summaryrefslogtreecommitdiff
path: root/OPJViewer/source
diff options
context:
space:
mode:
authorGiuseppe Baruffa <gbaruffa@users.noreply.github.com>2007-08-02 12:45:28 +0000
committerGiuseppe Baruffa <gbaruffa@users.noreply.github.com>2007-08-02 12:45:28 +0000
commit9cf692e89773ac83cebbb2969039913ce761c11d (patch)
treeb898526c52dc07cfe15c3f180d6ba4cbcf7320ab /OPJViewer/source
parent4f4aa1d49fc261185085a86c80e8b06e46a7d5db (diff)
Added a basic saving capability to OPJViewer
Diffstat (limited to 'OPJViewer/source')
-rw-r--r--OPJViewer/source/OPJViewer.cpp465
-rw-r--r--OPJViewer/source/OPJViewer.h53
-rw-r--r--OPJViewer/source/build.h2
-rw-r--r--OPJViewer/source/imagj2k.cpp264
-rw-r--r--OPJViewer/source/imagj2k.h69
-rw-r--r--OPJViewer/source/wxjp2parser.cpp127
6 files changed, 880 insertions, 100 deletions
diff --git a/OPJViewer/source/OPJViewer.cpp b/OPJViewer/source/OPJViewer.cpp
index 1e1ef647..8253f90b 100644
--- a/OPJViewer/source/OPJViewer.cpp
+++ b/OPJViewer/source/OPJViewer.cpp
@@ -235,6 +235,25 @@ bool OPJViewerApp::OnInit(void)
OPJconfig->Read(wxT("peekerheight"), &m_peekerheight, (long) OPJ_PEEKER_HEIGHT);
OPJconfig->Read(wxT("framewidth"), &m_framewidth, (long) OPJ_FRAME_WIDTH);
OPJconfig->Read(wxT("frameheight"), &m_frameheight, (long) OPJ_FRAME_HEIGHT);
+
+ // load encoding engine parameters
+ OPJconfig->Read(wxT("subsampling"), &m_subsampling, (wxString) wxT("1,1"));
+ OPJconfig->Read(wxT("origin"), &m_origin, (wxString) wxT("0,0"));
+ OPJconfig->Read(wxT("rates"), &m_rates, (wxString) wxT("20,10,5"));
+ OPJconfig->Read(wxT("quality"), &m_quality, (wxString) wxT("30,35,40"));
+ OPJconfig->Read(wxT("irreversible"), &m_irreversible, (bool) false);
+ OPJconfig->Read(wxT("resolutions"), &m_resolutions, (int) 6);
+ OPJconfig->Read(wxT("cbsize"), &m_cbsize, (wxString) wxT("32,32"));
+ OPJconfig->Read(wxT("prsize"), &m_prsize, (wxString) wxT("[128,128],[128,128]"));
+ OPJconfig->Read(wxT("tsize"), &m_tsize, (wxString) wxT(""));
+ OPJconfig->Read(wxT("torigin"), &m_torigin, (wxString) wxT("0,0"));
+ OPJconfig->Read(wxT("enablesop"), &m_enablesop, (bool) false);
+ OPJconfig->Read(wxT("enableeph"), &m_enableeph, (bool) false);
+ OPJconfig->Read(wxT("enablecomm"), &m_enablecomm, (bool) true);
+ OPJconfig->Read(wxT("comment"), &m_comment, (wxString) wxT(""));
+ OPJconfig->Read(wxT("enableidx"), &m_enableidx, (bool) false);
+ OPJconfig->Read(wxT("index"), &m_index, (wxString) wxT("index.txt"));
+
#else
// set decoding engine parameters
m_enabledeco = true;
@@ -256,8 +275,43 @@ bool OPJViewerApp::OnInit(void)
m_peekerheight = OPJ_PEEKER_HEIGHT;
m_framewidth = OPJ_FRAME_WIDTH;
m_frameheight = OPJ_FRAME_HEIGHT;
+
+ // set encoding engine parameters
+ m_subsampling = wxT("1,1");
+ m_origin = wxT("0,0");
+ m_rates = wxT("20,10,5");
+ m_quality = wxT("30,35,40");
+ m_irreversible = false;
+ m_resolutions = 6;
+ m_cbsize= wxT("32,32");
+ m_prsize= wxT("[128,128],[128,128]");
+ m_tsize = wxT("");
+ m_torigin = wxT("0,0");
+ m_enablesop = false;
+ m_enableeph = false;
+ m_enableidx = false;
+ m_index = wxT("index.txt");
+ m_enablecomm = true;
+ m_comment = wxT("");
+
#endif // OPJ_INICONFIG
+ if (m_comment == wxT("")) {
+#if defined __WXMSW__
+ m_comment = wxT("Created by OPJViewer Win32 - OpenJPEG version ");
+#elif defined __WXGTK__
+ m_comment = wxT("Created by OPJViewer Lin32 - OpenJPEG version ");
+#else
+ m_comment = wxT("Created by OPJViewer - OpenJPEG version ");
+#endif
+
+#ifdef USE_JPWL
+ m_comment += wxString::Format("%s with JPWL", opj_version());
+#else
+ m_comment += wxString::Format("%s", opj_version());
+#endif
+ }
+
// Create the main frame window
OPJFrame *frame = new OPJFrame(NULL, wxID_ANY, OPJ_APPLICATION_TITLEBAR,
wxDefaultPosition, wxSize(wxGetApp().m_framewidth, wxGetApp().m_frameheight),
@@ -310,6 +364,24 @@ int OPJViewerApp::OnExit()
OPJconfig->Write(wxT("peekerheight"), m_peekerheight);
OPJconfig->Write(wxT("framewidth"), m_framewidth);
OPJconfig->Write(wxT("frameheight"), m_frameheight);
+
+ OPJconfig->Write(wxT("subsampling"), m_subsampling);
+ OPJconfig->Write(wxT("origin"), m_origin);
+ OPJconfig->Write(wxT("rates"), m_rates);
+ OPJconfig->Write(wxT("quality"), m_quality);
+ OPJconfig->Write(wxT("irreversible"), m_irreversible);
+ OPJconfig->Write(wxT("resolutions"), m_resolutions);
+ OPJconfig->Write(wxT("cbsize"), m_cbsize);
+ OPJconfig->Write(wxT("prsize"), m_prsize);
+ OPJconfig->Write(wxT("tiles"), m_tsize);
+ OPJconfig->Write(wxT("torigin"), m_torigin);
+ OPJconfig->Write(wxT("enablesop"), m_enablesop);
+ OPJconfig->Write(wxT("enableeph"), m_enableeph);
+ OPJconfig->Write(wxT("enableidx"), m_enableidx);
+ OPJconfig->Write(wxT("index"), m_index);
+ OPJconfig->Write(wxT("enablecomm"), m_enablecomm);
+ OPJconfig->Write(wxT("comment"), m_comment);
+
#endif // OPJ_INICONFIG
return 1;
@@ -332,6 +404,8 @@ void OPJViewerApp::ShowCmdLine(const wxCmdLineParser& parser)
BEGIN_EVENT_TABLE(OPJFrame, wxMDIParentFrame)
EVT_MENU(OPJFRAME_HELPABOUT, OPJFrame::OnAbout)
EVT_MENU(OPJFRAME_FILEOPEN, OPJFrame::OnFileOpen)
+ EVT_MENU(OPJFRAME_FILESAVEAS, OPJFrame::OnFileSaveAs)
+ EVT_MENU(OPJFRAME_MEMORYOPEN, OPJFrame::OnMemoryOpen)
EVT_SIZE(OPJFrame::OnSize)
EVT_MENU(OPJFRAME_FILEEXIT, OPJFrame::OnQuit)
EVT_MENU(OPJFRAME_FILECLOSE, OPJFrame::OnClose)
@@ -361,9 +435,19 @@ OPJFrame::OPJFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
file_menu->Append(OPJFRAME_FILEOPEN, wxT("&Open\tCtrl+O"));
file_menu->SetHelpString(OPJFRAME_FILEOPEN, wxT("Open one or more files"));
+ file_menu->Append(OPJFRAME_MEMORYOPEN, wxT("&Memory\tCtrl+M"));
+ file_menu->SetHelpString(OPJFRAME_MEMORYOPEN, wxT("Open a memory buffer"));
+
+ file_menu->Append(OPJFRAME_FILECLOSE, wxT("&Close\tCtrl+C"));
+ file_menu->SetHelpString(OPJFRAME_FILECLOSE, wxT("Close current image"));
+
+ file_menu->AppendSeparator();
+
file_menu->Append(OPJFRAME_FILESAVEAS, wxT("&Save as\tCtrl+S"));
file_menu->SetHelpString(OPJFRAME_FILESAVEAS, wxT("Save the current image"));
- file_menu->Enable(OPJFRAME_FILESAVEAS, false);
+ //file_menu->Enable(OPJFRAME_FILESAVEAS, false);
+
+ file_menu->AppendSeparator();
file_menu->Append(OPJFRAME_FILETOGGLEB, wxT("Toggle &browser\tCtrl+B"));
file_menu->SetHelpString(OPJFRAME_FILETOGGLEB, wxT("Toggle the left browsing pane"));
@@ -374,8 +458,7 @@ OPJFrame::OPJFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
file_menu->Append(OPJFRAME_FILETOGGLET, wxT("Toggle &toolbar\tCtrl+T"));
file_menu->SetHelpString(OPJFRAME_FILETOGGLET, wxT("Toggle the toolbar"));
- file_menu->Append(OPJFRAME_FILECLOSE, wxT("&Close\tCtrl+C"));
- file_menu->SetHelpString(OPJFRAME_FILECLOSE, wxT("Close current image"));
+ file_menu->AppendSeparator();
file_menu->Append(OPJFRAME_FILEEXIT, wxT("&Exit\tCtrl+Q"));
file_menu->SetHelpString(OPJFRAME_FILEEXIT, wxT("Quit this program"));
@@ -459,7 +542,7 @@ OPJFrame::OPJFrame(wxWindow *parent, const wxWindowID id, const wxString& title,
tool_bar->AddTool(OPJFRAME_FILEOPEN, bmpOpen, wxT("Open"));
tool_bar->AddTool(OPJFRAME_FILESAVEAS, bmpSaveAs, wxT("Save as "));
- tool_bar->EnableTool(OPJFRAME_FILESAVEAS, false);
+ //tool_bar->EnableTool(OPJFRAME_FILESAVEAS, false);
tool_bar->AddSeparator();
tool_bar->AddTool(OPJFRAME_VIEWZOOM, bmpZoom, wxT("Zoom"));
tool_bar->AddTool(OPJFRAME_VIEWFIT, bmpFit, wxT("Zoom to fit"));
@@ -614,6 +697,23 @@ void OPJFrame::OnSetsEnco(wxCommandEvent& event)
if (dialog.ShowModal() == wxID_OK) {
+ // load settings
+ wxGetApp().m_subsampling = dialog.m_subsamplingCtrl->GetValue();
+ wxGetApp().m_origin = dialog.m_originCtrl->GetValue();
+ wxGetApp().m_rates = dialog.m_rateCtrl->GetValue();
+ wxGetApp().m_quality = dialog.m_qualityCtrl->GetValue();
+ wxGetApp().m_irreversible = dialog.m_irrevCheck->GetValue();
+ wxGetApp().m_resolutions = dialog.m_resolutionsCtrl->GetValue();
+ wxGetApp().m_cbsize = dialog.m_cbsizeCtrl->GetValue();
+ wxGetApp().m_prsize = dialog.m_prsizeCtrl->GetValue();
+ wxGetApp().m_tsize = dialog.m_tsizeCtrl->GetValue();
+ wxGetApp().m_torigin = dialog.m_toriginCtrl->GetValue();
+ wxGetApp().m_enablesop = dialog.m_sopCheck->GetValue();
+ wxGetApp().m_enableeph = dialog.m_ephCheck->GetValue();
+ wxGetApp().m_enableidx = dialog.m_enableidxCheck->GetValue();
+ wxGetApp().m_index = dialog.m_indexCtrl->GetValue();
+ wxGetApp().m_enablecomm = dialog.m_enablecommCheck->GetValue();
+ wxGetApp().m_comment = dialog.m_commentCtrl->GetValue();
};
}
@@ -914,6 +1014,41 @@ void OPJFrame::OnSashDrag(wxSashEvent& event)
}
+// physically save the file
+void OPJFrame::SaveFile(wxArrayString paths, wxArrayString filenames)
+{
+ size_t count = paths.GetCount();
+ wxString msg, s;
+
+ if (wxFile::Exists(paths[0].c_str())) {
+
+ s.Printf(wxT("File %s already exists. Do you want to overwrite it?\n"), filenames[0].c_str());
+ wxMessageDialog dialog3(this, s, _T("File exists"), wxYES_NO);
+ if (dialog3.ShowModal() == wxID_NO)
+ return;
+ }
+
+ /*s.Printf(_T("File %d: %s (%s)\n"), (int)0, paths[0].c_str(), filenames[0].c_str());
+ msg += s;
+
+ wxMessageDialog dialog2(this, msg, _T("Selected files"));
+ dialog2.ShowModal();*/
+
+ if (!GetActiveChild())
+ return;
+
+ ((OPJChildFrame *) GetActiveChild())->m_canvas->m_savename = paths[0];
+
+ OPJEncoThread *ethread = ((OPJChildFrame *) GetActiveChild())->m_canvas->CreateEncoThread();
+
+ if (ethread->Run() != wxTHREAD_NO_ERROR)
+ wxLogMessage(wxT("Can't start enco thread!"));
+ else
+ wxLogMessage(wxT("New enco thread started."));
+
+
+}
+
// physically open the files
void OPJFrame::OpenFiles(wxArrayString paths, wxArrayString filenames)
{
@@ -994,6 +1129,48 @@ void OPJFrame::OnFileOpen(wxCommandEvent& WXUNUSED(event))
}
+void OPJFrame::OnFileSaveAs(wxCommandEvent& WXUNUSED(event))
+{
+ wxString wildcards =
+#ifdef wxUSE_LIBOPENJPEG
+#ifdef __WXMOTIF__
+ wxT("JPEG 2000 codestream (*.j2k)|*.*j*2*");
+#else
+ wxT("JPEG 2000 codestream (*.j2k)|*.j2k")
+ wxT("|JPEG 2000 file format (*.jp2)|*.jp2");
+#endif
+#endif
+
+ wxFileDialog dialog(this, _T("Save image file"),
+ wxEmptyString, wxEmptyString, wildcards,
+ wxFD_SAVE);
+
+ if (dialog.ShowModal() == wxID_OK) {
+ wxArrayString paths, filenames;
+
+ dialog.GetPaths(paths);
+ dialog.GetFilenames(filenames);
+
+ SaveFile(paths, filenames);
+ }
+
+
+}
+
+void OPJFrame::OnMemoryOpen(wxCommandEvent& WXUNUSED(event))
+{
+ wxTextEntryDialog dialog(this, wxT("Memory HEX address range: start_address-stop_address"),
+ wxT("Decode a memory buffer"),
+ wxT("0x-0x"),
+ wxOK | wxCANCEL | wxCENTRE,
+ wxDefaultPosition);
+
+ if (dialog.ShowModal() == wxID_OK) {
+
+ }
+
+}
+
BEGIN_EVENT_TABLE(OPJCanvas, wxScrolledWindow)
EVT_MOUSE_EVENTS(OPJCanvas::OnEvent)
END_EVENT_TABLE()
@@ -1036,6 +1213,19 @@ OPJDecoThread *OPJCanvas::CreateDecoThread(void)
return dthread;
}
+OPJEncoThread *OPJCanvas::CreateEncoThread(void)
+{
+ OPJEncoThread *ethread = new OPJEncoThread(this);
+
+ if (ethread->Create() != wxTHREAD_NO_ERROR)
+ wxLogError(wxT("Can't create enco thread!"));
+
+ wxCriticalSectionLocker enter(wxGetApp().m_enco_critsect);
+ wxGetApp().m_enco_threads.Add(ethread);
+
+ return ethread;
+}
+
#define activeoverlay 0
// Define the repainting behaviour
void OPJCanvas::OnDraw(wxDC& dc)
@@ -2056,6 +2246,95 @@ void OPJMarkerData::ShowInfo(wxTreeCtrl *tree)
}
/////////////////////////////////////////////////////////////////////
+// Encoding thread class
+/////////////////////////////////////////////////////////////////////
+
+OPJEncoThread::OPJEncoThread(OPJCanvas *canvas)
+ : wxThread()
+{
+ m_count = 0;
+ m_canvas = canvas;
+}
+
+void OPJEncoThread::WriteText(const wxString& text)
+{
+ wxString msg;
+
+ // before doing any GUI calls we must ensure that this thread is the only
+ // one doing it!
+
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif // __WXGTK__
+
+ msg << text;
+ m_canvas->WriteText(msg);
+
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif // __WXGTK__
+}
+
+void OPJEncoThread::OnExit()
+{
+ wxCriticalSectionLocker locker(wxGetApp().m_enco_critsect);
+
+ wxArrayThread& ethreads = wxGetApp().m_enco_threads;
+ ethreads.Remove(this);
+
+ if (ethreads.IsEmpty() )
+ {
+ // signal the main thread that there are no more threads left if it is
+ // waiting for us
+ if (wxGetApp().m_enco_waitingUntilAllDone) {
+ wxGetApp().m_enco_waitingUntilAllDone = false;
+ wxGetApp().m_enco_semAllDone.Post();
+ }
+ }
+}
+
+void *OPJEncoThread::Entry()
+{
+ wxString text;
+
+ srand(GetId());
+ //int m_countnum = rand() % 9;
+ //text.Printf(wxT("Deco thread 0x%lx started (priority = %u, time = %d)."),
+ // GetId(), GetPriority(), m_countnum);
+ text.Printf(wxT("Enco thread %d started"), m_canvas->m_childframe->m_winnumber);
+ WriteText(text);
+
+ // set handler properties
+ wxJ2KHandler *j2kkkhandler = (wxJ2KHandler *) wxImage::FindHandler( wxBITMAP_TYPE_J2K);
+ j2kkkhandler->m_subsampling = wxGetApp().m_subsampling;
+ j2kkkhandler->m_origin = wxGetApp().m_origin;
+ j2kkkhandler->m_rates = wxGetApp().m_rates;
+ j2kkkhandler->m_quality = wxGetApp().m_quality;
+ j2kkkhandler->m_irreversible = wxGetApp().m_irreversible;
+ j2kkkhandler->m_resolutions = wxGetApp().m_resolutions;
+ j2kkkhandler->m_cbsize = wxGetApp().m_cbsize;
+ j2kkkhandler->m_prsize = wxGetApp().m_prsize;
+ j2kkkhandler->m_tsize = wxGetApp().m_tsize;
+ j2kkkhandler->m_torigin = wxGetApp().m_torigin;
+ j2kkkhandler->m_enablesop = wxGetApp().m_enablesop;
+ j2kkkhandler->m_enableeph = wxGetApp().m_enableeph;
+ j2kkkhandler->m_enableidx = wxGetApp().m_enableidx;
+ j2kkkhandler->m_index = m_canvas->m_savename.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxGetApp().m_index;
+ j2kkkhandler->m_enablecomm = wxGetApp().m_enablecomm;
+ j2kkkhandler->m_comment = wxGetApp().m_comment;
+
+ // save the file
+ if (!m_canvas->m_image100.SaveFile(m_canvas->m_savename.GetFullPath(), wxBITMAP_TYPE_J2K)) {
+ WriteText(wxT("Can't save image"));
+ return NULL;
+ }
+
+ text.Printf(wxT("Enco thread %d finished"), m_canvas->m_childframe->m_winnumber);
+ WriteText(text);
+ return NULL;
+}
+
+/////////////////////////////////////////////////////////////////////
// Decoding thread class
/////////////////////////////////////////////////////////////////////
@@ -2698,6 +2977,8 @@ IMPLEMENT_CLASS(OPJEncoderDialog, wxPropertySheetDialog)
BEGIN_EVENT_TABLE(OPJEncoderDialog, wxPropertySheetDialog)
#ifdef USE_JPWL
EVT_CHECKBOX(OPJENCO_ENABLEJPWL, OPJEncoderDialog::OnEnableJPWL)
+ EVT_CHECKBOX(OPJENCO_ENABLECOMM, OPJEncoderDialog::OnEnableComm)
+ EVT_CHECKBOX(OPJENCO_ENABLEINDEX, OPJEncoderDialog::OnEnableIdx)
#endif // USE_JPWL
END_EVENT_TABLE()
@@ -2714,27 +2995,12 @@ OPJEncoderDialog::OPJEncoderDialog(wxWindow* win, int dialogType)
m_settingsNotebook = GetBookCtrl();
- wxPanel* mainSettings = CreateMainSettingsPage(m_settingsNotebook);
wxPanel* jpeg2000Settings = CreatePart1SettingsPage(m_settingsNotebook);
-/* if (!wxGetApp().m_enabledeco)
- jpeg2000Settings->Enable(false);
- wxPanel* mjpeg2000Settings = CreatePart3SettingsPage(m_settingsNotebook);
- if (!wxGetApp().m_enabledeco)
- mjpeg2000Settings->Enable(false);
-#ifdef USE_JPWL
- wxPanel* jpwlSettings = CreatePart11SettingsPage(m_settingsNotebook);
- if (!wxGetApp().m_enabledeco)
- jpwlSettings->Enable(false);
-#endif // USE_JPWL
-*/
+ wxPanel* mainSettings = CreateMainSettingsPage(m_settingsNotebook);
- m_settingsNotebook->AddPage(mainSettings, wxT("General"), false);
m_settingsNotebook->AddPage(jpeg2000Settings, wxT("JPEG 2000"), false);
-/* m_settingsNotebook->AddPage(mjpeg2000Settings, wxT("MJPEG 2000"), false);
-#ifdef USE_JPWL
- m_settingsNotebook->AddPage(jpwlSettings, wxT("JPWL"), false);
-#endif // USE_JPWL
-*/
+ m_settingsNotebook->AddPage(mainSettings, wxT("General"), false);
+
LayoutDialog();
}
@@ -2772,7 +3038,7 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
//topSizer->AddSpacer(5);
// sub top sizer
- wxFlexGridSizer *subtopSizer = new wxFlexGridSizer(2, 3, 3);
+ wxFlexGridSizer *subtopSizer = new wxFlexGridSizer(4, 3, 3);
// image settings, column
wxStaticBox* imageBox = new wxStaticBox(panel, wxID_ANY, wxT("Image"));
@@ -2790,8 +3056,8 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// add the value control
subsSizer->Add(
- /*m_rateCtrl = */new wxTextCtrl(panel, OPJENCO_SUBSAMPLING,
- wxT("1,1"),
+ m_subsamplingCtrl = new wxTextCtrl(panel, OPJENCO_SUBSAMPLING,
+ wxGetApp().m_subsampling,
wxDefaultPosition, wxSize(120, wxDefaultCoord),
wxTE_LEFT),
0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
@@ -2810,8 +3076,8 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// add the value control
imorigSizer->Add(
- /*m_rateCtrl = */new wxTextCtrl(panel, OPJENCO_IMORIG,
- wxT("0,0"),
+ m_originCtrl = new wxTextCtrl(panel, OPJENCO_IMORIG,
+ wxGetApp().m_origin,
wxDefaultPosition, wxSize(120, wxDefaultCoord),
wxTE_LEFT),
0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
@@ -2821,7 +3087,7 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
subtopSizer->Add(imageSizer, 0, wxGROW | wxALL, 3);
// layer settings, column
- wxStaticBox* layerBox = new wxStaticBox(panel, wxID_ANY, wxT("Layers"));
+ wxStaticBox* layerBox = new wxStaticBox(panel, wxID_ANY, wxT("Layers/compression"));
wxBoxSizer* layerSizer = new wxStaticBoxSizer(layerBox, wxVERTICAL);
// rate factor sizer, row
@@ -2836,8 +3102,8 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// add the value control
rateSizer->Add(
- /*m_rateCtrl = */new wxTextCtrl(panel, OPJENCO_RATEFACTOR,
- wxT("20,10,5"),
+ m_rateCtrl = new wxTextCtrl(panel, OPJENCO_RATEFACTOR,
+ wxGetApp().m_rates,
wxDefaultPosition, wxSize(120, wxDefaultCoord),
wxTE_LEFT),
0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
@@ -2856,8 +3122,8 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// add the value control
qualitySizer->Add(
- /*m_rateCtrl = */new wxTextCtrl(panel, OPJENCO_QUALITYFACTOR,
- wxT("30,35,40"),
+ m_qualityCtrl = new wxTextCtrl(panel, OPJENCO_QUALITYFACTOR,
+ wxGetApp().m_quality,
wxDefaultPosition, wxSize(120, wxDefaultCoord),
wxTE_LEFT),
0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
@@ -2867,15 +3133,15 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
subtopSizer->Add(layerSizer, 0, wxGROW | wxALL, 3);
// wavelet settings, column
- wxStaticBox* waveletBox = new wxStaticBox(panel, wxID_ANY, wxT("Transform"));
+ wxStaticBox* waveletBox = new wxStaticBox(panel, wxID_ANY, wxT("Wavelet transform"));
wxBoxSizer* waveletSizer = new wxStaticBoxSizer(waveletBox, wxVERTICAL);
// irreversible check box
waveletSizer->Add(
- /*m_enabledecoCheck =*/ new wxCheckBox(panel, OPJENCO_ENABLEIRREV, wxT("Irreversible"),
+ m_irrevCheck = new wxCheckBox(panel, OPJENCO_ENABLEIRREV, wxT("Irreversible"),
wxDefaultPosition, wxDefaultSize),
0, wxGROW | wxALL, 3);
- /*m_enabledecoCheck->SetValue(wxGetApp().m_enabledeco);*/
+ m_irrevCheck->SetValue(wxGetApp().m_irreversible);
// resolution number sizer, row
wxBoxSizer* resnumSizer = new wxBoxSizer(wxHORIZONTAL);
@@ -2889,8 +3155,8 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// add the value control
resnumSizer->Add(
- /*m_layerCtrl =*/ new wxSpinCtrl(panel, OPJENCO_RESNUMBER,
- wxT("6"),
+ m_resolutionsCtrl = new wxSpinCtrl(panel, OPJENCO_RESNUMBER,
+ wxString::Format("%d", wxGetApp().m_resolutions),
wxDefaultPosition, wxSize(80, wxDefaultCoord),
wxSP_ARROW_KEYS,
0, 256, 6),
@@ -2898,6 +3164,12 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
waveletSizer->Add(resnumSizer, 0, wxGROW | wxALL, 3);
+ subtopSizer->Add(waveletSizer, 0, wxGROW | wxALL, 3);
+
+ // codestream settings, column
+ wxStaticBox* codestreamBox = new wxStaticBox(panel, wxID_ANY, wxT("Codestream"));
+ wxBoxSizer* codestreamSizer = new wxStaticBoxSizer(codestreamBox, wxVERTICAL);
+
// codeblock sizer, row
wxBoxSizer* codeblockSizer = new wxBoxSizer(wxHORIZONTAL);
@@ -2910,13 +3182,13 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// add the value control
codeblockSizer->Add(
- /*m_rateCtrl = */new wxTextCtrl(panel, OPJENCO_CODEBLOCKSIZE,
- wxT("32,32"),
+ m_cbsizeCtrl = new wxTextCtrl(panel, OPJENCO_CODEBLOCKSIZE,
+ wxGetApp().m_cbsize,
wxDefaultPosition, wxSize(120, wxDefaultCoord),
wxTE_LEFT),
0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
- waveletSizer->Add(codeblockSizer, 0, wxGROW | wxALL, 3);
+ codestreamSizer->Add(codeblockSizer, 0, wxGROW | wxALL, 3);
// precinct sizer, row
wxBoxSizer* precinctSizer = new wxBoxSizer(wxHORIZONTAL);
@@ -2930,15 +3202,15 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// add the value control
precinctSizer->Add(
- /*m_rateCtrl = */new wxTextCtrl(panel, OPJENCO_PRECINCTSIZE,
- wxT("[128,128],[128,128]"),
+ m_prsizeCtrl = new wxTextCtrl(panel, OPJENCO_PRECINCTSIZE,
+ wxGetApp().m_prsize,
wxDefaultPosition, wxSize(120, wxDefaultCoord),
wxTE_LEFT),
0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
- waveletSizer->Add(precinctSizer, 0, wxGROW | wxALL, 3);
+ codestreamSizer->Add(precinctSizer, 0, wxGROW | wxALL, 3);
- subtopSizer->Add(waveletSizer, 0, wxGROW | wxALL, 3);
+ subtopSizer->Add(codestreamSizer, 0, wxGROW | wxALL, 3);
// tile settings, column
wxStaticBox* tileBox = new wxStaticBox(panel, wxID_ANY, wxT("Tiles"));
@@ -2956,8 +3228,8 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// add the value control
tilesizeSizer->Add(
- /*m_rateCtrl = */new wxTextCtrl(panel, OPJENCO_TILESIZE,
- wxT(""),
+ m_tsizeCtrl = new wxTextCtrl(panel, OPJENCO_TILESIZE,
+ wxGetApp().m_tsize,
wxDefaultPosition, wxSize(120, wxDefaultCoord),
wxTE_LEFT),
0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
@@ -2976,8 +3248,8 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// add the value control
tilorigSizer->Add(
- /*m_rateCtrl = */new wxTextCtrl(panel, OPJENCO_TILORIG,
- wxT("0,0"),
+ m_toriginCtrl = new wxTextCtrl(panel, OPJENCO_TILORIG,
+ wxGetApp().m_torigin,
wxDefaultPosition, wxSize(120, wxDefaultCoord),
wxTE_LEFT),
0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
@@ -2989,7 +3261,7 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// progression settings, column
wxString choices[] = {wxT("LRCP"), wxT("RLCP"), wxT("RPCL"), wxT("PCRL"), wxT("CPRL")};
wxRadioBox *progressionBox = new wxRadioBox(panel, OPJENCO_PROGRESSION,
- wxT("Progression"),
+ wxT("Progression order"),
wxDefaultPosition, wxDefaultSize,
WXSIZEOF(choices),
choices,
@@ -3000,7 +3272,7 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
subtopSizer->Add(progressionBox, 0, wxGROW | wxALL, 3);
// resilience settings, column
- wxStaticBox* resilBox = new wxStaticBox(panel, wxID_ANY, wxT("Resilience"));
+ wxStaticBox* resilBox = new wxStaticBox(panel, wxID_ANY, wxT("Error resilience"));
wxBoxSizer* resilSizer = new wxStaticBoxSizer(resilBox, wxVERTICAL);
// resil2 sizer, row
@@ -3008,17 +3280,17 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// SOP check box
resil2Sizer->Add(
- /*m_enabledecoCheck =*/ new wxCheckBox(panel, OPJENCO_ENABLESOP, wxT("SOP"),
- wxDefaultPosition, wxDefaultSize),
- 0, wxGROW | wxALL, 3);
- /*m_enabledecoCheck->SetValue(wxGetApp().m_enabledeco);*/
+ m_sopCheck = new wxCheckBox(panel, OPJENCO_ENABLESOP, wxT("SOP"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_sopCheck->SetValue(wxGetApp().m_enablesop);
// EPH check box
resil2Sizer->Add(
- /*m_enabledecoCheck =*/ new wxCheckBox(panel, OPJENCO_ENABLEEPH, wxT("EPH"),
- wxDefaultPosition, wxDefaultSize),
- 0, wxGROW | wxALL, 3);
- /*m_enabledecoCheck->SetValue(wxGetApp().m_enabledeco);*/
+ m_ephCheck = new wxCheckBox(panel, OPJENCO_ENABLEEPH, wxT("EPH"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_ephCheck->SetValue(wxGetApp().m_enableeph);
resilSizer->Add(resil2Sizer, 0, wxGROW | wxALL, 3);
@@ -3075,7 +3347,7 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
subtopSizer->Add(resilSizer, 0, wxGROW | wxALL, 3);
// ROI settings, column
- wxStaticBox* roiBox = new wxStaticBox(panel, wxID_ANY, wxT("ROI"));
+ wxStaticBox* roiBox = new wxStaticBox(panel, wxID_ANY, wxT("Region Of Interest"));
wxBoxSizer* roiSizer = new wxStaticBoxSizer(roiBox, wxVERTICAL);
// component number sizer, row
@@ -3128,10 +3400,10 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// indexing check box
indexSizer->Add(
- /*m_enabledecoCheck =*/ new wxCheckBox(panel, OPJENCO_ENABLEINDEX, wxT("Enabled"),
+ m_enableidxCheck = new wxCheckBox(panel, OPJENCO_ENABLEINDEX, wxT("Enabled"),
wxDefaultPosition, wxDefaultSize),
0, wxGROW | wxALL, 3);
- /*m_enabledecoCheck->SetValue(wxGetApp().m_enabledeco);*/
+ m_enableidxCheck->SetValue(wxGetApp().m_enableidx);
// index file sizer, row
wxBoxSizer* indexnameSizer = new wxBoxSizer(wxHORIZONTAL);
@@ -3145,44 +3417,42 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
// add the value control
indexnameSizer->Add(
- /*m_rateCtrl = */new wxTextCtrl(panel, OPJENCO_INDEXNAME,
- wxT(""),
+ m_indexCtrl = new wxTextCtrl(panel, OPJENCO_INDEXNAME,
+ wxGetApp().m_index,
wxDefaultPosition, wxSize(120, wxDefaultCoord),
wxTE_LEFT),
0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+ m_indexCtrl->Enable(wxGetApp().m_enableidx);
indexSizer->Add(indexnameSizer, 0, wxGROW | wxALL, 3);
subtopSizer->Add(indexSizer, 0, wxGROW | wxALL, 3);
-/* // component settings, column
- wxStaticBox* compoBox = new wxStaticBox(panel, wxID_ANY, wxT("Components"));
- wxBoxSizer* compoSizer = new wxStaticBoxSizer(compoBox, wxVERTICAL);
-
- // quality layers sizer, row
- wxBoxSizer* numcompsSizer = new wxBoxSizer(wxHORIZONTAL);
+ // Comment settings, column
+ wxStaticBox* commentBox = new wxStaticBox(panel, wxID_ANY, wxT("Comment"));
+ wxBoxSizer* commentSizer = new wxStaticBoxSizer(commentBox, wxVERTICAL);
- // add some text
- numcompsSizer->Add(new wxStaticText(panel, wxID_ANY, wxT("&Component displayed:")),
- 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
+ // commenting check box
+ commentSizer->Add(
+ m_enablecommCheck = new wxCheckBox(panel, OPJENCO_ENABLECOMM, wxT("Enabled"),
+ wxDefaultPosition, wxDefaultSize),
+ 0, wxGROW | wxALL, 3);
+ m_enablecommCheck->SetValue(wxGetApp().m_enablecomm);
- // add some horizontal space
- numcompsSizer->Add(5, 5, 1, wxALL, 0);
+ // add some horizontal space
+ commentSizer->Add(3, 3, 1, wxALL, 0);
- // add the value control
- numcompsSizer->Add(
- m_numcompsCtrl = new wxSpinCtrl(panel, OPJDECO_NUMCOMPS,
- wxString::Format(wxT("%d"), wxGetApp().m_components),
- wxDefaultPosition, wxSize(80, wxDefaultCoord),
- wxSP_ARROW_KEYS,
- 0, 100000, wxGetApp().m_components),
- 0, wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5);
- m_numcompsCtrl->Enable(true);
+ // add the value control
+ commentSizer->Add(
+ m_commentCtrl = new wxTextCtrl(panel, OPJENCO_COMMENTTEXT,
+ wxGetApp().m_comment,
+ wxDefaultPosition, wxSize(wxDefaultCoord, 60),
+ wxTE_LEFT | wxTE_MULTILINE),
+ 0, wxGROW | wxALL | wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 3);
+ m_commentCtrl->Enable(wxGetApp().m_enablecomm);
- compoSizer->Add(numcompsSizer, 0, wxGROW | wxALL, 5);
+ subtopSizer->Add(commentSizer, 0, wxGROW | wxALL, 3);
- subtopSizer->Add(compoSizer, 0, wxGROW | wxALL, 5);
-*/
topSizer->Add(subtopSizer, 1, wxGROW | wxALIGN_CENTRE | wxALL, 5);
// assign top and fit it
@@ -3192,6 +3462,29 @@ wxPanel* OPJEncoderDialog::CreatePart1SettingsPage(wxWindow* parent)
return panel;
}
+void OPJEncoderDialog::OnEnableComm(wxCommandEvent& event)
+{
+ if (event.IsChecked()) {
+ wxLogMessage(wxT("Comment enabled"));
+ m_commentCtrl->Enable(true);
+ } else {
+ wxLogMessage(wxT("Comment disabled"));
+ m_commentCtrl->Enable(false);
+ }
+
+}
+
+void OPJEncoderDialog::OnEnableIdx(wxCommandEvent& event)
+{
+ if (event.IsChecked()) {
+ wxLogMessage(wxT("Index enabled"));
+ m_indexCtrl->Enable(true);
+ } else {
+ wxLogMessage(wxT("Index disabled"));
+ m_indexCtrl->Enable(false);
+ }
+}
+
#ifdef USE_JPWL
void OPJEncoderDialog::OnEnableJPWL(wxCommandEvent& event)
{
diff --git a/OPJViewer/source/OPJViewer.h b/OPJViewer/source/OPJViewer.h
index 8904c9ee..0c29af4d 100644
--- a/OPJViewer/source/OPJViewer.h
+++ b/OPJViewer/source/OPJViewer.h
@@ -151,6 +151,7 @@ typedef unsigned long long int8byte;
#define OPJ_CANVAS_COLOUR *wxWHITE
class OPJDecoThread;
+class OPJEncoThread;
class OPJParseThread;
WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
class OPJChildFrame;
@@ -175,17 +176,17 @@ class OPJViewerApp: public wxApp
// all the threads currently alive - as soon as the thread terminates, it's
// removed from the array
- wxArrayThread m_deco_threads, m_parse_threads;
+ wxArrayThread m_deco_threads, m_parse_threads, m_enco_threads;
// crit section protects access to all of the arrays below
- wxCriticalSection m_deco_critsect, m_parse_critsect;
+ wxCriticalSection m_deco_critsect, m_parse_critsect, m_enco_critsect;
// semaphore used to wait for the threads to exit, see OPJFrame::OnQuit()
- wxSemaphore m_deco_semAllDone, m_parse_semAllDone;
+ wxSemaphore m_deco_semAllDone, m_parse_semAllDone, m_enco_semAllDone;
// the last exiting thread should post to m_semAllDone if this is true
// (protected by the same m_critsect)
- bool m_deco_waitingUntilAllDone, m_parse_waitingUntilAllDone;
+ bool m_deco_waitingUntilAllDone, m_parse_waitingUntilAllDone, m_enco_waitingUntilAllDone;
// the list of all filenames written in the command line
wxArrayString m_filelist;
@@ -202,6 +203,12 @@ class OPJViewerApp: public wxApp
int m_framewidth, m_frameheight;
#endif // USE_JPWL
+ // encoding engine parameters
+ wxString m_subsampling, m_origin, m_rates, m_comment, m_index, m_quality;
+ wxString m_cbsize, m_prsize, m_tsize, m_torigin;
+ bool m_enablecomm, m_enableidx, m_irreversible, m_enablesop, m_enableeph;
+ int m_resolutions;
+
// some layout settings
bool m_showtoolbar, m_showbrowser, m_showpeeker;
int m_browserwidth, m_peekerheight;
@@ -240,10 +247,11 @@ class OPJCanvas: public wxScrolledWindow
#endif //__WXGTK__
}
OPJDecoThread *CreateDecoThread(void);
+ OPJEncoThread *CreateEncoThread(void);
OPJChildFrame *m_childframe;
wxBitmap m_image, m_image100;
- wxFileName m_fname;
+ wxFileName m_fname, m_savename;
long m_zooml;
DECLARE_EVENT_TABLE()
@@ -383,6 +391,8 @@ class OPJFrame: public wxMDIParentFrame
void OnSize(wxSizeEvent& WXUNUSED(event));
void OnAbout(wxCommandEvent& WXUNUSED(event));
void OnFileOpen(wxCommandEvent& WXUNUSED(event));
+ void OnFileSaveAs(wxCommandEvent& WXUNUSED(event));
+ void OnMemoryOpen(wxCommandEvent& WXUNUSED(event));
void OnQuit(wxCommandEvent& WXUNUSED(event));
void OnClose(wxCommandEvent& WXUNUSED(event));
void OnZoom(wxCommandEvent& WXUNUSED(event));
@@ -398,6 +408,7 @@ class OPJFrame: public wxMDIParentFrame
void OnSetsDeco(wxCommandEvent& event);
void OnSashDrag(wxSashEvent& event);
void OpenFiles(wxArrayString paths, wxArrayString filenames);
+ void SaveFile(wxArrayString paths, wxArrayString filenames);
void OnNotebook(wxNotebookEvent& event);
void Rescale(int scale, OPJChildFrame *child);
@@ -453,6 +464,7 @@ enum {
OPJFRAME_FILEEXIT = wxID_EXIT,
OPJFRAME_HELPABOUT = wxID_ABOUT,
OPJFRAME_FILEOPEN,
+ OPJFRAME_MEMORYOPEN,
OPJFRAME_FILESAVEAS,
OPJFRAME_FILETOGGLEB,
OPJFRAME_FILETOGGLEP,
@@ -524,6 +536,26 @@ enum
LEFT_NOTEBOOK_ID
};
+class OPJEncoThread : public wxThread
+{
+public:
+ OPJEncoThread(OPJCanvas *canvas);
+
+ // thread execution starts here
+ virtual void *Entry();
+
+ // called when the thread exits - whether it terminates normally or is
+ // stopped with Delete() (but not when it is Kill()ed!)
+ virtual void OnExit();
+
+ // write something to the text control
+ void WriteText(const wxString& text);
+
+public:
+ unsigned m_count;
+ OPJCanvas *m_canvas;
+};
+
class OPJDecoThread : public wxThread
{
public:
@@ -603,10 +635,17 @@ public:
/* wxPanel* CreatePart3SettingsPage(wxWindow* parent);*/
#ifdef USE_JPWL
void OnEnableJPWL(wxCommandEvent& event);
+ void OnEnableComm(wxCommandEvent& event);
+ void OnEnableIdx(wxCommandEvent& event);
/* wxPanel* CreatePart11SettingsPage(wxWindow* parent);
wxCheckBox *m_enablejpwlCheck;*/
#endif // USE_JPWL
+ wxTextCtrl *m_subsamplingCtrl, *m_originCtrl, *m_rateCtrl, *m_commentCtrl;
+ wxTextCtrl *m_indexCtrl, *m_qualityCtrl, *m_cbsizeCtrl, *m_prsizeCtrl;
+ wxTextCtrl *m_tsizeCtrl, *m_toriginCtrl;
+ wxCheckBox *m_enablecommCheck, *m_enableidxCheck, *m_irrevCheck, *m_sopCheck, *m_ephCheck;
+ wxSpinCtrl *m_resolutionsCtrl;
protected:
@@ -634,7 +673,9 @@ protected:
OPJENCO_TILORIG,
OPJENCO_ENABLEIRREV,
OPJENCO_ENABLEINDEX,
- OPJENCO_INDEXNAME
+ OPJENCO_INDEXNAME,
+ OPJENCO_ENABLECOMM,
+ OPJENCO_COMMENTTEXT
};
DECLARE_EVENT_TABLE()
diff --git a/OPJViewer/source/build.h b/OPJViewer/source/build.h
index 42c7d4db..fce4f83b 100644
--- a/OPJViewer/source/build.h
+++ b/OPJViewer/source/build.h
@@ -1 +1 @@
-wxT("59")
+wxT("200")
diff --git a/OPJViewer/source/imagj2k.cpp b/OPJViewer/source/imagj2k.cpp
index 7897ee3c..6dc57fac 100644
--- a/OPJViewer/source/imagj2k.cpp
+++ b/OPJViewer/source/imagj2k.cpp
@@ -231,17 +231,275 @@ bool wxJ2KHandler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose,
}
// save the j2k codestream
-bool wxJ2KHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
+bool wxJ2KHandler::SaveFile( wxImage *wimage, wxOutputStream& stream, bool verbose )
{
+ opj_cparameters_t parameters; /* compression parameters */
+ opj_event_mgr_t event_mgr; /* event manager */
+ opj_image_t *oimage = NULL;
+ opj_image_cmptparm_t *cmptparm;
+ opj_cio_t *cio = NULL;
+ int codestream_length;
+ bool bSuccess;
+ int i;
+
+ /*
+ configure the event callbacks (not required)
+ setting of each callback is optionnal
+ */
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = j2k_error_callback;
+ event_mgr.warning_handler = j2k_warning_callback;
+ event_mgr.info_handler = j2k_info_callback;
+
+ /* set encoding parameters to default values */
+ opj_set_default_encoder_parameters(&parameters);
+
+ /* load parameters */
+
+ /* subsampling */
+ if (sscanf(m_subsampling.c_str(), wxT("%d,%d"), &(parameters.subsampling_dx), &(parameters.subsampling_dy)) != 2) {
+ wxLogError(wxT("Wrong sub-sampling encoder setting: dx,dy"));
+ return false;
+ }
+
+ /* compression rates */
+ if (m_rates != wxT("")) {
+ char *s1 = (char *) m_rates.c_str();
+ wxLogMessage("rates %s", s1);
+ while (sscanf(s1, "%f", &(parameters.tcp_rates[parameters.tcp_numlayers])) == 1) {
+ parameters.tcp_numlayers++;
+ while (*s1 && *s1 != ',') {
+ s1++;
+ }
+ if (!*s1)
+ break;
+ s1++;
+ }
+ wxLogMessage("%d layers", parameters.tcp_numlayers);
+ parameters.cp_disto_alloc = 1;
+ }
+
+ /* image quality, dB */
+ if (m_rates == wxT("")) {
+ char *s2 = (char *) m_quality.c_str();
+ wxLogMessage("qualities %s", s2);
+ while (sscanf(s2, "%f", &parameters.tcp_distoratio[parameters.tcp_numlayers]) == 1) {
+ parameters.tcp_numlayers++;
+ while (*s2 && *s2 != ',') {
+ s2++;
+ }
+ if (!*s2)
+ break;
+ s2++;
+ }
+ wxLogMessage("%d layers", parameters.tcp_numlayers);
+ parameters.cp_fixed_quality = 1;
+ }
+
+ /* image origin */
+ if (sscanf(m_origin.c_str(), "%d,%d", &parameters.image_offset_x0, &parameters.image_offset_y0) != 2) {
+ wxLogError(wxT("bad coordinate of the image origin: x0,y0"));
+ return false;
+ }
+
+ /* Create comment for codestream */
+ if(m_enablecomm) {
+ parameters.cp_comment = (char *) malloc(strlen(m_comment.c_str()) + 1);
+ if(parameters.cp_comment) {
+ strcpy(parameters.cp_comment, m_comment.c_str());
+ }
+ } else {
+ parameters.cp_comment = NULL;
+ }
+
+ /* indexing file */
+ if (m_enableidx) {
+ strncpy(parameters.index, m_index.c_str(), m_index.Len());
+ wxLogMessage("index file is %s", parameters.index);
+ parameters.index_on = 1;
+ } else {
+ parameters.index_on = 0;
+ }
+
+ /* if no rate entered, lossless by default */
+ if (parameters.tcp_numlayers == 0) {
+ parameters.tcp_rates[0] = 0; /* MOD antonin : losslessbug */
+ parameters.tcp_numlayers++;
+ parameters.cp_disto_alloc = 1;
+ }
+
+ /* irreversible transform */
+ parameters.irreversible = (m_irreversible == true) ? 1 : 0;
+
+ /* resolutions */
+ parameters.numresolution = m_resolutions;
+
+ /* codeblocks size */
+ if (m_cbsize != wxT("")) {
+ int cblockw_init = 0, cblockh_init = 0;
+ sscanf(m_cbsize.c_str(), "%d,%d", &cblockw_init, &cblockh_init);
+ if (cblockw_init * cblockh_init > 4096 || cblockw_init > 1024 || cblockw_init < 4 || cblockh_init > 1024 || cblockh_init < 4) {
+ wxLogError("!! Size of code_block error !! Restrictions:\n width*height<=4096\n 4<=width,height<= 1024");
+ return false;
+ }
+ parameters.cblockw_init = cblockw_init;
+ parameters.cblockh_init = cblockh_init;
+ }
+
+ /* precincts size */
+ if (m_prsize != wxT("")) {
+ char sep;
+ int res_spec = 0;
+ char *s = (char *) m_prsize.c_str();
+ do {
+ sep = 0;
+ sscanf(s, "[%d,%d]%c", &parameters.prcw_init[res_spec], &parameters.prch_init[res_spec], &sep);
+ parameters.csty |= 0x01;
+ res_spec++;
+ s = strpbrk(s, "]") + 2;
+ } while (sep == ',');
+ parameters.res_spec = res_spec;
+ }
+
+ /* tiles */
+ if (m_tsize != wxT("")) {
+ sscanf(m_tsize.c_str(), "%d,%d", &parameters.cp_tdx, &parameters.cp_tdy);
+ parameters.tile_size_on = true;
+ }
+
+ /* tile origin */
+ if (sscanf(m_torigin.c_str(), "%d,%d", &parameters.cp_tx0, &parameters.cp_ty0) != 2) {
+ wxLogError("tile offset setting error: X0,Y0");
+ return false;
+ }
+
+ /* use SOP */
+ if (m_enablesop)
+ parameters.csty |= 0x02;
+
+ /* use EPH */
+ if (m_enableeph)
+ parameters.csty |= 0x04;
+
+
+
+ /* compression settings */
+ //parameters.tcp_numlayers = 1;
+ //parameters.tcp_rates[0] = 10.0;
+ //parameters.cp_disto_alloc = 1;
+ //parameters.irreversible = 1;
+ parameters.tcp_mct = 1;
+
+ /* convert wx image into opj image */
+ cmptparm = (opj_image_cmptparm_t*) malloc(3 * sizeof(opj_image_cmptparm_t));
+
+ /* initialize opj image components */
+ memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t));
+ for(i = 0; i < 3; i++) {
+ cmptparm[i].prec = 8;
+ cmptparm[i].bpp = 8;
+ cmptparm[i].sgnd = false;
+ cmptparm[i].dx = parameters.subsampling_dx;
+ cmptparm[i].dy = parameters.subsampling_dy;
+ cmptparm[i].w = wimage->GetWidth();
+ cmptparm[i].h = wimage->GetHeight();
+ }
+
+ /* create the image */
+ oimage = opj_image_create(3, &cmptparm[0], CLRSPC_SRGB);
+ if(!oimage) {
+ if (cmptparm)
+ free(cmptparm);
+ return false;
+ }
+
+ /* set image offset and reference grid */
+ oimage->x0 = parameters.image_offset_x0;
+ oimage->y0 = parameters.image_offset_y0;
+ oimage->x1 = parameters.image_offset_x0 + (wimage->GetWidth() - 1) * 1 + 1;
+ oimage->y1 = parameters.image_offset_y0 + (wimage->GetHeight() - 1) * 1 + 1;
+
+ /* load image data */
+ unsigned char *value = wimage->GetData();
+ int area = wimage->GetWidth() * wimage->GetHeight();
+ for (i = 0; i < area; i++) {
+ oimage->comps[0].data[i] = *(value++);
+ oimage->comps[1].data[i] = *(value++);
+ oimage->comps[2].data[i] = *(value++);
+ }
+
+ /* get a J2K compressor handle */
+ opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
+
+ /* setup the encoder parameters using the current image and user parameters */
+ opj_setup_encoder(cinfo, &parameters, oimage);
+
+ /* open a byte stream for writing */
+ /* allocate memory for all tiles */
+ cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
+
+ /* encode the image */
+ bSuccess = opj_encode(cinfo, cio, oimage, parameters.index);
+ if (!bSuccess) {
+
+ opj_cio_close(cio);
+ opj_destroy_compress(cinfo);
+ opj_image_destroy(oimage);
+ if (cmptparm)
+ free(cmptparm);
+ if(parameters.cp_comment)
+ free(parameters.cp_comment);
+ if(parameters.cp_matrice)
+ free(parameters.cp_matrice);
+
#ifndef __WXGTK__
wxMutexGuiEnter();
#endif /* __WXGTK__ */
- wxLogError(wxT("J2K: Couldn't save image -> not implemented."));
+
+ wxLogError(wxT("failed to encode image"));
+
+#ifndef __WXGTK__
+ wxMutexGuiLeave();
+#endif /* __WXGTK__ */
+
+ return false;
+ }
+ codestream_length = cio_tell(cio);
+ wxLogMessage(wxT("Codestream: %d bytes"), codestream_length);
+
+ /* write the buffer to stream */
+ stream.Write(cio->buffer, codestream_length);
+
+ /* close and free the byte stream */
+ opj_cio_close(cio);
+
+ /* free remaining compression structures */
+ opj_destroy_compress(cinfo);
+
+ /* free image data */
+ opj_image_destroy(oimage);
+
+ if (cmptparm)
+ free(cmptparm);
+ if(parameters.cp_comment)
+ free(parameters.cp_comment);
+ if(parameters.cp_matrice)
+ free(parameters.cp_matrice);
+
+#ifndef __WXGTK__
+ wxMutexGuiEnter();
+#endif /* __WXGTK__ */
+
+ wxLogMessage(wxT("J2K: Image encoded!"));
+
#ifndef __WXGTK__
wxMutexGuiLeave();
#endif /* __WXGTK__ */
- return false;
+ return true;
}
#ifdef __VISUALC__
diff --git a/OPJViewer/source/imagj2k.h b/OPJViewer/source/imagj2k.h
index b262ec6b..9b6f63a9 100644
--- a/OPJViewer/source/imagj2k.h
+++ b/OPJViewer/source/imagj2k.h
@@ -67,6 +67,7 @@ public:
m_type = wxBITMAP_TYPE_J2K;
m_mime = wxT("image/j2k");
+ /* decoding */
m_reducefactor = 0;
m_qualitylayers = 0;
m_components = 0;
@@ -75,15 +76,75 @@ public:
m_expcomps = JPWL_EXPECTED_COMPONENTS;
m_maxtiles = JPWL_MAXIMUM_TILES;
#endif // USE_JPWL
+
+ /* encoding */
+ m_subsampling = wxT("1,1");
+ m_origin = wxT("0,0");
+ m_rates = wxT("20,10,5");
+ m_quality = wxT("30,35,40");
+ m_irreversible = false;
+ m_resolutions = 6;
+ m_cbsize = wxT("32,32");
+ m_prsize = wxT("[128,128],[128,128]");
+ m_tsize = wxT("");
+ m_torigin = wxT("0,0");
+ /*m_progression
+ m_resilience*/
+ m_enablesop = false;
+ m_enableeph = false;
+ /*m_roicompo
+ m_roiup
+ m_indexfname*/
+ m_enableidx = false;
+ m_index = wxT("index.txt");
+ m_enablecomm = true;
+
+#if defined __WXMSW__
+ m_comment = wxT("Created by OPJViewer Win32 - OpenJPEG version ");
+#elif defined __WXGTK__
+ m_comment = wxT("Created by OPJViewer Lin32 - OpenJPEG version ");
+#else
+ m_comment = wxT("Created by OPJViewer - OpenJPEG version ");
+#endif
+
+#ifdef USE_JPWL
+ m_comment += wxString::Format("%s with JPWL", opj_version());
+#else
+ m_comment += wxString::Format("%s", opj_version());
+#endif
+
}
- // decoding engine parameters
- int m_reducefactor, m_qualitylayers, m_components;
+ // decoding engine parameters
+ int m_reducefactor, m_qualitylayers, m_components;
#ifdef USE_JPWL
- bool m_enablejpwl;
- int m_expcomps, m_maxtiles;
+ bool m_enablejpwl;
+ int m_expcomps, m_maxtiles;
#endif // USE_JPWL
+ // encoding engine parameters
+ wxString m_subsampling;
+ wxString m_origin;
+ wxString m_rates;
+ wxString m_quality;
+ bool m_irreversible;
+ int m_resolutions;
+ wxString m_cbsize;
+ wxString m_prsize;
+ wxString m_tsize;
+ wxString m_torigin;
+ /*m_progression
+ m_resilience*/
+ bool m_enablesop;
+ bool m_enableeph;
+ /*m_roicompo
+ m_roiup
+ m_indexfname*/
+ bool m_enableidx;
+ wxString m_index;
+ bool m_enablecomm;
+ wxString m_comment;
+
#if wxUSE_STREAMS
virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1 );
virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=true );
diff --git a/OPJViewer/source/wxjp2parser.cpp b/OPJViewer/source/wxjp2parser.cpp
index afacd394..6e89390a 100644
--- a/OPJViewer/source/wxjp2parser.cpp
+++ b/OPJViewer/source/wxjp2parser.cpp
@@ -60,6 +60,8 @@ typedef enum {
TRAK_BOX,
TKHD_BOX,
MDIA_BOX,
+ MDHD_BOX,
+ HDLR_BOX,
MINF_BOX,
VMHD_BOX,
STBL_BOX,
@@ -102,6 +104,8 @@ struct boxdef {
#define TRAK_SIGN "trak"
#define TKHD_SIGN "tkhd"
#define MDIA_SIGN "mdia"
+#define MDHD_SIGN "mdhd"
+#define HDLR_SIGN "hdlr"
#define MINF_SIGN "minf"
#define VMHD_SIGN "vmhd"
#define STBL_SIGN "stbl"
@@ -231,6 +235,22 @@ struct boxdef j22box[] =
/* req */ {1, 1, 1},
/* ins */ TRAK_BOX},
+/* sign */ {MDHD_SIGN,
+/* short */ "Media Header box",
+/* long */ "The media header declares overall information which is media-independent, and relevant to characteristics "
+ "of the media in a track",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MDIA_BOX},
+
+/* sign */ {HDLR_SIGN,
+/* short */ "Handler Reference box",
+/* long */ "This box within a Media Box declares the process by which the media-data in the track may be presented, "
+ "and thus, the nature of the media in a track",
+/* sbox */ 0,
+/* req */ {1, 1, 1},
+/* ins */ MDIA_BOX},
+
/* sign */ {MINF_SIGN,
/* short */ "Media Information box",
/* long */ "This box contains all the objects which declare characteristic information of the media in the track",
@@ -829,7 +849,114 @@ int OPJParseThread::box_handler_function(int boxtype, wxFile *fileid, wxFileOffs
};
break;
+ /* Media Header box */
+ case (MDHD_BOX): {
+ unsigned long int version;
+ unsigned short int language;
+ fileid->Read(&version, sizeof(unsigned long int));
+ version = BYTE_SWAP4(version);
+ if (version == 0) {
+ unsigned long int creation_time, modification_time, timescale, duration;
+ fileid->Read(&creation_time, sizeof(unsigned long int));
+ creation_time = BYTE_SWAP4(creation_time);
+ fileid->Read(&modification_time, sizeof(unsigned long int));
+ modification_time = BYTE_SWAP4(modification_time);
+ fileid->Read(&timescale, sizeof(unsigned long int));
+ timescale = BYTE_SWAP4(timescale);
+ fileid->Read(&duration, sizeof(unsigned long int));
+ duration = BYTE_SWAP4(duration);
+ const long unix_time = creation_time - 2082844800L;
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Creation time: %u (%.24s)"), creation_time, ctime(&unix_time)),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ const long unix_time1 = modification_time - 2082844800L;
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Modification time: %u (%.24s)"), modification_time, ctime(&unix_time1)),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Timescale: %u (%.6fs)"), timescale, 1.0 / (float) timescale),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Duration: %u (%.3fs)"), duration, (float) duration / (float) timescale),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ } else {
+ int8byte creation_time, modification_time, duration;
+ unsigned long int timescale;
+ fileid->Read(&creation_time, sizeof(int8byte));
+ creation_time = BYTE_SWAP8(creation_time);
+ fileid->Read(&modification_time, sizeof(int8byte));
+ modification_time = BYTE_SWAP8(modification_time);
+ fileid->Read(&timescale, sizeof(unsigned long int));
+ timescale = BYTE_SWAP4(timescale);
+ fileid->Read(&duration, sizeof(int8byte));
+ duration = BYTE_SWAP8(duration);
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Creation time: %u"), creation_time),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Modification time: %u"), modification_time),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Timescale: %u"), timescale),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Duration: %u"), duration),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ }
+ fileid->Read(&language, sizeof(unsigned short int));
+
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Language: %d (%c%c%c)"), language & 0xEFFF,
+ 0x60 + (char) ((language >> 10) & 0x001F), 0x60 + (char) ((language >> 5) & 0x001F), 0x60 + (char) ((language >> 0) & 0x001F)),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+ };
+ break;
+ /* Media Handler box */
+ case (HDLR_BOX): {
+ unsigned long int version, predefined, temp[3];
+ char handler[4], name[256];
+ int namelen = wxMin(256, (filelimit - filepoint - 24));
+ fileid->Read(&version, sizeof(unsigned long int));
+ version = BYTE_SWAP4(version);
+ fileid->Read(&predefined, sizeof(unsigned long int));
+ fileid->Read(handler, 4 * sizeof(char));
+ fileid->Read(&temp, 3 * sizeof(unsigned long int));
+ fileid->Read(name, namelen * sizeof(char));
+
+ wxTreeItemId currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Handler: %.4s"), handler),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ currid = m_tree->AppendItem(parentid,
+ wxString::Format(wxT("Name: %.255s"), name),
+ m_tree->TreeCtrlIcon_File, m_tree->TreeCtrlIcon_File + 1,
+ new OPJMarkerData(wxT("INFO"))
+ );
+
+ }
+ break;
+
/* not yet implemented */
default:
break;