Hoyt's FORK of DemoIccMAX 2.1.17.hoyt
Documentation for Hoyt's FORK of DemoIccMAX
Loading...
Searching...
No Matches
wxProfileDump.cpp
Go to the documentation of this file.
1/** @file
2File: wxProfileDump.cpp
3
4Contains: Main application that displays profile contents using wxWidgets
5
6Version: V1
7
8Copyright: (c) see ICC Software License
9*/
10
11/*
12* The ICC Software License, Version 0.2
13*
14*
15* Copyright (c) 2003-2023 The International Color Consortium. All rights
16* reserved.
17*
18* Redistribution and use in source and binary forms, with or without
19* modification, are permitted provided that the following conditions
20* are met:
21*
22* 1. Redistributions of source code must retain the above copyright
23* notice, this list of conditions and the following disclaimer.
24*
25* 2. Redistributions in binary form must reproduce the above copyright
26* notice, this list of conditions and the following disclaimer in
27* the documentation and/or other materials provided with the
28* distribution.
29*
30* 3. In the absence of prior written permission, the names "ICC" and "The
31* International Color Consortium" must not be used to imply that the
32* ICC organization endorses or promotes products derived from this
33* software.
34*
35*
36* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39* DISCLAIMED. IN NO EVENT SHALL THE INTERNATIONAL COLOR CONSORTIUM OR
40* ITS CONTRIBUTING MEMBERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47* SUCH DAMAGE.
48* ====================================================================
49*
50* This software consists of voluntary contributions made by many
51* individuals on behalf of the The International Color Consortium.
52*
53*
54* Membership in the ICC is encouraged when this software is used for
55* commercial purposes.
56*
57*
58* For more information on The International Color Consortium, please
59* see <http://www.color.org/>.
60*
61*
62*/
63
64// ===========================================================================
65// declarations
66// ===========================================================================
67
68// ---------------------------------------------------------------------------
69// headers
70// ---------------------------------------------------------------------------
71#include "IccProfile.h"
72#include "IccTag.h"
73#include "IccUtil.h"
74#include "IccEval.h"
75#include "IccPrmg.h"
76#include "IccProfLibVer.h"
77// For compilers that support precompilation, includes "wx/wx.h".
78#include "wx/wxprec.h"
79
80#ifdef __BORLANDC__
81 #pragma hdrstop
82#endif
83
84#ifndef WX_PRECOMP
85 #include "wx/wx.h"
86 #include "wx/mdi.h"
87#endif
88
89#include "wx/toolbar.h"
90#include "wx/config.h"
91#include "wx/filename.h"
92#include "wx/filedlg.h"
93
94#if !defined(__WXMSW__)
95// #include "mondrian.xpm"
96#endif
97
98#include "bitmaps/new.xpm"
99#include "bitmaps/open.xpm"
100#include "bitmaps/save.xpm"
101#include "bitmaps/copy.xpm"
102#include "bitmaps/cut.xpm"
103#include "bitmaps/paste.xpm"
104#include "bitmaps/print.xpm"
105#include "bitmaps/help.xpm"
106
107
108#include "wxProfileDump.h"
109
110#if wxMAJOR_VERSION > 2
111#define wxOPEN wxFD_OPEN
112#define wxFILE_MUST_EXIST wxFD_FILE_MUST_EXIST
113#endif
114
115#undef wxT
116#define wxT(x) x
117
118IMPLEMENT_APP(MyApp)
119
120// ---------------------------------------------------------------------------
121// global variables
122// ---------------------------------------------------------------------------
123
126
127// For drawing lines in a canvas
128static long xpos = -1;
129static long ypos = -1;
130
131static int gs_nFrames = 0;
132
133// ---------------------------------------------------------------------------
134// event tables
135// ---------------------------------------------------------------------------
136
137#define ID_VALIDATE_PROFILE 1000
138#define ID_TAG_LIST 1001
139#define ID_ROUND_TRIP 1002
140
141BEGIN_EVENT_TABLE(MyFrame, wxMDIParentFrame)
142 EVT_MENU(MDI_ABOUT, MyFrame::OnAbout)
144 EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, MyFrame::OnOpenProfile)
145 EVT_MENU(MDI_QUIT, MyFrame::OnQuit)
146
147 EVT_CLOSE(MyFrame::OnClose)
148 EVT_SIZE(MyFrame::OnSize)
149END_EVENT_TABLE()
150
151// Note that MDI_NEW_WINDOW and MDI_ABOUT commands get passed
152// to the parent window for processing, so no need to
153// duplicate event handlers here.
154BEGIN_EVENT_TABLE(MyChild, wxMDIChildFrame)
155 EVT_MENU(MDI_CHILD_QUIT, MyChild::OnQuit)
156 EVT_CLOSE(MyChild::OnClose)
157 EVT_BUTTON(ID_VALIDATE_PROFILE, MyChild::OnValidate)
158 EVT_BUTTON(ID_ROUND_TRIP, MyChild::OnRoundTrip)
159 EVT_LIST_ITEM_ACTIVATED(ID_TAG_LIST, MyChild::OnTagClicked)
160END_EVENT_TABLE()
161
162
163// ===========================================================================
164// implementation
165// ===========================================================================
166
167// ---------------------------------------------------------------------------
168// MyApp
169// ---------------------------------------------------------------------------
170
171// Initialise this in OnInit, not statically
172bool MyApp::OnInit()
173{
174 // Create the main frame window
175 my_frame = new MyFrame((wxFrame *)NULL, wxID_ANY, _T("ProfileDump"),
176 wxDefaultPosition, wxSize(1024, 768),
177 wxDEFAULT_FRAME_STYLE | wxHSCROLL | wxVSCROLL);
178
179 // using wxConfig instead of writing wxFileConfig or wxRegConfig enhances
180 // portability of the code
181 wxConfig config(wxT("wxProfileDump"));
182
183 m_history.Load(config);
184
185#ifdef __WXMSW__
186#if 0
187 // Experimental: change the window menu
188 wxMenu* windowMenu = new wxMenu;
189 windowMenu->Append(5000, _T("My menu item!"));
190 my_frame->SetWindowMenu(windowMenu);
191#endif
192#endif
193
194 // Give it an icon
195#ifdef __WXMSW__
196 my_frame->SetIcon(wxIcon(_T("wxProfileDump_icn")));
197#else
198 //my_frame->SetIcon(wxIcon( wxProfileDump_xpm ));
199#endif
200
201 // Make a menubar
202 wxMenu *file_menu = new wxMenu;
203
204 file_menu->Append(MDI_OPEN_PROFILE, _T("&Open Profile\tCtrl-O"), _T("Open an ICC profile"));
205 file_menu->Append(MDI_QUIT, _T("&Exit\tAlt-X"), _T("Quit the program"));
206
207 m_history.UseMenu(file_menu);
208 m_history.AddFilesToMenu(file_menu);
209
210 wxMenu *help_menu = new wxMenu;
211 help_menu->Append(MDI_ABOUT, _T("&About\tF1"));
212
213 wxMenuBar *menu_bar = new wxMenuBar;
214
215 menu_bar->Append(file_menu, _T("&File"));
216 menu_bar->Append(help_menu, _T("&Help"));
217
218 // Associate the menu bar with the frame
219 my_frame->SetMenuBar(menu_bar);
220
221#if wxUSE_STATUSBAR
222 my_frame->CreateStatusBar();
223#endif // wxUSE_STATUSBAR
224
225 my_frame->Show(true);
226 my_frame->SetDropTarget(new MyDnDFile(my_frame));
227
228 SetTopWindow(my_frame);
229
230 if (argc>1) {
231 my_frame->OpenFile(argv[1]);
232 }
233
234 return true;
235}
236
238{
239 wxConfig config;
240
241 m_history.Save(config);
242
243 return 0;
244}
245
246// ---------------------------------------------------------------------------
247// MyFrame
248// ---------------------------------------------------------------------------
249
250// Define my frame constructor
251MyFrame::MyFrame(wxWindow *parent,
252 const wxWindowID id,
253 const wxString& title,
254 const wxPoint& pos,
255 const wxSize& size,
256 const long style)
257 : wxMDIParentFrame(parent, id, title, pos, size,
258 style | wxNO_FULL_REPAINT_ON_RESIZE)
259{
260#if wxUSE_TOOLBAR
261 CreateToolBar(wxNO_BORDER | wxTB_FLAT | wxTB_HORIZONTAL);
262 InitToolBar(GetToolBar());
263#endif // wxUSE_TOOLBAR
264
265 // Accelerators
266 wxAcceleratorEntry entries[3];
267 entries[0].Set(wxACCEL_CTRL, (int) 'O', MDI_OPEN_PROFILE);
268 entries[1].Set(wxACCEL_CTRL, (int) 'X', MDI_QUIT);
269 entries[2].Set(wxACCEL_CTRL, (int) 'A', MDI_ABOUT);
270 wxAcceleratorTable accel(3, entries);
271 SetAcceleratorTable(accel);
272}
273
274void MyFrame::OnClose(wxCloseEvent& event)
275{
276 if ( event.CanVeto() && (gs_nFrames > 0) )
277 {
278 wxString msg;
279 msg.Printf(_T("%d windows still open, close anyhow?"), gs_nFrames);
280 if ( wxMessageBox(msg, _T("Please confirm"),
281 wxICON_QUESTION | wxYES_NO) != wxYES )
282 {
283 event.Veto();
284
285 return;
286 }
287 }
288
289 event.Skip();
290}
291
292void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
293{
294 Close();
295}
296
297void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
298{
299 (void)wxMessageBox(_T("wxProfileDump\n")
300 _T("Copyright (C) 2005-2023\n\n")
301 _T("Using ICCProflib version ") ICCPROFLIBVER _T("\n"),
302 _T("About wxProfileDump"));
303}
304
305void MyFrame::OpenFile(wxString profilePath)
306{
307 wxFileName filepath(profilePath);
308 wxString profileTitle = filepath.GetName();
309
310 char * pPath = strdup( profilePath.mb_str() );
311 CIccProfile *pIcc = OpenIccProfile(pPath);
312
313 if (!pIcc) {
314 (void)wxMessageBox(wxString(_T("Unable to open profile '")) + profilePath + _T("'"),
315 _T("Open Error!"));
316 return;
317 }
318
319 wxGetApp().m_history.AddFileToHistory(profilePath);
320
321 // Make another frame, containing a canvas
322 MyChild *subframe = new MyChild(my_frame, profileTitle, pIcc, profilePath);
323
324 subframe->SetTitle(profileTitle);
325
326 // Give it an icon
327#ifdef __WXMSW__
328 subframe->SetIcon(wxIcon(_T("ProfileDumpDoc_icn")));
329#else
330// subframe->SetIcon(wxIcon( mondrian_xpm ));
331#endif
332
333 // Make a menubar
334 wxMenu *file_menu = new wxMenu;
335 subframe->SetFileMenu(file_menu);
336
337 file_menu->Append(MDI_OPEN_PROFILE, _T("&Open Profile"));
338 file_menu->Append(MDI_CHILD_QUIT, _T("&Close"), _T("Close this window"));
339 file_menu->Append(MDI_QUIT, _T("&Exit"));
340
341 wxGetApp().m_history.UseMenu(file_menu);
342 wxGetApp().m_history.AddFilesToMenu(file_menu);
343
344 wxMenu *help_menu = new wxMenu;
345 help_menu->Append(MDI_ABOUT, _T("&About"));
346
347 wxMenuBar *menu_bar = new wxMenuBar;
348
349 menu_bar->Append(file_menu, _T("&File"));
350 menu_bar->Append(help_menu, _T("&Help"));
351
352 // Associate the menu bar with the frame
353 subframe->SetMenuBar(menu_bar);
354 subframe->Show(true);
355}
356
357void MyFrame::OnOpenProfile(wxCommandEvent& event )
358{
359 wxString profilePath;
360
361 if (event.GetId()==MDI_OPEN_PROFILE) {
362 wxFileDialog dialog(this, _T("Open Profile"), wxEmptyString, wxEmptyString, _T("ICC files (*.icc)|*.icc|ICM files (*.icm)|*.icm|All files|*.*"), wxOPEN |wxFILE_MUST_EXIST);
363
364 if (dialog.ShowModal()!=wxID_OK)
365 return;
366
367 profilePath = dialog.GetPath();
368 }
369 else {
370 profilePath = wxGetApp().m_history.GetHistoryFile(event.GetId() - wxID_FILE1);
371 }
372
373 OpenFile(profilePath);
374}
375
376
377#if wxUSE_TOOLBAR
378void MyFrame::InitToolBar(wxToolBar* toolBar)
379{
380 wxBitmap* bitmaps[6];
381
382 int index=0;
383 bitmaps[index++] = new wxBitmap( open_xpm );
384 //bitmaps[index++] = new wxBitmap( save_xpm );
385 //bitmaps[index++] = new wxBitmap( copy_xpm );
386 //bitmaps[index++] = new wxBitmap( cut_xpm );
387 //bitmaps[index++] = new wxBitmap( paste_xpm );
388 bitmaps[index++] = new wxBitmap( help_xpm );
389
390 int width = 24;
391 int currentX = 5;
392
393 index = 0;
394 toolBar->AddTool(MDI_OPEN_PROFILE, _T("Open"), *(bitmaps[index]), _T("Open Profile"));
395 currentX += width + 5;
396
397 //index++;
398 //toolBar->AddTool(index+1,_T("Save"), *bitmaps[index], _T("Save Profile"));
399 //currentX += width + 5;
400
401 //toolBar->AddSeparator();
402
403 //index++;
404 //toolBar->AddTool(index+1, _T("Copy"), *bitmaps[index], _T("Copy"));
405 //currentX += width + 5;
406
407 //index++;
408 //toolBar->AddTool(index+1, _T("Cut"), *bitmaps[index], _T("Cut"));
409 //currentX += width + 5;
410
411 //index++;
412 //toolBar->AddTool(index+1, _T("Paste"), *bitmaps[index], wxNullBitmap, false, currentX, wxDefaultCoord, (wxObject *) NULL, _T("Paste"));
413 //currentX += width + 5;
414
415 toolBar->AddSeparator();
416
417 index++;
418 toolBar->AddTool(MDI_ABOUT, _T("Help"), *bitmaps[index], _T("Help"));
419
420 toolBar->Realize();
421
422 int i;
423 for (i = 0; i <= index; i++)
424 delete bitmaps[i];
425}
426#endif // wxUSE_TOOLBAR
427
428static bool IsRoundTripable(CIccProfile *pIcc)
429{
430 icHeader *pHdr = &pIcc->m_Header;
431
432 if (pHdr->deviceClass == icSigLinkClass) {
433 return false;
434 }
435
436 if ((pIcc->FindTag(icSigAToB0Tag) && pIcc->FindTag(icSigBToA0Tag)) ||
437 (pIcc->FindTag(icSigAToB1Tag) && pIcc->FindTag(icSigBToA1Tag)) ||
438 (pIcc->FindTag(icSigAToB2Tag) && pIcc->FindTag(icSigBToA2Tag)) ||
439 (pIcc->FindTag(icSigDToB0Tag) && pIcc->FindTag(icSigBToD0Tag)) ||
440 (pIcc->FindTag(icSigDToB1Tag) && pIcc->FindTag(icSigBToD1Tag)) ||
441 (pIcc->FindTag(icSigDToB2Tag) && pIcc->FindTag(icSigBToD2Tag)) ||
442 (pIcc->FindTag(icSigRedMatrixColumnTag) && pIcc->FindTag(icSigGreenMatrixColumnTag) && pIcc->FindTag(icSigBlueMatrixColumnTag) &&
443 pIcc->FindTag(icSigRedTRCTag) && pIcc->FindTag(icSigGreenTRCTag) && pIcc->FindTag(icSigBlueTRCTag)))
444 return true;
445
446 return false;
447}
448
449// ---------------------------------------------------------------------------
450// MyChild
451// ---------------------------------------------------------------------------
452
453MyChild::MyChild(wxMDIParentFrame *parent, const wxString& title, CIccProfile *pIcc, const wxString &profilePath)
454 : wxMDIChildFrame(parent, wxID_ANY, title, wxDefaultPosition, wxSize(750,900),
455 wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
456{
457 m_pIcc = pIcc;
458 m_profilePath = profilePath;
459 icHeader* pHdr = &pIcc->m_Header;
460
461 my_children.Append(this);
462 // this should work for MDI frames as well as for normal ones
463 SetSizeHints(750, 900);
464
465 // create controls
466 m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN);
467
468 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
469 wxSizer *sizerBox = new wxStaticBoxSizer(new wxStaticBox(m_panel, wxID_ANY, _T("&Profile Header")), wxVERTICAL);
470
471 // Keep things consistent and in the same order as CLI "iccDumpProfile"
472 sizerBox->Add(CreateSizerWithText(_("Profile ID:"), &m_textProfileID), wxSizerFlags().Expand().Border(wxALL, 0));
473 sizerBox->Add(CreateSizerWithText(_("Size:"), &m_textSize), wxSizerFlags().Expand().Border(wxALL, 0));
474 sizerBox->Add(CreateSizerWithText(_("Attributes:"), &m_textAttribute), wxSizerFlags().Expand().Border(wxALL, 0));
475 sizerBox->Add(CreateSizerWithText(_("Cmm:"), &m_textCMM), wxSizerFlags().Expand().Border(wxALL, 0));
476 sizerBox->Add(CreateSizerWithText(_("Creation Date:"), &m_textCreationDate), wxSizerFlags().Expand().Border(wxALL, 0));
477 sizerBox->Add(CreateSizerWithText(_("Creator:"), &m_textCreator), wxSizerFlags().Expand().Border(wxALL, 0));
478 sizerBox->Add(CreateSizerWithText(_("Device Manufacturer:"), &m_textDeviceManufacturer), wxSizerFlags().Expand().Border(wxALL, 0));
479 sizerBox->Add(CreateSizerWithText(_("Data Color Space:"), &m_textColorSpace), wxSizerFlags().Expand().Border(wxALL, 0));
480 sizerBox->Add(CreateSizerWithText(_("Flags:"), &m_textFlags), wxSizerFlags().Expand().Border(wxALL, 0));
481 sizerBox->Add(CreateSizerWithText(_("PCS Color Space:"), &m_textPCS), wxSizerFlags().Expand().Border(wxALL, 0));
482 sizerBox->Add(CreateSizerWithText(_("Platform:"), &m_textPlatform), wxSizerFlags().Expand().Border(wxALL, 0));
483 sizerBox->Add(CreateSizerWithText(_("Rendering Intent:"), &m_textRenderingIntent), wxSizerFlags().Expand().Border(wxALL, 0));
484 sizerBox->Add(CreateSizerWithText(_("Profile Class:"), &m_textClass), wxSizerFlags().Expand().Border(wxALL, 0));
485 sizerBox->Add(CreateSizerWithText(_("Profile SubClass:"), &m_textSubClass), wxSizerFlags().Expand().Border(wxALL, 0));
486 sizerBox->Add(CreateSizerWithText(_("Version:"), &m_textVersion), wxSizerFlags().Expand().Border(wxALL, 0));
487 if (pHdr && (pHdr->version >= icVersionNumberV5) && pHdr->deviceSubClass) {
488 sizerBox->Add(CreateSizerWithText(_("SubClass Version:"), &m_textSubClassVersion), wxSizerFlags().Expand().Border(wxALL, 0));
489 }
490 sizerBox->Add(CreateSizerWithText(_("Illuminant:"), &m_textIlluminant), wxSizerFlags().Expand().Border(wxALL, 0));
491 sizerBox->Add(CreateSizerWithText(_("Spectral PCS:"), &m_textSpectralPCS), wxSizerFlags().Expand().Border(wxALL, 0));
492 sizerBox->Add(CreateSizerWithText(_("Spectral PCS Range:"), &m_textSpectralWavelengths), wxSizerFlags().Expand().Border(wxALL, 0));
493 sizerBox->Add(CreateSizerWithText(_("BiSpectral PCS Range:"), &m_textBiSpectralWavelengths), wxSizerFlags().Expand().Border(wxALL, 0));
494 sizerBox->Add(CreateSizerWithText(_("MCS Color Space:"), &m_textMaterialColorSpace), wxSizerFlags().Expand().Border(wxALL, 0));
495
496 sizerTop->Add(sizerBox, wxSizerFlags().Expand().Border(wxALL, 5));
497
498 wxSizer *sizerBtn = new wxBoxSizer(wxHORIZONTAL);
499 if (IsRoundTripable(pIcc)) {
500 sizerBtn->Add(new wxButton(m_panel, ID_ROUND_TRIP, _("&Round Trip Report")), wxSizerFlags().Border(wxRIGHT, 5));
501 }
502 sizerBtn->Add(new wxButton(m_panel, ID_VALIDATE_PROFILE, _("&Validate Profile")), wxSizerFlags().Border(wxRIGHT, 5));
503
504 sizerTop->Add(sizerBtn, wxSizerFlags().Right());
505
506 wxSizer *sizerLabel = new wxBoxSizer(wxHORIZONTAL);
507 sizerLabel->Add(new wxStaticText(m_panel, wxID_ANY, _("Profile Tags")), wxSizerFlags().Border(wxLEFT, 5));
508
509 sizerTop->Add(sizerLabel, wxSizerFlags().Left());
510
511 m_tagsCtrl = new wxListCtrl(m_panel, ID_TAG_LIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT);
512 wxSizer *sizerTags = new wxBoxSizer(wxVERTICAL);
513 sizerTags->Add(m_tagsCtrl, wxSizerFlags(1).Expand().Border(wxALL, 0));
514 sizerTags->SetItemMinSize((size_t)0, 455, 175);
515 sizerTop->Add(sizerTags, wxSizerFlags(1).Expand().Border(wxALL, 5));
516
517 m_tagsCtrl->InsertColumn(0, _("#"), wxLIST_FORMAT_RIGHT, 30);
518 m_tagsCtrl->InsertColumn(1, _("Tag ID"), wxLIST_FORMAT_LEFT, 210);
519 m_tagsCtrl->InsertColumn(2, _("Tag Type"), wxLIST_FORMAT_LEFT, 210);
520 m_tagsCtrl->InsertColumn(3, _("Offset"), wxLIST_FORMAT_RIGHT, 100);
521 m_tagsCtrl->InsertColumn(4, _("Size"), wxLIST_FORMAT_RIGHT, 100);
522 m_tagsCtrl->InsertColumn(5, _("Padding"), wxLIST_FORMAT_RIGHT, 100);
523
524 // don't allow frame to get smaller than what the sizers tell it and also set
525 // the initial size as calculated by the sizers
526 sizerTop->SetSizeHints( this );
527
528 m_panel->SetSizer(sizerTop);
529
530 CIccInfo Fmt;
531 char buf[64];
532 int n;
533 wxString str;
534
535 if (pHdr) {
536 // Make things the same as CLI "iccDumpProfile" for easy comparison
537 str.Empty();
538 for (n = 0; n < 16; n++) {
539 sprintf(buf, "%02x", pHdr->profileID.ID8[n]);
540 if (n && !(n % 4))
541 str += " ";
542 str += buf;
543 }
544 m_textProfileID->SetLabel(str);
545 m_textSize->SetLabel(wxString::Format(_T("%d (0x%x) bytes"), pHdr->size, pHdr->size));
546 m_textAttribute->SetLabel(wxT(Fmt.GetDeviceAttrName(pHdr->attributes)));
547 m_textCMM->SetLabel(wxT(Fmt.GetCmmSigName((icCmmSignature)pHdr->cmmId)));
548 m_textCreationDate->SetLabel(wxString::Format(wxT("%d/%d/%d (M/D/Y) %02u:%02u:%02u"),
549 pHdr->date.month, pHdr->date.day, pHdr->date.year,
550 pHdr->date.hours, pHdr->date.minutes, pHdr->date.seconds));
551 m_textCreator->SetLabel(icGetSig(buf, pHdr->creator));
552 m_textDeviceManufacturer->SetLabel(icGetSig(buf, pHdr->manufacturer));
554 m_textFlags->SetLabel(Fmt.GetProfileFlagsName(pHdr->flags, pHdr->mcs!=0));
555 m_textPCS->SetLabel(Fmt.GetColorSpaceSigName(pHdr->pcs));
556 m_textPlatform->SetLabel(Fmt.GetPlatformSigName(pHdr->platform));
558 m_textClass->SetLabel(Fmt.GetProfileClassSigName(pHdr->deviceClass));
559 if (pHdr->deviceSubClass)
560 m_textSubClass->SetLabel(icGetSig(buf, pHdr->deviceSubClass));
561 else
562 m_textSubClass->SetLabel(_T("Not Defined"));
563
564 m_textVersion->SetLabel(Fmt.GetVersionName(pHdr->version));
565
566 if (pHdr && (pHdr->version >= icVersionNumberV5) && pHdr->deviceSubClass)
568
569 m_textIlluminant->SetLabel(wxString::Format(_T("X=%.4lf, Y=%.4lf, Z=%.4lf"),
570 icFtoD(pHdr->illuminant.X),
571 icFtoD(pHdr->illuminant.Y),
572 icFtoD(pHdr->illuminant.Z)));
574 if (pHdr->spectralRange.start || pHdr->spectralRange.end || pHdr->spectralRange.steps) {
575 m_textSpectralWavelengths->SetLabel(wxString::Format(_T("start=%.1fnm, end=%.1fnm, steps=%d"),
578 pHdr->spectralRange.steps));
579 }
580 else {
581 m_textSpectralWavelengths->SetLabel(_T("Not Defined"));
582 }
583
584 if (pHdr->biSpectralRange.start || pHdr->biSpectralRange.end || pHdr->biSpectralRange.steps) {
585 m_textBiSpectralWavelengths->SetLabel(wxString::Format(_T("start=%.1fnm, end=%.1fnm, steps=%d"),
588 pHdr->biSpectralRange.steps));
589 }
590 else {
591 m_textBiSpectralWavelengths->SetLabel(_T("Not Defined"));
592 }
593
594 if (pHdr->mcs) {
596 }
597 else {
598 m_textMaterialColorSpace->SetLabel(_T("Not Defined"));
599 }
600
601 int item, closest, pad;
602 TagEntryList::iterator i, j;
603
604 for (n = 0, i = pIcc->m_Tags->begin(); i != pIcc->m_Tags->end(); i++, n++) {
605 item = m_tagsCtrl->InsertItem(n, wxString::Format("%d", n));
606
607 // Find closest tag after this tag, by scanning all offsets of other tags
608 closest = pHdr->size;
609 for (j = pIcc->m_Tags->begin(); j != pIcc->m_Tags->end(); j++) {
610 if ((i != j) && (j->TagInfo.offset >= i->TagInfo.offset + i->TagInfo.size) && ((int)j->TagInfo.offset <= closest)) {
611 closest = j->TagInfo.offset;
612 }
613 }
614 // Number of actual padding bytes between this tag and closest neighbour (or EOF)
615 // Should be 0-3 if compliant. Negative number if tags overlap!
616 pad = closest - i->TagInfo.offset - i->TagInfo.size;
617
618 m_tagsCtrl->SetItem(item, 1, Fmt.GetTagSigName(i->TagInfo.sig));
619 CIccTag* pTag = pIcc->FindTag(i->TagInfo.sig);
620 if (!pTag)
621 m_tagsCtrl->SetItem(item, 2, _T("***Invalid Tag!***"));
622 else
623 m_tagsCtrl->SetItem(item, 2, Fmt.GetTagTypeSigName(pTag->GetType()));
624
625 m_tagsCtrl->SetItem(item, 3, wxString::Format("%d", i->TagInfo.offset));
626 m_tagsCtrl->SetItem(item, 4, wxString::Format("%d", i->TagInfo.size));
627 m_tagsCtrl->SetItem(item, 5, wxString::Format("%d", pad));
628
629 m_tagsCtrl->SetItemData(item, (long)i->TagInfo.sig);
630 }
631 }
632 m_panel->Layout();
633}
634
636{
637 my_children.DeleteObject(this);
638 if (m_pIcc)
639 delete m_pIcc;
640}
641
642wxSizer *MyChild::CreateSizerWithText(const wxString &labelText, wxStaticText **ppText)
643{
644 wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL);
645
646 wxSize winSize = wxDefaultSize;
647
648 winSize.SetWidth(210);
649 wxStaticText *label = new wxStaticText(m_panel, wxID_ANY, labelText, wxDefaultPosition, winSize, wxALIGN_RIGHT);
650
651 winSize.SetWidth(250);
652 wxStaticText *text = new wxStaticText(m_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, winSize, wxSTATIC_BORDER|wxTE_RIGHT);
653
654 sizerRow->Add(label, 0, wxRIGHT | wxALIGN_CENTRE_VERTICAL, 5);
655 sizerRow->Add(text, 1, wxLEFT | wxALIGN_CENTRE_VERTICAL, 5);
656
657 if (ppText)
658 *ppText = text;
659
660 return sizerRow;
661}
662
663void MyChild::OnQuit(wxCommandEvent& WXUNUSED(event))
664{
665 Close(true);
666}
667
668void MyChild::SetFileMenu(wxMenu *file_menu)
669{
670 m_fileMenu = file_menu;
671}
672
673void MyChild::OnClose(wxCloseEvent& event)
674{
675 wxGetApp().m_history.RemoveMenu(m_fileMenu);
676 gs_nFrames--;
677
678 event.Skip();
679}
680
681void MyChild::OnValidate(wxCommandEvent& WXUNUSED(event))
682{
683 MyDialog dialog(this, _T("Profile Validation Report"), m_profilePath);
684
685 dialog.ShowModal();
686}
687
688void MyChild::OnRoundTrip(wxCommandEvent& WXUNUSED(event))
689{
690 MyRoundTripDialog dialog(this, _T("Round Trip Report"), m_profilePath, m_pIcc);
691
692 dialog.ShowModal();
693}
694
695void MyChild::OnTagClicked(wxListEvent& event)
696{
697 icTagSignature tagSig = (icTagSignature)event.GetData();
698 CIccTag *pTag = m_pIcc->FindTag(tagSig);
699
700 MyTagDialog dialog(this, m_pIcc, tagSig, pTag);
701
702 dialog.ShowModal();
703}
704
705MyDialog::MyDialog(wxWindow *pParent, const wxString& title, wxString &profilePath) :
706 wxDialog(pParent, wxID_ANY, title,wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
707{
708 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
709 wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL);
710
711 wxSize winSize = wxDefaultSize;
712
713 winSize.SetWidth(100);
714 wxStaticText *labelSttus = new wxStaticText(this, wxID_ANY, _T("Validation Status:"), wxDefaultPosition, winSize, wxALIGN_RIGHT);
715
716 winSize.SetWidth(500);
717 wxStaticText *textStatus = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, winSize,
718 wxSTATIC_BORDER | wxTE_LEFT | wxST_ELLIPSIZE_END);
719
720 sizerRow->Add(labelSttus, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5);
721 sizerRow->Add(textStatus, 1, wxALL | wxALIGN_CENTRE_VERTICAL, 5);
722
723 sizer->Add(sizerRow, wxSizerFlags().Expand());
724
725 winSize = wxSize(500, 400);
726 wxTextCtrl *textReport = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, winSize,
727 wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH | wxTE_BESTWRAP);
728
729 sizer->Add(textReport, wxSizerFlags(1).Expand());
730
731 icValidateStatus nStat;
732 wxString theReport, theValidateStatus;
733
734 std::string ver_str;
735
736 if (profilePath.IsEmpty()) {
737 theReport = "Invalid Profile Path!\n";
738 nStat = (icValidateStatus)-1;
739 }
740 else {
741 std::string sReport;
742 wxBeginBusyCursor();
743 char * pPath = strdup( profilePath.mb_str() );
744 CIccProfile *pIcc = ValidateIccProfile(pPath, sReport, nStat);
745 if (pIcc) {
746 int m, n;
747 TagEntryList::iterator i, j;
748 CIccInfo Fmt;
749 char str[256];
750
751 icHeader* pHdr = &pIcc->m_Header;
752 ver_str = " for version ";
753 ver_str += Fmt.GetVersionName(pHdr->version);
754
755 // Report all duplicated tags in the tag index
756 // Both ICC.1 and ICC.2 are silent on what should happen for this but report as a warning!!!
757 for (n = 0, i = pIcc->m_Tags->begin(); i != pIcc->m_Tags->end(); i++, n++)
758 for (m = 0, j = pIcc->m_Tags->begin(); j != pIcc->m_Tags->end(); j++, m++)
759 if ((i != j) && (i->TagInfo.sig == j->TagInfo.sig)) {
760 sprintf(str, "%28s is duplicated at positions %d and %d!\n", Fmt.GetTagSigName(i->TagInfo.sig), n, m);
761 sReport += str;
762 nStat = icMaxStatus(nStat, icValidateWarning);
763 }
764
765 // Check additional details if doing detailed validation:
766 // - First tag data offset is immediately after the Tag Table
767 // - Tag data offsets are all 4-byte aligned
768 // - Tag data should be tightly abutted with adjacent tags (or the end of the Tag Table)
769 // (note that tag data can be reused by multiple tags and tags do NOT have to be order)
770 // - Last tag also has to be padded and thus file size is always a multiple of 4. See clause
771 // 7.2.1, bullet (c) of ICC.1:2010 and ICC.2:2019 specs.
772 // - Tag offset + Tag Size should never go beyond EOF
773 // - Multiple tags can reuse data and this is NOT reported as it is perfectly valid and
774 // occurs in real-world ICC profiles
775 // - Tags with overlapping tag data are considered highly suspect (but officially valid)
776 // - 1-3 padding bytes after each tag's data need to be all zero *** NOT DONE - TODO ***
777 int closest, pad, rndup, smallest_offset = pHdr->size;
778
779 // File size is required to be a multiple of 4 bytes according to clause 7.2.1 bullet (c):
780 // "all tagged element data, including the last, shall be padded by no more than three
781 // following pad bytes to reach a 4 - byte boundary"
782 if ((pHdr->version >= icVersionNumberV4_2) && (pHdr->size % 4 != 0)) {
783 sReport += icMsgValidateNonCompliant;
784 sReport += "File size is not a multiple of 4 bytes (last tag needs padding?).\n";
785 nStat = icMaxStatus(nStat, icValidateNonCompliant);
786 }
787
788 for (i = pIcc->m_Tags->begin(); i != pIcc->m_Tags->end(); i++) {
789 rndup = 4 * ((i->TagInfo.size + 3) / 4); // Round up to a 4-byte aligned size as per ICC spec
790 pad = rndup - i->TagInfo.size; // Optimal smallest number of bytes of padding for this tag (0-3)
791
792 // Is the Tag offset + Tag Size beyond EOF?
793 if (i->TagInfo.offset + i->TagInfo.size > pHdr->size) {
794 sReport += icMsgValidateNonCompliant;
795 sprintf(str, "Tag %s (offset %d, size %d) ends beyond EOF.\n",
796 Fmt.GetTagSigName(i->TagInfo.sig), i->TagInfo.offset, i->TagInfo.size);
797 sReport += str;
798 nStat = icMaxStatus(nStat, icValidateNonCompliant);
799 }
800
801 // Is it the first tag data in the file?
802 if ((int)i->TagInfo.offset < smallest_offset) {
803 smallest_offset = (int)i->TagInfo.offset;
804 }
805
806 // Find closest tag after this tag, by scanning all other tag offsets
807 closest = pHdr->size;
808 for (j = pIcc->m_Tags->begin(); j != pIcc->m_Tags->end(); j++) {
809 if ((i != j) && (j->TagInfo.offset > i->TagInfo.offset) && ((int)j->TagInfo.offset <= closest)) {
810 closest = j->TagInfo.offset;
811 }
812 }
813
814 // Check if closest tag after this tag is less than offset+size - in which case it overlaps! Ignore last tag.
815 if ((closest < (int)i->TagInfo.offset + (int)i->TagInfo.size) && (closest < (int)pHdr->size)) {
816 sReport += icMsgValidateWarning;
817 sprintf(str, "Tag %s (offset %d, size %d) overlaps with following tag data starting at offset %d.\n",
818 Fmt.GetTagSigName(i->TagInfo.sig), i->TagInfo.offset, i->TagInfo.size, closest);
819 sReport += str;
820 nStat = icMaxStatus(nStat, icValidateWarning);
821 }
822
823 // Check for gaps between tag data (accounting for 4-byte alignment)
824 if (closest > (int)i->TagInfo.offset + rndup) {
825 sReport += icMsgValidateWarning;
826 sprintf(str, "Tag %s (size %d) is followed by %d unnecessary additional bytes (from offset %d).\n",
827 Fmt.GetTagSigName(i->TagInfo.sig), i->TagInfo.size, closest - (i->TagInfo.offset + rndup), (i->TagInfo.offset + rndup));
828 sReport += str;
829 nStat = icMaxStatus(nStat, icValidateWarning);
830 }
831 }
832
833 // Clause 7.2.1, bullet (b): "the first set of tagged element data shall immediately follow the tag table"
834 // 1st tag offset should be = Header (128) + Tag Count (4) + Tag Table (n*12)
835 if ((n > 0) && (smallest_offset > 128 + 4 + (n * 12))) {
836 sReport += icMsgValidateNonCompliant;
837 sprintf(str, "First tag data is at offset %d rather than immediately after tag table (offset %d).\n",
838 smallest_offset, 128 + 4 + (n * 12));
839 sReport += str;
840 nStat = icMaxStatus(nStat, icValidateNonCompliant);
841 }
842 delete pIcc;
843 }
844 wxEndBusyCursor();
845
846 if (sReport.empty())
847 sReport = "There is nothing to report.\n";
848
849 theReport = sReport.c_str();
850 }
851
852 wxColour status_color = *wxBLACK;
853 switch(nStat) {
854 case icValidateOK:
855 status_color = wxColour("DARK GREEN");
856 ver_str = "Valid Profile" + ver_str;
857 break;
858
860 status_color = wxColour("ORANGE RED");
861 ver_str = "Validation Warning(s)" + ver_str;
862 break;
863
865 status_color = *wxRED;
866 ver_str = "Profile violates ICC Specification" + ver_str;
867 break;
868
870 status_color = *wxRED;
871 ver_str = "Critical Error - Profile Violates ICC Specification" + ver_str;
872 break;
873
874 default:
875 status_color = *wxRED;
876 ver_str = "Unknown Validation Status";
877 break;
878 }
879 theValidateStatus = ver_str.c_str();
880
881 textStatus->SetForegroundColour(status_color);
882 textStatus->SetLabel(theValidateStatus);
883 *textReport << theReport;
884
885 SetSizer(sizer);
886 sizer->Fit(this);
887}
888
889class CIccMinMaxEval : public CIccEvalCompare
890{
891public:
893
894 void Compare(icFloatNumber *pixel, icFloatNumber *deviceLab, icFloatNumber *lab1, icFloatNumber *lab2);
895
898
902
904
905protected:
906
909};
910
912{
913 minDE1 = minDE2 = 10000;
914 maxDE1 = maxDE2 = -1;
915 sum1 = sum2 = 0;
916 num1 = num2 = num3 = m_nTotal = 0;
917
918 memset(&maxLab1[0], 0, sizeof(maxLab1));
919 memset(&maxLab2[0], 0, sizeof(maxLab2));
920}
921
923{
924 icFloatNumber DE1 = icDeltaE(deviceLab, lab1);
925 icFloatNumber DE2 = icDeltaE(lab1, lab2);
926
927 if (DE1<minDE1) {
928 minDE1 = DE1;
929 }
930
931 if (DE1>maxDE1) {
932 maxDE1 = DE1;
933 memcpy(&maxLab1[0], deviceLab, sizeof(maxLab1));
934 }
935
936 if (DE2<minDE2) {
937 minDE2 = DE2;
938 }
939
940 if (DE2>maxDE2) {
941 maxDE2 = DE2;
942 memcpy(&maxLab2[0], deviceLab, sizeof(maxLab2));
943 }
944
945 if(DE2 <= 1.0)
946 num3 += 1.0;
947
948 sum1 += DE1;
949 num1 += 1.0;
950
951 sum2 += DE2;
952 num2 += 1.0;
953
954 m_nTotal += 1.0;
955}
956
957wxString AnalyzeRoundTrip(wxString &profilePath, icRenderingIntent nIntent, bool bUseMPE)
958{
959 CIccInfo info;
960 wxString report;
961 CIccMinMaxEval eval;
962
963 if (bUseMPE)
964 report += wxString::Format("MPE Rendering Intent: %s\n", info.GetRenderingIntentName(nIntent));
965 else
966 report += wxString::Format("Rendering Intent: %s\n", info.GetRenderingIntentName(nIntent));
967
968 char * pPath = strdup( profilePath.mb_str() );
969 clock_t start = clock();
970 icStatusCMM stat = eval.EvaluateProfile( (const icChar*) pPath, 0, nIntent, icInterpTetrahedral, bUseMPE);
971
972 if (stat!=icCmmStatOk) {
973 report += wxString::Format(" Unable to perform round trip on '%s'\n", profilePath.c_str());
974 report += "\n";
975 report += "CMM Status: ";
976 report += CIccCmm::GetStatusText(stat);
977 report += "\n\n";
978
979 return report;
980 }
981
982 CIccPRMG prmg;
983
984 stat = prmg.EvaluateProfile( (const icChar*) pPath, nIntent, icInterpTetrahedral, bUseMPE);
985 clock_t elapsed = clock() - start;
986
987 if (stat!=icCmmStatOk) {
988 report += wxString::Format(" Unable to perform PRMG analysis on '%s'\n", profilePath.c_str());
989 report += "\n";
990
991 return report;
992 }
993
994 if (nIntent!=icRelativeColorimetric)
995 report += wxString::Format("Specified Rendering Intent Gamut: %s\n", prmg.m_bPrmgImplied ? "Perceptual Reference Medium Gamut" : "Not Specified");
996
997 report += wxString::Format("\n Round Trip 1\n");
998 report += wxString::Format( " ------------\n");
999 report += wxString::Format(" Min DeltaE: %8.2" ICFLOATSFX "\n", eval.minDE1);
1000 report += wxString::Format(" Mean DeltaE: %8.2" ICFLOATSFX "\n", eval.GetMean1());
1001 report += wxString::Format(" Max DeltaE: %8.2" ICFLOATSFX "\n\n", eval.maxDE1);
1002
1003 report += wxString::Format(" Max L, a, b: " ICFLOATFMT ", " ICFLOATFMT ", " ICFLOATFMT "\n", eval.maxLab1[0], eval.maxLab1[1], eval.maxLab1[2]);
1004
1005 report += wxString::Format("\n Round Trip 2\n");
1006 report += wxString::Format( " ------------\n");
1007 report += wxString::Format(" Min DeltaE: %8.2" ICFLOATSFX "\n", eval.minDE2);
1008 report += wxString::Format(" Mean DeltaE: %8.2" ICFLOATSFX "\n", eval.GetMean2());
1009 report += wxString::Format(" Max DeltaE: %8.2" ICFLOATSFX "\n", eval.maxDE2);
1010 report += wxString::Format(" DE <= 1.0 (%8u): %5.1f%%\n\n", eval.num3, (float)eval.num3 / (float)eval.m_nTotal*100.0);
1011
1012 report += wxString::Format(" Max L, a, b: " ICFLOATFMT ", " ICFLOATFMT ", " ICFLOATFMT "\n", eval.maxLab2[0], eval.maxLab2[1], eval.maxLab2[2]);
1013
1014 if (prmg.m_nTotal) {
1015 report += wxString::Format("\n PRMG Interoperability - Round Trip Results\n");
1016 report += wxString::Format( " ------------------------------------------------------\n");
1017
1018 report += wxString::Format(" DE <= 1.0 (%8u): %5.1f%%\n", prmg.m_nDE1, (float)prmg.m_nDE1/(float)prmg.m_nTotal*100.0);
1019 report += wxString::Format(" DE <= 2.0 (%8u): %5.1f%%\n", prmg.m_nDE2, (float)prmg.m_nDE2/(float)prmg.m_nTotal*100.0);
1020 report += wxString::Format(" DE <= 3.0 (%8u): %5.1f%%\n", prmg.m_nDE3, (float)prmg.m_nDE3/(float)prmg.m_nTotal*100.0);
1021 report += wxString::Format(" DE <= 5.0 (%8u): %5.1f%%\n", prmg.m_nDE5, (float)prmg.m_nDE5/(float)prmg.m_nTotal*100.0);
1022 report += wxString::Format(" DE <=10.0 (%8u): %5.1f%%\n", prmg.m_nDE10, (float)prmg.m_nDE10/(float)prmg.m_nTotal*100.0);
1023 report += wxString::Format(" Total (%8u)\n", prmg.m_nTotal);
1024 }
1025
1026 report += "\n";
1027
1028 report += wxString::Format("Evaluation took %f seconds\n\n", (double)elapsed / (double)CLOCKS_PER_SEC);
1029
1030 return report;
1031}
1032
1033MyRoundTripDialog::MyRoundTripDialog(wxWindow *pParent, const wxString& title, wxString &profilePath, CIccProfile *pIcc) :
1034 wxDialog(pParent, wxID_ANY, title,wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
1035{
1036 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
1037 wxSize winSize = winSize = wxSize(500, 400);
1038 wxTextCtrl *textReport = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, winSize,
1039 wxTE_MULTILINE |wxTE_READONLY | wxTE_RICH);
1040
1041 sizer->Add(textReport, wxSizerFlags(1).Expand());
1042
1043 wxString theReport;
1044
1045 if (profilePath.IsEmpty()) {
1046 theReport = "Invalid Profile Path\n";
1047 }
1048 else {
1049 bool bRelative = false;
1050
1051 wxBeginBusyCursor();
1052
1053 //Check colorimetric rendering intents
1054 if (pIcc->FindTag(icSigAToB1Tag) && pIcc->FindTag(icSigBToA1Tag)) {
1055 theReport += AnalyzeRoundTrip(profilePath, icRelativeColorimetric, false);
1056 bRelative = true;
1057 }
1058 if (pIcc->FindTag(icSigDToB1Tag) && pIcc->FindTag(icSigBToD1Tag)) {
1059 theReport += AnalyzeRoundTrip(profilePath, icRelativeColorimetric, true);
1060 bRelative = true;
1061 }
1062 if (!bRelative &&
1063 (pIcc->FindTag(icSigRedMatrixColumnTag) && pIcc->FindTag(icSigGreenMatrixColumnTag) && pIcc->FindTag(icSigBlueMatrixColumnTag) &&
1064 pIcc->FindTag(icSigRedTRCTag) && pIcc->FindTag(icSigGreenTRCTag) && pIcc->FindTag(icSigBlueTRCTag))) {
1065 theReport += AnalyzeRoundTrip(profilePath, icRelativeColorimetric, false);
1066 bRelative = true;
1067 }
1068
1069 //Check MPE absolute intent
1070 if (pIcc->FindTag(icSigDToB3Tag) && pIcc->FindTag(icSigBToD3Tag)) {
1071 theReport += AnalyzeRoundTrip(profilePath, icAbsoluteColorimetric, true);
1072 bRelative = true;
1073 }
1074
1075 //Perceptual intent
1076 if (pIcc->FindTag(icSigAToB0Tag) && pIcc->FindTag(icSigBToA0Tag)) {
1077 theReport += AnalyzeRoundTrip(profilePath, icPerceptual, false);
1078 bRelative = true;
1079 }
1080 if (pIcc->FindTag(icSigDToB0Tag) && pIcc->FindTag(icSigBToD0Tag)) {
1081 theReport += AnalyzeRoundTrip(profilePath, icPerceptual, true);
1082 bRelative = true;
1083 }
1084
1085 //Saturation intent
1086 if (pIcc->FindTag(icSigAToB2Tag) && pIcc->FindTag(icSigBToA2Tag)) {
1087 theReport += AnalyzeRoundTrip(profilePath, icSaturation, false);
1088 bRelative = true;
1089 }
1090 if (pIcc->FindTag(icSigDToB2Tag) && pIcc->FindTag(icSigBToD2Tag)) {
1091 theReport += AnalyzeRoundTrip(profilePath, icSaturation, true);
1092 bRelative = true;
1093 }
1094
1095 wxEndBusyCursor();
1096
1097 if (theReport.IsEmpty())
1098 theReport = "There is nothing to report\n";
1099 }
1100
1101 textReport->SetLabel(theReport);
1102
1103 SetSizer(sizer);
1104 sizer->Fit(this);
1105}
1106
1107MyTagDialog::MyTagDialog(wxWindow *pParent, CIccProfile *pIcc /*=NULL*/, icTagSignature sig/*=icMaxEnumTag*/, CIccTag *pTag /*=NULL*/) :
1108wxDialog(pParent, wxID_ANY, _T("View Tag"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
1109{
1110 m_pIcc = pIcc;
1111 m_sigTag = sig;
1112 m_pTag = pTag;
1113
1114 CIccInfo Fmt;
1115
1116 wxString sTagSignature = Fmt.GetTagSigName(sig);
1117 wxString sTagType;
1118 std::string desc;
1119
1120 if (pTag) {
1121 if (pTag->IsArrayType()) {
1122 sTagType = _T("Array of ");
1123 }
1124 else {
1125 sTagType.Empty();
1126 }
1127 sTagType += Fmt.GetTagTypeSigName(pTag->GetType());
1128
1129 wxBeginBusyCursor();
1130 pTag->Describe(desc, 100);
1131 wxEndBusyCursor();
1132 }
1133 else if (pIcc) {
1134 CIccMemIO *pIO = pIcc->GetTagIO(sig);
1135 sTagType = "***Invalid Tag!***";
1136
1137 if (pIO) {
1138 std::string dump;
1139 icMemDump(dump, pIO->GetData(), pIO->GetLength());
1140 delete pIO;
1141 desc = "Data contents of tag:\n\n";
1142 desc += dump;
1143 }
1144 else {
1145 desc = "Invalid Tag Directory Entry!\n";
1146 }
1147 }
1148 else {
1149 desc = "Invalid Tag Entry!\n";
1150 sTagType = "***Invalid Tag***";
1151 }
1152
1153 wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
1154
1155 wxSizer *sizerRow1 = new wxBoxSizer(wxHORIZONTAL);
1156 wxSize winSize = wxDefaultSize;
1157
1158 winSize.SetWidth(100);
1159 wxStaticText *labelSig = new wxStaticText(this, wxID_ANY, _T("Tag Signature:"), wxDefaultPosition, winSize, wxALIGN_RIGHT);
1160
1161 winSize.SetWidth(400);
1162 wxStaticText *textSig = new wxStaticText(this, wxID_ANY, sTagSignature, wxDefaultPosition, winSize, wxSTATIC_BORDER|wxTE_RIGHT);
1163
1164 sizerRow1->Add(labelSig, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5);
1165 sizerRow1->Add(textSig, 1, wxALL | wxALIGN_CENTRE_VERTICAL, 5);
1166
1167 sizer->Add(sizerRow1, wxSizerFlags().Expand());
1168
1169 wxSizer *sizerRow2 = new wxBoxSizer(wxHORIZONTAL);
1170 winSize = wxDefaultSize;
1171
1172 winSize.SetWidth(100);
1173 wxStaticText *labelType = new wxStaticText(this, wxID_ANY, _T("Tag Type:"), wxDefaultPosition, winSize, wxALIGN_RIGHT);
1174
1175 winSize.SetWidth(400);
1176 wxStaticText *textType = new wxStaticText(this, wxID_ANY, sTagType, wxDefaultPosition, winSize, wxSTATIC_BORDER|wxTE_RIGHT);
1177
1178 sizerRow2->Add(labelType, 0, wxALL | wxALIGN_CENTRE_VERTICAL, 5);
1179 sizerRow2->Add(textType, 1, wxALL | wxALIGN_CENTRE_VERTICAL, 5);
1180
1181 sizer->Add(sizerRow2, wxSizerFlags().Expand());
1182
1183 winSize = wxSize(500, 400);
1184 wxTextCtrl *textReport = new wxTextCtrl(this, wxID_ANY, wxString(desc.c_str()), wxDefaultPosition, winSize,
1185 wxTE_MULTILINE |wxTE_READONLY | wxTE_RICH| wxTE_DONTWRAP);
1186
1187 sizer->Add(textReport, wxSizerFlags(1).Expand());
1188
1189 SetSizer(sizer);
1190 sizer->Fit(this);
1191}
icArraySignature sig
@ icInterpTetrahedral
Definition IccCmm.h:115
icStatusCMM
CMM return status values.
Definition IccCmm.h:90
@ icCmmStatOk
Definition IccCmm.h:92
float icFloatNumber
All floating point operations/variables in IccProfLib use the icFloatNumber data type.
Definition IccDefs.h:100
#define ICFLOATFMT
Definition IccDefs.h:106
char icChar
Definition IccDefs.h:109
#define ICFLOATSFX
String formating macros need to match precision of icFloatNumber If precision is double change the "f...
Definition IccDefs.h:105
icValidateStatus
Definition IccDefs.h:118
@ icValidateOK
Definition IccDefs.h:119
@ icValidateWarning
Definition IccDefs.h:120
@ icValidateCriticalError
Definition IccDefs.h:122
@ icValidateNonCompliant
Definition IccDefs.h:121
File: IccEval.h.
File: IccPrmg.h.
#define ICCPROFLIBVER
CIccProfile * ValidateIccProfile(CIccIO *pIO, std::string &sReport, icValidateStatus &nStatus)
Name: ValidateIccProfile.
CIccProfile * OpenIccProfile(const icChar *szFilename, bool bUseSubProfile)
Name: OpenIccProfile.
File: IccProfile.h.
File: IccTag.h.
icValidateStatus icMaxStatus(icValidateStatus s1, icValidateStatus s2)
Name: icMaxStatus.
Definition IccUtil.cpp:244
const char * icMsgValidateWarning
Definition IccUtil.cpp:90
icFloatNumber icFtoD(icS15Fixed16Number num)
Definition IccUtil.cpp:559
void icMemDump(std::string &sDump, void *pBuf, icUInt32Number nNum)
Definition IccUtil.cpp:951
icFloatNumber icDeltaE(const icFloatNumber *lab1, const icFloatNumber *lab2)
Definition IccUtil.cpp:527
const char * icMsgValidateNonCompliant
Definition IccUtil.cpp:91
icFloatNumber icF16toF(icFloat16Number num)
Definition IccUtil.cpp:629
const icChar * icGetSig(icChar *pBuf, icUInt32Number nSig, bool bGetHexVal)
Definition IccUtil.cpp:1028
File: IccUtil.h.
unsigned int icUInt32Number
icStatusCMM EvaluateProfile(CIccProfile *pProfile, icUInt8Number nGran=0, icRenderingIntent nIntent=((icRenderingIntent) 0x3f3f3f3f), icXformInterp nInterp=icInterpLinear, bool buseMpeTags=true)
Definition IccEval.cpp:82
Type: Class.
Definition IccUtil.h:303
const icChar * GetVersionName(icUInt32Number val)
Definition IccUtil.cpp:1428
const icChar * GetSpectralColorSigName(icSpectralColorSignature sig)
Definition IccUtil.cpp:1769
const icChar * GetCmmSigName(icCmmSignature sig)
Definition IccUtil.cpp:1874
const icChar * GetProfileClassSigName(icProfileClassSignature sig)
Definition IccUtil.cpp:1804
const icChar * GetTagSigName(icTagSignature sig)
Definition IccUtil.cpp:1495
const icChar * GetProfileFlagsName(icUInt32Number val, bool bCheckMCS=false)
Definition IccUtil.cpp:1465
const icChar * GetPlatformSigName(icPlatformSignature sig)
Definition IccUtil.cpp:1845
const icChar * GetColorSpaceSigName(icColorSpaceSignature sig)
Definition IccUtil.cpp:1640
const icChar * GetTagTypeSigName(icTagTypeSignature sig)
Definition IccUtil.cpp:1594
const icChar * GetDeviceAttrName(icUInt64Number val)
Definition IccUtil.cpp:1448
const icChar * GetSubClassVersionName(icUInt32Number val)
Definition IccUtil.cpp:1438
const icChar * GetRenderingIntentName(icRenderingIntent val, bool bIsV5=false)
Definition IccUtil.cpp:2091
Type: Class.
Definition IccIO.h:217
icUInt8Number * GetData()
Definition IccIO.h:235
virtual icInt32Number GetLength()
Definition IccIO.cpp:752
icFloatNumber maxLab2[3]
icFloatNumber minDE2
icFloatNumber maxLab1[3]
icUInt32Number num3
icFloatNumber minDE1
icUInt32Number m_nTotal
icFloatNumber num1
icFloatNumber sum1
icFloatNumber num2
icFloatNumber sum2
icFloatNumber maxDE2
icFloatNumber GetMean1()
void Compare(icFloatNumber *pixel, icFloatNumber *deviceLab, icFloatNumber *lab1, icFloatNumber *lab2)
icFloatNumber GetMean2()
icFloatNumber maxDE1
icUInt32Number m_nTotal
Definition IccPrmg.h:96
icUInt32Number m_nDE2
Definition IccPrmg.h:96
icUInt32Number m_nDE1
Definition IccPrmg.h:96
icUInt32Number m_nDE3
Definition IccPrmg.h:96
icUInt32Number m_nDE5
Definition IccPrmg.h:96
bool m_bPrmgImplied
Definition IccPrmg.h:98
icUInt32Number m_nDE10
Definition IccPrmg.h:96
icStatusCMM EvaluateProfile(CIccProfile *pProfile, icRenderingIntent nIntent=((icRenderingIntent) 0x3f3f3f3f), icXformInterp nInterp=icInterpLinear, bool buseMpeTags=true)
Definition IccPrmg.cpp:203
Class: CIccTag.
virtual icTagTypeSignature GetType() const
Function: GetType()
virtual void Describe(std::string &sDescription, int nVerboseness=0)
Function: Describe(sDescription) Each derived tag will implement it's own Describe() function.
virtual bool IsArrayType()
wxFileHistory m_history
int OnExit()
wxStaticText * m_textIlluminant
CIccProfile * m_pIcc
wxStaticText * m_textAttribute
wxStaticText * m_textDeviceManufacturer
wxStaticText * m_textSubClass
wxStaticText * m_textFlags
wxSizer * CreateSizerWithText(const wxString &labelText, wxStaticText **ppText)
wxStaticText * m_textPlatform
wxStaticText * m_textRenderingIntent
wxStaticText * m_textSpectralWavelengths
void OnQuit(wxCommandEvent &event)
void OnValidate(wxCommandEvent &event)
void SetFileMenu(wxMenu *menu)
wxStaticText * m_textCreator
wxStaticText * m_textSize
void OnClose(wxCloseEvent &event)
wxMenu * m_fileMenu
wxStaticText * m_textBiSpectralWavelengths
wxStaticText * m_textClass
wxStaticText * m_textColorSpace
wxStaticText * m_textSpectralPCS
wxStaticText * m_textProfileID
wxListCtrl * m_tagsCtrl
void OnTagClicked(wxListEvent &event)
void OnRoundTrip(wxCommandEvent &event)
wxString m_profilePath
MyChild(wxMDIParentFrame *parent, const wxString &title, CIccProfile *pIcc, const wxString &profilePath)
wxPanel * m_panel
wxStaticText * m_textPCS
wxStaticText * m_textSubClassVersion
wxStaticText * m_textCMM
wxStaticText * m_textVersion
wxStaticText * m_textCreationDate
wxStaticText * m_textMaterialColorSpace
MyDialog(wxWindow *pParent, const wxString &title, wxString &profilePath)
void OpenFile(wxString path)
void OnOpenProfile(wxCommandEvent &event)
void OnQuit(wxCommandEvent &event)
void InitToolBar(wxToolBar *toolBar)
void OnAbout(wxCommandEvent &event)
void OnClose(wxCloseEvent &event)
MyFrame(wxWindow *parent, const wxWindowID id, const wxString &title, const wxPoint &pos, const wxSize &size, const long style)
MyRoundTripDialog(wxWindow *pParent, const wxString &title, wxString &profilePath, CIccProfile *pIcc)
icTagSignature m_sigTag
CIccProfile * m_pIcc
MyTagDialog(wxWindow *pParent, CIccProfile *pIcc, icTagSignature sig, CIccTag *pTag)
CIccTag * m_pTag
#define icVersionNumberV4_2
@ icSigLinkClass
icColorSpaceSignature
Color Space Signatures.
#define icVersionNumberV5
icTagSignature
public tags and sizes
@ icSigBToD0Tag
@ icSigBToA2Tag
@ icSigBlueMatrixColumnTag
@ icSigGreenTRCTag
@ icSigBToD2Tag
@ icSigAToB0Tag
@ icSigBToA1Tag
@ icSigDToB3Tag
@ icSigAToB2Tag
@ icSigDToB0Tag
@ icSigBToD3Tag
@ icSigBToA0Tag
@ icSigRedTRCTag
@ icSigBToD1Tag
@ icSigBlueTRCTag
@ icSigGreenMatrixColumnTag
@ icSigAToB1Tag
@ icSigDToB2Tag
@ icSigRedMatrixColumnTag
@ icSigDToB1Tag
icRenderingIntent
Rendering Intents, used in the profile header.
@ icPerceptual
@ icRelativeColorimetric
@ icAbsoluteColorimetric
@ icSaturation
icCmmSignature
CMM signatures from the signature registry (as of Mar 6, 2018)
icUInt16Number year
icUInt16Number month
icUInt16Number minutes
icUInt16Number seconds
icUInt16Number hours
icUInt16Number day
The Profile header.
icSpectralRange spectralRange
icXYZNumber illuminant
icUInt32Number renderingIntent
icUInt64Number attributes
icColorSpaceSignature colorSpace
icProfileClassSignature deviceClass
icSignature deviceSubClass
icSignature cmmId
icSpectralColorSignature spectralPCS
icDateTimeNumber date
icPlatformSignature platform
icSignature creator
icUInt32Number flags
icUInt32Number version
icMaterialColorSignature mcs
icProfileID profileID
icUInt32Number size
icSpectralRange biSpectralRange
icSignature manufacturer
icColorSpaceSignature pcs
icUInt16Number steps
icFloat16Number start
icFloat16Number end
icS15Fixed16Number Y
icS15Fixed16Number Z
icS15Fixed16Number X
icUInt8Number ID8[16]
wxList my_children
#define ID_ROUND_TRIP
wxString AnalyzeRoundTrip(wxString &profilePath, icRenderingIntent nIntent, bool bUseMPE)
#define ID_TAG_LIST
static int gs_nFrames
#define ID_VALIDATE_PROFILE
static long xpos
static long ypos
static bool IsRoundTripable(CIccProfile *pIcc)
#define wxT(x)
MyFrame * my_frame
File: wxProfileDump.h.
@ MDI_ABOUT
@ MDI_QUIT
@ MDI_CHILD_QUIT
@ MDI_OPEN_PROFILE