]> granicus.if.org Git - openjpeg/commitdiff
Added the OPJViewer Module (/OPJViewer), developed by Giuseppe Baruffa of the Univers...
authorFrancois-Olivier Devaux <fodevaux@users.noreply.github.com>
Thu, 22 Feb 2007 17:05:58 +0000 (17:05 +0000)
committerFrancois-Olivier Devaux <fodevaux@users.noreply.github.com>
Thu, 22 Feb 2007 17:05:58 +0000 (17:05 +0000)
22 files changed:
ChangeLog
OPJViewer/OPJViewer.dsp [new file with mode: 0644]
OPJViewer/OPJViewer.dsw [new file with mode: 0644]
OPJViewer/OPJViewer.iss [new file with mode: 0644]
OPJViewer/source/OPJViewer.cpp [new file with mode: 0644]
OPJViewer/source/OPJViewer.h [new file with mode: 0644]
OPJViewer/source/OPJViewer.ico [new file with mode: 0644]
OPJViewer/source/OPJViewer.rc [new file with mode: 0644]
OPJViewer/source/OPJViewer16.xpm [new file with mode: 0644]
OPJViewer/source/icon1.xpm [new file with mode: 0644]
OPJViewer/source/icon2.xpm [new file with mode: 0644]
OPJViewer/source/icon3.xpm [new file with mode: 0644]
OPJViewer/source/icon4.xpm [new file with mode: 0644]
OPJViewer/source/icon5.xpm [new file with mode: 0644]
OPJViewer/source/imagj2k.cpp [new file with mode: 0644]
OPJViewer/source/imagj2k.h [new file with mode: 0644]
OPJViewer/source/imagjp2.cpp [new file with mode: 0644]
OPJViewer/source/imagjp2.h [new file with mode: 0644]
OPJViewer/source/imagmj2.cpp [new file with mode: 0644]
OPJViewer/source/imagmj2.h [new file with mode: 0644]
OPJViewer/source/wxj2kparser.cpp [new file with mode: 0644]
OPJViewer/source/wxjp2parser.cpp [new file with mode: 0644]

index 0a693ac400a3230fc872cc90a6c34eac377890c2..fa24ad1fccecfbe01b36a371d099c43de1b2ce06 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,9 @@ What's New for OpenJPEG
 ! : changed
 + : added
 
+February 22, 2007
++ [FOD] Added the OPJViewer Module (/OPJViewer), developed by Giuseppe Baruffa of the university of Perugia
+
 February 21, 2007
 + [FOD] Algorithmic optimizations in t1.c, thanks to Guido J. !
 
diff --git a/OPJViewer/OPJViewer.dsp b/OPJViewer/OPJViewer.dsp
new file mode 100644 (file)
index 0000000..1ab84c3
--- /dev/null
@@ -0,0 +1,206 @@
+# Microsoft Developer Studio Project File - Name="OPJViewer" - Package Owner=<4>\r
+# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
+# ** DO NOT EDIT **\r
+\r
+# TARGTYPE "Win32 (x86) Console Application" 0x0103\r
+\r
+CFG=OPJVIEWER - WIN32 RELEASE\r
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
+!MESSAGE use the Export Makefile command and run\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "OPJViewer.mak".\r
+!MESSAGE \r
+!MESSAGE You can specify a configuration when running NMAKE\r
+!MESSAGE by defining the macro CFG on the command line. For example:\r
+!MESSAGE \r
+!MESSAGE NMAKE /f "OPJViewer.mak" CFG="OPJVIEWER - WIN32 RELEASE"\r
+!MESSAGE \r
+!MESSAGE Possible choices for configuration are:\r
+!MESSAGE \r
+!MESSAGE "OPJViewer - Win32 Release" (based on "Win32 (x86) Console Application")\r
+!MESSAGE "OPJViewer - Win32 Debug" (based on "Win32 (x86) Console Application")\r
+!MESSAGE \r
+\r
+# Begin Project\r
+# PROP AllowPerConfigDependencies 0\r
+# PROP Scc_ProjName ""\r
+# PROP Scc_LocalPath ""\r
+CPP=cl.exe\r
+RSC=rc.exe\r
+\r
+!IF  "$(CFG)" == "OPJViewer - Win32 Release"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 0\r
+# PROP BASE Output_Dir "Release"\r
+# PROP BASE Intermediate_Dir "Release"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 0\r
+# PROP Output_Dir "W32Release"\r
+# PROP Intermediate_Dir "W32Release"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c\r
+# ADD CPP /nologo /G6 /MD /GX /O2 /I "c:\programmi\wxWidgets-2.8.0\lib\vc_lib\msw" /I "c:\programmi\wxWidgets-2.8.0\include" /I ".." /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D WINVER=0x400 /D "_MT" /D wxUSE_GUI=1 /D "wxUSE_LIBOPENJPEG" /D "OPJ_STATIC" /D "USE_JPWL" /FR /FD /c\r
+# SUBTRACT CPP /YX\r
+# ADD BASE RSC /l 0x410 /d "NDEBUG"\r
+# ADD RSC /l 0x409 /i "c:\programmi\wxWidgets-2.8.0\include" /d "NDEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386\r
+# ADD 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 comctl32.lib rpcrt4.lib wsock32.lib wxzlib.lib wxregex.lib wxpng.lib wxjpeg.lib wxbase28.lib wxmsw28_core.lib wxmsw28_html.lib wxmsw28_adv.lib wxmsw28_core.lib wxbase28.lib wxtiff.lib wxjpeg.lib wxpng.lib wxzlib.lib wxregex.lib wxexpat.lib LibOpenJPEG_JPWL.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib:"libcmt.lib" /libpath:"c:\programmi\wxWidgets-2.8.0\lib\vc_lib" /libpath:"..\jpwl\Release" /IGNORE:4089\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ELSEIF  "$(CFG)" == "OPJViewer - Win32 Debug"\r
+\r
+# PROP BASE Use_MFC 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "OPJViewer___Win32_Debug"\r
+# PROP BASE Intermediate_Dir "OPJViewer___Win32_Debug"\r
+# PROP BASE Target_Dir ""\r
+# PROP Use_MFC 0\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "W32Debug"\r
+# PROP Intermediate_Dir "W32Debug"\r
+# PROP Ignore_Export_Lib 0\r
+# PROP Target_Dir ""\r
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c\r
+# ADD CPP /nologo /MDd /Gm /GX /Zi /Od /I "C:\Programmi\wxWidgets-2.8.0\INCLUDE" /I "c:\programmi\wxWidgets-2.8.0\lib\vc_lib\msw" /I "c:\programmi\wxWidgets-2.8.0\include" /I ".." /D "_DEBUG" /D "__WXDEBUG__" /D WXDEBUG=1 /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D WINVER=0x400 /D "_MT" /D wxUSE_GUI=1 /D "wxUSE_LIBOPENJPEG" /D "OPJ_STATIC" /D "USE_JPWL" /FR /FD /GZ /c\r
+# SUBTRACT CPP /YX\r
+# ADD BASE RSC /l 0x410 /d "_DEBUG"\r
+# ADD RSC /l 0x410 /i "c:\programmi\wxWidgets-2.8.0\include" /d "_DEBUG"\r
+BSC32=bscmake.exe\r
+# ADD BASE BSC32 /nologo\r
+# ADD BSC32 /nologo\r
+LINK32=link.exe\r
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept\r
+# ADD 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 comctl32.lib rpcrt4.lib wsock32.lib wxzlibd.lib wxregexd.lib wxpngd.lib wxjpegd.lib wxtiffd.lib wxbase28d.lib wxmsw28d_core.lib wxmsw28d_html.lib wxmsw28d_adv.lib LibOpenJPEG_JPWL.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"libcmtd.lib" /pdbtype:sept /libpath:"c:\programmi\wxWidgets-2.8.0\lib\vc_lib" /libpath:"..\jpwl\Debug"\r
+# SUBTRACT LINK32 /pdb:none\r
+\r
+!ENDIF \r
+\r
+# Begin Target\r
+\r
+# Name "OPJViewer - Win32 Release"\r
+# Name "OPJViewer - Win32 Debug"\r
+# Begin Group "Source Files"\r
+\r
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
+# Begin Source File\r
+\r
+SOURCE=.\source\imagj2k.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\imagjp2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\imagmj2.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\OPJViewer.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\wxj2kparser.cpp\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\wxjp2parser.cpp\r
+# End Source File\r
+# End Group\r
+# Begin Group "Header Files"\r
+\r
+# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
+# Begin Source File\r
+\r
+SOURCE=.\source\imagj2k.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\imagjp2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\imagmj2.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\OPJViewer.h\r
+# End Source File\r
+# End Group\r
+# Begin Group "Resource Files"\r
+\r
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
+# Begin Source File\r
+\r
+SOURCE=.\source\icon1.xpm\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\icon2.xpm\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\icon3.xpm\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\icon4.xpm\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\icon5.xpm\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\OPJViewer.ico\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\OPJViewer.rc\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\source\OPJViewer16.xpm\r
+# End Source File\r
+# End Group\r
+# Begin Group "JPWL"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\jpwl\crc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\jpwl\crc.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\jpwl\jpwl.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\jpwl\jpwl.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\jpwl\jpwl_lib.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\jpwl\rs.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\jpwl\rs.h\r
+# End Source File\r
+# End Group\r
+# End Target\r
+# End Project\r
diff --git a/OPJViewer/OPJViewer.dsw b/OPJViewer/OPJViewer.dsw
new file mode 100644 (file)
index 0000000..a4d64f9
--- /dev/null
@@ -0,0 +1,44 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00\r
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
+\r
+###############################################################################\r
+\r
+Project: "LibOpenJPEG_JPWL"=..\jpwl\LibOpenJPEG_JPWL.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Project: "OPJViewer"=.\OPJViewer.dsp - Package Owner=<4>\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<4>\r
+{{{\r
+    Begin Project Dependency\r
+    Project_Dep_Name LibOpenJPEG_JPWL\r
+    End Project Dependency\r
+}}}\r
+\r
+###############################################################################\r
+\r
+Global:\r
+\r
+Package=<5>\r
+{{{\r
+}}}\r
+\r
+Package=<3>\r
+{{{\r
+}}}\r
+\r
+###############################################################################\r
+\r
diff --git a/OPJViewer/OPJViewer.iss b/OPJViewer/OPJViewer.iss
new file mode 100644 (file)
index 0000000..6b324c7
--- /dev/null
@@ -0,0 +1,34 @@
+; Script generated by the Inno Setup Script Wizard.\r
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!\r
+\r
+[Setup]\r
+AppName=OPJViewer\r
+AppVerName=OPJViewer 0.1 alpha\r
+AppPublisher=OpenJPEG\r
+AppPublisherURL=http://www.openjpeg.org\r
+AppSupportURL=http://www.openjpeg.org\r
+AppUpdatesURL=http://www.openjpeg.org\r
+DefaultDirName={pf}\OPJViewer\r
+DefaultGroupName=OPJViewer\r
+OutputDir=setup\r
+OutputBaseFilename=OPJViewer01alpha_setup\r
+Compression=lzma\r
+SolidCompression=yes\r
+\r
+[Languages]\r
+Name: english; MessagesFile: compiler:Default.isl\r
+\r
+[Tasks]\r
+Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked\r
+\r
+[Files]\r
+Source: W32Release\OPJViewer.exe; DestDir: {app}; Flags: ignoreversion\r
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files\r
+\r
+[Icons]\r
+Name: {group}\OPJViewer; Filename: {app}\OPJViewer.exe\r
+Name: {group}\{cm:UninstallProgram,OPJViewer}; Filename: {uninstallexe}\r
+Name: {userdesktop}\OPJViewer; Filename: {app}\OPJViewer.exe; Tasks: desktopicon\r
+\r
+[Run]\r
+Filename: {app}\OPJViewer.exe; Description: {cm:LaunchProgram,OPJViewer}; Flags: nowait postinstall skipifsilent\r
diff --git a/OPJViewer/source/OPJViewer.cpp b/OPJViewer/source/OPJViewer.cpp
new file mode 100644 (file)
index 0000000..3bbf479
--- /dev/null
@@ -0,0 +1,1849 @@
+/*\r
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        sashtest.cpp\r
+// Purpose:     Layout/sash sample\r
+// Author:      Julian Smart\r
+// Modified by:\r
+// Created:     04/01/98\r
+// RCS-ID:      $Id: sashtest.cpp,v 1.18 2005/08/23 15:54:35 ABX Exp $\r
+// Copyright:   (c) Julian Smart\r
+// Licence:     wxWindows license\r
+/////////////////////////////////////////////////////////////////////////////\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        treetest.cpp\r
+// Purpose:     wxTreeCtrl sample\r
+// Author:      Julian Smart\r
+// Modified by:\r
+// Created:     04/01/98\r
+// RCS-ID:      $Id: treetest.cpp,v 1.110 2006/11/04 11:26:51 VZ Exp $\r
+// Copyright:   (c) Julian Smart\r
+// Licence:     wxWindows license\r
+/////////////////////////////////////////////////////////////////////////////\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        dialogs.cpp\r
+// Purpose:     Common dialogs demo\r
+// Author:      Julian Smart\r
+// Modified by: ABX (2004) - adjustements for conditional building + new menu\r
+// Created:     04/01/98\r
+// RCS-ID:      $Id: dialogs.cpp,v 1.163 2006/11/04 10:57:24 VZ Exp $\r
+// Copyright:   (c) Julian Smart\r
+// Licence:     wxWindows license\r
+/////////////////////////////////////////////////////////////////////////////\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        thread.cpp\r
+// Purpose:     wxWidgets thread sample\r
+// Author:      Guilhem Lavaux, Vadim Zeitlin\r
+// Modified by:\r
+// Created:     06/16/98\r
+// RCS-ID:      $Id: thread.cpp,v 1.26 2006/10/02 05:36:28 PC Exp $\r
+// Copyright:   (c) 1998-2002 wxWidgets team\r
+// Licence:     wxWindows license\r
+/////////////////////////////////////////////////////////////////////////////\r
+///////////////////////////////////////////////////////////////////////////////\r
+// Name:        samples/image/image.cpp\r
+// Purpose:     sample showing operations with wxImage\r
+// Author:      Robert Roebling\r
+// Modified by:\r
+// Created:     1998\r
+// RCS-ID:      $Id: image.cpp,v 1.120 2006/12/06 17:13:11 VZ Exp $\r
+// Copyright:   (c) 1998-2005 Robert Roebling\r
+// License:     wxWindows licence\r
+///////////////////////////////////////////////////////////////////////////////\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        samples/console/console.cpp\r
+// Purpose:     A sample console (as opposed to GUI) program using wxWidgets\r
+// Author:      Vadim Zeitlin\r
+// Modified by:\r
+// Created:     04.10.99\r
+// RCS-ID:      $Id: console.cpp,v 1.206 2006/11/12 19:55:19 VZ Exp $\r
+// Copyright:   (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>\r
+// Licence:     wxWindows license\r
+/////////////////////////////////////////////////////////////////////////////\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        samples/notebook/notebook.cpp\r
+// Purpose:     a sample demonstrating notebook usage\r
+// Author:      Julian Smart\r
+// Modified by: Dimitri Schoolwerth\r
+// Created:     26/10/98\r
+// RCS-ID:      $Id: notebook.cpp,v 1.49 2006/11/04 18:24:07 RR Exp $\r
+// Copyright:   (c) 1998-2002 wxWidgets team\r
+// License:     wxWindows license\r
+/////////////////////////////////////////////////////////////////////////////\r
+#include "OPJViewer.h"\r
+\r
+OPJFrame *frame = NULL;\r
+wxList my_children;\r
+\r
+IMPLEMENT_APP(OPJViewerApp)\r
+\r
+// For drawing lines in a canvas\r
+long xpos = -1;\r
+long ypos = -1;\r
+\r
+int winNumber = 1;\r
+\r
+// Initialise this in OnInit, not statically\r
+bool OPJViewerApp::OnInit(void)\r
+{\r
+#if wxUSE_UNICODE\r
+    wxChar **wxArgv = new wxChar *[argc + 1];\r
+\r
+    {\r
+        int n;\r
+\r
+        for (n = 0; n < argc; n++ )\r
+        {\r
+            wxMB2WXbuf warg = wxConvertMB2WX(argv[n]);\r
+            wxArgv[n] = wxStrdup(warg);\r
+        }\r
+\r
+        wxArgv[n] = NULL;\r
+    }\r
+#else // !wxUSE_UNICODE\r
+    #define wxArgv argv\r
+#endif // wxUSE_UNICODE/!wxUSE_UNICODE\r
+\r
+#if wxUSE_CMDLINE_PARSER\r
+    static const wxCmdLineEntryDesc cmdLineDesc[] =\r
+    {\r
+        { wxCMD_LINE_SWITCH, _T("h"), _T("help"), _T("show this help message"),\r
+            wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },\r
+        /*{ wxCMD_LINE_SWITCH, _T("v"), _T("verbose"), _T("be verbose") },\r
+        { wxCMD_LINE_SWITCH, _T("q"), _T("quiet"),   _T("be quiet") },\r
+\r
+        { wxCMD_LINE_OPTION, _T("o"), _T("output"),  _T("output file") },\r
+        { wxCMD_LINE_OPTION, _T("i"), _T("input"),   _T("input dir") },\r
+        { wxCMD_LINE_OPTION, _T("s"), _T("size"),    _T("output block size"),\r
+            wxCMD_LINE_VAL_NUMBER },\r
+        { wxCMD_LINE_OPTION, _T("d"), _T("date"),    _T("output file date"),\r
+            wxCMD_LINE_VAL_DATE },*/\r
+\r
+        { wxCMD_LINE_PARAM,  NULL, NULL, _T("input file"),\r
+            wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE },\r
+\r
+        { wxCMD_LINE_NONE }\r
+    };\r
+\r
+    wxCmdLineParser parser(cmdLineDesc, argc, wxArgv);\r
+\r
+    /*parser.AddOption(_T("project_name"), _T(""), _T("full path to project file"),\r
+                     wxCMD_LINE_VAL_STRING,\r
+                     wxCMD_LINE_OPTION_MANDATORY | wxCMD_LINE_NEEDS_SEPARATOR);*/\r
+\r
+    switch ( parser.Parse() )\r
+    {\r
+        case -1:\r
+            wxLogMessage(_T("Help was given, terminating."));\r
+            break;\r
+\r
+        case 0:\r
+            ShowCmdLine(parser);\r
+            break;\r
+\r
+        default:\r
+            wxLogMessage(_T("Syntax error detected."));\r
+            break;\r
+    }\r
+#endif // wxUSE_CMDLINE_PARSER\r
+\r
+    //wxInitAllImageHandlers();\r
+#if wxUSE_LIBJPEG\r
+  wxImage::AddHandler( new wxJPEGHandler );\r
+#endif\r
+#if wxUSE_LIBOPENJPEG\r
+  wxImage::AddHandler( new wxJ2KHandler );\r
+  wxImage::AddHandler( new wxJP2Handler );\r
+  wxImage::AddHandler( new wxMJ2Handler );\r
+#endif\r
+\r
+\r
+       // Create the main frame window\r
+\r
+  frame = new OPJFrame(NULL, wxID_ANY, OPJ_APPLICATION_TITLEBAR, wxDefaultPosition, wxSize(800, 600),\r
+                      wxDEFAULT_FRAME_STYLE |\r
+                      wxNO_FULL_REPAINT_ON_RESIZE |\r
+                      wxHSCROLL | wxVSCROLL);\r
+\r
+  // Give it an icon (this is ignored in MDI mode: uses resources)\r
+#ifdef __WXMSW__\r
+  frame->SetIcon(wxIcon(_T("OPJViewer16")));\r
+#endif\r
+\r
+  frame->Show(true);\r
+\r
+  SetTopWindow(frame);\r
+\r
+  return true;\r
+}\r
+\r
+void OPJViewerApp::ShowCmdLine(const wxCmdLineParser& parser)\r
+{\r
+    wxString s = _T("Command line parsed successfully:\nInput files: ");\r
+\r
+    size_t count = parser.GetParamCount();\r
+    for ( size_t param = 0; param < count; param++ )\r
+    {\r
+        s << parser.GetParam(param) << ';';\r
+\r
+               m_filelist.Add(parser.GetParam(param));\r
+    }\r
+\r
+    /*s << '\n'\r
+      << _T("Verbose:\t") << (parser.Found(_T("v")) ? _T("yes") : _T("no")) << '\n'\r
+      << _T("Quiet:\t") << (parser.Found(_T("q")) ? _T("yes") : _T("no")) << '\n';\r
+\r
+    wxString strVal;\r
+    long lVal;\r
+    wxDateTime dt;\r
+    if ( parser.Found(_T("o"), &strVal) )\r
+        s << _T("Output file:\t") << strVal << '\n';\r
+    if ( parser.Found(_T("i"), &strVal) )\r
+        s << _T("Input dir:\t") << strVal << '\n';\r
+    if ( parser.Found(_T("s"), &lVal) )\r
+        s << _T("Size:\t") << lVal << '\n';\r
+    if ( parser.Found(_T("d"), &dt) )\r
+        s << _T("Date:\t") << dt.FormatISODate() << '\n';\r
+    if ( parser.Found(_T("project_name"), &strVal) )\r
+        s << _T("Project:\t") << strVal << '\n';*/\r
+\r
+    //wxLogMessage(s);\r
+}\r
+\r
+// OPJFrame events\r
+BEGIN_EVENT_TABLE(OPJFrame, wxMDIParentFrame)\r
+    EVT_MENU(SASHTEST_ABOUT, OPJFrame::OnAbout)\r
+    EVT_MENU(SASHTEST_NEW_WINDOW, OPJFrame::OnFileOpen)\r
+    EVT_SIZE(OPJFrame::OnSize)\r
+    EVT_MENU(SASHTEST_QUIT, OPJFrame::OnQuit)\r
+    EVT_MENU(SASHTEST_TOGGLE_WINDOW, OPJFrame::OnToggleWindow)\r
+    EVT_SASH_DRAGGED_RANGE(ID_WINDOW_TOP, ID_WINDOW_BOTTOM, OPJFrame::OnSashDrag)\r
+    EVT_NOTEBOOK_PAGE_CHANGED(LEFT_NOTEBOOK_ID, OPJFrame::OnNotebook)\r
+END_EVENT_TABLE()\r
+\r
+// this is the frame constructor\r
+OPJFrame::OPJFrame(wxWindow *parent, const wxWindowID id, const wxString& title,\r
+                                  const wxPoint& pos, const wxSize& size, const long style)\r
+               : wxMDIParentFrame(parent, id, title, pos, size, style)\r
+{\r
+       // file menu and its items\r
+       wxMenu *file_menu = new wxMenu;\r
+\r
+       file_menu->Append(SASHTEST_NEW_WINDOW, wxT("&Open\tCtrl+O"));\r
+       file_menu->SetHelpString(SASHTEST_NEW_WINDOW, wxT("Open one or more files"));\r
+\r
+       file_menu->Append(SASHTEST_TOGGLE_WINDOW, wxT("&Toggle browser\tCtrl+T"));\r
+       file_menu->SetHelpString(SASHTEST_TOGGLE_WINDOW, wxT("Toggle the left browsing pane"));\r
+\r
+       file_menu->Append(SASHTEST_QUIT, wxT("&Exit\tCtrl+Q"));\r
+       file_menu->SetHelpString(SASHTEST_QUIT, wxT("Quit this program"));\r
+\r
+       // help menu and its items\r
+       wxMenu *help_menu = new wxMenu;\r
+\r
+       help_menu->Append(SASHTEST_ABOUT, wxT("&About\tF1"));\r
+       help_menu->SetHelpString(SASHTEST_ABOUT, wxT("Basic info on the program"));\r
+\r
+       // the whole menubar\r
+       wxMenuBar *menu_bar = new wxMenuBar;\r
+       menu_bar->Append(file_menu, wxT("&File"));\r
+       menu_bar->Append(help_menu, wxT("&Help"));\r
+\r
+       // Associate the menu bar with the frame\r
+       SetMenuBar(menu_bar);\r
+\r
+       // the status bar\r
+       CreateStatusBar();\r
+\r
+       // the logging window\r
+       loggingWindow = new wxSashLayoutWindow(this, ID_WINDOW_BOTTOM,\r
+                                                                                       wxDefaultPosition, wxSize(400, 130),\r
+                                                                                       wxNO_BORDER | wxSW_3D | wxCLIP_CHILDREN\r
+                                                                                       );\r
+       loggingWindow->SetDefaultSize(wxSize(1000, 130));\r
+       loggingWindow->SetOrientation(wxLAYOUT_HORIZONTAL);\r
+       loggingWindow->SetAlignment(wxLAYOUT_BOTTOM);\r
+       //loggingWindow->SetBackgroundColour(wxColour(0, 0, 255));\r
+       loggingWindow->SetSashVisible(wxSASH_TOP, true);\r
+\r
+       // create the bottom notebook\r
+       m_bookCtrlbottom = new wxNotebook(loggingWindow, BOTTOM_NOTEBOOK_ID,\r
+                                                               wxDefaultPosition, wxDefaultSize,\r
+                                                               wxBK_LEFT);\r
+\r
+       // create the text control of the logger\r
+       m_textCtrl = new wxTextCtrl(m_bookCtrlbottom, wxID_ANY, wxT(""),\r
+                                                               wxDefaultPosition, wxDefaultSize,\r
+                                                               wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY \r
+                                                               );\r
+       m_textCtrl->SetValue(_T("Logging window\n"));\r
+\r
+       // add it to the notebook\r
+       m_bookCtrlbottom->AddPage(m_textCtrl, wxT("Log"));\r
+\r
+       // create the text control of the browser\r
+       m_textCtrlbrowse = new wxTextCtrl(m_bookCtrlbottom, wxID_ANY, wxT(""),\r
+                                                               wxDefaultPosition, wxDefaultSize,\r
+                                                               wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY \r
+                                                               );\r
+       m_textCtrlbrowse->SetValue(_T("Browsing window\n"));\r
+\r
+       // add it the notebook\r
+       m_bookCtrlbottom->AddPage(m_textCtrlbrowse, wxT("Peek"));\r
+\r
+       // the browser window\r
+       markerTreeWindow = new wxSashLayoutWindow(this, ID_WINDOW_LEFT1,\r
+                                                                                         wxDefaultPosition, wxSize(300, 30),\r
+                                                                                         wxNO_BORDER | wxSW_3D | wxCLIP_CHILDREN\r
+                                                                                         );\r
+       markerTreeWindow->SetDefaultSize(wxSize(300, 1000));\r
+       markerTreeWindow->SetOrientation(wxLAYOUT_VERTICAL);\r
+       markerTreeWindow->SetAlignment(wxLAYOUT_LEFT);\r
+       //markerTreeWindow->SetBackgroundColour(wxColour(0, 255, 0));\r
+       markerTreeWindow->SetSashVisible(wxSASH_RIGHT, true);\r
+       markerTreeWindow->SetExtraBorderSize(0);\r
+\r
+       // create the browser notebook\r
+       m_bookCtrl = new wxNotebook(markerTreeWindow, LEFT_NOTEBOOK_ID,\r
+                                                               wxDefaultPosition, wxDefaultSize,\r
+                                                               wxBK_TOP);\r
+\r
+\r
+#if wxUSE_LOG\r
+#ifdef __WXMOTIF__\r
+       // For some reason, we get a memcpy crash in wxLogStream::DoLogStream\r
+       // on gcc/wxMotif, if we use wxLogTextCtl. Maybe it's just gcc?\r
+       delete wxLog::SetActiveTarget(new wxLogStderr);\r
+#else\r
+       // set our text control as the log target\r
+       wxLogTextCtrl *logWindow = new wxLogTextCtrl(m_textCtrl);\r
+       delete wxLog::SetActiveTarget(logWindow);\r
+#endif\r
+#endif // wxUSE_LOG\r
+\r
+       // if there are files on the command line, open them\r
+       /*if (!wxGetApp().m_filelist.IsEmpty()) {\r
+       wxLogMessage(wxT("Habemus files!!!"));\r
+       wxArrayString paths, filenames;\r
+       for (int f = 0; f < wxGetApp().m_filelist.GetCount(); f++) {\r
+       paths.Add(wxFileName(wxGetApp().m_filelist[f]).GetFullPath());\r
+       filenames.Add(wxFileName(wxGetApp().m_filelist[f]).GetFullName());\r
+       }\r
+       OpenFiles(paths, filenames);\r
+       }*/\r
+}\r
+\r
+// this is the frame destructor\r
+OPJFrame::~OPJFrame(void)\r
+{\r
+       // delete all possible things\r
+       delete m_bookCtrl;\r
+       m_bookCtrl = NULL;\r
+\r
+       delete markerTreeWindow;\r
+       markerTreeWindow = NULL;\r
+\r
+       delete m_textCtrl;\r
+       m_textCtrl = NULL;\r
+\r
+       delete m_bookCtrlbottom;\r
+       m_bookCtrlbottom = NULL;\r
+\r
+       delete loggingWindow;\r
+       loggingWindow = NULL;\r
+}\r
+\r
+void OPJFrame::OnNotebook(wxNotebookEvent& event)\r
+{\r
+       int sel = event.GetSelection();\r
+       long childnum;\r
+\r
+       m_bookCtrl->GetPageText(sel).ToLong(&childnum);\r
+\r
+       m_childhash[childnum]->Activate();\r
+\r
+       wxLogMessage(wxString::Format(wxT("Selection changed (now %d --> %d)"), childnum, m_childhash[childnum]->m_winnumber));\r
+\r
+}\r
+\r
+\r
+void OPJFrame::Resize(int number)\r
+{\r
+       wxSize size = GetClientSize();\r
+}\r
+\r
+void OPJFrame::OnQuit(wxCommandEvent& WXUNUSED(event))\r
+{\r
+       Close(true);\r
+}\r
+\r
+// about window for the frame\r
+void OPJFrame::OnAbout(wxCommandEvent& WXUNUSED(event))\r
+{\r
+       wxMessageBox(wxString::Format(OPJ_APPLICATION_TITLEBAR\r
+                                                                 wxT("\n\n")\r
+                                                                 wxT("Built with %s and OpenJPEG ")\r
+                                                                 wxT(OPENJPEG_VERSION)\r
+                                                                 wxT("\non ") wxT(__DATE__) wxT(", ") wxT(__TIME__)\r
+                                                                 wxT("\nRunning under %s\n\n")\r
+                                                                 OPJ_APPLICATION_COPYRIGHT,\r
+                                                                 wxVERSION_STRING,\r
+                                                                 wxGetOsDescription().c_str()\r
+                                                                 ),\r
+                                wxT("About ") OPJ_APPLICATION_NAME,\r
+                                wxOK | wxICON_INFORMATION,\r
+                                this\r
+                                );\r
+}\r
+\r
+void OPJFrame::OnToggleWindow(wxCommandEvent& WXUNUSED(event))\r
+{\r
+    if (markerTreeWindow->IsShown())\r
+    {\r
+        markerTreeWindow->Show(false);\r
+    }\r
+    else\r
+    {\r
+        markerTreeWindow->Show(true);\r
+    }\r
+#if wxUSE_MDI_ARCHITECTURE\r
+    wxLayoutAlgorithm layout;\r
+    layout.LayoutMDIFrame(this);\r
+#endif // wxUSE_MDI_ARCHITECTURE\r
+}\r
+\r
+void OPJFrame::OnSashDrag(wxSashEvent& event)\r
+{\r
+    if (event.GetDragStatus() == wxSASH_STATUS_OUT_OF_RANGE)\r
+        return;\r
+\r
+    switch (event.GetId())\r
+    {\r
+        case ID_WINDOW_LEFT1:\r
+        {\r
+            markerTreeWindow->SetDefaultSize(wxSize(event.GetDragRect().width, 1000));\r
+            break;\r
+        }\r
+        case ID_WINDOW_BOTTOM:\r
+        {\r
+            loggingWindow->SetDefaultSize(wxSize(1000, event.GetDragRect().height));\r
+            break;\r
+        }\r
+    }\r
+\r
+#if wxUSE_MDI_ARCHITECTURE\r
+    wxLayoutAlgorithm layout;\r
+    layout.LayoutMDIFrame(this);\r
+#endif // wxUSE_MDI_ARCHITECTURE\r
+\r
+    // Leaves bits of itself behind sometimes\r
+    GetClientWindow()->Refresh();\r
+}\r
+\r
+// physically open the files\r
+void OPJFrame::OpenFiles(wxArrayString paths, wxArrayString filenames)\r
+{\r
+\r
+        size_t count = paths.GetCount();\r
+        for ( size_t n = 0; n < count; n++ )\r
+        {\r
+                       wxString msg, s;\r
+            s.Printf(_T("File %d: %s (%s)\n"),\r
+                     (int)n, paths[n].c_str(), filenames[n].c_str());\r
+\r
+            msg += s;\r
+                       //s.Printf(_T("Filter index: %d"), dialog.GetFilterIndex());\r
+                       msg += s;\r
+\r
+                       /*wxMessageDialog dialog2(this, msg, _T("Selected files"));\r
+                       dialog2.ShowModal();*/\r
+\r
+                       // Make another frame, containing a canvas\r
+                         OPJChildFrame *subframe = new OPJChildFrame(frame,\r
+                                                                                         paths[n],\r
+                                                                                         winNumber,\r
+                                                                                         _T("Canvas Frame"),\r
+                                                                                         wxDefaultPosition, wxSize(300, 300),\r
+                                                                                         wxDEFAULT_FRAME_STYLE |\r
+                                                                                         wxNO_FULL_REPAINT_ON_RESIZE);\r
+                         m_childhash[winNumber] = subframe;\r
+\r
+                                 // create own marker tree\r
+                               long tstyle = wxTR_DEFAULT_STYLE | wxSUNKEN_BORDER | \r
+                       #ifndef NO_VARIABLE_HEIGHT\r
+                                                        wxTR_HAS_VARIABLE_ROW_HEIGHT /*|*/\r
+                       #endif\r
+                                                        /*wxTR_EDIT_LABELS*/;\r
+\r
+                               m_treehash[winNumber] = new OPJMarkerTree(m_bookCtrl, paths[n], wxT("Parsing..."), TreeTest_Ctrl,\r
+                                                                                       wxDefaultPosition, wxDefaultSize,\r
+                                                                                       tstyle);\r
+\r
+                               m_bookCtrl->AddPage(m_treehash[winNumber],\r
+                                                                               wxString::Format(wxT("%u"), winNumber), false);\r
+\r
+                               for (int p = 0; p < m_bookCtrl->GetPageCount(); p++) {\r
+\r
+                                       if (m_bookCtrl->GetPageText(p) == wxString::Format(wxT("%u"), winNumber)) {\r
+                                               m_bookCtrl->ChangeSelection(p);\r
+                                               break;\r
+                                       }\r
+\r
+                               }\r
+\r
+                         winNumber++;\r
+               \r
+               }\r
+\r
+\r
+}\r
+\r
+void OPJFrame::OnFileOpen(wxCommandEvent& WXUNUSED(event))\r
+{\r
+    wxString wildcards =\r
+#ifdef __WXMOTIF__\r
+       wxT("JPEG 2000 files (*.jp2,*.j2k,*.j2c,*.mj2)|*.*j*2*");\r
+#else\r
+       wxT("JPEG 2000 files (*.jp2,*.j2k,*.j2c,*.mj2)|*.jp2;*.j2k;*.j2c;*.mj2|JPEG files (*.jpg)|*.jpg|All files|*");\r
+#endif\r
+    wxFileDialog dialog(this, _T("Open JPEG 2000 file(s)"),\r
+                        wxEmptyString, wxEmptyString, wildcards,\r
+                        wxFD_OPEN|wxFD_MULTIPLE);\r
+\r
+    if (dialog.ShowModal() == wxID_OK)\r
+    {\r
+        wxArrayString paths, filenames;\r
+\r
+        dialog.GetPaths(paths);\r
+        dialog.GetFilenames(filenames);\r
+\r
+               OpenFiles(paths, filenames);\r
+\r
+    }\r
+\r
+}\r
+\r
+BEGIN_EVENT_TABLE(OPJCanvas, wxScrolledWindow)\r
+    EVT_MOUSE_EVENTS(OPJCanvas::OnEvent)\r
+END_EVENT_TABLE()\r
+\r
+// Define a constructor for my canvas\r
+OPJCanvas::OPJCanvas(wxFileName fname, wxWindow *parent, const wxPoint& pos, const wxSize& size)\r
+        : wxScrolledWindow(parent, wxID_ANY, pos, size,\r
+                           wxSUNKEN_BORDER | wxNO_FULL_REPAINT_ON_RESIZE)\r
+{\r
+    SetBackgroundColour(OPJ_CANVAS_COLOUR);\r
+\r
+       m_fname = fname;\r
+\r
+    OPJDecoThread *dthread = CreateDecoThread();\r
+\r
+    if (dthread->Run() != wxTHREAD_NO_ERROR)\r
+        wxLogMessage(wxT("Can't start deco thread!"));\r
+    else\r
+               wxLogMessage(_T("New deco thread started."));\r
+\r
+}\r
+\r
+OPJDecoThread *OPJCanvas::CreateDecoThread(void)\r
+{\r
+    OPJDecoThread *dthread = new OPJDecoThread(this);\r
+\r
+    if (dthread->Create() != wxTHREAD_NO_ERROR)\r
+               wxLogError(wxT("Can't create deco thread!"));\r
+\r
+    wxCriticalSectionLocker enter(wxGetApp().m_deco_critsect);\r
+    wxGetApp().m_deco_threads.Add(dthread);\r
+\r
+    return dthread;\r
+}\r
+\r
+// Define the repainting behaviour\r
+void OPJCanvas::OnDraw(wxDC& dc)\r
+{\r
+    /*dc.SetFont(*wxSWISS_FONT);\r
+    dc.SetPen(*wxBLACK_PEN);\r
+    dc.DrawText(_T("Image drawing canvas"), 10, 10);\r
+    dc.DrawLine(8, 22, 300, 22);*/\r
+       if (m_image.Ok()) {\r
+               dc.DrawBitmap(m_image, OPJ_CANVAS_BORDER, OPJ_CANVAS_BORDER);\r
+       } else {\r
+               dc.SetFont(*wxSWISS_FONT);\r
+               dc.SetPen(*wxBLACK_PEN);\r
+               dc.DrawText(_T("Decoding image, please wait..."), 40, 50);\r
+       }\r
+\r
+    /*dc.SetFont(*wxSWISS_FONT);\r
+    dc.SetPen(*wxGREEN_PEN);\r
+    dc.DrawLine(0, 0, 200, 200);\r
+    dc.DrawLine(200, 0, 0, 200);\r
+\r
+    dc.SetBrush(*wxCYAN_BRUSH);\r
+    dc.SetPen(*wxRED_PEN);\r
+    dc.DrawRectangle(100, 100, 100, 50);\r
+    dc.DrawRoundedRectangle(150, 150, 100, 50, 20);\r
+\r
+    dc.DrawEllipse(250, 250, 100, 50);\r
+#if wxUSE_SPLINES\r
+    dc.DrawSpline(50, 200, 50, 100, 200, 10);\r
+#endif // wxUSE_SPLINES\r
+    dc.DrawLine(50, 230, 200, 230);\r
+    dc.DrawText(_T("This is a test string"), 50, 230);\r
+\r
+    wxPoint points[3];\r
+    points[0].x = 200; points[0].y = 300;\r
+    points[1].x = 100; points[1].y = 400;\r
+    points[2].x = 300; points[2].y = 400;\r
+\r
+    dc.DrawPolygon(3, points);*/\r
+}\r
+\r
+// This implements a tiny doodling program! Drag the mouse using\r
+// the left button.\r
+void OPJCanvas::OnEvent(wxMouseEvent& event)\r
+{\r
+  wxClientDC dc(this);\r
+  PrepareDC(dc);\r
+\r
+  wxPoint pt(event.GetLogicalPosition(dc));\r
+\r
+  if (xpos > -1 && ypos > -1 && event.Dragging())\r
+  {\r
+    dc.SetPen(*wxBLACK_PEN);\r
+    dc.DrawLine(xpos, ypos, pt.x, pt.y);\r
+  }\r
+  xpos = pt.x;\r
+  ypos = pt.y;\r
+}\r
+\r
+void OPJFrame::OnSize(wxSizeEvent& WXUNUSED(event))\r
+{\r
+#if wxUSE_MDI_ARCHITECTURE\r
+    wxLayoutAlgorithm layout;\r
+    layout.LayoutMDIFrame(this);\r
+#endif // wxUSE_MDI_ARCHITECTURE\r
+}\r
+\r
+// Note that SASHTEST_NEW_WINDOW and SASHTEST_ABOUT commands get passed\r
+// to the parent window for processing, so no need to\r
+// duplicate event handlers here.\r
+\r
+BEGIN_EVENT_TABLE(OPJChildFrame, wxMDIChildFrame)\r
+  /*EVT_MENU(SASHTEST_CHILD_QUIT, OPJChildFrame::OnQuit)*/\r
+  EVT_CLOSE(OPJChildFrame::OnClose)\r
+  EVT_SET_FOCUS(OPJChildFrame::OnGotFocus)\r
+  /*EVT_KILL_FOCUS(OPJChildFrame::OnLostFocus)*/\r
+END_EVENT_TABLE()\r
+\r
+OPJChildFrame::OPJChildFrame(OPJFrame *parent, wxFileName fname, int winnumber, const wxString& title, const wxPoint& pos, const wxSize& size,\r
+const long style):\r
+  wxMDIChildFrame(parent, wxID_ANY, title, pos, size, style)\r
+{\r
+  m_frame = (OPJFrame  *) parent;\r
+  m_canvas = NULL;\r
+  my_children.Append(this);\r
+  m_fname = fname;\r
+  m_winnumber = winnumber;\r
+       SetTitle(wxString::Format(_T("%d: "), m_winnumber) + m_fname.GetFullName());\r
+\r
+\r
+         // Give it an icon (this is ignored in MDI mode: uses resources)\r
+#ifdef __WXMSW__\r
+         SetIcon(wxIcon(_T("sashtest_icn")));\r
+#endif\r
+\r
+#if wxUSE_STATUSBAR\r
+         // Give it a status line\r
+         //CreateStatusBar();\r
+#endif // wxUSE_STATUSBAR\r
+\r
+         // Make a menubar\r
+         /*wxMenu *file_menu = new wxMenu;\r
+\r
+         file_menu->Append(SASHTEST_NEW_WINDOW, _T("&Open\tCtrl+O"));\r
+         file_menu->Append(SASHTEST_CHILD_QUIT, _T("&Close\tCtrl+C"));\r
+         file_menu->Append(SASHTEST_QUIT, _T("&Exit\tCtrl+Q"));\r
+\r
+         wxMenu *option_menu = new wxMenu;\r
+\r
+         // Dummy option\r
+         option_menu->Append(SASHTEST_REFRESH, _T("&Refresh picture"));\r
+\r
+         wxMenu *help_menu = new wxMenu;\r
+         help_menu->Append(SASHTEST_ABOUT, _T("&About\tF1"));\r
+\r
+         wxMenuBar *menu_bar = new wxMenuBar;\r
+\r
+         menu_bar->Append(file_menu, _T("&File"));\r
+         menu_bar->Append(option_menu, _T("&Options"));\r
+         menu_bar->Append(help_menu, _T("&Help"));\r
+\r
+         // Associate the menu bar with the frame\r
+         SetMenuBar(menu_bar);*/\r
+\r
+\r
+         int width, height;\r
+         GetClientSize(&width, &height);\r
+\r
+         OPJCanvas *canvas = new OPJCanvas(fname, this, wxPoint(0, 0), wxSize(width, height));\r
+         canvas->SetCursor(wxCursor(wxCURSOR_PENCIL));\r
+         m_canvas = canvas;\r
+\r
+         // Give it scrollbars\r
+         canvas->SetScrollbars(20, 20, 5, 5);\r
+\r
+         Show(true);\r
+         Maximize(true);\r
+\r
+\r
+    /*wxSize gsize = m_frame->m_bookCtrl->GetClientSize();\r
+    m_frame->m_treehash[m_winnumber]->SetSize(0, 0, gsize.x, gsize.y);*/\r
+\r
+    /*m_frame->Resize(m_winnumber);*/\r
+       /*m_frame->m_treehash[0]->Show(false);\r
+       m_frame->m_treehash[m_winnumber]->Show(true);*/\r
+    /*m_frame->Resize(m_winnumber);*/\r
+\r
+       /*wxLogError(wxString::Format(wxT("Created tree %d (0x%x)"), m_winnumber, m_frame->m_treehash[m_winnumber]));*/\r
+\r
+}\r
+\r
+OPJChildFrame::~OPJChildFrame(void)\r
+{\r
+  my_children.DeleteObject(this);\r
+}\r
+\r
+/*void OPJChildFrame::OnQuit(wxCommandEvent& WXUNUSED(event))\r
+{\r
+       for (int p = 0; p < m_frame->m_bookCtrl->GetPageCount(); p++) {\r
+\r
+               if (m_frame->m_bookCtrl->GetPageText(p) == wxString::Format(wxT("%u"), m_winnumber)) {\r
+                       m_frame->m_bookCtrl->DeletePage(p);;\r
+                       break;\r
+               }\r
+\r
+       }\r
+\r
+       Close(true);\r
+}*/\r
+\r
+void OPJChildFrame::OnClose(wxCloseEvent& event)\r
+{\r
+       for (int p = 0; p < m_frame->m_bookCtrl->GetPageCount(); p++) {\r
+\r
+               if (m_frame->m_bookCtrl->GetPageText(p) == wxString::Format(wxT("%u"), m_winnumber)) {\r
+                       m_frame->m_bookCtrl->DeletePage(p);\r
+                       break;\r
+               }\r
+\r
+       }\r
+       Destroy();\r
+\r
+       wxLogMessage(wxString::Format(wxT("Closed: %d"), m_winnumber));\r
+\r
+}\r
+\r
+void OPJChildFrame::OnActivate(wxActivateEvent& event)\r
+{\r
+  /*if (event.GetActive() && m_canvas)\r
+    m_canvas->SetFocus();*/\r
+}\r
+\r
+void OPJChildFrame::OnGotFocus(wxFocusEvent& event)\r
+{\r
+       // we need to check if the notebook is being destroyed or not\r
+       if (!m_frame->m_bookCtrl)\r
+               return;\r
+\r
+       for (int p = 0; p < m_frame->m_bookCtrl->GetPageCount(); p++) {\r
+\r
+               if (m_frame->m_bookCtrl->GetPageText(p) == wxString::Format(wxT("%u"), m_winnumber)) {\r
+                       m_frame->m_bookCtrl->ChangeSelection(p);\r
+                       break;\r
+               }\r
+\r
+       }\r
+\r
+       wxLogMessage(wxString::Format(wxT("Got focus: %d (%x)"), m_winnumber, event.GetWindow()));\r
+}\r
+\r
+/*void OPJChildFrame::OnLostFocus(wxFocusEvent& event)\r
+{\r
+       wxLogMessage(wxString::Format(wxT("Lost focus: %d (%x)"), m_winnumber, event.GetWindow()));\r
+\r
+}*/\r
+\r
+#if USE_GENERIC_TREECTRL\r
+BEGIN_EVENT_TABLE(OPJMarkerTree, wxGenericTreeCtrl)\r
+#else\r
+BEGIN_EVENT_TABLE(OPJMarkerTree, wxTreeCtrl)\r
+#endif\r
+    /*EVT_TREE_BEGIN_DRAG(TreeTest_Ctrl, OPJMarkerTree::OnBeginDrag)\r
+    EVT_TREE_BEGIN_RDRAG(TreeTest_Ctrl, OPJMarkerTree::OnBeginRDrag)\r
+    EVT_TREE_END_DRAG(TreeTest_Ctrl, OPJMarkerTree::OnEndDrag)*/\r
+    /*EVT_TREE_BEGIN_LABEL_EDIT(TreeTest_Ctrl, OPJMarkerTree::OnBeginLabelEdit)\r
+    EVT_TREE_END_LABEL_EDIT(TreeTest_Ctrl, OPJMarkerTree::OnEndLabelEdit)*/\r
+    /*EVT_TREE_DELETE_ITEM(TreeTest_Ctrl, OPJMarkerTree::OnDeleteItem)*/\r
+#if 0       // there are so many of those that logging them causes flicker\r
+    /*EVT_TREE_GET_INFO(TreeTest_Ctrl, OPJMarkerTree::OnGetInfo)*/\r
+#endif\r
+    /*EVT_TREE_SET_INFO(TreeTest_Ctrl, OPJMarkerTree::OnSetInfo)\r
+    EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, OPJMarkerTree::OnItemExpanded)*/\r
+    EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, OPJMarkerTree::OnItemExpanding)\r
+    /*EVT_TREE_ITEM_COLLAPSED(TreeTest_Ctrl, OPJMarkerTree::OnItemCollapsed)\r
+    EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, OPJMarkerTree::OnItemCollapsing)*/\r
+\r
+    EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, OPJMarkerTree::OnSelChanged)\r
+    /*EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, OPJMarkerTree::OnSelChanging)*/\r
+    /*EVT_TREE_KEY_DOWN(TreeTest_Ctrl, OPJMarkerTree::OnTreeKeyDown)*/\r
+    /*EVT_TREE_ITEM_ACTIVATED(TreeTest_Ctrl, OPJMarkerTree::OnItemActivated)*/\r
+\r
+    // so many differents ways to handle right mouse button clicks...\r
+    /*EVT_CONTEXT_MENU(OPJMarkerTree::OnContextMenu)*/\r
+    // EVT_TREE_ITEM_MENU is the preferred event for creating context menus\r
+    // on a tree control, because it includes the point of the click or item,\r
+    // meaning that no additional placement calculations are required.\r
+    /*EVT_TREE_ITEM_MENU(TreeTest_Ctrl, OPJMarkerTree::OnItemMenu)*/\r
+    /*EVT_TREE_ITEM_RIGHT_CLICK(TreeTest_Ctrl, OPJMarkerTree::OnItemRClick)*/\r
+\r
+    /*EVT_RIGHT_DOWN(OPJMarkerTree::OnRMouseDown)\r
+    EVT_RIGHT_UP(OPJMarkerTree::OnRMouseUp)\r
+    EVT_RIGHT_DCLICK(OPJMarkerTree::OnRMouseDClick)*/\r
+END_EVENT_TABLE()\r
+\r
+// OPJMarkerTree implementation\r
+#if USE_GENERIC_TREECTRL\r
+IMPLEMENT_DYNAMIC_CLASS(OPJMarkerTree, wxGenericTreeCtrl)\r
+#else\r
+IMPLEMENT_DYNAMIC_CLASS(OPJMarkerTree, wxTreeCtrl)\r
+#endif\r
+\r
+OPJMarkerTree::OPJMarkerTree(wxWindow *parent, wxFileName fname, wxString name, const wxWindowID id,\r
+                       const wxPoint& pos, const wxSize& size,\r
+                       long style)\r
+          : wxTreeCtrl(parent, id, pos, size, style)\r
+{\r
+    m_reverseSort = false;\r
+       m_fname = fname;\r
+\r
+       m_peektextCtrl = ((OPJFrame *) (parent->GetParent()->GetParent()))->m_textCtrlbrowse;\r
+    CreateImageList();\r
+\r
+    // Add some items to the tree\r
+    //AddTestItemsToTree(5, 5);\r
+    int image = wxGetApp().ShowImages() ? OPJMarkerTree::TreeCtrlIcon_Folder : -1;\r
+    wxTreeItemId rootId = AddRoot(name,\r
+                                  image, image,\r
+                                  new OPJMarkerData(name));\r
+\r
+    OPJParseThread *pthread = CreateParseThread();\r
+    if (pthread->Run() != wxTHREAD_NO_ERROR)\r
+        wxLogMessage(wxT("Can't start parse thread!"));\r
+    else\r
+               wxLogMessage(_T("New parse thread started."));\r
+}\r
+\r
+void OPJMarkerTree::CreateImageList(int size)\r
+{\r
+    if ( size == -1 )\r
+    {\r
+        SetImageList(NULL);\r
+        return;\r
+    }\r
+    if ( size == 0 )\r
+        size = m_imageSize;\r
+    else\r
+        m_imageSize = size;\r
+\r
+    // Make an image list containing small icons\r
+    wxImageList *images = new wxImageList(size, size, true);\r
+\r
+    // should correspond to TreeCtrlIcon_xxx enum\r
+    wxBusyCursor wait;\r
+    wxIcon icons[5];\r
+    icons[0] = wxIcon(icon1_xpm);\r
+    icons[1] = wxIcon(icon2_xpm);\r
+    icons[2] = wxIcon(icon3_xpm);\r
+    icons[3] = wxIcon(icon4_xpm);\r
+    icons[4] = wxIcon(icon5_xpm);\r
+\r
+    int sizeOrig = icons[0].GetWidth();\r
+    for ( size_t i = 0; i < WXSIZEOF(icons); i++ )\r
+    {\r
+        if ( size == sizeOrig )\r
+        {\r
+            images->Add(icons[i]);\r
+        }\r
+        else\r
+        {\r
+            images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));\r
+        }\r
+    }\r
+\r
+    AssignImageList(images);\r
+}\r
+\r
+#if USE_GENERIC_TREECTRL || !defined(__WXMSW__)\r
+void OPJMarkerTree::CreateButtonsImageList(int size)\r
+{\r
+    if ( size == -1 )\r
+    {\r
+        SetButtonsImageList(NULL);\r
+        return;\r
+    }\r
+\r
+    // Make an image list containing small icons\r
+    wxImageList *images = new wxImageList(size, size, true);\r
+\r
+    // should correspond to TreeCtrlIcon_xxx enum\r
+    wxBusyCursor wait;\r
+    wxIcon icons[4];\r
+    icons[0] = wxIcon(icon3_xpm);   // closed\r
+    icons[1] = wxIcon(icon3_xpm);   // closed, selected\r
+    icons[2] = wxIcon(icon5_xpm);   // open\r
+    icons[3] = wxIcon(icon5_xpm);   // open, selected\r
+\r
+    for ( size_t i = 0; i < WXSIZEOF(icons); i++ )\r
+    {\r
+        int sizeOrig = icons[i].GetWidth();\r
+        if ( size == sizeOrig )\r
+        {\r
+            images->Add(icons[i]);\r
+        }\r
+        else\r
+        {\r
+            images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));\r
+        }\r
+    }\r
+\r
+    AssignButtonsImageList(images);\r
+#else\r
+void OPJMarkerTree::CreateButtonsImageList(int WXUNUSED(size))\r
+{\r
+#endif\r
+}\r
+\r
+void OPJParseThread::LoadFile(wxFileName fname)\r
+{\r
+       wxTreeItemId rootid;\r
+\r
+       // this is the root node\r
+       int image = wxGetApp().ShowImages() ? m_tree->TreeCtrlIcon_Folder : -1;\r
+\r
+       if (this->m_parentid) {\r
+               // leaf of a tree\r
+               rootid = m_parentid;\r
+               m_tree->SetItemText(rootid, wxT("Parsing..."));\r
+\r
+       } else {\r
+\r
+               // delete the existing tree hierarchy\r
+               m_tree->DeleteAllItems();\r
+\r
+               // new tree\r
+               rootid = m_tree->AddRoot(wxT("Parsing..."),\r
+                       image,\r
+                       image,\r
+                       new OPJMarkerData(fname.GetFullPath())\r
+                       );\r
+               //m_tree->SetItemFont(rootid, *wxITALIC_FONT);\r
+               m_tree->SetItemBold(rootid);\r
+       }\r
+\r
+       // open the file\r
+       wxFile m_file(fname.GetFullPath().c_str(), wxFile::read);\r
+\r
+       // what is the extension?\r
+       if ((fname.GetExt() == wxT("j2k")) || (fname.GetExt() == wxT("j2c"))) {\r
+\r
+               // parse the file\r
+               ParseJ2KFile(&m_file, 0, m_file.Length(), rootid);\r
+\r
+       } else if ((fname.GetExt() == wxT("jp2")) || (fname.GetExt() == wxT("mj2"))) {\r
+\r
+               // parse the file\r
+               if (this->m_parentid) {\r
+                       //WriteText(wxT("Only a subsection of jp2"));\r
+                       OPJMarkerData *data = (OPJMarkerData *) m_tree->GetItemData(rootid);\r
+                       ParseJ2KFile(&m_file, data->m_start, data->m_length, rootid);\r
+                       m_tree->Expand(rootid);\r
+\r
+               } else\r
+                       // as usual\r
+                       ParseJP2File(&m_file, 0, m_file.Length(), rootid);\r
+\r
+       } else {\r
+\r
+               // unknown extension\r
+               WriteText(wxT("Unknown file format!"));\r
+\r
+       }\r
+\r
+       // close the file\r
+       m_file.Close();\r
+\r
+       // this is the root node\r
+       if (this->m_parentid)\r
+               m_tree->SetItemText(rootid, wxT("Codestream"));\r
+       else\r
+               m_tree->SetItemText(rootid, fname.GetFullName());\r
+       \r
+       WriteText(wxT("Parsing finished!"));\r
+}\r
+\r
+/*int OPJMarkerTree::OnCompareItems(const wxTreeItemId& item1,\r
+                               const wxTreeItemId& item2)\r
+{\r
+    if ( m_reverseSort )\r
+    {\r
+        // just exchange 1st and 2nd items\r
+        return wxTreeCtrl::OnCompareItems(item2, item1);\r
+    }\r
+    else\r
+    {\r
+        return wxTreeCtrl::OnCompareItems(item1, item2);\r
+    }\r
+}*/\r
+\r
+/*void OPJMarkerTree::AddItemsRecursively(const wxTreeItemId& idParent,\r
+                                     size_t numChildren,\r
+                                     size_t depth,\r
+                                     size_t folder)\r
+{\r
+    if ( depth > 0 )\r
+    {\r
+        bool hasChildren = depth > 1;\r
+\r
+        wxString str;\r
+        for ( size_t n = 0; n < numChildren; n++ )\r
+        {\r
+            // at depth 1 elements won't have any more children\r
+            if ( hasChildren )\r
+                str.Printf(wxT("%s child %u"), wxT("Folder"), unsigned(n + 1));\r
+            else\r
+                str.Printf(wxT("%s child %u.%u"), wxT("File"), unsigned(folder), unsigned(n + 1));\r
+\r
+            // here we pass to AppendItem() normal and selected item images (we\r
+            // suppose that selected image follows the normal one in the enum)\r
+            int image, imageSel;\r
+            if ( wxGetApp().ShowImages() )\r
+            {\r
+                image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder;\r
+                imageSel = image + 1;\r
+            }\r
+            else\r
+            {\r
+                image = imageSel = -1;\r
+            }\r
+            wxTreeItemId id = AppendItem(idParent, str, image, imageSel,\r
+                                         new OPJMarkerData(str));\r
+\r
+            // and now we also set the expanded one (only for the folders)\r
+            if ( hasChildren && wxGetApp().ShowImages() )\r
+            {\r
+                SetItemImage(id, TreeCtrlIcon_FolderOpened,\r
+                             wxTreeItemIcon_Expanded);\r
+            }\r
+\r
+            // remember the last child for OnEnsureVisible()\r
+            if ( !hasChildren && n == numChildren - 1 )\r
+            {\r
+                m_lastItem = id;\r
+            }\r
+\r
+            AddItemsRecursively(id, numChildren, depth - 1, n + 1);\r
+        }\r
+    }\r
+    //else: done!\r
+}*/\r
+\r
+/*void OPJMarkerTree::AddTestItemsToTree(size_t numChildren,\r
+                                    size_t depth)\r
+{\r
+    int image = wxGetApp().ShowImages() ? OPJMarkerTree::TreeCtrlIcon_Folder : -1;\r
+    wxTreeItemId rootId = AddRoot(wxT("Root"),\r
+                                  image, image,\r
+                                  new OPJMarkerData(wxT("Root item")));\r
+    if ( image != -1 )\r
+    {\r
+        SetItemImage(rootId, TreeCtrlIcon_FolderOpened, wxTreeItemIcon_Expanded);\r
+    }\r
+\r
+    AddItemsRecursively(rootId, numChildren, depth, 0);\r
+\r
+    // set some colours/fonts for testing\r
+    SetItemFont(rootId, *wxITALIC_FONT);\r
+\r
+    wxTreeItemIdValue cookie;\r
+    wxTreeItemId id = GetFirstChild(rootId, cookie);\r
+    SetItemTextColour(id, *wxBLUE);\r
+\r
+    id = GetNextChild(rootId, cookie);\r
+    id = GetNextChild(rootId, cookie);\r
+    SetItemTextColour(id, *wxRED);\r
+    SetItemBackgroundColour(id, *wxLIGHT_GREY);\r
+}*/\r
+\r
+/*void OPJMarkerTree::GetItemsRecursively(const wxTreeItemId& idParent,\r
+                                     wxTreeItemIdValue cookie)\r
+{\r
+    wxTreeItemId id;\r
+\r
+    if ( !cookie )\r
+        id = GetFirstChild(idParent, cookie);\r
+    else\r
+        id = GetNextChild(idParent, cookie);\r
+\r
+    if ( !id.IsOk() )\r
+        return;\r
+\r
+    wxString text = GetItemText(id);\r
+    wxLogMessage(text);\r
+\r
+    if (ItemHasChildren(id))\r
+        GetItemsRecursively(id);\r
+\r
+    GetItemsRecursively(idParent, cookie);\r
+}*/\r
+\r
+/*void OPJMarkerTree::DoToggleIcon(const wxTreeItemId& item)\r
+{\r
+    int image = (GetItemImage(item) == TreeCtrlIcon_Folder)\r
+                    ? TreeCtrlIcon_File\r
+                    : TreeCtrlIcon_Folder;\r
+    SetItemImage(item, image, wxTreeItemIcon_Normal);\r
+\r
+    image = (GetItemImage(item) == TreeCtrlIcon_FolderSelected)\r
+                    ? TreeCtrlIcon_FileSelected\r
+                    : TreeCtrlIcon_FolderSelected;\r
+    SetItemImage(item, image, wxTreeItemIcon_Selected);\r
+}*/\r
+\r
+void OPJMarkerTree::LogEvent(const wxChar *name, const wxTreeEvent& event)\r
+{\r
+    wxTreeItemId item = event.GetItem();\r
+    wxString text;\r
+    if ( item.IsOk() )\r
+        text << _T('"') << GetItemText(item).c_str() << _T('"');\r
+    else\r
+        text = _T("invalid item");\r
+    wxLogMessage(wxT("%s(%s)"), name, text.c_str());\r
+}\r
+\r
+OPJParseThread *OPJMarkerTree::CreateParseThread(wxTreeItemId parentid)\r
+{\r
+    OPJParseThread *pthread = new OPJParseThread(this, parentid);\r
+\r
+    if (pthread->Create() != wxTHREAD_NO_ERROR)\r
+               wxLogError(wxT("Can't create parse thread!"));\r
+\r
+    wxCriticalSectionLocker enter(wxGetApp().m_parse_critsect);\r
+    wxGetApp().m_parse_threads.Add(pthread);\r
+\r
+    return pthread;\r
+}\r
+\r
+\r
+/*// avoid repetition\r
+#define TREE_EVENT_HANDLER(name)                                 \\r
+void OPJMarkerTree::name(wxTreeEvent& event)                        \\r
+{                                                                \\r
+    LogEvent(_T(#name), event);                                  \\r
+    SetLastItem(wxTreeItemId());                                 \\r
+    event.Skip();                                                \\r
+}*/\r
+\r
+/*TREE_EVENT_HANDLER(OnBeginRDrag)*/\r
+/*TREE_EVENT_HANDLER(OnDeleteItem)*/\r
+/*TREE_EVENT_HANDLER(OnGetInfo)\r
+TREE_EVENT_HANDLER(OnSetInfo)*/\r
+/*TREE_EVENT_HANDLER(OnItemExpanded)\r
+TREE_EVENT_HANDLER(OnItemExpanding)*/\r
+/*TREE_EVENT_HANDLER(OnItemCollapsed)*/\r
+/*TREE_EVENT_HANDLER(OnSelChanged)\r
+TREE_EVENT_HANDLER(OnSelChanging)*/\r
+\r
+/*#undef TREE_EVENT_HANDLER*/\r
+\r
+void OPJMarkerTree::OnItemExpanding(wxTreeEvent& event)\r
+{\r
+       wxTreeItemId item = event.GetItem();\r
+       OPJMarkerData* data = (OPJMarkerData *) GetItemData(item);\r
+       wxString text;\r
+\r
+       if (item.IsOk())\r
+               text << wxT('"') << GetItemText(item).c_str() << wxT('"');\r
+       else\r
+               text = wxT("invalid item");\r
+\r
+       if (strcmp(data->GetDesc1(), wxT("INFO-CSTREAM")))\r
+               return;\r
+\r
+       wxLogMessage(wxT("Expanding... (%s -> %s, %s, %d, %d)"),\r
+               text.c_str(), data->GetDesc1(), data->GetDesc2(),\r
+               data->m_start, data->m_length);\r
+\r
+       // the codestream box is being asked for expansion\r
+       wxTreeItemIdValue cookie;\r
+       if (!GetFirstChild(item, cookie).IsOk()) {\r
+               OPJParseThread *pthread = CreateParseThread(item);\r
+               if (pthread->Run() != wxTHREAD_NO_ERROR)\r
+                       wxLogMessage(wxT("Can't start parse thread!"));\r
+               else\r
+                       wxLogMessage(wxT("New parse thread started."));\r
+       }\r
+}\r
+\r
+void OPJMarkerTree::OnSelChanged(wxTreeEvent& event)\r
+{\r
+#define BUNCH_LINESIZE 24\r
+#define BUNCH_NUMLINES 6\r
+\r
+       wxTreeItemId item = event.GetItem();\r
+       OPJMarkerData* data = (OPJMarkerData *) GetItemData(item);\r
+       wxString text;\r
+       int l, c, pos = 0, pre_pos;\r
+       unsigned char buffer[BUNCH_LINESIZE * BUNCH_NUMLINES];\r
+\r
+       m_peektextCtrl->Clear();\r
+\r
+       /*wxTextAttr myattr = m_peektextCtrl->GetDefaultStyle();\r
+       myattr.SetFont(wxFont(10, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));\r
+       m_peektextCtrl->SetDefaultStyle(myattr);*/\r
+\r
+       text << wxString::Format(wxT("Selected... (%s -> %s, %s, %d, %d)"),\r
+               text.c_str(), data->GetDesc1(), data->GetDesc2(),\r
+               data->m_start, data->m_length) << wxT("\n");\r
+\r
+       // open the file and browse a little\r
+       wxFile *fp = new wxFile(m_fname.GetFullPath().c_str(), wxFile::read);\r
+\r
+       // go to position claimed\r
+       fp->Seek(data->m_start, wxFromStart);\r
+\r
+       // read a bunch\r
+       int max_read = wxMin(WXSIZEOF(buffer), data->m_length - data->m_start + 1);\r
+       fp->Read(buffer, max_read);\r
+\r
+       pos = 0;\r
+       for (l = 0; l < BUNCH_NUMLINES; l++) {\r
+\r
+               text << wxString::Format(wxT("%08d:"), data->m_start + pos);\r
+\r
+               pre_pos = pos;\r
+\r
+               // add hex browsing text\r
+               for (c = 0; c < BUNCH_LINESIZE; c++) {\r
+\r
+                       if (!(c % 8))\r
+                               text << wxT(" ");\r
+\r
+                       if (pos < max_read) {\r
+                               text << wxString::Format(wxT("%02X "), wxT(buffer[pos]));\r
+                       } else\r
+                               text << wxT("   ");\r
+                       pos++;\r
+               }\r
+\r
+               text << wxT("    ");\r
+\r
+               // add char browsing text\r
+               for (c = 0; c < BUNCH_LINESIZE; c++) {\r
+\r
+                       if (pre_pos < max_read) {\r
+                               if ((buffer[pre_pos] == '\n') || (buffer[pre_pos] == '\t'))\r
+                                       buffer[pre_pos] = ' ';\r
+                               text << wxString::Format(wxT("%c."), wxChar(buffer[pre_pos]));\r
+                       } else\r
+                               text << wxT("  ");\r
+                       pre_pos++;\r
+               }\r
+\r
+               text << wxT("\n");\r
+\r
+       }\r
+\r
+       // close the file\r
+       fp->Close();\r
+\r
+       m_peektextCtrl->WriteText(text);\r
+}\r
+\r
+/*void LogKeyEvent(const wxChar *name, const wxKeyEvent& event)\r
+{\r
+    wxString key;\r
+    long keycode = event.GetKeyCode();\r
+    {\r
+        switch ( keycode )\r
+        {\r
+            case WXK_BACK: key = wxT("BACK"); break;\r
+            case WXK_TAB: key = wxT("TAB"); break;\r
+            case WXK_RETURN: key = wxT("RETURN"); break;\r
+            case WXK_ESCAPE: key = wxT("ESCAPE"); break;\r
+            case WXK_SPACE: key = wxT("SPACE"); break;\r
+            case WXK_DELETE: key = wxT("DELETE"); break;\r
+            case WXK_START: key = wxT("START"); break;\r
+            case WXK_LBUTTON: key = wxT("LBUTTON"); break;\r
+            case WXK_RBUTTON: key = wxT("RBUTTON"); break;\r
+            case WXK_CANCEL: key = wxT("CANCEL"); break;\r
+            case WXK_MBUTTON: key = wxT("MBUTTON"); break;\r
+            case WXK_CLEAR: key = wxT("CLEAR"); break;\r
+            case WXK_SHIFT: key = wxT("SHIFT"); break;\r
+            case WXK_ALT: key = wxT("ALT"); break;\r
+            case WXK_CONTROL: key = wxT("CONTROL"); break;\r
+            case WXK_MENU: key = wxT("MENU"); break;\r
+            case WXK_PAUSE: key = wxT("PAUSE"); break;\r
+            case WXK_CAPITAL: key = wxT("CAPITAL"); break;\r
+            case WXK_END: key = wxT("END"); break;\r
+            case WXK_HOME: key = wxT("HOME"); break;\r
+            case WXK_LEFT: key = wxT("LEFT"); break;\r
+            case WXK_UP: key = wxT("UP"); break;\r
+            case WXK_RIGHT: key = wxT("RIGHT"); break;\r
+            case WXK_DOWN: key = wxT("DOWN"); break;\r
+            case WXK_SELECT: key = wxT("SELECT"); break;\r
+            case WXK_PRINT: key = wxT("PRINT"); break;\r
+            case WXK_EXECUTE: key = wxT("EXECUTE"); break;\r
+            case WXK_SNAPSHOT: key = wxT("SNAPSHOT"); break;\r
+            case WXK_INSERT: key = wxT("INSERT"); break;\r
+            case WXK_HELP: key = wxT("HELP"); break;\r
+            case WXK_NUMPAD0: key = wxT("NUMPAD0"); break;\r
+            case WXK_NUMPAD1: key = wxT("NUMPAD1"); break;\r
+            case WXK_NUMPAD2: key = wxT("NUMPAD2"); break;\r
+            case WXK_NUMPAD3: key = wxT("NUMPAD3"); break;\r
+            case WXK_NUMPAD4: key = wxT("NUMPAD4"); break;\r
+            case WXK_NUMPAD5: key = wxT("NUMPAD5"); break;\r
+            case WXK_NUMPAD6: key = wxT("NUMPAD6"); break;\r
+            case WXK_NUMPAD7: key = wxT("NUMPAD7"); break;\r
+            case WXK_NUMPAD8: key = wxT("NUMPAD8"); break;\r
+            case WXK_NUMPAD9: key = wxT("NUMPAD9"); break;\r
+            case WXK_MULTIPLY: key = wxT("MULTIPLY"); break;\r
+            case WXK_ADD: key = wxT("ADD"); break;\r
+            case WXK_SEPARATOR: key = wxT("SEPARATOR"); break;\r
+            case WXK_SUBTRACT: key = wxT("SUBTRACT"); break;\r
+            case WXK_DECIMAL: key = wxT("DECIMAL"); break;\r
+            case WXK_DIVIDE: key = wxT("DIVIDE"); break;\r
+            case WXK_F1: key = wxT("F1"); break;\r
+            case WXK_F2: key = wxT("F2"); break;\r
+            case WXK_F3: key = wxT("F3"); break;\r
+            case WXK_F4: key = wxT("F4"); break;\r
+            case WXK_F5: key = wxT("F5"); break;\r
+            case WXK_F6: key = wxT("F6"); break;\r
+            case WXK_F7: key = wxT("F7"); break;\r
+            case WXK_F8: key = wxT("F8"); break;\r
+            case WXK_F9: key = wxT("F9"); break;\r
+            case WXK_F10: key = wxT("F10"); break;\r
+            case WXK_F11: key = wxT("F11"); break;\r
+            case WXK_F12: key = wxT("F12"); break;\r
+            case WXK_F13: key = wxT("F13"); break;\r
+            case WXK_F14: key = wxT("F14"); break;\r
+            case WXK_F15: key = wxT("F15"); break;\r
+            case WXK_F16: key = wxT("F16"); break;\r
+            case WXK_F17: key = wxT("F17"); break;\r
+            case WXK_F18: key = wxT("F18"); break;\r
+            case WXK_F19: key = wxT("F19"); break;\r
+            case WXK_F20: key = wxT("F20"); break;\r
+            case WXK_F21: key = wxT("F21"); break;\r
+            case WXK_F22: key = wxT("F22"); break;\r
+            case WXK_F23: key = wxT("F23"); break;\r
+            case WXK_F24: key = wxT("F24"); break;\r
+            case WXK_NUMLOCK: key = wxT("NUMLOCK"); break;\r
+            case WXK_SCROLL: key = wxT("SCROLL"); break;\r
+            case WXK_PAGEUP: key = wxT("PAGEUP"); break;\r
+            case WXK_PAGEDOWN: key = wxT("PAGEDOWN"); break;\r
+            case WXK_NUMPAD_SPACE: key = wxT("NUMPAD_SPACE"); break;\r
+            case WXK_NUMPAD_TAB: key = wxT("NUMPAD_TAB"); break;\r
+            case WXK_NUMPAD_ENTER: key = wxT("NUMPAD_ENTER"); break;\r
+            case WXK_NUMPAD_F1: key = wxT("NUMPAD_F1"); break;\r
+            case WXK_NUMPAD_F2: key = wxT("NUMPAD_F2"); break;\r
+            case WXK_NUMPAD_F3: key = wxT("NUMPAD_F3"); break;\r
+            case WXK_NUMPAD_F4: key = wxT("NUMPAD_F4"); break;\r
+            case WXK_NUMPAD_HOME: key = wxT("NUMPAD_HOME"); break;\r
+            case WXK_NUMPAD_LEFT: key = wxT("NUMPAD_LEFT"); break;\r
+            case WXK_NUMPAD_UP: key = wxT("NUMPAD_UP"); break;\r
+            case WXK_NUMPAD_RIGHT: key = wxT("NUMPAD_RIGHT"); break;\r
+            case WXK_NUMPAD_DOWN: key = wxT("NUMPAD_DOWN"); break;\r
+            case WXK_NUMPAD_PAGEUP: key = wxT("NUMPAD_PAGEUP"); break;\r
+            case WXK_NUMPAD_PAGEDOWN: key = wxT("NUMPAD_PAGEDOWN"); break;\r
+            case WXK_NUMPAD_END: key = wxT("NUMPAD_END"); break;\r
+            case WXK_NUMPAD_BEGIN: key = wxT("NUMPAD_BEGIN"); break;\r
+            case WXK_NUMPAD_INSERT: key = wxT("NUMPAD_INSERT"); break;\r
+            case WXK_NUMPAD_DELETE: key = wxT("NUMPAD_DELETE"); break;\r
+            case WXK_NUMPAD_EQUAL: key = wxT("NUMPAD_EQUAL"); break;\r
+            case WXK_NUMPAD_MULTIPLY: key = wxT("NUMPAD_MULTIPLY"); break;\r
+            case WXK_NUMPAD_ADD: key = wxT("NUMPAD_ADD"); break;\r
+            case WXK_NUMPAD_SEPARATOR: key = wxT("NUMPAD_SEPARATOR"); break;\r
+            case WXK_NUMPAD_SUBTRACT: key = wxT("NUMPAD_SUBTRACT"); break;\r
+            case WXK_NUMPAD_DECIMAL: key = wxT("NUMPAD_DECIMAL"); break;\r
+\r
+            default:\r
+            {\r
+               if ( keycode < 128 && wxIsprint((int)keycode) )\r
+                   key.Printf(wxT("'%c'"), (char)keycode);\r
+               else if ( keycode > 0 && keycode < 27 )\r
+                   key.Printf(_("Ctrl-%c"), wxT('A') + keycode - 1);\r
+               else\r
+                   key.Printf(wxT("unknown (%ld)"), keycode);\r
+            }\r
+        }\r
+    }\r
+\r
+    wxLogMessage( wxT("%s event: %s (flags = %c%c%c%c)"),\r
+                  name,\r
+                  key.c_str(),\r
+                  event.ControlDown() ? wxT('C') : wxT('-'),\r
+                  event.AltDown() ? wxT('A') : wxT('-'),\r
+                  event.ShiftDown() ? wxT('S') : wxT('-'),\r
+                  event.MetaDown() ? wxT('M') : wxT('-'));\r
+}\r
+\r
+void OPJMarkerTree::OnTreeKeyDown(wxTreeEvent& event)\r
+{\r
+    LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());\r
+\r
+    event.Skip();\r
+}*/\r
+\r
+/*void OPJMarkerTree::OnBeginDrag(wxTreeEvent& event)\r
+{\r
+    // need to explicitly allow drag\r
+    if ( event.GetItem() != GetRootItem() )\r
+    {\r
+        m_draggedItem = event.GetItem();\r
+\r
+        wxLogMessage(wxT("OnBeginDrag: started dragging %s"),\r
+                     GetItemText(m_draggedItem).c_str());\r
+\r
+        event.Allow();\r
+    }\r
+    else\r
+    {\r
+        wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));\r
+    }\r
+}\r
+\r
+void OPJMarkerTree::OnEndDrag(wxTreeEvent& event)\r
+{\r
+    wxTreeItemId itemSrc = m_draggedItem,\r
+                 itemDst = event.GetItem();\r
+    m_draggedItem = (wxTreeItemId)0l;\r
+\r
+    // where to copy the item?\r
+    if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )\r
+    {\r
+        // copy to the parent then\r
+        itemDst = GetItemParent(itemDst);\r
+    }\r
+\r
+    if ( !itemDst.IsOk() )\r
+    {\r
+        wxLogMessage(wxT("OnEndDrag: can't drop here."));\r
+\r
+        return;\r
+    }\r
+\r
+    wxString text = GetItemText(itemSrc);\r
+    wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),\r
+                 text.c_str(), GetItemText(itemDst).c_str());\r
+\r
+    // just do append here - we could also insert it just before/after the item\r
+    // on which it was dropped, but this requires slightly more work... we also\r
+    // completely ignore the client data and icon of the old item but could\r
+    // copy them as well.\r
+    //\r
+    // Finally, we only copy one item here but we might copy the entire tree if\r
+    // we were dragging a folder.\r
+    int image = wxGetApp().ShowImages() ? TreeCtrlIcon_File : -1;\r
+    AppendItem(itemDst, text, image);\r
+}*/\r
+\r
+/*void OPJMarkerTree::OnBeginLabelEdit(wxTreeEvent& event)\r
+{\r
+    wxLogMessage(wxT("OnBeginLabelEdit"));\r
+\r
+    // for testing, prevent this item's label editing\r
+    wxTreeItemId itemId = event.GetItem();\r
+    if ( IsTestItem(itemId) )\r
+    {\r
+        wxMessageBox(wxT("You can't edit this item."));\r
+\r
+        event.Veto();\r
+    }\r
+    else if ( itemId == GetRootItem() )\r
+    {\r
+        // test that it is possible to change the text of the item being edited\r
+        SetItemText(itemId, _T("Editing root item"));\r
+    }\r
+}\r
+\r
+void OPJMarkerTree::OnEndLabelEdit(wxTreeEvent& event)\r
+{\r
+    wxLogMessage(wxT("OnEndLabelEdit"));\r
+\r
+    // don't allow anything except letters in the labels\r
+    if ( !event.GetLabel().IsWord() )\r
+    {\r
+        wxMessageBox(wxT("The new label should be a single word."));\r
+\r
+        event.Veto();\r
+    }\r
+}*/\r
+\r
+/*void OPJMarkerTree::OnItemCollapsing(wxTreeEvent& event)\r
+{\r
+    wxLogMessage(wxT("OnItemCollapsing"));\r
+\r
+    // for testing, prevent the user from collapsing the first child folder\r
+    wxTreeItemId itemId = event.GetItem();\r
+    if ( IsTestItem(itemId) )\r
+    {\r
+        wxMessageBox(wxT("You can't collapse this item."));\r
+\r
+        event.Veto();\r
+    }\r
+}*/\r
+\r
+/*void OPJMarkerTree::OnItemActivated(wxTreeEvent& event)\r
+{\r
+    // show some info about this item\r
+    wxTreeItemId itemId = event.GetItem();\r
+    OPJMarkerData *item = (OPJMarkerData *)GetItemData(itemId);\r
+\r
+    if ( item != NULL )\r
+    {\r
+        item->ShowInfo(this);\r
+    }\r
+\r
+    wxLogMessage(wxT("OnItemActivated"));\r
+}*/\r
+\r
+/*void OPJMarkerTree::OnItemMenu(wxTreeEvent& event)\r
+{\r
+    wxTreeItemId itemId = event.GetItem();\r
+    OPJMarkerData *item = itemId.IsOk() ? (OPJMarkerData *)GetItemData(itemId)\r
+                                         : NULL;\r
+\r
+    wxLogMessage(wxT("OnItemMenu for item \"%s\""), item ? item->GetDesc()\r
+                                                         : _T(""));\r
+\r
+    event.Skip();\r
+}*/\r
+\r
+/*void OPJMarkerTree::OnContextMenu(wxContextMenuEvent& event)\r
+{\r
+    wxPoint pt = event.GetPosition();\r
+    wxTreeItemId item;\r
+    wxLogMessage(wxT("OnContextMenu at screen coords (%i, %i)"), pt.x, pt.y);\r
+\r
+    // check if event was generated by keyboard (MSW-specific?)\r
+    if ( pt.x == -1 && pt.y == -1 ) //(this is how MSW indicates it)\r
+    {\r
+        if ( !HasFlag(wxTR_MULTIPLE) )\r
+            item = GetSelection();\r
+\r
+        // attempt to guess where to show the menu\r
+        if ( item.IsOk() )\r
+        {\r
+            // if an item was clicked, show menu to the right of it\r
+            wxRect rect;\r
+            GetBoundingRect(item, rect, true );// only the label\r
+            pt = wxPoint(rect.GetRight(), rect.GetTop());\r
+        }\r
+        else\r
+        {\r
+            pt = wxPoint(0, 0);\r
+        }\r
+    }\r
+    else // event was generated by mouse, use supplied coords\r
+    {\r
+        pt = ScreenToClient(pt);\r
+        item = HitTest(pt);\r
+    }\r
+\r
+    ShowMenu(item, pt);\r
+}*/\r
+\r
+/*void OPJMarkerTree::ShowMenu(wxTreeItemId id, const wxPoint& pt)\r
+{\r
+    wxString title;\r
+    if ( id.IsOk() )\r
+    {\r
+        title << wxT("Menu for ") << GetItemText(id);\r
+    }\r
+    else\r
+    {\r
+        title = wxT("Menu for no particular item");\r
+    }\r
+\r
+#if wxUSE_MENUS\r
+    wxMenu menu(title);\r
+    menu.Append(TreeTest_About, wxT("&About..."));\r
+    menu.AppendSeparator();\r
+    menu.Append(TreeTest_Highlight, wxT("&Highlight item"));\r
+    menu.Append(TreeTest_Dump, wxT("&Dump"));\r
+\r
+    PopupMenu(&menu, pt);\r
+#endif // wxUSE_MENUS\r
+}*/\r
+\r
+/*void OPJMarkerTree::OnItemRClick(wxTreeEvent& event)\r
+{\r
+    wxTreeItemId itemId = event.GetItem();\r
+    OPJMarkerData *item = itemId.IsOk() ? (OPJMarkerData *)GetItemData(itemId)\r
+                                         : NULL;\r
+\r
+    wxLogMessage(wxT("Item \"%s\" right clicked"), item ? item->GetDesc()\r
+                                                        : _T(""));\r
+\r
+    event.Skip();\r
+}*/\r
+\r
+/*\r
+void OPJMarkerTree::OnRMouseDown(wxMouseEvent& event)\r
+{\r
+    wxLogMessage(wxT("Right mouse button down"));\r
+\r
+    event.Skip();\r
+}\r
+\r
+void OPJMarkerTree::OnRMouseUp(wxMouseEvent& event)\r
+{\r
+    wxLogMessage(wxT("Right mouse button up"));\r
+\r
+    event.Skip();\r
+}\r
+\r
+void OPJMarkerTree::OnRMouseDClick(wxMouseEvent& event)\r
+{\r
+    wxTreeItemId id = HitTest(event.GetPosition());\r
+    if ( !id )\r
+        wxLogMessage(wxT("No item under mouse"));\r
+    else\r
+    {\r
+        OPJMarkerData *item = (OPJMarkerData *)GetItemData(id);\r
+        if ( item )\r
+            wxLogMessage(wxT("Item '%s' under mouse"), item->GetDesc());\r
+    }\r
+\r
+    event.Skip();\r
+}\r
+*/\r
+\r
+static inline const wxChar *Bool2String(bool b)\r
+{\r
+    return b ? wxT("") : wxT("not ");\r
+}\r
+\r
+void OPJMarkerData::ShowInfo(wxTreeCtrl *tree)\r
+{\r
+    wxLogMessage(wxT("Item '%s': %sselected, %sexpanded, %sbold,\n")\r
+                 wxT("%u children (%u immediately under this item)."),\r
+                 m_desc.c_str(),\r
+                 Bool2String(tree->IsSelected(GetId())),\r
+                 Bool2String(tree->IsExpanded(GetId())),\r
+                 Bool2String(tree->IsBold(GetId())),\r
+                 unsigned(tree->GetChildrenCount(GetId())),\r
+                 unsigned(tree->GetChildrenCount(GetId(), false)));\r
+}\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Decoding thread class\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+OPJDecoThread::OPJDecoThread(OPJCanvas *canvas)\r
+        : wxThread()\r
+{\r
+    m_count = 0;\r
+    m_canvas = canvas;\r
+}\r
+\r
+void OPJDecoThread::WriteText(const wxString& text)\r
+{\r
+    wxString msg;\r
+\r
+    // before doing any GUI calls we must ensure that this thread is the only\r
+    // one doing it!\r
+\r
+    wxMutexGuiEnter();\r
+\r
+    msg << text;\r
+    m_canvas->WriteText(msg);\r
+\r
+    wxMutexGuiLeave();\r
+}\r
+\r
+void OPJDecoThread::OnExit()\r
+{\r
+    wxCriticalSectionLocker locker(wxGetApp().m_deco_critsect);\r
+\r
+    wxArrayThread& dthreads = wxGetApp().m_deco_threads;\r
+    dthreads.Remove(this);\r
+\r
+    if (dthreads.IsEmpty() )\r
+    {\r
+        // signal the main thread that there are no more threads left if it is\r
+        // waiting for us\r
+        if (wxGetApp().m_deco_waitingUntilAllDone) {\r
+            wxGetApp().m_deco_waitingUntilAllDone = false;\r
+            wxGetApp().m_deco_semAllDone.Post();\r
+        }\r
+    }\r
+}\r
+\r
+void *OPJDecoThread::Entry()\r
+{\r
+\r
+    wxString text;\r
+\r
+       srand(GetId());\r
+       int m_countnum = rand() % 9;\r
+    text.Printf(wxT("Deco thread 0x%lx started (priority = %u, time = %d)."),\r
+                GetId(), GetPriority(), m_countnum);\r
+    WriteText(text);\r
+    // wxLogMessage(text); -- test wxLog thread safeness\r
+\r
+       //wxBusyCursor wait;\r
+       //wxBusyInfo wait(wxT("Decoding image ..."));\r
+\r
+\r
+    /*for (m_count = 0; m_count < m_countnum; m_count++) {\r
+        // check if we were asked to exit\r
+        if ( TestDestroy() )\r
+            break;\r
+\r
+        text.Printf(wxT("[%u] Deco thread 0x%lx here."), m_count, GetId());\r
+        WriteText(text);\r
+\r
+        // wxSleep() can't be called from non-GUI thread!\r
+        wxThread::Sleep(10);\r
+    }*/\r
+\r
+    wxBitmap bitmap( 100, 100 );\r
+    wxImage image = bitmap.ConvertToImage();\r
+    image.Destroy();\r
+\r
+       WriteText(m_canvas->m_fname.GetFullPath());\r
+\r
+    if (!image.LoadFile(m_canvas->m_fname.GetFullPath(), wxBITMAP_TYPE_ANY), 0) {\r
+        wxLogError(wxT("Can't load image"));\r
+               return NULL;\r
+       }\r
+\r
+    m_canvas->m_image = wxBitmap(image);\r
+       m_canvas->Refresh();\r
+       m_canvas->SetScrollbars(20, 20, (int)(0.5 + (double) image.GetWidth() / 20.0), (int)(0.5 + (double) image.GetHeight() / 20.0));\r
+\r
+    text.Printf(wxT("Deco thread 0x%lx finished."), GetId());\r
+    WriteText(text);\r
+    // wxLogMessage(text); -- test wxLog thread safeness\r
+\r
+    return NULL;\r
+}\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Parsing thread class\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+OPJParseThread::OPJParseThread(OPJMarkerTree *tree, wxTreeItemId parentid)\r
+        : wxThread()\r
+{\r
+    m_count = 0;\r
+    m_tree = tree;\r
+       m_parentid = parentid;\r
+}\r
+\r
+void OPJParseThread::WriteText(const wxString& text)\r
+{\r
+    wxString msg;\r
+\r
+    // before doing any GUI calls we must ensure that this thread is the only\r
+    // one doing it!\r
+\r
+    wxMutexGuiEnter();\r
+\r
+    msg << text;\r
+    m_tree->WriteText(msg);\r
+\r
+    wxMutexGuiLeave();\r
+}\r
+\r
+void OPJParseThread::OnExit()\r
+{\r
+    wxCriticalSectionLocker locker(wxGetApp().m_parse_critsect);\r
+\r
+    wxArrayThread& threads = wxGetApp().m_parse_threads;\r
+    threads.Remove(this);\r
+\r
+    if ( threads.IsEmpty() )\r
+    {\r
+        // signal the main thread that there are no more threads left if it is\r
+        // waiting for us\r
+        if ( wxGetApp().m_parse_waitingUntilAllDone )\r
+        {\r
+            wxGetApp().m_parse_waitingUntilAllDone = false;\r
+\r
+            wxGetApp().m_parse_semAllDone.Post();\r
+        }\r
+    }\r
+}\r
+\r
+void *OPJParseThread::Entry()\r
+{\r
+\r
+    wxString text;\r
+\r
+       srand( GetId() );\r
+       int m_countnum = rand() % 9;\r
+    text.Printf(wxT("Parse thread 0x%lx started (priority = %u, time = %d)."),\r
+                GetId(), GetPriority(), m_countnum);\r
+    WriteText(text);\r
+    // wxLogMessage(text); -- test wxLog thread safeness\r
+\r
+       //wxBusyCursor wait;\r
+       //wxBusyInfo wait(wxT("Decoding image ..."));\r
+\r
+\r
+    /*for ( m_count = 0; m_count < m_countnum; m_count++ )\r
+    {\r
+        // check if we were asked to exit\r
+        if ( TestDestroy() )\r
+            break;\r
+\r
+        text.Printf(wxT("[%u] Parse thread 0x%lx here."), m_count, GetId());\r
+        WriteText(text);\r
+\r
+        // wxSleep() can't be called from non-GUI thread!\r
+        wxThread::Sleep(10);\r
+    }*/\r
+\r
+\r
+    LoadFile(m_tree->m_fname);\r
+\r
+    text.Printf(wxT("Parse thread 0x%lx finished."), GetId());\r
+    WriteText(text);\r
+    // wxLogMessage(text); -- test wxLog thread safeness\r
+\r
+    return NULL;\r
+}\r
diff --git a/OPJViewer/source/OPJViewer.h b/OPJViewer/source/OPJViewer.h
new file mode 100644 (file)
index 0000000..f386ea8
--- /dev/null
@@ -0,0 +1,469 @@
+/*\r
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        sashtest.h\r
+// Purpose:     Layout window/sash sample\r
+// Author:      Julian Smart\r
+// Modified by:\r
+// Created:     04/01/98\r
+// RCS-ID:      $Id: sashtest.h,v 1.5 2005/06/02 12:04:24 JS Exp $\r
+// Copyright:   (c) Julian Smart\r
+// Licence:     wxWindows license\r
+/////////////////////////////////////////////////////////////////////////////\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        treectrl.h\r
+// Purpose:     wxTreeCtrl sample\r
+// Author:      Julian Smart\r
+// Modified by:\r
+// Created:     04/01/98\r
+// RCS-ID:      $Id: treetest.h,v 1.50 2006/11/04 11:26:51 VZ Exp $\r
+// Copyright:   (c) Julian Smart\r
+// Licence:     wxWindows license\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef __OPJ_VIEWER_H__\r
+#define __OPJ_VIEWER_H__\r
+\r
+// For compilers that support precompilation, includes "wx/wx.h".\r
+#include "wx/wxprec.h"\r
+\r
+#ifdef __BORLANDC__\r
+#pragma hdrstop\r
+#endif\r
+\r
+#ifndef WX_PRECOMP\r
+#include "wx/wx.h"\r
+#include "wx/mdi.h"\r
+#endif\r
+\r
+#include "wx/toolbar.h"\r
+#include "wx/laywin.h"\r
+#include "wx/treectrl.h"\r
+\r
+#include "icon1.xpm"\r
+#include "icon2.xpm"\r
+#include "icon3.xpm"\r
+#include "icon4.xpm"\r
+#include "icon5.xpm"\r
+\r
+#include "wx/filedlg.h"\r
+#include "wx/toolbar.h"\r
+#include <wx/filename.h>\r
+#include <wx/busyinfo.h>\r
+#include <wx/cmdline.h>\r
+#include <wx/file.h>\r
+#include "wx/notebook.h"\r
+\r
+#include "libopenjpeg\openjpeg.h"\r
+\r
+#include "imagj2k.h"\r
+#include "imagjp2.h"\r
+#include "imagmj2.h"\r
+\r
+#define USE_GENERIC_TREECTRL 0\r
+\r
+#if USE_GENERIC_TREECTRL\r
+#include "wx/generic/treectlg.h"\r
+#ifndef wxTreeCtrl\r
+#define wxTreeCtrl wxGenericTreeCtrl\r
+#define sm_classwxTreeCtrl sm_classwxGenericTreeCtrl\r
+#endif\r
+#endif\r
+\r
+#define OPJ_APPLICATION_NAME           wxT("OpenJPEG Viewer")\r
+#define OPJ_APPLICATION_VERSION                wxT("0.1 alpha")\r
+#define OPJ_APPLICATION_TITLEBAR       OPJ_APPLICATION_NAME wxT(" ") OPJ_APPLICATION_VERSION\r
+#define OPJ_APPLICATION_COPYRIGHT      wxT("(C) 2007, Giuseppe Baruffa")\r
+\r
+#define OPJ_CANVAS_BORDER 10\r
+#define OPJ_CANVAS_COLOUR *wxWHITE\r
+\r
+class OPJDecoThread;\r
+class OPJParseThread;\r
+WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);\r
+class OPJChildFrame;\r
+\r
+//////////////////////////////////\r
+// this is our main application //\r
+//////////////////////////////////\r
+class OPJViewerApp: public wxApp\r
+{\r
+       // public methods and variables\r
+       public:\r
+\r
+               // class constructor\r
+               OPJViewerApp() { m_showImages = true; m_showButtons = false; }\r
+\r
+               // other methods\r
+               bool OnInit(void);\r
+               void SetShowImages(bool show) { m_showImages = show; }\r
+               bool ShowImages() const { return m_showImages; }\r
+               void ShowCmdLine(const wxCmdLineParser& parser);\r
+\r
+               // all the threads currently alive - as soon as the thread terminates, it's\r
+               // removed from the array\r
+               wxArrayThread m_deco_threads, m_parse_threads;\r
+\r
+               // crit section protects access to all of the arrays below\r
+               wxCriticalSection m_deco_critsect, m_parse_critsect;\r
+\r
+               // semaphore used to wait for the threads to exit, see OPJFrame::OnQuit()\r
+               wxSemaphore m_deco_semAllDone, m_parse_semAllDone;\r
+\r
+               // the last exiting thread should post to m_semAllDone if this is true\r
+               // (protected by the same m_critsect)\r
+               bool m_deco_waitingUntilAllDone, m_parse_waitingUntilAllDone;\r
+\r
+               // the list of all filenames written in the command line\r
+               wxArrayString m_filelist;\r
+\r
+       // private methods and variables\r
+       private:\r
+               bool m_showImages, m_showButtons;\r
+\r
+};\r
+\r
+DECLARE_APP(OPJViewerApp)\r
+\r
+///////////////////////////////////////////\r
+// this canvas is used to draw the image //\r
+///////////////////////////////////////////\r
+class OPJCanvas: public wxScrolledWindow\r
+{\r
+       // public methods and variables\r
+       public:\r
+\r
+               // class constructor\r
+               OPJCanvas(wxFileName fname, wxWindow *parent, const wxPoint& pos, const wxSize& size);\r
+\r
+               virtual void OnDraw(wxDC& dc);\r
+               void OnEvent(wxMouseEvent& event);\r
+               void WriteText(const wxString& text) { wxMutexGuiEnter(); wxLogMessage(text); wxMutexGuiLeave();}\r
+               OPJDecoThread *CreateDecoThread(void);\r
+\r
+               wxBitmap  m_image;\r
+               wxFileName m_fname;\r
+\r
+       DECLARE_EVENT_TABLE()\r
+};\r
+\r
+///////////////////////////////////////////////////\r
+// the data associated to each tree leaf or node //\r
+///////////////////////////////////////////////////\r
+class OPJMarkerData : public wxTreeItemData\r
+{\r
+       // public methods and variables\r
+       public:\r
+\r
+               // class constructor\r
+               OPJMarkerData(const wxString& desc, const wxString& fname = wxT(""), wxFileOffset start = 0, wxFileOffset length = 0) : m_desc(desc), m_filestring(fname) { m_start = start; m_length = length; }\r
+\r
+               void ShowInfo(wxTreeCtrl *tree);\r
+               const wxChar *GetDesc1() const { return m_desc.c_str(); }\r
+               const wxChar *GetDesc2() const { return m_filestring.c_str(); }\r
+               wxFileOffset m_start, m_length;\r
+\r
+       // private methods and variables\r
+       private:\r
+               wxString m_desc;\r
+               wxString m_filestring;\r
+};\r
+\r
+\r
+class OPJMarkerTree : public wxTreeCtrl\r
+{\r
+public:\r
+    enum\r
+    {\r
+        TreeCtrlIcon_File,\r
+        TreeCtrlIcon_FileSelected,\r
+        TreeCtrlIcon_Folder,\r
+        TreeCtrlIcon_FolderSelected,\r
+        TreeCtrlIcon_FolderOpened\r
+    };\r
+\r
+    OPJMarkerTree() { };\r
+    OPJMarkerTree(wxWindow *parent, wxFileName fname, wxString name, const wxWindowID id,\r
+               const wxPoint& pos, const wxSize& size,\r
+               long style);\r
+    virtual ~OPJMarkerTree(){};\r
+       OPJParseThread *CreateParseThread(wxTreeItemId parentid = 0x00);\r
+    void WriteText(const wxString& text) { wxMutexGuiEnter(); wxLogMessage(text); wxMutexGuiLeave(); }\r
+\r
+       wxFileName m_fname;\r
+       wxTextCtrl *m_peektextCtrl;\r
+\r
+    /*void OnBeginDrag(wxTreeEvent& event);\r
+    void OnBeginRDrag(wxTreeEvent& event);\r
+    void OnEndDrag(wxTreeEvent& event);*/\r
+    /*void OnBeginLabelEdit(wxTreeEvent& event);\r
+    void OnEndLabelEdit(wxTreeEvent& event);*/\r
+    /*void OnDeleteItem(wxTreeEvent& event);*/\r
+    /*void OnContextMenu(wxContextMenuEvent& event);*/\r
+    /*void OnItemMenu(wxTreeEvent& event);*/\r
+    /*void OnGetInfo(wxTreeEvent& event);\r
+    void OnSetInfo(wxTreeEvent& event);*/\r
+    /*void OnItemExpanded(wxTreeEvent& event);*/\r
+    void OnItemExpanding(wxTreeEvent& event);\r
+    /*void OnItemCollapsed(wxTreeEvent& event);\r
+    void OnItemCollapsing(wxTreeEvent& event);*/\r
+    void OnSelChanged(wxTreeEvent& event);\r
+    /*void OnSelChanging(wxTreeEvent& event);*/\r
+    /*void OnTreeKeyDown(wxTreeEvent& event);*/\r
+    /*void OnItemActivated(wxTreeEvent& event);*/\r
+    /*void OnItemRClick(wxTreeEvent& event);*/\r
+    /*void OnRMouseDown(wxMouseEvent& event);\r
+    void OnRMouseUp(wxMouseEvent& event);\r
+    void OnRMouseDClick(wxMouseEvent& event);*/\r
+    /*void GetItemsRecursively(const wxTreeItemId& idParent,\r
+                             wxTreeItemIdValue cookie = 0);*/\r
+\r
+    void CreateImageList(int size = 16);\r
+    void CreateButtonsImageList(int size = 11);\r
+\r
+    /*void AddTestItemsToTree(size_t numChildren, size_t depth);*/\r
+    /*void DoSortChildren(const wxTreeItemId& item, bool reverse = false)\r
+        { m_reverseSort = reverse; wxTreeCtrl::SortChildren(item); }*/\r
+    /*void DoEnsureVisible() { if (m_lastItem.IsOk()) EnsureVisible(m_lastItem); }*/\r
+    /*void DoToggleIcon(const wxTreeItemId& item);*/\r
+    /*void ShowMenu(wxTreeItemId id, const wxPoint& pt);*/\r
+\r
+    int ImageSize(void) const { return m_imageSize; }\r
+\r
+    void SetLastItem(wxTreeItemId id) { m_lastItem = id; }\r
+\r
+protected:\r
+    /*virtual int OnCompareItems(const wxTreeItemId& i1, const wxTreeItemId& i2);*/\r
+\r
+    // is this the test item which we use in several event handlers?\r
+    /*bool IsTestItem(const wxTreeItemId& item)\r
+    {\r
+        // the test item is the first child folder\r
+        return GetItemParent(item) == GetRootItem() && !GetPrevSibling(item);\r
+    }*/\r
+\r
+private:\r
+    /*void AddItemsRecursively(const wxTreeItemId& idParent,\r
+                             size_t nChildren,\r
+                             size_t depth,\r
+                             size_t folder);*/\r
+\r
+    void LogEvent(const wxChar *name, const wxTreeEvent& event);\r
+\r
+    int          m_imageSize;               // current size of images\r
+    bool         m_reverseSort;             // flag for OnCompareItems\r
+    wxTreeItemId m_lastItem,                // for OnEnsureVisible()\r
+                 m_draggedItem;             // item being dragged right now\r
+\r
+    // NB: due to an ugly wxMSW hack you _must_ use DECLARE_DYNAMIC_CLASS()\r
+    //     if you want your overloaded OnCompareItems() to be called.\r
+    //     OTOH, if you don't want it you may omit the next line - this will\r
+    //     make default (alphabetical) sorting much faster under wxMSW.\r
+    DECLARE_DYNAMIC_CLASS(OPJMarkerTree)\r
+    DECLARE_EVENT_TABLE()\r
+};\r
+\r
+// this hash map stores all the trees of currently opened images, with an integer key\r
+WX_DECLARE_HASH_MAP(int, OPJMarkerTree*, wxIntegerHash, wxIntegerEqual, OPJMarkerTreeHash);\r
+\r
+// this hash map stores all the children of currently opened images, with an integer key\r
+WX_DECLARE_HASH_MAP(int, OPJChildFrame*, wxIntegerHash, wxIntegerEqual, OPJChildFrameHash);\r
+\r
+// Define a new frame\r
+class OPJFrame: public wxMDIParentFrame\r
+{\r
+  public:\r
+\r
+    OPJFrame(wxWindow *parent, const wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);\r
+\r
+    ~OPJFrame(void);\r
+    void OnSize(wxSizeEvent& event);\r
+    void OnAbout(wxCommandEvent& WXUNUSED(event));\r
+    void OnFileOpen(wxCommandEvent& WXUNUSED(event));\r
+    void OnQuit(wxCommandEvent& WXUNUSED(event));\r
+       void OnToggleWindow(wxCommandEvent& WXUNUSED(event));\r
+       void OnSashDrag(wxSashEvent& event);\r
+       void OpenFiles(wxArrayString paths, wxArrayString filenames);\r
+       void OnNotebook(wxNotebookEvent& event);\r
+\r
+       OPJMarkerTreeHash m_treehash;\r
+       OPJChildFrameHash m_childhash;\r
+    wxSashLayoutWindow* markerTreeWindow;\r
+    wxSashLayoutWindow* loggingWindow;\r
+    void Resize(int number);\r
+       wxNotebook *m_bookCtrl;\r
+       wxNotebook *m_bookCtrlbottom;\r
+    wxTextCtrl *m_textCtrlbrowse;\r
+\r
+  private:\r
+    void TogStyle(int id, long flag);\r
+\r
+    void DoSort(bool reverse = false);\r
+\r
+    wxPanel *m_panel;\r
+    wxTextCtrl *m_textCtrl;\r
+\r
+    void DoSetBold(bool bold = true);\r
+\r
+protected:\r
+    wxSashLayoutWindow* m_topWindow;\r
+    wxSashLayoutWindow* m_leftWindow2;\r
+\r
+DECLARE_EVENT_TABLE()\r
+};\r
+\r
+class OPJChildFrame: public wxMDIChildFrame\r
+{\r
+  public:\r
+    OPJCanvas *m_canvas;\r
+    OPJChildFrame(OPJFrame *parent, wxFileName fname, int winnumber, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);\r
+    ~OPJChildFrame(void);\r
+    void OnActivate(wxActivateEvent& event);\r
+       /*void OnQuit(wxCommandEvent& WXUNUSED(event));*/\r
+       void OnClose(wxCloseEvent& event);\r
+       void OnGotFocus(wxFocusEvent& event);\r
+       /*void OnLostFocus(wxFocusEvent& event);*/\r
+    OPJFrame *m_frame;\r
+       wxFileName m_fname;\r
+       int m_winnumber;\r
+\r
+DECLARE_EVENT_TABLE()\r
+};\r
+\r
+#define SASHTEST_QUIT        wxID_EXIT\r
+#define SASHTEST_NEW_WINDOW  2\r
+#define SASHTEST_REFRESH     3\r
+#define SASHTEST_CHILD_QUIT  4\r
+#define SASHTEST_ABOUT       wxID_ABOUT\r
+#define SASHTEST_TOGGLE_WINDOW 6\r
+\r
+#define ID_WINDOW_TOP       100\r
+#define ID_WINDOW_LEFT1     101\r
+#define ID_WINDOW_LEFT2     102\r
+#define ID_WINDOW_BOTTOM    103\r
+\r
+// menu and control ids\r
+enum\r
+{\r
+    TreeTest_Quit = wxID_EXIT,\r
+    TreeTest_About = wxID_ABOUT,\r
+    TreeTest_TogButtons = wxID_HIGHEST,\r
+    TreeTest_TogTwist,\r
+    TreeTest_TogLines,\r
+    TreeTest_TogEdit,\r
+    TreeTest_TogHideRoot,\r
+    TreeTest_TogRootLines,\r
+    TreeTest_TogBorder,\r
+    TreeTest_TogFullHighlight,\r
+    TreeTest_SetFgColour,\r
+    TreeTest_SetBgColour,\r
+    TreeTest_ResetStyle,\r
+    TreeTest_Highlight,\r
+    TreeTest_Dump,\r
+    TreeTest_DumpSelected,\r
+    TreeTest_Count,\r
+    TreeTest_CountRec,\r
+    TreeTest_Sort,\r
+    TreeTest_SortRev,\r
+    TreeTest_SetBold,\r
+    TreeTest_ClearBold,\r
+    TreeTest_Rename,\r
+    TreeTest_Delete,\r
+    TreeTest_DeleteChildren,\r
+    TreeTest_DeleteAll,\r
+    TreeTest_Recreate,\r
+    TreeTest_ToggleImages,\r
+    TreeTest_ToggleButtons,\r
+    TreeTest_SetImageSize,\r
+    TreeTest_ToggleSel,\r
+    TreeTest_CollapseAndReset,\r
+    TreeTest_EnsureVisible,\r
+    TreeTest_AddItem,\r
+    TreeTest_InsertItem,\r
+    TreeTest_IncIndent,\r
+    TreeTest_DecIndent,\r
+    TreeTest_IncSpacing,\r
+    TreeTest_DecSpacing,\r
+    TreeTest_ToggleIcon,\r
+    TreeTest_Select,\r
+    TreeTest_Unselect,\r
+    TreeTest_SelectRoot,\r
+    TreeTest_Ctrl = 1000,\r
+       BOTTOM_NOTEBOOK_ID,\r
+       LEFT_NOTEBOOK_ID\r
+};\r
+\r
+class OPJDecoThread : public wxThread\r
+{\r
+public:\r
+    OPJDecoThread(OPJCanvas *canvas);\r
+\r
+    // thread execution starts here\r
+    virtual void *Entry();\r
+\r
+    // called when the thread exits - whether it terminates normally or is\r
+    // stopped with Delete() (but not when it is Kill()ed!)\r
+    virtual void OnExit();\r
+\r
+    // write something to the text control\r
+    void WriteText(const wxString& text);\r
+\r
+public:\r
+    unsigned m_count;\r
+    OPJCanvas *m_canvas;\r
+};\r
+\r
+class OPJParseThread : public wxThread\r
+{\r
+public:\r
+    OPJParseThread(OPJMarkerTree *tree, wxTreeItemId parentid = 0x00);\r
+\r
+    // thread execution starts here\r
+    virtual void *Entry();\r
+\r
+    // called when the thread exits - whether it terminates normally or is\r
+    // stopped with Delete() (but not when it is Kill()ed!)\r
+    virtual void OnExit();\r
+\r
+    // write something to the text control\r
+    void WriteText(const wxString& text);\r
+       void LoadFile(wxFileName fname);\r
+       void ParseJ2KFile(wxFile *m_file, wxFileOffset offset, wxFileOffset length, wxTreeItemId parentid);\r
+       void ParseJP2File(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit, wxTreeItemId parentid);\r
+\r
+    unsigned m_count;\r
+    OPJMarkerTree *m_tree;\r
+       wxTreeItemId m_parentid;\r
+\r
+private:\r
+       int jpeg2000parse(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit,\r
+                       wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint);\r
+       int box_handler_function(int boxtype, wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit,\r
+                       wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint);\r
+\r
+};\r
+\r
+#endif //__OPJ_VIEWER_H__\r
diff --git a/OPJViewer/source/OPJViewer.ico b/OPJViewer/source/OPJViewer.ico
new file mode 100644 (file)
index 0000000..931d5e0
Binary files /dev/null and b/OPJViewer/source/OPJViewer.ico differ
diff --git a/OPJViewer/source/OPJViewer.rc b/OPJViewer/source/OPJViewer.rc
new file mode 100644 (file)
index 0000000..56e5b69
--- /dev/null
@@ -0,0 +1,2 @@
+OPJViewer16 ICON OPJViewer.ico\r
+#include "wx/msw/wx.rc"
\ No newline at end of file
diff --git a/OPJViewer/source/OPJViewer16.xpm b/OPJViewer/source/OPJViewer16.xpm
new file mode 100644 (file)
index 0000000..27e522b
--- /dev/null
@@ -0,0 +1,26 @@
+/* XPM */\r
+static char *OPJViewer16[] = {\r
+/* columns rows colors chars-per-pixel */\r
+"16 16 4 1",\r
+"  c black",\r
+". c #800000",\r
+"X c red",\r
+"o c None",\r
+/* pixels */\r
+"oooooooooooooooo",\r
+"ooo.XXXXoooooooo",\r
+"ooXXoo .Xooooooo",\r
+"o..oooo .ooooooo",\r
+"oX.oooo  ooooooo",\r
+"oX.oooo .ooooooo",\r
+"oXXoooo .ooooooo",\r
+"o.XXoo .oooooooo",\r
+"oo.XXXXooooooooo",\r
+"ooooooooo.Xo .oo",\r
+"ooooooooo X. ooo",\r
+"oooooooooo...ooo",\r
+"oooooooooo XXooo",\r
+"oooooooooo .Xooo",\r
+"oooooooooooooooo",\r
+"oooooooooooooooo"\r
+};\r
diff --git a/OPJViewer/source/icon1.xpm b/OPJViewer/source/icon1.xpm
new file mode 100644 (file)
index 0000000..fbc605b
--- /dev/null
@@ -0,0 +1,79 @@
+/* XPM */
+static char *icon1_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 41 1",
+"> c #97C4E7",
+"# c #4381AA",
+"d c #FFFFFF",
+"< c #71B2DE",
+"+ c #538BB1",
+"& c #D1E5F5",
+"q c #63B3DE",
+"6 c #F1F4F7",
+"* c #CAE1F3",
+"y c #7AC4E5",
+"= c #C3DDF1",
+"X c #74A1BD",
+"- c #BCD9EF",
+"5 c #619BC4",
+"3 c #E6EAF1",
+"2 c #4B8EBF",
+"o c #6B97B6",
+". c #4B82A8",
+"  c None",
+"w c #54A6D8",
+"1 c #71A8D1",
+", c #85BBE2",
+"t c #EFF6FC",
+"7 c #DEEDF8",
+"@ c #4388B4",
+"a c #F7FBFD",
+"$ c #D7E0E9",
+"r c #FAFCFE",
+"4 c #DAEAF7",
+"e c #E9F3FA",
+"0 c #76BAE2",
+"% c #7FA6C0",
+"s c #FDFDFE",
+"O c #5896BE",
+"p c #B6D5EE",
+"8 c #87ABC3",
+": c #A5CCEA",
+"9 c #E5F0F9",
+"; c #AFD1EC",
+"i c #F4F9FD",
+"u c #8FB0C3",
+/* pixels */
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"        .XXXooOO++@#$           ",
+"        %&*=-;:>>,<123          ",
+"        %4&*=-;:>>,1>56         ",
+"        %74&*=-;:>>1*>56        ",
+"        89700qqqqwq1e*>X        ",
+"        8e974&*=-;:1re*>8       ",
+"        8te974&*=-;11111#       ",
+"        8tty000qqqqqww>,+       ",
+"        uitte974&*=-p:>>+       ",
+"        uaitte974&*=-p:>O       ",
+"        uaayyyy000qqqqp:O       ",
+"        uraaitte974&*=-po       ",
+"        urraaitte974&*=-o       ",
+"        usryyyyyyy000q*=X       ",
+"        ussrraaitte974&*X       ",
+"        udssrraaitte974&X       ",
+"        uddyyyyyyyyyy074%       ",
+"        udddssrraaitte97%       ",
+"        uddddssrraaitte9%       ",
+"        udddddssrraaitte8       ",
+"        uddddddssrraaitt8       ",
+"        uuuuuuuuuuuuuu88u       ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "
+};
diff --git a/OPJViewer/source/icon2.xpm b/OPJViewer/source/icon2.xpm
new file mode 100644 (file)
index 0000000..7ae8c92
--- /dev/null
@@ -0,0 +1,53 @@
+/* XPM */
+static char *icon2_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 15 1",
+". c Black",
+"O c #97C4E7",
+"$ c #63B3DE",
+"@ c #CAE1F3",
+"; c #7AC4E5",
+"* c #74A1BD",
+"+ c #619BC4",
+"o c #4B8EBF",
+"  c None",
+"% c #54A6D8",
+"= c #FAFCFE",
+"& c #E9F3FA",
+"# c #76BAE2",
+"X c #C00000",
+"- c #87ABC3",
+/* pixels */
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"        .............           ",
+"        .XXXXXXXXXX.o.          ",
+"        .XXXXXXXXXX.O+.         ",
+"        .XXXXXXXXXX.@O+.        ",
+"        .XX##$$$$%$.&@O*        ",
+"        .XXXXXXXXXX.=&@O-       ",
+"        .XXXXXXXXXX......       ",
+"        .XX;###$$$$$%%XX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XX;;;;###$$$$XX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XX;;;;;;;###$XX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XX;;;;;;;;;;#XX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .XXXXXXXXXXXXXXX.       ",
+"        .................       ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "
+};
diff --git a/OPJViewer/source/icon3.xpm b/OPJViewer/source/icon3.xpm
new file mode 100644 (file)
index 0000000..722de6b
--- /dev/null
@@ -0,0 +1,79 @@
+/* XPM */
+static char *icon3_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 41 1",
+"6 c #EDF2FB",
+"- c #AAC1E8",
+": c #B9CDED",
+"X c #295193",
+", c #C6D6F0",
+"a c #4A7CCE",
+"u c #779DDB",
+"y c #7FA2DD",
+"$ c #3263B4",
+"5 c #EAF0FA",
+". c #2D59A3",
+"o c #6E96D8",
+"* c #356AC1",
+"r c #F7F9FD",
+"> c #BED0EE",
+"3 c #E1E9F7",
+"7 c #F0F5FC",
+"< c #CBD9F1",
+"2 c #DAE5F6",
+"# c #3161B1",
+"  c None",
+"0 c #FDFEFF",
+"= c #9FB9E5",
+"e c #AEC5EA",
+"t c #89A9DF",
+"q c #98B5E4",
+"p c #5584D1",
+"d c #3A70CA",
+"@ c #305FAC",
+"i c #5D89D3",
+"1 c #D2DFF4",
+"% c #3366B9",
+"9 c #FAFCFE",
+"8 c #F5F8FD",
+"s c #4075CC",
+"O c #638ED5",
+"w c #90AFE2",
+"& c #3467BC",
+"+ c #2F5DA9",
+"; c #B3C8EB",
+"4 c #E5EDF9",
+/* pixels */
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"      ......X                   ",
+"      .oooooO+                  ",
+"      .ooooooo.                 ",
+"      .+@@@##$%%&&&&&****.      ",
+"      .=-;:>,<12345678900.      ",
+"      .q=-;:>,<1234567890.      ",
+"      .wq=-e:>,<12345678r.      ",
+"      .twq=-e:>,<12345678.      ",
+"      .ytwq=-e:>,<1234567.      ",
+"      .uytwq=-e:>,<123456.      ",
+"      .ouytwq=-e:>,<12345.      ",
+"      .Oouytwq=-e;>,<1234.      ",
+"      .iOouytwq=-e;>,<123.      ",
+"      .piOouytwq=-e;>,<12.      ",
+"      .apiOouytwq=-e;>,<1.      ",
+"      .sapiOouytwq=-e;>,<.      ",
+"      .dsapiOouytwq=-e;>,.      ",
+"      ...................#      ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "
+};
diff --git a/OPJViewer/source/icon4.xpm b/OPJViewer/source/icon4.xpm
new file mode 100644 (file)
index 0000000..a18e1a7
--- /dev/null
@@ -0,0 +1,43 @@
+/* XPM */
+static char *icon4_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 5 1",
+". c Black",
+"o c #8399B4",
+"X c #8DA0B9",
+"  c None",
+"O c #800000",
+/* pixels */
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"      .......                   ",
+"      .XXXXXo.                  ",
+"      .XXXXXXX.                 ",
+"      ....................      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      .OOOOOOOOOOOOOOOOOO.      ",
+"      ....................      ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "
+};
diff --git a/OPJViewer/source/icon5.xpm b/OPJViewer/source/icon5.xpm
new file mode 100644 (file)
index 0000000..9f63c31
--- /dev/null
@@ -0,0 +1,79 @@
+/* XPM */
+static char *icon5_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 41 1",
+"0 c #AAC1E8",
+"q c #B9CDED",
+"X c #295193",
+"e c #C6D6F0",
+"a c #4A7CCE",
+"& c #779DDB",
+"* c #7FA2DD",
+"2 c #EAF0FA",
+"@ c #2D59A3",
+"o c #6E96D8",
+"y c #356AC1",
+"d c #214279",
+"w c #BED0EE",
+"= c #85A7DF",
+"< c #E1E9F7",
+"3 c #F0F5FC",
+"s c #CBD9F1",
+", c #DAE5F6",
+"7 c #3161B1",
+"  c None",
+". c #274D8B",
+"6 c #FDFEFF",
+"i c #E7EEF9",
+"9 c #9FB9E5",
+"- c #89A9DF",
+"8 c #98B5E4",
+"$ c #5584D1",
+"+ c #3569BF",
+"% c #305FAC",
+"O c #5D89D3",
+"> c #D2DFF4",
+"p c #3366B9",
+"5 c #FAFCFE",
+"4 c #F5F8FD",
+"t c #4075CC",
+"u c #638ED5",
+"r c #CEDCF2",
+"; c #90AFE2",
+"# c #2F5DA9",
+": c #B3C8EB",
+"1 c #E5EDF9",
+/* pixels */
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"     ......X                    ",
+"     XoooooO.                   ",
+"     Xoooooo+.                  ",
+"     Xooooooo@XXXXXXXXXX#       ",
+"     Xoooooooooooooooooo#       ",
+"     Xoooooooooooooooooo#       ",
+"     Xoo$###################    ",
+"     Xoo%O&*=-;:>,<123445667    ",
+"     XooX890:qwer>,<123445q#    ",
+"     Xoty;890:qwer>,<12344#     ",
+"     Xo%u-;890:qwer>,<i234#     ",
+"     XoX&*-;890:qwer>,<i2r#     ",
+"     Xtpo&*-;890:qwer>,<i#      ",
+"     X%auo&*-;890:qwer>,<#      ",
+"     XX$Ouo&*-;890:qwer>s#      ",
+"     d%a$Ouo&*-;890:qwer#       ",
+"     d+ta$Ouo&*-;890:qwe#       ",
+"     d..................#       ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                ",
+"                                "
+};
diff --git a/OPJViewer/source/imagj2k.cpp b/OPJViewer/source/imagj2k.cpp
new file mode 100644 (file)
index 0000000..b58c7a5
--- /dev/null
@@ -0,0 +1,312 @@
+/*\r
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        imagj2k.cpp\r
+// Purpose:     wxImage JPEG 2000 codestream handler\r
+// Author:      Giuseppe Baruffa - based on imagjpeg.cpp, Vaclav Slavik\r
+// RCS-ID:      $Id: imagj2k.cpp,v 0.00 2007/02/08 23:59:00 MW Exp $\r
+// Copyright:   (c) Giuseppe Baruffa\r
+// Licence:     wxWindows licence\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+// For compilers that support precompilation, includes "wx.h".\r
+#include "wx/wxprec.h"\r
+\r
+#ifdef __BORLANDC__\r
+    #pragma hdrstop\r
+#endif\r
+\r
+#if wxUSE_IMAGE && wxUSE_LIBOPENJPEG\r
+\r
+#include "imagj2k.h"\r
+\r
+#ifndef WX_PRECOMP\r
+    #include "wx/log.h"\r
+    #include "wx/app.h"\r
+    #include "wx/intl.h"\r
+    #include "wx/bitmap.h"\r
+    #include "wx/module.h"\r
+#endif\r
+\r
+\r
+#include "libopenjpeg/openjpeg.h"\r
+\r
+\r
+#include "wx/filefn.h"\r
+#include "wx/wfstream.h"\r
+\r
+// ----------------------------------------------------------------------------\r
+// types\r
+// ----------------------------------------------------------------------------\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// wxJ2KHandler\r
+//-----------------------------------------------------------------------------\r
+\r
+IMPLEMENT_DYNAMIC_CLASS(wxJ2KHandler,wxImageHandler)\r
+\r
+#if wxUSE_STREAMS\r
+\r
+//------------- JPEG 2000 Data Source Manager\r
+\r
+#define J2K_CFMT 0\r
+#define JP2_CFMT 1\r
+#define JPT_CFMT 2\r
+#define MJ2_CFMT 3\r
+#define PXM_DFMT 0\r
+#define PGX_DFMT 1\r
+#define BMP_DFMT 2\r
+#define YUV_DFMT 3\r
+\r
+#define MAX_MESSAGE_LEN 200\r
+\r
+/* sample error callback expecting a FILE* client object */\r
+void j2k_error_callback(const char *msg, void *client_data) {\r
+       char m_msg[MAX_MESSAGE_LEN];\r
+       int message_len = strlen(msg) - 1;\r
+       if (msg[message_len] != '\n')\r
+               message_len = MAX_MESSAGE_LEN;\r
+       sprintf(m_msg, "[ERROR] %.*s", message_len, msg);\r
+    wxMutexGuiEnter();\r
+       wxLogMessage(m_msg);\r
+    wxMutexGuiLeave();\r
+}\r
+/* sample warning callback expecting a FILE* client object */\r
+void j2k_warning_callback(const char *msg, void *client_data) {\r
+       char m_msg[MAX_MESSAGE_LEN];\r
+       int message_len = strlen(msg) - 1;\r
+       if (msg[message_len] != '\n')\r
+               message_len = MAX_MESSAGE_LEN;\r
+       sprintf(m_msg, "[WARNING] %.*s", message_len, msg);\r
+    wxMutexGuiEnter();\r
+       wxLogMessage(m_msg);\r
+    wxMutexGuiLeave();\r
+}\r
+/* sample debug callback expecting no client object */\r
+void j2k_info_callback(const char *msg, void *client_data) {\r
+       char m_msg[MAX_MESSAGE_LEN];\r
+       int message_len = strlen(msg) - 1;\r
+       if (msg[message_len] != '\n')\r
+               message_len = MAX_MESSAGE_LEN;\r
+       sprintf(m_msg, "[INFO] %.*s", message_len, msg);\r
+    wxMutexGuiEnter();\r
+       wxLogMessage(m_msg);\r
+    wxMutexGuiLeave();\r
+}\r
+\r
+// load the j2k codestream\r
+bool wxJ2KHandler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index)\r
+{\r
+       opj_dparameters_t parameters;   /* decompression parameters */\r
+       opj_event_mgr_t event_mgr;              /* event manager */\r
+       opj_image_t *opjimage = NULL;\r
+       FILE *fsrc = NULL;\r
+       unsigned char *src = NULL;\r
+    unsigned char *ptr;\r
+       int file_length;\r
+       int shiftbpp;\r
+\r
+       // destroy the image\r
+    image->Destroy();\r
+\r
+       /* handle to a decompressor */\r
+       opj_dinfo_t* dinfo = NULL;      \r
+       opj_cio_t *cio = NULL;\r
+\r
+       /* configure the event callbacks (not required) */\r
+       memset(&event_mgr, 0, sizeof(opj_event_mgr_t));\r
+       event_mgr.error_handler = j2k_error_callback;\r
+       event_mgr.warning_handler = j2k_warning_callback;\r
+       event_mgr.info_handler = j2k_info_callback;\r
+\r
+       /* set decoding parameters to default values */\r
+       opj_set_default_decoder_parameters(&parameters);\r
+\r
+       /* prepare parameters */\r
+       parameters.decod_format = J2K_CFMT;\r
+       parameters.cod_format = BMP_DFMT;\r
+\r
+       /* JPWL only */\r
+#ifdef USE_JPWL\r
+       parameters.jpwl_exp_comps = 3;\r
+       parameters.jpwl_max_tiles = 100;\r
+       parameters.jpwl_correct = true;\r
+#endif /* USE_JPWL */\r
+\r
+       /* get a decoder handle */\r
+       dinfo = opj_create_decompress(CODEC_J2K);\r
+\r
+       /* find length of the stream */\r
+       stream.SeekI(0, wxFromEnd);\r
+       file_length = (int) stream.TellI();\r
+\r
+       /* get data */\r
+       stream.SeekI(0, wxFromStart);\r
+    src = (unsigned char *) malloc(file_length);\r
+       stream.Read(src, file_length);\r
+\r
+       /* catch events using our callbacks and give a local context */\r
+       opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);\r
+\r
+       /* setup the decoder decoding parameters using user parameters */\r
+       opj_setup_decoder(dinfo, &parameters);\r
+\r
+       /* open a byte stream */\r
+       cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);\r
+\r
+       /* decode the stream and fill the image structure */\r
+       opjimage = opj_decode(dinfo, cio);\r
+       if (!opjimage) {\r
+               wxMutexGuiEnter();\r
+               wxLogError("J2K: failed to decode image!");\r
+               wxMutexGuiLeave();\r
+               opj_destroy_decompress(dinfo);\r
+               opj_cio_close(cio);\r
+               opj_image_destroy(opjimage);\r
+               free(src);\r
+               return false;\r
+       }\r
+\r
+       // check image components\r
+       if ((opjimage->numcomps != 1) && (opjimage->numcomps != 3)) {\r
+               wxMutexGuiEnter();\r
+               wxLogError("J2K: weird number of components");\r
+               wxMutexGuiLeave();\r
+               opj_destroy_decompress(dinfo);\r
+               opj_cio_close(cio);\r
+               free(src);\r
+               return false;\r
+       }\r
+\r
+       // check image depth (only on the first one, for now)\r
+       shiftbpp = opjimage->comps[0].prec - 8;\r
+\r
+       // prepare image size\r
+    image->Create(opjimage->comps[0].w, opjimage->comps[0].h, true );\r
+\r
+       // access image raw data\r
+    image->SetMask( false );\r
+    ptr = image->GetData();\r
+\r
+       // RGB color picture\r
+       if (opjimage->numcomps == 3) {\r
+               int row, col;\r
+               int *r = opjimage->comps[0].data;\r
+               int *g = opjimage->comps[1].data;\r
+               int *b = opjimage->comps[2].data;\r
+               if (shiftbpp > 0) {\r
+                       for (row = 0; row < opjimage->comps[0].h; row++) {\r
+                               for (col = 0; col < opjimage->comps[0].w; col++) {\r
+                                       \r
+                                       *(ptr++) = (*(r++)) >> shiftbpp;\r
+                                       *(ptr++) = (*(g++)) >> shiftbpp;\r
+                                       *(ptr++) = (*(b++)) >> shiftbpp;\r
+\r
+                               }\r
+                       }\r
+               } else {\r
+                       for (row = 0; row < opjimage->comps[0].h; row++) {\r
+                               for (col = 0; col < opjimage->comps[0].w; col++) {\r
+                                       \r
+                                       *(ptr++) = *(r++);\r
+                                       *(ptr++) = *(g++);\r
+                                       *(ptr++) = *(b++);\r
+\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       // B/W picture\r
+       if (opjimage->numcomps == 1) {\r
+               int row, col;\r
+               int *y = opjimage->comps[0].data;\r
+               if (shiftbpp > 0) {\r
+                       for (row = 0; row < opjimage->comps[0].h; row++) {\r
+                               for (col = 0; col < opjimage->comps[0].w; col++) {\r
+                                       \r
+                                       *(ptr++) = (*(y)) >> shiftbpp;\r
+                                       *(ptr++) = (*(y)) >> shiftbpp;\r
+                                       *(ptr++) = (*(y++)) >> shiftbpp;\r
+\r
+                               }\r
+                       }\r
+               } else {\r
+                       for (row = 0; row < opjimage->comps[0].h; row++) {\r
+                               for (col = 0; col < opjimage->comps[0].w; col++) {\r
+                                       \r
+                                       *(ptr++) = *(y);\r
+                                       *(ptr++) = *(y);\r
+                                       *(ptr++) = *(y++);\r
+\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+    wxMutexGuiEnter();\r
+    wxLogMessage(wxT("J2K: image loaded."));\r
+    wxMutexGuiLeave();\r
+\r
+       /* close openjpeg structs */\r
+       opj_destroy_decompress(dinfo);\r
+       opj_cio_close(cio);\r
+       opj_image_destroy(opjimage);\r
+       free(src);\r
+\r
+       if (!image->Ok())\r
+               return false;\r
+       else\r
+               return true;\r
+\r
+}\r
+\r
+// save the j2k codestream\r
+bool wxJ2KHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )\r
+{\r
+    wxLogError(wxT("J2K: Couldn't save image -> not implemented."));\r
+    return false;\r
+}\r
+\r
+#ifdef __VISUALC__\r
+    #pragma warning(default:4611)\r
+#endif /* VC++ */\r
+\r
+// recognize the 0xFF4F JPEG 2000 SOC marker\r
+bool wxJ2KHandler::DoCanRead( wxInputStream& stream )\r
+{\r
+    unsigned char hdr[2];\r
+\r
+    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )\r
+        return false;\r
+\r
+    return hdr[0] == 0xFF && hdr[1] == 0x4F;\r
+}\r
+\r
+#endif   // wxUSE_STREAMS\r
+\r
+#endif   // wxUSE_LIBOPENJPEG\r
diff --git a/OPJViewer/source/imagj2k.h b/OPJViewer/source/imagj2k.h
new file mode 100644 (file)
index 0000000..c98fdd2
--- /dev/null
@@ -0,0 +1,75 @@
+/*\r
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        imagj2k.h\r
+// Purpose:     wxImage JPEG 2000 raw codestream handler\r
+// Author:      G. Baruffa - based on imagjpeg.h, Vaclav Slavik\r
+// RCS-ID:      $Id: imagj2k.h,v 0.0 2007/02/08 23:45:00 VZ Exp $\r
+// Copyright:   (c) Giuseppe Baruffa\r
+// Licence:     wxWindows licence\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef _WX_IMAGJ2K_H_\r
+#define _WX_IMAGJ2K_H_\r
+\r
+#include "wx/defs.h"\r
+\r
+//-----------------------------------------------------------------------------\r
+// wxJ2KHandler\r
+//-----------------------------------------------------------------------------\r
+\r
+#if wxUSE_LIBOPENJPEG\r
+\r
+#include "wx/image.h"\r
+\r
+#define wxBITMAP_TYPE_J2K      47\r
+\r
+class WXDLLEXPORT wxJ2KHandler: public wxImageHandler\r
+{\r
+public:\r
+    inline wxJ2KHandler()\r
+    {\r
+        m_name = wxT("JPEG 2000 codestream file");\r
+        m_extension = wxT("j2k");\r
+        m_type = wxBITMAP_TYPE_J2K;\r
+        m_mime = wxT("image/j2k");\r
+    }\r
+\r
+#if wxUSE_STREAMS\r
+    virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1 );\r
+    virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=true );\r
+protected:\r
+    virtual bool DoCanRead( wxInputStream& stream );\r
+#endif\r
+\r
+private:\r
+    DECLARE_DYNAMIC_CLASS(wxJ2KHandler)\r
+};\r
+\r
+#endif // wxUSE_LIBOPENJPEG\r
+\r
+#endif // _WX_IMAGJ2K_H_\r
+\r
diff --git a/OPJViewer/source/imagjp2.cpp b/OPJViewer/source/imagjp2.cpp
new file mode 100644 (file)
index 0000000..4b7437f
--- /dev/null
@@ -0,0 +1,286 @@
+/*\r
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        imagjp2.cpp\r
+// Purpose:     wxImage JPEG 2000 file format handler\r
+// Author:      Giuseppe Baruffa - based on imagjpeg.cpp, Vaclav Slavik\r
+// RCS-ID:      $Id: imagjp2.cpp,v 0.00 2007/02/08 23:59:00 MW Exp $\r
+// Copyright:   (c) Giuseppe Baruffa\r
+// Licence:     wxWindows licence\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+// For compilers that support precompilation, includes "wx.h".\r
+#include "wx/wxprec.h"\r
+\r
+#ifdef __BORLANDC__\r
+    #pragma hdrstop\r
+#endif\r
+\r
+#if wxUSE_IMAGE && wxUSE_LIBOPENJPEG\r
+\r
+#include "imagjp2.h"\r
+\r
+#ifndef WX_PRECOMP\r
+    #include "wx/log.h"\r
+    #include "wx/app.h"\r
+    #include "wx/intl.h"\r
+    #include "wx/bitmap.h"\r
+    #include "wx/module.h"\r
+#endif\r
+\r
+\r
+#include "libopenjpeg/openjpeg.h"\r
+\r
+\r
+#include "wx/filefn.h"\r
+#include "wx/wfstream.h"\r
+\r
+// ----------------------------------------------------------------------------\r
+// types\r
+// ----------------------------------------------------------------------------\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// wxJP2Handler\r
+//-----------------------------------------------------------------------------\r
+\r
+IMPLEMENT_DYNAMIC_CLASS(wxJP2Handler,wxImageHandler)\r
+\r
+#if wxUSE_STREAMS\r
+\r
+//------------- JPEG 2000 Data Source Manager\r
+\r
+#define J2K_CFMT 0\r
+#define JP2_CFMT 1\r
+#define JPT_CFMT 2\r
+#define MJ2_CFMT 3\r
+#define PXM_DFMT 0\r
+#define PGX_DFMT 1\r
+#define BMP_DFMT 2\r
+#define YUV_DFMT 3\r
+\r
+#define MAX_MESSAGE_LEN 200\r
+\r
+/* sample error callback expecting a FILE* client object */\r
+void jp2_error_callback(const char *msg, void *client_data) {\r
+       char m_msg[MAX_MESSAGE_LEN];\r
+       int message_len = strlen(msg) - 1;\r
+       if (msg[message_len] != '\n')\r
+               message_len = MAX_MESSAGE_LEN;\r
+       sprintf(m_msg, "[ERROR] %.*s", message_len, msg);\r
+    wxMutexGuiEnter();\r
+       wxLogMessage(m_msg);\r
+    wxMutexGuiLeave();\r
+}\r
+/* sample warning callback expecting a FILE* client object */\r
+void jp2_warning_callback(const char *msg, void *client_data) {\r
+       char m_msg[MAX_MESSAGE_LEN];\r
+       int message_len = strlen(msg) - 1;\r
+       if (msg[message_len] != '\n')\r
+               message_len = MAX_MESSAGE_LEN;\r
+       sprintf(m_msg, "[WARNING] %.*s", message_len, msg);\r
+    wxMutexGuiEnter();\r
+       wxLogMessage(m_msg);\r
+    wxMutexGuiLeave();\r
+}\r
+/* sample debug callback expecting no client object */\r
+void jp2_info_callback(const char *msg, void *client_data) {\r
+       char m_msg[MAX_MESSAGE_LEN];\r
+       int message_len = strlen(msg) - 1;\r
+       if (msg[message_len] != '\n')\r
+               message_len = MAX_MESSAGE_LEN;\r
+       sprintf(m_msg, "[INFO] %.*s", message_len, msg);\r
+    wxMutexGuiEnter();\r
+       wxLogMessage(m_msg);\r
+    wxMutexGuiLeave();\r
+}\r
+\r
+// load the jp2 file format\r
+bool wxJP2Handler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index)\r
+{\r
+       opj_dparameters_t parameters;   /* decompression parameters */\r
+       opj_event_mgr_t event_mgr;              /* event manager */\r
+       opj_image_t *opjimage = NULL;\r
+       FILE *fsrc = NULL;\r
+       unsigned char *src = NULL;\r
+    unsigned char *ptr;\r
+       int file_length;\r
+\r
+       // destroy the image\r
+    image->Destroy();\r
+\r
+       /* handle to a decompressor */\r
+       opj_dinfo_t* dinfo = NULL;      \r
+       opj_cio_t *cio = NULL;\r
+\r
+       /* configure the event callbacks (not required) */\r
+       memset(&event_mgr, 0, sizeof(opj_event_mgr_t));\r
+       event_mgr.error_handler = jp2_error_callback;\r
+       event_mgr.warning_handler = jp2_warning_callback;\r
+       event_mgr.info_handler = jp2_info_callback;\r
+\r
+       /* set decoding parameters to default values */\r
+       opj_set_default_decoder_parameters(&parameters);\r
+\r
+       /* prepare parameters */\r
+       parameters.decod_format = JP2_CFMT;\r
+       parameters.cod_format = BMP_DFMT;\r
+\r
+       /* get a decoder handle */\r
+       dinfo = opj_create_decompress(CODEC_JP2);\r
+\r
+       /* find length of the stream */\r
+       stream.SeekI(0, wxFromEnd);\r
+       file_length = (int) stream.TellI();\r
+\r
+       /* get data */\r
+       stream.SeekI(0, wxFromStart);\r
+    src = (unsigned char *) malloc(file_length);\r
+       stream.Read(src, file_length);\r
+\r
+       /* catch events using our callbacks and give a local context */\r
+       opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);\r
+\r
+       /* setup the decoder decoding parameters using user parameters */\r
+       opj_setup_decoder(dinfo, &parameters);\r
+\r
+       /* open a byte stream */\r
+       cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);\r
+\r
+       /* decode the stream and fill the image structure */\r
+       opjimage = opj_decode(dinfo, cio);\r
+       if (!opjimage) {\r
+               wxMutexGuiEnter();\r
+               wxLogError("JP2: failed to decode image!");\r
+               wxMutexGuiLeave();\r
+               opj_destroy_decompress(dinfo);\r
+               opj_cio_close(cio);\r
+               free(src);\r
+               return false;\r
+       }\r
+\r
+       // check image size\r
+       if ((opjimage->numcomps != 1) && (opjimage->numcomps != 3)) {\r
+               wxMutexGuiEnter();\r
+               wxLogError("JP2: weird number of components");\r
+               wxMutexGuiLeave();\r
+               opj_destroy_decompress(dinfo);\r
+               opj_cio_close(cio);\r
+               free(src);\r
+               return false;\r
+       }\r
+\r
+       // prepare image size\r
+    image->Create(opjimage->comps[0].w, opjimage->comps[0].h, true );\r
+\r
+       // access image raw data\r
+    image->SetMask( false );\r
+    ptr = image->GetData();\r
+\r
+       // RGB color picture\r
+       if (opjimage->numcomps == 3) {\r
+               int row, col;\r
+               int *r = opjimage->comps[0].data;\r
+               int *g = opjimage->comps[1].data;\r
+               int *b = opjimage->comps[2].data;\r
+               for (row = 0; row < opjimage->comps[0].h; row++) {\r
+                       for (col = 0; col < opjimage->comps[0].w; col++) {\r
+                               \r
+                               *(ptr++) = *(r++);\r
+                               *(ptr++) = *(g++);\r
+                               *(ptr++) = *(b++);\r
+\r
+                       }\r
+               }\r
+       }\r
+\r
+       // B/W picture\r
+       if (opjimage->numcomps == 1) {\r
+               int row, col;\r
+               int *y = opjimage->comps[0].data;\r
+               for (row = 0; row < opjimage->comps[0].h; row++) {\r
+                       for (col = 0; col < opjimage->comps[0].w; col++) {\r
+                               \r
+                               *(ptr++) = *(y);\r
+                               *(ptr++) = *(y);\r
+                               *(ptr++) = *(y++);\r
+\r
+                       }\r
+               }\r
+       }\r
+\r
+    wxMutexGuiEnter();\r
+    wxLogMessage(wxT("JP2: image loaded."));\r
+    wxMutexGuiLeave();\r
+\r
+       /* close openjpeg structs */\r
+       opj_destroy_decompress(dinfo);\r
+       opj_cio_close(cio);\r
+       opj_image_destroy(opjimage);\r
+       free(src);\r
+\r
+       if (!image->Ok())\r
+               return false;\r
+       else\r
+               return true;\r
+\r
+}\r
+\r
+// save the jp2 file format\r
+bool wxJP2Handler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )\r
+{\r
+    wxLogError(wxT("JP2: Couldn't save image -> not implemented."));\r
+    return false;\r
+}\r
+\r
+#ifdef __VISUALC__\r
+    #pragma warning(default:4611)\r
+#endif /* VC++ */\r
+\r
+// recognize the JPEG 2000 starting box\r
+bool wxJP2Handler::DoCanRead( wxInputStream& stream )\r
+{\r
+    unsigned char hdr[23];\r
+\r
+    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )\r
+        return false;\r
+\r
+    return (hdr[0] == 0x00 &&\r
+                       hdr[1] == 0x00 &&\r
+                       hdr[2] == 0x00 &&\r
+                       hdr[3] == 0x0C &&\r
+                       hdr[4] == 0x6A &&\r
+                       hdr[5] == 0x50 &&\r
+                       hdr[6] == 0x20 &&\r
+                       hdr[7] == 0x20 &&\r
+                       hdr[20] == 0x6A &&\r
+                       hdr[21] == 0x70 &&\r
+                       hdr[22] == 0x32);\r
+}\r
+\r
+#endif   // wxUSE_STREAMS\r
+\r
+#endif   // wxUSE_LIBOPENJPEG\r
diff --git a/OPJViewer/source/imagjp2.h b/OPJViewer/source/imagjp2.h
new file mode 100644 (file)
index 0000000..1ebad87
--- /dev/null
@@ -0,0 +1,75 @@
+/*\r
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        imagjp2.h\r
+// Purpose:     wxImage JPEG 2000 file format handler\r
+// Author:      G. Baruffa - based on imagjpeg.h, Vaclav Slavik\r
+// RCS-ID:      $Id: imagjp2.h,v 0.0 2007/02/08 23:45:00 VZ Exp $\r
+// Copyright:   (c) Giuseppe Baruffa\r
+// Licence:     wxWindows licence\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef _WX_IMAGJP2_H_\r
+#define _WX_IMAGJP2_H_\r
+\r
+#include "wx/defs.h"\r
+\r
+//-----------------------------------------------------------------------------\r
+// wxJP2Handler\r
+//-----------------------------------------------------------------------------\r
+\r
+#if wxUSE_LIBOPENJPEG\r
+\r
+#include "wx/image.h"\r
+\r
+#define wxBITMAP_TYPE_JP2      48\r
+\r
+class WXDLLEXPORT wxJP2Handler: public wxImageHandler\r
+{\r
+public:\r
+    inline wxJP2Handler()\r
+    {\r
+        m_name = wxT("JPEG 2000 file format");\r
+        m_extension = wxT("jp2");\r
+        m_type = wxBITMAP_TYPE_JP2;\r
+        m_mime = wxT("image/jp2");\r
+    }\r
+\r
+#if wxUSE_STREAMS\r
+    virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1 );\r
+    virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=true );\r
+protected:\r
+    virtual bool DoCanRead( wxInputStream& stream );\r
+#endif\r
+\r
+private:\r
+    DECLARE_DYNAMIC_CLASS(wxJP2Handler)\r
+};\r
+\r
+#endif // wxUSE_LIBOPENJPEG\r
+\r
+#endif // _WX_IMAGJP2_H_\r
+\r
diff --git a/OPJViewer/source/imagmj2.cpp b/OPJViewer/source/imagmj2.cpp
new file mode 100644 (file)
index 0000000..351621e
--- /dev/null
@@ -0,0 +1,785 @@
+/*\r
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        imagmj2.cpp\r
+// Purpose:     wxImage Motion JPEG 2000 file format handler\r
+// Author:      Giuseppe Baruffa - based on imagjpeg.cpp, Vaclav Slavik\r
+// RCS-ID:      $Id: imagmj2.cpp,v 0.00 2007/02/18 23:59:00 MW Exp $\r
+// Copyright:   (c) Giuseppe Baruffa\r
+// Licence:     wxWindows licence\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+// For compilers that support precompilation, includes "wx.h".\r
+#include "wx/wxprec.h"\r
+\r
+#ifdef __BORLANDC__\r
+    #pragma hdrstop\r
+#endif\r
+\r
+#if wxUSE_IMAGE && wxUSE_LIBOPENJPEG\r
+\r
+#include "imagmj2.h"\r
+\r
+#ifndef WX_PRECOMP\r
+    #include "wx/log.h"\r
+    #include "wx/app.h"\r
+    #include "wx/intl.h"\r
+    #include "wx/bitmap.h"\r
+    #include "wx/module.h"\r
+#endif\r
+\r
+\r
+#include "libopenjpeg/openjpeg.h"\r
+\r
+\r
+#include "wx/filefn.h"\r
+#include "wx/wfstream.h"\r
+\r
+// ----------------------------------------------------------------------------\r
+// types\r
+// ----------------------------------------------------------------------------\r
+\r
+\r
+//-----------------------------------------------------------------------------\r
+// wxMJ2Handler\r
+//-----------------------------------------------------------------------------\r
+\r
+IMPLEMENT_DYNAMIC_CLASS(wxMJ2Handler,wxImageHandler)\r
+\r
+#if wxUSE_STREAMS\r
+\r
+//------------- JPEG 2000 Data Source Manager\r
+\r
+#define J2K_CFMT 0\r
+#define JP2_CFMT 1\r
+#define JPT_CFMT 2\r
+#define MJ2_CFMT 3\r
+#define PXM_DFMT 0\r
+#define PGX_DFMT 1\r
+#define BMP_DFMT 2\r
+#define YUV_DFMT 3\r
+\r
+#define MAX_MESSAGE_LEN 200\r
+\r
+/* sample error callback expecting a FILE* client object */\r
+void mj2_error_callback(const char *msg, void *client_data) {\r
+       char m_msg[MAX_MESSAGE_LEN];\r
+       int message_len = strlen(msg) - 1;\r
+       if (msg[message_len] != '\n')\r
+               message_len = MAX_MESSAGE_LEN;\r
+       sprintf(m_msg, "[ERROR] %.*s", message_len, msg);\r
+    wxMutexGuiEnter();\r
+       wxLogMessage(m_msg);\r
+    wxMutexGuiLeave();\r
+}\r
+/* sample warning callback expecting a FILE* client object */\r
+void mj2_warning_callback(const char *msg, void *client_data) {\r
+       char m_msg[MAX_MESSAGE_LEN];\r
+       int message_len = strlen(msg) - 1;\r
+       if (msg[message_len] != '\n')\r
+               message_len = MAX_MESSAGE_LEN;\r
+       sprintf(m_msg, "[WARNING] %.*s", message_len, msg);\r
+    wxMutexGuiEnter();\r
+       wxLogMessage(m_msg);\r
+    wxMutexGuiLeave();\r
+}\r
+/* sample debug callback expecting no client object */\r
+void mj2_info_callback(const char *msg, void *client_data) {\r
+       char m_msg[MAX_MESSAGE_LEN];\r
+       int message_len = strlen(msg) - 1;\r
+       if (msg[message_len] != '\n')\r
+               message_len = MAX_MESSAGE_LEN;\r
+       sprintf(m_msg, "[INFO] %.*s", message_len, msg);\r
+    wxMutexGuiEnter();\r
+       wxLogMessage(m_msg);\r
+    wxMutexGuiLeave();\r
+}\r
+\r
+/* macro functions */\r
+/* From little endian to big endian, 2 and 4 bytes */\r
+#define        BYTE_SWAP2(X)   ((X & 0x00FF) << 8) | ((X & 0xFF00) >> 8)\r
+#define        BYTE_SWAP4(X)   ((X & 0x000000FF) << 24) | ((X & 0x0000FF00) << 8) | ((X & 0x00FF0000) >> 8) | ((X & 0xFF000000) >> 24)\r
+#define        BYTE_SWAP8(X)   ((X & 0x00000000000000FF) << 56) | ((X & 0x000000000000FF00) << 40) | \\r
+                        ((X & 0x0000000000FF0000) << 24) | ((X & 0x00000000FF000000) << 8) | \\r
+                                               ((X & 0x000000FF00000000) >> 8)  | ((X & 0x0000FF0000000000) >> 24) | \\r
+                                               ((X & 0x00FF000000000000) >> 40) | ((X & 0xFF00000000000000) >> 56)\r
+\r
+/* From codestream to int values */\r
+#define STREAM_TO_UINT32(C, P) (((unsigned long int) (C)[(P) + 0] << 24) + \\r
+                                                               ((unsigned long int) (C)[(P) + 1] << 16) + \\r
+                                                               ((unsigned long int) (C)[(P) + 2] << 8) + \\r
+                                                               ((unsigned long int) (C)[(P) + 3] << 0))\r
+\r
+#define STREAM_TO_UINT16(C, P) (((unsigned long int) (C)[(P) + 0] << 8) + \\r
+                                                               ((unsigned long int) (C)[(P) + 1] << 0))\r
+\r
+/* defines */\r
+#define SHORT_DESCR_LEN        32\r
+#define LONG_DESCR_LEN         256\r
+\r
+/* enumeration for file formats */\r
+#define J2FILENUM              4\r
+typedef enum {\r
+\r
+        JP2_FILE,\r
+        J2K_FILE,\r
+               MJ2_FILE,\r
+               UNK_FILE\r
+\r
+} my_j2filetype;\r
+\r
+/* enumeration for the box types */\r
+#define J2BOXNUM                23\r
+typedef enum {\r
+\r
+                       FILE_BOX,\r
+                       JP_BOX,\r
+                       FTYP_BOX,\r
+                       JP2H_BOX,\r
+                       IHDR_BOX,\r
+                       COLR_BOX,\r
+                       JP2C_BOX,\r
+                       JP2I_BOX,\r
+                       XML_BOX,\r
+                       UUID_BOX,\r
+                       UINF_BOX,\r
+                       MOOV_BOX,\r
+                       MVHD_BOX,\r
+                       TRAK_BOX,\r
+                       TKHD_BOX,\r
+                       MDIA_BOX,\r
+                       MINF_BOX,\r
+                       STBL_BOX,\r
+                       STSD_BOX,\r
+                       MJP2_BOX,\r
+                       MDAT_BOX,\r
+                       ANY_BOX,\r
+                       UNK_BOX\r
+\r
+} my_j2boxtype;\r
+\r
+/* jp2 family box signatures */\r
+#define FILE_SIGN           ""\r
+#define JP_SIGN             "jP\040\040"\r
+#define FTYP_SIGN           "ftyp"\r
+#define JP2H_SIGN           "jp2h"\r
+#define IHDR_SIGN           "ihdr"\r
+#define COLR_SIGN           "colr"\r
+#define JP2C_SIGN           "jp2c"\r
+#define JP2I_SIGN           "jp2i"\r
+#define XML_SIGN            "xml\040"\r
+#define UUID_SIGN           "uuid"\r
+#define UINF_SIGN           "uinf"\r
+#define MOOV_SIGN           "moov"\r
+#define MVHD_SIGN           "mvhd"\r
+#define TRAK_SIGN           "trak"\r
+#define TKHD_SIGN           "tkhd"\r
+#define MDIA_SIGN           "mdia"\r
+#define MINF_SIGN           "minf"\r
+#define STBL_SIGN           "stbl"\r
+#define STSD_SIGN           "stsd"\r
+#define MJP2_SIGN           "mjp2"\r
+#define MDAT_SIGN           "mdat"\r
+#define ANY_SIGN                       ""\r
+#define UNK_SIGN            ""\r
+\r
+/* the box structure itself */\r
+struct my_boxdef {\r
+\r
+        char                  value[5];                 /* hexadecimal value/string*/\r
+               char                  name[SHORT_DESCR_LEN];    /* short description       */\r
+               char                  descr[LONG_DESCR_LEN];    /* long  description       */\r
+               int                   sbox;                     /* is it a superbox?       */\r
+               int                   req[J2FILENUM];           /* mandatory box           */\r
+               my_j2boxtype             ins;                      /* contained in box...     */\r
+\r
+};\r
+\r
+/* the possible boxes */\r
+struct my_boxdef j2box[] =\r
+{\r
+/* sign */     {FILE_SIGN,\r
+/* short */    "placeholder for nothing",\r
+/* long */     "Nothing to say",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {JP_SIGN,\r
+/* short */    "JPEG 2000 Signature box",\r
+/* long */     "This box uniquely identifies the file as being part of the JPEG 2000 family of files",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {FTYP_SIGN,\r
+/* short */    "File Type box",\r
+/* long */     "This box specifies file type, version and compatibility information, including specifying if this file "\r
+                       "is a conforming JP2 file or if it can be read by a conforming JP2 reader",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {JP2H_SIGN,\r
+/* short */    "JP2 Header box",\r
+/* long */     "This box contains a series of boxes that contain header-type information about the file",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {IHDR_SIGN,\r
+/* short */    "Image Header box",\r
+/* long */     "This box specifies the size of the image and other related fields",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      JP2H_BOX},\r
+\r
+/* sign */     {COLR_SIGN,\r
+/* short */    "Colour Specification box",\r
+/* long */     "This box specifies the colourspace of the image",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      JP2H_BOX},\r
+\r
+/* sign */     {JP2C_SIGN,\r
+/* short */    "Contiguous Codestream box",\r
+/* long */     "This box contains the codestream as defined by Annex A",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {JP2I_SIGN,\r
+/* short */    "Intellectual Property box",\r
+/* long */     "This box contains intellectual property information about the image",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {XML_SIGN,\r
+/* short */    "XML box",\r
+/* long */     "This box provides a tool by which vendors can add XML formatted information to a JP2 file",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {UUID_SIGN,\r
+/* short */    "UUID box",\r
+/* long */     "This box provides a tool by which vendors can add additional information to a file "\r
+                       "without risking conflict with other vendors",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {UINF_SIGN,\r
+/* short */    "UUID Info box",\r
+/* long */     "This box provides a tool by which a vendor may provide access to additional information associated with a UUID",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {MOOV_SIGN,\r
+/* short */    "Movie box",\r
+/* long */     "This box contains the media data. In video tracks, this box would contain JPEG2000 video frames",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {MVHD_SIGN,\r
+/* short */    "Movie Header box",\r
+/* long */     "This box defines overall information which is media-independent, and relevant to the entire presentation "\r
+                       "considered as a whole",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MOOV_BOX},\r
+\r
+/* sign */     {TRAK_SIGN,\r
+/* short */    "Track box",\r
+/* long */     "This is a container box for a single track of a presentation. A presentation may consist of one or more tracks",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MOOV_BOX},\r
+\r
+/* sign */     {TKHD_SIGN,\r
+/* short */    "Track Header box",\r
+/* long */     "This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      TRAK_BOX},\r
+\r
+/* sign */     {MDIA_SIGN,\r
+/* short */    "Media box",\r
+/* long */     "The media declaration container contains all the objects which declare information about the media data "\r
+                       "within a track",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      TRAK_BOX},\r
+\r
+/* sign */     {MINF_SIGN,\r
+/* short */    "Media Information box",\r
+/* long */     "This box contains all the objects which declare characteristic information of the media in the track",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MDIA_BOX},\r
+\r
+/* sign */     {STBL_SIGN,\r
+/* short */    "Sample Table box",\r
+/* long */     "The sample table contains all the time and data indexing of the media samples in a track",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MINF_BOX},\r
+\r
+/* sign */     {STSD_SIGN,\r
+/* short */    "Sample Description box",\r
+/* long */     "The sample description table gives detailed information about the coding type used, and any initialization "\r
+                       "information needed for that coding",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MINF_BOX},\r
+\r
+/* sign */     {MJP2_SIGN,\r
+/* short */    "MJP2 Sample Description box",\r
+/* long */     "The MJP2 sample description table gives detailed information about the coding type used, and any initialization "\r
+                       "information needed for that coding",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MINF_BOX},\r
+\r
+/* sign */     {MDAT_SIGN,\r
+/* short */    "Media Data box",\r
+/* long */     "The meta-data for a presentation is stored in the single Movie Box which occurs at the top-level of a file",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {ANY_SIGN,\r
+/* short */    "Any box",\r
+/* long */     "All the existing boxes",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {UNK_SIGN,\r
+/* short */    "Unknown Type box",\r
+/* long */     "The signature is not recognised to be that of an existing box",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      ANY_BOX}\r
+\r
+};\r
+\r
+/* declaration */\r
+int\r
+my_box_handler_function(my_j2boxtype boxtype, wxInputStream& stream, unsigned long int filepoint, unsigned long int filelimit, int level,\r
+                                        char *scansign, unsigned long int *scanpoint);\r
+\r
+/* internal mini-search for a box signature */\r
+int\r
+my_jpeg2000parse(wxInputStream& stream, unsigned long int filepoint, unsigned long int filelimit, int level,\r
+                         char *scansign, unsigned long int *scanpoint)\r
+{\r
+       unsigned long int       LBox = 0x00000000;\r
+       int                     LBox_read;\r
+       char                    TBox[5] = "\0\0\0\0";\r
+       int                     TBox_read;\r
+       __int64                 XLBox = 0x0000000000000000;\r
+       int                     XLBox_read;\r
+       unsigned long int       box_length = 0;\r
+       int                     last_box = 0, box_num = 0;\r
+       int                     box_type = ANY_BOX;\r
+       unsigned char           onebyte[1], twobytes[2], fourbytes[4];\r
+       int                     box_number = 0;\r
+\r
+       /* cycle all over the file */\r
+       box_num = 0;\r
+       last_box = 0;\r
+       while (!last_box) {\r
+\r
+               /* do not exceed file limit */\r
+               if (filepoint >= filelimit)\r
+                       return (0);\r
+\r
+               /* seek on file */\r
+               if (stream.SeekI(filepoint, wxFromStart) == wxInvalidOffset)\r
+                       return (-1);\r
+\r
+               /* read the mandatory LBox, 4 bytes */\r
+               if (!stream.Read(fourbytes, 4)) {\r
+                       (wxT("Problem reading LBox from the file (file ended?)"));\r
+                       return -1;\r
+               };\r
+               LBox = STREAM_TO_UINT32(fourbytes, 0);\r
+\r
+               /* read the mandatory TBox, 4 bytes */\r
+               if (!stream.Read(TBox, 4)) {\r
+                       wxLogError(wxT("Problem reading TBox from the file (file ended?)"));\r
+                       return -1;\r
+               };\r
+\r
+               /* look if scansign is got */\r
+               if ((scansign != NULL) && (memcmp(TBox, scansign, 4) == 0)) {\r
+                       /* hack/exploit */\r
+                       // stop as soon as you find the level-th codebox\r
+                       if (box_number == level) {\r
+                               memcpy(scansign, "    ", 4);\r
+                               *scanpoint = filepoint;\r
+                               return (0);\r
+                       } else\r
+                               box_number++;\r
+\r
+               };\r
+\r
+\r
+               /* determine the box type */\r
+               for (box_type = JP_BOX; box_type < UNK_BOX; box_type++)\r
+                       if (memcmp(TBox, j2box[box_type].value, 4) == 0)\r
+                               break;  \r
+\r
+               /* read the optional XLBox, 8 bytes */\r
+               if (LBox == 1) {\r
+\r
+                       if (!stream.Read(&XLBox, 8)) {\r
+                               wxLogError(wxT("Problem reading XLBox from the file (file ended?)"));\r
+                               return -1;\r
+                       };\r
+                       box_length = (unsigned long int) BYTE_SWAP8(XLBox);\r
+\r
+               } else if (LBox == 0x00000000) {\r
+\r
+                       /* last box in file */\r
+                       last_box = 1; \r
+                       box_length = filelimit - filepoint;\r
+\r
+               } else\r
+\r
+                       box_length = LBox;\r
+\r
+\r
+               /* go deep in the box */\r
+               my_box_handler_function((my_j2boxtype) box_type, stream, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length, level,\r
+                       scansign, scanpoint);\r
+\r
+               /* if it's a superbox go inside it */\r
+               if (j2box[box_type].sbox)\r
+                       my_jpeg2000parse(stream, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length,\r
+                               level, scansign, scanpoint);\r
+\r
+               /* increment box number and filepoint*/\r
+               box_num++;\r
+               filepoint += box_length;\r
+\r
+       };\r
+\r
+       /* all good */\r
+       return (0);\r
+}\r
+\r
+// search first contiguos codestream box in an mj2 file\r
+unsigned long int\r
+searchfirstjp2c(wxInputStream& stream, unsigned long int fsize)\r
+{\r
+       char scansign[] = "jp2c";\r
+       unsigned long int scanpoint = 0L;\r
+\r
+       wxLogMessage("MJ2: searching jp2c box... ");\r
+\r
+       /* do the parsing */\r
+       if (my_jpeg2000parse(stream, 0, fsize, 0, scansign, &scanpoint) < 0)            \r
+               wxLogMessage("MJ2: Unrecoverable error during file parsing: stopping");\r
+\r
+       if (strcmp(scansign, "    "))\r
+               wxLogMessage("MJ2: not found");\r
+       else {\r
+\r
+               wxLogMessage(wxString::Format("MJ2: found at byte %d", scanpoint));\r
+\r
+       };\r
+\r
+\r
+       return (scanpoint);\r
+}\r
+\r
+// search the jp2h box in the file\r
+unsigned long int\r
+searchjpegheaderbox(wxInputStream& stream, unsigned long int fsize)\r
+{\r
+       char scansign[] = "jp2h";\r
+       unsigned long int scanpoint = 0L;\r
+\r
+       wxLogMessage("MJ2: searching jp2h box... ");\r
+\r
+       /* do the parsing */\r
+       if (my_jpeg2000parse(stream, 0, fsize, 0, scansign, &scanpoint) < 0)            \r
+               wxLogMessage("Unrecoverable error during file parsing: stopping");\r
+\r
+       if (strcmp(scansign, "    "))\r
+               wxLogMessage("MJ2: not found");\r
+       else\r
+               wxLogMessage(wxString::Format("MJ2: found at byte %d", scanpoint));\r
+\r
+       return (scanpoint);\r
+}\r
+\r
+/* handling functions */\r
+#define ITEM_PER_ROW   10\r
+\r
+/* Box handler function */\r
+int\r
+my_box_handler_function(my_j2boxtype boxtype, wxInputStream& stream, unsigned long int filepoint, unsigned long int filelimit, int level,\r
+                                        char *scansign, unsigned long int *scanpoint)\r
+{\r
+       switch (boxtype) {\r
+\r
+                       /* Sample Description box */\r
+       case (STSD_BOX):\r
+               my_jpeg2000parse(stream, filepoint + 8, filelimit, level, scansign, scanpoint);\r
+               break;\r
+\r
+                       /* MJP2 Sample Description box */\r
+       case (MJP2_BOX):\r
+               my_jpeg2000parse(stream, filepoint + 78, filelimit, level, scansign, scanpoint);\r
+               break;\r
+               \r
+       /* not yet implemented */\r
+       default:\r
+               break;\r
+\r
+       };\r
+\r
+       return (0);\r
+}\r
+\r
+// the jP and ftyp parts of the header\r
+#define my_jPheadSIZE  32\r
+unsigned char my_jPhead[my_jPheadSIZE] = {\r
+               0x00, 0x00, 0x00, 0x0C,  'j',  'P',  ' ',  ' ',\r
+               0x0D, 0x0A, 0x87, 0x0A, 0x00, 0x00, 0x00, 0x14,\r
+                'f',  't',  'y',  'p',  'j',  'p',  '2',  ' ',\r
+               0x00, 0x00, 0x00, 0x00,  'j',  'p',  '2',  ' '                  \r
+};\r
+\r
+/////////////////////////////////////////////////\r
+/////////////////////////////////////////////////\r
+\r
+// load the mj2 file format\r
+bool wxMJ2Handler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index)\r
+{\r
+       opj_dparameters_t parameters;   /* decompression parameters */\r
+       opj_event_mgr_t event_mgr;              /* event manager */\r
+       opj_image_t *opjimage = NULL;\r
+       FILE *fsrc = NULL;\r
+       unsigned char *src = NULL;\r
+    unsigned char *ptr;\r
+       int file_length, jp2c_point, jp2h_point;\r
+       unsigned long int jp2hboxlen, jp2cboxlen;\r
+\r
+       // destroy the image\r
+    image->Destroy();\r
+\r
+       /* handle to a decompressor */\r
+       opj_dinfo_t* dinfo = NULL;      \r
+       opj_cio_t *cio = NULL;\r
+\r
+       /* configure the event callbacks (not required) */\r
+       memset(&event_mgr, 0, sizeof(opj_event_mgr_t));\r
+       event_mgr.error_handler = mj2_error_callback;\r
+       event_mgr.warning_handler = mj2_warning_callback;\r
+       event_mgr.info_handler = mj2_info_callback;\r
+\r
+       /* set decoding parameters to default values */\r
+       opj_set_default_decoder_parameters(&parameters);\r
+\r
+       /* prepare parameters */\r
+       parameters.decod_format = JP2_CFMT;\r
+       parameters.cod_format = BMP_DFMT;\r
+\r
+       /* get a decoder handle */\r
+       dinfo = opj_create_decompress(CODEC_JP2);\r
+\r
+       /* find length of the stream */\r
+       stream.SeekI(0, wxFromEnd);\r
+       file_length = (int) stream.TellI();\r
+\r
+       /* search for the first codestream box and the movie header box  */\r
+       jp2c_point = searchfirstjp2c(stream, file_length);\r
+       jp2h_point = searchjpegheaderbox(stream, file_length);\r
+\r
+       // read the jp2h box and store it\r
+       stream.SeekI(jp2h_point, wxFromStart);\r
+       stream.Read(&jp2hboxlen, sizeof(unsigned long int));\r
+       jp2hboxlen = BYTE_SWAP4(jp2hboxlen);\r
+\r
+       // read the jp2c box and store it\r
+       stream.SeekI(jp2c_point, wxFromStart);\r
+       stream.Read(&jp2cboxlen, sizeof(unsigned long int));\r
+       jp2cboxlen = BYTE_SWAP4(jp2cboxlen);\r
+\r
+       // malloc memory source\r
+    src = (unsigned char *) malloc(my_jPheadSIZE + jp2hboxlen + jp2cboxlen);\r
+\r
+       // copy the jP and ftyp\r
+       memcpy(src, my_jPhead, my_jPheadSIZE);\r
+\r
+       // copy the jp2h\r
+       stream.SeekI(jp2h_point, wxFromStart);\r
+       stream.Read(&src[my_jPheadSIZE], jp2hboxlen);\r
+\r
+       // copy the jp2c\r
+       stream.SeekI(jp2c_point, wxFromStart);\r
+       stream.Read(&src[my_jPheadSIZE + jp2hboxlen], jp2cboxlen);\r
+\r
+       /* catch events using our callbacks and give a local context */\r
+       opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);\r
+\r
+       /* setup the decoder decoding parameters using user parameters */\r
+       opj_setup_decoder(dinfo, &parameters);\r
+\r
+       /* open a byte stream */\r
+       cio = opj_cio_open((opj_common_ptr)dinfo, src, my_jPheadSIZE + jp2hboxlen + jp2cboxlen);\r
+\r
+       /* decode the stream and fill the image structure */\r
+       opjimage = opj_decode(dinfo, cio);\r
+       if (!opjimage) {\r
+               wxMutexGuiEnter();\r
+               wxLogError("MJ2: failed to decode image!");\r
+               wxMutexGuiLeave();\r
+               opj_destroy_decompress(dinfo);\r
+               opj_cio_close(cio);\r
+               free(src);\r
+               return false;\r
+       }\r
+\r
+       // check image size\r
+       if ((opjimage->numcomps != 1) && (opjimage->numcomps != 3)) {\r
+               wxMutexGuiEnter();\r
+               wxLogError("MJ2: weird number of components");\r
+               wxMutexGuiLeave();\r
+               opj_destroy_decompress(dinfo);\r
+               opj_cio_close(cio);\r
+               free(src);\r
+               return false;\r
+       }\r
+\r
+       // prepare image size\r
+    image->Create(opjimage->comps[0].w, opjimage->comps[0].h, true );\r
+\r
+       // access image raw data\r
+    image->SetMask( false );\r
+    ptr = image->GetData();\r
+\r
+       // RGB color picture\r
+       // does not handle comps. subsampling,\r
+       // so simply render the first component\r
+       if (opjimage->numcomps == 3) {\r
+               int row, col;\r
+               int *r = opjimage->comps[0].data;\r
+               /*\r
+               int *g = opjimage->comps[1].data;\r
+               int *b = opjimage->comps[2].data;\r
+               */\r
+               for (row = 0; row < opjimage->comps[0].h; row++) {\r
+                       for (col = 0; col < opjimage->comps[0].w; col++) {\r
+                               \r
+                               /*\r
+                               *(ptr++) = *(r++);\r
+                               *(ptr++) = *(g++);\r
+                               *(ptr++) = *(b++);\r
+                               */\r
+                               *(ptr++) = *(r);\r
+                               *(ptr++) = *(r);\r
+                               *(ptr++) = *(r++);\r
+\r
+                       }\r
+               }\r
+       }\r
+\r
+       // B/W picture\r
+       if (opjimage->numcomps == 1) {\r
+               int row, col;\r
+               int *y = opjimage->comps[0].data;\r
+               for (row = 0; row < opjimage->comps[0].h; row++) {\r
+                       for (col = 0; col < opjimage->comps[0].w; col++) {\r
+                               \r
+                               *(ptr++) = *(y);\r
+                               *(ptr++) = *(y);\r
+                               *(ptr++) = *(y++);\r
+\r
+                       }\r
+               }\r
+       }\r
+\r
+    wxMutexGuiEnter();\r
+    wxLogMessage(wxT("MJ2: image loaded."));\r
+    wxMutexGuiLeave();\r
+\r
+       /* close openjpeg structs */\r
+       opj_destroy_decompress(dinfo);\r
+       opj_cio_close(cio);\r
+       opj_image_destroy(opjimage);\r
+       free(src);\r
+\r
+       if (!image->Ok())\r
+               return false;\r
+       else\r
+               return true;\r
+\r
+}\r
+\r
+// save the mj2 file format\r
+bool wxMJ2Handler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )\r
+{\r
+    wxLogError(wxT("MJ2: Couldn't save movie -> not implemented."));\r
+    return false;\r
+}\r
+\r
+#ifdef __VISUALC__\r
+    #pragma warning(default:4611)\r
+#endif /* VC++ */\r
+\r
+// recognize the Motion JPEG 2000 starting box\r
+bool wxMJ2Handler::DoCanRead( wxInputStream& stream )\r
+{\r
+    unsigned char hdr[24];\r
+\r
+    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )\r
+        return false;\r
+\r
+    return (hdr[0] == 0x00 &&\r
+                       hdr[1] == 0x00 &&\r
+                       hdr[2] == 0x00 &&\r
+                       hdr[3] == 0x0C &&\r
+                       hdr[4] == 0x6A &&\r
+                       hdr[5] == 0x50 &&\r
+                       hdr[6] == 0x20 &&\r
+                       hdr[7] == 0x20 &&\r
+                       hdr[20] == 0x6D &&\r
+                       hdr[21] == 0x6A &&\r
+                       hdr[22] == 0x70 &&\r
+                       hdr[23] == 0x32);\r
+}\r
+\r
+#endif   // wxUSE_STREAMS\r
+\r
+#endif   // wxUSE_LIBOPENJPEG\r
diff --git a/OPJViewer/source/imagmj2.h b/OPJViewer/source/imagmj2.h
new file mode 100644 (file)
index 0000000..1c9667f
--- /dev/null
@@ -0,0 +1,75 @@
+/*\r
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+/////////////////////////////////////////////////////////////////////////////\r
+// Name:        imagmj2.h\r
+// Purpose:     wxImage Motion JPEG 2000 file format handler\r
+// Author:      G. Baruffa - based on imagjpeg.h, Vaclav Slavik\r
+// RCS-ID:      $Id: imagmj2.h,v 0.0 2007/02/18 23:45:00 VZ Exp $\r
+// Copyright:   (c) Giuseppe Baruffa\r
+// Licence:     wxWindows licence\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef _WX_IMAGMJ2_H_\r
+#define _WX_IMAGMJ2_H_\r
+\r
+#include "wx/defs.h"\r
+\r
+//-----------------------------------------------------------------------------\r
+// wxMJ2Handler\r
+//-----------------------------------------------------------------------------\r
+\r
+#if wxUSE_LIBOPENJPEG\r
+\r
+#include "wx/image.h"\r
+\r
+#define wxBITMAP_TYPE_MJ2      49\r
+\r
+class WXDLLEXPORT wxMJ2Handler: public wxImageHandler\r
+{\r
+public:\r
+    inline wxMJ2Handler()\r
+    {\r
+        m_name = wxT("Motion JPEG 2000 file format");\r
+        m_extension = wxT("mj2");\r
+        m_type = wxBITMAP_TYPE_MJ2;\r
+        m_mime = wxT("image/mj2");\r
+    }\r
+\r
+#if wxUSE_STREAMS\r
+    virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1 );\r
+    virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=true );\r
+protected:\r
+    virtual bool DoCanRead( wxInputStream& stream );\r
+#endif\r
+\r
+private:\r
+    DECLARE_DYNAMIC_CLASS(wxMJ2Handler)\r
+};\r
+\r
+#endif // wxUSE_LIBOPENJPEG\r
+\r
+#endif // _WX_IMAGMJ2_H_\r
+\r
diff --git a/OPJViewer/source/wxj2kparser.cpp b/OPJViewer/source/wxj2kparser.cpp
new file mode 100644 (file)
index 0000000..7e189d7
--- /dev/null
@@ -0,0 +1,337 @@
+/*\r
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+#include "OPJViewer.h"\r
+\r
+/* From little endian to big endian, 2 bytes */\r
+#define        BYTE_SWAP2(X)   ((X & 0x00FF) << 8) | ((X & 0xFF00) >> 8)\r
+#define        BYTE_SWAP4(X)   ((X & 0x000000FF) << 24) | ((X & 0x0000FF00) << 8) | ((X & 0x00FF0000) >> 8) | ((X & 0xFF000000) >> 24)\r
+\r
+/* From codestream to int values */\r
+#define STREAM_TO_UINT32(C, P) (((unsigned long int) (C)[(P) + 0] << 24) + \\r
+                                                               ((unsigned long int) (C)[(P) + 1] << 16) + \\r
+                                                               ((unsigned long int) (C)[(P) + 2] << 8) + \\r
+                                                               ((unsigned long int) (C)[(P) + 3] << 0))\r
+\r
+#define STREAM_TO_UINT16(C, P) (((unsigned long int) (C)[(P) + 0] << 8) + \\r
+                                                               ((unsigned long int) (C)[(P) + 1] << 0))\r
+\r
+\r
+/* Markers values */\r
+enum {\r
+       SOC_VAL = 0xFF4F,\r
+       SOT_VAL = 0xFF90,\r
+       SOD_VAL = 0xFF93,\r
+       EOC_VAL = 0xFFD9,\r
+       SIZ_VAL = 0xFF51,\r
+       COD_VAL = 0xFF52,\r
+       COC_VAL = 0xFF53,\r
+       RGN_VAL = 0xFF5E,\r
+       QCD_VAL = 0xFF5C,\r
+       QCC_VAL = 0xFF5D,\r
+       POD_VAL = 0xFF5F,\r
+       TLM_VAL = 0xFF55,\r
+       PLM_VAL = 0xFF57,\r
+       PLT_VAL = 0xFF58,\r
+       PPM_VAL = 0xFF60,\r
+       PPT_VAL = 0xFF61,\r
+       SOP_VAL = 0xFF91,\r
+       EPH_VAL = 0xFF92,\r
+       CME_VAL = 0xFF64,\r
+#ifndef USEOLDJPWL \r
+       EPB_VAL = 0xFF66,\r
+       ESD_VAL = 0xFF67,\r
+       EPC_VAL = 0xFF68,\r
+       RED_VAL = 0xFF69\r
+#else\r
+       EPB_VAL = 0xFF96,\r
+       ESD_VAL = 0xFF98,\r
+       EPC_VAL = 0xFF97,\r
+       RED_VAL = 0xFF99\r
+#endif\r
+};\r
+\r
+// All the markers in one vector\r
+unsigned short int marker_val[] = {\r
+       SOC_VAL, SOT_VAL, SOD_VAL, EOC_VAL,\r
+       SIZ_VAL,\r
+       COD_VAL, COC_VAL, RGN_VAL, QCD_VAL, QCC_VAL, POD_VAL,\r
+       TLM_VAL, PLM_VAL, PLT_VAL, PPM_VAL, PPT_VAL,\r
+       SOP_VAL, EPH_VAL,\r
+       CME_VAL,\r
+       EPB_VAL, ESD_VAL, EPC_VAL, RED_VAL\r
+};\r
+\r
+// Marker names\r
+char *marker_name[] = {\r
+       "SOC", "SOT", "SOD", "EOC",\r
+       "SIZ",\r
+       "COD", "COC", "RGN", "QCD", "QCC", "POD",\r
+       "TLM", "PLM", "PLT", "PPM", "PPT",\r
+       "SOP", "EPH",\r
+       "CME",\r
+       "EPB", "ESD", "EPC", "RED"\r
+};\r
+\r
+// Marker descriptions\r
+char *marker_descr[] = {\r
+       "Start of codestream", "Start of tile-part", "Start of data", "End of codestream",\r
+       "Image and tile size",\r
+       "Coding style default", "Coding style component", "Region-of-interest", "Quantization default",\r
+       "Quantization component", "Progression order change, default",\r
+       "Tile-part lengths, main header", "Packet length, main header", "Packets length, tile-part header",\r
+       "Packed packet headers, main header", "Packed packet headers, tile-part header",\r
+       "Start of packet", "End of packet header",\r
+       "Comment and extension",\r
+       "Error Protection Block", "Error Sensitivity Descriptor", "Error Protection Capability",\r
+       "Residual Errors Descriptor"\r
+};\r
+\r
+void OPJParseThread::ParseJ2KFile(wxFile *m_file, wxFileOffset offset, wxFileOffset length, wxTreeItemId parentid)\r
+{\r
+       // check if the file is opened\r
+       if (m_file->IsOpened())\r
+               WriteText(wxT("File OK"));\r
+       else\r
+               return;\r
+\r
+       // position at the beginning\r
+       m_file->Seek(offset, wxFromStart);\r
+\r
+       //WriteText(wxString::Format(wxT("from  to %d"), length));\r
+\r
+       // navigate the file\r
+       int m, inside_sod = 0, nmarks = 0, maxmarks = 10000, done = 0;\r
+       unsigned char onebyte[1];\r
+       unsigned char twobytes[2];\r
+       unsigned char fourbytes[4];\r
+       unsigned short int currmark;\r
+       unsigned short int currlen;\r
+       int lastPsot = 0, lastsotpos = 0;\r
+\r
+       WriteText(wxT("Start search..."));\r
+       while ((offset < length) && (!m_file->Eof())) {\r
+\r
+               done = 0;\r
+\r
+               // read da marka\r
+               if (m_file->Read(twobytes, 2) != 2)\r
+                       break;\r
+               currmark = (((unsigned short int) twobytes[0]) << 8) + (unsigned short int) twobytes[1];\r
+\r
+               // Markers cycle\r
+               for (m = 0; m < 23; m++) {\r
+\r
+                       // check the marker\r
+                       if (currmark == marker_val[m]) {\r
+\r
+                               if (currmark == SOD_VAL) {\r
+\r
+                                       // we enter SOD\r
+                                       currlen = 0;\r
+                                       inside_sod = 1;\r
+\r
+                               } else if ((currmark == SOC_VAL) || (currmark == EOC_VAL) || (currmark == EPH_VAL))\r
+                                       \r
+                                       currlen = 0;\r
+\r
+                               else {\r
+\r
+                                       // read length\r
+                                       if (m_file->Read(twobytes, 2) != 2)\r
+                                               break;\r
+                                       currlen = (((unsigned short int) twobytes[0]) << 8) + (unsigned short int) twobytes[1];\r
+\r
+                               }\r
+\r
+                               // inside SOD, only some markers are allowed\r
+                               if (inside_sod && (currmark != SOD_VAL) && (currmark != SOT_VAL)\r
+                                       && (currmark != EOC_VAL) && (currmark != SOP_VAL) && (currmark != EPH_VAL))\r
+                                       break; /*randomly marker coincident data */\r
+\r
+                               if (inside_sod && (currmark == SOT_VAL) && (lastPsot == 0))\r
+                                       inside_sod = 0; /* random data coincident with SOT, but last SOT was the last one */\r
+\r
+                               if (inside_sod && (currmark == SOT_VAL))\r
+                                       inside_sod = 0; /* new tile part */\r
+\r
+                               // here we pass to AppendItem() normal and selected item images (we\r
+                               // suppose that selected image follows the normal one in the enum)\r
+                               int image, imageSel;\r
+                               image = m_tree->TreeCtrlIcon_Folder;\r
+                               imageSel = image + 1;\r
+\r
+                               // append the marker\r
+                               wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format(wxT("%03d: %s (0x%04X)"), nmarks, marker_name[m], marker_val[m]),\r
+                                       image, imageSel,\r
+                                       new OPJMarkerData(wxT("MARK"), m_tree->m_fname.GetFullPath(), offset, offset + currlen + 1)\r
+                                       );\r
+\r
+                               // append some info\r
+                               image = m_tree->TreeCtrlIcon_File;\r
+                               imageSel = image + 1;\r
+\r
+                               // marker name\r
+                               wxTreeItemId subcurrid1 = m_tree->AppendItem(currid,\r
+                                       wxT("*** ") + wxString(marker_descr[m]) + wxT(" ***"),\r
+                                       image, imageSel,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+                               m_tree->SetItemFont(subcurrid1, *wxITALIC_FONT);\r
+\r
+                               // position and length\r
+                               wxTreeItemId subcurrid2 = m_tree->AppendItem(currid,\r
+                                       wxLongLong(offset).ToString() + wxT(" > ") + wxLongLong(offset + currlen + 1).ToString() + \r
+                                       wxT(", ") + wxString::Format(wxT("%d + 2 (%d)"), currlen, currlen + 2),\r
+                                       image, imageSel,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+\r
+                               // give additional info on markers\r
+                               switch (currmark) {\r
+                                       \r
+                               case SOP_VAL:\r
+                                       {\r
+                                       // read packet number\r
+                                       if (m_file->Read(twobytes, 2) != 2)\r
+                                               break;\r
+                                       int packnum = STREAM_TO_UINT16(twobytes, 0);;\r
+                                       wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,\r
+                                               wxString::Format(wxT("Pack. no. %d"), packnum),\r
+                                               image, imageSel,\r
+                                               new OPJMarkerData(wxT("INFO"))\r
+                                               );\r
+                                       }\r
+                                       break;\r
+\r
+                               case SIZ_VAL:\r
+                                       {\r
+                                       m_file->Seek(2, wxFromCurrent);\r
+                                       if (m_file->Read(fourbytes, 4) != 4)\r
+                                               break;\r
+                                       unsigned long int xsiz = STREAM_TO_UINT32(fourbytes, 0);\r
+\r
+                                       if (m_file->Read(fourbytes, 4) != 4)\r
+                                               break;\r
+                                       unsigned long int ysiz = STREAM_TO_UINT32(fourbytes, 0);\r
+\r
+                                       m_file->Seek(24, wxFromCurrent);\r
+                                       if (m_file->Read(twobytes, 2) != 2)\r
+                                               break;\r
+                                       unsigned short int csiz = STREAM_TO_UINT16(twobytes, 0);\r
+\r
+                                       if (m_file->Read(onebyte, 1) != 1)\r
+                                               break;\r
+                                       unsigned char ssiz = onebyte[0];\r
+\r
+                                       wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,\r
+                                               wxString::Format(wxT("%d x %d, %d comps. @ %d bpp"), xsiz, ysiz, csiz, (ssiz + 1) & 0xEF),\r
+                                               image, imageSel,\r
+                                               new OPJMarkerData(wxT("INFO"))\r
+                                               );\r
+\r
+                                       }\r
+                                       break;\r
+\r
+                               case SOT_VAL:\r
+                                       {\r
+                                       if (m_file->Read(twobytes, 2) != 2)\r
+                                               break;\r
+                                       unsigned short int isot = STREAM_TO_UINT16(twobytes, 0);\r
+\r
+                                       if (m_file->Read(fourbytes, 4) != 4)\r
+                                               break;\r
+                                       unsigned long int psot = STREAM_TO_UINT32(fourbytes, 0);\r
+\r
+                                       if (m_file->Read(onebyte, 1) != 1)\r
+                                               break;\r
+                                       unsigned char tpsot = onebyte[0];\r
+\r
+                                       if (m_file->Read(onebyte, 1) != 1)\r
+                                               break;\r
+                                       unsigned char tnsot = onebyte[0];\r
+\r
+                                       wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,\r
+                                               wxString::Format(wxT("tile %d, psot = %d, part %d of %d"), isot, psot, tpsot, tnsot),\r
+                                               image, imageSel,\r
+                                               new OPJMarkerData(wxT("INFO"))\r
+                                               );\r
+\r
+                                       lastPsot = psot;\r
+                                       lastsotpos = offset;\r
+                                       };\r
+                                       break;\r
+\r
+                               case CME_VAL:\r
+                                       {\r
+                                       #define showlen 25\r
+                                       unsigned char comment[showlen];\r
+\r
+                                       m_file->Seek(2, wxFromCurrent);\r
+                                       if (m_file->Read(comment, showlen) != showlen)\r
+                                               break;\r
+\r
+                                       wxTreeItemId subcurrid3 = m_tree->AppendItem(currid,\r
+                                               wxString::Format(wxT("%.*s%s"), wxMin(showlen, currlen - 4), comment,\r
+                                               (((currlen - 4) > showlen) ? "..." : "")),\r
+                                               image, imageSel,\r
+                                               new OPJMarkerData(wxT("INFO"))\r
+                                               );\r
+                                       }\r
+                                       break;\r
+\r
+                               default:\r
+                                       break;\r
+                               }\r
+                               \r
+                               \r
+                               // increment number of markers\r
+                               nmarks++;\r
+                               if (nmarks >= maxmarks)\r
+                                       break;\r
+\r
+                               // increment offset\r
+                               if (currmark == SOD_VAL)\r
+                                       offset += lastPsot - (offset - lastsotpos);\r
+                               else\r
+                                       offset += (2 + currlen);\r
+\r
+                               m_file->Seek(offset, wxFromStart);\r
+                               done = 1;\r
+\r
+                               break;\r
+                       }\r
+               }\r
+\r
+               if (done)\r
+                       continue;\r
+               else {\r
+                       offset++;\r
+                       m_file->Seek(offset, wxFromStart);\r
+               }\r
+       }\r
+       \r
+}\r
diff --git a/OPJViewer/source/wxjp2parser.cpp b/OPJViewer/source/wxjp2parser.cpp
new file mode 100644 (file)
index 0000000..7d8f344
--- /dev/null
@@ -0,0 +1,851 @@
+/*\r
+ * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+#include "OPJViewer.h"\r
+\r
+/* defines */\r
+#define SHORT_DESCR_LEN        32\r
+#define LONG_DESCR_LEN         256\r
+\r
+/* enumeration for file formats */\r
+#define J2FILENUM              4\r
+typedef enum {\r
+\r
+        JP2_FILE,\r
+        J2K_FILE,\r
+               MJ2_FILE,\r
+               UNK_FILE\r
+\r
+} j2filetype;\r
+\r
+/* enumeration for the box types */\r
+#define J2BOXNUM                23\r
+typedef enum {\r
+\r
+                       FILE_BOX,\r
+                       JP_BOX,\r
+                       FTYP_BOX,\r
+                       JP2H_BOX,\r
+                       IHDR_BOX,\r
+                       COLR_BOX,\r
+                       JP2C_BOX,\r
+                       JP2I_BOX,\r
+                       XML_BOX,\r
+                       UUID_BOX,\r
+                       UINF_BOX,\r
+                       MOOV_BOX,\r
+                       MVHD_BOX,\r
+                       TRAK_BOX,\r
+                       TKHD_BOX,\r
+                       MDIA_BOX,\r
+                       MINF_BOX,\r
+                       STBL_BOX,\r
+                       STSD_BOX,\r
+                       MJP2_BOX,\r
+                       MDAT_BOX,\r
+                       ANY_BOX,\r
+                       UNK_BOX\r
+\r
+} j2boxtype;\r
+\r
+/* the box structure itself */\r
+struct boxdef {\r
+\r
+        char                  value[5];                 /* hexadecimal value/string*/\r
+               char                  name[SHORT_DESCR_LEN];    /* short description       */\r
+               char                  descr[LONG_DESCR_LEN];    /* long  description       */\r
+               int                   sbox;                     /* is it a superbox?       */\r
+               int                   req[J2FILENUM];           /* mandatory box           */\r
+               j2boxtype             ins;                      /* contained in box...     */\r
+\r
+};\r
+\r
+/* the possible boxes */\r
+struct boxdef j2box[];\r
+\r
+/* macro functions */\r
+/* From little endian to big endian, 2 and 4 bytes */\r
+#define        BYTE_SWAP2(X)   ((X & 0x00FF) << 8) | ((X & 0xFF00) >> 8)\r
+#define        BYTE_SWAP4(X)   ((X & 0x000000FF) << 24) | ((X & 0x0000FF00) << 8) | ((X & 0x00FF0000) >> 8) | ((X & 0xFF000000) >> 24)\r
+#define        BYTE_SWAP8(X)   (((X & 0x00000000000000FF) << 56) | ((X & 0x000000000000FF00) << 40) | \\r
+                        ((X & 0x0000000000FF0000) << 24) | ((X & 0x00000000FF000000) << 8) | \\r
+                                               ((X & 0x000000FF00000000) >> 8)  | ((X & 0x0000FF0000000000) >> 24) | \\r
+                                               ((X & 0x00FF000000000000) >> 40) | ((X & 0xFF00000000000000) >> 56))\r
+\r
+/* From codestream to int values */\r
+#define STREAM_TO_UINT32(C, P) (((unsigned long int) (C)[(P) + 0] << 24) + \\r
+                                                               ((unsigned long int) (C)[(P) + 1] << 16) + \\r
+                                                               ((unsigned long int) (C)[(P) + 2] << 8) + \\r
+                                                               ((unsigned long int) (C)[(P) + 3] << 0))\r
+\r
+#define STREAM_TO_UINT16(C, P) (((unsigned long int) (C)[(P) + 0] << 8) + \\r
+                                                               ((unsigned long int) (C)[(P) + 1] << 0))\r
+\r
+#define OPJREAD_LONG(F,L,N) { \\r
+                                                       if (F->Read(fourbytes, 4) < 4) { \\r
+                                                               wxLogMessage(wxT("Problem reading " N " from the file (file ended?)")); \\r
+                                                               return -1; \\r
+                                                       }; \\r
+                                                       L = STREAM_TO_UINT32(fourbytes, 0); \\r
+                                                       }\r
+\r
+/* handling functions */\r
+#define ITEM_PER_ROW   10\r
+\r
+//#define indprint     if (0) printf("%.*s", 2 * level + 9, indent), printf\r
+char    indent[] =  "                                                                   "\r
+                                       "                                                                   "\r
+                                       "                                                                   "\r
+                                       "                                                                   ";\r
+\r
+void indprint(wxString printout, int level)\r
+{\r
+       wxLogMessage(/*wxString::Format(wxT("%.*s"), 2 * level + 9, indent) + */printout);\r
+}\r
+\r
+/* Box handler function */\r
+int OPJParseThread::box_handler_function(int boxtype, wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit,\r
+                                                wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint)\r
+{\r
+       switch ((j2boxtype) boxtype) {\r
+\r
+\r
+       /* JPEG 2000 Signature box */\r
+       case (JP_BOX): {\r
+\r
+                       unsigned long int checkdata = 0;\r
+                       fileid->Read(&checkdata, sizeof(unsigned long int));\r
+                       checkdata = BYTE_SWAP4(checkdata);\r
+\r
+                       // add info\r
+                       wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Check data: %X -> %s"), checkdata, (checkdata == 0x0D0A870A) ? wxT("OK") : wxT("KO")),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+\r
+               };\r
+               break;\r
+\r
+\r
+       /* JPEG 2000 codestream box */\r
+       case (JP2C_BOX): {\r
+\r
+                       // add info\r
+                       wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                               wxString(wxT("Codestream")),\r
+                               m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1,\r
+                               new OPJMarkerData(wxT("INFO-CSTREAM"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)\r
+                               );\r
+\r
+                       m_tree->SetItemHasChildren(currid);\r
+\r
+                       // parse the file\r
+                       //ParseJ2KFile(fileid, filepoint, filelimit, currid);\r
+\r
+               };\r
+               break;\r
+\r
+\r
+\r
+\r
+\r
+       /* File Type box */\r
+       case (FTYP_BOX): {\r
+\r
+                       char BR[4], CL[4];\r
+                       unsigned long int MinV, numCL, i;\r
+                       fileid->Read(BR, sizeof(char) * 4);\r
+                       fileid->Read(&MinV, sizeof(unsigned long int));\r
+                       MinV = BYTE_SWAP4(MinV);\r
+                       numCL = (filelimit - fileid->Tell()) / 4;                               \r
+\r
+                       // add info\r
+                       wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Brand/Minor version: %.4s/%d"), BR, MinV),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+\r
+                       currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Compatibility list")),\r
+                               m_tree->TreeCtrlIcon_Folder, m_tree->TreeCtrlIcon_Folder + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+\r
+                       for (i = 0; i < numCL; i++) {\r
+                               fileid->Read(CL, sizeof(char) * 4);\r
+                               m_tree->AppendItem(currid,\r
+                                       wxString::Format(wxT("%.4s"), CL),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+                       };\r
+                       \r
+               };\r
+               break;\r
+\r
+\r
+\r
+       /* JP2 Header box */\r
+       case (IHDR_BOX): {\r
+\r
+                       unsigned long int height, width;\r
+                       unsigned short int nc;\r
+                       unsigned char bpc, C, UnkC, IPR;\r
+                       fileid->Read(&height, sizeof(unsigned long int));\r
+                       height = BYTE_SWAP4(height);\r
+                       fileid->Read(&width, sizeof(unsigned long int));\r
+                       width = BYTE_SWAP4(width);\r
+                       fileid->Read(&nc, sizeof(unsigned short int));\r
+                       nc = BYTE_SWAP2(nc);\r
+                       fileid->Read(&bpc, sizeof(unsigned char));\r
+                       fileid->Read(&C, sizeof(unsigned char));\r
+                       fileid->Read(&UnkC, sizeof(unsigned char));\r
+                       fileid->Read(&IPR, sizeof(unsigned char));\r
+                       \r
+                       // add info\r
+                       wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Dimensions: %d x %d x %d @ %d bpc"), width, height, nc, bpc + 1),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+\r
+                       currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Compression type: %d"), C),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+\r
+                       currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Colourspace unknown: %d"), UnkC),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+\r
+                       currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Intellectual Property Rights: %d"), IPR),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+                       \r
+               };\r
+               break;\r
+\r
+\r
+\r
+       /* Colour Specification box */\r
+       case (COLR_BOX): {\r
+\r
+                       unsigned char METH, PREC, APPROX;\r
+                       char methdescr[80], enumcsdescr[80];\r
+                       unsigned long int EnumCS;\r
+                       fileid->Read(&METH, sizeof(unsigned char));\r
+                       switch (METH) {\r
+                       case 1:\r
+                               strcpy(methdescr, "Enumerated Colourspace");\r
+                               break;\r
+                       case 2:\r
+                               strcpy(methdescr, "Restricted ICC profile");\r
+                               break;\r
+                       default:\r
+                               strcpy(methdescr, "Unknown");\r
+                               break;\r
+                       };\r
+                       fileid->Read(&PREC, sizeof(unsigned char));\r
+                       fileid->Read(&APPROX, sizeof(unsigned char));\r
+                       if (METH != 2) {\r
+                               fileid->Read(&EnumCS, sizeof(unsigned long int));\r
+                               EnumCS = BYTE_SWAP4(EnumCS);\r
+                               switch (EnumCS) {\r
+                               case 16:\r
+                                       strcpy(enumcsdescr, "sRGB");\r
+                                       break;\r
+                               case 17:\r
+                                       strcpy(enumcsdescr, "greyscale");\r
+                                       break;\r
+                               case 18:\r
+                                       strcpy(enumcsdescr, "sYCC");\r
+                                       break;\r
+                               default:\r
+                                       strcpy(enumcsdescr, "Unknown");\r
+                                       break;\r
+                               };\r
+                       };\r
+\r
+                       // add info\r
+                       wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Specification method: %d (%s)"), METH, methdescr),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+\r
+                       currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Precedence: %d"), PREC),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+\r
+                       currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Colourspace approximation: %d"), APPROX),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+\r
+                       if (METH != 2)\r
+                               currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format(wxT("Enumerated colourspace: %d (%s)"), EnumCS, enumcsdescr),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+\r
+                       if (METH != 1)\r
+                               currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format("ICC profile: there is one"),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+\r
+\r
+               };\r
+               break;\r
+\r
+\r
+\r
+\r
+               \r
+\r
+       /* Movie Header Box */\r
+       case (MVHD_BOX): {\r
+\r
+                       unsigned long int version, rate, matrix[9], next_track_ID;\r
+                       unsigned short int volume;\r
+                       fileid->Read(&version, sizeof(unsigned long int));\r
+                       version = BYTE_SWAP4(version);\r
+                       if (version == 0) {\r
+                               unsigned long int creation_time, modification_time, timescale, duration;\r
+                               fileid->Read(&creation_time, sizeof(unsigned long int));\r
+                               creation_time = BYTE_SWAP4(creation_time);\r
+                               fileid->Read(&modification_time, sizeof(unsigned long int));\r
+                               modification_time = BYTE_SWAP4(modification_time);\r
+                               fileid->Read(&timescale, sizeof(unsigned long int));\r
+                               timescale = BYTE_SWAP4(timescale);\r
+                               fileid->Read(&duration, sizeof(unsigned long int));\r
+                               duration = BYTE_SWAP4(duration);\r
+                               const long unix_time = creation_time - 2082844800L;\r
+                               wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format(wxT("Creation time: %u (%.24s)"), creation_time, ctime(&unix_time)),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+                               const long unix_time1 = modification_time - 2082844800L;\r
+                               currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format(wxT("Modification time: %u (%.24s)"), modification_time, ctime(&unix_time1)),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+                               currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format(wxT("Timescale: %u (%.6fs)"), timescale, 1.0 / (float) timescale),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+                               currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format(wxT("Duration: %u (%.3fs)"), duration, (float) duration / (float) timescale),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+                       } else {\r
+                               unsigned __int64 creation_time, modification_time, duration;\r
+                               unsigned long int timescale;\r
+                               fileid->Read(&creation_time, sizeof(unsigned __int64));\r
+                               creation_time = BYTE_SWAP8(creation_time);\r
+                               fileid->Read(&modification_time, sizeof(unsigned __int64));\r
+                               modification_time = BYTE_SWAP8(modification_time);\r
+                               fileid->Read(&timescale, sizeof(unsigned long int));\r
+                               timescale = BYTE_SWAP4(timescale);\r
+                               fileid->Read(&duration, sizeof(unsigned __int64));\r
+                               duration = BYTE_SWAP8(duration);\r
+                               wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format(wxT("Creation time: %u"), creation_time),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+                               currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format(wxT("Modification time: %u"), modification_time),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+                               currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format(wxT("Timescale: %u"), timescale),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+                               currid = m_tree->AppendItem(parentid,\r
+                                       wxString::Format(wxT("Duration: %u"), duration),\r
+                                       m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                                       new OPJMarkerData(wxT("INFO"))\r
+                                       );\r
+                       };\r
+                       fileid->Read(&rate, sizeof(unsigned long int));\r
+                       rate = BYTE_SWAP4(rate);\r
+                       fileid->Read(&volume, sizeof(unsigned short int));\r
+                       volume = BYTE_SWAP2(volume);\r
+                       fileid->Seek(6, wxFromCurrent);\r
+                       fileid->Read(&matrix, sizeof(unsigned char) * 9);\r
+                       fileid->Seek(4, wxFromCurrent);\r
+                       fileid->Read(&next_track_ID, sizeof(unsigned long int));\r
+                       next_track_ID = BYTE_SWAP4(next_track_ID);\r
+                       wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Rate: %d (%d.%d)"), rate, rate >> 16, rate & 0x0000FFFF),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+                       currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Volume: %d (%d.%d)"), volume, volume >> 8, volume & 0x00FF),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+                       currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Next track ID: %d"), next_track_ID),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+               };\r
+               break;\r
+\r
+\r
+                       /* Sample Description box */\r
+       case (STSD_BOX): {\r
+\r
+                       unsigned long int version, entry_count;\r
+                       fileid->Read(&version, sizeof(unsigned long int));\r
+                       version = BYTE_SWAP4(version);\r
+                       fileid->Read(&entry_count, sizeof(unsigned long int));\r
+                       entry_count = BYTE_SWAP4(entry_count);\r
+                       wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Entry count: %d"), entry_count),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)\r
+                               );\r
+                       jpeg2000parse(fileid, filepoint + 8, filelimit, parentid, level + 1, scansign, scanpoint);\r
+               };\r
+               break;\r
+\r
+\r
+\r
+                       /* MJP2 Sample Description box */\r
+       case (MJP2_BOX): {\r
+\r
+                       unsigned short int height, width, depth;\r
+                       unsigned long int horizresolution, vertresolution;\r
+                       char compressor_name[32];\r
+                       fileid->Seek(24, wxFromCurrent);\r
+                       fileid->Read(&width, sizeof(unsigned short int));\r
+                       width = BYTE_SWAP2(width);\r
+                       fileid->Read(&height, sizeof(unsigned short int));\r
+                       height = BYTE_SWAP2(height);\r
+                       fileid->Read(&horizresolution, sizeof(unsigned long int));\r
+                       horizresolution = BYTE_SWAP4(horizresolution);\r
+                       fileid->Read(&vertresolution, sizeof(unsigned long int));\r
+                       vertresolution = BYTE_SWAP4(vertresolution);\r
+                       fileid->Seek(6, wxFromCurrent);\r
+                       fileid->Read(compressor_name, sizeof(char) * 32);\r
+                       fileid->Read(&depth, sizeof(unsigned short int));\r
+                       depth = BYTE_SWAP2(depth);\r
+                       wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Dimensions: %d x %d @ %d bpp"), width, height, depth),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"), m_tree->m_fname.GetFullPath(), filepoint, filelimit)\r
+                               );\r
+                       currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Resolution: %d.%d x %d.%d"), horizresolution >> 16, horizresolution & 0x0000FFFF,\r
+                               vertresolution >> 16, vertresolution & 0x0000FFFF),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+                       currid = m_tree->AppendItem(parentid,\r
+                               wxString::Format(wxT("Compressor: %.32s"), compressor_name),\r
+                               m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,\r
+                               new OPJMarkerData(wxT("INFO"))\r
+                               );\r
+                       jpeg2000parse(fileid, filepoint + 78, filelimit, parentid, level + 1, scansign, scanpoint);\r
+\r
+               };\r
+               break;\r
+\r
+               \r
+       /* not yet implemented */\r
+       default:\r
+               break;\r
+\r
+\r
+\r
+       };\r
+\r
+       return (0);\r
+}\r
+\r
+/* jp2 family box signatures */\r
+#define FILE_SIGN           ""\r
+#define JP_SIGN             "jP\040\040"\r
+#define FTYP_SIGN           "ftyp"\r
+#define JP2H_SIGN           "jp2h"\r
+#define IHDR_SIGN           "ihdr"\r
+#define COLR_SIGN           "colr"\r
+#define JP2C_SIGN           "jp2c"\r
+#define JP2I_SIGN           "jp2i"\r
+#define XML_SIGN            "xml\040"\r
+#define UUID_SIGN           "uuid"\r
+#define UINF_SIGN           "uinf"\r
+#define MOOV_SIGN           "moov"\r
+#define MVHD_SIGN           "mvhd"\r
+#define TRAK_SIGN           "trak"\r
+#define TKHD_SIGN           "tkhd"\r
+#define MDIA_SIGN           "mdia"\r
+#define MINF_SIGN           "minf"\r
+#define STBL_SIGN           "stbl"\r
+#define STSD_SIGN           "stsd"\r
+#define MJP2_SIGN           "mjp2"\r
+#define MDAT_SIGN           "mdat"\r
+#define ANY_SIGN                       ""\r
+#define UNK_SIGN            ""\r
+\r
+/* the possible boxes */\r
+struct boxdef j2box[] =\r
+{\r
+/* sign */     {FILE_SIGN,\r
+/* short */    "placeholder for nothing",\r
+/* long */     "Nothing to say",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {JP_SIGN,\r
+/* short */    "JPEG 2000 Signature box",\r
+/* long */     "This box uniquely identifies the file as being part of the JPEG 2000 family of files",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {FTYP_SIGN,\r
+/* short */    "File Type box",\r
+/* long */     "This box specifies file type, version and compatibility information, including specifying if this file "\r
+                       "is a conforming JP2 file or if it can be read by a conforming JP2 reader",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {JP2H_SIGN,\r
+/* short */    "JP2 Header box",\r
+/* long */     "This box contains a series of boxes that contain header-type information about the file",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {IHDR_SIGN,\r
+/* short */    "Image Header box",\r
+/* long */     "This box specifies the size of the image and other related fields",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      JP2H_BOX},\r
+\r
+/* sign */     {COLR_SIGN,\r
+/* short */    "Colour Specification box",\r
+/* long */     "This box specifies the colourspace of the image",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      JP2H_BOX},\r
+\r
+/* sign */     {JP2C_SIGN,\r
+/* short */    "Contiguous Codestream box",\r
+/* long */     "This box contains the codestream as defined by Annex A",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {JP2I_SIGN,\r
+/* short */    "Intellectual Property box",\r
+/* long */     "This box contains intellectual property information about the image",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {XML_SIGN,\r
+/* short */    "XML box",\r
+/* long */     "This box provides a tool by which vendors can add XML formatted information to a JP2 file",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {UUID_SIGN,\r
+/* short */    "UUID box",\r
+/* long */     "This box provides a tool by which vendors can add additional information to a file "\r
+                       "without risking conflict with other vendors",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {UINF_SIGN,\r
+/* short */    "UUID Info box",\r
+/* long */     "This box provides a tool by which a vendor may provide access to additional information associated with a UUID",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {MOOV_SIGN,\r
+/* short */    "Movie box",\r
+/* long */     "This box contains the media data. In video tracks, this box would contain JPEG2000 video frames",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {MVHD_SIGN,\r
+/* short */    "Movie Header box",\r
+/* long */     "This box defines overall information which is media-independent, and relevant to the entire presentation "\r
+                       "considered as a whole",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MOOV_BOX},\r
+\r
+/* sign */     {TRAK_SIGN,\r
+/* short */    "Track box",\r
+/* long */     "This is a container box for a single track of a presentation. A presentation may consist of one or more tracks",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MOOV_BOX},\r
+\r
+/* sign */     {TKHD_SIGN,\r
+/* short */    "Track Header box",\r
+/* long */     "This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      TRAK_BOX},\r
+\r
+/* sign */     {MDIA_SIGN,\r
+/* short */    "Media box",\r
+/* long */     "The media declaration container contains all the objects which declare information about the media data "\r
+                       "within a track",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      TRAK_BOX},\r
+\r
+/* sign */     {MINF_SIGN,\r
+/* short */    "Media Information box",\r
+/* long */     "This box contains all the objects which declare characteristic information of the media in the track",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MDIA_BOX},\r
+\r
+/* sign */     {STBL_SIGN,\r
+/* short */    "Sample Table box",\r
+/* long */     "The sample table contains all the time and data indexing of the media samples in a track",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MINF_BOX},\r
+\r
+/* sign */     {STSD_SIGN,\r
+/* short */    "Sample Description box",\r
+/* long */     "The sample description table gives detailed information about the coding type used, and any initialization "\r
+                       "information needed for that coding",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MINF_BOX},\r
+\r
+/* sign */     {MJP2_SIGN,\r
+/* short */    "MJP2 Sample Description box",\r
+/* long */     "The MJP2 sample description table gives detailed information about the coding type used, and any initialization "\r
+                       "information needed for that coding",\r
+/* sbox */     0,\r
+/* req */      {1, 1, 1},\r
+/* ins */      MINF_BOX},\r
+\r
+/* sign */     {MDAT_SIGN,\r
+/* short */    "Media Data box",\r
+/* long */     "The meta-data for a presentation is stored in the single Movie Box which occurs at the top-level of a file",\r
+/* sbox */     1,\r
+/* req */      {1, 1, 1},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {ANY_SIGN,\r
+/* short */    "Any box",\r
+/* long */     "All the existing boxes",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      FILE_BOX},\r
+\r
+/* sign */     {UNK_SIGN,\r
+/* short */    "Unknown Type box",\r
+/* long */     "The signature is not recognised to be that of an existing box",\r
+/* sbox */     0,\r
+/* req */      {0, 0, 0},\r
+/* ins */      ANY_BOX}\r
+\r
+};\r
+\r
+void OPJParseThread::ParseJP2File(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit, wxTreeItemId parentid)\r
+{\r
+       unsigned long int scanpoint;\r
+\r
+       jpeg2000parse(fileid, filepoint, filelimit, parentid, 0, NULL, &scanpoint);\r
+}\r
+\r
+/* the parsing function itself */\r
+/*\r
+  fileid    = fid of the file to scan (you should open it by yourself)\r
+  filepoint = first byte where to start to scan from (usually 0)\r
+  filelimit = first byte where to stop to scan from (usually the file size)\r
+  level     = set this to 0\r
+  scansign  = signature to scan for (NULL avoids search, returns "    " if successful)\r
+  scanpoint = point where the scan signature lies\r
+*/\r
+int OPJParseThread::jpeg2000parse(wxFile *fileid, wxFileOffset filepoint, wxFileOffset filelimit,\r
+                                                                 wxTreeItemId parentid, int level, char *scansign, unsigned long int *scanpoint)\r
+{\r
+       unsigned long int       LBox = 0x00000000;\r
+       int                     LBox_read;\r
+       char                    TBox[5] = "\0\0\0\0";\r
+       int                     TBox_read;\r
+       __int64              XLBox = 0x0000000000000000;\r
+       int                     XLBox_read;\r
+       unsigned long int       box_length = 0;\r
+       int                     last_box = 0, box_num = 0;\r
+       int                     box_type = ANY_BOX;\r
+       unsigned char           onebyte[1], twobytes[2], fourbytes[4];\r
+\r
+       /* cycle all over the file */\r
+       box_num = 0;\r
+       last_box = 0;\r
+       while (!last_box) {\r
+\r
+               /* do not exceed file limit */\r
+               if (filepoint >= filelimit)\r
+                       return (0);\r
+\r
+               /* seek on file */\r
+               if (fileid->Seek(filepoint, wxFromStart) == wxInvalidOffset)\r
+                       return (-1);\r
+\r
+               /* read the mandatory LBox, 4 bytes */\r
+               if (fileid->Read(fourbytes, 4) < 4) {\r
+                       WriteText(wxT("Problem reading LBox from the file (file ended?)"));\r
+                       return -1;\r
+               };\r
+               LBox = STREAM_TO_UINT32(fourbytes, 0);\r
+\r
+               /* read the mandatory TBox, 4 bytes */\r
+               if (fileid->Read(TBox, 4) < 4) {\r
+                       WriteText(wxT("Problem reading TBox from the file (file ended?)"));\r
+                       return -1;\r
+               };\r
+\r
+               /* look if scansign is got */\r
+               if ((scansign != NULL) && (memcmp(TBox, scansign, 4) == 0)) {\r
+                       memcpy(scansign, "    ", 4);\r
+                       *scanpoint = filepoint;\r
+\r
+                       /* hack/exploit */\r
+                       // stop as soon as you find the codebox\r
+                       return (0);\r
+\r
+               };\r
+\r
+               /* determine the box type */\r
+               for (box_type = JP_BOX; box_type < UNK_BOX; box_type++)\r
+                       if (memcmp(TBox, j2box[box_type].value, 4) == 0)\r
+                               break;  \r
+\r
+               /* read the optional XLBox, 8 bytes */\r
+               if (LBox == 1) {\r
+\r
+                       if (fileid->Read(&XLBox, 8) < 8) {\r
+                               WriteText(wxT("Problem reading XLBox from the file (file ended?)"));\r
+                               return -1;\r
+                       };\r
+                       box_length = (unsigned long int) BYTE_SWAP8(XLBox);\r
+\r
+               } else if (LBox == 0x00000000) {\r
+\r
+                       /* last box in file */\r
+                       last_box = 1; \r
+                       box_length = filelimit - filepoint;\r
+\r
+               } else\r
+\r
+                       box_length = LBox;\r
+\r
+               /* show box info */\r
+\r
+               // append the marker\r
+               int image, imageSel;\r
+               image = m_tree->TreeCtrlIcon_Folder;\r
+               imageSel = image + 1;\r
+               wxTreeItemId currid = m_tree->AppendItem(parentid,\r
+                       wxString::Format(wxT("%03d: %s (0x%04X)"), box_num, TBox,\r
+                               ((unsigned long int) TBox[3]) + ((unsigned long int) TBox[2] << 8) +\r
+                               ((unsigned long int) TBox[1] << 16) + ((unsigned long int) TBox[0] << 24)\r
+                       ),\r
+                       image, imageSel,\r
+                       new OPJMarkerData(wxT("BOX"), m_tree->m_fname.GetFullPath(), filepoint, filepoint + box_length)\r
+                       );\r
+\r
+               // append some info\r
+               image = m_tree->TreeCtrlIcon_File;\r
+               imageSel = image + 1;\r
+\r
+               // box name\r
+               wxTreeItemId subcurrid1 = m_tree->AppendItem(currid,\r
+                       wxT("*** ") + wxString(j2box[box_type].name) + wxT(" ***"),\r
+                       image, imageSel,\r
+                       new OPJMarkerData(wxT("INFO"))\r
+                       );\r
+               m_tree->SetItemFont(subcurrid1, *wxITALIC_FONT);\r
+\r
+               // position and length\r
+               wxTreeItemId subcurrid2 = m_tree->AppendItem(currid,\r
+                       wxLongLong(filepoint).ToString() + wxT(" > ") + wxLongLong(filepoint + box_length - 1).ToString() + \r
+                       wxT(", ") + wxString::Format(wxT("%d + 8 (%d)"), box_length, box_length + 8),\r
+                       image, imageSel,\r
+                       new OPJMarkerData(wxT("INFO"))\r
+                       );\r
+\r
+               /* go deep in the box */\r
+               box_handler_function((int) box_type, fileid, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length,\r
+                       currid, level, scansign, scanpoint);\r
+\r
+               /* if it's a superbox go inside it */\r
+               if (j2box[box_type].sbox)\r
+                       jpeg2000parse(fileid, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length,\r
+                               currid, level + 1, scansign, scanpoint);\r
+\r
+               /* increment box number and filepoint*/\r
+               box_num++;\r
+               filepoint += box_length;\r
+\r
+       };\r
+\r
+       /* all good */\r
+       return (0);\r
+}\r
+\r