From e4f684f8ebf42845c244c5283a5657f554f78996 Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Fri, 20 Jul 2018 00:13:30 -0700 Subject: [PATCH 01/14] Initial capture of JPEGsnoop Qt project - First version of JPEGsnoop port for Mac, LINUX and Windows using Qt - Vast majority of edits provided by Bob Parker (archive from 2018/07/03) - Moved existing Visual Studio files into msvc/ - This release only includes basic parsing functionality; later releases will port over remaining features - Tested on Windows 10 (with Qt 5.11.1 and MinGW) --- JPEGSnoopQt.pro | 88 + docs/Calls-DecodeMarker.png | Bin 0 -> 113204 bytes docs/Calls-DecodeScanImg.png | Bin 0 -> 62135 bytes docs/Calls-ProcessFile.png | Bin 0 -> 136758 bytes mainwindow.ui | 134 + JPEGsnoop.sln => msvc/JPEGsnoop.sln | 0 JPEGsnoop.vcproj => msvc/JPEGsnoop.vcproj | 0 JPEGsnoop.vcxproj => msvc/JPEGsnoop.vcxproj | 0 .../JPEGsnoop.vcxproj.filters | 0 source/DbSigs.cpp | 2072 +- source/DbSigs.h | 275 +- source/DecodeDicom.h | 298 +- source/DecodePs.cpp | 6475 +++--- source/DecodePs.h | 494 +- source/Dib.h | 180 +- source/DocLog.cpp | 432 +- source/DocLog.h | 132 +- source/General.cpp | 667 +- source/General.h | 84 +- source/ImgDecode.cpp | 12639 ++++++----- source/ImgDecode.h | 1364 +- source/JPEGsnoop.h | 273 +- source/JPEGsnoopCore.cpp | 2894 +-- source/JPEGsnoopCore.h | 330 +- source/JfifDecode.cpp | 18526 +++++++++------- source/JfifDecode.h | 815 +- source/Md5.cpp | 623 +- source/Md5.h | 214 +- source/Signatures.inl | 6735 +++--- source/SnoopConfig.cpp | 1474 +- source/SnoopConfig.h | 315 +- source/UrlString.h | 6 +- source/WindowBuf.cpp | 2221 +- source/WindowBuf.h | 263 +- source/main.cpp | 36 + source/mainwindow.cpp | 685 + source/mainwindow.h | 164 + source/q_decodedetaildlg.cpp | 28 + source/q_decodedetaildlg.h | 36 + source/q_decodedetaildlg.ui | 315 + source/resource.h | 408 +- source/snoop.h | 363 +- source/snoopconfigdialog.cpp | 62 + source/snoopconfigdialog.h | 41 + source/snoopconfigdialog.ui | 409 + ui_q_decodedetaildlg.h | 212 + ui_snoopconfigdialog.h | 309 + 47 files changed, 34991 insertions(+), 28100 deletions(-) create mode 100644 JPEGSnoopQt.pro create mode 100644 docs/Calls-DecodeMarker.png create mode 100644 docs/Calls-DecodeScanImg.png create mode 100644 docs/Calls-ProcessFile.png create mode 100644 mainwindow.ui rename JPEGsnoop.sln => msvc/JPEGsnoop.sln (100%) rename JPEGsnoop.vcproj => msvc/JPEGsnoop.vcproj (100%) rename JPEGsnoop.vcxproj => msvc/JPEGsnoop.vcxproj (100%) rename JPEGsnoop.vcxproj.filters => msvc/JPEGsnoop.vcxproj.filters (100%) create mode 100644 source/main.cpp create mode 100644 source/mainwindow.cpp create mode 100644 source/mainwindow.h create mode 100644 source/q_decodedetaildlg.cpp create mode 100644 source/q_decodedetaildlg.h create mode 100644 source/q_decodedetaildlg.ui create mode 100644 source/snoopconfigdialog.cpp create mode 100644 source/snoopconfigdialog.h create mode 100644 source/snoopconfigdialog.ui create mode 100644 ui_q_decodedetaildlg.h create mode 100644 ui_snoopconfigdialog.h diff --git a/JPEGSnoopQt.pro b/JPEGSnoopQt.pro new file mode 100644 index 0000000..e91dd98 --- /dev/null +++ b/JPEGSnoopQt.pro @@ -0,0 +1,88 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2018-06-07T16:53:35 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = JPEGSnoopQt +TEMPLATE = app + +QMAKE_CXXFLAGS += -std=c++11 + +macx{ +QMAKE_CXXFLAGS += -isystem /Users/bob/Qt/5.11.0/clang_64/lib/QtCore.framework/Versions/5/Headers +QMAKE_CXXFLAGS += -isystem /Users/bob/Qt/5.11.0/clang_64/lib/QtGui.framework/Versions/5/Headers +QMAKE_CXXFLAGS += -isystem /Users/bob/Qt/5.11.0/clang_64/lib/QtWidgets.framework/Versions/5/Headers +} + +linux:!macx{ +QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtCore +QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtGui +QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtWidgets +} + +QMAKE_CXXFLAGS += -fstrict-aliasing -Wextra -pedantic -Weffc++ -Wfloat-equal -Wswitch-default -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wdisabled-optimization -Wformat-nonliteral -Wformat-security +QMAKE_CXXFLAGS += -Wconversion -Wformat-nonliteral -Wformat-y2k -Wformat=2 -Wimport -Winit-self -Winline -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wold-style-cast +QMAKE_CXXFLAGS += -Wpacked -Wpointer-arith -Wredundant-decls -Wshadow -Wstack-protector -Wstrict-aliasing=2 -Wswitch-enum -Wunreachable-code -Wunused -Wvariadic-macros -Wwrite-strings + +#CAL! Added source directory +INCLUDEPATH += source + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES = \ + source/JfifDecode.cpp \ + source/DbSigs.cpp \ + source/DecodePs.cpp \ + source/DocLog.cpp \ + source/General.cpp \ + source/ImgDecode.cpp \ + source/JPEGsnoopCore.cpp \ + source/main.cpp \ + source/mainwindow.cpp \ + source/Md5.cpp \ + source/q_decodedetaildlg.cpp \ + source/SnoopConfig.cpp \ + source/snoopconfigdialog.cpp \ + source/WindowBuf.cpp +SOURCES += +SOURCES += + + +HEADERS = \ + source/JfifDecode.h \ + source/DbSigs.h \ + source/WindowBuf.h \ + source/snoopconfigdialog.h \ + source/SnoopConfig.h \ + source/snoop.h \ + source/q_decodedetaildlg.h \ + source/Md5.h \ + source/mainwindow.h \ + source/JPEGsnoopCore.h \ + source/JPEGsnoop.h \ + source/ImgDecode.h \ + source/General.h \ + source/DocLog.h \ + source/DecodePs.h \ + source/DecodeDicom.h +HEADERS += +HEADERS += + + +FORMS += \ + source/q_decodedetaildlg.ui \ + source/snoopconfigdialog.ui diff --git a/docs/Calls-DecodeMarker.png b/docs/Calls-DecodeMarker.png new file mode 100644 index 0000000000000000000000000000000000000000..c592878be8de2c207976d2f2b4a7de8c68403537 GIT binary patch literal 113204 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

nCeR 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 R4Ho#P@KRN_OxpPC{{UR4ObY-2 literal 0 HcmV?d00001 diff --git a/docs/Calls-ProcessFile.png b/docs/Calls-ProcessFile.png new file mode 100644 index 0000000000000000000000000000000000000000..9de62cf942c9ea02d8307628ba756610a1b513ce GIT binary patch literal 136758 zcmdqIhg*|D(=QxAKtXy_5JY-MMIyb3^j<=52I&C=LFq*-RFN(nsS*qjgwTr$qV!Gx zDIy?U=~8nx=<~kMcg}zC<+_x+?9R^2?#|BqX6{Hm9aRc4W-j=w510TF0rTS~JpxSw1pvN4bD(G-El?%U2VfKQ2I>Gj0fB*p zfNMYuFb#SFwg4YsU_cv?#^I+3-x|CI_uz*EGX@k1<4wkz?T!uHcKqNT4)@&=qVREhAq@P#f$NSG7LFh62vgYZ zj)&+KrYh(SrYbZ&5KdJPE?qbp%hoHz|KhX9_8`LX8%_SgVI9I@P21bwBZVQUgWF@N zdNmJ(AJqM^1v_Be+d#(0Y-CpY{rUMHG+$1UjgLk&zS*{YNpz+g40}ppt^bwm z=j^=-F4{y5Mqcy)ME7@|?$7mxUnCcvK$N4-F;5*@6)sG$N67E2Opq||pKPClKqQ_! z9s(w2`xOun$j?w3=6sbata0>8Cce5cQ4o;>{8Qe>J5(w2-!ZI8(r;>a9arywQ;1{5u@-8@IooHWs#Tj!VeVX z=c)&FUCLcp4j+ERp~@M9LTDo9!}ll69$7*l`KDZ$2Mqq!LW`cJ{=s+0(!8K-bKG9v^@%4q8 znG#mA2#Qcf+j#89k(N?T{d$HJWPtrvoPn`DJetIt6j4@ii^9}c2;;1e*s@DZ42fN& zi4-1%XE3%wM{+dFTaFHPQ2oCivvXC$ zPh6n+Ygd@OoA8FA{7@gq<;;jb5*n&o21)Kc1LDrSc>Uhm7@E}69L{RW zS^5YQ$m;=1gC@_dhY#rb@3z?x zO?)qZEd$AAH5I||_79Q3xJRZHBvo0YYwgG@VwL%t-=M=tJM z8;K<$+?Dg-Tv-6kRe6Jg(cMojpea0tF{F{peRXGLYbPe%J3Ce`Gh!IGzO!|cnwsUo zg$PvaJYB8-jorZ=BC=6)^})Qc0M?E|vC3gD$|-Xa-vQ<=yPxz8J_m0~{WE8FV2_w~ zPprIA;n+}V1;nEI;yoY2)LTPqs9SmpAIwYD&Ant6m812_Chb0SNqV~;c&5C*S}>;g z&5v3Gv1w6v`Cw+oNjQQ+g0#(nlD`TqpY+Ebe)RAjkJm6eJMJBqvwl=e|G0Q&e0!JQ zkLbAKpCl9XJ}h62jP0B=+^`qUM{P#7c3m3zn{M3ohq{ z_Rp8i8Z&RB|M>b#G0S!jZNCqhddtPa4LvZcYxmpn03$~#!v*44#x8vo)M1>c z)o_Y_XuW?vN8_Bm% zaP-J&fbUybglJW=>_bAPNK^~8g`B!(vAg{n%cS_il!r^kdz*IEpE(_!2U7UlS0e&d zSPa9$fXXQY+Mre1h_4%W1jn~`?w5ySwfqlE>kT17r0~+kv;eG<(`tZ@yxe6fUp{u| zEG4yt`2N27C3n#xqVsNbKZE4lhI9zt5>K{cY{m!j>fa^>>oX)nIp1;bz%X!M_rWJ9WZnEFz<~x`Z`9)s} zBIqnNV`PuK?|8g_!K(h)m8r%QC5cncqrn1jS{woUqLDDWFC?9inz!?(87Y}CmdBJO ziHmP{_-#;CLSrFIN)_t4#yHt*ubN}@gRM;R(2)z5d#ctXdOkdnwC9`MCoAz;fk)A9 zeU+Tzeh=t9dj^c$)K6~6!QzgjakZq+5v?#GCKf}(@%U}3r90rxlG?(`Ue%4S1j!IV zQ5!`LFO4>)|1kFTrIG>U9Ra-b^MlDe`#P*Z>{tweEi2IMi|J49u{@~@aAM}t%S5f_ zLW~(ctlnZ61Vwgo^ab4QUqU<9hWe&IYqEVEdQAOSn}WX~9WFvv(I$vJ2e$hN%7N|vrjdeYWddE#O=_>_id6!WA1$+u>`9`QpxXly3#U++?LnMN_w+99gS`9fA{wC z!@Ue*QAV)&-lar)X1%7LYjfp-NQ5A8SAxheE?;iUAJi+0?9<%5 z?<0>E_7a8^TG;xeXrAG|DqYUJJH+XOB1039hhn>LQgwWKBkwMEA-nw%4++8g6Cor< zb28)Hu|S8XS3IKyyVDUNoXFS~jn$HW((?1d*L&%rS&Y4!Y(TTs1 zP224I+W3ZzEp2(AfUtJB*fIIuyA$4r;#w^7G=|?4XdCM_lI^O($nF(6`A%$H@X+;u ziTt`N)_0_7^Ud0S`qOqFOQ=H_HoL3rXvTZFZUIA;b*_cThLNf+?R1&|OBk_Uw^k7% zu2iu+_^`|Es?>#GQWa{JiVNWRx0$XRSi^kLpyh*|sCGAbT1C#M3s)#{){(H__}!d6`4#!mEmG~ zkGzBLrsf%W%#$wryrLvJ(U;1;81lhg>|Dlmw{q<(bH|XkOkls(GOqYB>uf|gC4 zm}C@BG^nn$&DLgk_-MpjD|z|Xl~7^)bg>=HAP4R%@x!`^Pd$oLQ~evH8jzO^?GL3% zZ8d?3YGUIn<*ca-}8+ibA7J)gSGJOY^Z4!;$p`Bdf)@7+)y@I8h4NG81 z^h3Q%z2r;dsL6b%%Nz{lDKy&FaUw7Cc6Fl@kk=HSsd+cu=JzY+pAdM3cj<`N7&8Q< z6GV4}KFSzeGccklpe;H~O6l;qyE8u~-oicCMP(%bW!?-xKUOr1LGtjgN6se(YCA_= zmz5tKQFoD@e$|Og&}`W!vO;jJ)X^*B4_BaU{Q+OUas5M)bbnbte&n43Bjx@zl>e$` zo6p^$_cSBSB{g%sL<}tLtihstgewOqmxTG}r>n%9>i!2NlIM@Bi%S!IWvj0x!<1oK zURoXPD&qGhY+=Jb&5$dM(QU@vGjwL-1E~?&$kg!L{*;=qbLyqeXnj_i$n}j5g%+O# zH~l8nINghcC&wpl*PGXLkDPy5m>k=ks+;g``nxCzlt!`b;W+!-RUn~^@ObR!Rq~RP zHktLiIKkm+9@)HdfhUY`L!Y}V20Jqzj2`y=0p4+L*D%X4kLkqxO5Nq7anD2kQXPXy zJz{l%QkPEnP`gU)<~fC<3N^$6KWw?~aYA+oqtx9f!6$PyD>p0YJXr^fnuCT$Jk*8t z(E|}PcIf4gdBXvmWj4wMxBQ;riRJAMlRLt`Y7Sf;;V7Bof+&!KQ#fk=+jhZy5d0q0 z?LJX{rYH5g`G|i`ibLRzRP>HTkYc-v`iq$#n)+6Wck`RoZws>G3Q7}){Tr|KBFR9= z@cu6yOGH~0#^TQcmkCExF9T%OfIbv+uN>QbFmKEoO$afM!kdv$GImVUheAGx+b3)E z2VQUw*5Wdzt{T%%j6W+$&;+wrpwSc%hz8me@fJq{NwO=)GP|#bzm$bw!`tDmqql&g zZwsP;9)t!%8%e0F0>T3L__kEklPMs|#)hxMfA}H~0z!vh z=?SINY_5?M^UQHo2~kDq*|GD=BFg3zy~D`@cyWPY_+F1a?T%iL;WS%8OEJrv=q$Zca#cfT^jB`BQ?7sg?r0>}(-&6l?dY2!28Ed>!NALL z?bChok2zT1?EgSwjVc&a4VN|bU)Fa%B85~CflZKYz&*I?e#lSzCe>csYJVX#hB5w6 z3fkb1ZIYdRM&FeDCs!Ahmi*A(O|<7N22l|9RnRuHtLW=br|o3?WF@}isLlOzdcdx8 z6K2Sun+q@GOGVNZ$}79%cK8`yu~fch%*%yo9()~DlxN=|FxdG55TNL4$1t>;mN)`O z+?GmI5kVT6`~*CI!E_Cy1o^MICThcQ0}pBsm_cyPLG)fW!Ic&XAi0Fm?IaM$0tg&q z2Ebn|2d3Zv96_Zdp(tQ@>zl%_u|P0jN2d4608FL=xN)>#ek{VU0s!-Z7+b>xSqG{VU>^5FbJx1@ebdAY%t!V{Aa-- z=<0aP8N#GM@HcjCLm0)RnO(CCkZ!(67H{!2u=#i|!ACkdsCv9o`E_b2HdGvp!maJWF1qyf5iV+xC7xJbWH( zg#4sO`k;MU$$x4rsDH$KHQt)z^qD_J`BOh&08D{1qp5XODd?hRTM=FD-G7J>PpWa^ z=^f3%$G8L1=-3~%5)RS9B&7qELYPpZ+Bv(4TAi}*dKtTF*<=ac`cpt8fM9n!p!}w6?HFvz|GLuB4zZ~I8O-EKkz3-*}rgX<|OdY_}yPt zh}s;oH_g$eB4Mk#_2Q4Z;a%|B;nGHlUaZmgZqqyC3n=7Xm5P%u@i1FRwPd6OqsKDC$Eq-O84w`KWf z{HXQrPN4##%VWPC*Gl8^{}YX{d7gT%4?==^t+9X>^$c6L_0XdW3rAT$4Lvip0tc8TASb{uhHb(mm18Lv4oSM*!1H2 zcdDccT_&{qLUN5~%2U)~H658o$<5KHtNKs7b`V^to{kU5O7ew7`sEx`EQ8EJNz1UdgZT92<=$>k&wS^Hw?x%k0>+71VsKP~eoi`FJO1pC(e9 z8`jiCT>p*aN7reUF1+FB29sZF!7r8kXfa`^f1=dWePTygDKsj)`ire7za^Cyrd{s8&GwA5OS3Da#f&bakzTurj~Bzv8pxOl z6JL)}>F7G-T3BdJTe~}Rd0Zoa&r=fzPAN2C2t$O?ppjk)t58X zK)D9zY@6Iexb%fj2T40d&=J<@+WlV0S3`q;`R>+>kHu0{@I}9n@BF&re*I%+uyKcA zE3SL(#k^H1z4f%d--xh)nviR%&!@@+eVJTxJQ^8m@Gel-Jj<^?;S&?hQ`0;o1SlaU_Dj$_J7+vr0>l|NEwCWVFlv0(M!+h__8Q_ zuA^>gqh?4Uy98+QXDv5zX5wxj@c^N=PmqlySKGiu2)lW#Kag(NZoQ-^$e2*E6TQdE9gg6 z7(hl7fIE*Ria=f1>af;Vt|n|7Nc z9NLqMUHLN2fz}V-xuEKy?n<_)%6{rwOHq`wa22|74*rlXpbax(wLgkZG8?HgnN(?B6jIBzy3lBu z;pvC3;Zl_~a^$oQN!g@Vnz-e!;e=ik-wJxb0sYlBoJz1l3@=Sw;Bq>sQmh+Y(J0BA zd2~ZkU;6r9tt!R1g;zD5e-DPky{Xq`p@cHn%a&r?pmTUzdAfEh zQN8vPQg7CC@X|Qtg#c#;*v+!C%gXAoL=f(^vMC^{(QgAqGbpDD#3N8<0JXQJV#iE; z@ixB6Do~BtOriYWMPPM5HHRB!r0YZhcTG84DgkYKcZbF?H%3j;SBKu{x=^rsXArY` zv$oNqxiOK#8Prw{iI``j=WbG^w|_|`Z~+1lpGa&>R4GPu6hfRJ5h%)?r%s*|wgISn zuLxV^6c9eSO&I?#(lMjo8aqf7?692B=(6v=cf5TjY>T7yZaadE$Hj>C-w#fHc2<3O zxjza#tUZuMlUVssoh*RND!%yd!L5~E^I)l+%VKYU2N?je50_vE*%_2UqeN^6GR4Vy zJWX+(R1T5aV!QD>)}p_|Kl%gQnMJb=TBCxvWn^KjFS}h=ZJC`&W-n#oS0m)C-tzF2 z2zPI*!8)EZ^J5mo!ASNtdLm|>Pf}TM6hJ{%mtqtEo^5dwa?XLqVAU8 z_Ao_ArK)q^^bAg_)GB~|-WJtQ#G{+jlcuT}Ju7nJk9lv+fUfvm(TaFWxn_Rc7b z=s&*)b^Bd4nxN%uFGg@6!&`|hun@sGU+;+)-U~jhqeHJ&UN6!@2&_7LZIusP;e^i0 z0mQ_TE)(frP*-017V7GjKe$sTyq(FH#J@wBh4P*%e)nB>o~PG7VJu5bw4no#!|=U|+9I%fe-0q_5{%J3*k2Cq*@@S5S=3N4u5h8`y}RCOK#OEt@FGa*bg-crI&P!rCiS#g zx;3j)y49UO6(?gnsklML%G4xKWBrvhq*a9-GsQo%{XkAjqlzaPI<4rOv8UIGVhdj< z0oe)?_+-}L6%F|-o%uTtqpJsxvyxKQ@AWC&Y9@ljz$39A1<)mx`L(=lQw$80?Wu}4 zb4;d_b;(=$xED0+OGPlM(gM1aR6!vdj^><&13gua9l!4&AZyPS;6wJR`y6t?1s~t6 zlHTwOdOT24yK2OzBEWAVV6mG~qudCv50k)(fy#eL_>>CL+>L!F0R{ z7dcBUAiG}9nZWl_vPU&u5XdJ;4UZ@pSpHwV6Q>5C=)z&AM)W8x}iuz1rX zL0R-lK}M&rZi9hGY$OHbEQR;`se9R)lQv>d*HSjAhGFcIFf!^X<77dD-^k8kLyqoD z6z-_2M&ws{n5I760-RLB1v2qu3a_kE_>oY;hsfELYXYMFOrDaoW0y9!%-HASL`)_c z1-{0VDSI@AwvV>WD{e2qYgb7uKf0rrD>-Q`Lasskw#()%EM*H;Ue;cTz?^IUPc1;C zYmD!~n8?Zf1q~LHtp4rt+gs*F8p3kM0T`TTobeiM=mdZax_1f&!aZjRrp_KbP(&5e>nOQJyJ(gebosJ$eY^pZDd*ZS(y#zI zME=)91LSaJ$lcNm;16k%1 zdrxGy&`7&aC4b;Zt^9^W^qpt~8SUb+2tHFO+hgk>ewYSAUfDnPS_m`X;2s*= z9gBtjjz3Mb;@X!hvlQ_NsoyO!0s(&0=Ts-OCdBfCH9D=KV^8Z5pE>e&p+G~&XIBM8 zt0I6$-C820uRLhthoxbCDXzkaHtt1YkD2%|C|?JS5xItQxhKG@(T~Pvrx{d_i4Zu+ zQd`&!b7GY4O^sb>B|$Jvaum8GTje3!5LH{Yr=L4Cyu%V(zOQ(kI9&o6v?8F*=p-az z!(CX`zDn`penS{)$0DKX&j%{)-Idw1kkKO~Lf<4Od{} zLr0y$KZvFexH2t5wYmIbCaF?mPMA!5O&^2>)~bQa}3^LbYpy9TfU&SFeC(KdyC>z zn*oJX95pevk7H^?st6%60EEZfD2)11Qh-h2POwmc(F`gV=MQ|cjCMn#@wwO~B)7F9 zlf-8Ju@H2cQTCSxN8{36a`ZxqJ*gHVA40V#HUmr=pb&H zNHOl~b0+n(n#ukPMCI;Hlq!f;nl%OsX)&tN zKec~`8A+x}jr zd0|a!yDfar*jZ>aXThL+=fvqQNkMBVJzAvoGT5K2T&G)o$wRsAuaSXuSkcXeVqBvM z!&{@g_Ckhw%y;M|o4w*7+R3RnsWEo)8+sOMeNA>&!YaD-Ik>|Q0sT3!LhEH|S{734 zYbTIe0EfKiDAYiEy}l=6<1Nfm{UlIhq@&@*^3ty-rGj%C8qU}q_f3^n{;XLFR4>E|y|Y{njA8 zQQv|aJ@CY2JU;n`=r_~Svhth0aTJfSq2yR$sNET>)7kWsHyEzV4)nj1xNI)@%=W>z zr`K2>5CBM4hui>(oT6szed9s~l25jx?`SeSbTvjuZqsKh7!R8OSaa>!Ly#QKc!|)y zU-(x;z_HGbRmD8oG=oZ}>y`-c&mn{LxCRWH{`uA9cG&T^_vtKK2BymyLf6BvlzpE$ zHAlOR4Q!G{nJoC{42+n9^ktsFfn&W%wfo|?rw{7=z>CCPDqLS8sD0oDAg_hg665P~ zKSYq%EfbLx(YYvZ37Cj^)M`_$ortW|@ePA$5kf1OqHLq0g!1Vb-{9JO7rtS3k(#gX zhA+a2+-=LTh_5oH`4Zw9iTNY^Ff*F5JdU+Ris;z~5c_UI0(1;#)AiD`sM=F1p-shSx0m8~4;Izx+t`&3hb8p$Ga0t}NzV*&p`<*gV0hSUTK!fGdFgghwF0H7S5Ome_0K_&}&&yuK$RXJ|HpLu{&%^5pRJ8iyqQ8$Zg zeG!LgnAFHv&96nO@vpxMnlyd2EJ*`6E{g(!$25o8iu+7c26cv(W7QEU2D{do8p)^h zC1Gq#Pdw2~BPm(0uoBN)^x=!L5%%%pm1l~ApfA5MrLwUNXjrrSwM!4;A%cjWiy0Z= zzid;jR-3Z%J`iXFx8sq~KtizO(rqcVyqIeLKQezqtjl(v&Jp6vvp^1`m}poye*&@e z7av(vLl&#V`cZ&tm~#LC%jAhQuNz_8^*3?phR9&15Z{#+d{P~soIJt&ee0Gxo`hVcTJ9LP z==6x!XiV{tJs+H5{0wX$P`;7-H3>P3YfjH9#NlE@oE-D1R)qiOty{r#64KlEn(D*U zps1&~u~`4;nchbfq3d}3emY6u#wJ_4k-K4M92A(2pA|}o@8t9rz@@l#$><@Si?+XJ zi!d;(o>=U2Y72g~5<**6d=W|k+5cOF0ucWv|DYm`n18zcuX29_IC`kFaOy!n&CNOwh&|uXz(ZXf7QAaK+)XyUJq9~L(Bml zrQ)Uj+fz59L9o*+PBi?!T)9@5F8NJM^;fADxjlzFvSp-wM6=9~B6>n1;X~@b&w?JI z{r?0#PUoz@yfC@2W#(Zu@uc5|vzx>kU|67R??Xq^>zh``v!ko$=!;alV7byw)2mN? zUk3eLz~>EOn*W&oiH|sPA@@2bF+A%+Ukd;UGGyZH4}4@pxHEXKmH&+r>yl37FY79` zh!$DK#^Y6%YaxUCNwHc3hF(fl#8xd~*I0Zn04QN*M{!tf$%N;FCOUqOq*EV{{7>;; zGFxJ|XFV!Q+2$E~oIlW>#>k>c3nvmKi9k_2B_5eim>p~5fqf3!@I!m9NsIo}?k{v& zQT9WBH=u941ZLs72u+606B~v}$M}mn=Sb@f=Z+d8=;kE%vQqm9uZ8f51V5sukc-aH zLV$A0GpaGDPx_ZC`D?Hluh2)Jh(T)W z3aHv5e%gL{#!_R%WrE%?&4`i*4_$*0M_J;pci^MNkAh5kFvZ{ zO%C~aOnUlh{&CaX)fKAmQOvyMCtbn81R%;M0w+&PzTdUU>g`IKgJ;YC@9IsmytAL6+dN&rC{WAsdv zGV@3e3!_Eg&g)DPdKkBjbo?>R9LUlViw=H(38BL*e}J>#hVjt*_{J}>g^Z+*D;f;{ zxb834DS@N2gq19II26r9=onzTs*gy8Pc}Vytcn=zKY+MO=jk6>&zNM!$qU5RC4GvB zR^YEPUf(M6@!tO%>(@KQ$jY64c`vxZF+k~?~eV3u|-0_88z z@2}BbWQgQ*6WAgA;A}J&B*~ty%+<^%TdX;dmO5p}a&BH)qg;y0`@zVLn42gaONZ&^ zO#lyFY#Sv!9_%L4DaorU$yZpqg`EE;?O&j5;3H6=@wC{nMsYB5UiZ+jfW*JX`e%6< zWm%qODIKkajk8v}=|H7jvgLvjq7^`vjCvv%lv>$*h5Jk+6Nqt1@Py~SuG^+th`Ucx zfhW&};TA_zk0b9X-4lU<;}S0>$l^XQ#fy7a9txq1l7(w#TlW}`o>l(hOXdhi+n#q5 z;gLI6f>nI^5&l_B9QL{k(Mtk!8t;vuxY*Vp=qxRDhMz{;Xrul0`}mMM%~9@Frk|}- zDrA@h@|7P~;A?8j_F_?#V!0{1|<$$KL*#6NjHgZO9{)cSGRc4)%3Aa>8 z)zyd|nN#y~CZG6W(i^m)qkvUMC#mlCei4GV6yO~=LP<&BVtt2S&-^R~ct(o^`V7c{ zpwo)y=b88MHHQ3PScxDn$ZH5(OlNNED=O5J&xtIeM?zEuQTy;bGr;F5VIR}wo~yK4 ziUOdtM`HWC`C?dx0wVVYJM>3)P(;rgt0%_bXyx4*yGiv8R8hy?dxpIe(L?;Ii5TBq zr*_nFQ2*aeZ!|4SWsL%-0^+l$G2-EU4+2AQX%;8*AdKq@qaktp-##y+;TcDtb|2o^ zV>}ykHJ&tulhpM`rPzNxF{VqQ7^VL*O&CjnzT9E6deL3+AhFg$H|W-e_(iO>5Oszph}bH3Z7J|2e_Dp=3vgS+`)$7B zDufHCN}o&e6y+7u7vk`T7$!SVvl`Z*uZgJ_g~6cJ7xEpe$u^qmDBB#;D}|WyIirLh zSzAG?e?HI1Q+`3{@_`I}Ky48&Q@tH)Z+L{LRW$eJ%Vh*!O1CBl6#&h6JBzYgzN2~sMhd38S^NTMA$93znhQ_S+f;akOwU>o|MgypKm@FLl}MCSAAc~ngGUL)BdOt* zMkUs+yLH;uRbTw-|8sQTJtp7H?wQVwC9uuL^I!P+2k(`$xKUf@ks6BIL_uF0 zRByROjuU&__vCA}2TMUOMKcZSojrua%0=IQz#)+m>6J09oVndLpw$@2c>X|%Bz`RK zkb+?|Y09o4nEHLd0ZaK@uF+nid0xBmuX)8pe%OJ>syr^H&8O7{`1;>K>YT#9j{b#G zoeb~)!k+>ukwjS%KO+H~c*s+WPi&T_-{WlrFC$CHyneBqaAnR*HoL5wdcS_Kfx1GV zL&FKwv{c)ooN)wdj;V)2p#8I!F0))VR3-I2M(6o(I0{9vN&f>1-f!$K2~C)*VAHo zChZc>mU%?atwOkK5UJH>%;+o#67aiOI}Q8piwst_yM4(FRryJuhy~>M6O*EPm>)&W z5aj~X_X((Q@Hk>U)Uo2EqNnIR;UgjtBN!p7XJVz+WQ&BmP(spzwqm0ZJtM1G2mM$3 zqMb#m<76qD!`(VjYv7eIC|$ThGYMTVhGsKV&`0!KA9nPz)_RCGBG65;F!MJCSpw*% zSJ*qMAg@)ITweZX|^vF(p3nLf-U2_;JfMvZt0xuQrQy+d8iu4j}=p!=) zk;rQe^hoMYt`!pn=ep!w&>K`SrpZ08&lO7beD9}|cY#>1E;+!F7(oCR>we8ab-a>< zWZufWt3>wtcDljHuo;11DE4B$R5;UBchv1Z^-Bh!8IHu}K>hzHUySN$dQXTt2N$~- zjgl%vK9}LWr-#_cVsPRHq8W|lQSifbe|O99K7>z_W%QC&(E>&_5CQkuWJLQ)7U1uf z-zf+JwZ1RMW~)xNj}EdzT)~K+;DSQlh6L`}f9bG8qaWeF1rXD!!)C6DuP&N}855!} ztN4)ANNw8&e3KFE2YPzXwea`kc3`BP{N`a&wnR%ea~?tpjwW(dws-byRh(k1`|t4e zP7c@5&sO2CFZ9j5Ep!<1jN9!Ek-!nPUyb zfD`{&JBGhd<6pUk=Hj+}$g4j$SEJFi#6FL!>nA!tJLJQ!M@e1GX+GeknT_ zS|GMP>#!1i{1!>6Sr zBCDv8E9VU4@SnkrNNNjA^9M1VjOE`=Tpm{w`Jpnte4RS;S5mXdHC`JIf5$yz_f^HW z&65ISCA`h7tFeV=K(r1Cxn=J*>-{^nn(Fis6IXlm8#JotvE z=EI*#`SnEXM)2?j$j+z#D&TP0e@5w}0g9KUcGL^LKMM>Wm7)PO!Boe)pCzaaoV>xa} zM-_Cr-$V~&NmKfyH@>0x{rOZTYN=(erWF2Zo}hv;qDROa0pJ_&qZ|_BaiLH=DPB+3 z2eieFpJk#4!}h0iH4suW%ip&DyMW`TUU9p_ysQ7}K;WG~|2wYBOT1wnvY}1*$uN%Y zk?~bv0(E%~jEojP?ukqeoYik2s3)($#gzWlX>{K)u#j)~-?}2;IY8b5U_|Jaryd6s zkMdn*hvqMRA-c~7d7y`&u|Rjc<5WZI&xhqtkhIcMXXvXTzDLtc2A#-5z{g7Xma2Va ztwB_9B8q$A!1V$dGjh=C4zO#s7^3^2a_Jg6_N4kc)9tXw3U=Uj0Iozt0la8o_(N~4 zPw}Lp8i>rMYT8_wZAufTiNM`H#NnmqPi=vfNCKacSnj2e^-GnSdTdGK_BA?FtOo^! z?u~9$w`zj(qVo@TWNbeuq^QpHw>H2s?tWeSRys!Ne{y<<)VU-HWdeV+va2lecs2Pn z$-HdTh{h5!ABv5+X)OM`EDCk0nVWIk0{@ko*QB<*oPSJ{S~E{E!O4LUsq^xmR{R%G zSq;1DyVp%}2D?Vm=|6Bk;3orByDFPzh}DBNk?TSi7>>n6G4IdL-kbVeOFpz(3#(TN zNSzCRwgmrXYwKARA~4r`|Im-MR1SRKrj62s+(gi1*jKXr@(%<0cfi~gHj34fC&k=(IBv0$ zep4?5gio)8#VHiZ@c|QH8I5&1FiQdQYRe1B`S4VJK_x!drK-9Dpe%Dl5!H|1F{~$~ zpoTvj`&lO%RUlS-@>J!t325XdSOpRSm!Y8p4tn z^#rLi)GecBu$F2gwE0!@*A;-p=DG0VQ~w*1dR=;h>NdXrwE7k$+t#A$oIJm=;G$V*aQVZAj*Zcz{Q!I{6%WSpf1zmoo{5o3^N zD3py4%rmK@-Tjgb-vTB(aW#+SYL~KsnLu`wal^m|LC4fH-)`unv^z;hDbliwl5d|U$%QoJ`NqFb6yO6@5|y%XhhEx zE?_syIk({v^q8Ry|LH0;P*UGKmK%oeI10N)E^;j}Zw|@h;Y8GkmX9;4_d0$A1L&A9 z4On?4D;K8|ke!6d$|-_F_4n*6fcZ1`o7-q>zz`JGgpF0LQt8FP1*`& zL{Z!uHi7ohm#SvuMyxP*U+7h;(wrc-uV&u~rcxnbjR} zK@pSK1>oSwk5BZ@G;QT~l9eplZxdStHhTj1Cf69K`@wveEL^be`HwqDE}` zPZP;0S4iG6fW4T}UW61VN#EMg_(K5GOi598i7HGHiO8k-FQ&Ki1vbYwnjZv3lDO0t_A+rELQHEDNJvCN&aP*M;_b zl|?6&?^{}zlydqVtc3+HNgDf;!G9nPj9c{i7ngR_UY-xAnNEH^sAC}c^60Pu*%`>~ zPz)yNYsKOBm$X`f+VA&USe)bm?E(RBqNx?6#?3B^Ya~F#1Z>;&L7#ZlI5bnqmWCDU z*T1zVk;1_ZelQwb!YO^^2lZRYA^U8D+kMBDuh0K_S?RS6juR7?_^sKx3;i1G(C}_C z^s`_eSfKz}UR0+j_^hziCw}K*X@9kvC2PqlH-ix7J+E<=w_%(0G9x zqyBgsxxD*WKBu`Sa@~Rl%0HU8Bdg2SEg}U|PWi4A|Ms&o@!7@-f11%&R4QQ7zGuc2 zPWQnle#^jMC8A5PPAcIH`+Zw*bLUAdeC(@I4 zK{@52Y6ga`mc{V~P@T~{fh@`<&{p0ArVd{fZCmu4P7c%@Q68K*tZz)fPmRgQY>b9L z+!G*d|GUc zTY{6Qm9XqHHZs(|e_3kc4Fn5(G-}3-ojdvzn&`r-f@~JjT;NMJLn34+O=>>s=Jk(N zmm+%D?=kx631gu8K}M53*X9AzFsvM5wx{!Eiy#yQqKTWm^^6RWnWX7HOm`i8op8?=vIaaY-!zd|@> zc;AP{=;G!VADYA6(bZ$|+4=||H?Pr1z*_4yuo~~jldi%`wdJdAtR;ApT<5yZpK#yz-fOSD_S!3cYYq0(WE$WWuiQX5LJNY2;Sa+7bj;bCxxe&ouIUjz z*exGTR5m1IOn00NVBRd%xwNj5y}f8avQY>tj}$$GQ0JGoy_gE{J88G0~T|fXDZ)a6F&TA6MO5&lSUOi z)=wtBgpGM0xfO}5?!H<5fwsBV^h3)~QG8iiA|yqxcZ6f^LeM=&inI%LmURBX;^$%} zFmHd2zSkF?bw13l=)*Qk;r#hW)$yE&rc_AlQI^oIKb;jkPD7z^^T~*zcuU&}RZ3@= z0YjF&wJ1TLI$3B(5_1DXT0%nHd5ed24reEA*1Jbg`^|&z)dt$-3dUaRvcFHB7#bA1 zhy9Z9Dsbm}!(}Hzp7xL?7XPa0KUjTC%f!Cut89a1r|x*AbftOu>m&cuCn^I^<0Z!m zGGpVdIujB$-ch6W*>m0RZF1B87;aUqe53EA%R8O?(Hu+ahWGRxd_?{#)`<~@J7k)75ZJ#!cYnm#m)$J=Xca4l@yzkc{9W-9tT(?;2-pqpoX z_jkgaNF{w}AA=GM?zi(+PHF6)WB19P?V(**WBP-FyU+hx18^U%U7yjG$_D0gHg8cn z<8)gDf-{XO?HQqYp10E_=ju0NEbp89KkC$kkIR|HP`o|`^Goq5wm*j@qMkfxh+B&7 z*6hq{NI#5Q(0M%d6@GOcXA-zq9G>guz`2~Av;k~Z1=i$$Me1zcUQh%| z3fA=9@C4?fyP?qV{|t>n?Lsj}?!TxL?q=@h4R}7+|FJQKKvj5G$2e+5_V&rSmW~Z# zBQA8cpa@QxF-!D_-y3k?l(!!{y-AbD-F0t0H{In9lDU5T&@pi=d-%)B=T6@>GRvbP zm$EtN$$hTo2;CoF+F=u|ufT~|>CnyiTS7n{3rYy$xzy5gxt@p+?n$O9-+DWLncwj( zA;E=fJhr7K^CZa!a)KIMW=gO@Fdndfis}FTO& z@*uim>GV>9L1L!Ka_n&+TjE$==7y)vRpuyd)w5mC(fLJlKmac}y|L7Ge2+cRVlLx! za6BA);4sC)QT zKC5f(0hu5nrT`Xr%_6jHY@x9V{Y46D?W%`-+G&34C>x#0>tpb#MU`%6H!_AaG?U5T zf{)i1XYL%O7*VE`rQjQ8!-epHl?Xe3mf3NUgqukM+LgReU<$P0WF9dLQ2tXa?)>}B zh={jvt1W<;x!qq*yssnw+ky*;rww;otNhuk`A(Dx-YZ)M@u5>cetwRalPKuIp{S56Nxp1z0LsL3ud^4NmaTBozgmBWH4gnU~nE z0HvEwfY0?&p6PV8tZiC0g0#TaA*{=0`8sSTb$C_hg^2`&w8MbM;@4S4G%$^ypCn0#dEt_BvX%8vbSGnlET9Wq@Idb zD~i0i$o&l2?*3dQ?>Rr2!$1&%5_L@5B?At2a!%9mw=5 z$)d;|hd-F0!s@m~e@5FF+gBi1dPMi`$5O=% zeYY$`JY+~*=!u;tQ$V~M!w_7^78D-ntf=YV58CQ;tRFpkmH6Y3RKjOnY7w^1g~03amN%n$XgKfG_CW4t_`oAL!720m~GzCDKdG-|=$ z=#ij+kbfu@IvsqimrMjAf<9o_N>q{GtHuXpfF-~vzhCFa53o6lK$;Qj#3s~h<^-U5 zKs2uT!7SDEgZ*sQUd!uv`1g;^RvX$|S!BC;GyRyAx0M0v=9V4H;t%XG>nh&fRZ~#k z>}qMT0(l*+>r_m$mGxqFPXd%lg6t;M0cVF>XgqxRFwUsnx5T_?ebvARruL}qQ&#an z{w`xz(onIN>P~$#Aj1g6h~*PkbEgnvF#ww+U-K+(PvNY&cp{G~iN7F%6w4#!&$d3X zT5d62N#`vDrXI+d#nKuwazX!=pE;q_W6$rkB+XHn~IXB zaeXzyo)y=E_dlvQVCnd*M`5XsdokCmy`jB_pxfO0^h)5-u58CXBUv1NE7)x9($KO8 zy_UQ2aOnp1vb}=er}+QTS|kymorMODzfxDqGUyQkI7w%q8gtUjwV(6P$b2?V!T*oZ z%cXwh=*%||CGAsXL|H8!sH#R0fh|Zu1zY|tDn15rq@W6kfTS>z6#Ty+scag5fyTRozk(CmN3K{t@RD8&UR1qW zvI=Ag91HS;CR8}07*7ixSjTikBY}^;QssC%Ag>ga#ts9G(7l|1Z+fQ+uVMMVB~!9` zaV|3e7+`f+g$ALD7!3hHkt3s|M@@SAAqG12b41hTRxY9=+ z@go2LC&0o0r-&Czl!ri592pW&4f~rmqb*how>1YL2O|y6c(a0el)?}tm#+gr2w)xS z{R_Mh`~fnIIPk71qF5^KN|}QGTPiwpB?oi_jp6;?PF1@W=g`Ig7LZoz$o1oA|4J*d z-k`XBmz#J}288-T(^2C>|I+fn*2glheuLji#{v=Jtv0$ia)U)-A^g4p@Yv3*k@~(j z$HZ5o8MdTmXkrfZlAWzV#rGe=#s?vd(SZkCT%q1t)I|~pB%@jWwt+RzE{zs)e>eTQ z)i?Q~T<=2e@(wQ?^ryQGN@tzS^RRG6LPiMcfANit>=#xDAxBGIIX{GM-~Tjs;u8~9 zbf@y7ck=r)z6JsphNNzvn7hcj6VaWzu9QG>`X8VPkl+h9ycfF$D}-YJJZHXVi1>kO z@M!<9^bV_T#h&w{^y3-4xGxLx;!zQukQjT(VI^)fK*KbQ(cF1=%@f2Vi^}CynN=Ub ze$1hr%CfYA#6L44nyE;Jqsje$Opkr8o{SyZfL)= zNMK1a;Ch_+|E*$jVVHOf_$9a9MsaP36ohFVinan+yi z$!*;u7q{SfcoM~A8>^EMK6i6*W6~kUh4oC%Z$Nmk@krd4#HEs^z!jh_&$%Olc=c9XWygH0ur2#GTJt% zIY!-Af}@iIRtrA@I#%6a?3exab9evk`by`T70Jca3_wk#0yzsfOxbmt$USnrC%*3g z&87vl78UOBs{u7W0Jo|zYsI5M-GQ7myx{FzvvVdB1&K^>-h#cd6h)~u_D3DJ??Mjb z#QzMSm6wnWA~FGG^vj?|%H0$)Z=(4}Rcz)d3}i2EgH9)iuEOX-Jf%#t`_eO&z9!=r z?lz!Q{B}IbD`Xmx(9d{FEXpdn^@_31AME$*XVv6sCEF;aR}87w1vT>$Yb|ohfVRi9 zo!{<2`A<@KGbC)T1j7|#0?jh6E&NeafU3YC^x}0MxW}j$hrfF~W31V)<8_jb^TY;}L9w$3bjHjZDO>6fnuu#pCj*5n&%>!JdMm_l z6>?rk>>lM!(eXVCPMx|s31lfp0u+wfq_tLRAAsD~2W-Z3KU_&|E?Aq}5L}pF%ppz7 z73LN&$k&@?A~Lx;ij0vKpXEMg8s7TilcimH_~H~Av7KNiHF(?H^$R!kl zEoo;T8!=2^whXTkuz3i8De=1yV2;Z8rm2==G z24jKT$?EHjp##@Nx*0O*5p9o zl4jIr?KsQtE}AbHZ5h;Q_Z)uU$pDzv(;p&(u9fx_eT?zPeDE{;_dx9t7{H?3__Uny z*;DWz0n8K#9tC<~8=rJMb;jqH%E14Xb7_8%L6a7@jk4Lv-t!fj(ZdJr>nPb?eYPk` zmU!=pRyiE{6lu;PzoE|f7-&ou7Nf_4jRZ2h9=orfLQTBGj=fUxyUuF0njjMn`rDO` zHPZ=J@w}?~0PCk>8{{PktsIQnM<2dOFIWO-n`!wU6{lCANE%hY!Vnn8W?$ zy(szRWtl?zaKKe>JzTrSB>Xzt;2n^-DR%U@ieVmlE)T`&y$Qq$mBRU$&2U?R6O5yb zc!;VEeQLG&&1^E|(LV}$`q70JnOT=x91F?ZTu84#Y7C+&0kk=02cfVfwV+wOZ%s67uIV~Hto#fowo zz7KVxI`PeMks+E5}FDJ^H79=Iuosw5IpJ?~cdZ2%=?sN6YnpW+c6y z2BKF7l6g2F``6_LbHRl(nc12p6TQ6;xbr&+?7sa@&Kl{8@4zh24*oGFM4~6$qaX5`$Ij zlejRJ_W7hVQIm@Q#| z+^b5=me7X5M6TKK+nsa6K{7Nl5N9VmGV?H7`zs&Bl!~WgZAu`l-$~P(gK^6se~q-G zus1-wRi7MuOdP{Yw=O;r<-oANTyME8l*2rDi#!d}WyLRI8?|Ct1TTO~m01_)lr?>) zfZhb|?x>txQ{G(e33UQFMGX%Y*DFnpzAar&;333MNtwYzXosz(9EK<9*I z-0}2CTxP{ZxhkGK%2f8{D%6QZWyWcBniIuSB~d`NU=g9*VEeIjL;Dcodn&Mek?##O zT|I-Ve8?qJ9pi8*&?_iZAePEdDp%>%4GL&B0B>U4QD8dVskNYYiY=l`XSe)x+!W6p z8^%Yg3H(|x9)>PhUG`lvub)$hp&86a$)CEpy0eD7O_atEzY9?3XQAA5pDih%byT>x zpzFwo5N_P5<~1hgNAB7Dk0-)AkrQNE@YYQIJCIL4XF=Ug&ks{vHfL5?B7xGGH=ho& z1{Q1#FcjWr$urfB*FGCyEQ%Q9=vi>&A|wQXbq#ZRiF=UCx8)54#>^3qrO`-IY_tH4 z)jsQEB=Dx#9FP0n3d~LHm1#u%=!~3+_s8i`c^j>9+nbCovT|UEA7OpPYB-FnW1OaxJk8=HC(a1lIH??!KlIFQWfRb2f<D)94>U6F!sjSTc$5ceg>>APo*REtwf|)}|SC^Q0ru70(^mstoX!v6 zStCb*!o*acH(Rb)cCXcX9_lK8ncI3_j&8Y~5;dLrXppS-S+uK#YAx;++R2=Zks-mzrO~h|B-xpM+VjxN1G<6H!0_ed;a(p zBFN&*S840Iu@~2|EKC*t!J>BGT)TqD(a;5*kT!wUQO$x%7>}>=)^C!~*VQ>q+A`U@ z-x_6yd^gibm;N&;TuKw0HskM#kgkJMzRd|F`}Eg&yP^(D*KP!**IDn>1;1 z4JLW!MTMHxxeOih|59#DkLubG2Has0*bOUN71p4gAhnyit?|G7^5GZ_4%5k7P^xqA z0q9&t@!CD3S@XQM)Dpd1`e3`%8SDmhmBuZy^&J4hmt^p06;)GV?pa)@$1WCCU_M4k z>WuJ$$_+_VFBT=Z+c!cqLJ)g-ODaz8(-dNFrtMqEBRkuT1F8_Q&!0lEUyoa|AlJ+g567caug=NpTVAfVGak7Uw41Wk~BlZfQ8wHyXShf7oOLK6ccG32Q0SICfd;-$hyzkID3aL&G^?J)EL& z_){u!be+4V!DHu6YQlDJx%s;t4F^PHs>g9`v!H@IbI$XG(C<5SH-M<-L_< zV|5(iF%x`DYA>SE0d)Bj8K@e_moQ(h$M%eGXvo~e=<9Z~wnuC~)R}gCT{i2-18UOa zUYa`>11lhwHZScp0)aZV*F{Q9rz~i=kFg+uNiEW^1tSHz6#lz;@0%z5&t+P|cK-;6 z*bfbdt>#*9{Bo1L@=yN<3xIw-T_QkYtoGjC#?AP{N?8hg8!(>wXf*R%EGlz*;NvX= z14hL|x{vWUAClzLKeBU{2kwN}P0l4!wv^avs~lZNvro2Bo@?c&+dM6zt zr+Ic)+WGizJ>(vMGV=Bwpqio-XY2f?7v zSF%eNXyx=tI@p5>Y#>l$)>G(qtII7VqqrY~UQ|3ng zb}+QlgwUpksYW@pJc&p#3w2NiV`x6-AC;NNkc#u%$^Kobu=h*lLMye7YBlVIB|`Bt zXy#~|N^AJ*^1_+Zd}5=1AqdsLhV1MWM7IYtTrT2GLTGz)e9sZ4Q{?lFaM*TBJ1^i( z;px>M4}xz^>bw}^=$yCAbm?tY=q!Y;7WSz#t%to(N+WER`Hi#d`hxU_4MmuM(!hq6 z%Njr;;$faeaRd%vKcbbqRGIGS_$JhjWj;+8TIQ&eNF+MwT2LR773dYgCoO1@whwJN z+HwveqKOMGZrDt1T59R6(AA4eviz)|dDT3*Iv?e;mGpYFb(u+WPuW&m!EcbVsjJ@o z@L5Fu=4ev|x*>l+K4n)H_%VZw?y`w9`|O|ow(!%yj&V-J#%&A0U~q5{&gckWj<#_` zu&^zQe4;PPq8UdvOm%?zRVk6Gy1LDRGcTxQ{M20$<;q^{>p^AQL)L%yJm@5^&iT&7 z0{yWtQ!e+Yp{H9Q1nxf7kM9!4^RRT(-24vmbbGB~ z@KB4?sIcWYkom`ptJAmRVTTd{LJy2~{h%BILroz%CaZfY`G-q&}KcsmKs>9PPgSFFf4>2IDwO{})A?UWH24&_9u@8%npn4Rl4L81}fO%&*3 z{mdeLWk<(AZT{WT^JnZxTRoGJp_^wR=+wO;a>St@L;m+G(E3WP+^_tu$ZxY}(LaNE z9`JZ*x!(aW4QFGUb1rXbiNuPZ*4GU;miqBMWga&lu-{zr#U<%aG>;HM6tp~J9{%`x z_RvMxGuc{VmavA;i4d$?A7&9Ug*bCAMwnGO8J6W6eCRA(BNUwoQu?FXBon@^AmaO0 z#X0CAii+OY2L4>$vqmH_pg!%Fmd?zNmd*@?sqv$LLtDEV;CPMIA60e6FF`$ zx$v8e*GW{g%(~Z?zA2R#(c2Au;AP1xQ%dLOZOx}8e-(av& z(wr?nKURA6bAqfU5OSWp?LvD@UzZc`3Rop{A)RZDBWPQz=+^0~>8D7o?d_ugfLc7BoV=FUa- z6x52toi;mW(Zd|f;~l%UnL=+$ygP#Tra`O8$YtQ=`<7cQBw-H@3stMa%uoCbw@*;I zZH%9lSdfK^PUb@1ydh>kH2Ld$2J&n2zdlA#G!oCyNy!sWg65j3-yVWc2DZm`O7-(I zmQRa|y_onShGaAUG;`mK2%_)1Gxh4n#tL0WbG#rvQ=FV&3eC;9#_V$;_1?)lsi*4iKeukg} zN)zvwi@|~~F5r~ECoy+kI`Q=jmn3M<;W3U_yJFpwSsuTpfPTgP%%Kf0w7%;RORvnQ z^+FsI;Q$(?)A2#98)$-ZlqB^{d>h1FHJ(;;K@DI|T`|%(5KwTVMcSJm{FDQarG70w z!~IoVBwFxag`b}mAbXKFX)whNc1|<>*t%Su5r!@mHo-$UfO0rtC784O6oO>c)#i%E z(Dw3=at?TC;KnQV&8l8P1JvOO`*1)+8)*721&OFFP4?fHUB$zH?(B4e(?SxVT43D3 zf)vz=Y@>~S+mv4%;A*E{?0LLnLI==>WiP0q+;HGw4b}e0vd+n!oR4IRGSko+qX9Gl zg|5vlp02&xX8vtKUY$_}whgv`?tAJxV%o?yY5~tpuy9a4I#S1ute4h}Y^x^HpzXIM z8gzOVSN6|0=OS`7L5xv15-@ga^BW)H?11;3`t{iQ5C-UBpK5gn z!U=}`>GQy7?zwZ@SSv1=zspK~cHKaD<*NSNESgrz6=Mo;L$IsLuN?b?^rzI(fU)GV zA0|BrE*iF1f?#Hi1(DpCv|d(MM3y*486Y+J4E^p;5mHxYGTcJaUK~fWC>LP&nd!sI zUHIsN8+`e%`_>UPn0JSYZ@-1};e+9oVEr`~c~L0`zX++c@vW3G1z+|6KB^RTu05Gx zO_f0J-xJMiA5bujo`JWg^9CXaSdTPxg`_OVV*v8~MJq!}GmVNYmtVf%Ln5@V)doPx zDlj10?;-jaZNGDnJR+?Qc_ips`4NX1?K0%@o}4~-Mo6*aG3+0$baSQJA<frA*oB+Uk9L0%>hCpfsAo-I z((RdGh}|LUXJS0B;lG<7NMeQ}&O3ci*z%6x~zmo>+8ZiHy5v^Tdrk zhClu2$fewE@4frD2C9EPb6;ne++&hm-Bp#=evqa9@cz}h&KHi8#|1{RFkpm{EK7{a zh%z{*DK5#YG4}Rg#kt<}x=`w!`{?}tTaL}K9KA{Ywt`bY{?qK?1%7z>X4vcR=5KDQ zj_LD#3w0o&?^qkvXmu~L9}-)E#9dgo zoV4s`Y_a?Uy%?)V_n<=W)6AgUGhXhcvQ2N9^CMO z!m{Kah*2=03)FX6)k1%Qfu)E7FLD~~g*+TQmKAT4GM_bH|B$_1(4j7_`OBLoPIR-{ z*pDMzx`}++Xz`&k|2BR^^RKe)TVW}PjafTCjEa?l9}O2^IJHeEueieaICi) zX@b5q(X76+?}8*EHDJ>`4i3yCao6AH{@9B~S=i6V^CUYx*eNP+ot-xrvHs}Bo>d_; zYh9MQS=;c7@&h&0S}JVJuaD9zF%FWqi`PKK5TU53M*7-3mt%f`{PTgiMF7<^|8ol> z7R(*%QM$C;XOFqBh)peat=oMh)_cy7k9Eh+i6GD00;^r9L^krOHw|f*QDhd>@y|K)MN2P2(5C1WW-NjUJ-lj{G&pK6-Ets<- zPdXGjlqPjF!9pT$x)nhHOJr}Q`6Ecxhk;p#x;t|N2fs_S!RRM_g6Fvi^Naq}=^&cd z*32C|{`Pz?4R7QJRmjkVw~o_NpnfUoGxatX8Bm4fFoan(ddr7&i+bKQS(E+{p#1iz zB8ycYSSiI?fWt@o5XJ@8|Hh_xkHCT|ZVS3RN{eo0yE|4RLdX?00ysnCX3Au8Qn z@_sCw&&8BwojhPPVj5u%L9j`!OR8DhuxNmNNz=pzH(lfC?|C#0X)knSBy<8>`S z(X*_M`Q22wC7GAwRLPULE8#+wNT0&$1}r}_6bxbGA$W2pPwDM2Muy>I{K&A+?JM+c z4VNR6zZ?^y2YgznSuR*Bzem^CH5eK1@1(xPZN;-yd~siXrdwlFCwiMa3Bn7w)6HCo zc~3W&;(YS!+UX(7*;8VqiFDN}_D>V3DAQ}l!=JIYa@X1<+%7p{D?VhJ%?rmgKjLY_ z7IKCOze9dLCq?#pW9bB%@Jq#81fcx%f8~%d+H9&ZvCgksQ&_)G%9=D5JXZ)DI5TEp zC7YlK;7>;-Uj4o!=9k{XB1ZGc-Mt>)b@G_Tudh75d%^fcHxG5lfyUujO@Xs(`v~?L z{dR6mV%*AaEMu(cIo8TaYX80vxV-ro;YGH6DDv0J;(nx?mO-B1Y&<+5ycPMG0OrQt z%CUwp7TCEHJbH1h*D&aJEU_h7V0V4e#Cqc@W~#PYky{?@W?d=qju@({INf|Ci1hG9 zN`R@{_H*QV%yWwqy`@USPxy)=fID_3<0&ppb`-mw!Ie&rX~k`x=lD8U*z1 zNw<6*$lQ3Ev5l9P;j~?O*-2u>AL3Yi&gX~SMiHNX z^A-Dti;I)P`VtK`t%0z$scM(9Is@|6$KqJic zQ!7%`rw=WU>{E(kOCF{xk3Ar`f>0=!*32y9qL->EGjU`lAIewcD@t!DLRFbVnj-R) z$mImRiQQNYQ2``VL+KjRl3$ppP^76M;}z=tH;x!#h|i{5=Sn7=MrKCX&;L9o%ki1b zEPMweWf-?cGul|@^A?Xs0?P%(ghK8#jVA-!e9;%V8NpBf?On5{duO&C!Qbd_z)aAT zW{#$GR1{3fP1g*{t&^WUy;k=Q+4@GGH5W|#fIW;kE6d7buV+Y_o<SZa|I-zJrwpO)zzCw9_Ou)s@4K3}SL@_u4f*d-`Fq#3{>W@976!g|M0e1A@4f z3a5Jwcxl45o+fxWkZUw&svgu$Km4sx{fyCToYu3nWNa-NS(&pGphKZwA6ycX-iu3VJ^Ra`MLDx|np-h^T5BWTc#rh1 zUmuXrQaDE1GBjdA`FRMb9nqu1SrMzb0{AQCg0YNsng>{EKfw)?z-($57He~6e?(-r zQI7bMlm9|bPP`KEKty2n#Hie$qa}XK)1a(s@b27TrO$tlf#RuuZJO4z%ETYQhcg|F zWt|YjL?6(6`B<@~JlMq)%+1Z)w&pa(Diz-!j`^uU$z9t$k|fukzgPfF3MG)!{2B31 zhN)#GrQyB9)>KpZbKL|)bjT?7Lk!5LiS>yZ{_N?agr>(l$sF<00B~;5p_0`{X8!RF5wlvG&nueJE3QOk=|Ij(b057?3n@+s0dLxg{DWl#>YJbp|mt zx=*0|jNrN@!F<$)QgR+MYsdSl`h_1aM)BG3Ti4$FEG!3iT79QqwW$4}NbHmQH^E2m zTqaOvMsPI&0X6zyZS|J5<(}uxjiXpR%7iDLtkW{!CM?cq8&8{L=}RCG#+Wz;ga_2? z6uj=}3Ev+5M8F;Ov*hBVr8MWo^Cni+5;56bT%cvCBA?>3V5O;sy|WJykMqWxhF40U z9;El{B5owXaW?(t)fRG4YOBk4rKtLRRj#O?Y=n8?s+R0K2J#a)VnQ~nNMvvzX$I7$ z(;t0Ctt-}4O0vr)H zzGx-uQXliL%$42c5d7VMiqhyOHGSdW;gSQ&iN^XtZ zTazdwlL%BE8({6n5Rg`$=Gsf2$7S7r!+3xFEBFDg8bT>W7%Sh&tr$Qndnlx@ToNA4Y+q;Ox+Z`KEiefi{Ukhp{$eOY|$+gAL*e?6{U`Y$A-Ch$;vrhU9 z@Y@bIE$sA8)7j;k@j;eV^=)S4qbResKuK(A#$dXX2a6^nK2PEvZ2$cRE-jSAwhZnE zof$0|QBpEyX)05R=_dQDyYC|l+Uk?Xz6<5Eehd}bH>m7;f!f-jBS1wo%HIizO#J;T~po5H(27hSH z*o;$bWY-)hHTqz>y>R+A>^Xnl%y9t^d{>gh@&Wa#dqCzAOiNbv#{=?1LYcp6job8; zS89{fqrm^Znq+8|lFy>bpad?Pld@>K(V@C5@B-nh> z+jSke75xTyMR6+8MsoWa-jPoT}E&wXD#ahPNkbk;N_ zmK!!MoEA^F$lIvR0Vi77qeuxtbVB z`z_sfI=WuJ1liatV@ta*D?Q?8@l_~qL!mewk#lMjl7=Od1V$nFcZa4LmK@}?u;{x| z{|)20B-@f;2ERv~MgL?@?CC#O~0ZB%Vw zRF;{3-hE1cfvMcF$Ji3eY)&0{X8ZMuft`;i^#)9i(yuSqpl!TwwMi!ihgn%6X^l=Y zM?Xn0S0{xB-f0#lw#Q4kPusSxsjnVH!B*XWvq*FQe(Woqs#FHuDB`@seOi@U^zy%s z^^V!euS1xiw9NghJs(;jlEB-rTg6A2+u-b0b(xl55#8jGF(~QnvU4ourEvd4+Lp-l z$okW;CpRPeMH|ZaP?$@p!%XBM&NPY6b#TTLhx$&@v+t|#in;@tpy|=44}K|`(x)^$xP_6TopH_yC7bGVkJnr?)JKI@L>SBaPU^!(ld^>_+#hG8*2uGFa|QDPZo5wc8-4IC99>zX-V-j}~qjxoz5Kesa{Z@%(J z>HsGGdxiz;TVmR&CC|m@;pkcCE`dS>Z1M;j*Z^^W%htoLm0{iTGdjUigvfK&VUu-iy1enxt2TdkfdvVVu1rT~As|LLapu+9hh31g()2K(jz z^(gJ#ZK%DIcFNdfeh zT11t66=rQp`&t#*Siz=W!S{g$A=k?vnR9c#bhT7ma1Xs3?j^Z9_zZrF!<4M_#oSnF zkAU(%wn~Sw)ZltrcKRBX*j1;xexOQ%A3g~3j5Bkg{lI$fkYqY&l1ftg*$FoYf^YXI zyp_59eV80{Lz#1lU|-w8v-V>!9~i2Puo5ax%g@2|Mzx)s_Y^0QUE7Y*ezIn^fZMx0 zaW|*VT`F?0&6K;Zur-qVnbHZo(IR;I`tA4AyVp0o46}LprO6pEDff$ep2CZNn)X~^ z84{SZ*BTCXc3|TT1)MQ_%ay6ly>V0lpDhRvAR%|Zdn?E^Vh~2CVwf!K5u2!EF2QvF z+7a@{g`+Jv2FRT-xGc3x%Y^Ek1oz&zoeHHtX47#Iv#eTA?Ekc+HHJa2a647C*i=rL zdnPL6eU1$i8#l`4p3*RINz}1mkxnrF@&U_1<$wYn;=COBBnLys=-~o5A##AX@u8Uw z1oxGWG{?G0P@+zq_wD;v7(6Abnob8Pvoxl83z&*`|M8ap!<&PsUeh4{!;ep*tM#`K zj;fhUTDYcZ@uo!n7&Nay6VA%w$Nw1Xo8FFHTKY5^b{oexE%dIS!4BwK2WY`SdgL*r zIqULkrQ4es=?wBwl0m!;yRl|FyB7HaY1Ticf`yJWf!nm6C__ckGzKD)6@I5E+i)nn z4;m4kwI7XtIGz{JjTYZ`+-q_+`MJA}55&=Uy zp{yMF8dr13W73evZ+wpFpNt=`(4tVnALQ=ucPv^DMUez?+<>teqNmouhbT~z)x8aI z2p6Nw+oMvQv=654$=Zu`5P$>x^e>;MmYAZfbna6; z3bjyqudp0Y^=WND@2L|MP&(}2C(lDWs+8XrQDJSeT~*sQr4jAGJb7yR?2*Pm8_gdA zBw;s$sw763A|#e0e0jrF`_NuW+{Itu$$_IBg-Uyr0e@#|29H7kd9R2;Fsk89j`>^#kJ8lVU zS4yc_f<}CujW+g}(xPiqXNVmth6eoL?>p+p-ee5QcYnk`3oYcF!iFC%+mClK~^(S#|O@+p6={@gAMI0a*(wp%6gN* zFpmf0`3;@>zRMcJm6pQbu(Q)N^CW?m{ZH2_qwajsR_>fz$}DJ$-QHisBey?aykzaw zQ)PfGayVvChb?jot&}bPpUC8m2^?-D2{;Xy)rcuW?LfOysxxBV*QgQYe+8m zn8nlSl-bWgY*QL#v@@)ekDJyGbgMqzb=;e8^+*z)D6%Cj_9z|9v|Gauj$JaZ^}e35 zw*~KZe{VU+S?{y_G4nfR${NA)>WF3vosAWXRaoWo#vwtUAJeoW!# za1YHGBfZ)mP##(;7t~ua)hKyOmV8&-h&xGeZ*bR!pOZm8apvd*8C1HuiiA+8RZ-`u zPbMQh+L<&8@RMY!Sh3PXs7*^;WR39+@%)CwhYaY({#Wh_HR7;$UBKp@32Vlx-sGE} zvE0IhdcL{A#sg-KE3XR~0ay4FvTRnvp%1LDvcHQ!2ic!%gCpfh3i(7ymW)wd`6z~s zCv~LiSDk(7BaILTLG*_-u=3BOgsS_o*3Bhrrvzy$O<-?y-m4m~txBQ9#@|YV64H^+ zC0jcNT!vYs#X`VsSJaE@+y20f=b@8sJ7T4$y5%u=$v_`&HH8jtq!LyZD?7~s77vQ_ z1a8Zk&1wi2eagfynlmEkN(N&KCmf-;r_;d;4?J7{WZ?ej7OW`j8K=)YTzmZN+o*44 z{oE(60$f8qT4zC356;MuQll8XYy-;OZ4z})=R0f`KsjmYQVl{yJu#5P%BqPn5k0h< zjmN>9&GqCT?;kP1T(>Ag3b50*fOvdm*06h^{hs5xrL(s{E(s1pY6%3cR1?6E@m(mt z?gtZqG3z;DT5*=zYh}jBek1tlL*IvH5udBcbP~{eIytPQJ=2a|8FocilZWB<+@@-% z4!rf2Q^2=<35O_-5*3_%70`E7XLg4XWi(KPrHTMGT*W~LnRPmQviBNvW|t;!z^=fR zt}KsfoM73{$t1XN>%6`+Jh;qumNtnyv0Wp+#pE+PjAK=Vek4Fhv1A+qdG7GH_J=Ykfrh5Ta$n)~ZKs16yb2K%l0+Qi`n??uJe z{DCi3a3F@GpJGFpZ;~b3;HgwuCLoFgN?e}30?7hpZ7$0=GH@n76s@vNH^@$Dx=k?F zZhIbCFM45nftw)F#q=Q0FfK^&FmULTzfi_c*%xalgQLx^&*f>)szZVRpV$;~H&@~W z9MWjW3glDG+^+vnR($zdo`yO)`vYtNzB6KE>6-<^XnBzvd6z9)1h6?^W+*$=hKQf6 zC{M3BF1CK^@JOQ!{hw!wL94Q*uQqp_NV!9qdOO+DhV!jXv#;G}+vRA!SEQW&Y6z=% z^ zp;^3Tzx467LH|^0e==;Lgnl6sWPfVx{QKfMuyq4TO@9}Ekf-m7CR^2VMOsd9zA2^a z!8TDi+gRNp99@7kYxnef~hJ6GKTbpMNB-PD* zq$E&te^@F;nYu9pHYXB7m!P01PRbwj;=?_)+a^?o9rO!LO+rDhNp}N24-mf_dn~}z z%h(@E1QJN0JSI54msGNvM_vgps($?pl#b9F?vc>U6?*g~8YN5jmu?_`w_{JSA;gR? z$8ebojo|v{J_qF*$tN4>ciCH_7O14##D3#p1RHYvI%Z5id3r(onr6%c@dKf8t3?Cf z)*K7!`>^>;&glLxU%LNye2o2V@As_dQs4a7xA5K`2yAttc|C(OJrfNC3=haFO@>}W zKE8YLO%RBw+M0O1e_y|`SBjuA(zi}bx$q4R3hT9L?%PvUwr%rM%lr`R>5|Ag|G!zN z>S@ZRCEWRIqFv)}Sy)kRHa_>CtNczlO!jl-mLz~dfsay*k@n!(Z??Q}gumTjHVH+n zT%8UkDzpFduT*TQ^zk~fO7;WyIZ*utO^liY7>%Q{%Jg&Td z==#68spBI_>C3Il5MPO2{VDo?6I6BO`T9H)p&+rn{z|%}l~9>X)(P3^zEAFj=k)uI z0WPd=)f3A&eM2anao*_twqRQT_ASS~vWaNe*?T?S4_SHA(H-O>WOIlu(J(K|L*hUD z)-ChK?D)2S<#M>`c~oCg;r-Yn1C^@U6FIU)E!^cA5Fc{7y5hfeX+eUlocS1erV)M3 z&_ZUV#fM zjs1)S>B0Lgdl28@MaM9G5?q(j$*(+;qgyP<)5jn?0=-!%j5JZ8+HD~Tu>s>&N8bwI zP<)l*s^N|rpJrogsY3-Eh%(`)Bk{O7HYUM9;ob5@HbcYcoNIT+)o@R6YT1K;7r^uS zCYk=Eall$F|G?I@v4ZKrQ}7wL?z6Jbr`1wPW`{DK9G^)Me|#q>P=95g4Ha*as%M(^ z-F{$2w-O{d=0sc33|CY`aG4%-bmOw;;hWD@)|$=E9X76yWd$6N{08Qz@<&tc9S`4| zWVfQEBNQQ7xvXpoz$nb;KuH3(+}~!Nxux`FxIG(!ha8aPyLlAK0b5 z(Eimarb8?jB0*CSV}nk@=5e6BA{e_Ji;`a+*oDnWZMrbh^O2fT( zW%drzJ7=76oLbaVSTt|i(}Xz<*PLnpY!Z1Z#0sb?J>}nE5iqGq2{U1568zdu8Aymqz zTI%5qz_~ok_o^zDUDv_lG>_sbFA$ZgnXQI4^mMFpO@?-7WOH6V-NO3y(E~|d>&be za&}>vdiYBj;Xt65c+=hVl_JEDbW|`Y_&i*XQn%bioLsID>rpuGf!7=Hw6)jdu& zwS%29`&0Jg_2pK5rN_64D>7__p^N3qW%FZZ*!|Q#!pcXH<@`_Mmj10nq;<^@T>NTu z7aWZ#8-LP3}9;l5Ve-U_&UlCI>%- z*qMq*j+`>Npz)n^O_qqNJwrPm*c&$>Cf*_^s$PZ(9FoB{=2Kro`EohAeym#$gYThG zP#E8ATD9DUSgeeUPdu3Ihlc4uD0 z8RvAgTCa^WgjC9|OQWPxqZ~pjTOEaqs2uX#V(?Q|6mh194i@P;*!oeF2?Og5(?SV3(Za1bXKLL0y?e-3j}uh8a;Ws z>+!WT)!Krpz?^xpnpJs?EPng?AYZQ+Hlhg&Ey~|OG5+w@ix^25i28Zy6Q;igYVXtz z{!Z~J`e8>L78+n4oiF2KefwP{PVXQg=xovCAZ z^|FQ%MbxgHJQ&78dyPQr@~l9tv5d^=Ih{Z3dwhIn88j^Wo7-t_L|%~}?CuGK09c!} zHV0*j%)r-&85nw?86_Wg=-gCD_qO@1zH{RZp{mOLelL-@&PVS?m?F02;E|hz*O*gM zt@D4>wS%*oH!g%Uj8JH}HG;duBu7>o(>g%ehha8gLprd7+HrXY{=OnMdxiSiSi^kx zZ;l{_tY936hd%N8E0iDgd4`elArq4Xv?K1ufmaA{K3#zGVP|mrmyaZufS==cwds?^ zo+YLmBP@Dl!BH8dMq&e4kw^eWgBsa7l%@IRA(#=HGHbz6GqVV(`yLw zyB~AljUV?1jRUZl(7CW-mb#By)xB1xT$d^W|A^2coE56Mqw(`Fjld5Ff++m{3;20+ zL=|FY>JGrmiCPwe`=S{1JZD{EGvIO`DPvbK0hkl@vGe=~O`@@fSm3b=?t@r3)OG0C4I>Umx zSq!`uO2(oJMO&T|n6BPH4a}Z@DS5hXLb1u7t|whfzv?PzfQfCjbYgm{3>%v4Y%hON zsq9WrwkHAEOI5uhD|~Uj2G`kvVqj&k4`rz-9@;!IpcpdyVu_qLD@&5wX^gy&lfT4# zmlBL>9l8f%BP=Kdn5d&hEg3$nME-fqFwS&45YaP`__a>ELmXGzgkAfa${;}lNSD|5 zikh#o5`V!>l1G4&Y@@5AV*4)fy>ggu^X#yG%G!MnE(2U2MX-mmMAg~MdLg!HpSDB( z#0dF4*-bM^)E;qlkT9+Ern5D(3|764IsrZ~?RYtz?+AY;xC13clEapm5_{FT0{B)Y zvt52|yX5$6{q9k%5s_V-)&Z1#9q>-x%P^;Pdei{i(EaK3ZOwA+DDp&?{fKaSFJ2D42Z7ly&R?mX zXbSsjDHGo$^s}GkD4ZXoQ7(V6qUdVx#I2S^7zhmEh}tO}br;||zGa?ch2S15E#8*F zizU_EAEEv@OWyyv|MIdE$#H|M_=VYhy3d)$UO^6y+-mE9js+RR0v3dTqKiJ7Lt3F@ zSeupkPFqp$bxPQ8`xi_#Bd+TNLZAG@n)WWOG)R>Jv_pmI&19T4h??RFnib-e6Ts$H zK!VD_Qt~?Cv;x9~dVf#K$MgQ$pMB#}}) z?S@B=(0j5Fgu5F$;!5)F=*jOkQg|7NZK!}7{d<{VhMZpb@NHs;jlr5kS+7N10AOGM zGnz@jODi{FPeF{lQkL{C1=s?xu$VqT`GWrD8whkGHj{TlE5I>Pph$~{;g;m6U(Jqwoz#xR zZt&;TkSe1oVGJN}2RL}#6@~(Tz|T%^nBS`)FypfdAxkZ4px!F12$Esn1MNMoyovq^ z+T+Y8WE4rRT0!mSrHbDMDkvAsUA0JA3d~aE(a30rj`rQ?eO}OJ2>~Ri((EzHcq2PC z+CsXWf217Kuq3LbjqY0aR}(fCL^0mlnoXPqz#GZN2WpOoOUS6mU>dat33r}Nt%1`G z(XTZ5<-33#Z@u}EJsn`cDhFw0Ou98u{sw+JzlQcIzb!4F@)e0ShlX`cw4ub_<{-D~ zYL(A|$N4@#pH{{QVe+$Q596H$iZ|)grt7DSla@00`#m`IU{_xWO;7w;DO&baiC|Jy$@U501Mp1pTO zt$$0F{?O1a0!akR0=ADFP~A>Tp(F1$03!0Qt+i8rN53!0!OgR|g>=|uzjIa$`O!C# zFcJsB-FeL4UO|`tkaPu~BbB(HN9Y_l8#T381cGn~$g zPtf3ZBn4mCHx5(*3vC+UpaT}5Qj^hAvgrpQZKxJuv*- zRSDL6vfvO3X>4Wt`56}&0Te^dt?;Jla^M2?s4|70+WRaEx-|oEe|~S%{n>N*mKQNj z+@Zbx?;*kur-dJ9>-6pK7yXL@J|=^OJu%LSW!~4FkY)Pd3%n`r3Vi{_hYQ$Dy-%fe zV=)u!Ac4SUXNDtIu{{S=yvDrYzQV&6Ly9+*EQ^e^c0^;YAj1*@gjRK5lIU>QmZa90 z4O0fdHAS1=@;{H3pmR0PKm}dYey;c_NLkv!I$Ch51}8&aITHh<6VD$CR~;F8AA5ypV~U3%y7BhYP)G5Sw;g7en34 zMjHNH4#PIJzNh0>>JS{0Pa0UH56?x@I0uavQlbdBaMFD%!5Ed4Xh#(&z|r7E$<+N` zewF);=CvCsv0rj&R_XB_h) z_??;s=7}EZROm~}ms|hIY$T-*A3rG~v7qDn0$5>~X>EJj;4u7{ilS-R%51phqteB$ zXIF3_W@?CF%e3Wv(h(ngu%gh&=cagwuF^@U=`l84HFt1Oo7NUAdB(w}I6pmbdY(n~&*;MOAS^XM^W#o^r&FB$sT`-H#F`H# zg@4p<-W-g!e0L!+oS7;LNY-DV+5VHWx2mQK1|8?sR{9yBLBMB|;UBH0 z`OBcOAgAXDPb|&ZIrH%swA(lRKoEO;Bw}jTW_#Qp&E5XYGIrO~>%n|1%@GHEUAWH6 zTZQ>69(ZeoKT6MxL&+?q{j{`+VLd=8w1I`fw8nwry`k6GMa+lv`r>cA0^2>xRy}!n zy$0qL^tO6svHZuTs-G@r`X9NK-|~1&FR6{6X#ZJZ9b&c!-?Sux_2^e$A#PfC3-ua+ zx9~}ryX!D9Ou$5Ai}gY(ZRp+Z!I=ldAAE%Q-Vf2++2=2r=FwQtYsVr$7IVO%1ThO= zgEBfYW*Ft~Uj4_Zl#Bv1Z$=aXG$j1!j&pTh`hCgHo=L2hmmXNcy{FEe{(^Venz(L% z=){&75^%8Udjqrq+;iVjDAVHwIr$X4+jw&NMWM`cJHh|aC`W*0#g#YJFEB@@r`Wgg zbaq7_k5HkOr}diBA23RKUMyz+V#lnN7se#@r^tkz-tz|xil zMo&}(I81KfFl`)~s1#TMht-U4poBG!zkCv!?vIT~K`OBt1LAL!K3uE~qRRdO8?>N~ zkA6>0p@Na%MzVvi(63%xYn|b$bj9^tKQhF3SvZ+bU{$FntX?H%3=E{{QK7>yctNA` zvRII*6ilNVn8p_i7?q}t2U*k|tO@VYl5$;xvllBuMFbm~UQ=xP*1QEAg+-Rjt~>S$ z;76Qvnov!K=HleH)0Q%yILa8u<6>)qYNx17V!@wAo%gxv z*ac>|c?_5@7(kGfgxy8z};G=UZ8%%1hsbp8<571E^EL zD7acT9-wp=UAl5MUb>M}2z|IMU28*mM%F%i zL*Vb7HL!$LRv`lEjrWv{b6W39{JdcwB8X|y-i8F#mQ839&eWpi2w%EwnpD}Ykf007 zv?HIJ(84|ad5RiH#JyB`j1n;S->3;spR|;nR_nrAQXJ%;J8@JOx$M3WB136%{ofy= zCJmy`G^OmWy)smw^-!Gvy;u6QGjvV%h8;e%Gf-+$x&`?FqNt;~UCWD4%gHt#s1#IT z9%`P1qMJJM1?8n7>#cE&;Di}A32x12CJrVY+!DKyW^Ee%9IXQImZHMop}O8MpO)MX`IMybP@XahAXh2$fp7hGkxMG5LtczL81Gx|5q8#r=!Ix zj7G%Ccr(`OcZ0g75>{uFp=`8ZN5rJ;sRuEFyggH&IiVN?&@TD>|u#CDtxvx;|@$WS= z3WQ?)rhQ!nZMGmj^bc+p~SV<oFSSha4U`nGw%3h`vI>*>*NM^hhAi;Wwn@_&LRZ4wrp|cTFX8#K z<1Ok%wX>D|2v4ttrM@;G+$q zdcDBlN{NiQ!<$_;Xtoo4a*Xq12V}Qyllpw7b?|tjWnvJ~3^a-^P-j*{>To9&sg&1F zz&-JYvc0Ma1jw2jnOisJ|FgvOtK%#&J-eE_a0G-3(@n_qsk|@-y&TG~Z-Gqx^#*D{-dnH*X-zYfWC98$;(aEkX4&Df|j@s^HxOP@R zMiPG$gmU2n{zcNeITB+%>^>EJO~QBgiMK}3{jJe=e4edQ+zyRrC(D86)k&+jPchu3ir;+o8 z({L<2Y4`c7v#^vmj2W0nOBfGJ!1F)Qr~E;J+LTHQu}G4c4;BIU`x&l{-d$vqxC?gt zCKh7(7rLWPr!%rjxkYdN)Fq}x2{L5%OHA-<7ymwIH}kLCEB9Dg^Vr%PPpYv3Oz3Py z-h6oTXZG=PYV-0x*}cD5T?m5k9b5&OQ%g7nL-~_`Z`4RV!G`$ayxV1Ci2Bo5z&3m? z?^u3sxBEQEv7iAE1;YgVwl!?rVkh46#>D>VfTpvcy!qvjO3eedyv^8EOH@g%}X4X*e{ zB34$eF}YKnv`aWt1G)zoi#@zu6KOs3zaLrYKE| zSxnQSgO9^Gd5us<%k!E=-)F}fhrO>8yH==R_gF)R78aN#zlK;d8W-YkmV&cyHVJa}zU|1kNPrZi#t-sOxMyn&P1ZnE*muc>IC zy3zGmrF;ul*1i99kujj_f(KwFvOgR*=~?kXu=3y7rbxLDAL^%*wUpDdZ5MrQ;*oz9 zP90c@78!4Ey^ag}PD=a#{s75F4(oq3W2ZMst!<~2bj-hQ!GBln)A}VCU1emc< z7CQX-K~uFSVMwJ~!1p(%HHa2foZRs&H?lTkG76&n$1*I(feEX8qV`LLa!lTIm@pJ3cjkmoa(_T0gL&I11qDE&6+lW1 z@lhr}$EIDN<%ZC_pUb-8N_^YHNopy%9q|z%%HMw2_h#!|@SBw~v_@xfl8US1^1ecm z%`V>Xq9QPe2B}8BLb1n(QW;7?QUpe>MCfRhg_F3>p`2$rZ(kt^xC#zkdHAz(*^l(_ zzWrmu>KhYc$BIWNmFuTX$Xkg6)yGF;x6#4w%X-g6yRU7Il zUyn!V|G0nOFGBOC=QW}9r@L!E%-PLLk<1C+`&*&IvaI$G@h=Rxun>{R6rqw(r~YmP zFJOv;)6{$$dd=800lCeCi16al^y+K%96mfJ_mKP$1pLBrwNTA$E1?P=M4*a0*NM}F zmhvAE!OM@bk$?ow!k*~CfXh@1TzQ?o+NResyU63^O)d;=8npb~9e$jQ-3e|kOnC9F zgJ4&Yrqs?o+?Qb`p@JCXLrE;zAi5slX}BHchQN?P$bse6&#f>iAfvuND@j!fm~=M` zh#^Cc^65|6;(h~*Mn9d3A_CH<#EOYKl(3`fBMHMW|5cQJgQol8LN-fAk3Yt#0HYK0 zuSX=I41Fr>x}vNq=0ug@z|z+0Lu`;D)*C3hc1DaFsN;l%M&6rCtL z>eH`{7$o(|lj1dQP@%@U^@}E5{WXUKzgddDD5U_gmRN*+`}v8Kp-db3{)D z<6B?_V7WLO9PrUt_vVa7y|{eH|BDeklJ^!;dOo6JJk=4s>GS2R|HtpqR6M3fACOl> zcU``lEcUE97q-ZLvNS%e9WuCELT+v=38X%-f76GEA!=DJFEl11j~!6)IB6R>nVV*6 zE7QcSs_u6gbseVKh;xyWO?T~{_v77K7(Tq!c$e+tZ76-Gl$x_l9U2ElBXt#}DQyzi zMV|5?9{1enBW6ZIc)IBDu=#&dMr_&P$CB^boxVd~-hWMq>WgLm@jprDVFh}fUCSq% zvdVC={>%>T8ck0&C!3J1g(A25En?vsX+W<(D<&Q2ZmaNvLP1ayfIACaSI9s~l89r?`ooFIKe zPv^^6MIj|{?*}vF;r|L5aE3!2D?T2GSo+JO zux#3tF$q0DgQ!}K=fS@U-!4W$UX#7T#0b{KQD(Pmt%NiE2#5MfkIcJ4F89@#)Iuu} z<2|HDPFA=q|Bk9qTgr}9GjkHirRG*z)}om^RlIu7`1uQ-nGdp`$gHH}vye)>;Lz~| zE`)gN!AyGyxW@}geinV@t)4h588iAgJ4d12IeZ;XCT( z`QHwS(Fc*l$3%#e7iQmzP*Xhw@Bg_JxMIrH z;F-86H6}jb***sQ&}WvQ%TPV%4=--V64QuPCD7~6dTx}$9{DXv1&sG21 z6VG`Rw`sC5;Uhvd9zix$gP`}`dUhKo3v_1q2^pk6dG$5xnGQ#)xE`zp-o;q~jtnNx zmVl#-Zd_$qJx*2A#ZP1cY`SQmaTBmi1%{Eatnq2^E=UDv0%WR-aO=FQB!En!*~dtk zVEv33roMh>*TeyBn{J+ij+5`}4JRD2Zh}^5Oxz0g=Pb~6p{mpl3vLH91a;k!{ev{{ z%hck1=DPm;G(iQ!iw3|aiC^9wAKKsq9dd$;iZ#9gj%`)Rx;XlV>_)bc=otIxq$cPW z8{troJm56wA$Zl0_FH?enb83fI1M)EBY3H)S@zTNS7bzv;Jiu7z=ee(EbH6Y;xYu_8btBa$ee&i~MBnxjl{Om~D_Dask>6E0hmAQLu%uaD4Og!>- zNNVR6bC|#$4lL2Q0oKohAWuqjmR^#CJ$&Mr=+JwB99gu5kF>mertPvV8)LFAH2%B! z&*)(EsFHnrv1NG8q~9qkvWHkEg}qlUt-wt3W>+^5>kCiV3s_>oU-M#=9}(gnXbgP^ zBa}vN!E;P(n#duw$7_Fd;Ty$B&NcJKtGM)IR_VZhi{99O=Rn-1PcmEEZ4Xw1B;JFR zJ1OwI7L>?EH?dlL0q#x8=>S^0qSEg>L1k`mA+w zxZb%R`eM4M1%?N4kD7NZXJ`Jsh_p9O*XFre%c4ysvkV+$7?Ybk8$Rp)D2^o~XCSO# z!*IS1|L()_{gr?Ku~um-n8Yb1ErEI6k7AK#zS(EguxckN3&|^*k^2)I7%#Dx;62|r z#AxXTVi;zM%FB0sxs}YwNOn${&+GL`ayAUt>iS-p(tCW?vaRbkz_7;*)2?^>2vY1& zUb>%5o>E*AxEmxzYs=}Pe4Wh?xmSsk3Fhje&ES<2JA~5?*%yEN9 z$;^Nx;Q5asVtHACxrta}MvvSLx~oumFirs9B_f&PCRKOcwJfVQEm9wn%m#mKdmG^} z8HN&8JAY`}PyhBCfrWk_M))#V)2ZjHA}58ARcrNB7iTxv;6!e-CVS#z~jJ zMkRFqPA@`)pqZy6 z!d{J~0(4d%*YvchDlQHhR2C7D=Wo~3sV+awF<#~BKNL7z&UU~MX% z8yHpjLjxO;eM|wkn!dSbkW-LjFr*dBnq)D9Z$#Q+C7wt3>JRgiAO6&ZAk%%x|j>&|gc8Bs@_a#V`WP4f%|GEk&(RaCh$ogb0^knlIlyCipF4ft)sRa|ct3qDO zqM20_L9?dGM62(0LO0g}+%4>0o+oc>&+>uNHedg25IY7t;dF)Vw_!tczQOMoTIeHG zhLeImsD(c^-zh$4`|=BKRkw{J=si>S39k|k`W?8O^dOnfH;7XaEN{Ikxk3f3+$f#C zUJG9f`Y-Y((#GuvttICR`t~Z(vw&rdCRQhyY~u!9G3+{R8h^v4Wq}Dx{f#sGYW%d= z&aT^8FB2cUye`}8DN2R%0vKhAVdC2|1Z#YyBCEpYshzsTD)pDxX_*;wye>9%kSv(N zZja;$BMgXzk>X$DKyhj?%ZF~JSV_w(6?S=#OdRsjK8l{BP;%_8L$QZS#&-MhzCD`d zya?ub9UJM9|DlWJ>|-}KFpoNeDl#;nXdP+5le~{wP*XA(T;K|P>ognG(HZHc-V(Ha zT2;(0LjQO#R`1Wg8Tn2V6giVa`^|q-drT&pXVq;V=i}ZNcU(l0Q_(h zc+$dsiM?S-h*k0J({J7pQ2!xWzuH-J*)puVZHuh%iR9i1U(?1572P)6|Ao=ieEx;AF1Y*Mqf}zLbynY&xDo7L(3#nn;p+?>g{@#AYF}}OI03fUTjFJ+LAq7q2|C_Q7SuB$Y|+Q{;~nMW`g@IP zrIfs3viD5bp5BKOBVYfo+61dg9AWa;p1gk&N+z%P7Ks3vZy#yOprhI~4cK|HP`*b* z3;o!6m4~rz%Tk|8wccQJX(F_kKhFv{S zGzveHuXa>56~x(i_O9|fq8VY(z!UZ`ovO|Gb~wPdFl)2UX*0>fbbVc!u(iIVCrtwpVZL&e1mr8VxR+W;S%uKKOHLnBN zp4T6obT~ENKO(4ewf^h(I{$qIh+t@J^oA`5n6&piZ?KqONIzTrBRzJ$prWwN8*syG z`g{WRit=Il_lb>Giy*h1p-o8=jsw+p0`%7)ZvRrx1v%@V#+}E-h8wgO|5L|95Y!)3 z2c>n)dc?IFi#q6^V7?w}S=vcJg)Z{K~c67oQ zZkzBKtwk)cWIQ4_vtiN7gm+GCR+cEQr4S17f&!SiMlHWdxrcSz^E_9V(3axOLV9H+1=Ko*}y5q^xTADWB zen0N#n)Wbs-Y?wMHWKv;rRQU$X+Z#SBEl|^Pp6_%y{l(u#<0uxCdY^vJscSc(9Flg zA7!tMRYh)_#j1c}zY_eL2FG_vdpPd3v3f;(C#F7k96M<>8GqpVpzOZY^_mdQkHi71 zjnE^%xPq?Yxu_tIo%RTN<kSExd}9~XxewnYy;7yt-`aO?b8JIFov z{p_uXq1h)a_hnz6yftZfJ>ihjmTzHL4LA4y%eW7=XPGp6cNf8%MQhuab!;fsx3H3| zzxOV5?u*vkOQ`joJhPRckNhS}0tfKjjVG$|O?X_KZYwlKd$)*S!sWqa^7le*qs3J( zvZ-MGc}oDQNWtEBo|V};PK`$Zl7yO-PG*73ScL~_UrgpCOV>b0ok%Xo?go{8aEv?= z8xwD((1nhqs4#I%@!nAD1TrGyvo^4YX(QBy+Cm=;3jShwohQTwzkintf{*IxraU89 zJ}_JmX^O-UNf~k*&+4~znMNRB-AnOIooekZjt_)7@(9P&wb~t9h9%i`{{?B^!jO;u z^yA5MFkB)x2j2)-ooKw$g=`P#aE9_LmV`%=j~%d?%6xK-1fW8gO7dC{9tAuy_N>$L z8Lx1_e_Q}SI+E#GjhCBa$L?l9WzBTa?j`SCh7Pa3Tw!qnp~i%wQOZ(->Mu`zsAiLF zGoVc5iPGe)Rq*}^H3_8(vN5rO6hx}GL34+)U*~mz1Y1`U+#6#>Mx06yB1vSTGxa3i z%YJ!5!2(;5eCkfG(AX9kfaQ1ljZZj3)B^2mRy}q*;{6X6;4bBHgA+%La}M(+l9(pf z9yW$nSyZyTQY)W$J+V^i#bc7QkqoFHqL~ZR7MV}Wdmo~s!@NH>B+r;`vfwr7^l2aW z&ycl~$LlKEVL0PO`W4^EOjpKkdXzd$lC!+Bm_2x{8p?G5a_{tbk%rCl21!nWpO>=` zUNAE}rbK}k`t1biqXx9df~fIHcka$-&Xa<}cBVwRlYgDieVayhwUe4RfeJ2S7b!F0 z8vluy8*xx4>iSI5;-5rNOw}R{?w*8SPqhdch_QhcwK zOMPlO`lT_P*`OhU(oCJkRDFo~$9-ncLcU)Eo*f{6O|M%rRgGyt_LNC;PWrJaQI|Q~ zpcS=uxLd-9bX}6Ptg;BJ+~5OAnSr}4WHz&!mZhJ#8eUP}Brp{_tqhb}ClNAh{+bN* zzDg<cch^oc#v7lZ%4}s2sAzV6y(Z@F1h>bwr zvH}^G@l5=DFMgFj5yZ`CnYeeoE-X8`?ra#81-hK<+8HUCO*K|LBsNnX^gIDugQf3j zpj%{J?Z)!RzhUya}x6&;GOR?_bC|J4VXFEocyq)}Pi? zJJOIQVJd|S(LP)I(O=-2^hli7LtOxt^WAyp4 zkT>rt>GA8)qVSCMwaXhBeO>5Rv}j_O`G6BV-1T^={V}O(pas%!Qf7JZ6krwTpC4&@WBsC;N1X8k3zBZn&3Tw9B8^!M}6sp<4P^b+Y{4Gc`A>+0Ib2 z2_D-=Mf9wFk5dobBx{xU=A!jWsU{OSQ7DCF`dRn~O(#8EY-~%HW4dVn;!u0UNs*c3 z%J}?lT;`h3i{!i-PS7m>w?9Fa-3(+IC375WRDI;0Y~rnGW7)S&I|3-zmo43K#75JBSmlV58U-SJzdznZJ#4%4HpeH)H6?>k&89*X zm$EgknZo9|9@BY+1ID0JL#NC;o8RADYr-cZgcBEOK1L{CBQ>fe;S|aTiadOOFr9^~;#SK0v*`O%lIemY&UYO1Qhk6L z+R6>+@hmXOJOD2mK*5*rb8>6;w?kb(hVbh;X*O~uLy-~j& zQYqg|j%eCZQpzKxiC__;na_8pgnZ|&Nk7gC zb{c(F`p+Q-G)|V?^6cb8{|h7DDaEgb-z&?{(FMTE2fFJ0(Rg&{@27JM9_r-9N$>b-#`=FwxJPuq~g21zdrJ%^}dG24}6^?jBX$-E5k*G44h|wvK=V4Ud z`y#!geu`aOlhyg$sgAMCE=ce&wD{^_#;4K{@N?mQu1>ds<(MVhrYejq7XnvP?1>w_ zlsr%Ffo@2`^>y~v<#ndRic)EfPkwK%CaU|CxY!zQg;pA=M=)-LF4!~Fxhh^m(cC!s z*kTf2c$%)*v>puXf;#AkyWiEwq4{SKI~3)LN7P z9}xKT04}ySziaX;^ID7QG`>rAS0zcAcX7XliBa6!XrvdVwA3@V3a@YXCyVNXD|xM< z<$;HE2I33dE@lZF%E_hHh?HPcgNt~$W88!R`{IjRFoZ^V7eCPYe5mi5yku2becQ*eAQD&C-4b>1d%O1ai<>ZrMq~KhsnPTU z^|kbmGYd1i+f}7P?kuH}W8#KiEW56!EZ1#6-pDNx%^KL!{)UeNm9r^6h@n)TFF{Zh zDbCqh!F%6@PhfRB3wEFTsr!jr9QG`!udhB#WXmf>4@SqVKAdG}i7%j*FdaYp{UDhk zDsOizY_*`BenxLFA1{a{)hMWoZgTj0;@V-K?2%khlR~zWmwQq{|DX=5dBbtFPbJxp zi#9)Q+*t-KgYzV0h%2J(?6?204K-DW_B>}|4EDg<8Zm=vi1@ki8P4hV$72;gu}yD! zJ!=U(KFByeMjX@tLPgSCe(5`jo z{DBConY3A0KAw4lJf5lbXE`ad*X>e9qbJ}^whMX=P|BHSa>u**XFey`;=k^r9#5w` zi_=9`k$ejaQJb_B+mG>VewaLF1X`8k^s{N1K2jH;D<>5X&KaT*-;X&cO9rl_KkIGe z1g@AMXIR%TG`ePO!{R8JZ;Hm3d0&A%r1H?O^FrDY3Aqh3-bw6m*r7x!tw)|*Lo|;< z<4Xy{NMjJ5`k4Hc7YwlWs+_@J-DTJWlqTf_{)TeNW46uL5HJ0i;ZO0qcW{U%oJIr? zF~6d~+wc~zS+T#td2Py&daO|ES?bT)5~L9Mpi7D|b?#9`!sX7!NXO|QzJlCOH{fE= z3m#-zqh+dbr6FdzQYBd3MG}gOvkXIsI1&j`gy1Eui>ySj=HYmnar}&fHDl_o%Ub}S zKKdG5DV(<rHW+X%! zdO;(uKSU+j%0bzT<2RtxS<2!1*_$ox*UNoa3h8a=ydeH6W9LWCiL-r4FX96h4^8dJ zul*RHBV`GOC(f*k7wr-{W@iolD(<9lnV;o%CfZ2d2i(J4nXt+i`J&%*e3-9t>VC)k zlT)X^v)0l(|5UVR=8%vCMGt|Jb>%JHAio7+|&W z{{!QJo6(P1fVHH%^sb+e#h4)ihdrLvXCi$4HhtK@MjkIIv;zY*&E`)MpBvA z9tW2k_@@Lgv1!H-^3R*j#YVigxEvzEAeCh0{S2HzXHg&d^nwj;3Tjs+92^}pGr02UsrIBmD1k)@v=s=9SIjYw z>a%TcP+^j-z@=b?CU}$U4b7*&wM)f1wH=Fer@@;0sIl-P8G2jC7XpqglqItaCt+({ zh&Ob+sFAtTZDr!xsw1sy@JN@sf0)Y>xQJ46*vQ@+>D^tGoo2lBdhti)`Bz*rqPqoW zhc_bx*sviPUDuVH&XxSM3b&(gi0#gtby6|JT#$-uo)ig{@@jP$)zykgT@`!M*Y>7FhX)soZ4qZVW9OJZ|Cz_)dhN zfe;Tt(BSc9NaUEp6jSc_b!F;9+)%8d5|_}<04`(_h}2p|hK5?m^F2zz2vg9w$sCB{l%sLne~1D)y$ z$`qR2JL%!ufAEkIvqV#-0Je0LAV*Zy^PwF0_u^q>RckGduxuB8Oufu zJr_i4XNBjk))+YZ-JLdPyyjLvErysB_u@K*oP&~K+TXzA)Yub&P288@_HnW`eY^h^e4$)) zL-$}G(pI96#{wrat_rRMxb)vB4%B`;?7&7(wQa#5yg>S}ab2O0{j7DS?gjU{l<&kC#42;GR@Lq)@B57No zcC(DfcEoo)Ocbcc(jJlv40}u>9%HmG~`&GeKf=>w}>MR>fo_9Q#G4(O51MIMufp(dwtF{OJHabvk4 zT&o{U_Mr>HZ#;Ui44%2oT-y{<;bY-7c^JXSye~vQ`E4}LkHZ$ZJaaGb<$2R1?+&o_ zmc=;CrLG`%stycSYsnXIwf@#{4z)Fx|0E_)lkIUSr>&Zzu#swfky-P^=PzqXWSB0X zcnV;!2E%2#co>sWg%~c8L(37adTch!{OL)Y^i|SVB;CY^Ph$4VL*`3b3xD_1rOsB? z`tXaaw2D1zZCD@tE_@t6R9lv8&i?tD1TN(7NbDU(lTat?GRH+lj7%C<^F~*QyWwPy zSKI;FH;Q{PH{E;OFqvSAX~!Qyt0{AMpS4~%@m1-imaQ=(8zvvdfTTZVK4%86CZEW_TJ)snj{afx6GTqtY#96(AV*PRw@mrO% zPQb>w3H44n!G1a2Tj0fT&`)Am8%y;g)0M$@rV8GE zEcAKKd%fRx{+ny>JuB{Y_xi1Sf%6zy_tp&ysF#9&dP=@g5u9y)78B9>Q^TElK<4B0 znw8i3vx(x$2|4eebf9JyvCd03+6ee2OXXu?`Tu)919YCV5PiKc#==n)?1v+-kJzyG z`R-P@77<`;+X9{WMU%?SDk7tm|9mzy#T}klXKi^B^~#}9!S1ZJ_-dMMw@H+bQlscA z2d&q9*Ix6S$9_5f?CYX(x9gkpxAQJB$#9`vP>&^p9ND8$Yt^8DiBh$3xsf3fRWD^Y zCbPfa__XpJ5MY5@gnqSlbW+%7yr^&X5pjX0ST)*g@;4aN|>Mi=lp1h~1xrePHy#ld9hgV19 zdgz^UPYF=J?Vo&PTV5orBFB4JwSV?pqxBX5i zRJPA$F*3S-8Jo=QG1(0Aq{-Rhj)k&h2YOpWM_S_t!ll?sJGy9{+TqDfeSOc@LcO@;_6%Way+r~j#eZ6p_W-ia7!eQ-xj}t<@#u6FdY1K7< zIL|P5`vWCsYgoKU^)&OF$_FHJEtkrnih=(1jb-fMX~$#Hb(oMvuU9R1T5l9M1MTeV zx7en-1B)-Iv>$}aH@mkmmqx;n4stG%lzmgPDt(= z{gIPsw|uXZWIVl@8=7JIHgbeKMC^q3aHVE^d*rE`IWp-@mt-%lB=Ee*ja>@axyLs6ML}W?XC2k2+|X89&J>-B){;Y@^}SmMBIB zZA0t5R{eJ70|yO^YVP;{9BRFi|Ci^#;iN_2yHg-}jD80U1=7qur-i2od~^A~4ZOP? zUO(GwzV<3xuG5TDx`=U~tZKisv7_prGysH72KqNL;=Xg6r9JmcfU)CCUD%nD=j~`u z)hcMpap=>TZi*@~JsT~2dQr(XfmYr_a+Id`=6)kvtk^ycGJzK&GGcsh-&meZ_Spl% z3A*}H>8ebp^>>~#f--a`lH#_xLl{xO&tm0mH2vT*A=PTM^)t*{g_HYT*6#9=Uw@yl z>V6!b32HV%&_Lq5b4A$~2VRrqe4ePzff<_SM$1=za-}-i4m$t`q1-+p_$uZxfbyx`Nlfds)HKRnpVWithL->mMo+){2)zbIi9RuFhaeMH z0(8Ou8d=>O{{By1`#ad&)QoP!v|6R}W*g!gQb=vtw-G*-ct0Mk@Qfc0->`spCf0<* zsSR|wrD4Kps5N*puU5X0rcLo!D+@V+|IsVs*4RlN4Dx z!Ywu5GW}Xi`}L-_xWDlBcepXieyR&)?<*#e@x}C0epN-RG;B5BUYmOSnoVt4{!~X{ zj!rq_|2`OrAF1xt9ud|U@NpbiS3pF90uFYZ^j|)X@zTSkKwdyG$HRd+UefQc+eTNi zl8|Jj5Ei{wN&!LVhS+iViVXg5-D>FJqClJMuXiTChc90)g%EHh^IfeFLf;$xq!Vh> z%x~NC7cQCoeUlfL9)JO`d)%=kH1g!lUBTramwrO4z7q+^>bqSrEWPBlMJ&pUxTv~v zX%Z-S<<@D*Z!20JZke;`A2Xr}v`_Tlk$=mNcuU|Wm40eeI@Aa_ftzdZr$eY`{{$|li<*E!%D1YzA8Q`;*o*_RddoDSj)J@?*E2VnNQR^WYmo>jZK%Xh7 zoNU|T;l^>Ca}{LxaG{**Dl{YN!}>x-stJ+)B|*qZ`6S5RjE{JdG_Q{y94&c%Q)Op+ z?AO6nr3mG9i2iAso0Wrhr|BZup`AV5VYg-!3nE^K~ZYDj!Oiy1%m(>51K7uCGcN*qV^27&1iUBGk4^GYH z7niluHt5{3Pxmej3aPKO<+#n*1(Bb)s=Ib);$7E(y zfVRCkT$oZ(M#a+auN{8lVr7ZLwc^|+D_tH)Ak#c^JwU!5ho0GcvAzqC_3XN~OV_XC z7(Qm~UPEm~teMZiI23-$=1X{Aw3&qb?&maZQuEzG?46+ijr3X!lXM}HG=vXlNs ztXN9)9RB1Se)4FNSvy$KE7SY{NHcB$1-BK*k~JG{-Kiy>ge9RYLUmlLwxg8&MN%_1 ztl%CYt=gxHHlBon&ptJxZiQ!NmN}qAaei-c9_&ZH3D{m_!ghSpAU2GNJnEeHF#n&M z7dlu{+>Su~%Db^7!2>@**i%m47XnTac=NDTImA$zxz)U?C|jhU)!%yHJvR%)o$<@K zD?R@^#lro?=J(+yyn}rJLi)Qd5ek+Z$ZyUSs7NomTcs!A>+7tZm4GDRQNu0m8%T1L zExy;T{brl=q7E5iBK$yg27Oj^c@YCakT7<^H5xQ;DLl6^^_^;?%K=MUCFUibG-^@R z*)!m%_P+Nv@&U0we^S-a`#HSYI^(nVB-fFF?=FYepHBphfx*8W`A5mshsYhf(1WTM zcN9L3{|IV+0>PTGK?t8kA-tO~?;;^9;$t-RV}@0#Ex3kydJ!~MbZ16exKptL*87D{ z2}9~1i~cIW$L14A6B@##PG3pmE!-WUdrw@!@dyAF?X-Fkoh$Rx*3C1fz8x70%Ei;c zieK@iSL6{&|9Qr6hI*RWjbCNum}tR+gZZ@2WZs-bH8uXF%?6w zg&JYxrd!Y32#fjFrjNv-yS=TpjE1HQSFjA_2C$t{y)H~DZGCeW(3(7F%(?v%x0VE6 zJs>;IWeO~3r~t|ND&EZ)5=3lyxx&;7kNwv6U7$#Ifrh|Mw~# zC#}T0sE|F$W9|vYj-fJ-&;-0*jV%@bKoU8g9B*^)#a@N_a;*0a%uZKB-Xa!O6}H2) z`@nmUNo-FpRk}oq)9c%vvZP8O18RnWM`~M_ne^;%#GI90?OUcpkOJaD)(&P;N&Y6E zXh4j1$%UrRov_k=T(ZyTzJk>M;r%XXku7bOSo+QF*;HXpuLc=V%y5S8_ZJn3&9Stn zYFin=_0*8NxY0%v?2BU{)VYh#{A9#4&AnZ1>pfob)Zzryx0sXzr3#Ul^f`$HVo*7s zur*yVZc$1$tNa$cX{yj~)G^L+{5sQfax=s9dkuNQRWVe)%wPkumOQ* z%-v_8y}-l8YlU+iQ3t`f3s+|W#85@awL{Ougi`dnD|275f@$|VxQW1o0&qCB! zovl}3GT`Bu!opjV*^-W&OC4y?!+omQc?+{kap46kYql`W*y;QdMh z?}4FZ0GAQjtgBQk4}~|%T@*Y`VFsAAg`2uSEssIgGaYIfbX}{+ic*hdM zdwBvvZWGB*T>V)5M`K^+z|Udnk+C5>}W zmaJoZT0CxjJ0Sl{$^1~@j%#yMH^Hkr-ghwHzehkiFdDm3u=HMUq0y%6%s97l2@&fK z8Qpc*YNf{*WJcra^c%8vnc!Q}d&wrD<-NOJ6pPo2`M=PFM7#&OZ1PPs=`z~aul7Ihrd4gLj|e(EpN{9iy!GN~;pI-{N5Vhw5O|+oVM!IaF;!ac z%3YuJRbFQ%r@wdkVUHFQIyJl06$KGr-z@OM1&`&KJH}_NRmH^L4X!-?^rW0R3aWMSx?k`%y zXuu4e7!CYMceSy`jHR(R(e0n}XHVIr@lO@RN&CeFj34r{Krg_^dX8D&v!wNxplV0b zY0@T>_bPXomz=l@V32J{ZnOLTy$vGtQScc8Br3YY>us3~#drQ z@%ldk>U7d*J%+;VTrKuKwxuB>5|uy2Ld zu--;>wuZ=coYu8>0oqj3o>6=5OTt3f=F63)M-Vr>sX$h$R@)2qcWXeYqAMF3u` z^V<|dRClUu(_v|L`t7P1(rIXx#l)EZl4p*T4Uth1VD8<%{W>fnGn;1`S>3`hZ98Ud zF!PP^d*m^L#BUwpvfQ;Dl(T7{&EK)@sJIs>-lj1|Mlp?cQSdoB)MiaZnFkI??X&2e z%3LM9Y|ljuql$K^E{5bZ-S^gTTGczvL`u~SfP$M~hGn#dmFp@xK*$m}+SyEy(M+Q! zxilX*4b{r6sK>N3y}5YL@4OBi!9(xA7_3S?W?HkvaH-%?b#>TUTY2p8Nr8QUTZ(r6_iM_O;TkSOUIPi=qwy2H z-;H`3;=)l+x*<)Lh6>rbrOoNy0X|VrXT*ODkc2=;)3oY5Fyv{oSRUw^$!a~eBN!Wg z#1zkKV5|sF+tTcFYouM>j-^bgVCwj}-b5Cd=qhc5#G!)@w|bs#WKA*|wel#$+Pp8>OL2ckT~Xwcl}uc!v&Xt zS=^c-2nL1xaYfQiNySt!pe&!D8yyt&Q!EWna z^ut(%g%G7TxfU5M)JJ61n)Rd};+bSRosPpIHA65@`bzcA%A#X@(W3_Wbje7(BG~ri zu*YBnacG|tl6v}+7`oH2JC|Nrc6v8GAN!PGf`Yn12N40|rRq$(#u$>@p61mgjyPuw zQ_T-R)-Y<1@G+aJIH|#$iI~@aRF>}XF`{pHtvN0+~t&BE~X(Mdv>0zQt$jv z_(gyCMI}Ngl)e!Nk-NAlI%Ihi$H9J@6?hUKdHRtvjOeafZC??{`t4E`5And%vcJK; z+DEK=WOUo3>+p&1kkZES>f{k_s1Eh`XrWdMR_G5-+P++!X~~B@MoL>$V%_sT(xJn0 z-#GF(X!bcyyy=+qqz&x4^ZfAzjjVfelr1A<)On1b9=gjfb540a~ZK~kN9RHBLrv8P` zenqlLgJUt>-SRJ-ZLq>`UM14q!|(9agCGo%vK*UCQY-g27=Pi-ShTkYX>@s__nZ4I zJ>+bm-1eXdC!w0v$D~@)I}F7RK^*kOcxcANHLd3cFUZv)?YX2@A9d~MpS%Lv?-zAi zD)G>+E0Vs(nMZ%?x=mY?sQ07VvdY)sB@mMiYBbzHAP17e)07(__v_aR?#Q8`L^3ut zaS`tW+7u~u!PCTz(No~CA&q9bry7{&)AQXx;r%z`E%P)YZrlO1E^8;d5a zw~39b3^Ky`E^(%H^}*Sir(5!`agT$)2;RfDx82mDnUFQJzsh^e??0wR zT7bW|t`$R|#`Nhma~90(;? z@JNno_Um>IvE6E1`!dht37?aOlH6){Men!tFDz|6qI9%sI}!HALE~CHLJ}6*SKv<& z6df^n>y1_p;lT#+KUWzc{VD|;xG^eY1nR(ncuh!idRt2Lnz1QO75RGS_#e75dN{wk z!xmeAGlLY)$D4@}<(nQH^__+Gf!ZEq-XH6S@NiVj!T7&tPreVsRFFt_KY-f~kL}Fi zxL*eg1nrRLA)B|%Sb9J~nnXyLEdh*c*YY+3JQsA2d$Z&-SY^93vx18g42IGIhBC>j zTnzPM7SY75evz>s$^99!_iEUPMv_;l z=36uOmZs|KBH2GfpYse;Hpdh`o0bSLy&RVCpBIQF5teQx9RM|bS)f^HW8|4rA2O70 zJcrN-W1B+*f8iEa9(z^&zW4l+7H8|O&G!!UCfVK*nR&cAcczlG&0c%Bh+n9?s3d1h z4~?PsIc>tlgF$pJtCY|4+nGZVkB}xn;!`6HZ6#$yROaQxc-MZfJWdq4%CY`M5~Fvl z6CbuI;uH_gD_cR|a*>+&GnFlbkk=3WEYL`E7j2Hk)_t>3lyHHaB83t%zQOFby*s4f zp?x;LXbdmbRmMA@*QpYga)ad<8Ku4~1gXt~{Q`E(koYZqC(8Jw(=RStS>Y14M-#mb z?sQI&Pd|v!8P~RVmE<~~p))j!B_EO@cIhrDZ2PP&hfs1>2EzB%Ya!cw@8inNGh^R2 z{AVR&rL?fvxk*HHQ6C~rt_B4_0qQSrm&LEUi~4e7v?xd#k0@{?xl4|kk&z6~~!5WI{6i(}Q5^$yFgZ^1yV zJ{={-C=E>83}XGI7-l1CNp|4R)7Y{Hyp4Vdmu-8qW+hCyk#dkdzmw)6&g-%ZRIc2r59y0+3JdzRNQ(uFiGZpWEAeN0QVhBn)DZ9i-UhZ z>HBl7hE=Z?>TTBNvvV%3?8&{}t))#kJ)$o~^2|Rp8;=DeQ=^~ArS?S4ts7{8+!uS< z)rVYv{nJFU0vkyh*lT%pq--%>H8WJ7z_;pE4OGpij_s(<3>p&1DIf-a|$ z(d~d9lEnn2Zsr8b)f5f|uFdE9#4rhTi|LZhZ|~29Jnn5NDrZ-WuDxMb_NOI0ez?bP zxOZs=L)K&R?A~-ufsRRn*rfy*B1z*drtPEHsDtg zQF#Y=q28LY26p+F0p^vvNlioXr!LO@RCoLLrJDoDx+T_UWS<7c+b7@WjT)%YzB#sg z!dkKo&w0&%X*q3yMiF!$^Cgqw?a3oFU!Tw0OGy5}F1$$9!sMDeK|aKqX9nk2YLud} zKdE$jbDF(s8eOCnD%8vsxv#XD2mK<0%Gh@t_W8hA$r)S{vZC|ovEGiAmc?6d5|Y0` zo+{=JG&P6*Ghk`5h@E$~C-Zmh*s3G<1_pTeFi*?xC#f$ zU6o*mwnR^{kd-_iZ?YO`s>AmD{H2e?N&e)B7So7wXxgh+a{G}CnQV(=R!t#H=u{9! zD<+f(%fitm3G(($((>nhr+N#Qaj5~)UcK%ylh)?frm#sfajEYHd29zW)Ellj*j;s+ zz1yK1bI34Nb<4aXCgNk;9?4=}>8YF33Ngl6*Xn{pY3TgwwIX6imG0L0@%yBXemlPD z%eJ}wgl&d8gK?c?)v%>zN>#G;N1p8Hb;h#rkOL{N!I>xbzd7xa^!}AVVKh5zCa{-A z^W0<@l$)qN4DImL4+lG+#7E?nceF~QM|0WghMziI?8i&*tppl`vPF87{o&T($XE$1 zo*A{60M&L+r$tKVbNto+R4o)d=G5cIoYVfn(&%z|Xng$>I#y-t#(1Oe*TNj<`#@>+ z!Me+DfTgq1M!Li-QCg>xAbGA0^_Yi{TzzxNl_a)iny2E`YdvC@N zZaMw=NC1FUT=<-`M^>W5sT{>y~ znxA1Mr!9&WH+?5aggY}|l8304^l&m;KKuPkOWM z_ClD8g>%c>w@kxi%yU|=HuU(Qv_vc89f`%skjzbrQuCpyl>o-g_Q22$#b4|NYnS$1?K!SVGaV^@V^NU(B;^^vn(==U5VyS7tG~6la!`B!LsJ3 zA2tVj5XtyZ!;G}Fb4eC>{ti|`o>kXs-s!^7SbO$Kj1~&|LLNrl=Zn>AfEjkPiNqIh z*9Tx9Ie~0V{{fP;FmY5K9P0=kj_RQ*+t2N}KPuuO6z8|z#?A>_X_EL$(hh{8asxj3wvmnK znZwE~Q}JhmDdga*tLM#op`O`6PiqKcMs63LMUa39f}5AxaH$q#LB1q*OG8K^K4&SH zG)nhXs((>P*q2q0K=pJfj8Z44w>0F(^R&cB5fuQvyUE8W;P3U zwE1WW)MDchVgh!J8Sv7yHU!Fay2f+l%Af} zmVmPdEgS}%VLp%ziG)YUrf7Mn=S1SImf&J3qhZ27g3e%bBNZ zv}dIk2&@+>Kt+`=PQMPyQGz=`wir#yJ_AvsUx_4`nYF4@2%aaowSVgwS4l63_7 zU#KPlXMGdpZA{Th08R*>F4+K4@zk|^`$>wjn?Im(iqw zd&$-iKToCjjo6rT73zz&9P?qCsqsj(X6UHk71VeDOu}<4p>5!M#_)x!Q%qL*@Ejg> zb(!S0cu!@?fhBY(TZD+05cEHZ!Nxw&gC!BnW@rh&P;D=z09Jo3o}3?@+!e)Bow>Plb{0gM{- z{@geO)_t-2!5+;x(hJYza&*6TrGw!33g9?xQPFc_2L~_m)(saCF5(2x!KHmyinaWmGLeDui)RTz`XN__9e%v;JhL5hiX zBVOvzzf1=OJno7lxet?+N#dyP9JMVai^zS=k0bC2fo{;UseTMN4!qDrxU$mhH@X?q zmyrlQ6u>bF2cnzfE7ZKVX*IX%Y}{ua zOq)493~9|2Sz!i*S`!(9RoOn3Aq4!bGh;D59Vy(d8$|zF8V^mEt%!u^2`z;o>wKJb z>YxXn4}vRuP|U3N-d=XcU>JvWui}zoEw_H2Obiy95Rk}V1-EZ-vBOeo*5bsa^m`mR z{R%UfRLa=62U>HIHT4T-?ue<5vPq|f^ABc+5p3O5=_30tMNsM;DlZHPbjRT&;Ezly zIQ!B_WHD-E1tPBFB9x()fV45(DA&3wz#6u5~xOJ z9i^;OiOS5W^H`(T-A*{3-{x%j$$5^@Zi}vLujySQxC|(%(fC2`SSgFB4LD!F7KHb0Ifdx1y&p+Hoc$9)tLR~GLp4->@ zRm0@9hzh6Dl>Fhb2Pa#}U7%FOB)nSRD%h+I7~g$aKRAZ`57 zQNHz-Cq?FO67d^%*ZAmRzE&KX-zeUXqhRe==!5hflHyk-z?eiv7xO@}yxl;tb}RP; zU#*T+-8HLx*^2xXrX3zgQfV}=X_&zytJl5bV$xYX@Kq{`#jx4tp(A32UgWKz>pcU3 z38&=qQ19lO_S*Xjk8H&ChShvqYlhrW!&Uuq><4L;FD z;vtJ*`mE~GSCfto5#DZ33OXZJAV>M?F^*;1y3_eD+Ln&Ufa+`e$efN z8Z7s&sJ^aPj;UPJenDa?usm$lT=M?&6C~#olSFY-J`C0I$gIrMI7(T~d zNxdRii5G+$v)^!BN8A1^@Y+i8Ms0C-(RqgEvaTVARbJXH0d zeJAZFAnKV~{d`pCSYYyOM0fSu3h%m}E(#C)I&5p-a3}UX%P9 zHTB8JU1{t-iH#DvTSvuTA~`CP8tzf*TC@Os1LfO_D4e(o*pXha-^l8oRC~lp}^KYtx|5`3K7IA}s)F+qM3ZIY z_R%oLqBWfyfky+x(iN$S$fIlYW}OBeg*AlUN#JWH1La8D)tO&Upz9{72s|`MR9U|! zKzE{neI@Z(qh|Mt^g!g4!X;dw37uAC)v>7rjy{^m6 zehE~#4bciTEYfCWSQaCSmimg1z&mS4pvAPK%5&yYA;Kk`)xvKYuzQ(ru#doAsmdT5 zMumM#xc|>1eB-o!`aSZ{zN>wRpJB+IXmC51B@@=;`@d$_RGz^t)E=)Qh&H!-c#9)u=x%=cS zwNNzmz{~IrqW1;PmP#3Qn)0RL;NZA4>(#+tg#UfR0;LjyaX`Qn`~HYpDvc>2wVP%2 z3~9;G0hw3ODcQ!zM(3gNYg>=CQTA4X;Yr2#n~#y%m3lnTBtW%tKJxTr70oS@T`5wa zZR$1OYA;UiurIaG#Tp>j9{tE5Dt?W9WQqphP3l31uTKj)7Lt_$M|{Zwx#6q#J4NAH ze5Uh|p7t>hSiZc=kufeh;5(uc%K+&b=Yp!K6b{b`O}4|7#tx^SgL=izXGrg`vbCC1!$BE#!_% zD9PS!pUx$XjBa_fCgOp*Y00qC9b`%Chw=rr2|4?lz*t0;BZ!Sr2BTaU zWOa5J()`&{+Z`=bJeKQo$?-3XW48_|4e58j>FuQ~&_P`m=v|@6H^oOxDCZ#>0xeYL z)eZs>NLs&X5_cXj5c%ooo`8RWp+qbQ} zgZWi0Yec?wChp?QrC=eLj{9ig+J|;P_`m1?29f>Gnwy|K{D^!C{;CCtQ7t}X<;oW8 zN5he72^P<&=+6|WCd)|NUR;q9htE-XhV!|pAyt)+UjVm< zcs=^y3(eo>nDD+5@i;yNF|9d`NdKRe7(Q=z6hI=}oc>fU9@m#c$Z9fp!`R$KX^d)R zsN_oYE6^bq6qPV78M9%=4X2--H6CTIOn0@&g_DGmU_&zy$_%A~ll&Oog)n5H778_6 z)YTigSsx`N`A}l|oypYuyB!3`s|dj-+A9IIj9@L3H^Ew>dj6COU6VgPac4;HE&S1x z7ebGcc;QcPbhFb_1`-eZt=^TW0Ft|@v#ei;^xoDX+)xaLHQ4HVBM8Ant%6qFrh!?S z*$_>C>Vm*U$d#fG3pGG!Vx}nAFDsY zQ$+SV@!x*E?_$b?cjw5t;hle)oA%<4O~QGYbvvMX!#rp#)9luH(oOcbo{ANo7EZ?K zK4LU3&%d6K6o$zluRqPeTVQ`CMX0&D=@i(Ob@x~&eB%UuywNmgS`Jh zo1`$K+~=wUSJt7SZNN)8;UKYVlP3XT`>s_Aaa zkd5A$d7qON4!wmV(58cKfZJ5VkrD4*SPhH*V4Wv!>@kP--RMI^l#E)o%VN|F0c0oO z9PG+|10or_q}4xI2PpvKKI_s!i|Is_U&g8;y=6)zK$BerV80ID^3Jwi(OPO7_Y5U@ zMT-jtppVq=mBlD2!5<5kqiD9ODU1>_6NndUR?p-IVNzbGRJnqzYv{k70Dk7SZ&B@( zEf1KD(SjpUJxHF2@Ykh<%uz%SjT6MvNeZ7oHWx$HLz_jXZxqb)qHK4=fQR}J$W|S9 zX`~(hYh9SIie)JXtirmZVbLc>Z=T2BD5x$L6@@&co%A_Y8T(XO49mZ!8!w-r?%`qV zxa#thI!Hxx`^#QJe{CvRU@vP#czcnfrZ}aj%pDBrvg*vltYUxPfCIH5jew2iao0Cazrp+aIAV{5B{n83^ zcZ{!^E=`sC+{NgrT22?nY9(Aa|GAfT9-@)Mzq%^VI`(Vc*M-SdJnOJ4%>lhl(en;M zIsHdSD?5t^7y|LhM?vb3ksldZpfW%pO3xT=k2Np^{(*IiJ?Wrg3! z-%ZK93y&tPvFo$K`y-_gSbUW3fWouIgZ(3IB#qv^poSo2}Eb=WcHbqruIEXkG0Ft@eAAO{*9c} z<&dibI}tBuie4&n#(n69jumxViWv?cBqXaobrLk7c-O0-yLa^4>4}5-QJ^HJ19iy5 zO0S2S{)uGj96R{Zs{SV7bk81`^cb%`-BX1Q#c%r2c8-5bFOWbc1~mXvegW$&Jb$A6 zGyj6UV>YQlh_df4`Abv9`t7afa~ThOQtJv}qYV-I+O1`=N`_GX9_g%*ai#n!UhE8nI$>*xl znsGpdcJ^KRqx%8)U>A5!4rYjSpWrba@8DoRI25@pTO6V4pu6yJH|at*%%QNe@K5sW zFqO5I9f}9l;hD9i-MkVGEo!J87~FU#bHRlpDoTx392&exL-@Q)JCDdn(#X;x+SnvR zaQLL3>N^Z1vKrD@T;EajJwcWnEJ>XoU6jB1=Bys=Ot0Y~cfk}EU$@de_t?$B`BE#I z;o@us!4%|57WeAQD^}h(okS>{TgYcEnh4?hKe&ETSYNq`R-8}xuKsdK%G!O-_sP#| z>ooMtVIOwQ8x_*9Q$QVeeD^2tlX4n-xJKn}^HR{CQd(uufr5Tuusoyz8-Mjfy^mvX zCD9)uzd{bo>2jjoGs2D#b~v!@-oX`cbN=aH81Ec+4k95#h<>vf}8cle|i-c3{kIVeT%&3dApM^rv!u^Bg`7roM$<4`% zPgkcOb|1O_Oyt&OA=hu9Wh@m<{ho@PwJ49&f5|=ei_e3VzBWnYi~H(Vv4?Udc~j)_ z^b&j+e~@<{VA=gh&Ieo&HJa^;cvLFtAIi(trxd~S0m7W6-m8alE7NxM5F{z%elfq1Y=sQLYbv}&13p65S5?Jz|`4!1qLFfku5Au;9LaO14D z?{-vasX5b`T5_wfhXi?SUM-Z9O>NPTSjeJMOuop`k;$@J$tk4H@B9%nh{badDAAU1 zi0XHv!nTmP*KVcm)+zv)DJOo&@=&|_3iF*01uA8Q9(PQY7Eya)D^$8Mh6x{ekB-Q4 z`ln(C=+6EVi`yqYzg4jOGKVO|x7FUz`{1{b7-p3W9NmM!?W>=fir#~oA3 zMZ&aGs!Y_OrI1)D%a`rSzWKjGb4`SHfWA9?N6^OMx(mIO2~l0i@!f1eMqWEk>DftJ zh(trl==^@D56DgrJVF-QHn1hUsJdIQmXPf1wy<6M)Y%*@SFJ9>C=a`3)Kyb_3dzB& z=Ph@K%xQJOG-Zc9xLSvV#cSpmA<{A!!u>r%v0+ zoNATUq0@$kZfwVs8dDoeGo87%Bl4<}pEBQRqR$L(c`oO1kSHEwjqc0Uhl3jY_=?8I`}oGg+H(uZ8w8I3$hIEahJ20prf9PM4BdOCC%Lt44cFHSJ~elxZEo z?N5vjgzj!j%!Esf--pK)WNV<lfns%u-}{V$JhRNi<(yk5*}Z!d==j$ zZf1rKUXA4kH>R6^unQ@%Z=*#Om5uXGDMIW18?Rq3cSJe+SGfXMi93WFIvL*WL^wjB zpk@4}>q0_9q(4wOL!w}(bo9VfOj!B@$x3Tucu8Y{#IwiFH^Xvy#3g^^Xgu^lPH#Q&FDNRhxhkkrpZ*v6n<6ZUANg z_b$0?jEcm@mC}ZMQ125cku+OX1#6`$c&Pb1o~T4Ag!ATAVK4Iav%@el2K@p@kSYI2 z!UDCZRWpA9&kC!-Y;KdTYpB$@{h6J9*8#_ya685 zM-n8p;q<2-CMp>u&MlD1mj?{nUUlU^NdSx5aRR6GoN0=XGYT9tpqFlKAf9dJU%_d; z`tNsY&NH5nGdkQVW+Zi*dJdrnT0i0H2VBQb0VX(Tx;$ef=*5@DXW+&wqRZ*ZkOAi2 z7z=5!A$WxUw}l$cuZuNUA8Q;K2;_0mxMoC`k8=pYqN7$}$D(6TQGE7C@ZHtw61dt>7%xMmXMX=0wCPX^pp)>YS+^M z>8FZEPdZ^P-eV{GZ6L#~CUJ4+?Ij)@fIkq1f|AONxfT( zx)f4=w^kXSB3Gw9iWA(|oVp+^JP885s-i$MT>-{GqQXu=X^iLokJ`kp5!SY#PMYq_ zHTPSZ=FT~ICav0JyPkgEB#+3A){-GTPrOW--a3A0`C0Tbe3VoPnFpHuQusUw`pR% z!?aK^@dWo6q|su1;A&`G0sq3!3&yKS>4F|5f~7G3gsF3$qR-2h+sVbrsOeXPWZ{7T z6#r0xl`hJ0pETaw<7OC`vUujr>HCYuB>{T>q2a(yLq#p|Ru@jK#qbz(oj#{6Wa%Q6>ZF0)LNSzSZa! zI{gYPL)agLpap}_B(QX`j5&lrVlHu_ORum--gIWdph^4foJ?~Sq<*Yq!*?8Ks!L87 zHflC=nl$WlF<9(-QRC#W|7d_$F7+19o+u9Bu1Y0m<7{f z>7+^Grqn-g%NI3ZK=^FvA@gn83xa^6D`>h75wx)E=q~{Om7*OD7kS-2$bN`NJ}$Dw+<0TcLd{nPCo1sokyB^_IHv50J1_nogVY zz`CoAxvxNWNS(h2d-reGLsHO&gppd9uMScqERsANo^{>7vpXlB zVYGtgax)Kxyx%eI12~8gkoc5Hs(3~dUnc1jzCMXVZX5@^meYa*1R6DRNG#zT%?RK+qs`6eHo z^uz%rZxHsZp)1yN{%Yy}&;91uRzkV}FQcFXY;M)9sKy7dFo_kcX}b{eU3iNdXaCj7uOW{U-R%(Wh@&sLrX5D3m`_RWj+3%h|xCq&!;vzeg6=nS9$&+ zMy)9aI>s}#I#ar01|P#FlkwgKK0-z9mdO4;prO{(at0ZHp`qz!a??@x4%fkP0zj`{ zbuXy3g`h5vlg1~+s!mx zJN`P;I{=6T98Zv4z6O?^JWa6~u*yF)5eqc#kPm9fgku44I5!aM5>e+wj~@aLab6o( z;L1Vg2$FJ<=t~mBVb`8h-I%o~eSPB43R>$Z8Vr=fx-12-3y_Ed^%ACzQ2xh>iuRgm zq;YQ;LmKpUhO?=7fk$VAOS{G02ezXa!A=ZdaN*#F%XDqd`2al`*z^K&a#N%d6+?q& zgcLxSD>^m<6OuE87y<5$B(#sq(FA_Cu4j%=t)%ft(U<5j8f3%Wj1vByjl)ILb@r9o zvyqY%!Tb^~?!8pD6VM9NrRap0gxKkZ_KEzWPK)cb20r?&RMnE>|M%&>J}&>TK3gTY z^bw1pn@zQk#AU!lRvu@}0-Xg8!Tb_jm{RTkQ1;$YO$A-ws0~n&E}+sBq&F3aNEH=Nw1ng~UF-gtlR5j$ z>@&0LZ}0OnQ!BW|gx6v{Uc=7?7$LSdA!+5F(9q`zjRusl8n{q7R@Auk+^wTRf5PE; zxJZb?S297kH?6l~&VErGsl7=7AyLa;2fiSlF;8xMLmb$Z(S+7qo4@k#q5G$3x~FSA z_?O+T@yP$M6aZ%^{__X-=1p5_CSVU~5~Ytm;)m23VlH2muZ|5Pc%$i5ilpsEO&48! zjM7I~6?p=dM!#2s=e}fhaSx}sKLF}1MM7k)g%kq_64B%dh-APx68HjGhX`25E}hp+ zoCVQTn`Q#?u9}u;p5A{*9Q7H;gu&UtC!^7uKHet?j8#%ayaOyaJYpnHO(6NRz*KWH zhupt`-k3QMj<7tnf=aab1}O_QTE^kkn@y|VvM;=%Zw+-xPlNW@o`3C6_&E_un2)K? z<%JgE7*4TpTT13Dq_WA*r4C-7=(1)vzK0cRRA`-AKp|$;w0{P=l(@C?vcLTW5HHB^ zlS4$r7->Nq&h|XWz5JXACvX8GkiGpn(J_z+xndzJn?L zxm$)-t898mG@&opOXDS<6Pgb)C0%OBVmWzD0)ytm^3)#ltp9P@FQgtASuOFf8>gX0 z=}FNJfpAU;!Q5D+_Ro0Eb2k+zaR~r^OQX#fr(~C+@W>CroE9{3z+u5XN;BQT}j4Szy4kc}VH;!0H>Cn<7brPH;f zfsYNuS);g@-cZTE8_$CqgYb8f(xiOrmlHUX3j!N`R)1254K{qJEFTKL?*aFH5i zT1^8JAE?p#kBu>@Fnd;>^<5|&Ccw}h%bnM+w?t4Zt|*D_Pr;tScn0I(&Knld3h<$t zq#r%ffsB@o>KjpQoL@oFC&EL|muF;G$iPlWFo{LQ0rW+xFm?F1yxm*abSPqFit&D2 zRouI7)j58@hkwiJ7hbk$K54G6cn08Yqiw!?%E~Lam_rLpDxUpH82czH#h{vRl@f-F z73YTtcN>)d`n!#PrvV&?5#>i4JNyaJ{73H2pIMOu8S%9-OC>zDA>H)>KYDEhN=u@{ z?vVd_sS^#!nwcmw`!6ZLSMu;CY^jqVwrd&8TKr;I>?yb0fLG)skmFF&=Fu#r-L|Sc3GRcH2hO9>+bx1~mDCOFCgfO^Xt&aHJ z{!ym*b~G7PnD%DfJ*J-chZ0gWW%c77G*lj=r0STG=3#DO zs|yhNH^Omleq(1xt}35n0oGb`7n&1QNU*7`6RHj*MWuin*K|P@0XUK>vq-``r&yIW z=4mT@T1bqUW}xDSXr35WUCYH_BpgcPXICH#jO%f|Nk$8*i@qF=m3zf0T1_iuw(-q&Hjtryh-tH3f7 zXHBp8)Zc)R9C?G=Hu7_FuJBgmS&FWiAbaA+RBe2!*PomKgX0b zsL z@cV61HnRGzd#6>}-Q)0_{$CwgE2*1LJ{7`z* z*xFgvu};lW!ryI_=6o0BDF*N3q+dci`~x97?z*pqA`cbov-_=Nu>IBTIL5BvhtvD_Y;fgy zxMc0h+b}fe8&!-RBJ9`BE7{GP_6(@mCR?jQqDE$xZPFHQA@v7^Ta)I$kb>rz-q){L zN(nN`jItb#y5MSg3OEa~W()JILzeX_;$%REO;!`Ml3E9|v3V*SunzL-GeLMMzo0zr zFueX7fZ!b`0q}Jl2bqJL*uomE-~YJ=!V_zc5nJsg(3?9udXeH1*4;oaqKbP+4jG1? zR%?0H97~LC8$F)5ilH%eb-z^<_?+>saks_R$uGvQ8xsfibzm)o|G*@Di$ouz{> z=exPQ>6^N%;RzMl+sb<8<5eDN!8XMxX?y|h3=WD^ zKGLopt~{}1eA8XtxK()l?b~Y-54^5rrunrpc5L@7}0K| z^=>IRrQx>KKi%PNRGNaSyY-6G?tKcRQf*phq`4;L2rMOx-O*{SY3O|?YA)H#sFfws()5}6%UT9Xwph*>YA?!I=LRjqJuN)m}l__h#_lnhkTSJl#0X-hQ4l%S_ZT zvT_!$LLQ_yDDii4)bjIvL~jpuyUNY@TwCj6qD-uH;eE| z$+)lEA2FOo&Gedr7^XO7by4I$6C~=EL>Xc4)w^V4%@q-Oly24QLi z!7TJul`VytGK4tI+pW545pgS7VBv$ZgjX-yx-`D9@R(#gR;1h{X$;$WhPvp#f>}fL3N*-V#Wa+ znL)70sK<|)HHM0TI9z3&Ck7V^7jd{QI^Y9>7w2|x3|yrXtRT`#*3?Jx3mMvm831%K zdmwT`vW&Eg{2k&AX2lFa3cBea^22s6L%Z(Y#)y5W0MJVO7hd@T2gx4tftkbTLnDWa zX@jcs*A}vYRjUJ5R&0y&rH18|w>(v%Cs7H7u#SYJqGj$KEBUVNMvbn~y^cU+N0c48 zmU{Al8*XBS9NhwwU&PcmW}@YLqxsOwDsn=6&=A=TF4Z)zFCDKhruisAou{0i%6{|c z`2gaCP7mKAFaYbI{*sq0VsP6z!iGNCX~5t=#CDed=p$M|rQm5w7_YDYswtrh+smF$ZIW9DQ>A;zWcd zT87@ebG;yL!wh{(=sq;kSQo+l`K&pJSbcL?@IZNl)zHSqpztChfNnZ-fo-yPb*5+-bXv!I{#oJOdPXFH5}0(HIaH z*YD=ak@%HG+v@1T^b%B0{HWD)db|RV`VYE4L$6x9K7wn~Kod?Yh_>(+DB#mPUJgMj!Qdao+ z=|X+Pa?R0*inHETc<#wIXb=TbfrX^-g$w;ShWi5a(vC_o{)D<4L3wn;6w>1oQK2|# z%EbSB5I9B&syVdOOuB$$Z+qb6F@#6OywG#-^R_p!s*d;Z?{QoQU+F;H|G$@Dh+B+1 zR#%)K82k_6JTKNbxN<}0oj8D2zZ69A?F~Vq-VTE^DCN1E40`RnIY)dvJuJJaPc&j_ zoEJ*X1R9%2)Q_-#G*vIuWUl$zA_CR(dS9(e4S%pHNv3#k>T^hVmX&jlXmX z9jTvPy$!}r7~*oVANN#b;G-q0&sl0z8mOMN%#D4(56Qps3yPe7EDNdOy#-MK=JD3A zkCNqs?S1e`vDKmQf!)mN+Kx!`*R`O_6vIudy(7@#BPO;K&Rx9FgiW6#*P5ebJOgse z*njg|_I4MwV=2yOaFsEO;VAVN@86n@ZX_E)Uf;IUe*E-u`x5C z`~*_@%8Q?22@O@CPAW?+ryT7Z@ja_U>&#&YQZX=h$OKf)XC}{PjaPC zX2ItKO;PBrOuyQ`xz47|SFa>fQW^XDg_Clrugu@dX9G`)vtC>N&$EJsTDYbdfaXd_ z(qNjBhzzWhp|1sf-gznW{-H1uV?kc0EN6Xe?=~%8X^2u#N0{RE^~rs6v8Z1fdOF=~ z8)fUllw#|Ck}+h@!rvEp{O*5K2u3^tT<67^yuLIs zwA?NO0&nhrp>ti)-B~VL{|lbGU~qo_g(GzBG=TfU)iL7rj@njPBk z5mV0RrDmKc{Hrl&Z0N*8lWxe{CUA=AHezl;1_Rt`GOIL;Xm;o1_*6M{yB_ybctnrnj+^m9l4LR-<*tv1 zmV1?^Rypob;55}8RF<(dEnGV_Uep`j^DS*Hy*;`Jhq=-3i;<*7EZ2TChba|mz`cDQ zSFLRWtgl#tqksK*u$lZp3l-36jY9y42%sts z^!$OO+ZqvOW`t$OhTPzxFmij5BDbwFrI@7BDNo&R3KV*MZ)ZTT9!4ca80(_@`R4GS zNWKeBELVf_n3x$*2{;Bd8=R<}k0v}XJB@f+ZD!vvFcrM{K-dlsm3_=lB;bm{DUyMz ze-M7+0UKOg5c>pVgv&xNSN0_pR1x^G1Zzx1!nB5#;AKgWh&i|IbL1;&Yzd@9*r+L^ zJyL}VDRJ0ATgV!e$1%*nM8BJ@Rv_cyJpI{a?ff|lAfFmkFkOS~jtVGaN0Bg1gm&MPJ(I%At-$? zHP%=xMabQ+w*IY^zCi6vqCH>$mSPNCXeiU?b&-VOMi0dw6BWt^^`o9EFT{k zL1%OWbj?>Ep>!W@@%K-7V{vgP#{$c?fjKP!^q*)4R`6GtEqHh?jcT;&mf0PpxBdJP z-h&)=v!{fjxG3b(+{4uR0*(gm?4kRl%IpnA4H=iH7H~D-?r<_3-IL+Hj~9C zg}6kc*`p4G$SDz^JxPVgkm*EMo3T2`U0J5f_~OL6&Gf@DKU_b8JojCL+x*c zeq!6(4XR8|BvRc!*n@q2mCb`zqG#^c(=rfEr1})j)=abV;?gU*C_I1n|!UxOf>;0nAq#`w+q3@F+aiLq{p*vXeR-)`ADEQ^YgTgy@~NcrKNFr5UZc ziSc!R4IRD@HiD2OdHI9c^Xb3uL*b8ge!nD6#yMC#IFv!_y&|&^fd2f0pHO7od)dz| z0S%D|9h+O_J!Rd?`}b&T*__Oa+Hw*EkSjf9kEULzYZ1LyXMJ;ZC!J`p&esu!U7L2E zMOK9mLco!6Vc?$xx}Dq)1M*NAn)qFNKTx2E*2*ORs+pnnDXPuAdqAW5NJlla!{Pjm zi=7Xka$0_`HOvi@f;_1Y*NT3mPH3~RnYcAfrwQ-_{}pI`j^V3APl5$~RIMF}#y@4< z1w+t!RiXh;a%@l<)WpEOHD-h)WKV4!GFM8Q3@KeKR3I)=A5pFKd;bpO&@Zw@8X^?~ zXubO+Ic9)$8a}k=FMST<`mPu_v|ka$Dhyw@c%i2|dmF$9v4mj*A?+Z+D~w;@ufj@8)0bMH+xK*2~)v z?trsbg^Xal*iRx7E@(|ztyHK%HtxV6Q93Ho~I`OTBZC<7FVpAVI7;T^> zm`V?&Ag9`n){t-cq(A^IOb#?(#9Ul?+pi3oE2Y!s@+9!R?htG0^^>T-Oy4j9M9pPJ z?&%MeHtN~hS}Z&nN^EHinw&e;o@sB<`4zvHK|3zB-aWF7vbVTqT=SHZ>s$JJhQm!Z z7_sL@?qrs@%-E2~0m^6%&hUuvfXStJzCq*JFX)A!V#B9BAmk~CjZWSIg;H|0UsMa< z5{6HoXB)7w#3zV#Jgq2vDxIkmtU?0ijqAF5vX;q?U9nz$$fnM%`;~v5i}=QPu!_8p z1Y*e=pG-4er!*eTUon$&8Ql$9PVPuTgP{W09UoSoVfOmV0c7^@GJ?TkKD{^}WH}T~ z5B;E&LpvaTQB}J%p08rhD#vYR?VJo31)U>2=FkYK!lJ{iYg+jMC@aH1@L4%|#6VP| zfrN5Sx5?Xl(9+ECPYGe7wc$9LFEoRky$%V|;tfui3Q*gG%Vc2HP0`4}Y?gq_Foe+P z2R=tFL^WwL&cZhy+5F#a(SqZG4VB(ul%#;qS-$~wP_FL-tcCP$VPD{Z2Xu|tw-M~J z$DI+9Am3H0C2C(TH(1)BKRcm70YHUi1-xSKdWiJmKU~xa3;Tn zHBu*{g&vjxOaG5iQlfe40_J@b?zU~KRNR@f57XcKj{PzdC^zz zEm zoF0SI>N|SK3*|#7;ne4(+3dAa>)(bm&!suOYH;VjT$E5t&leYxmbVK#i+S*mxxg7{ z=0|f4d<8KVLUc&lgfvdYu>sZbl%D}Lc;F7?vwvNMmc*da0X^KAfyii>c72qzE~51| z>i7O2SeJ&WCSRBmatSuD@Y_(G7Bwg-oti|JLEwqA`I?${6Vi{-M^J!)piua&#~^e~eJ1YA{%o z)9G)P2`J}rv6ulLaoQ@|Nv!5fVP7wXM)YJvRyT-9Z~(9E86tlqaIj7f(-p#3<`5ps zd?!db-N7Av!-}sagN4U)!IGX_ecHt-vVSY6>=7as#5@hEzULPkWV51#;Ycd_CLEk; zX;kcWK`k^Ga&=*~{}E!}B=N79I@x=Iz#H83dgu*H9D}!rY+25;Rin4%&k*5RRqinW zv8suf*yolryDYC7r?lRU7Z1YI0_zQfS*=6vRfP6-?9erp(kfCfjY3`J+p~p~MiW@_ znj92z*|U^6J>?K?G?K!Qmdrx!rr4%@Ljw+cspt+(lNhD=Mfgm<2BJ4xNOiQ5+^X}- zk2wvh57a2=Lxi;1_tcOTDOX}L_0s_an;n`Z@(KO( z7`=1B__?wVX7KjQ#4uvH<9^C*l_N&0fA17T6h5Hfll0K2pC9%rwwAH@^}@a3ZP3}C zB@7>=YgO>x=8s%|mYIKLwcWorEx-UfhuI1#CHUxhyr_K&svt-}@3U<}0?gs~2{Kei z>jBr&(}bs`RoH%^pC|7mfVQG88$Arp7g6L#SA)0i;-0!f5G116s9L?`W7syFQGUKw zQF_38z7-ZC_}SwwU~$>Vk~E}tIdus{NvO-382B+x(MT#V^w{2w7)H0F0Hf{kTlz>9 z$e>hw%8*MiHA)bW1u;yvN32peF*s3y!L2#w#Az6!S*`sD)Yfdd*RO$VHu>gwUaTD`$KZzAxlP`~QY+X>-E$FCWS><9b zy7_OYa^BkaTRJ=5=>6Ui%?Hi7_dR_#2j+LVr71h>UC*s4wXVti1tm}V&8K#Zu!(J^ zCUuNTWarZBPZxdP0~NfVT&(M7)YUcZAph%)fRFi6bX4!6RR*h$F{ABZr@0vj{5#qH zETe`!Bd1ENEaLhtt7Pi)B^tew*+XoiyMBF!;r|Gi+X3q?2q0%6FeN8GG7@0vZ z_f#d!d)A*F&=W2Yyj|qY_;1eU23se*N=qS5twNgo?S#`-X`M?rAD}JHiB08r0(X9m z{h%?Z*=Vp0%z)xY_d&#aL@X95=&X-Wwe}Xo5(2CdK5w>O$A8SwQqiF>HdE}qfy7~N zVjdh(Iw>KL^M?j;LfoF*7rhjraRv5_MCx0|1tEA|v-@A4`ZC=Eone)MAa2UZ z<;OM4ts17_-~6eM2+Vy)K-Ak~aH`+8Y{gw&r#3r-58#@$<%NDJtn@B+^{+4wj5r%I za(m!u^iZe8T~P?DnAM?WjxqoTYXbpA8<(F?%|udPB_kVG(6MDMZkKDnbI)_xvAP1pIr<`_%d`8xCnb1%NOsP(1>3QNG;1EvN5N>c?*^GT9A9Jwb zJSY5eLyHB8fOqA%fIuXtP$;W51FN`<(T`F4nx{y_#9oL;P@b~ERn!4Fm4`HR!}w=o zx)%MJKwwA5S0Ixu}o8DA(BgFXxwTVt3*+Tx(Qw^x4LVj%%Jn zT(}RXZ0HuIU{|dpSM?FXa3Ymp<(Jv+r=MgV4Up{XRZq%)r|1dOyY7v#?=So~xwgb7Y7Ocp=7Cu}kxYPR&CCRTK4uzt z6#*0l@mko0KDe_&pDUMy-Z$-nXXi1*_$_aKaHyGll}t?IEy*u7s;)yT6!2n_pghe) zI@HjH^W>AG_XxwgMP<=w%d;3@rAy$Fn3jxwcEo%~EL)Ww4{pb3Y)Re3N`Q?$rKoNn zf*;wdDEgW?Xp^@*3Zl9Ig?Kt2)qoOeRQrbWRK}X{x1%z*+N@~w%zp^VV;(pwiZ#5S z55~G;P-0V%!y>f6Dw@pGznDJl@=>0<0qz!t=3o-1KsuRl{{mOavKaM@Nh{N7mAQ(h`5hyyruND~RAbO|OH%i2`XD$_yUqOOGxal^>XQ7JP!J}sS zk>iX=T+!6E1y^lJw{C=x;M7(Yct5V+z>-!D84N0_@2%GjSR>XQCd`ZL`)K16sfd*j z(*e-{%=l+-V6|xfMI}Jn4jSl7NG6Q3=2n^(TS`Vv)<>if0h&(K%z_(h zxXtO?6hg6HONXcO>Mx^B*EvB!U#%Y3;;OHR@2z-t5c%#Ioo~hEzEuI%x5z(UZ8Zes zcl>=Q;Gt{o>x%E!`~MBL6a(%xlAj_GFuiw7C-R5tc4a-5zXCsa1v13M zi@_tb0CGg&@yWHyTDq3=0jT>|7*1d$)6je?HmH<|YJ4c&HBm5Od08ca44!LNOn?J) zr;?px%gl_$dP4}bu!^+k7KE5@!qI?yQ!J7rtr~WFEuDH$)paao%>ChgT;w9KPZ?U8 zrsofbU-SylrhIqreBa+`VhfTG3<~JO=m@f~<4SX7ExfqP-<>I$Z6qFFqw{?HN&4LVgwo3P6>*EDFGoyTub^R$LpTs%~Ob|cbCTW4-krhK+OH&g0TeU!3^k7 zOl4QfK0jypR?^{CB55P}wN)F)QHC-w1yP9f+U~|{Mlfg41N2fbJ_b4=D6Zj<|53{E z)eYFaKZ|+X2Fy(s>5Tm|h@^n>jG9qUO6&H%PCERJ!h#puQsF2f9S1^!uQt zG?JzA*NwO29}?FS=JXh$rti^-EHiFYQ83Rvv(pzb4jJCamXx!UCky zqL#N$FDR%q^6RbvO5h_5J~Z%c4mVWr=XPV3u)pd52Zpp=ZO~nS5jOk0z6fFfN=cTh zsd`TzsLG|5?DC}J`1@51iZN5sok4UqohV5oPHT0%3n;8vrLhZBU^*PQpt6{>3SFuuul&1#W>>mb7O4_Q7_}wneRb$$?k&h_Lah=}C_HS8Xcy z9nzn^j$)CqCqMeO3~$YP*~r5pFe7(+r$$B(|EyvvwV$uG$C|fTj-ptYiNWK>zo`vd zMLxI< zM~MqVxbuZ=6H}@L-}zEp2NIe+Li$Hi)v@Z%LKrS)*kyk=utp1>#yaCrRJ^a`rp*tR zgu0(3kWnSeyut^1c7It4OSZ0MiHLG&7t>ZHGe z-qNsGErr#UTTEmM%B6-iCVV@!b}C4IMqlf))sI!)LxaodGIIC5 zr`rO!DF(Y$iw2aaJ_Q&HYi=Kji^qi)02y%9k!s6b;QR`6_^Y21G^&Z z2=2_Wlui$rVNDBDAr*9}eN1&-<~`VzrDSv3D}Sv6`ZEYJl2!-F-fi8l@5gB@oN6!? z`Y8>)0MORDQ_1nTuCZ+WOs~@jD9HctfRm-i56`_M3AVqulka;1Wb~-id-=P^fmovX zbH?ow>j$i53;Nd)vdrc2~2!>bM?G~hidc%wse zJiM5|AQOZS?hJrOJ}C{=t}QgGKDwd$>TWQ%TB4(F$dYpa_7%5H8AVpl2a@ZH(a|yC z3bn(9MbC6kII`PwnzUK^GxBGN(B3K{1219dLFv-a{Cz6#wQXAo#e}wP(PCbVv}tGT zB6n>q$ip7&Nsrhok42v8eUay*IFN9_Gb<@m*Ib@I47xB$4*~}&WD5=x7sCD|!Mvw{ z=Z-n7*pe8oofPjJ4~8=74GCvcX2yJE-lG3O*}S0qEzE_aBmnE3XFYepUViC$)J4kM z&mEs|atsIH$LS+PbId*HjLjz~DCgZ&m%fvmfDguexj?6Xe>X~Gj+^eo$*gfF03+H7s({qby&OS@AC)~z+OPUH(BiJMt8U* zNrinnM+ISGJ!H`PGo5+?=39#S+N&7SqnvtClCp|S^Wbb{<&OY6bG@^Wda*r?0hf{P zJI^s^E29vs2;v_Iy$g^BHYT{;Y6H{APT%r{Z&C!82(lqU5g8)mS~T=&|HkdB6#*>f z8zw#StO&Dqjluy({rB2kKAgX@lZZr~c^B$Mh#{gVE>Ih)TT8urIi~Ojoh{O%gpHuB z<$x-8>+J{N1IcPtAc@AlKKamFkZX<2YN`e~eGxHfj`;h8`R?n8943?Eo7bRhOQs5@ z;{&zQX@Gv^Fr5u zZZ7)LuYDf%K7fkj#@8ymDStq10&Tj{%COhzt#w#*SV!r2B3fyhfQ_yE!dFB?=rpo% z*7Gek7lx{9bHXLOd6+5$EctYD*JV~@0}h}gXEK*xn0=QbG{=%qKSNJC=aFOXmQ&H# zbm#E?2sD8)<5SaSZlDQ0LkDV6r0yRYYLu+*ejXv)tL#d6+0(8!(91WLWv*BH!0##Y z+n|@Ln%qK$2qB)yMC5h3r3TBA>7-ad4w?0P3ndttD377R8Ut+8)-m>iLw$L-KX`@YCI4g|v2G&I%HuD;M$%`Yt7;1!e znDoyq)@Xf#sRqN9YeS!oF1NJfJ>8toscQXIBcX=>sT`@94|o4~LU(YJk-sptEmNVB ze#&;VCKsk1ocgDIN9!|V?x&3-qZYjjc@@Kv4H;Z0B4rbSh3az$Y{yLRLG^7kisdJ~BZLE#+F3z5Xh=dACB>^k_w3@2Wxl{&Q13&bmOqJF-3(S#e~e zHJo%-R1o~%dW*o+wp|0J#|RIOiOxhU7sO58vmoMS$KmVR0uq9sKwWc0kG-+{LA@_x z^dcj_>C8`K4#Ipal$PN4_U{`42h1;_j)i`fniG>arp2;Dp*`2Kb4~Ugp4d?d|tb2N3_yteD z(J1W_MTWYL_Q$_<3DPk2v%yEn-yofRRqgaElw0cXrabHH_w|k>+Cb0H>>SjYguEG&9 zd(1rH+l5~o@)*)7n*<1%n!o@3fA0*~A}pWGWyso0ip83q>V(u-`btAars^S;i1Vnt zTM!A6H%oz4-8!AUK)j^2AKrv}`sDA;^xQ^d(bS>#hs-#>$$dCrnqwcS$F7_77*DNL zOqV@mBFW;qk-m*pUIG$g_TI?_rGkN zRSKBboyM=B0x-q-U|I~aJUo;2v9ZlF31h|f4A{PPuAKQNRKtPmD%hvs2n$WB-4P7! zC>3wg&WEMnSpQR>iF6@@!H=D5m77z>l~|Wd7=^|1B*6L5aCrUsRo=UHd9hnSNIu>YI^}mXnix zr=m%vhzxU+PbG;=8Qm=;MYus^(ns0)3MrZXd1{o2{@ql0>*>fUtvANM_2x#<^f8;i zHktOP=I&!AQg)R!9!>TP&8Gf+I91=rLxt^nd01CaAv)N&Obt60)Y`1djZ=M<(-0Y6 zrqgie^6L=3Pe_yXi?S!IxPdF^>2E`_>><6ToGQ9?3BbolGR@ur$1S)N2QDqNxlN5_BjOixa<2N&qA@b06P~w5=i@F zgr`}a^^4NK8t<>R=k1_PU`^!L5vcKl6>eL2(qb=}i6mKJL_o}J$VBACWOekq36o(C zy-AvJ=!Z?!uIrHZRJY^Mi<1eQa?b8P0f(JS3O zchFw{lv2CoXFwjZgcSD9L`3>RsdBSUVoaUIQCTNt|M}JoJ`|~y%fmo*D?mnkzB46+ zGt1K5NkVVq^?+ShX84-dYFgQysqxbUfud!euZ1f&?;@ zP&W%A0z7(<(oE#&xrE~Ir<%9- z>26_D8<(Ec4(S3rMt>S|c?AE58z{*VUbG9$K)dB0kmm!TL^xWU?eD_x8*9p;Z;?9_@3?{K}{ zq@9>O@$2^|cH)13>mfB)$jIr($P6-=F= z#;(w@$SXzjAO0p1r$%BDU{!h4d-?KImVVW%B4sEAkD9}ZtjY~OdgzsJR~dA+pmT8( zoWHFn*?iqgMr$ls5fW|mg`ZX4N%7ivP?`&i>2WCwL91~LM>i5V>xaaYWuNiF_?rvMX z#gS`dbQXoa0UF{!IMuU0ksq@j{ShaL)vB*7ESzxYS(hEXd#t8wP+HKY(`MXoxqath zdAq`G_7k##&t#~uS0o6Fjy!4;XPzdmEje)B#0if|&fzHxFA(6b63@*ra3vbO6Q&o+ z8o7+j-G&y2PjKcxe5kUb7Je*wBvmEddUl~cGliB4a{hLmg~takSuu5kS2+_W2fl)J zSl8c^KI|>LpS7E$^;HjO7<86$Ulsbo&JLZdpBT#~|FQ@N{epa_E)uRdECj7p2)!rh z;|<;^$6SDnn*Frz^5B~?)O?lrHvez9ZBZe+F`s_T#{t>~ODm_|8a`KfMuNx`KVozv z{J7!7yV}pZo$QY7FRE5K;=bRgCk++rv5j8LBK-)sjWSz}oG^hU7BAZ0lnu!- z))N}N@~3^K(>%M^iyW)tX|3@n|EQ-#DO$ciEx4w_- ze4WK>*_K&q=(VR$*-rSiP9Ay9wq~G#njJh{9_iz2T-(N9NqLjT4;*vm*{QG)FuO0m z5ruio6c}DopUtU%4>(<5RmHonT^~;PdhPKw258{<0z<~E zuR!kNL{Z5{Gur1+vmp(+^40M_fe20lZ!xjZEjKoCA=k*XOniIum75pT_)o{!RoJb5 z^Z32wY=Lt_K-mw=a7I_Ak}rNIR7U1iPE~YJ$DEX-I z^NE(75}eV-*Vi<@IkIQQ7Xg3X`3ha(Dh03S!-GGlx;9`;7y`Y)qyF>fT-v|+f{*_A zbS+7SsE&<4K^#BW<8I8<{0enoI&4$UpC4ij-9hFcSW;!sGKkT8AJQ=F9ky@>UWl zwPL{3;raX5%7kPdJdmz>T*w>f{c(f4Tk|x=prXK1WMs;ik>WWSQK!xFg{gP`xa!+u zfW9*izP$m?a@vhL$g}Sas+EmgY?{n^e`o62C7Ant0`j0>)=Fb2ZS|4H4yn~{wZQ

-dSF1T+tW$HC=t1ku@el)%jT5 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 Mk%eK2!Ik^}11(xZDF6Tf literal 0 HcmV?d00001 diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..63810e6 --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,134 @@ + + + MainWindow + + + + 0 + 0 + 708 + 652 + + + + MainWindow + + + + + + 0 + 0 + 708 + 22 + + + + + File + + + + + + + + + + + + + + + + + + Edit + + + + + View + + + + + Tools + + + + + Options + + + + + Help + + + + + + + + + + + + TopToolBarArea + + + false + + + + + + Open Image... + + + + + Save Log... + + + + + Reprocess File + + + + + Batch Process... + + + + + Offset + + + + + Print... + + + + + Print Preview + + + + + Print Setup... + + + + + Exit + + + + + + + diff --git a/JPEGsnoop.sln b/msvc/JPEGsnoop.sln similarity index 100% rename from JPEGsnoop.sln rename to msvc/JPEGsnoop.sln diff --git a/JPEGsnoop.vcproj b/msvc/JPEGsnoop.vcproj similarity index 100% rename from JPEGsnoop.vcproj rename to msvc/JPEGsnoop.vcproj diff --git a/JPEGsnoop.vcxproj b/msvc/JPEGsnoop.vcxproj similarity index 100% rename from JPEGsnoop.vcxproj rename to msvc/JPEGsnoop.vcxproj diff --git a/JPEGsnoop.vcxproj.filters b/msvc/JPEGsnoop.vcxproj.filters similarity index 100% rename from JPEGsnoop.vcxproj.filters rename to msvc/JPEGsnoop.vcxproj.filters diff --git a/source/DbSigs.cpp b/source/DbSigs.cpp index e6105e2..afc6f27 100644 --- a/source/DbSigs.cpp +++ b/source/DbSigs.cpp @@ -1,1022 +1,1050 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "stdafx.h" -#include "DbSigs.h" -#include "General.h" - -#include "snoop.h" - -#include "Signatures.inl" - -#define MAX_BUF_SET_FILE 131072 - - -// TODO: -// - Convert m_sSigListExtra[] to use CObArray instead of managing it -// directly. Otherwise we are inefficient with memory and could potentially -// not allocate enough space. - - -// Initialize the signature database array sizes -// -// PRE: -// - m_sSigList[] -// - m_sExcMmNoMkrList[] -// - m_sExcMmIsEditList[] -// - m_sSwIjgList[] -// - m_sXComSwList[] -// -// POST: -// - m_nSigListNum -// - m_nSigListExtraNum -// - m_nExcMmNoMkrListNum -// - m_nExcMmIsEditListNum -// - m_nSwIjgListNum -// - m_nXcomSwListNum -// - m_strDbDir -// -CDbSigs::CDbSigs() -{ - // Count the built-in database - bool bDone; - - m_bFirstRun = false; - - bDone = false; - m_nSigListNum = 0; - while (!bDone) - { - if (!_tcscmp(m_sSigList[m_nSigListNum].strXMake,_T("*"))) - bDone = true; - else - m_nSigListNum++; - } - - // Count number of exceptions in Signatures.inl - bDone = false; - m_nExcMmNoMkrListNum = 0; - while (!bDone) - { - if (!_tcscmp(m_sExcMmNoMkrList[m_nExcMmNoMkrListNum].strXMake,_T("*"))) - bDone = true; - else - m_nExcMmNoMkrListNum++; - } - - bDone = false; - m_nExcMmIsEditListNum = 0; - while (!bDone) - { - if (!_tcscmp(m_sExcMmIsEditList[m_nExcMmIsEditListNum].strXMake,_T("*"))) - bDone = true; - else - m_nExcMmIsEditListNum++; - } - - - bDone = false; - m_nSwIjgListNum = 0; - while (!bDone) { - if (!_tcscmp(m_sSwIjgList[m_nSwIjgListNum],_T("*"))) - bDone = true; - else - m_nSwIjgListNum++; - } - - bDone = false; - m_nXcomSwListNum = 0; - while (!bDone) { - if (!_tcscmp(m_sXComSwList[m_nXcomSwListNum],_T("*"))) - bDone = true; - else - m_nXcomSwListNum++; - } - - - // Reset extra database - m_nSigListExtraNum = 0; - - // Default to user database dir not set yet - // This will cause a fail if database load/store - // functions are called before SetDbDir() - m_strDbDir = _T(""); - -} - -CDbSigs::~CDbSigs() -{ -} - -// Is this the first time running the application? -// If so, we skip certain warning messages (such as lack of existing user DB file) -void CDbSigs::SetFirstRun(bool bFirstRun) -{ - m_bFirstRun = bFirstRun; -} - -unsigned CDbSigs::GetNumSigsInternal() -{ - return m_nSigListNum; -} - -unsigned CDbSigs::GetNumSigsExtra() -{ - return m_nSigListExtraNum; -} - - -// Read an unsigned integer (4B) from the buffer -bool CDbSigs::BufReadNum(PBYTE pBuf,unsigned &nOut,unsigned nMaxBytes,unsigned &nOffsetBytes) -{ - nMaxBytes; // Unreferenced param - - ASSERT(pBuf); - // TODO: check for buffer bounds - nOut = (unsigned)pBuf[nOffsetBytes]; - nOffsetBytes += sizeof(unsigned); - return true; -} - -// Write an unsigned integer (4B) to the buffer -bool CDbSigs::BufWriteNum(PBYTE pBuf,unsigned nIn,unsigned nMaxBytes,unsigned &nOffsetBytes) -{ - nMaxBytes; // Unreferenced param - - ASSERT(pBuf); - // TODO: check for buffer bounds - PBYTE pBufBase; - unsigned* pBufInt; - pBufBase = &pBuf[nOffsetBytes]; - pBufInt = (unsigned*)pBufBase; - pBufInt[0] = nIn; - nOffsetBytes += sizeof(unsigned); - return true; -} - - -// Attempt to read a line from the buffer -// This is a replacement for CStdioFile::ReadLine() -// Both 16-bit unicode and 8-bit SBCS encoding modes are supported (via bUni) -// Offset parameter is incremented accordingly -// Supports both newline and NULL for string termination -bool CDbSigs::BufReadStr(PBYTE pBuf,CString &strOut,unsigned nMaxBytes,bool bUni,unsigned &nOffsetBytes) -{ - ASSERT(pBuf); - CString strOutTmp; - bool bDone; - - char chAsc; - wchar_t chUni; - unsigned nCharSz = ((bUni)?sizeof(wchar_t):sizeof(char)); - - bDone = false; - strOut = _T(""); - // Ensure we don't overrun the buffer by calculating the last - // byte index required for each iteration. - for (unsigned nInd=nOffsetBytes;(!bDone)&&(nInd+nCharSz-1GetErrorMessage(msg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - - // To avoid any user confusion, we disable this warning message if this - // is the first time the program has been run (when we would expect that the user - // database is not present). After first run, the user database will have been - // created. - // Take from SnoopConfig.bEulaAccepted - if (!m_bFirstRun) { - strError.Format(_T("Couldn't find User Signature Database\n\n[%s]\n\nCreating default database"),(LPCTSTR)msg); - OutputDebugString(strError); - AfxMessageBox(strError); - } - pInFile = NULL; - - // Now create default database file in current DB location - DatabaseExtraStore(); - - return; - } - - // Allocate the input buffer - pBuf = new BYTE [MAX_BUF_SET_FILE]; - ASSERT(pBuf); - - // Load the buffer - nBufLenBytes = pInFile->Read(pBuf,MAX_BUF_SET_FILE); - - ASSERT(nBufLenBytes>0); - // TODO: Error check for config file longer than max buffer! - ASSERT(nBufLenBytesClose(); - delete pInFile; - pInFile = NULL; - } - // Copy old config file - TCHAR szFilePathNameBak[200]; - _stprintf_s(szFilePathNameBak,_T("%s\\%s.bak"),(LPCTSTR)m_strDbDir,DAT_FILE); - CopyFile(szFilePathName,szFilePathNameBak,false); - // Now rewrite file in latest version - DatabaseExtraStore(); - // Notify user - strTmp.Format(_T("Created default User Signature Database. Backup of old DB in [%s]"),szFilePathNameBak); - AfxMessageBox(strTmp); - return; - } - - m_nSigListExtraNum = 0; - - // Version - bRet = BufReadStr(pBuf,strVer,nBufLenBytes,bFileModeUni,nBufOffset); - bValid = false; - if (strVer == _T("00")) { bValid = false; } - if (strVer == _T("01")) { bValid = true; } - if (strVer == _T("02")) { bValid = true; } - if (strVer == _T("03")) { bValid = true; } - - // Should consider trimming down local database if same entry - // exists in built-in database (for example, user starts running - // new version of tool). - - while (!bDone && bValid) { - - // Read section header - - bRet = BufReadStr(pBuf,strSec,nBufLenBytes,bFileModeUni,nBufOffset); - - if (strSec == _T("*DB*")) { - // Read DB count - bRet = BufReadNum(pBuf,nNumLoad,nBufLenBytes,nBufOffset); - - // For each entry that we read, we should double-check to see - // if we already have it in the built-in DB. If we do, then - // don't add it to the runtime DB, and mark the local DB as - // needing trimming. If so, rewrite the DB. - - for (unsigned ind=0;ind(_tstoi(strTmp)); - - bRet = BufReadStr(pBuf,sDbLocalEntry.strUmQual,nBufLenBytes,bFileModeUni,nBufOffset); - bRet = BufReadStr(pBuf,sDbLocalEntry.strCSig,nBufLenBytes,bFileModeUni,nBufOffset); - - // In older version of DB, these entries won't exist - bRet = BufReadStr(pBuf,sDbLocalEntry.strXSubsamp,nBufLenBytes,bFileModeUni,nBufOffset); - bRet = BufReadStr(pBuf,sDbLocalEntry.strMSwTrim,nBufLenBytes,bFileModeUni,nBufOffset); - bRet = BufReadStr(pBuf,sDbLocalEntry.strMSwDisp,nBufLenBytes,bFileModeUni,nBufOffset); - - } else if ( (strVer == _T("02")) || (strVer == _T("03")) ) { - - // For version 02 or 03: - // NOTE: Difference between 02 and 03: - // - 02 : SBCS format - // - 03 : Unicode format - bRet = BufReadStr(pBuf,sDbLocalEntry.strXMake,nBufLenBytes,bFileModeUni,nBufOffset); - bRet = BufReadStr(pBuf,sDbLocalEntry.strXModel,nBufLenBytes,bFileModeUni,nBufOffset); - - strTmp = _T(""); - bRet = BufReadStr(pBuf,strTmp,nBufLenBytes,bFileModeUni,nBufOffset); - sDbLocalEntry.eEditor = static_cast(_tstoi(strTmp)); - - bRet = BufReadStr(pBuf,sDbLocalEntry.strUmQual,nBufLenBytes,bFileModeUni,nBufOffset); - bRet = BufReadStr(pBuf,sDbLocalEntry.strCSig,nBufLenBytes,bFileModeUni,nBufOffset); - bRet = BufReadStr(pBuf,sDbLocalEntry.strCSigRot,nBufLenBytes,bFileModeUni,nBufOffset); - - - // In older version of DB, these entries won't exist - bRet = BufReadStr(pBuf,sDbLocalEntry.strXSubsamp,nBufLenBytes,bFileModeUni,nBufOffset); - bRet = BufReadStr(pBuf,sDbLocalEntry.strMSwTrim,nBufLenBytes,bFileModeUni,nBufOffset); - bRet = BufReadStr(pBuf,sDbLocalEntry.strMSwDisp,nBufLenBytes,bFileModeUni,nBufOffset); - } - - // ------------------------------------------------------- - - - // Does the entry already exist in the internal DB? - bDbLocalEntryFound = SearchSignatureExactInternal(sDbLocalEntry.strXMake,sDbLocalEntry.strXModel,sDbLocalEntry.strCSig); - - if (!bDbLocalEntryFound) { - // Add it! - m_sSigListExtra[m_nSigListExtraNum].bValid = true; - m_sSigListExtra[m_nSigListExtraNum].strXMake = sDbLocalEntry.strXMake; - m_sSigListExtra[m_nSigListExtraNum].strXModel = sDbLocalEntry.strXModel; - m_sSigListExtra[m_nSigListExtraNum].eEditor = sDbLocalEntry.eEditor; - m_sSigListExtra[m_nSigListExtraNum].strUmQual = sDbLocalEntry.strUmQual; - m_sSigListExtra[m_nSigListExtraNum].strCSig = sDbLocalEntry.strCSig; - m_sSigListExtra[m_nSigListExtraNum].strCSigRot = sDbLocalEntry.strCSigRot; - - m_sSigListExtra[m_nSigListExtraNum].strXSubsamp = sDbLocalEntry.strXSubsamp; - m_sSigListExtra[m_nSigListExtraNum].strMSwTrim = sDbLocalEntry.strMSwTrim; - m_sSigListExtra[m_nSigListExtraNum].strMSwDisp = sDbLocalEntry.strMSwDisp; - m_nSigListExtraNum++; - } else { - bDbLocalTrimmed = true; - } - - } - } else if (strSec == _T("*Z*")) { - bDone = true; - } else { - bValid = false; - } // strSec - - } // while - - - - - // ---------------------- - - if (pInFile) { - pInFile->Close(); - delete pInFile; - pInFile = NULL; - } - - if (pBuf) { - delete [] pBuf; - pBuf = NULL; - } - - // If we did make changes to the database (trim), then rewrite it! - // Ensure that we have closed the file above before we rewrite it - // otherwise we could end up with a sharing violation - if (bDbLocalTrimmed) { - DatabaseExtraStore(); - } - - // Now is this an old config file version? If so, - // create a backup and then rewrite the new version - if (bValid) { - if (strVer != DB_VER_STR) { - // Copy old config file - TCHAR szFilePathNameBak[200]; - _stprintf_s(szFilePathNameBak,_T("%s\\%s.bak"),(LPCTSTR)m_strDbDir,DAT_FILE); - CopyFile(szFilePathName,szFilePathNameBak,false); - // Now rewrite file in latest version - DatabaseExtraStore(); - // Notify user - strError.Format(_T("Upgraded User Signature Database. Backup in:\n%s"),szFilePathNameBak); - AfxMessageBox(strError); - } - } -} - -void CDbSigs::DatabaseExtraClean() -{ - m_nSigListExtraNum = 0; - DatabaseExtraStore(); -} - -unsigned CDbSigs::DatabaseExtraGetNum() -{ - return m_nSigListExtraNum; -} - -CompSig CDbSigs::DatabaseExtraGet(unsigned nInd) -{ - ASSERT(nIndGetErrorMessage(msg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - strError.Format(_T("ERROR: Couldn't open file: [%s]"),(LPCTSTR)msg); - OutputDebugString(strError); - AfxMessageBox(strError); - pOutFile = NULL; - return; - } - - // Allocate the output buffer - pBuf = new BYTE [MAX_BUF_SET_FILE]; - ASSERT(pBuf); - - nBufOffset = 0; - - CString strLine; - CString strParam; - CString strVal; - //bool bErr = false; - //bool bDone = false; - BOOL bRet; - - unsigned nMaxBufBytes = MAX_BUF_SET_FILE; - - bRet = BufWriteStr(pBuf,_T("JPEGsnoop"),nMaxBufBytes,bModeUni,nBufOffset); - bRet = BufWriteStr(pBuf,_T(DB_VER_STR),nMaxBufBytes,bModeUni,nBufOffset); - bRet = BufWriteStr(pBuf,_T("*DB*"),nMaxBufBytes,bModeUni,nBufOffset); - - // Determine how many entries will remain (after removing marked - // deleted entries - unsigned nNewExtraNum = m_nSigListExtraNum; - for (unsigned nInd=0;nIndWrite(pBuf,nBufOffset); - - pOutFile->Close(); - delete pOutFile; - pOutFile = NULL; - } - - if (pBuf) { - delete [] pBuf; - pBuf = NULL; - } - -} - -void CDbSigs::DatabaseExtraAdd(CString strExifMake,CString strExifModel, - CString strQual,CString strSig,CString strSigRot,CString strCss, - teSource eUserSource,CString strUserSoftware) -{ - ASSERT(m_nSigListExtraNum < DBEX_ENTRIES_MAX); - if (m_nSigListExtraNum >= DBEX_ENTRIES_MAX) { - CString strTmp; - strTmp.Format(_T("ERROR: Can only store maximum of %u extra signatures in local DB"),DBEX_ENTRIES_MAX); - AfxMessageBox(strTmp); - return; - } - - // Now append it to the local database and resave - m_sSigListExtra[m_nSigListExtraNum].strXMake = strExifMake; - m_sSigListExtra[m_nSigListExtraNum].strXModel = strExifModel; - m_sSigListExtra[m_nSigListExtraNum].strUmQual = strQual; - m_sSigListExtra[m_nSigListExtraNum].strCSig = strSig; - m_sSigListExtra[m_nSigListExtraNum].strCSigRot = strSigRot; - m_sSigListExtra[m_nSigListExtraNum].strXSubsamp = strCss; - - if (eUserSource == ENUM_SOURCE_CAM) { // digicam - m_sSigListExtra[m_nSigListExtraNum].eEditor = ENUM_EDITOR_CAM; - m_sSigListExtra[m_nSigListExtraNum].strMSwTrim = _T(""); - m_sSigListExtra[m_nSigListExtraNum].strMSwDisp = _T(""); - } else if (eUserSource == ENUM_SOURCE_SW) { // software - m_sSigListExtra[m_nSigListExtraNum].eEditor = ENUM_EDITOR_SW; - m_sSigListExtra[m_nSigListExtraNum].strMSwTrim = _T(""); - m_sSigListExtra[m_nSigListExtraNum].strMSwDisp = strUserSoftware; // Not quite right perfect - m_sSigListExtra[m_nSigListExtraNum].strXMake = _T(""); - m_sSigListExtra[m_nSigListExtraNum].strXModel = _T(""); - } else { // user didn't know - m_sSigListExtra[m_nSigListExtraNum].eEditor = ENUM_EDITOR_UNSURE; - m_sSigListExtra[m_nSigListExtraNum].strMSwTrim = _T(""); - m_sSigListExtra[m_nSigListExtraNum].strMSwDisp = strUserSoftware; // Not quite right perfect - } - - m_nSigListExtraNum++; - - // Now resave the database - DatabaseExtraStore(); -} - -// TODO: Should we include editors in this search? -bool CDbSigs::SearchSignatureExactInternal(CString strMake, CString strModel, CString strSig) -{ - bool bFoundExact = false; - bool bDone = false; - unsigned nInd = 0; - while (!bDone) { - if (nInd >= m_nSigListNum) { - bDone = true; - } else { - - if ( (m_sSigList[nInd].strXMake == strMake) && - (m_sSigList[nInd].strXModel == strModel) && - ((m_sSigList[nInd].strCSig == strSig) || (m_sSigList[nInd].strCSigRot == strSig)) ) - { - bFoundExact = true; - bDone = true; - } - nInd++; - } - } - - return bFoundExact; -} - -bool CDbSigs::SearchCom(CString strCom) -{ - bool bFound = false; - bool bDone = false; - unsigned nInd = 0; - if (strCom.GetLength() == 0) { - bDone = true; - } - while (!bDone) { - if (nInd >= m_nXcomSwListNum) { - bDone = true; - } else { - if (strCom.Find(m_sXComSwList[nInd]) != -1) { - bFound = true; - bDone = true; - } - nInd++; - } - } - return bFound; -} - -// Returns total of built-in plus local DB -unsigned CDbSigs::GetDBNumEntries() -{ - return (m_nSigListNum + m_nSigListExtraNum); -} - -// Returns total of built-in plus local DB -unsigned CDbSigs::IsDBEntryUser(unsigned nInd) -{ - if (nInd < m_nSigListNum) { - return false; - } else { - return true; - } -} - -// Return a ptr to the struct containing the indexed entry -bool CDbSigs::GetDBEntry(unsigned nInd,CompSig* pEntry) -{ - unsigned nIndOffset; - unsigned nIndMax = GetDBNumEntries(); - ASSERT(pEntry); - ASSERT(nIndeEditor = m_sSigList[nInd].eEditor; - pEntry->strXMake = m_sSigList[nInd].strXMake; - pEntry->strXModel = m_sSigList[nInd].strXModel; - pEntry->strUmQual = m_sSigList[nInd].strUmQual; - pEntry->strCSig = m_sSigList[nInd].strCSig; - pEntry->strCSigRot = m_sSigList[nInd].strCSigRot; - pEntry->strXSubsamp = m_sSigList[nInd].strXSubsamp; - pEntry->strMSwTrim = m_sSigList[nInd].strMSwTrim; - pEntry->strMSwDisp = m_sSigList[nInd].strMSwDisp; - return true; - } else { - nIndOffset = nInd-m_nSigListNum; - pEntry->eEditor = m_sSigListExtra[nIndOffset].eEditor; - pEntry->strXMake = m_sSigListExtra[nIndOffset].strXMake; - pEntry->strXModel = m_sSigListExtra[nIndOffset].strXModel; - pEntry->strUmQual = m_sSigListExtra[nIndOffset].strUmQual; - pEntry->strCSig = m_sSigListExtra[nIndOffset].strCSig; - pEntry->strCSigRot = m_sSigListExtra[nIndOffset].strCSigRot; - pEntry->strXSubsamp = m_sSigListExtra[nIndOffset].strXSubsamp; - pEntry->strMSwTrim = m_sSigListExtra[nIndOffset].strMSwTrim; - pEntry->strMSwDisp = m_sSigListExtra[nIndOffset].strMSwDisp; - return true; - } -} - -void CDbSigs::SetEntryValid(unsigned nInd,bool bValid) -{ - // TODO: Bounds check - ASSERT(nInd < m_nSigListExtraNum); - m_sSigListExtra[nInd].bValid = bValid; -} - - -unsigned CDbSigs::GetIjgNum() -{ - return m_nSwIjgListNum; -} - -LPTSTR CDbSigs::GetIjgEntry(unsigned nInd) -{ - return m_sSwIjgList[nInd]; -} - -// Update the directory used for user database -void CDbSigs::SetDbDir(CString strDbDir) -{ - m_strDbDir = strDbDir; -} - - -// Search exceptions for Make/Model in list of ones that don't have Makernotes -bool CDbSigs::LookupExcMmNoMkr(CString strMake,CString strModel) -{ - bool bFound = false; - bool bDone = false; - unsigned nInd = 0; - if (strMake.GetLength() == 0) { - bDone = true; - } - while (!bDone) { - if (nInd >= m_nExcMmNoMkrListNum) { - bDone = true; - } else { - // Perform exact match on Make, case sensitive - // Check Make field and possibly Model field (if non-empty) - if (_tcscmp(m_sExcMmNoMkrList[nInd].strXMake,strMake) != 0) { - // Make did not match - } else { - // Make matched, now check to see if we need - // to compare the Model string - if (_tcslen(m_sExcMmNoMkrList[nInd].strXModel) == 0) { - // No need to compare, we're bDone - bFound = true; - bDone = true; - } else { - // Need to check model as well - // Since we may like to do a substring match, support wildcards - - // FnInd position of "*" if it exists in DB entry - LPTSTR pWildcard; - unsigned nCompareLen; - pWildcard = _tcschr(m_sExcMmNoMkrList[nInd].strXModel,'*'); - if (pWildcard != NULL) { - // Wildcard present - nCompareLen = pWildcard - (m_sExcMmNoMkrList[nInd].strXModel); - } else { - // No wildcard, do full match - nCompareLen = _tcslen(m_sExcMmNoMkrList[nInd].strXModel); - } - - if (_tcsnccmp(m_sExcMmNoMkrList[nInd].strXModel,strModel,nCompareLen) != 0) { - // No match - } else { - // Matched as well, we're bDone - bFound = true; - bDone = true; - } - } - } - - nInd++; - } - } - - return bFound; -} - -// Search exceptions for Make/Model in list of ones that are always edited -bool CDbSigs::LookupExcMmIsEdit(CString strMake,CString strModel) -{ - bool bFound = false; - bool bDone = false; - unsigned nInd = 0; - if (strMake.GetLength() == 0) { - bDone = true; - } - while (!bDone) { - if (nInd >= m_nExcMmIsEditListNum) { - bDone = true; - } else { - // Perform exact match, case sensitive - // Check Make field and possibly Model field (if non-empty) - if (_tcscmp(m_sExcMmIsEditList[nInd].strXMake,strMake) != 0) { - // Make did not match - } else { - // Make matched, now check to see if we need - // to compare the Model string - if (_tcslen(m_sExcMmIsEditList[nInd].strXModel) == 0) { - // No need to compare, we're bDone - bFound = true; - bDone = true; - } else { - // Need to check model as well - if (_tcscmp(m_sExcMmIsEditList[nInd].strXModel,strModel) != 0) { - // No match - } else { - // Matched as well, we're bDone - bFound = true; - bDone = true; - } - } - } - - nInd++; - } - } - - return bFound; -} - - -// ----------------------------------------------------------------------- -// Sample string indicator database -// ----------------------------------------------------------------------- - - -// Sample list of software programs that also use the IJG encoder -LPTSTR CDbSigs::m_sSwIjgList[] = { - _T("GIMP"), - _T("IrfanView"), - _T("idImager"), - _T("FastStone Image Viewer"), - _T("NeatImage"), - _T("Paint.NET"), - _T("Photomatix"), - _T("XnView"), - _T("*"), -}; - - -// Sample list of software programs marked by EXIF.COMMENT field -// -// NOTE: Have not included the following indicators as they -// also appear in some digicams in addition to software encoders. -// "LEAD Technologies" -// "U-Lead Systems" -// "Intel(R) JPEG Library" (unsure if ever in hardware) -// -LPTSTR CDbSigs::m_sXComSwList[] = { - _T("gd-jpeg"), - _T("Photoshop"), - _T("ACD Systems"), - _T("AppleMark"), - _T("PICResize"), - _T("NeatImage"), - _T("*"), -}; - - -// Software signature list (m_sSigList) is located in "Signatures.inl" - +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include + +#include "DbSigs.h" +#include "General.h" + +#include "snoop.h" + +#include "Signatures.inl" + +#define MAX_BUF_SET_FILE 131072 + + +// TODO: +// - Convert m_sSigListExtra[] to use CObArray instead of managing it +// directly. Otherwise we are inefficient with memory and could potentially +// not allocate enough space. + + +// Initialize the signature database array sizes +// +// PRE: +// - m_sSigList[] +// - m_sExcMmNoMkrList[] +// - m_sExcMmIsEditList[] +// - m_sSwIjgList[] +// - m_sXComSwList[] +// +// POST: +// - m_nSigListNum +// - m_nSigListExtraNum +// - m_nExcMmNoMkrListNum +// - m_nExcMmIsEditListNum +// - m_nSwIjgListNum +// - m_nXcomSwListNum +// - m_strDbDir +// +CDbSigs::CDbSigs() +{ + // Count the built-in database + bool bDone; + + m_bFirstRun = false; + + bDone = false; + m_nSigListNum = 0; + + while (!bDone) + { +// if (!_tcscmp(m_sSigList[m_nSigListNum].strXMake,"*")) + if (m_sSigList[m_nSigListNum].strXMake == "*") + bDone = true; + else + m_nSigListNum++; + } + + // Count number of exceptions in Signatures.inl + bDone = false; + m_nExcMmNoMkrListNum = 0; + + while (!bDone) + { +// if (!_tcscmp(m_sExcMmNoMkrList[m_nExcMmNoMkrListNum].strXMake,"*")) + if (m_sExcMmNoMkrList[m_nExcMmNoMkrListNum].strXMake == "*") + bDone = true; + else + m_nExcMmNoMkrListNum++; + } + + bDone = false; + m_nExcMmIsEditListNum = 0; + + while (!bDone) + { +// if (!_tcscmp(m_sExcMmIsEditList[m_nExcMmIsEditListNum].strXMake,"*")) + if (m_sExcMmIsEditList[m_nExcMmIsEditListNum].strXMake == "*") + bDone = true; + else + m_nExcMmIsEditListNum++; + } + + + bDone = false; + m_nSwIjgListNum = 0; + + // Sample list of software programs that also use the IJG encoder + + m_sSwIjgList + << "GIMP" + << "IrfanView" + << "idImager" + << "FastStone Image Viewer" + << "NeatImage" + << "Paint.NET" + << "Photomatix" + << "XnView"; + + m_nSwIjgListNum = m_sSwIjgList.count(); + + + bDone = false; + m_nXcomSwListNum = 0; + + // Sample list of software programs marked by EXIF.COMMENT field + // + // NOTE: Have not included the following indicators as they also appear in some digicams in addition to software encoders. + // "LEAD Technologies" + // "U-Lead Systems" + // "Intel(R) JPEG Library" (unsure if ever in hardware) + // + + m_sXComSwList + << "gd-jpeg" + << "Photoshop" + << "ACD Systems" + << "AppleMark" + << "PICResize" + << "NeatImage"; + + m_nXcomSwListNum = m_sXComSwList.count(); + + // Reset extra database + m_nSigListExtraNum = 0; + + // Default to user database dir not set yet + // This will cause a fail if database load/store + // functions are called before SetDbDir() + m_strDbDir = ""; +} + +CDbSigs::~CDbSigs() +{ +} + +// Is this the first time running the application? +// If so, we skip certain warning messages (such as lack of existing user DB file) +void CDbSigs::SetFirstRun(bool bFirstRun) +{ + m_bFirstRun = bFirstRun; +} + +unsigned CDbSigs::GetNumSigsInternal() +{ + return m_nSigListNum; +} + +unsigned CDbSigs::GetNumSigsExtra() +{ + return m_nSigListExtraNum; +} + + +// Read an unsigned integer (4B) from the buffer +bool CDbSigs::BufReadNum(uint8_t *pBuf,unsigned &nOut,unsigned,unsigned &nOffsetBytes) +{ + Q_ASSERT(pBuf); + // TODO: check for buffer bounds + nOut = (unsigned)pBuf[nOffsetBytes]; + nOffsetBytes += sizeof(unsigned); + return true; +} + +// Write an unsigned integer (4B) to the buffer +bool CDbSigs::BufWriteNum(uint8_t *pBuf,unsigned nIn,unsigned,unsigned &nOffsetBytes) +{ + Q_ASSERT(pBuf); + // TODO: check for buffer bounds + uint8_t * pBufBase; + unsigned* pBufInt; + pBufBase = &pBuf[nOffsetBytes]; + pBufInt = (unsigned*)pBufBase; + pBufInt[0] = nIn; + nOffsetBytes += sizeof(unsigned); + return true; +} + +// Attempt to read a line from the buffer +// This is a replacement for CStdioFile::ReadLine() +// Both 16-bit unicode and 8-bit SBCS encoding modes are supported (via bUni) +// Offset parameter is incremented accordingly +// Supports both newline and NULL for string termination +bool CDbSigs::BufReadStr(uint8_t *pBuf,QString &strOut,unsigned nMaxBytes,bool bUni,unsigned &nOffsetBytes) +{ + Q_ASSERT(pBuf); + QString strOutTmp; + bool bDone; + + char chAsc; + wchar_t chUni; + unsigned nCharSz = ((bUni)?sizeof(wchar_t):sizeof(char)); + + bDone = false; + strOut = ""; + + // Ensure we don't overrun the buffer by calculating the last byte index required for each iteration. + for (unsigned nInd=nOffsetBytes; (!bDone) && (nInd + nCharSz - 1 < nMaxBytes); nInd += nCharSz) + { + if (bUni) + { + chUni = pBuf[nInd]; + + if ( (chUni != '\n') && (chUni != 0) ) + { + strOut += chUni; + } + else + { + bDone = true; + nOffsetBytes = nInd+nCharSz; + } + } + else + { + chAsc = pBuf[nInd]; + + if ( (chAsc != '\n') && (chAsc != 0) ) + { + strOut += chAsc; + } + else + { + bDone = true; + nOffsetBytes = nInd+nCharSz; + } + } + } + + if (!bDone) + { + nOffsetBytes = nMaxBytes; + // The input was not terminated, so we're still going to return what we got so far + return false; + } + + return true; +} + +// Return true if we managed to write entire string including terminator without overrunning nMaxBytes +bool CDbSigs::BufWriteStr(unsigned char *pBuf,QString strIn,unsigned nMaxBytes,bool bUni,unsigned &nOffsetBytes) +{ + Q_ASSERT(pBuf); + + bool bRet = false; + char chAsc; + wchar_t chUni; + unsigned nCharSz = ((bUni)?sizeof(wchar_t):sizeof(char)); + unsigned char *pBufBase; + wchar_t *pBufUni; + unsigned char *pBufAsc; + + pBufBase = pBuf + nOffsetBytes; + pBufUni = (wchar_t *)pBufBase; + pBufAsc = pBufBase; + + // FIXME: Comment out the following until a cross-platform solution can be written + /* + +#ifdef UNICODE + // Create non-Unicode version of string + // Ref: http://social.msdn.microsoft.com/Forums/vstudio/en-US/85f02321-de88-47d2-98c8-87daa839a98e/how-to-convert-cstring-to-const-char-?forum=vclanguage + // Added constant specifier + LPCSTR pszNonUnicode; + USES_CONVERSION; + // Not specifying code page explicitly but assume content + // should be ASCII. Default code page is probably Windows-1252. + pszNonUnicode = CW2A( strIn.LockBuffer( ) ); + strIn.UnlockBuffer( ); +#endif + + unsigned nStrLen; + unsigned nChInd; + nStrLen = strIn.size(); + + for (nChInd=0;(nChInd0); + // TODO: Error check for config file longer than max buffer! + Q_ASSERT(nBufLenBytes(_tstoi(strTmp)); + + bRet = BufReadStr(pBuf,sDbLocalEntry.strUmQual,nBufLenBytes,bFileModeUni,nBufOffset); + bRet = BufReadStr(pBuf,sDbLocalEntry.strCSig,nBufLenBytes,bFileModeUni,nBufOffset); + + // In older version of DB, these entries won't exist + bRet = BufReadStr(pBuf,sDbLocalEntry.strXSubsamp,nBufLenBytes,bFileModeUni,nBufOffset); + bRet = BufReadStr(pBuf,sDbLocalEntry.strMSwTrim,nBufLenBytes,bFileModeUni,nBufOffset); + bRet = BufReadStr(pBuf,sDbLocalEntry.strMSwDisp,nBufLenBytes,bFileModeUni,nBufOffset); + + } + else if ( (strVer == "02") || (strVer == "03") ) + { + // For version 02 or 03: + // NOTE: Difference between 02 and 03: + // - 02 : SBCS format + // - 03 : Unicode format + bRet = BufReadStr(pBuf,sDbLocalEntry.strXMake,nBufLenBytes,bFileModeUni,nBufOffset); + bRet = BufReadStr(pBuf,sDbLocalEntry.strXModel,nBufLenBytes,bFileModeUni,nBufOffset); + + strTmp = ""; + bRet = BufReadStr(pBuf,strTmp,nBufLenBytes,bFileModeUni,nBufOffset); +//@@ sDbLocalEntry.eEditor = static_cast(_tstoi(strTmp)); + + bRet = BufReadStr(pBuf,sDbLocalEntry.strUmQual,nBufLenBytes,bFileModeUni,nBufOffset); + bRet = BufReadStr(pBuf,sDbLocalEntry.strCSig,nBufLenBytes,bFileModeUni,nBufOffset); + bRet = BufReadStr(pBuf,sDbLocalEntry.strCSigRot,nBufLenBytes,bFileModeUni,nBufOffset); + + + // In older version of DB, these entries won't exist + bRet = BufReadStr(pBuf,sDbLocalEntry.strXSubsamp,nBufLenBytes,bFileModeUni,nBufOffset); + bRet = BufReadStr(pBuf,sDbLocalEntry.strMSwTrim,nBufLenBytes,bFileModeUni,nBufOffset); + bRet = BufReadStr(pBuf,sDbLocalEntry.strMSwDisp,nBufLenBytes,bFileModeUni,nBufOffset); + } + + // ------------------------------------------------------- + + // Does the entry already exist in the internal DB? + bDbLocalEntryFound = SearchSignatureExactInternal(sDbLocalEntry.strXMake,sDbLocalEntry.strXModel,sDbLocalEntry.strCSig); + + if (!bDbLocalEntryFound) + { + // Add it! + m_sSigListExtra[m_nSigListExtraNum].bValid = true; + m_sSigListExtra[m_nSigListExtraNum].strXMake = sDbLocalEntry.strXMake; + m_sSigListExtra[m_nSigListExtraNum].strXModel = sDbLocalEntry.strXModel; + m_sSigListExtra[m_nSigListExtraNum].eEditor = sDbLocalEntry.eEditor; + m_sSigListExtra[m_nSigListExtraNum].strUmQual = sDbLocalEntry.strUmQual; + m_sSigListExtra[m_nSigListExtraNum].strCSig = sDbLocalEntry.strCSig; + m_sSigListExtra[m_nSigListExtraNum].strCSigRot = sDbLocalEntry.strCSigRot; + + m_sSigListExtra[m_nSigListExtraNum].strXSubsamp = sDbLocalEntry.strXSubsamp; + m_sSigListExtra[m_nSigListExtraNum].strMSwTrim = sDbLocalEntry.strMSwTrim; + m_sSigListExtra[m_nSigListExtraNum].strMSwDisp = sDbLocalEntry.strMSwDisp; + m_nSigListExtraNum++; + } else + { + bDbLocalTrimmed = true; + } + } + } + else if (strSec == "*Z*") + { + bDone = true; + } + else + { + bValid = false; + } // strSec + } // while + + // ---------------------- + + pInFile.close(); + + if (pBuf) + { + delete [] pBuf; + pBuf = NULL; + } + + // If we did make changes to the database (trim), then rewrite it! + // Ensure that we have closed the file above before we rewrite it + // otherwise we could end up with a sharing violation + if (bDbLocalTrimmed) + { + DatabaseExtraStore(); + } + + // Now is this an old config file version? If so, + // create a backup and then rewrite the new version +// if (bValid) { +// if (strVer != DB_VER_STR) { +// // Copy old config file +// TCHAR szFilePathNameBak[200]; +// _stprintf_s(szFilePathNameBak,"%s\\%s.bak",m_strDbDir,DAT_FILE); +// CopyFile(szFilePathName,szFilePathNameBak,false); +// // Now rewrite file in latest version +// DatabaseExtraStore(); +// // Notify user +// strError = QString(("Upgraded User Signature Database. Backup in:\n%s",szFilePathNameBak); +// AfxMessageBox(strError); +// } +// } +} + +void CDbSigs::DatabaseExtraClean() +{ + m_nSigListExtraNum = 0; + DatabaseExtraStore(); +} + +unsigned CDbSigs::DatabaseExtraGetNum() +{ + return m_nSigListExtraNum; +} + +CompSig CDbSigs::DatabaseExtraGet(unsigned nInd) +{ + Q_ASSERT(nInd= DBEX_ENTRIES_MAX) + { + QString strTmp; + strTmp = QString("ERROR: Can only store maximum of %1 extra signatures in local DB").arg(DBEX_ENTRIES_MAX); +//@@ AfxMessageBox(strTmp); + return; + } + + // Now append it to the local database and resave + m_sSigListExtra[m_nSigListExtraNum].strXMake = strExifMake; + m_sSigListExtra[m_nSigListExtraNum].strXModel = strExifModel; + m_sSigListExtra[m_nSigListExtraNum].strUmQual = strQual; + m_sSigListExtra[m_nSigListExtraNum].strCSig = strSig; + m_sSigListExtra[m_nSigListExtraNum].strCSigRot = strSigRot; + m_sSigListExtra[m_nSigListExtraNum].strXSubsamp = strCss; + + if (eUserSource == ENUM_SOURCE_CAM) { // digicam + m_sSigListExtra[m_nSigListExtraNum].eEditor = ENUM_EDITOR_CAM; + m_sSigListExtra[m_nSigListExtraNum].strMSwTrim = ""; + m_sSigListExtra[m_nSigListExtraNum].strMSwDisp = ""; + } else if (eUserSource == ENUM_SOURCE_SW) { // software + m_sSigListExtra[m_nSigListExtraNum].eEditor = ENUM_EDITOR_SW; + m_sSigListExtra[m_nSigListExtraNum].strMSwTrim = ""; + m_sSigListExtra[m_nSigListExtraNum].strMSwDisp = strUserSoftware; // Not quite right perfect + m_sSigListExtra[m_nSigListExtraNum].strXMake = ""; + m_sSigListExtra[m_nSigListExtraNum].strXModel = ""; + } else { // user didn't know + m_sSigListExtra[m_nSigListExtraNum].eEditor = ENUM_EDITOR_UNSURE; + m_sSigListExtra[m_nSigListExtraNum].strMSwTrim = ""; + m_sSigListExtra[m_nSigListExtraNum].strMSwDisp = strUserSoftware; // Not quite right perfect + } + + m_nSigListExtraNum++; + + // Now resave the database + DatabaseExtraStore(); +} + +// TODO: Should we include editors in this search? +bool CDbSigs::SearchSignatureExactInternal(QString strMake, QString strModel, QString strSig) +{ + bool bFoundExact = false; + bool bDone = false; + unsigned nInd = 0; + + while (!bDone) + { + if (nInd >= m_nSigListNum) + { + bDone = true; + } + else + { + if((m_sSigList[nInd].strXMake == strMake) && + (m_sSigList[nInd].strXModel == strModel) && + ((m_sSigList[nInd].strCSig == strSig) || (m_sSigList[nInd].strCSigRot == strSig)) ) + { + bFoundExact = true; + bDone = true; + } + + nInd++; + } + } + + return bFoundExact; +} + +bool CDbSigs::SearchCom(QString strCom) +{ + bool bFound = false; + + if (strCom.size() > 0) + { + for(int i = 0; i < m_sXComSwList.size(); i++) + { + if(m_sXComSwList.at(i).contains(strCom)) + { + bFound = true; + break; + } + } + } + + return bFound; +} + +// Returns total of built-in plus local DB +unsigned CDbSigs::GetDBNumEntries() +{ + return (m_nSigListNum + m_nSigListExtraNum); +} + +// Returns total of built-in plus local DB +unsigned CDbSigs::IsDBEntryUser(unsigned nInd) +{ + if (nInd < m_nSigListNum) + { + return false; + } + else + { + return true; + } +} + +// Return a ptr to the struct containing the indexed entry +bool CDbSigs::GetDBEntry(unsigned nInd,CompSig* pEntry) +{ + unsigned nIndOffset; + unsigned nIndMax = GetDBNumEntries(); + Q_ASSERT(pEntry); + Q_ASSERT(nIndeEditor = m_sSigList[nInd].eEditor; + pEntry->strXMake = m_sSigList[nInd].strXMake; + pEntry->strXModel = m_sSigList[nInd].strXModel; + pEntry->strUmQual = m_sSigList[nInd].strUmQual; + pEntry->strCSig = m_sSigList[nInd].strCSig; + pEntry->strCSigRot = m_sSigList[nInd].strCSigRot; + pEntry->strXSubsamp = m_sSigList[nInd].strXSubsamp; + pEntry->strMSwTrim = m_sSigList[nInd].strMSwTrim; + pEntry->strMSwDisp = m_sSigList[nInd].strMSwDisp; + return true; + } + else + { + nIndOffset = nInd-m_nSigListNum; + pEntry->eEditor = m_sSigListExtra[nIndOffset].eEditor; + pEntry->strXMake = m_sSigListExtra[nIndOffset].strXMake; + pEntry->strXModel = m_sSigListExtra[nIndOffset].strXModel; + pEntry->strUmQual = m_sSigListExtra[nIndOffset].strUmQual; + pEntry->strCSig = m_sSigListExtra[nIndOffset].strCSig; + pEntry->strCSigRot = m_sSigListExtra[nIndOffset].strCSigRot; + pEntry->strXSubsamp = m_sSigListExtra[nIndOffset].strXSubsamp; + pEntry->strMSwTrim = m_sSigListExtra[nIndOffset].strMSwTrim; + pEntry->strMSwDisp = m_sSigListExtra[nIndOffset].strMSwDisp; + return true; + } +} + +void CDbSigs::SetEntryValid(unsigned nInd,bool bValid) +{ + // TODO: Bounds check + Q_ASSERT(nInd < m_nSigListExtraNum); + m_sSigListExtra[nInd].bValid = bValid; +} + + +unsigned CDbSigs::GetIjgNum() +{ + return m_nSwIjgListNum; +} + +QString CDbSigs::GetIjgEntry(unsigned nInd) +{ + return m_sSwIjgList[nInd]; +} + +// Update the directory used for user database +void CDbSigs::SetDbDir(QString strDbDir) +{ + m_strDbDir = strDbDir; +} + + +// Search exceptions for Make/Model in list of ones that don't have Makernotes +bool CDbSigs::LookupExcMmNoMkr(QString strMake,QString strModel) +{ + bool bFound = false; + bool bDone = false; + unsigned nInd = 0; + + if (strMake.size() == 0) + { + bDone = true; + } + + while (!bDone) + { + if (nInd >= m_nExcMmNoMkrListNum) + { + bDone = true; + } + else + { + // Perform exact match on Make, case sensitive + // Check Make field and possibly Model field (if non-empty) + if (m_sExcMmNoMkrList[nInd].strXMake == strMake) + { + // Make matched, now check to see if we need to compare the Model string + if (m_sExcMmNoMkrList[nInd].strXModel != strModel) + { + // No need to compare, we're bDone + bFound = true; + bDone = true; + } + else + { + // Need to check model as well. Since we may like to do a substring match, support wildcards + + // Find position of "*" if it exists in DB entry + int pWildcard; + unsigned nCompareLen; + pWildcard = m_sExcMmNoMkrList[nInd].strXModel.indexOf(QChar('*')); + + if (pWildcard != -1) + { + // Wildcard present + nCompareLen = m_sExcMmNoMkrList[nInd].strXModel.size() - pWildcard; //!! - 1 + } + else + { + // No wildcard, do full match + nCompareLen = m_sExcMmNoMkrList[nInd].strXModel.size(); + } + + if (m_sExcMmNoMkrList[nInd].strXModel.left(nCompareLen) == strModel) + { + // Matched as well, we're bDone + bFound = true; + bDone = true; + } + } + } + + nInd++; + } + } + + return bFound; +} + +// Search exceptions for Make/Model in list of ones that are always edited +bool CDbSigs::LookupExcMmIsEdit(QString strMake,QString strModel) +{ + bool bFound = false; + bool bDone = false; + unsigned nInd = 0; + + if (strMake.size() == 0) + { + bDone = true; + } + + while (!bDone) + { + if (nInd >= m_nExcMmIsEditListNum) + { + bDone = true; + } + else + { + // Perform exact match, case sensitive + // Check Make field and possibly Model field (if non-empty) + if (m_sExcMmIsEditList[nInd].strXMake == strMake) + { + // Make matched, now check to see if we need + // to compare the Model string + if (m_sExcMmIsEditList[nInd].strXModel.size() == 0) + { + // No need to compare, we're bDone + bFound = true; + bDone = true; + } + else + { + // Need to check model as well + if (m_sExcMmIsEditList[nInd].strXModel == strModel) + { + // Matched as well, we're bDone + bFound = true; + bDone = true; + } + } + } + + nInd++; + } + } + + return bFound; +} + +// Software signature list (m_sSigList) is located in "Signatures.inl" + diff --git a/source/DbSigs.h b/source/DbSigs.h index 81af69f..0074e4f 100644 --- a/source/DbSigs.h +++ b/source/DbSigs.h @@ -1,138 +1,137 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Class provides management of the signatures database -// - Supports both built-in and user database entries -// -// ========================================================================== - - -#pragma once - -#define DBEX_ENTRIES_MAX 300 -#define DB_VER_STR "03" - -#include "snoop.h" - -// Signature exception structure with metadata fields -struct CompExcMm { - LPTSTR strXMake; // EXIF Make - LPTSTR strXModel; // EXIF Model -}; - - -// Signature structure for hardcoded table -struct CompSigConst { - teEditor eEditor; // Digicam vs software/editor - LPTSTR strXMake; // Blank for editors (set to strMSwDisp) - LPTSTR strXModel; // Blank for editors - LPTSTR strUmQual; - LPTSTR strCSig; // Signature - LPTSTR strCSigRot; // Signature of rotated DQTs - LPTSTR strXSubsamp; // Blank for editors - LPTSTR strMSwTrim; // Blank for digicam - LPTSTR strMSwDisp; // Blank for digicam -}; - - -// Signature structure for runtime table (can use CStrings) -struct CompSig { - bool bValid; // Set to FALSE for removal - teEditor eEditor; - CString strXMake; // Blank for editors - CString strXModel; // Blank for editors - CString strUmQual; - CString strCSig; - CString strCSigRot; - CString strXSubsamp; // Blank for editors - CString strMSwTrim; // Blank for digicam - CString strMSwDisp; // Blank for digicam -}; - - - -class CDbSigs -{ -public: - CDbSigs(); - ~CDbSigs(); - - unsigned GetNumSigsInternal(); - unsigned GetNumSigsExtra(); - - unsigned GetDBNumEntries(); - bool GetDBEntry(unsigned nInd,CompSig* pEntry); - unsigned IsDBEntryUser(unsigned nInd); - - void SetEntryValid(unsigned nInd,bool bValid); - - void DatabaseExtraClean(); - void DatabaseExtraLoad(); - void DatabaseExtraStore(); - - unsigned DatabaseExtraGetNum(); - CompSig DatabaseExtraGet(unsigned nInd); - - void DatabaseExtraAdd(CString strExifMake,CString strExifModel, - CString strQual,CString strSig,CString strSigRot,CString strCss, - teSource eUserSource,CString strUserSoftware); - - bool BufReadNum(PBYTE pBuf,unsigned &nOut,unsigned nMaxBytes,unsigned &nOffsetBytes); - bool BufReadStr(PBYTE pBuf,CString &strOut,unsigned nMaxBytes,bool bUni,unsigned &nOffsetBytes); - bool BufWriteNum(PBYTE pBuf,unsigned nIn,unsigned nMaxBytes,unsigned &nOffsetBytes); - bool BufWriteStr(PBYTE pBuf,CString strIn,unsigned nMaxBytes,bool bUni,unsigned &nOffsetBytes); - - bool SearchSignatureExactInternal(CString strMake, CString strModel, CString strSig); - bool SearchCom(CString strCom); - - bool LookupExcMmNoMkr(CString strMake,CString strModel); - bool LookupExcMmIsEdit(CString strMake,CString strModel); - - unsigned GetIjgNum(); - LPTSTR GetIjgEntry(unsigned nInd); - - void SetDbDir(CString strDbDir); - void SetFirstRun(bool bFirstRun); - -private: - CompSig m_sSigListExtra[DBEX_ENTRIES_MAX]; // Extra entries - unsigned m_nSigListExtraNum; - - unsigned m_nSigListNum; - static const CompSigConst m_sSigList[]; // Built-in entries - - unsigned m_nExcMmNoMkrListNum; - static const CompExcMm m_sExcMmNoMkrList[]; - - unsigned m_nExcMmIsEditListNum; - static const CompExcMm m_sExcMmIsEditList[]; - - unsigned m_nSwIjgListNum; - static LPTSTR m_sSwIjgList[]; - - unsigned m_nXcomSwListNum; - static LPTSTR m_sXComSwList[]; - - CString m_strDbDir; // Database directory - - bool m_bFirstRun; // First time running app? - -}; - +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - Class provides management of the signatures database +// - Supports both built-in and user database entries +// +// ========================================================================== + +#pragma once + +#include + +#define DBEX_ENTRIES_MAX 300 +#define DB_VER_STR "03" + +#include "snoop.h" + +// Signature exception structure with metadata fields +struct CompExcMm +{ + QString strXMake; // EXIF Make + QString strXModel; // EXIF Model +}; + +// Signature structure for hardcoded table +struct CompSigConst +{ + teEditor eEditor; // Digicam vs software/editor + QString strXMake; // Blank for editors (set to strMSwDisp) + QString strXModel; // Blank for editors + QString strUmQual; + QString strCSig; // Signature + QString strCSigRot; // Signature of rotated DQTs + QString strXSubsamp; // Blank for editors + QString strMSwTrim; // Blank for digicam + QString strMSwDisp; // Blank for digicam +}; + +// Signature structure for runtime table (can use QStrings) +struct CompSig +{ + bool bValid; // Set to FALSE for removal + teEditor eEditor; + QString strXMake; // Blank for editors + QString strXModel; // Blank for editors + QString strUmQual; + QString strCSig; + QString strCSigRot; + QString strXSubsamp; // Blank for editors + QString strMSwTrim; // Blank for digicam + QString strMSwDisp; // Blank for digicam +}; + +class CDbSigs +{ +public: + CDbSigs(); + ~CDbSigs(); + + unsigned GetNumSigsInternal(); + unsigned GetNumSigsExtra(); + + unsigned GetDBNumEntries(); + bool GetDBEntry(unsigned nInd, CompSig * pEntry); + unsigned IsDBEntryUser(unsigned nInd); + + void SetEntryValid(unsigned nInd, bool bValid); + + void DatabaseExtraClean(); + void DatabaseExtraLoad(); + void DatabaseExtraStore(); + + unsigned DatabaseExtraGetNum(); + CompSig DatabaseExtraGet(unsigned nInd); + + void DatabaseExtraAdd(QString strExifMake, QString strExifModel, + QString strQual, QString strSig, QString strSigRot, QString strCss, + teSource eUserSource, QString strUserSoftware); + + bool BufReadNum(quint8 * pBuf, unsigned &nOut, unsigned nMaxBytes, unsigned &nOffsetBytes); + bool BufReadStr(quint8 * pBuf, QString & strOut, unsigned nMaxBytes, bool bUni, unsigned &nOffsetBytes); + bool BufWriteNum(quint8 * pBuf, unsigned nIn, unsigned nMaxBytes, unsigned &nOffsetBytes); + bool BufWriteStr(quint8 * pBuf, QString strIn, unsigned nMaxBytes, bool bUni, unsigned &nOffsetBytes); + + bool SearchSignatureExactInternal(QString strMake, QString strModel, QString strSig); + bool SearchCom(QString strCom); + + bool LookupExcMmNoMkr(QString strMake, QString strModel); + bool LookupExcMmIsEdit(QString strMake, QString strModel); + + unsigned GetIjgNum(); + QString GetIjgEntry(unsigned nInd); + + void SetDbDir(QString strDbDir); + void SetFirstRun(bool bFirstRun); + +private: + CompSig m_sSigListExtra[DBEX_ENTRIES_MAX]; // Extra entries + unsigned m_nSigListExtraNum; + + unsigned m_nSigListNum; + static const CompSigConst m_sSigList[]; // Built-in entries + + unsigned m_nExcMmNoMkrListNum; + static const CompExcMm m_sExcMmNoMkrList[]; + + unsigned m_nExcMmIsEditListNum; + static const CompExcMm m_sExcMmIsEditList[]; + + unsigned m_nSwIjgListNum; + + + unsigned m_nXcomSwListNum; + + QString m_strDbDir; // Database directory + QStringList m_sXComSwList; + QStringList m_sSwIjgList; + + bool m_bFirstRun; // First time running app? +}; diff --git a/source/DecodeDicom.h b/source/DecodeDicom.h index edccfb6..9822092 100644 --- a/source/DecodeDicom.h +++ b/source/DecodeDicom.h @@ -1,146 +1,152 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - This module parses DICOM files -// - No rendering is done -// -// ========================================================================== - -#pragma once - -#include "WindowBuf.h" -#include "snoop.h" -#include "SnoopConfig.h" - - -// Structure used for each Tag entry -// Reference: Types defined in Part 3, Section 5.2 -enum teDicomType { DICOM_T_UNK, - DICOM_T_TYPE1, - DICOM_T_TYPE1C, - DICOM_T_TYPE3, - DICOM_T_END }; -// Definition of Group & Element in Part 10, Section 5 -struct tsDicomTag { - unsigned nTagGroup; - unsigned nTagElement; - teDicomType eTagType; - CString strTagName; -}; - -// Definition of Transfer Syntaxes and other UIDs -struct tsDicomTagSpec { - unsigned nTagGroup; - unsigned nTagElement; - CString strVal; - CString strDefinition; -}; - -struct tsTagDetail { - unsigned nTagGroup; - unsigned nTagElement; - CString strVR; - unsigned nLen; - unsigned nOffset; // Offset after parsing this tag - - bool bVrExplicit; - bool bLen4B; - - bool bTagOk; - CString strTag; - bool bValOk; - CString strVal; - - bool bTagIsJpeg; - unsigned long nPosJpeg; - - tsTagDetail() { - Reset(); - }; - void Reset() { - nTagGroup = 0; - nTagElement = 0; - strVR = _T(""); - nLen = 0; - nOffset = 0; - - bVrExplicit = false; - bLen4B = false; - - bTagOk = false; - strTag = _T(""); - bValOk = false; - strVal = _T(""); - - bTagIsJpeg = false; - nPosJpeg = 0; - }; -}; - - -// Byte Swap enable for DICOM decoding -#define DC_BSWAP true - -// Define the DICOM hex output display characteristics -#define DC_HEX_MAX_INLINE 16 // Threshold for displaying hex in-line with field name -#define DC_HEX_MAX_ROW 16 // Maximum number of bytes to report per line -#define DC_HEX_TOTAL 128 // Total number of bytes to report before clipping - -// Define the maximum length Unicode string to display -#define DC_MAX_UNICODE_STRLEN 256 - - -class CDecodeDicom -{ -public: - CDecodeDicom(CwindowBuf* pWBuf,CDocLog* pLog); - ~CDecodeDicom(void); - - void Reset(); - - bool DecodeDicom(unsigned long nPos,unsigned long nPosFileEnd,unsigned long &nPosJpeg); - //bool DecodeTagHeader(unsigned long nPos,CString &strTag,CString &strVR,unsigned &nLen,unsigned &nOffset,unsigned long &nPosJpeg); - bool GetTagHeader(unsigned long nPos,tsTagDetail &sTagDetail); - bool FindTag(unsigned nTagGroup,unsigned nTagElement,unsigned &nFldInd); - - BYTE Buf(unsigned long offset,bool bClean); - - CString ParseIndent(unsigned nIndent); - void ReportFldStr(unsigned nIndent,CString strField,CString strVal); - void ReportFldStrEnc(unsigned nIndent,CString strField,CString strVal,CString strEncVal); - void ReportFldHex(unsigned nIndent,CString strField,unsigned long nPosStart,unsigned nLen); - void ReportFldEnum(unsigned nIndent,CString strField,unsigned nTagGroup,unsigned nTagElement,CString strVal); - bool LookupEnum(unsigned nTagGroup,unsigned nTagElement,CString strVal,CString &strDesc); - -private: - // Configuration - CSnoopConfig* m_pAppConfig; - - // General classes required for decoding - CwindowBuf* m_pWBuf; - CDocLog* m_pLog; - -public: - bool m_bDicom; - bool m_bJpegEncap; - bool m_bJpegEncapOffsetNext; - -}; - +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - This module parses DICOM files +// - No rendering is done +// +// ========================================================================== + +#ifndef DECODEDICOM_H +#define DECODEDICOM_H + +#include + +#include "WindowBuf.h" +#include "snoop.h" +#include "SnoopConfig.h" + + +// Structure used for each Tag entry +// Reference: Types defined in Part 3, Section 5.2 +enum teDicomType { DICOM_T_UNK, + DICOM_T_TYPE1, + DICOM_T_TYPE1C, + DICOM_T_TYPE3, + DICOM_T_END }; +// Definition of Group & Element in Part 10, Section 5 +struct tsDicomTag { + unsigned nTagGroup; + unsigned nTagElement; + teDicomType eTagType; + QString strTagName; +}; + +// Definition of Transfer Syntaxes and other UIDs +struct tsDicomTagSpec { + unsigned nTagGroup; + unsigned nTagElement; + QString strVal; + QString strDefinition; +}; + +struct tsTagDetail { + unsigned nTagGroup; + unsigned nTagElement; + QString strVR; + unsigned nLen; + unsigned nOffset; // Offset after parsing this tag + + bool bVrExplicit; + bool bLen4B; + + bool bTagOk; + QString strTag; + bool bValOk; + QString strVal; + + bool bTagIsJpeg; + unsigned long nPosJpeg; + + tsTagDetail() { + Reset(); + }; + void Reset() { + nTagGroup = 0; + nTagElement = 0; + strVR = ""; + nLen = 0; + nOffset = 0; + + bVrExplicit = false; + bLen4B = false; + + bTagOk = false; + strTag = ""; + bValOk = false; + strVal = ""; + + bTagIsJpeg = false; + nPosJpeg = 0; + }; +}; + + +// Byte Swap enable for DICOM decoding +#define DC_BSWAP true + +// Define the DICOM hex output display characteristics +#define DC_HEX_MAX_INLINE 16 // Threshold for displaying hex in-line with field name +#define DC_HEX_MAX_ROW 16 // Maximum number of bytes to report per line +#define DC_HEX_TOTAL 128 // Total number of bytes to report before clipping + +// Define the maximum length Unicode string to display +#define DC_MAX_UNICODE_STRLEN 256 + + +class CDecodeDicom +{ +public: + CDecodeDicom(CwindowBuf* pWBuf,CDocLog* pLog); + ~CDecodeDicom(void); + + void Reset(); + + bool DecodeDicom(unsigned long nPos,unsigned long nPosFileEnd,unsigned long &nPosJpeg); + //bool DecodeTagHeader(unsigned long nPos,QString &strTag,QString &strVR,unsigned &nLen,unsigned &nOffset,unsigned long &nPosJpeg); + bool GetTagHeader(unsigned long nPos,tsTagDetail &sTagDetail); + bool FindTag(unsigned nTagGroup,unsigned nTagElement,unsigned &nFldInd); + + quint8 Buf(unsigned long offset,bool bClean); + + QString ParseIndent(unsigned nIndent); + void ReportFldStr(unsigned nIndent,QString strField,QString strVal); + void ReportFldStrEnc(unsigned nIndent,QString strField,QString strVal,QString strEncVal); + void ReportFldHex(unsigned nIndent,QString strField,unsigned long nPosStart,unsigned nLen); + void ReportFldEnum(unsigned nIndent,QString strField,unsigned nTagGroup,unsigned nTagElement,QString strVal); + bool LookupEnum(unsigned nTagGroup,unsigned nTagElement,QString strVal,QString &strDesc); + +private: + CDecodeDicom &operator = (const CDecodeDicom&); + CDecodeDicom(CDecodeDicom&); + + // Configuration + CSnoopConfig* m_pAppConfig; + + // General classes required for decoding + CwindowBuf* m_pWBuf; + CDocLog* m_pLog; + +public: + bool m_bDicom; + bool m_bJpegEncap; + bool m_bJpegEncapOffsetNext; +}; + +#endif diff --git a/source/DecodePs.cpp b/source/DecodePs.cpp index f81faba..c6bafe6 100644 --- a/source/DecodePs.cpp +++ b/source/DecodePs.cpp @@ -1,2983 +1,3492 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - - -#include "stdafx.h" - -#include "DecodePs.h" -#include "snoop.h" -#include "JPEGsnoop.h" // for m_pAppConfig get - -#include "WindowBuf.h" - - -// Forward declarations -struct tsIptcField asIptcFields[]; -struct tsBimRecord asBimRecords[]; -struct tsBimEnum asBimEnums[]; - -CDecodePs::CDecodePs(CwindowBuf* pWBuf,CDocLog* pLog) -{ - // Save copies of class pointers - m_pWBuf = pWBuf; - m_pLog = pLog; - - // HACK - // Only select a single layer to decode into the DIB - // FIXME: Need to allow user control over this setting - m_bDisplayLayer = false; - m_nDisplayLayerInd = 0; - m_bDisplayImage = true; - - // Ideally this would be passed by constructor, but simply access - // directly for now. - CJPEGsnoopApp* pApp; - pApp = (CJPEGsnoopApp*)AfxGetApp(); - m_pAppConfig = pApp->m_pAppConfig; - - Reset(); -} - -void CDecodePs::Reset() -{ - m_bPsd = false; - m_nQualitySaveAs = 0; - m_nQualitySaveForWeb = 0; - m_bAbort = false; -} - - -CDecodePs::~CDecodePs(void) -{ -} - - -// Provide a short-hand alias for the m_pWBuf buffer -// INPUT: -// - offset File offset to read from -// - bClean Forcibly disables any redirection to Fake DHT table -// -// POST: -// - m_pLog -// -// RETURN: -// - Byte from file -// -BYTE CDecodePs::Buf(unsigned long offset,bool bClean=false) -{ - return m_pWBuf->Buf(offset,bClean); -} - - -// Determine if the file is a Photoshop PSD -// If so, parse the headers. Generally want to start at start of file (nPos=0). -bool CDecodePs::DecodePsd(unsigned long nPos,CDIB* pDibTemp,unsigned &nWidth,unsigned &nHeight) -{ - CString strTmp; - - m_bPsd = false; - - CString strSig; - unsigned nVer; - - strSig = m_pWBuf->BufReadStrn(nPos,4); nPos+=4; - nVer = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - if ((strSig == _T("8BPS")) && (nVer == 1)) { - m_bPsd = true; - m_pLog->AddLine(_T("")); - m_pLog->AddLineHdr(_T("*** Photoshop PSD File Decoding ***")); - m_pLog->AddLine(_T("Decoding Photoshop format...")); - m_pLog->AddLine(_T("")); - } else { - return false; - } - - // Rewind back to header (signature) - nPos-=6; - - bool bDecOk = true; - - tsImageInfo sImageInfo; - - PhotoshopParseFileHeader(nPos,3,&sImageInfo); - nWidth = sImageInfo.nImageWidth; - nHeight = sImageInfo.nImageHeight; - - PhotoshopParseColorModeSection(nPos,3); - if (bDecOk) - bDecOk &= PhotoshopParseImageResourcesSection(nPos,3); - - if (bDecOk) - bDecOk &= PhotoshopParseLayerMaskInfo(nPos,3,pDibTemp); - if (bDecOk) { - unsigned char* pDibBits = NULL; - -#ifdef PS_IMG_DEC_EN - if ((pDibTemp) && (m_bDisplayImage)) { - // Allocate the device-independent bitmap (DIB) - // - Although we are creating a 32-bit DIB, it should also - // work to run in 16- and 8-bit modes - - // Start by killing old DIB since we might be changing its dimensions - pDibTemp->Kill(); - - // Allocate the new DIB - bool bDibOk = pDibTemp->CreateDIB(nWidth,nHeight,32); - // Should only return false if already exists or failed to allocate - if (bDibOk) { - // Fetch the actual pixel array - pDibBits = (unsigned char*) ( pDibTemp->GetDIBBitArray() ); - } - } -#endif - - bDecOk &= PhotoshopParseImageData(nPos,3,&sImageInfo,pDibBits); - PhotoshopParseReportFldOffset(3,_T("Image data decode complete:"),nPos); - } - PhotoshopParseReportNote(3,_T("")); - - if (bDecOk) { - } else { - m_pLog->AddLineErr(_T("ERROR: There was a problem during decode. Aborting.")); - return false; - } - return true; - -} - - -// Locate a field ID in the constant 8BIM / Image Resource array -// -// INPUT: -// - nBimId = Image Resource ID (16-bit unsigned) -// OUTPUT: -// - nFldInd = Index into asBimRecords[] array -// RETURN: -// - Returns true if ID was found in array -// NOTE: -// - The constant struct array depends on BIM_T_END as a terminator for the list -// -bool CDecodePs::FindBimRecord(unsigned nBimId,unsigned &nFldInd) -{ - unsigned nInd=0; - bool bDone=false; - bool bFound=false; - while (!bDone) { - if (asBimRecords[nInd].eBimType == BIM_T_END) { - bDone = true; - } else { - // Support detection of code ranges - unsigned nCodeStart = asBimRecords[nInd].nCode; - unsigned nCodeEnd = asBimRecords[nInd].nCodeEnd; - if ((nCodeEnd == 0) && (nCodeStart == nBimId)) { - // Match with single code (ie. not ranged entry) - bDone = true; - bFound = true; - } else if ((nCodeEnd != 0) && (nCodeStart <= nBimId) && (nCodeEnd >= nBimId)) { - // Match with code in ranged entry - bDone = true; - bFound = true; - } else { - nInd++; - } - - } - } - if (bFound) { - nFldInd = nInd; - } - return bFound; -} - -// Search the constant array of IPTC fields for the Record:DataSet index -// -// OUTPUT: -// - nFldInd = The index into the array of the located entry (if found) -// RETURN -// - Successfully found the Record:DataSet value -// -bool CDecodePs::LookupIptcField(unsigned nRecord,unsigned nDataSet,unsigned &nFldInd) -{ - unsigned nInd=0; - bool bDone=false; - bool bFound=false; - while (!bDone) { - if (asIptcFields[nInd].eFldType == IPTC_T_END) { - bDone = true; - } else { - if ((asIptcFields[nInd].nRecord == nRecord) && (asIptcFields[nInd].nDataSet == nDataSet)) { - bDone = true; - bFound = true; - } else { - nInd++; - } - } - } - if (bFound) { - nFldInd = nInd; - } - return bFound; -} - - - -// Generate the custom-formatted string representing the IPTC field name and value -// -// INPUT: -// - eIptcType = Enumeration representing the IPTC field type -// - nFldCnt = The number of elements in this field to report -// - nPos = The starting file offset for this field -// RETURN: -// - The IPTC formattted string -// NOTE: -// - The IPTC field type is used to determine how to represent the input values -// -CString CDecodePs::DecodeIptcValue(teIptcType eIptcType,unsigned nFldCnt,unsigned long nPos) -{ - //unsigned nFldInd = 0; - unsigned nInd; - unsigned nVal; - CString strField = _T(""); - CString strByte = _T(""); - CString strVal = _T(""); - switch (eIptcType) { - case IPTC_T_NUM: - case IPTC_T_NUM1: - case IPTC_T_NUM2: - nVal = m_pWBuf->BufX(nPos,nFldCnt,PS_BSWAP); nPos+=nFldCnt; - nPos += nFldCnt; - strVal.Format(_T("%u"),nVal); - break; - case IPTC_T_HEX: - strVal = _T("["); - for (nInd=0;nIndAddLine(strTmp); - nPos += nDataFieldCnt; - } else { - // Unknown Tag Marker - // I have seen at least one JPEG file that had an IPTC block with all zeros. - // In this example, the TagMarker check for 0x1C would fail. - // Since we don't know how to parse it, abort now. - strTmp.Format(_T("ERROR: Unknown IPTC TagMarker [0x%02X] @ 0x%08X. Skipping parsing."),nTagMarker,nPos-5); - m_pLog->AddLineErr(strTmp); - -#ifdef DEBUG_LOG - CString strDebug; - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("PsDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#endif - - // Adjust length to end - nPos = nPosStart + nLen; - - // Now abort - bDone = true; - } - - if (nPos >= nPosStart+nLen) { - bDone = true; - } - } -} - - -// Create indent string -// - Returns a sequence of spaces according to the indent level -CString CDecodePs::PhotoshopParseIndent(unsigned nIndent) -{ - CString strIndent = _T(""); - for (unsigned nInd=0;nIndBufRdAdv4(nPos,PS_BSWAP); - if (nStrLen!=0) { - strVal = m_pWBuf->BufReadStrn(nPos,nStrLen); - nPos += nStrLen; - } else { - // 4 byte string - strVal.Format(_T("%c%c%c%c"),Buf(nPos+0),Buf(nPos+1),Buf(nPos+2),Buf(nPos+3)); - nPos+=4; - } - return strVal; -} - -// Read a UNICODE string starting at nPos according to Photoshop Unicode string format -// - Start with 4 byte length -// - Follow with UNICODE string -// OUTPUT: -// - The byte offset to advance the file pointer -// RETURN: -// - Unicode string -CString CDecodePs::PhotoshopParseGetBimLStrUni(unsigned long nPos,unsigned &nPosOffset) -{ - CString strVal; - unsigned nStrLenActual,nStrLenTrunc; - BYTE anStrBuf[(PS_MAX_UNICODE_STRLEN+1)*2]; - wchar_t acStrBuf[(PS_MAX_UNICODE_STRLEN+1)]; - BYTE nChVal; - nPosOffset = 0; - nStrLenActual = m_pWBuf->BufX(nPos+nPosOffset,4,PS_BSWAP); - nPosOffset+=4; - nStrLenTrunc = nStrLenActual; - - // Initialize return - strVal = _T(""); - - - if (nStrLenTrunc>0) { - // Read unicode bytes into byte array - // Truncate the string, leaving room for terminator - if (nStrLenTrunc>PS_MAX_UNICODE_STRLEN) { - nStrLenTrunc = PS_MAX_UNICODE_STRLEN; - } - for (unsigned nInd=0;nIndAddLine(strLine); -} - - -// Display a formatted numeric field with optional units string -// - Report the value with the field name (strField) and current indent level (nIndent) -void CDecodePs::PhotoshopParseReportFldNum(unsigned nIndent,CString strField,unsigned nVal,CString strUnits) -{ - CString strIndent; - CString strVal; - CString strLine; - - strIndent = PhotoshopParseIndent(nIndent); - strVal.Format(_T("%u"),nVal); - strLine.Format(_T("%s%-50s = %s %s"),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strVal,(LPCTSTR)strUnits); - m_pLog->AddLine(strLine); -} - -// Display a formatted boolean field -// - Report the value with the field name (strField) and current indent level (nIndent) -void CDecodePs::PhotoshopParseReportFldBool(unsigned nIndent,CString strField,unsigned nVal) -{ - CString strIndent; - CString strVal; - CString strLine; - - strIndent = PhotoshopParseIndent(nIndent); - strVal = (nVal!=0)? _T("true") : _T("false"); - strLine.Format(_T("%s%-50s = %s"),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strVal); - m_pLog->AddLine(strLine); -} - - -// -// Display a formatted hexadecimal field -// - Report the value with the field name (strField) and current indent level (nIndent) -// - Depending on the length of the buffer, either report the hex value in-line with -// the field name or else start a new row and begin a hex dump -// - Also report the ASCII representation alongside the hex dump -// -// INPUT: -// - nIndent = Current indent level for reporting -// - strField = Field name -// - nPosStart = Field byte array file position start -// - nLen = Field byte array length -// -void CDecodePs::PhotoshopParseReportFldHex(unsigned nIndent,CString strField,unsigned long nPosStart,unsigned nLen) -{ - CString strIndent; - unsigned nByte; - CString strPrefix; - CString strByteHex; - CString strByteAsc; - CString strValHex; - CString strValAsc; - CString strLine; - - strIndent = PhotoshopParseIndent(nIndent); - - if (nLen == 0) { - // Print out the header row, but no data will be shown - strLine.Format(_T("%s%-50s = "),(LPCTSTR)strIndent,(LPCTSTR)strField); - m_pLog->AddLine(strLine); - // Nothing to report, exit now - return; - } else if (nLen <= PS_HEX_MAX_INLINE) { - // Define prefix for row - strPrefix.Format(_T("%s%-50s = "),(LPCTSTR)strIndent,(LPCTSTR)strField); - } else { - // Print out header row - strLine.Format(_T("%s%-50s ="),(LPCTSTR)strIndent,(LPCTSTR)strField); - m_pLog->AddLine(strLine); - // Define prefix for next row - strPrefix.Format(_T("%s"),(LPCTSTR)strIndent); - } - - - // Build up the hex string - // Limit to PS_HEX_TOTAL bytes - unsigned nRowOffset = 0; - bool bDone = false; - unsigned nLenClip; - nLenClip = min(nLen,PS_HEX_TOTAL); - strValHex = _T(""); - strValAsc = _T(""); - while (!bDone) { - // Have we reached the end of the data we wish to display? - if (nRowOffset>=nLenClip) { - bDone = true; - } else { - // Reset the cumulative hex/ascii value strings - strValHex = _T(""); - strValAsc = _T(""); - // Build the hex/ascii value strings - for (unsigned nInd=0;nIndBuf(nPosStart+nRowOffset+nInd); - strByteHex.Format(_T("%02X "),nByte); - // Only display printable characters - if (isprint(nByte)) { - strByteAsc.Format(_T("%c"),nByte); - } else { - strByteAsc = _T("."); - } - } else { - // Pad out to end of row - strByteHex.Format(_T(" ")); - strByteAsc = _T(" "); - } - // Build up the strings - strValHex += strByteHex; - strValAsc += strByteAsc; - } - - // Generate the line with Hex and ASCII representations - strLine.Format(_T("%s | 0x%s | %s"),(LPCTSTR)strPrefix,(LPCTSTR)strValHex,(LPCTSTR)strValAsc); - m_pLog->AddLine(strLine); - - // Now increment file offset - nRowOffset += PS_HEX_MAX_ROW; - } - } - - // If we had to clip the display length, then show ellipsis now - if (nLenClip < nLen) { - strLine.Format(_T("%s | ..."),(LPCTSTR)strPrefix); - m_pLog->AddLine(strLine); - } - - -} - -CString CDecodePs::PhotoshopDispHexWord(unsigned nVal) -{ - CString strValHex; - CString strValAsc; - unsigned nByte; - CString strByteHex; - CString strByteAsc; - CString strLine; - - // Reset the cumulative hex/ascii value strings - strValHex = _T(""); - strValAsc = _T(""); - // Build the hex/ascii value strings - for (unsigned nInd=0;nInd<=3;nInd++) { - nByte = (nVal & 0xFF000000) >> 24; - nVal <<= 8; - - strByteHex.Format(_T("%02X "),nByte); - // Only display printable characters - if (isprint(nByte)) { - strByteAsc.Format(_T("%c"),nByte); - } else { - strByteAsc = _T("."); - } - - // Build up the strings - strValHex += strByteHex; - strValAsc += strByteAsc; - } - - // Generate the line with Hex and ASCII representations - strLine.Format(_T("0x%s | %s"),(LPCTSTR)strValHex,(LPCTSTR)strValAsc); - - return strLine; -} - -// Look up the enumerated constant (nVal) for the specified field (eEnumField) -// - Returns "" if the field wasn't found -CString CDecodePs::PhotoshopParseLookupEnum(teBimEnumField eEnumField,unsigned nVal) -{ - CString strVal = _T(""); - // Find the enum value - bool bDone = false; - bool bFound = false; - unsigned nEnumInd=0; - while (!bDone) { - if (asBimEnums[nEnumInd].eBimEnum == eEnumField) { - if (asBimEnums[nEnumInd].nVal == nVal) { - bDone = true; - bFound = true; - strVal = asBimEnums[nEnumInd].strVal; - } - } - if (asBimEnums[nEnumInd].eBimEnum == BIM_T_ENUM_END) { - bDone = true; - } - if (!bDone) { - nEnumInd++; - } - } - - // If enum wasn't found, then replace by hex value - if (!bFound) { - CString strWord = PhotoshopDispHexWord(nVal); - strVal.Format(_T("? [%s]"),(LPCTSTR)strWord); - } - return strVal; -} - -// Display a formatted enumerated type field -// - Look up enumerated constant (nVal) for the given field (eEnumField) -// - Report the value with the field name (strField) and current indent level (nIndent) -void CDecodePs::PhotoshopParseReportFldEnum(unsigned nIndent,CString strField,teBimEnumField eEnumField,unsigned nVal) -{ - CString strIndent; - CString strVal; - CString strLine; - - strIndent = PhotoshopParseIndent(nIndent); - strVal = PhotoshopParseLookupEnum(eEnumField,nVal); - strLine.Format(_T("%s%-50s = %s"),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strVal); - m_pLog->AddLine(strLine); -} - -// Display a formatted fixed-point field -// - Convert a 32-bit unsigned integer into Photoshop fixed point -// - Assume fixed point representation is 16-bit integer : 16-bit fraction -// - Report the value with the field name (strField) and current indent level (nIndent) -void CDecodePs::PhotoshopParseReportFldFixPt(unsigned nIndent,CString strField,unsigned nVal,CString strUnits) -{ - CString strIndent; - CString strVal; - CString strLine; - float fVal; - - fVal = (nVal / (float)65536.0); - strIndent = PhotoshopParseIndent(nIndent); - strVal.Format(_T("%.f"),fVal); - strLine.Format(_T("%s%-50s = %s %s"),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strVal,(LPCTSTR)strUnits); - m_pLog->AddLine(strLine); -} - -// Display a formatted fixed-point field -// - Convert a 32-bit unsigned integer into Photoshop floating point -// - Report the value with the field name (strField) and current indent level (nIndent) -void CDecodePs::PhotoshopParseReportFldFloatPt(unsigned nIndent,CString strField,unsigned nVal,CString strUnits) -{ - CString strIndent; - CString strVal; - CString strLine; - float fVal; - - // Convert 4 byte unsigned int to floating-point - // TODO: Need to check this since Photoshop web spec doesn't - // indicate how floating points are stored. - union tUnionTmp - { - BYTE nVal[4]; - float fVal; - }; - tUnionTmp myUnion; - // NOTE: Empirically determined the byte order for double representation - myUnion.nVal[3] = static_cast((nVal & 0xFF000000)>>24); - myUnion.nVal[2] = static_cast((nVal & 0x00FF0000)>>16); - myUnion.nVal[1] = static_cast((nVal & 0x0000FF00)>>8); - myUnion.nVal[0] = static_cast((nVal & 0x000000FF)>>0); - fVal = myUnion.fVal; - - strIndent = PhotoshopParseIndent(nIndent); - strVal.Format(_T("%.5f"),fVal); - strLine.Format(_T("%s%-50s = %s %s"),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strVal,(LPCTSTR)strUnits); - m_pLog->AddLine(strLine); -} - -// Display a formatted double-precision floating-point field -// - Convert two 32-bit unsigned integers into Photoshop double-precision floating point -// - Report the value with the field name (strField) and current indent level (nIndent) -void CDecodePs::PhotoshopParseReportFldDoublePt(unsigned nIndent,CString strField,unsigned nVal1,unsigned nVal2,CString strUnits) -{ - CString strIndent; - CString strVal; - CString strLine; - double dVal; - - // Convert 2x4 byte unsigned int to double-point - // TODO: Need to check this since Photoshop web spec doesn't - // indicate how double points are stored. - union tUnionTmp - { - BYTE nVal[8]; - double dVal; - }; - tUnionTmp myUnion; - // NOTE: Empirically determined the byte order for double representation - myUnion.nVal[7] = static_cast((nVal1 & 0xFF000000)>>24); - myUnion.nVal[6] = static_cast((nVal1 & 0x00FF0000)>>16); - myUnion.nVal[5] = static_cast((nVal1 & 0x0000FF00)>>8); - myUnion.nVal[4] = static_cast((nVal1 & 0x000000FF)>>0); - myUnion.nVal[3] = static_cast((nVal2 & 0xFF000000)>>24); - myUnion.nVal[2] = static_cast((nVal2 & 0x00FF0000)>>16); - myUnion.nVal[1] = static_cast((nVal2 & 0x0000FF00)>>8); - myUnion.nVal[0] = static_cast((nVal2 & 0x000000FF)>>0); - dVal = myUnion.dVal; - - strIndent = PhotoshopParseIndent(nIndent); - strVal.Format(_T("%.5f"),dVal); - strLine.Format(_T("%s%-50s = %s %s"),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strVal,(LPCTSTR)strUnits); - m_pLog->AddLine(strLine); -} - -// Display a formatted string field -// - Report the value with the field name (strField) and current indent level (nIndent) -void CDecodePs::PhotoshopParseReportFldStr(unsigned nIndent,CString strField,CString strVal) -{ - CString strIndent; - CString strLine; - - strIndent = PhotoshopParseIndent(nIndent); - strLine.Format(_T("%s%-50s = \"%s\""),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strVal); - m_pLog->AddLine(strLine); -} - - -// Display a formatted file offset field -// - Report the offset with the field name (strField) and current indent level (nIndent) -void CDecodePs::PhotoshopParseReportFldOffset(unsigned nIndent,CString strField,unsigned long nOffset) -{ - CString strIndent; - CString strLine; - - strIndent = PhotoshopParseIndent(nIndent); - strLine.Format(_T("%s%-50s @ 0x%08X"),(LPCTSTR)strIndent,(LPCTSTR)strField,nOffset); - m_pLog->AddLine(strLine); -} - -// Parse the Photoshop IRB Thumbnail Resource -// - NOTE: Returned nPos doesn't take into account JFIF data -void CDecodePs::PhotoshopParseThumbnailResource(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Format"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Width of thumbnail"),nVal,_T("pixels")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Height of thumbnail"),nVal,_T("pixels")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Widthbytes"),nVal,_T("bytes")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Total size"),nVal,_T("bytes")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Size after compression"),nVal,_T("bytes")); - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Bits per pixel"),nVal,_T("bits")); - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Number of planes"),nVal,_T("")); - - PhotoshopParseReportFldOffset(nIndent,_T("JFIF data"),nPos); - - // NOTE: nPos doesn't take into account JFIF data! -} - -// Parse the Photoshop IRB Version Info -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseVersionInfo(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - unsigned nPosOffset; - - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Version"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("hasRealMergedData"),nVal,_T("")); - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("Writer name"),strVal); - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("Reader name"),strVal); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("File version"),nVal,_T("")); -} - -// Parse the Photoshop IRB Print Scale -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParsePrintScale(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldEnum(nIndent,_T("Style"),BIM_T_ENUM_PRINT_SCALE_STYLE,nVal); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldFloatPt(nIndent,_T("X location"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldFloatPt(nIndent,_T("Y location"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldFloatPt(nIndent,_T("Scale"),nVal,_T("")); -} - -// Parse the Photoshop IRB Global Angle -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseGlobalAngle(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Global Angle"),nVal,_T("degrees")); -} - -// Parse the Photoshop IRB Global Altitude -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseGlobalAltitude(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Global Altitude"),nVal,_T("")); -} - -// Parse the Photoshop IRB Print Flags -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParsePrintFlags(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Labels"),nVal); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Crop marks"),nVal); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Color bars"),nVal); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Registration marks"),nVal); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Negative"),nVal); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Flip"),nVal); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Interpolate"),nVal); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Caption"),nVal); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Print flags"),nVal); -} - -// Parse the Photoshop IRB Print Flags Information -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParsePrintFlagsInfo(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Version"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Center crop marks"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Reserved"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Bleed width value"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Bleed width scale"),nVal,_T("")); -} - -// Parse the Photoshop IRB Copyright Flag -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseCopyrightFlag(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Copyright flag"),nVal); -} - -// Parse the Photoshop IRB Aspect Ratio -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParsePixelAspectRatio(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal,nVal1,nVal2; - CString strVal; - - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Version"),nVal,_T("")); - nVal1 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nVal2 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldDoublePt(nIndent,_T("X/Y Ratio"),nVal1,nVal2,_T("")); -} - -// Parse the Photoshop IRB Document-Specific Seed -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseDocSpecificSeed(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Base value"),nVal,_T("")); -} - -// Parse the Photoshop IRB Grid and Guides -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseGridGuides(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Version"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Grid Horizontal"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Grid Vertical"),nVal,_T("")); - unsigned nNumGuides = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Number of Guide Resources"),nNumGuides,_T("")); - - if (nNumGuides>0) - PhotoshopParseReportNote(nIndent,_T("-----")); - for (unsigned nInd=0;nIndBufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent+1,_T("Location"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldEnum(nIndent+1,_T("Direction"),BIM_T_ENUM_GRID_GUIDE_DIR,nVal); - } - if (nNumGuides>0) - PhotoshopParseReportNote(nIndent,_T("-----")); -} - -// Parse the Photoshop IRB Resolution Info -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseResolutionInfo(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal,nUnit; - CString strVal,strUnit; - - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nUnit = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - strUnit = PhotoshopParseLookupEnum(BIM_T_ENUM_RESOLUTION_INFO_RES_UNIT,nUnit); - PhotoshopParseReportFldFixPt(nIndent,_T("Horizontal resolution"),nVal,strUnit); - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldEnum(nIndent,_T("Width unit"),BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT,nVal); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nUnit = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - strUnit = PhotoshopParseLookupEnum(BIM_T_ENUM_RESOLUTION_INFO_RES_UNIT,nUnit); - PhotoshopParseReportFldFixPt(nIndent,_T("Vertical resolution"),nVal,strUnit); - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldEnum(nIndent,_T("Height unit"),BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT,nVal); -} - -// Parse the Photoshop IRB Layer State Info -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseLayerStateInfo(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Target layer"),nVal,_T("")); -} - -// Parse the Photoshop IRB Layer Group Info -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// - nLen = Length of IRB entry (to determine number of layers) -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseLayerGroupInfo(unsigned long &nPos,unsigned nIndent,unsigned nLen) -{ - unsigned nVal; - CString strVal; - - // NOTE: - // According to the Photoshop documentation: - // - 2 bytes per layer containing a group ID for the dragging groups. - // - Layers in a group have the same group ID. - // It was not clear whether there was a separate indication of the number of layers - // For now, assume we can derive it from the total IRB length - unsigned nNumLayers; - nNumLayers = nLen / 2; - - for (unsigned nInd=0;nIndBufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent+1,_T("Layer Group"),nVal,_T("")); - } -} - -// Parse the Photoshop IRB Layer Groups Enabled -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// - nLen = Length of IRB entry (to determine number of layers) -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseLayerGroupEnabled(unsigned long &nPos,unsigned nIndent,unsigned nLen) -{ - unsigned nVal; - CString strVal; - - // NOTE: - // According to the Photoshop documentation: - // - 1 byte for each layer in the document, repeated by length of the resource. - // - NOTE: Layer groups have start and end markers - // For now, assume we can derive it from the total IRB length - unsigned nNumLayers; - nNumLayers = nLen / 1; - - for (unsigned nInd=0;nIndBufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent+1,_T("Layer Group Enabled ID"),nVal,_T("")); - } -} - -// Parse the Photoshop IRB Layer Select IDs -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseLayerSelectId(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - - unsigned nNumLayer = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Num selected"),nNumLayer,_T("")); - for (unsigned nInd=0;nIndBufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent+1,_T("Layer ID"),nVal,_T("")); - } -} - - -// Parse the Photoshop IRB File Header -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseFileHeader(unsigned long &nPos,unsigned nIndent,tsImageInfo* psImageInfo) -{ - ASSERT(psImageInfo); - - unsigned nVal; - CString strVal; - - PhotoshopParseReportNote(nIndent,_T("File Header Section:")); - nIndent++; - - CString strSig = m_pWBuf->BufReadStrn(nPos,4); nPos+=4; - PhotoshopParseReportFldStr(nIndent,_T("Signature"),strSig); - - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Version"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Reserved1"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Reserved2"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Num channels in image"),nVal,_T("")); - psImageInfo->nNumChans = nVal; - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Image height"),nVal,_T("pixels")); - psImageInfo->nImageHeight = nVal; - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Image width"),nVal,_T("pixels")); - psImageInfo->nImageWidth = nVal; - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Depth"),nVal,_T("bits per pixel")); - psImageInfo->nDepthBpp = nVal; - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldEnum(nIndent,_T("Color mode"),BIM_T_ENUM_FILE_HDR_COL_MODE,nVal); - -} - -// Parse the Photoshop IRB Color Mode Section (from File Header) -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseColorModeSection(unsigned long &nPos,unsigned nIndent) -{ - CString strVal; - - PhotoshopParseReportNote(nIndent,_T("Color Mode Data Section:")); - nIndent++; - - unsigned nColModeLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Length"),nColModeLen,_T("")); - if (nColModeLen != 0) { - PhotoshopParseReportFldOffset(nIndent,_T("Color data"),nPos); - } - - // Skip data - nPos += nColModeLen; -} - -// ------------- - -// Parse the Photoshop IRB Layer and Mask Info Section (from File Header) -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// - pDibTemp = DIB for image display -// OUTPUT: -// - nPos = File position after reading the block -// -bool CDecodePs::PhotoshopParseLayerMaskInfo(unsigned long &nPos,unsigned nIndent,CDIB* pDibTemp) -{ - CString strVal; - bool bDecOk = true; - - PhotoshopParseReportNote(nIndent,_T("Layer and Mask Information Section:")); - nIndent++; - - unsigned nLayerMaskLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - unsigned long nPosStart = nPos; - unsigned long nPosEnd = nPosStart + nLayerMaskLen; - PhotoshopParseReportFldNum(nIndent,_T("Length"),nLayerMaskLen,_T("")); - if (nLayerMaskLen == 0) { - return true; - } - else { - if (bDecOk) - bDecOk &= PhotoshopParseLayerInfo(nPos,nIndent,pDibTemp); - if (bDecOk) - bDecOk &= PhotoshopParseGlobalLayerMaskInfo(nPos,nIndent); - if (bDecOk) { - //while ((bDecOk) && (nPos < nPosEnd)) { - //while ((bDecOk) && ((nPos+12) < nPosEnd)) { - while ((bDecOk) && (nPosStart+nLayerMaskLen-nPos > 12)) { - bDecOk &= PhotoshopParseAddtlLayerInfo(nPos,nIndent); - } - } - } - - if (bDecOk) { - // Skip data - nPos = nPosEnd; - } - - return bDecOk; -} - -// Parse the Photoshop IRB Layer Info Section -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// - pDibTemp = DIB for image display -// OUTPUT: -// - nPos = File position after reading the block -// -bool CDecodePs::PhotoshopParseLayerInfo(unsigned long &nPos,unsigned nIndent,CDIB* pDibTemp) -{ - CString strVal; - bool bDecOk = true; - - PhotoshopParseReportNote(nIndent,_T("Layer Info:")); - nIndent++; - - unsigned nLayerLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Length"),nLayerLen,_T("")); - if (nLayerLen == 0) { - return bDecOk; - } - - // Round up length to multiple of 2 - if (nLayerLen%2 != 0) { - nLayerLen++; - } - - // Save file position - unsigned nPosStart = nPos; - - // According to Adobe, "Layer count" is defined as follows: - // - If it is a negative number, its absolute value is the number of layers and the - // first alpha channel contains the transparency data for the merged result. - // Therefore, we'll treat it as signed short and take absolute value - unsigned short nLayerCountU = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - signed short nLayerCountS = (signed short)nLayerCountU; - unsigned nLayerCount = abs(nLayerCountS); - PhotoshopParseReportFldNum(nIndent,_T("Layer count"),nLayerCount,_T("")); - if (nLayerCountU & 0x8000) { - PhotoshopParseReportNote(nIndent,_T("First alpha channel contains transparency for merged result")); - } - - tsLayerAllInfo sLayerAllInfo; - sLayerAllInfo.nNumLayers = nLayerCount; - sLayerAllInfo.psLayers = new tsLayerInfo[nLayerCount]; - ASSERT(sLayerAllInfo.psLayers); - - for (unsigned nLayerInd=0;(bDecOk)&&(nLayerIndKill(); - - // Allocate the new DIB - bool bDibOk = pDibTemp->CreateDIB(nWidth,nHeight,32); - // Should only return false if already exists or failed to allocate - if (bDibOk) { - // Fetch the actual pixel array - pDibBits = (unsigned char*) ( pDibTemp->GetDIBBitArray() ); - } - } -#endif - - nPosLastLayer = nPos; - for (unsigned nChanInd=0;(bDecOk)&&(nChanIndAddLine(strLine); - PhotoshopParseReportNote(nIndent+1,strLine); - if (bDecOk) { - - // Fetch the channel ID to determine what RGB channel to map to - // - Layer 0 (background): 0->R, 1->G, 2->B - // - Layer n (other): 65535->A, 0->R, 1->G, 2->B - unsigned nChanID = sLayerAllInfo.psLayers[nLayerInd].pnChanID[nChanInd]; - - // Parse, and optionally paint the DIB - // NOTE: For uncompressed channels, the width & height generally appear to be zero - // According to the spec: - // If the compression code is 0, the image data is just the raw image data, - // whose size is calculated as (LayerBottom-LayerTop)* (LayerRight-LayerLeft) - - bDecOk &= PhotoshopParseChannelImageData(nPos,nIndent+1,nWidth,nHeight,nChanID,pDibBits); - } - strLine.Format(_T("CurPos @ 0x%08X, bDecOk=%u, LastLayer @ 0x%08X, LastChan @ 0x%08X"),nPos,bDecOk,nPosLastLayer,nPosLastChan); - //m_pLog->AddLine(strLine); - //PhotoshopParseReportNote(nIndent+1,strLine); - } - } - - // Pad out to specified length - signed nPad; - nPad = nPosStart + nLayerLen - nPos; - if (nPad > 0) { - nPos += nPad; - } - - // Deallocate - if (sLayerAllInfo.psLayers) { - for (unsigned nLayerInd=0;(nLayerIndBufRdAdv4(nPos,PS_BSWAP); - nRect2 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nRect3 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nRect4 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Rect Top"),nRect1,_T("")); - PhotoshopParseReportFldNum(nIndent,_T("Rect Left"),nRect2,_T("")); - PhotoshopParseReportFldNum(nIndent,_T("Rect Bottom"),nRect3,_T("")); - PhotoshopParseReportFldNum(nIndent,_T("Rect Right"),nRect4,_T("")); - - pLayerInfo->nHeight = nRect3-nRect1; - pLayerInfo->nWidth = nRect4-nRect2; - //nHeight = nRect3-nRect1; - - unsigned nNumChans = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Number of channels"),nNumChans,_T("")); - - //nChans = nNumChans; - pLayerInfo->nNumChans = nNumChans; - - ASSERT(pLayerInfo->pnChanLen == NULL); - pLayerInfo->pnChanLen = new unsigned [nNumChans]; - ASSERT(pLayerInfo->pnChanLen); - pLayerInfo->pnChanID = new unsigned [nNumChans]; - ASSERT(pLayerInfo->pnChanID); - - for (unsigned nChanInd=0;nChanIndBufRdAdv2(nPos,PS_BSWAP); - unsigned nChanDataLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - CString strField; - strField.Format(_T("Channel index #%u"),nChanInd); - strVal.Format(_T("ID=%5u DataLength=0x%08X"),nChanID,nChanDataLen); - PhotoshopParseReportFldStr(nIndent,strField,strVal); - pLayerInfo->pnChanID[nChanInd] = nChanID; - pLayerInfo->pnChanLen[nChanInd] = nChanDataLen; - } - CString strBlendModeSig = m_pWBuf->BufReadStrn(nPos,4); nPos+=4; - PhotoshopParseReportFldStr(nIndent,_T("Blend mode signature"),strBlendModeSig); - unsigned nBlendModeKey = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldEnum(nIndent,_T("Blend mode key"),BIM_T_ENUM_BLEND_MODE_KEY,nBlendModeKey); - unsigned nOpacity = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Opacity"),nOpacity,_T("(0=transparent ... 255=opaque)")); - m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); // unsigned nClipping - m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); // unsigned nFlags - m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); // unsigned nFiller - unsigned nExtraDataLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - unsigned long nPosExtra = nPos; - if (bDecOk) - bDecOk &= PhotoshopParseLayerMask(nPos,nIndent); - if (bDecOk) - bDecOk &= PhotoshopParseLayerBlendingRanges(nPos,nIndent); - - if (bDecOk) { - unsigned nLayerNameLen = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - CString strLayerName = m_pWBuf->BufReadStrn(nPos,nLayerNameLen); nPos+=nLayerNameLen; - // According to spec, length is padded to multiple of 4 bytes, - unsigned nSkip = 0; - nSkip = (4 - ((1 + nLayerNameLen) % 4)) %4; - nPos += nSkip; - } - - // Now use up the "extra bytes" with "Additional Layer Info" - while ((bDecOk)&&(nPos < nPosExtra + nExtraDataLen)) { - if (bDecOk) - bDecOk &= PhotoshopParseAddtlLayerInfo(nPos,nIndent); - } - - return bDecOk; -} - -// Parse the Photoshop IRB Layer Mask -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -bool CDecodePs::PhotoshopParseLayerMask(unsigned long &nPos,unsigned nIndent) -{ - CString strVal; - bool bDecOk = true; - - PhotoshopParseReportNote(nIndent,_T("Layer Mask / Adjustment layer data:")); - nIndent++; - - unsigned nLayerMaskLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - if (nLayerMaskLen == 0) { - return bDecOk; - } - - unsigned nRectA1,nRectA2,nRectA3,nRectA4; - unsigned nRectB1,nRectB2,nRectB3,nRectB4; - nRectA1 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nRectA2 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nRectA3 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nRectA4 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - - unsigned nTmp; - m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); // unsigned nDefaultColor - unsigned nFlags = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - - //FIXME: Is this correct? - if (nLayerMaskLen == 20) { - m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); // unsigned nPad - } - - if (nFlags & (1<<4)) { - unsigned nMaskParams = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - if (nMaskParams & (1<<0)) { - // User mask density, 1 byte - nTmp = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - } - if (nMaskParams & (1<<1)) { - // User mask feather, 8 bytes, double - nTmp = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nTmp = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - } - if (nMaskParams & (1<<2)) { - // Vector mask density, 1 byte - nTmp = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - } - if (nMaskParams & (1<<3)) { - // Vector mask feather, 8 bytes, double - nTmp = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nTmp = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - } - - m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); // unsigned nPadding - m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); // unsigned nRealFlags - m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); // unsigned nRealUserMaskBackground - nRectB1 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nRectB2 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nRectB3 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - nRectB4 = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - - } - - return bDecOk; -} - -// Parse the Photoshop IRB Layer blending ranges data -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -bool CDecodePs::PhotoshopParseLayerBlendingRanges(unsigned long &nPos,unsigned nIndent) -{ - CString strVal; - bool bDecOk = true; - - PhotoshopParseReportNote(nIndent,_T("Layer blending ranges data:")); - nIndent++; - - unsigned nLayerBlendLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - if (nLayerBlendLen == 0) { - return bDecOk; - } - - m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); // unsigned nCompGrayBlendSrc - m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); // unsigned nCompGrayBlendDstRng - unsigned nNumChans; - nNumChans = (nLayerBlendLen - 8) /8; - - for (unsigned nChanInd=0;nChanIndBufRdAdv4(nPos,PS_BSWAP); // unsigned nSrcRng - m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); // unsigned nDstRng - } - return bDecOk; -} - -// Parse the Photoshop IRB Channel image data -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// - nChan = Channel being parsed (used for DIB mapping) -// - pDibTemp = DIB for rendering (NULL if disabled) -// OUTPUT: -// - nPos = File position after reading the block -// -bool CDecodePs::PhotoshopParseChannelImageData(unsigned long &nPos,unsigned nIndent,unsigned nWidth,unsigned nHeight,unsigned nChan,unsigned char* pDibBits) -{ - bool bDecOk = true; - - unsigned nCompressionMethod = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent+1,_T("Compression method"),nCompressionMethod,_T("")); - - - if (nCompressionMethod == 1) { - // *** RLE Compression *** - if (nHeight == 0) { - return true; - } - // Read the line lengths into an array - // - LOOP [nHeight] - // - 16-bit: row length - // - ENDLOOP - unsigned* anRowLen; - anRowLen = new unsigned [nHeight]; - ASSERT(anRowLen); - for (unsigned nRow=0;nRowBufRdAdv2(nPos,PS_BSWAP); - } - - // Read the compressed data - for (unsigned nRow=0;(bDecOk)&&(nRowAddLineWarn(_T("Unsupported compression method. Stopping.")); - bDecOk = false; - return bDecOk; - } - - return bDecOk; -} - - -bool CDecodePs::PhotoshopDecodeRowUncomp(unsigned long &nPos,unsigned nWidth,unsigned nHeight,unsigned nRow,unsigned nChanID,unsigned char* pDibBits) -{ - bool bDecOk = true; - unsigned char nVal; - unsigned nRowActual; - unsigned nPixByte; - - for (unsigned nCol=0;(bDecOk)&&(nColBufRdAdv1(nPos,PS_BSWAP); - -#ifdef PS_IMG_DEC_EN - if (pDibBits) { - nRowActual = nHeight-nRow-1; // Need to flip vertical for DIB - nPixByte = (nRowActual*nWidth + nCol)*sizeof(RGBQUAD); - - // Assign the RGB pixel map - pDibBits[nPixByte+3] = 0; - if (nChanID == 0) { - pDibBits[nPixByte+2] = nVal; - } else if (nChanID == 1) { - pDibBits[nPixByte+1] = nVal; - } else if (nChanID == 2) { - pDibBits[nPixByte+0] = nVal; - } else { - } - } // pDibBits -#endif - - } // nCol - - - return bDecOk; -} - -bool CDecodePs::PhotoshopDecodeRowRle(unsigned long &nPos,unsigned nWidth,unsigned nHeight,unsigned nRow,unsigned nRowLen,unsigned nChanID,unsigned char* pDibBits) -{ - bool bDecOk = true; - - unsigned char nRleRun; - signed char nRleRunS; - unsigned nRleRunCnt; - unsigned char nRleVal; - unsigned nRowOffsetComp; // Row offset (compressed size) - unsigned nRowOffsetDecomp; // Row offset (decompressed size) - unsigned nRowOffsetDecompLast; - unsigned nRowActual; - unsigned nPixByte; - - // Decompress the row data - nRowOffsetComp = 0; - nRowOffsetDecomp = 0; - nRowOffsetDecompLast = 0; - while ((bDecOk)&&(nRowOffsetCompBufRdAdv1(nPos,PS_BSWAP); - nRleRunS = (signed char)(nRleRun); - nRowOffsetComp++; - - if (nRleRunS<0) { - // Replicate the next byte - nRleRunCnt = 1-nRleRunS; - nRleVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - nRowOffsetComp++; - nRowOffsetDecomp += nRleRunCnt; - -#ifdef PS_IMG_DEC_EN - if (pDibBits) { - nRowActual = nHeight-nRow-1; // Need to flip vertical for DIB - for (unsigned nRunInd=0;nRunIndBufRdAdv1(nPos,PS_BSWAP); - nRowOffsetComp++; - nRowOffsetDecomp++; - -#ifdef PS_IMG_DEC_EN - if (pDibBits) { - nRowActual = nHeight-nRow-1; // Need to flip vertical for DIB - nPixByte = (nRowActual*nWidth + nRowOffsetDecompLast+nRunInd)*sizeof(RGBQUAD); - - // Assign the RGB pixel map - pDibBits[nPixByte+3] = 0; - if (nChanID == 0) { - pDibBits[nPixByte+2] = nRleVal; - } else if (nChanID == 1) { - pDibBits[nPixByte+1] = nRleVal; - } else if (nChanID == 2) { - pDibBits[nPixByte+0] = nRleVal; - } else { - } - } // pDibBits -#endif - - } // nRunInd - } // nRleRunS - - } // nRowOffsetComp - - // Now that we've finished the row, compare the decompressed size - // to the expected width - if (nRowOffsetDecomp != nWidth) { - bDecOk = false; - ASSERT(false); - } - - return bDecOk; -} - -// Parse the Photoshop IRB Layer and Mask Info Section (from File Header) -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -// NOTE: -// - Image decoding (into DIB) is enabled if pDibBits is not NULL -// -bool CDecodePs::PhotoshopParseImageData(unsigned long &nPos,unsigned nIndent,tsImageInfo* psImageInfo,unsigned char* pDibBits) -{ - ASSERT(psImageInfo); - - CString strVal; - - //PhotoshopParseReportNote(nIndent,_T("Image data section:")); - PhotoshopParseReportFldOffset(nIndent,_T("Image data section:"),nPos); - - - bool bDecOk = true; - - //---- - unsigned nWidth = psImageInfo->nImageWidth; - unsigned nHeight = psImageInfo->nImageHeight; - unsigned nNumChans = psImageInfo->nNumChans; - //---- - - unsigned nCompressionMethod = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent+1,_T("Compression method"),nCompressionMethod,_T("")); - - // ----------------------------------------------------- - - if (nCompressionMethod == 1) { - // *** RLE Compression *** - if (nHeight == 0) { - return true; - } - - // Read the line lengths into an array - // - LOOP [nNumChans] - // - LOOP [nHeight] - // - 16-bit: row length - // - ENDLOOP - // - ENDLOOP - unsigned* anRowLen; - anRowLen = new unsigned [nNumChans*nHeight]; - ASSERT(anRowLen); - for (unsigned nRow=0;nRow<(nNumChans*nHeight);nRow++) { - anRowLen[nRow] = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - } - - // Read the compressed data - for (unsigned nChan=0;nChanAddLineWarn(_T("Unsupported compression method. Stopping.")); - bDecOk = false; - return bDecOk; - } - - - return bDecOk; - -} - -// Parse the Photoshop IRB Global layer mask info -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -bool CDecodePs::PhotoshopParseGlobalLayerMaskInfo(unsigned long &nPos,unsigned nIndent) -{ - CString strVal; - bool bDecOk = true; - - PhotoshopParseReportNote(nIndent,_T("Global layer mask info:")); - nIndent++; - - unsigned nInfoLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - if (nInfoLen == 0) { - return bDecOk; - } - unsigned long nPosStart = nPos; - m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); // unsigned nOverlayColorSpace - m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); // unsigned nColComp1 - m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); // unsigned nColComp2 - m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); // unsigned nColComp3 - m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); // unsigned nColComp4 - m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); // unsigned nOpacity - m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); // unsigned nKind - - // Variable Filler: zeros - //nPos += nInfoLen - 17; - nPos = nPosStart + nInfoLen; - - return bDecOk; -} - -// Parse the Photoshop IRB Additional layer info -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -bool CDecodePs::PhotoshopParseAddtlLayerInfo(unsigned long &nPos,unsigned nIndent) -{ - bool bDecOk = true; - unsigned long nPosStart; - - PhotoshopParseReportNote(nIndent,_T("Additional layer info:")); - nIndent++; - - CString strSig = m_pWBuf->BufReadStrn(nPos,4); nPos+=4; - - if (strSig != _T("8BIM")) { - // Signature did not match! - CString strError; - strError.Format(_T("ERROR: Addtl Layer Info signature unknown [%s] @ 0x%08X"),(LPCTSTR)strSig,nPos-4); - PhotoshopParseReportNote(nIndent,strError); - -#ifdef DEBUG_LOG - CString strDebug; - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("PsDecode"),(LPCTSTR)strError); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - bDecOk = false; - return false; - } - - CString strKey = m_pWBuf->BufReadStrn(nPos,4); nPos+=4; - PhotoshopParseReportFldStr(nIndent,_T("Key"),strKey); - bool bLen8B = false; - if (strKey == _T("Lr16")) { - // FIXME: Might need some additional processing here? - ASSERT(false); - } - /* - //CAL! FIXME: Empirically, I didn't see 8B length being used by "FMsk" in psd-flame-icon.psd @ 0x7A458 - if (strKey == _T("LMsk")) { bLen8B = true; } - if (strKey == _T("Lr16")) { bLen8B = true; } - if (strKey == _T("Lr32")) { bLen8B = true; } - if (strKey == _T("Layr")) { bLen8B = true; } - if (strKey == _T("Mt16")) { bLen8B = true; } - if (strKey == _T("Mt32")) { bLen8B = true; } - if (strKey == _T("Mtrn")) { bLen8B = true; } - if (strKey == _T("Alph")) { bLen8B = true; } - if (strKey == _T("FMsk")) { bLen8B = true; } - if (strKey == _T("lnk2")) { bLen8B = true; } - if (strKey == _T("FEid")) { bLen8B = true; } - if (strKey == _T("FXid")) { bLen8B = true; } - if (strKey == _T("PxSD")) { bLen8B = true; } - */ - - unsigned nLen; - if (!bLen8B) { - nLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - } else { - // DUMMY for now - //FIXME: Untested - nLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - ASSERT(nLen == 0); - nLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - } - PhotoshopParseReportFldNum(nIndent,_T("Length"),nLen,_T("")); - if (nLen > 0) { - PhotoshopParseReportFldHex(nIndent,strKey,nPos,nLen); - } - - unsigned nVal; - CString sStr; - unsigned nPosOffset = 0; - if (strKey == _T("luni")) { - sStr = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); - PhotoshopParseReportFldStr(nIndent,_T("Layer Name (Unicode)"),sStr); - } else if (strKey == _T("lnsr")) { - nVal = m_pWBuf->BufX(nPos,4,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Layer Name Source ID"),nVal,_T("")); - } else if (strKey == _T("lyid")) { - nVal = m_pWBuf->BufX(nPos,4,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Layer ID"),nVal,_T("")); - } else if (strKey == _T("clbl")) { - nVal = m_pWBuf->BufX(nPos,4,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Blend clipped elements"),nVal); - } else if (strKey == _T("infx")) { - nVal = m_pWBuf->BufX(nPos,4,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Blend interior elements"),nVal); - } else if (strKey == _T("knko")) { - nVal = m_pWBuf->BufX(nPos,4,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Knockout"),nVal); - } - - nPosStart = nPos; - - // Skip data - nPos = nPosStart + nLen; - - // FIXME: It appears that we need to pad out to ensure that - // length is multiple of 4 (not file position). - unsigned nMod; - nMod = (nLen%4); - if (nMod != 0) { - nPos += (4-nMod); - } - - - return bDecOk; -} - - - -// ------------- - - -// Parse the Photoshop IRB Image Resources Section -// - Iteratively works through the individual Image Resource Blocks (IRB) -// -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -bool CDecodePs::PhotoshopParseImageResourcesSection(unsigned long &nPos,unsigned nIndent) -{ - CString strVal; - bool bDecOk = true; - - PhotoshopParseReportNote(nIndent,_T("Image Resources Section:")); - nIndent++; - - unsigned long nPosSectionStart = 0; - unsigned long nPosSectionEnd = 0; - - unsigned nImgResLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Length"),nImgResLen,_T("")); - - nPosSectionStart = nPos; - nPosSectionEnd = nPos + nImgResLen; - - while (nPos < nPosSectionEnd) { - bDecOk &= PhotoshopParseImageResourceBlock(nPos,nIndent); - if (!bDecOk) { return false; } - } - return bDecOk; -} - -// Parse the Photoshop IRB (Image Resource Block) -// - Decode the 8BIM ID and invoke the appropriate IRB parsing handler -// -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -bool CDecodePs::PhotoshopParseImageResourceBlock(unsigned long &nPos,unsigned nIndent) -{ - CString strVal; - //bool bDecOk = true; - - //PhotoshopParseReportNote(nIndent,_T("Image Resource Block:")); - //nIndent++; - - // - // - Signature (4B) "8BIM" - // - NameLen (2B) Generally 0 - // - Name (NameLen Bytes, min 1 Byte) Usually empty (NULL) - // - BimLen (4B) Length of 8BIM data - // - Data (1..BimLen) Field data - // - - CString strSig = m_pWBuf->BufReadStrn(nPos,4); nPos+=4; - - if (strSig != _T("8BIM")) { - // Signature did not match! - CString strError; - strError.Format(_T("ERROR: IRB signature unknown [%s]"),(LPCTSTR)strSig); - PhotoshopParseReportNote(nIndent,strError); - -#ifdef DEBUG_LOG - CString strDebug; - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("PsDecode"),(LPCTSTR)strError); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - - return false;; - } - - unsigned nBimId = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - - unsigned nResNameLen = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - CString strResName = m_pWBuf->BufReadStrn(nPos,nResNameLen); nPos+=nResNameLen; - - // If size wasn't even, pad here - if ((1+nResNameLen)%2!=0) { - nPos+=1; - } - unsigned nBimLen = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - - CString strTmp; - CString strBimName; - CString strByte; - - // Lookup 8BIM defined name - CString strBimDefName = _T(""); - bool bBimKnown = false; - unsigned nFldInd = 0; - bBimKnown = FindBimRecord(nBimId,nFldInd); - - if (bBimKnown) { - strBimDefName = asBimRecords[nFldInd].strRecordName; - } - - strTmp.Format(_T("8BIM: [0x%04X] Name=\"%s\" Len=[0x%04X] DefinedName=\"%s\""), - nBimId,(LPCTSTR)strBimName,nBimLen,(LPCTSTR)strBimDefName); - PhotoshopParseReportNote(nIndent,strTmp); - - nIndent++; - - if (nBimLen == 0) { - // If length is zero, then skip this block - PhotoshopParseReportNote(nIndent,_T("Length is zero. Skipping.")); - - } else if (bBimKnown) { - - // Save the file pointer - unsigned nPosSaved; - nPosSaved = nPos; - - // Calculate the end of the record - // - This is used for parsing records that have a conditional parsing - // of additional fields "if length permits". - unsigned nPosEnd; - nPosEnd = nPos + nBimLen - 1; - - switch (asBimRecords[nFldInd].eBimType) { - - case BIM_T_STR: - strVal = DecodeIptcValue(IPTC_T_STR,nBimLen,nPos); - PhotoshopParseReportFldStr(nIndent,strBimDefName,strVal); - break; - case BIM_T_HEX: - PhotoshopParseReportFldHex(nIndent,strBimDefName,nPos,nBimLen); - nPos += nBimLen; - break; - - - case BIM_T_PS_THUMB_RES: - PhotoshopParseThumbnailResource(nPos,nIndent); - // Since this block has image data that we are not going to parse, - // force the end position to match the length - nPos = nPosSaved + nBimLen; - break; - case BIM_T_PS_SLICES: - PhotoshopParseSliceHeader(nPos,nIndent,nPosEnd); - break; - case BIM_T_PS_DESCRIPTOR: - PhotoshopParseDescriptor(nPos,nIndent); - break; - case BIM_T_PS_VER_INFO: - PhotoshopParseVersionInfo(nPos,nIndent); - break; - case BIM_T_PS_PRINT_SCALE: - PhotoshopParsePrintScale(nPos,nIndent); - break; - case BIM_T_PS_PIXEL_ASPECT_RATIO: - PhotoshopParsePixelAspectRatio(nPos,nIndent); - break; - case BIM_T_PS_DOC_SPECIFIC_SEED: - PhotoshopParseDocSpecificSeed(nPos,nIndent); - break; - case BIM_T_PS_RESOLUTION_INFO: - PhotoshopParseResolutionInfo(nPos,nIndent); - break; - case BIM_T_PS_GRID_GUIDES: - PhotoshopParseGridGuides(nPos,nIndent); - break; - case BIM_T_PS_GLOBAL_ANGLE: - PhotoshopParseGlobalAngle(nPos,nIndent); - break; - case BIM_T_PS_GLOBAL_ALTITUDE: - PhotoshopParseGlobalAltitude(nPos,nIndent); - break; - case BIM_T_PS_PRINT_FLAGS: - PhotoshopParsePrintFlags(nPos,nIndent); - break; - case BIM_T_PS_PRINT_FLAGS_INFO: - PhotoshopParsePrintFlagsInfo(nPos,nIndent); - break; - case BIM_T_PS_COPYRIGHT_FLAG: - PhotoshopParseCopyrightFlag(nPos,nIndent); - break; - case BIM_T_PS_LAYER_STATE_INFO: - PhotoshopParseLayerStateInfo(nPos,nIndent); - break; - case BIM_T_PS_LAYER_GROUP_INFO: - PhotoshopParseLayerGroupInfo(nPos,nIndent,nBimLen); - break; - case BIM_T_PS_LAYER_GROUP_ENABLED: - PhotoshopParseLayerGroupEnabled(nPos,nIndent,nBimLen); - break; - case BIM_T_PS_LAYER_SELECT_ID: - PhotoshopParseLayerSelectId(nPos,nIndent); - break; - - case BIM_T_PS_STR_UNI: - PhotoshopParseStringUni(nPos,nIndent); - break; - case BIM_T_PS_STR_ASC: - strVal += m_pWBuf->BufReadStrn(nPos,nBimLen); - nPos += nBimLen; - PhotoshopParseReportFldStr(nIndent,strBimDefName,strVal); - break; - case BIM_T_PS_STR_ASC_LONG: - strVal = _T("\n"); - strVal += m_pWBuf->BufReadStrn(nPos,nBimLen); - nPos += nBimLen; - PhotoshopParseReportFldStr(nIndent,strBimDefName,strVal); - break; - - case BIM_T_JPEG_QUAL: // (0x0406) - // JPEG Quality - PhotoshopParseJpegQuality(nPos,nIndent,nPosEnd); - break; - - case BIM_T_IPTC_NAA: // (0x0404) - // IPTC-NAA - DecodeIptc(nPos,nBimLen,nIndent); - break; - - default: - return false; - break; - } // switch - - // Check to see if we ended up with a length mismatch after decoding - if (nPos > nPosEnd+1) { - // Length mismatch detected: we read too much (versus length) - strTmp.Format(_T("ERROR: Parsing exceeded expected length. Stopping decode. BIM=[%s], CurPos=[0x%08X], ExpPosEnd=[0x%08X], ExpLen=[%u]"), - (LPCTSTR)strBimDefName,nPos,nPosEnd+1,nBimLen); - m_pLog->AddLineErr(strTmp); -#ifdef DEBUG_LOG - CString strDebug; - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("PsDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - - // TODO: Add interactive error message here - - // Now we should roll-back the file position to the position indicated - // by the length. This will help us stay on track for next decoding. - nPos = nPosEnd+1; - - return false; - } else if (nPos != nPosEnd+1) { - // Length mismatch detected: we read too little (versus length) - // This is generally an indication that either I haven't accurately captured the - // specific block parsing format or else the specification is loose. - strTmp.Format(_T("WARNING: Parsing offset length mismatch. Current pos=[0x%08X], expected end pos=[0x%08X], expect length=[%u]"), - nPos,nPosEnd+1,nBimLen); - m_pLog->AddLineWarn(strTmp); -#ifdef DEBUG_LOG - CString strDebug; - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("PsDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#endif - return false; - } - - // Reset the file marker - nPos = nPosSaved; - } // bBimKnown - - // Skip rest of 8BIM - nPos += nBimLen; - - // FIXME: correct to make for even parity? - if ((nBimLen % 2) != 0) nPos++; - - return true; -} - - -// Parse the Photoshop IRB Slice Header -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// - nPosEnd = File position at end of block (last byte address) -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseSliceHeader(unsigned long &nPos,unsigned nIndent,unsigned long nPosEnd) -{ - unsigned nVal; - CString strVal; - unsigned nPosOffset; - - PhotoshopParseReportNote(nIndent,_T("Slice Header:")); - nIndent++; - - unsigned nSliceVer = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Version"),nSliceVer,_T("")); - - if (nSliceVer == 6) { - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Bound Rect (top)"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Bound Rect (left)"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Bound Rect (bottom)"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Bound Rect (right)"),nVal,_T("")); - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); - nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("Name of group of slices"),strVal); - unsigned nNumSlices = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Number of slices"),nNumSlices,_T("")); - - // Slice resource block - if (nNumSlices>0) - PhotoshopParseReportNote(nIndent,_T("-----")); - for (unsigned nSliceInd=0;nSliceInd0) - PhotoshopParseReportNote(nIndent,_T("-----")); - - } else if ((nSliceVer == 7) || (nSliceVer == 8)) { - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Descriptor version"),nVal,_T("")); - PhotoshopParseDescriptor(nPos,nIndent); - } - - -} - -// Parse the Photoshop IRB Slice Resource -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// - nPosEnd = File position at end of block (last byte address) -// OUTPUT: -// - nPos = File position after reading the block -// NOTE: -// - The nPosEnd is supplied as this resource block depends on some -// conditional field parsing that is "as length allows" -// -void CDecodePs::PhotoshopParseSliceResource(unsigned long &nPos,unsigned nIndent,unsigned long nPosEnd) -{ - unsigned nVal; - CString strVal; - unsigned nPosOffset; - - PhotoshopParseReportNote(nIndent,_T("Slice Resource:")); - nIndent++; - - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("ID"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Group ID"),nVal,_T("")); - unsigned nOrigin = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Origin"),nOrigin,_T("")); - if (nOrigin==1) { - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Associated Layer ID"),nVal,_T("")); - } - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("Name"),strVal); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Type"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Position (top)"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Position (left)"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Position (bottom)"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Position (right)"),nVal,_T("")); - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("URL"),strVal); - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("Target"),strVal); - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("Message"),strVal); - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("Alt Tag"),strVal); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Cell text is HTML"),nVal); - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("Cell text"),strVal); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Horizontal alignment"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Vertical alignment"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Alpha color"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Red"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Green"),nVal,_T("")); - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Blue"),nVal,_T("")); - - // Per standard, we are only supposed to parse additional fields - // "as length allows". This is not a particularly good format - // definition. At this point we'll perform a check to see if - // we have exhausted the length of the block. If not, continue - // to parse the next fields. - // TODO: Do we need to be any more precise than this? (ie. check - // after reading the descriptor version?) - if (nPos <= nPosEnd) { - - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Descriptor version"),nVal,_T("")); - - PhotoshopParseDescriptor(nPos,nIndent); - } else { - // We ran out of space in the block so end now - } -} - - -// Parse the Photoshop IRB JPEG Quality -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// - nPosEnd = File position at end of block (last byte address) -// OUTPUT: -// - nPos = File position after reading the block -// NOTE: -// - This IRB is private, so reverse-engineered and may not be per spec -// -void CDecodePs::PhotoshopParseJpegQuality(unsigned long &nPos,unsigned nIndent,unsigned long nPosEnd) -{ - nPosEnd; // Unreferenced param - - unsigned nVal; - CString strVal; - unsigned nSaveFormat; - - // Save As Quality - // Index 0: Quality level - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - switch(nVal) { - case 0xFFFD: m_nQualitySaveAs = 1; break; - case 0xFFFE: m_nQualitySaveAs = 2; break; - case 0xFFFF: m_nQualitySaveAs = 3; break; - case 0x0000: m_nQualitySaveAs = 4; break; - case 0x0001: m_nQualitySaveAs = 5; break; - case 0x0002: m_nQualitySaveAs = 6; break; - case 0x0003: m_nQualitySaveAs = 7; break; - case 0x0004: m_nQualitySaveAs = 8; break; - case 0x0005: m_nQualitySaveAs = 9; break; - case 0x0006: m_nQualitySaveAs = 10; break; - case 0x0007: m_nQualitySaveAs = 11; break; - case 0x0008: m_nQualitySaveAs = 12; break; - default: m_nQualitySaveAs = 0; break; - } - if (m_nQualitySaveAs != 0) { - PhotoshopParseReportFldNum(nIndent,_T("Photoshop Save As Quality"),m_nQualitySaveAs,_T("")); - } - - // TODO: I have observed a file that had this block with length=2, which would end here - // - Perhaps we should check against length in case some older files had a shorter format - // to this IRB? - - // Index 1: Format - nSaveFormat = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - switch(nSaveFormat) { - case 0x0000: strVal = _T("Standard"); break; - case 0x0001: strVal = _T("Optimized"); break; - case 0x0101: strVal = _T("Progressive"); break; - default: strVal = _T("???"); break; - } - PhotoshopParseReportFldStr(nIndent,_T("Photoshop Save Format"),strVal); - - // Index 2: Progressive Scans - // - Only meaningful if Progressive mode - nVal = m_pWBuf->BufRdAdv2(nPos,PS_BSWAP); - switch(nVal) { - case 0x0001: strVal = _T("3 Scans"); break; - case 0x0002: strVal = _T("4 Scans"); break; - case 0x0003: strVal = _T("5 Scans"); break; - default: strVal = _T("???"); break; - } - PhotoshopParseReportFldStr(nIndent,_T("Photoshop Save Progressive Scans"),strVal); - - // Not sure what this byte is for - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("???"),nVal,_T("")); - -} - -// Decode the OSType field and invoke the appropriate IRB parsing handler -// -// INPUT: -// - nPos = File position at start of block -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the block -// -void CDecodePs::PhotoshopParseHandleOsType(CString strOsType,unsigned long &nPos,unsigned nIndent) -{ - if (strOsType==_T("obj ")) { - //PhotoshopParseReference(nPos,nIndent); - } else if (strOsType==_T("Objc")) { - PhotoshopParseDescriptor(nPos,nIndent); - } else if (strOsType==_T("VlLs")) { - PhotoshopParseList(nPos,nIndent); - } else if (strOsType==_T("doub")) { - //PhotoshopParseDouble(nPos,nIndent); - } else if (strOsType==_T("UntF")) { - //PhotoshopParseUnitFloat(nPos,nIndent); - } else if (strOsType==_T("TEXT")) { - PhotoshopParseStringUni(nPos,nIndent); - } else if (strOsType==_T("enum")) { - PhotoshopParseEnum(nPos,nIndent); - } else if (strOsType==_T("long")) { - PhotoshopParseInteger(nPos,nIndent); - } else if (strOsType==_T("bool")) { - PhotoshopParseBool(nPos,nIndent); - } else if (strOsType==_T("GlbO")) { - PhotoshopParseDescriptor(nPos,nIndent); - } else if (strOsType==_T("type")) { - //PhotoshopParseClass(nPos,nIndent); - } else if (strOsType==_T("GlbC")) { - //PhotoshopParseClass(nPos,nIndent); - } else if (strOsType==_T("alis")) { - //PhotoshopParseAlias(nPos,nIndent); - } else if (strOsType==_T("tdta")) { - //PhotoshopParseRawData(nPos,nIndent); - } else { - -#ifdef DEBUG_LOG - CString strError; - CString strDebug; - strError.Format(_T("ERROR: Unsupported OSType [%s]"),(LPCTSTR)strOsType); - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("PsDecode"),(LPCTSTR)strError); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - - } -} - -// Parse the Photoshop IRB OSType Descriptor -// INPUT: -// - nPos = File position at start of entry -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the entry -// -void CDecodePs::PhotoshopParseDescriptor(unsigned long &nPos,unsigned nIndent) -{ - CString strVal; - unsigned nPosOffset; - - PhotoshopParseReportNote(nIndent,_T("Descriptor:")); - nIndent++; - - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("Name from classID"),strVal); - - strVal = PhotoshopParseGetLStrAsc(nPos); - PhotoshopParseReportFldStr(nIndent,_T("classID"),strVal); - - unsigned nDescNumItems = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Num items in descriptor"),nDescNumItems,_T("")); - - if (nDescNumItems>0) - PhotoshopParseReportNote(nIndent,_T("-----")); - for (unsigned nDescInd=0;nDescInd0) - PhotoshopParseReportNote(nIndent,_T("-----")); -} - -// Parse the Photoshop IRB OSType List -// INPUT: -// - nPos = File position at start of entry -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the entry -// -void CDecodePs::PhotoshopParseList(unsigned long &nPos,unsigned nIndent) -{ - CString strVal; - CString strLine; - - unsigned nNumItems = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Num items in list"),nNumItems,_T("")); - - if (nNumItems>0) - PhotoshopParseReportNote(nIndent,_T("-----")); - for (unsigned nItemInd=0;nItemInd0) - PhotoshopParseReportNote(nIndent,_T("-----")); -} - -// Parse the Photoshop IRB OSType Integer -// INPUT: -// - nPos = File position at start of entry -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the entry -// -void CDecodePs::PhotoshopParseInteger(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - CString strLine; - nVal = m_pWBuf->BufRdAdv4(nPos,PS_BSWAP); - PhotoshopParseReportFldNum(nIndent,_T("Value"),nVal,_T("")); -} - -// Parse the Photoshop IRB OSType Boolean -// INPUT: -// - nPos = File position at start of entry -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the entry -// -void CDecodePs::PhotoshopParseBool(unsigned long &nPos,unsigned nIndent) -{ - unsigned nVal; - CString strVal; - CString strLine; - nVal = m_pWBuf->BufRdAdv1(nPos,PS_BSWAP); - PhotoshopParseReportFldBool(nIndent,_T("Value"),nVal); -} - -// Parse the Photoshop IRB OSType Enumerated type -// INPUT: -// - nPos = File position at start of entry -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the entry -// -void CDecodePs::PhotoshopParseEnum(unsigned long &nPos,unsigned nIndent) -{ - CString strVal; - CString strLine; - - strVal = PhotoshopParseGetLStrAsc(nPos); - PhotoshopParseReportFldStr(nIndent,_T("Type"),strVal); - - strVal = PhotoshopParseGetLStrAsc(nPos); - PhotoshopParseReportFldStr(nIndent,_T("Enum"),strVal); - -} - -// Parse the Photoshop IRB Unicode String -// INPUT: -// - nPos = File position at start of entry -// - nIndent = Indent level for formatted output -// OUTPUT: -// - nPos = File position after reading the entry -// NOTE: -// - The string is in Photoshop Unicode format (length first) -// -void CDecodePs::PhotoshopParseStringUni(unsigned long &nPos,unsigned nIndent) -{ - CString strVal; - unsigned nPosOffset; - - strVal = PhotoshopParseGetBimLStrUni(nPos,nPosOffset); nPos+=nPosOffset; - PhotoshopParseReportFldStr(nIndent,_T("String"),strVal); -} - - -// =============================================================================== -// CONSTANTS -// =============================================================================== - - -// Define all of the currently-known IPTC fields, used when we -// parse the APP13 marker -// -// - Reference: IPTC-NAA Information Interchange Model Version 4 -// - See header for struct encoding -struct tsIptcField asIptcFields[] = -{ - { 1, 0,IPTC_T_NUM2, _T("Model Version")}, - { 1, 5,IPTC_T_STR, _T("Destination")}, - { 1, 20,IPTC_T_NUM2, _T("File Format")}, - { 1, 22,IPTC_T_NUM2, _T("File Format Version")}, - { 1, 30,IPTC_T_STR, _T("Service Identifier")}, - { 1, 40,IPTC_T_STR, _T("Envelope Number")}, - { 1, 50,IPTC_T_STR, _T("Product I.D.")}, - { 1, 60,IPTC_T_STR, _T("Envelope Priority")}, - { 1, 70,IPTC_T_STR, _T("Date Sent")}, - { 1, 80,IPTC_T_STR, _T("Time Sent")}, - { 1, 90,IPTC_T_STR, _T("Coded Character Set")}, - { 1,100,IPTC_T_STR, _T("UNO")}, - { 1,120,IPTC_T_NUM2, _T("ARM Identifier")}, - { 1,122,IPTC_T_NUM2, _T("ARM Version")}, - { 2, 0,IPTC_T_NUM2, _T("Record Version")}, - { 2, 3,IPTC_T_STR, _T("Object Type Reference")}, - { 2, 4,IPTC_T_STR, _T("Object Attrib Reference")}, - { 2, 5,IPTC_T_STR, _T("Object Name")}, - { 2, 7,IPTC_T_STR, _T("Edit Status")}, - { 2, 8,IPTC_T_STR, _T("Editorial Update")}, - { 2, 10,IPTC_T_STR, _T("Urgency")}, - { 2, 12,IPTC_T_STR, _T("Subject Reference")}, - { 2, 15,IPTC_T_STR, _T("Category")}, - { 2, 20,IPTC_T_STR, _T("Supplemental Category")}, - { 2, 22,IPTC_T_STR, _T("Fixture Identifier")}, - { 2, 25,IPTC_T_STR, _T("Keywords")}, - { 2, 26,IPTC_T_STR, _T("Content Location Code")}, - { 2, 27,IPTC_T_STR, _T("Content Location Name")}, - { 2, 30,IPTC_T_STR, _T("Release Date")}, - { 2, 35,IPTC_T_STR, _T("Release Time")}, - { 2, 37,IPTC_T_STR, _T("Expiration Date")}, - { 2, 38,IPTC_T_STR, _T("Expiration Time")}, - { 2, 40,IPTC_T_STR, _T("Special Instructions")}, - { 2, 42,IPTC_T_STR, _T("Action Advised")}, - { 2, 45,IPTC_T_UNK, _T("Reference Service")}, - { 2, 47,IPTC_T_UNK, _T("Reference Date")}, - { 2, 50,IPTC_T_UNK, _T("Reference Number")}, - { 2, 55,IPTC_T_STR, _T("Date Created")}, - { 2, 60,IPTC_T_STR, _T("Time Created")}, - { 2, 62,IPTC_T_STR, _T("Digital Creation Date")}, - { 2, 63,IPTC_T_STR, _T("Digital Creation Time")}, - { 2, 65,IPTC_T_STR, _T("Originating Program")}, - { 2, 70,IPTC_T_STR, _T("Program Version")}, - { 2, 75,IPTC_T_STR, _T("Object Cycle")}, - { 2, 80,IPTC_T_STR, _T("By-line")}, - { 2, 85,IPTC_T_STR, _T("By-line Title")}, - { 2, 90,IPTC_T_STR, _T("City")}, - { 2, 92,IPTC_T_STR, _T("Sub-location")}, - { 2, 95,IPTC_T_STR, _T("Province/State")}, - { 2,100,IPTC_T_STR, _T("Country/Primary Location Code")}, - { 2,101,IPTC_T_STR, _T("Country/Primary Location Name")}, - { 2,103,IPTC_T_STR, _T("Original Transmission Reference")}, - { 2,105,IPTC_T_STR, _T("Headline")}, - { 2,110,IPTC_T_STR, _T("Credit")}, - { 2,115,IPTC_T_STR, _T("Source")}, - { 2,116,IPTC_T_STR, _T("Copyright Notice")}, - { 2,118,IPTC_T_STR, _T("Contact")}, - { 2,120,IPTC_T_STR, _T("Caption/Abstract")}, - { 2,122,IPTC_T_STR, _T("Writer/Editor")}, - { 2,125,IPTC_T_UNK, _T("Rasterized Caption")}, - { 2,130,IPTC_T_STR, _T("Image Type")}, - { 2,131,IPTC_T_STR, _T("Image Orientation")}, - { 2,135,IPTC_T_STR, _T("Language Identifier")}, - { 2,150,IPTC_T_STR, _T("Audio Type")}, - { 2,151,IPTC_T_STR, _T("Audio Sampling Rate")}, - { 2,152,IPTC_T_STR, _T("Audio Sampling Resolution")}, - { 2,153,IPTC_T_STR, _T("Audio Duration")}, - { 2,154,IPTC_T_STR, _T("Audio Outcue")}, - { 2,200,IPTC_T_NUM2, _T("ObjectData Preview File Format")}, - { 2,201,IPTC_T_NUM2, _T("ObjectData Preview File Format Version")}, - { 2,202,IPTC_T_UNK, _T("ObjectData Preview Data")}, - { 7, 10,IPTC_T_NUM1, _T("Size Mode")}, - { 7, 20,IPTC_T_NUM, _T("Max Subfile Size")}, - { 7, 90,IPTC_T_NUM1, _T("ObjectData Size Announced")}, - { 7, 95,IPTC_T_NUM, _T("Maximum ObjectData Size")}, - { 8, 10,IPTC_T_UNK, _T("Subfile")}, - { 9, 10,IPTC_T_NUM, _T("Confirmed ObjectData Size")}, - { 0, 0,IPTC_T_END, _T("DONE")}, -}; - - - -// Adobe Photoshop File Formats Specification (October 2013) -// - Image Resource Blocks IRB (8BIM) -// - See header for struct encoding -struct tsBimRecord asBimRecords[] = -{ - { 0x03E8, 0x0000, BIM_T_UNK, _T("-")}, - { 0x03E9, 0x0000, BIM_T_HEX, _T("Macintosh print manager print info record")}, - { 0x03EB, 0x0000, BIM_T_HEX, _T("Indexed color table")}, - { 0x03ED, 0x0000, BIM_T_PS_RESOLUTION_INFO, _T("ResolutionInfo structure")}, - { 0x03EE, 0x0000, BIM_T_HEX, _T("Names of alpha channels")}, - { 0x03EF, 0x0000, BIM_T_HEX, _T("DisplayInfo structure")}, - { 0x03F0, 0x0000, BIM_T_HEX, _T("Caption")}, - { 0x03F1, 0x0000, BIM_T_HEX, _T("Border information")}, - { 0x03F2, 0x0000, BIM_T_HEX, _T("Background color")}, - { 0x03F3, 0x0000, BIM_T_PS_PRINT_FLAGS, _T("Print flags")}, - { 0x03F4, 0x0000, BIM_T_HEX, _T("Grayscale and multichannel halftoning information")}, - { 0x03F5, 0x0000, BIM_T_HEX, _T("Color halftoning information")}, - { 0x03F6, 0x0000, BIM_T_HEX, _T("Duotone halftoning information")}, - { 0x03F7, 0x0000, BIM_T_HEX, _T("Grayscale and multichannel transfer function")}, - { 0x03F8, 0x0000, BIM_T_HEX, _T("Color transfer functions")}, - { 0x03F9, 0x0000, BIM_T_HEX, _T("Duotone transfer functions")}, - { 0x03FA, 0x0000, BIM_T_HEX, _T("Duotone image information")}, - { 0x03FC, 0x0000, BIM_T_HEX, _T("-")}, - { 0x03FD, 0x0000, BIM_T_HEX, _T("EPS options")}, - { 0x03FE, 0x0000, BIM_T_HEX, _T("Quick Mask information")}, - { 0x03FF, 0x0000, BIM_T_HEX, _T("-")}, - { 0x0400, 0x0000, BIM_T_PS_LAYER_STATE_INFO, _T("Layer state information")}, - { 0x0401, 0x0000, BIM_T_HEX, _T("Working path")}, - { 0x0402, 0x0000, BIM_T_PS_LAYER_GROUP_INFO, _T("Layers group information")}, - { 0x0403, 0x0000, BIM_T_HEX, _T("-")}, - { 0x0404, 0x0000, BIM_T_IPTC_NAA, _T("IPTC-NAA record")}, - { 0x0405, 0x0000, BIM_T_HEX, _T("Image mode (raw format files)")}, - { 0x0406, 0x0000, BIM_T_JPEG_QUAL, _T("JPEG quality")}, - { 0x0408, 0x0000, BIM_T_PS_GRID_GUIDES, _T("Grid and guides information")}, - { 0x0409, 0x0000, BIM_T_HEX, _T("Thumbnail resource (PS 4.0)")}, - { 0x040A, 0x0000, BIM_T_PS_COPYRIGHT_FLAG, _T("Copyright flag")}, - { 0x040B, 0x0000, BIM_T_HEX, _T("URL")}, - { 0x040C, 0x0000, BIM_T_PS_THUMB_RES, _T("Thumbnail resources")}, - { 0x040D, 0x0000, BIM_T_PS_GLOBAL_ANGLE, _T("Global Angle")}, - { 0x040E, 0x0000, BIM_T_HEX, _T("Color samplers resource")}, - { 0x040F, 0x0000, BIM_T_HEX, _T("ICC Profile")}, - { 0x0410, 0x0000, BIM_T_HEX, _T("Watermark")}, - { 0x0411, 0x0000, BIM_T_HEX, _T("ICC Untagged Profile")}, - { 0x0412, 0x0000, BIM_T_HEX, _T("Effects visible")}, - { 0x0413, 0x0000, BIM_T_HEX, _T("Spot Halftone")}, - { 0x0414, 0x0000, BIM_T_PS_DOC_SPECIFIC_SEED, _T("Document-specific IDs seed number")}, - { 0x0415, 0x0000, BIM_T_PS_STR_UNI, _T("Unicode Alpha Names")}, - { 0x0416, 0x0000, BIM_T_HEX, _T("Indexed Color Table Count")}, - { 0x0417, 0x0000, BIM_T_HEX, _T("Transparency Index")}, - { 0x0419, 0x0000, BIM_T_PS_GLOBAL_ALTITUDE, _T("Global Altitude")}, - { 0x041A, 0x0000, BIM_T_PS_SLICES, _T("Slices")}, - { 0x041B, 0x0000, BIM_T_PS_STR_UNI, _T("Workflow URL")}, - { 0x041C, 0x0000, BIM_T_HEX, _T("Jump to XPEP")}, - { 0x041D, 0x0000, BIM_T_HEX, _T("Alpha Identifiers")}, - { 0x041E, 0x0000, BIM_T_HEX, _T("URL List")}, - { 0x0421, 0x0000, BIM_T_PS_VER_INFO, _T("Version Info")}, - { 0x0422, 0x0000, BIM_T_HEX, _T("Exif data 1")}, - { 0x0423, 0x0000, BIM_T_HEX, _T("Exif data 3")}, - { 0x0424, 0x0000, BIM_T_PS_STR_ASC_LONG, _T("XMP metadata")}, - { 0x0425, 0x0000, BIM_T_HEX, _T("Caption digest")}, - { 0x0426, 0x0000, BIM_T_PS_PRINT_SCALE, _T("Print scale")}, - { 0x0428, 0x0000, BIM_T_PS_PIXEL_ASPECT_RATIO, _T("Pixel Aspect Ratio")}, - { 0x0429, 0x0000, BIM_T_HEX, _T("Layer Comps")}, - { 0x042A, 0x0000, BIM_T_HEX, _T("Alternate Duotone Colors")}, - { 0x042B, 0x0000, BIM_T_HEX, _T("Alternate Spot Colors")}, - { 0x042D, 0x0000, BIM_T_PS_LAYER_SELECT_ID, _T("Layer Selection IDs")}, - { 0x042E, 0x0000, BIM_T_HEX, _T("HDR Toning information")}, - { 0x042F, 0x0000, BIM_T_HEX, _T("Print info")}, - { 0x0430, 0x0000, BIM_T_PS_LAYER_GROUP_ENABLED, _T("Layer Groups Enabled ID")}, - { 0x0431, 0x0000, BIM_T_HEX, _T("Color samplers resource")}, - { 0x0432, 0x0000, BIM_T_HEX, _T("Measurement Scale")}, - { 0x0433, 0x0000, BIM_T_HEX, _T("Timeline Information")}, - { 0x0434, 0x0000, BIM_T_HEX, _T("Sheet Disclosure")}, - { 0x0435, 0x0000, BIM_T_HEX, _T("DisplayInfo structure (FloatPt colors)")}, - { 0x0436, 0x0000, BIM_T_HEX, _T("Onion Skins")}, - { 0x0438, 0x0000, BIM_T_HEX, _T("Count Information")}, - { 0x043A, 0x0000, BIM_T_HEX, _T("Print Information")}, - { 0x043B, 0x0000, BIM_T_HEX, _T("Print Style")}, - { 0x043C, 0x0000, BIM_T_HEX, _T("Macintosh NSPrintInfo")}, - { 0x043D, 0x0000, BIM_T_HEX, _T("Windows DEVMODE")}, - { 0x043E, 0x0000, BIM_T_HEX, _T("Auto Save File Path")}, - { 0x043F, 0x0000, BIM_T_HEX, _T("Auto Save Format")}, - { 0x0440, 0x0000, BIM_T_HEX, _T("Path Selection State")}, - { 0x07D0, 0x0BB6, BIM_T_HEX, _T("Path Information (saved paths)")}, - { 0x0BB7, 0x0000, BIM_T_HEX, _T("Name of clipping path")}, - { 0x0BB8, 0x0000, BIM_T_HEX, _T("Origin Path Info")}, - { 0x0FA0, 0x1387, BIM_T_HEX, _T("Plug-In resources")}, - { 0x1B58, 0x0000, BIM_T_HEX, _T("Image Ready variables")}, - { 0x1B59, 0x0000, BIM_T_HEX, _T("Image Ready data sets")}, - { 0x1F40, 0x0000, BIM_T_HEX, _T("Lightroom workflow")}, - { 0x2710, 0x0000, BIM_T_PS_PRINT_FLAGS_INFO, _T("Print flags information")}, - { 0x0000, 0x0000, BIM_T_END, _T("")}, -}; - - -// Adobe Photoshop enumerated constants -// - See header for struct encoding -struct tsBimEnum asBimEnums[] = -{ - { BIM_T_ENUM_FILE_HDR_COL_MODE, 0,_T("Bitmap")}, - { BIM_T_ENUM_FILE_HDR_COL_MODE, 1,_T("Grayscale")}, - { BIM_T_ENUM_FILE_HDR_COL_MODE, 2,_T("Indexed")}, - { BIM_T_ENUM_FILE_HDR_COL_MODE, 3,_T("RGB")}, - { BIM_T_ENUM_FILE_HDR_COL_MODE, 4,_T("CMYK")}, - { BIM_T_ENUM_FILE_HDR_COL_MODE, 7,_T("Multichannel")}, - { BIM_T_ENUM_FILE_HDR_COL_MODE, 8,_T("Duotone")}, - { BIM_T_ENUM_FILE_HDR_COL_MODE, 9,_T("Lab")}, - { BIM_T_ENUM_RESOLUTION_INFO_RES_UNIT, 1,_T("pixels per inch")}, - { BIM_T_ENUM_RESOLUTION_INFO_RES_UNIT, 2,_T("pixels per cm")}, - { BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, 1,_T("inch")}, - { BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, 2,_T("cm")}, - { BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, 3,_T("picas")}, - { BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, 4,_T("columns")}, - { BIM_T_ENUM_PRINT_SCALE_STYLE, 0,_T("centered")}, - { BIM_T_ENUM_PRINT_SCALE_STYLE, 1,_T("size to fit")}, - { BIM_T_ENUM_PRINT_SCALE_STYLE, 2,_T("user defined")}, - { BIM_T_ENUM_GRID_GUIDE_DIR, 0,_T("vertical")}, - { BIM_T_ENUM_GRID_GUIDE_DIR, 1,_T("horizontal")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'pass',_T("pass through")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'norm',_T("normal")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'diss',_T("dissolve")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'dark',_T("darken")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'mul ',_T("multiply")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'idiv',_T("color burn")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'lbrn',_T("linear burn")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'dkCl',_T("darker color")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'lite',_T("lighten")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'scrn',_T("screen")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'div ',_T("color dodge")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'lddg',_T("linear dodge")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'lgCl',_T("lighter color")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'over',_T("overlay")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'sLit',_T("soft light")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'hLit',_T("hard light")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'vLit',_T("vivid light")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'lLit',_T("linear light")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'pLit',_T("pin light")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'hMix',_T("hard mix")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'diff',_T("difference")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'smud',_T("exclusion")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'fsub',_T("subtract")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'fdiv',_T("divide")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'hue ',_T("hue")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'sat ',_T("saturation")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'colr',_T("color")}, - { BIM_T_ENUM_BLEND_MODE_KEY, 'lum ',_T("luminosity")}, - { BIM_T_ENUM_END, 0,_T("???")}, -}; +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include + +#include + +#include "DecodePs.h" +#include "snoop.h" +#include "JPEGsnoop.h" // for m_pAppConfig get + +#include "WindowBuf.h" + +// Forward declarations +//struct tsIptcField asIptcFields[]; +//struct tsBimRecord asBimRecords[]; +//struct tsBimEnum asBimEnums[]; + +// =============================================================================== +// CONSTANTS +// =============================================================================== + +// Define all of the currently-known IPTC fields, used when we +// parse the APP13 marker +// +// - Reference: IPTC-NAA Information Interchange Model Version 4 +// - See header for struct encoding +struct tsIptcField asIptcFields[] = { + {1, 0, IPTC_T_NUM2, "Model Version"}, + {1, 5, IPTC_T_STR, "Destination"}, + {1, 20, IPTC_T_NUM2, "File Format"}, + {1, 22, IPTC_T_NUM2, "File Format Version"}, + {1, 30, IPTC_T_STR, "Service Identifier"}, + {1, 40, IPTC_T_STR, "Envelope Number"}, + {1, 50, IPTC_T_STR, "Product I.D."}, + {1, 60, IPTC_T_STR, "Envelope Priority"}, + {1, 70, IPTC_T_STR, "Date Sent"}, + {1, 80, IPTC_T_STR, "Time Sent"}, + {1, 90, IPTC_T_STR, "Coded Character Set"}, + {1, 100, IPTC_T_STR, "UNO"}, + {1, 120, IPTC_T_NUM2, "ARM Identifier"}, + {1, 122, IPTC_T_NUM2, "ARM Version"}, + {2, 0, IPTC_T_NUM2, "Record Version"}, + {2, 3, IPTC_T_STR, "Object Type Reference"}, + {2, 4, IPTC_T_STR, "Object Attrib Reference"}, + {2, 5, IPTC_T_STR, "Object Name"}, + {2, 7, IPTC_T_STR, "Edit Status"}, + {2, 8, IPTC_T_STR, "Editorial Update"}, + {2, 10, IPTC_T_STR, "Urgency"}, + {2, 12, IPTC_T_STR, "Subject Reference"}, + {2, 15, IPTC_T_STR, "Category"}, + {2, 20, IPTC_T_STR, "Supplemental Category"}, + {2, 22, IPTC_T_STR, "Fixture Identifier"}, + {2, 25, IPTC_T_STR, "Keywords"}, + {2, 26, IPTC_T_STR, "Content Location Code"}, + {2, 27, IPTC_T_STR, "Content Location Name"}, + {2, 30, IPTC_T_STR, "Release Date"}, + {2, 35, IPTC_T_STR, "Release Time"}, + {2, 37, IPTC_T_STR, "Expiration Date"}, + {2, 38, IPTC_T_STR, "Expiration Time"}, + {2, 40, IPTC_T_STR, "Special Instructions"}, + {2, 42, IPTC_T_STR, "Action Advised"}, + {2, 45, IPTC_T_UNK, "Reference Service"}, + {2, 47, IPTC_T_UNK, "Reference Date"}, + {2, 50, IPTC_T_UNK, "Reference Number"}, + {2, 55, IPTC_T_STR, "Date Created"}, + {2, 60, IPTC_T_STR, "Time Created"}, + {2, 62, IPTC_T_STR, "Digital Creation Date"}, + {2, 63, IPTC_T_STR, "Digital Creation Time"}, + {2, 65, IPTC_T_STR, "Originating Program"}, + {2, 70, IPTC_T_STR, "Program Version"}, + {2, 75, IPTC_T_STR, "Object Cycle"}, + {2, 80, IPTC_T_STR, "By-line"}, + {2, 85, IPTC_T_STR, "By-line Title"}, + {2, 90, IPTC_T_STR, "City"}, + {2, 92, IPTC_T_STR, "Sub-location"}, + {2, 95, IPTC_T_STR, "Province/State"}, + {2, 100, IPTC_T_STR, "Country/Primary Location Code"}, + {2, 101, IPTC_T_STR, "Country/Primary Location Name"}, + {2, 103, IPTC_T_STR, "Original Transmission Reference"}, + {2, 105, IPTC_T_STR, "Headline"}, + {2, 110, IPTC_T_STR, "Credit"}, + {2, 115, IPTC_T_STR, "Source"}, + {2, 116, IPTC_T_STR, "Copyright Notice"}, + {2, 118, IPTC_T_STR, "Contact"}, + {2, 120, IPTC_T_STR, "Caption/Abstract"}, + {2, 122, IPTC_T_STR, "Writer/Editor"}, + {2, 125, IPTC_T_UNK, "Rasterized Caption"}, + {2, 130, IPTC_T_STR, "Image Type"}, + {2, 131, IPTC_T_STR, "Image Orientation"}, + {2, 135, IPTC_T_STR, "Language Identifier"}, + {2, 150, IPTC_T_STR, "Audio Type"}, + {2, 151, IPTC_T_STR, "Audio Sampling Rate"}, + {2, 152, IPTC_T_STR, "Audio Sampling Resolution"}, + {2, 153, IPTC_T_STR, "Audio Duration"}, + {2, 154, IPTC_T_STR, "Audio Outcue"}, + {2, 200, IPTC_T_NUM2, "ObjectData Preview File Format"}, + {2, 201, IPTC_T_NUM2, "ObjectData Preview File Format Version"}, + {2, 202, IPTC_T_UNK, "ObjectData Preview Data"}, + {7, 10, IPTC_T_NUM1, "Size Mode"}, + {7, 20, IPTC_T_NUM, "Max Subfile Size"}, + {7, 90, IPTC_T_NUM1, "ObjectData Size Announced"}, + {7, 95, IPTC_T_NUM, "Maximum ObjectData Size"}, + {8, 10, IPTC_T_UNK, "Subfile"}, + {9, 10, IPTC_T_NUM, "Confirmed ObjectData Size"}, + {0, 0, IPTC_T_END, "DONE"}, +}; + +// Adobe Photoshop File Formats Specification (October 2013) +// - Image Resource Blocks IRB (8BIM) +// - See header for struct encoding +struct tsBimRecord asBimRecords[] = { + {0x03E8, 0x0000, BIM_T_UNK, "-"}, + {0x03E9, 0x0000, BIM_T_HEX, "Macintosh print manager print info record"}, + {0x03EB, 0x0000, BIM_T_HEX, "Indexed color table"}, + {0x03ED, 0x0000, BIM_T_PS_RESOLUTION_INFO, "ResolutionInfo structure"}, + {0x03EE, 0x0000, BIM_T_HEX, "Names of alpha channels"}, + {0x03EF, 0x0000, BIM_T_HEX, "DisplayInfo structure"}, + {0x03F0, 0x0000, BIM_T_HEX, "Caption"}, + {0x03F1, 0x0000, BIM_T_HEX, "Border information"}, + {0x03F2, 0x0000, BIM_T_HEX, "Background color"}, + {0x03F3, 0x0000, BIM_T_PS_PRINT_FLAGS, "Print flags"}, + {0x03F4, 0x0000, BIM_T_HEX, "Grayscale and multichannel halftoning information"}, + {0x03F5, 0x0000, BIM_T_HEX, "Color halftoning information"}, + {0x03F6, 0x0000, BIM_T_HEX, "Duotone halftoning information"}, + {0x03F7, 0x0000, BIM_T_HEX, "Grayscale and multichannel transfer function"}, + {0x03F8, 0x0000, BIM_T_HEX, "Color transfer functions"}, + {0x03F9, 0x0000, BIM_T_HEX, "Duotone transfer functions"}, + {0x03FA, 0x0000, BIM_T_HEX, "Duotone image information"}, + {0x03FC, 0x0000, BIM_T_HEX, "-"}, + {0x03FD, 0x0000, BIM_T_HEX, "EPS options"}, + {0x03FE, 0x0000, BIM_T_HEX, "Quick Mask information"}, + {0x03FF, 0x0000, BIM_T_HEX, "-"}, + {0x0400, 0x0000, BIM_T_PS_LAYER_STATE_INFO, "Layer state information"}, + {0x0401, 0x0000, BIM_T_HEX, "Working path"}, + {0x0402, 0x0000, BIM_T_PS_LAYER_GROUP_INFO, "Layers group information"}, + {0x0403, 0x0000, BIM_T_HEX, "-"}, + {0x0404, 0x0000, BIM_T_IPTC_NAA, "IPTC-NAA record"}, + {0x0405, 0x0000, BIM_T_HEX, "Image mode (raw format files)"}, + {0x0406, 0x0000, BIM_T_JPEG_QUAL, "JPEG quality"}, + {0x0408, 0x0000, BIM_T_PS_GRID_GUIDES, "Grid and guides information"}, + {0x0409, 0x0000, BIM_T_HEX, "Thumbnail resource (PS 4.0)"}, + {0x040A, 0x0000, BIM_T_PS_COPYRIGHT_FLAG, "Copyright flag"}, + {0x040B, 0x0000, BIM_T_HEX, "URL"}, + {0x040C, 0x0000, BIM_T_PS_THUMB_RES, "Thumbnail resources"}, + {0x040D, 0x0000, BIM_T_PS_GLOBAL_ANGLE, "Global Angle"}, + {0x040E, 0x0000, BIM_T_HEX, "Color samplers resource"}, + {0x040F, 0x0000, BIM_T_HEX, "ICC Profile"}, + {0x0410, 0x0000, BIM_T_HEX, "Watermark"}, + {0x0411, 0x0000, BIM_T_HEX, "ICC Untagged Profile"}, + {0x0412, 0x0000, BIM_T_HEX, "Effects visible"}, + {0x0413, 0x0000, BIM_T_HEX, "Spot Halftone"}, + {0x0414, 0x0000, BIM_T_PS_DOC_SPECIFIC_SEED, "Document-specific IDs seed number"}, + {0x0415, 0x0000, BIM_T_PS_STR_UNI, "Unicode Alpha Names"}, + {0x0416, 0x0000, BIM_T_HEX, "Indexed Color Table Count"}, + {0x0417, 0x0000, BIM_T_HEX, "Transparency Index"}, + {0x0419, 0x0000, BIM_T_PS_GLOBAL_ALTITUDE, "Global Altitude"}, + {0x041A, 0x0000, BIM_T_PS_SLICES, "Slices"}, + {0x041B, 0x0000, BIM_T_PS_STR_UNI, "Workflow URL"}, + {0x041C, 0x0000, BIM_T_HEX, "Jump to XPEP"}, + {0x041D, 0x0000, BIM_T_HEX, "Alpha Identifiers"}, + {0x041E, 0x0000, BIM_T_HEX, "URL List"}, + {0x0421, 0x0000, BIM_T_PS_VER_INFO, "Version Info"}, + {0x0422, 0x0000, BIM_T_HEX, "Exif data 1"}, + {0x0423, 0x0000, BIM_T_HEX, "Exif data 3"}, + {0x0424, 0x0000, BIM_T_PS_STR_ASC_LONG, "XMP metadata"}, + {0x0425, 0x0000, BIM_T_HEX, "Caption digest"}, + {0x0426, 0x0000, BIM_T_PS_PRINT_SCALE, "Print scale"}, + {0x0428, 0x0000, BIM_T_PS_PIXEL_ASPECT_RATIO, "Pixel Aspect Ratio"}, + {0x0429, 0x0000, BIM_T_HEX, "Layer Comps"}, + {0x042A, 0x0000, BIM_T_HEX, "Alternate Duotone Colors"}, + {0x042B, 0x0000, BIM_T_HEX, "Alternate Spot Colors"}, + {0x042D, 0x0000, BIM_T_PS_LAYER_SELECT_ID, "Layer Selection IDs"}, + {0x042E, 0x0000, BIM_T_HEX, "HDR Toning information"}, + {0x042F, 0x0000, BIM_T_HEX, "Print info"}, + {0x0430, 0x0000, BIM_T_PS_LAYER_GROUP_ENABLED, "Layer Groups Enabled ID"}, + {0x0431, 0x0000, BIM_T_HEX, "Color samplers resource"}, + {0x0432, 0x0000, BIM_T_HEX, "Measurement Scale"}, + {0x0433, 0x0000, BIM_T_HEX, "Timeline Information"}, + {0x0434, 0x0000, BIM_T_HEX, "Sheet Disclosure"}, + {0x0435, 0x0000, BIM_T_HEX, "DisplayInfo structure (FloatPt colors)"}, + {0x0436, 0x0000, BIM_T_HEX, "Onion Skins"}, + {0x0438, 0x0000, BIM_T_HEX, "Count Information"}, + {0x043A, 0x0000, BIM_T_HEX, "Print Information"}, + {0x043B, 0x0000, BIM_T_HEX, "Print Style"}, + {0x043C, 0x0000, BIM_T_HEX, "Macintosh NSPrintInfo"}, + {0x043D, 0x0000, BIM_T_HEX, "Windows DEVMODE"}, + {0x043E, 0x0000, BIM_T_HEX, "Auto Save File Path"}, + {0x043F, 0x0000, BIM_T_HEX, "Auto Save Format"}, + {0x0440, 0x0000, BIM_T_HEX, "Path Selection State"}, + {0x07D0, 0x0BB6, BIM_T_HEX, "Path Information (saved paths)"}, + {0x0BB7, 0x0000, BIM_T_HEX, "Name of clipping path"}, + {0x0BB8, 0x0000, BIM_T_HEX, "Origin Path Info"}, + {0x0FA0, 0x1387, BIM_T_HEX, "Plug-In resources"}, + {0x1B58, 0x0000, BIM_T_HEX, "Image Ready variables"}, + {0x1B59, 0x0000, BIM_T_HEX, "Image Ready data sets"}, + {0x1F40, 0x0000, BIM_T_HEX, "Lightroom workflow"}, + {0x2710, 0x0000, BIM_T_PS_PRINT_FLAGS_INFO, "Print flags information"}, + {0x0000, 0x0000, BIM_T_END, ""}, +}; + +// Adobe Photoshop enumerated constants +// - See header for struct encoding +struct tsBimEnum asBimEnums[] = { + {BIM_T_ENUM_FILE_HDR_COL_MODE, 0, "Bitmap"}, + {BIM_T_ENUM_FILE_HDR_COL_MODE, 1, "Grayscale"}, + {BIM_T_ENUM_FILE_HDR_COL_MODE, 2, "Indexed"}, + {BIM_T_ENUM_FILE_HDR_COL_MODE, 3, "RGB"}, + {BIM_T_ENUM_FILE_HDR_COL_MODE, 4, "CMYK"}, + {BIM_T_ENUM_FILE_HDR_COL_MODE, 7, "Multichannel"}, + {BIM_T_ENUM_FILE_HDR_COL_MODE, 8, "Duotone"}, + {BIM_T_ENUM_FILE_HDR_COL_MODE, 9, "Lab"}, + {BIM_T_ENUM_RESOLUTION_INFO_RES_UNIT, 1, "pixels per inch"}, + {BIM_T_ENUM_RESOLUTION_INFO_RES_UNIT, 2, "pixels per cm"}, + {BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, 1, "inch"}, + {BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, 2, "cm"}, + {BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, 3, "picas"}, + {BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, 4, "columns"}, + {BIM_T_ENUM_PRINT_SCALE_STYLE, 0, "centered"}, + {BIM_T_ENUM_PRINT_SCALE_STYLE, 1, "size to fit"}, + {BIM_T_ENUM_PRINT_SCALE_STYLE, 2, "user defined"}, + {BIM_T_ENUM_GRID_GUIDE_DIR, 0, "vertical"}, + {BIM_T_ENUM_GRID_GUIDE_DIR, 1, "horizontal"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'pass', "pass through"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'norm', "normal"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'diss', "dissolve"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'dark', "darken"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'mul ', "multiply"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'idiv', "color burn"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'lbrn', "linear burn"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'dkCl', "darker color"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'lite', "lighten"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'scrn', "screen"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'div ', "color dodge"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'lddg', "linear dodge"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'lgCl', "lighter color"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'over', "overlay"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'sLit', "soft light"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'hLit', "hard light"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'vLit', "vivid light"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'lLit', "linear light"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'pLit', "pin light"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'hMix', "hard mix"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'diff', "difference"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'smud', "exclusion"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'fsub', "subtract"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'fdiv', "divide"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'hue ', "hue"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'sat ', "saturation"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'colr', "color"}, + {BIM_T_ENUM_BLEND_MODE_KEY, 'lum ', "luminosity"}, + {BIM_T_ENUM_END, 0, "???"}, +}; + +CDecodePs::CDecodePs(CwindowBuf * pWBuf, CDocLog * pLog) +{ + // Save copies of class pointers + m_pWBuf = pWBuf; + m_pLog = pLog; + + // HACK + // Only select a single layer to decode into the DIB + // FIXME: Need to allow user control over this setting + m_bDisplayLayer = false; + m_nDisplayLayerInd = 0; + m_bDisplayImage = true; + + // Ideally this would be passed by constructor, but simply access + // directly for now. + CJPEGsnoopApp *pApp; + +//@@ pApp = (CJPEGsnoopApp*)AfxGetApp(); +//@@ m_pAppConfig = pApp->m_pAppConfig; + + Reset(); +} + +void CDecodePs::Reset() +{ + m_bPsd = false; + m_nQualitySaveAs = 0; + m_nQualitySaveForWeb = 0; + m_bAbort = false; +} + +CDecodePs::~CDecodePs(void) +{ +} + +// Provide a short-hand alias for the m_pWBuf buffer +// INPUT: +// - offset File offset to read from +// - bClean Forcibly disables any redirection to Fake DHT table +// +// POST: +// - m_pLog +// +// RETURN: +// - Byte from file +// +BYTE CDecodePs::Buf(uint32_t offset, bool bClean = false) +{ + return m_pWBuf->Buf(offset, bClean); +} + +// Determine if the file is a Photoshop PSD +// If so, parse the headers. Generally want to start at start of file (nPos=0). +bool CDecodePs::DecodePsd(uint32_t nPos, CDIB * pDibTemp, uint32_t &nWidth, uint32_t &nHeight) +{ + QString strTmp; + + m_bPsd = false; + + QString strSig; + + uint32_t nVer; + + strSig = m_pWBuf->BufReadStrn(nPos, 4); + nPos += 4; + nVer = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + if((strSig == "8BPS") && (nVer == 1)) + { + m_bPsd = true; + m_pLog->AddLine(""); + m_pLog->AddLineHdr("*** Photoshop PSD File Decoding ***"); + m_pLog->AddLine("Decoding Photoshop format..."); + m_pLog->AddLine(""); + } + else + { + return false; + } + + // Rewind back to header (signature) + nPos -= 6; + + bool bDecOk = true; + + tsImageInfo sImageInfo; + + PhotoshopParseFileHeader(nPos, 3, &sImageInfo); + nWidth = sImageInfo.nImageWidth; + nHeight = sImageInfo.nImageHeight; + + PhotoshopParseColorModeSection(nPos, 3); + if(bDecOk) + bDecOk &= PhotoshopParseImageResourcesSection(nPos, 3); + + if(bDecOk) + bDecOk &= PhotoshopParseLayerMaskInfo(nPos, 3, pDibTemp); + if(bDecOk) + { + unsigned char *pDibBits = NULL; + +#ifdef PS_IMG_DEC_EN + if((pDibTemp) && (m_bDisplayImage)) + { + // Allocate the device-independent bitmap (DIB) + // - Although we are creating a 32-bit DIB, it should also + // work to run in 16- and 8-bit modes + + // Start by killing old DIB since we might be changing its dimensions +//@@ pDibTemp->Kill(); + + // Allocate the new DIB +//@@ bool bDibOk = pDibTemp->CreateDIB(nWidth, nHeight, 32); + + // Should only return false if already exists or failed to allocate +//@@ if(bDibOk) + { + // Fetch the actual pixel array +//@@ pDibBits = (unsigned char *) (pDibTemp->GetDIBBitArray()); + } + } +#endif + + bDecOk &= PhotoshopParseImageData(nPos, 3, &sImageInfo, pDibBits); + PhotoshopParseReportFldOffset(3, "Image data decode complete:", nPos); + } + PhotoshopParseReportNote(3, ""); + + if(bDecOk) + { + } + else + { + m_pLog->AddLineErr("ERROR: There was a problem during decode. Aborting."); + return false; + } + return true; + +} + +// Locate a field ID in the constant 8BIM / Image Resource array +// +// INPUT: +// - nBimId = Image Resource ID (16-bit unsigned) +// OUTPUT: +// - nFldInd = Index into asBimRecords[] array +// RETURN: +// - Returns true if ID was found in array +// NOTE: +// - The constant struct array depends on BIM_T_END as a terminator for the list +// +bool CDecodePs::FindBimRecord(uint32_t nBimId, uint32_t &nFldInd) +{ + uint32_t nInd = 0; + + bool bDone = false; + + bool bFound = false; + + while(!bDone) + { + if(asBimRecords[nInd].eBimType == BIM_T_END) + { + bDone = true; + } + else + { + // Support detection of code ranges + uint32_t nCodeStart = asBimRecords[nInd].nCode; + + uint32_t nCodeEnd = asBimRecords[nInd].nCodeEnd; + + if((nCodeEnd == 0) && (nCodeStart == nBimId)) + { + // Match with single code (ie. not ranged entry) + bDone = true; + bFound = true; + } + else if((nCodeEnd != 0) && (nCodeStart <= nBimId) && (nCodeEnd >= nBimId)) + { + // Match with code in ranged entry + bDone = true; + bFound = true; + } + else + { + nInd++; + } + + } + } + if(bFound) + { + nFldInd = nInd; + } + return bFound; +} + +// Search the constant array of IPTC fields for the Record:DataSet index +// +// OUTPUT: +// - nFldInd = The index into the array of the located entry (if found) +// RETURN +// - Successfully found the Record:DataSet value +// +bool CDecodePs::LookupIptcField(uint32_t nRecord, uint32_t nDataSet, uint32_t &nFldInd) +{ + uint32_t nInd = 0; + + bool bDone = false; + + bool bFound = false; + + while(!bDone) + { + if(asIptcFields[nInd].eFldType == IPTC_T_END) + { + bDone = true; + } + else + { + if((asIptcFields[nInd].nRecord == nRecord) && (asIptcFields[nInd].nDataSet == nDataSet)) + { + bDone = true; + bFound = true; + } + else + { + nInd++; + } + } + } + if(bFound) + { + nFldInd = nInd; + } + return bFound; +} + +// Generate the custom-formatted string representing the IPTC field name and value +// +// INPUT: +// - eIptcType = Enumeration representing the IPTC field type +// - nFldCnt = The number of elements in this field to report +// - nPos = The starting file offset for this field +// RETURN: +// - The IPTC formattted string +// NOTE: +// - The IPTC field type is used to determine how to represent the input values +// +QString CDecodePs::DecodeIptcValue(teIptcType eIptcType, uint32_t nFldCnt, uint32_t nPos) +{ + //uint32_t nFldInd = 0; + uint32_t nInd; + + uint32_t nVal; + + QString strField = ""; + + QString strByte = ""; + + QString strVal = ""; + + switch (eIptcType) + { + case IPTC_T_NUM: + case IPTC_T_NUM1: + case IPTC_T_NUM2: + nVal = m_pWBuf->BufX(nPos, nFldCnt, PS_BSWAP); + nPos += nFldCnt; + nPos += nFldCnt; + strVal = QString("%1").arg(nVal); + break; + case IPTC_T_HEX: + strVal = "["; + for(nInd = 0; nInd < nFldCnt; nInd++) + { + strByte = QString("0x%1 ").arg(Buf(nPos++), 2, 16, QChar('0')); + strVal += strByte; + } + strVal += "]"; + break; + case IPTC_T_STR: + strVal = "\""; + for(nInd = 0; nInd < nFldCnt; nInd++) + { + strByte = QString("%1").arg(Buf(nPos++)); + strVal += strByte; + } + strVal += "\""; + break; + case IPTC_T_UNK: + strVal = "???"; + default: + break; + } + return strVal; +} + +// Decode the IPTC metadata segment +// INPUT: +// nLen : Length of the 8BIM:IPTC resource data +void CDecodePs::DecodeIptc(uint32_t &nPos, uint32_t nLen, uint32_t nIndent) +{ + QString strIndent; + + QString strTmp; + + QString strIptcTypeName; + + QString strIptcField; + + QString strIptcVal; + + QString strByte; + + uint32_t nPosStart; + + bool bDone; + + uint32_t nTagMarker, nRecordNumber, nDataSetNumber, nDataFieldCnt; + + strIndent = PhotoshopParseIndent(nIndent); + nPosStart = nPos; + bDone = true; + if(nPos <= nPosStart + nLen) + { + // TODO: Should probably check to see if we have at least 5 bytes? + bDone = false; + } + while(!bDone) + { + nTagMarker = Buf(nPos + 0); + nRecordNumber = Buf(nPos + 1); + nDataSetNumber = Buf(nPos + 2); + nDataFieldCnt = Buf(nPos + 3) * 256 + Buf(nPos + 4); + nPos += 5; + + if(nTagMarker == 0x1C) + { + uint32_t nFldInd; + + teIptcType eIptcType; + + if(LookupIptcField(nRecordNumber, nDataSetNumber, nFldInd)) + { + strIptcField = QString("%1").arg(asIptcFields[nFldInd].strFldName, -35); + eIptcType = asIptcFields[nFldInd].eFldType; + } + else + { + strIptcField = QString("%1").arg("?", -35); + eIptcType = IPTC_T_UNK; + } + + strIptcVal = DecodeIptcValue(eIptcType, nDataFieldCnt, nPos); + strTmp = + QString("%1IPTC [%03u:%03u] %4 = %5").arg(strIndent).arg(nRecordNumber, 3, 10, QChar('0')).arg(nDataSetNumber, 3, 10, + QChar('0')). + arg(strIptcField).arg(strIptcVal); + m_pLog->AddLine(strTmp); + nPos += nDataFieldCnt; + } + else + { + // Unknown Tag Marker + // I have seen at least one JPEG file that had an IPTC block with all zeros. + // In this example, the TagMarker check for 0x1C would fail. + // Since we don't know how to parse it, abort now. + strTmp = + QString("ERROR: Unknown IPTC TagMarker [0x%02X] @ 0x%08X. Skipping parsing.").arg(nTagMarker, 2, 16, + QChar('0')).arg(nPos - 5, 8, 16, + QChar('0')); + m_pLog->AddLineErr(strTmp); + +#ifdef DEBUG_LOG + QString strDebug; + + strDebug = + QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", -10).arg(strTmp); + qDebug() << (strDebug); +#endif + + // Adjust length to end + nPos = nPosStart + nLen; + + // Now abort + bDone = true; + } + + if(nPos >= nPosStart + nLen) + { + bDone = true; + } + } +} + +// Create indent string +// - Returns a sequence of spaces according to the indent level +QString CDecodePs::PhotoshopParseIndent(uint32_t nIndent) +{ + QString strIndent = ""; + + for(uint32_t nInd = 0; nInd < nIndent; nInd++) + { + strIndent += " "; + } + return strIndent; +} + +// Get ASCII string according to Photoshop format +// - String length prefix +// - If length is 0 then fixed 4-character string +// - Otherwise it is defined length string (no terminator required) +QString CDecodePs::PhotoshopParseGetLStrAsc(uint32_t &nPos) +{ + uint32_t nStrLen; + + QString strVal = ""; + + nStrLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + if(nStrLen != 0) + { + strVal = m_pWBuf->BufReadStrn(nPos, nStrLen); + nPos += nStrLen; + } + else + { + // 4 byte string + strVal = QString("%1%2%3%4").arg(Buf(nPos + 0)).arg(Buf(nPos + 1)).arg(Buf(nPos + 2)).arg(Buf(nPos + 3)); + nPos += 4; + } + return strVal; +} + +// Read a UNICODE string starting at nPos according to Photoshop Unicode string format +// - Start with 4 byte length +// - Follow with UNICODE string +// OUTPUT: +// - The byte offset to advance the file pointer +// RETURN: +// - Unicode string +QString CDecodePs::PhotoshopParseGetBimLStrUni(uint32_t nPos, uint32_t &nPosOffset) +{ + QString strVal; + + uint32_t nStrLenActual, nStrLenTrunc; + + char anStrBuf[(PS_MAX_UNICODE_STRLEN + 1) * 2]; + + wchar_t acStrBuf[(PS_MAX_UNICODE_STRLEN + 1)]; + + char nChVal; + + nPosOffset = 0; + nStrLenActual = m_pWBuf->BufX(nPos + nPosOffset, 4, PS_BSWAP); + nPosOffset += 4; + nStrLenTrunc = nStrLenActual; + + // Initialize return + strVal = ""; + + if(nStrLenTrunc > 0) + { + // Read unicode bytes into byte array + // Truncate the string, leaving room for terminator + if(nStrLenTrunc > PS_MAX_UNICODE_STRLEN) + { + nStrLenTrunc = PS_MAX_UNICODE_STRLEN; + } + for(uint32_t nInd = 0; nInd < nStrLenTrunc; nInd++) + { + // Reverse the order of the bytes + nChVal = Buf(nPos + nPosOffset + (nInd * 2) + 0); + anStrBuf[(nInd * 2) + 1] = nChVal; + nChVal = Buf(nPos + nPosOffset + (nInd * 2) + 1); + anStrBuf[(nInd * 2) + 0] = nChVal; + } + // TODO: Replace with call to ByteStr2Unicode() + // Ensure it is terminated + anStrBuf[nStrLenTrunc * 2 + 0] = 0; + anStrBuf[nStrLenTrunc * 2 + 1] = 0; + // Copy into unicode string + // Ensure that it is terminated first! +// wcscpy(acStrBuf,anStrBuf); + // Copy into QString + strVal = QString(anStrBuf); + } + // Update the file position offset + nPosOffset += nStrLenActual * 2; + // Return + return strVal; +} + +// Display a formatted note line +// - Apply the current indent level (nIndent) +void CDecodePs::PhotoshopParseReportNote(uint32_t nIndent, QString strNote) +{ + QString strIndent; + + QString strLine; + + strIndent = PhotoshopParseIndent(nIndent); + strLine = QString("%1%2").arg(strIndent).arg(strNote, -50); + m_pLog->AddLine(strLine); +} + +// Display a formatted numeric field with optional units string +// - Report the value with the field name (strField) and current indent level (nIndent) +void CDecodePs::PhotoshopParseReportFldNum(uint32_t nIndent, QString strField, uint32_t nVal, QString strUnits) +{ + QString strIndent; + + QString strVal; + + QString strLine; + + strIndent = PhotoshopParseIndent(nIndent); + strVal = QString("%1").arg(nVal); + strLine = QString("%1%2 = %3 %4").arg(strIndent).arg(strField, -50).arg(strVal).arg(strUnits); + m_pLog->AddLine(strLine); +} + +// Display a formatted boolean field +// - Report the value with the field name (strField) and current indent level (nIndent) +void CDecodePs::PhotoshopParseReportFldBool(uint32_t nIndent, QString strField, uint32_t nVal) +{ + QString strIndent; + + QString strVal; + + QString strLine; + + strIndent = PhotoshopParseIndent(nIndent); + strVal = (nVal != 0) ? "true" : "false"; + strLine = QString("%1%2 = %3").arg(strIndent).arg(strField, -50).arg(strVal); + m_pLog->AddLine(strLine); +} + +// +// Display a formatted hexadecimal field +// - Report the value with the field name (strField) and current indent level (nIndent) +// - Depending on the length of the buffer, either report the hex value in-line with +// the field name or else start a new row and begin a hex dump +// - Also report the ASCII representation alongside the hex dump +// +// INPUT: +// - nIndent = Current indent level for reporting +// - strField = Field name +// - nPosStart = Field byte array file position start +// - nLen = Field byte array length +// +void CDecodePs::PhotoshopParseReportFldHex(uint32_t nIndent, QString strField, uint32_t nPosStart, uint32_t nLen) +{ + QString strIndent; + + uint32_t nByte; + + QString strPrefix; + + QString strByteHex; + + QString strByteAsc; + + QString strValHex; + + QString strValAsc; + + QString strLine; + + strIndent = PhotoshopParseIndent(nIndent); + + if(nLen == 0) + { + // Print out the header row, but no data will be shown + strLine = QString("%1%2 = ").arg(strIndent).arg(strField, -50); + m_pLog->AddLine(strLine); + // Nothing to report, exit now + return; + } + else if(nLen <= PS_HEX_MAX_INLINE) + { + // Define prefix for row + strPrefix = QString("%1%2 = ").arg(strIndent).arg(strField, -50); + } + else + { + // Print out header row + strLine = QString("%1%2s =").arg(strIndent).arg(strField, -50); + m_pLog->AddLine(strLine); + // Define prefix for next row + strPrefix = QString("%1").arg(strIndent); + } + + // Build up the hex string + // Limit to PS_HEX_TOTAL bytes + uint32_t nRowOffset = 0; + + bool bDone = false; + + uint32_t nLenClip; + + nLenClip = qMin(nLen, PS_HEX_TOTAL); + strValHex = ""; + strValAsc = ""; + while(!bDone) + { + // Have we reached the end of the data we wish to display? + if(nRowOffset >= nLenClip) + { + bDone = true; + } + else + { + // Reset the cumulative hex/ascii value strings + strValHex = ""; + strValAsc = ""; + // Build the hex/ascii value strings + for(uint32_t nInd = 0; nInd < PS_HEX_MAX_ROW; nInd++) + { + if((nRowOffset + nInd) < nLenClip) + { + nByte = m_pWBuf->Buf(nPosStart + nRowOffset + nInd); + strByteHex = QString("%1 ").arg(nByte, 2, 16, QChar('0')); + // Only display printable characters + if(isprint(nByte)) + { + strByteAsc = QString("%1").arg(nByte); + } + else + { + strByteAsc = "."; + } + } + else + { + // Pad out to end of row + strByteHex = QString(" "); + strByteAsc = " "; + } + // Build up the strings + strValHex += strByteHex; + strValAsc += strByteAsc; + } + + // Generate the line with Hex and ASCII representations + strLine = QString("%1 | 0x%2 | %3").arg(strPrefix).arg(strValHex).arg(strValAsc); + m_pLog->AddLine(strLine); + + // Now increment file offset + nRowOffset += PS_HEX_MAX_ROW; + } + } + + // If we had to clip the display length, then show ellipsis now + if(nLenClip < nLen) + { + strLine = QString("%1 | ...").arg(strPrefix); + m_pLog->AddLine(strLine); + } + +} + +QString CDecodePs::PhotoshopDispHexWord(uint32_t nVal) +{ + QString strValHex; + + QString strValAsc; + + uint32_t nByte; + + QString strByteHex; + + QString strByteAsc; + + QString strLine; + + // Reset the cumulative hex/ascii value strings + strValHex = ""; + strValAsc = ""; + // Build the hex/ascii value strings + for(uint32_t nInd = 0; nInd <= 3; nInd++) + { + nByte = (nVal & 0xFF000000) >> 24; + nVal <<= 8; + + strByteHex = QString("%02X ").arg(nByte, 2, 16, QChar('0')); + // Only display printable characters + if(isprint(nByte)) + { + strByteAsc = QString("%1").arg(nByte); + } + else + { + strByteAsc = "."; + } + + // Build up the strings + strValHex += strByteHex; + strValAsc += strByteAsc; + } + + // Generate the line with Hex and ASCII representations + strLine = QString("0x%1 | %2").arg(strValHex).arg(strValAsc); + + return strLine; +} + +// Look up the enumerated constant (nVal) for the specified field (eEnumField) +// - Returns "" if the field wasn't found +QString CDecodePs::PhotoshopParseLookupEnum(teBimEnumField eEnumField, uint32_t nVal) +{ + QString strVal = ""; + + // Find the enum value + bool bDone = false; + + bool bFound = false; + + uint32_t nEnumInd = 0; + + while(!bDone) + { + if(asBimEnums[nEnumInd].eBimEnum == eEnumField) + { + if(asBimEnums[nEnumInd].nVal == nVal) + { + bDone = true; + bFound = true; + strVal = asBimEnums[nEnumInd].strVal; + } + } + if(asBimEnums[nEnumInd].eBimEnum == BIM_T_ENUM_END) + { + bDone = true; + } + if(!bDone) + { + nEnumInd++; + } + } + + // If enum wasn't found, then replace by hex value + if(!bFound) + { + QString strWord = PhotoshopDispHexWord(nVal); + + strVal = QString("? [%1]").arg(strWord); + } + return strVal; +} + +// Display a formatted enumerated type field +// - Look up enumerated constant (nVal) for the given field (eEnumField) +// - Report the value with the field name (strField) and current indent level (nIndent) +void CDecodePs::PhotoshopParseReportFldEnum(uint32_t nIndent, QString strField, teBimEnumField eEnumField, uint32_t nVal) +{ + QString strIndent; + + QString strVal; + + QString strLine; + + strIndent = PhotoshopParseIndent(nIndent); + strVal = PhotoshopParseLookupEnum(eEnumField, nVal); + strLine = QString("%1%2 = %3").arg(strIndent).arg(strField, -50).arg(strVal); + m_pLog->AddLine(strLine); +} + +// Display a formatted fixed-point field +// - Convert a 32-bit unsigned integer into Photoshop fixed point +// - Assume fixed point representation is 16-bit integer : 16-bit fraction +// - Report the value with the field name (strField) and current indent level (nIndent) +void CDecodePs::PhotoshopParseReportFldFixPt(uint32_t nIndent, QString strField, uint32_t nVal, QString strUnits) +{ + QString strIndent; + + QString strVal; + + QString strLine; + + float fVal; + + fVal = (nVal / (float) 65536.0); + strIndent = PhotoshopParseIndent(nIndent); + strVal = QString("%1").arg(fVal); + strLine = QString("%1%2 = %3 %4").arg(strIndent).arg(strField, -50).arg(strVal).arg(strUnits); + m_pLog->AddLine(strLine); +} + +// Display a formatted fixed-point field +// - Convert a 32-bit unsigned integer into Photoshop floating point +// - Report the value with the field name (strField) and current indent level (nIndent) +void CDecodePs::PhotoshopParseReportFldFloatPt(uint32_t nIndent, QString strField, uint32_t nVal, QString strUnits) +{ + QString strIndent; + + QString strVal; + + QString strLine; + + float fVal; + + // Convert 4 byte unsigned int to floating-point + // TODO: Need to check this since Photoshop web spec doesn't + // indicate how floating points are stored. + union tUnionTmp + { + BYTE nVal[4]; + float fVal; + }; + + tUnionTmp myUnion; + + // NOTE: Empirically determined the byte order for double representation + myUnion.nVal[3] = static_cast < BYTE > ((nVal & 0xFF000000) >> 24); + myUnion.nVal[2] = static_cast < BYTE > ((nVal & 0x00FF0000) >> 16); + myUnion.nVal[1] = static_cast < BYTE > ((nVal & 0x0000FF00) >> 8); + myUnion.nVal[0] = static_cast < BYTE > ((nVal & 0x000000FF) >> 0); + fVal = myUnion.fVal; + + strIndent = PhotoshopParseIndent(nIndent); + strVal = QString("%1").arg(fVal,0,'f',5); + strLine = QString("%1%2 = %3 %4").arg(strIndent).arg(strField, -50).arg(strVal).arg(strUnits); + m_pLog->AddLine(strLine); +} + +// Display a formatted double-precision floating-point field +// - Convert two 32-bit unsigned integers into Photoshop double-precision floating point +// - Report the value with the field name (strField) and current indent level (nIndent) +void CDecodePs::PhotoshopParseReportFldDoublePt(uint32_t nIndent, QString strField, uint32_t nVal1, uint32_t nVal2, + QString strUnits) +{ + QString strIndent; + + QString strVal; + + QString strLine; + + double dVal; + + // Convert 2x4 byte unsigned int to double-point + // TODO: Need to check this since Photoshop web spec doesn't + // indicate how double points are stored. + union tUnionTmp + { + BYTE nVal[8]; + double dVal; + }; + + tUnionTmp myUnion; + + // NOTE: Empirically determined the byte order for double representation + myUnion.nVal[7] = static_cast < BYTE > ((nVal1 & 0xFF000000) >> 24); + myUnion.nVal[6] = static_cast < BYTE > ((nVal1 & 0x00FF0000) >> 16); + myUnion.nVal[5] = static_cast < BYTE > ((nVal1 & 0x0000FF00) >> 8); + myUnion.nVal[4] = static_cast < BYTE > ((nVal1 & 0x000000FF) >> 0); + myUnion.nVal[3] = static_cast < BYTE > ((nVal2 & 0xFF000000) >> 24); + myUnion.nVal[2] = static_cast < BYTE > ((nVal2 & 0x00FF0000) >> 16); + myUnion.nVal[1] = static_cast < BYTE > ((nVal2 & 0x0000FF00) >> 8); + myUnion.nVal[0] = static_cast < BYTE > ((nVal2 & 0x000000FF) >> 0); + dVal = myUnion.dVal; + + strIndent = PhotoshopParseIndent(nIndent); + strVal = QString("%1").arg(dVal,0,'f',5); + strLine = QString("%1%2 = %3 %4").arg(strIndent).arg(strField, -50).arg(strVal).arg(strUnits); + m_pLog->AddLine(strLine); +} + +// Display a formatted string field +// - Report the value with the field name (strField) and current indent level (nIndent) +void CDecodePs::PhotoshopParseReportFldStr(uint32_t nIndent, QString strField, QString strVal) +{ + QString strIndent; + + QString strLine; + + strIndent = PhotoshopParseIndent(nIndent); + strLine = QString("%1%2 = \"%3\"").arg(strIndent).arg(strField, -50).arg(strVal); + m_pLog->AddLine(strLine); +} + +// Display a formatted file offset field +// - Report the offset with the field name (strField) and current indent level (nIndent) +void CDecodePs::PhotoshopParseReportFldOffset(uint32_t nIndent, QString strField, uint32_t nOffset) +{ + QString strIndent; + + QString strLine; + + strIndent = PhotoshopParseIndent(nIndent); + strLine = QString("%1%2 @ 0x%3").arg(strIndent).arg(strField, -50).arg(nOffset, 8, 16, QChar('0')); + m_pLog->AddLine(strLine); +} + +// Parse the Photoshop IRB Thumbnail Resource +// - NOTE: Returned nPos doesn't take into account JFIF data +void CDecodePs::PhotoshopParseThumbnailResource(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Format", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Width of thumbnail", nVal, "pixels"); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Height of thumbnail", nVal, "pixels"); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Widthbytes", nVal, "bytes"); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Total size", nVal, "bytes"); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Size after compression", nVal, "bytes"); + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Bits per pixel", nVal, "bits"); + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Number of planes", nVal, ""); + + PhotoshopParseReportFldOffset(nIndent, "JFIF data", nPos); + + // NOTE: nPos doesn't take into account JFIF data! +} + +// Parse the Photoshop IRB Version Info +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseVersionInfo(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + uint32_t nPosOffset; + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Version", nVal, ""); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "hasRealMergedData", nVal, ""); + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "Writer name", strVal); + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "Reader name", strVal); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "File version", nVal, ""); +} + +// Parse the Photoshop IRB Print Scale +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParsePrintScale(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldEnum(nIndent, "Style", BIM_T_ENUM_PRINT_SCALE_STYLE, nVal); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldFloatPt(nIndent, "X location", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldFloatPt(nIndent, "Y location", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldFloatPt(nIndent, "Scale", nVal, ""); +} + +// Parse the Photoshop IRB Global Angle +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseGlobalAngle(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Global Angle", nVal, "degrees"); +} + +// Parse the Photoshop IRB Global Altitude +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseGlobalAltitude(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Global Altitude", nVal, ""); +} + +// Parse the Photoshop IRB Print Flags +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParsePrintFlags(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Labels", nVal); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Crop marks", nVal); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Color bars", nVal); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Registration marks", nVal); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Negative", nVal); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Flip", nVal); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Interpolate", nVal); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Caption", nVal); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Print flags", nVal); +} + +// Parse the Photoshop IRB Print Flags Information +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParsePrintFlagsInfo(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Version", nVal, ""); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Center crop marks", nVal, ""); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Reserved", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Bleed width value", nVal, ""); + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Bleed width scale", nVal, ""); +} + +// Parse the Photoshop IRB Copyright Flag +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseCopyrightFlag(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Copyright flag", nVal); +} + +// Parse the Photoshop IRB Aspect Ratio +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParsePixelAspectRatio(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal, nVal1, nVal2; + + QString strVal; + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Version", nVal, ""); + nVal1 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nVal2 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldDoublePt(nIndent, "X/Y Ratio", nVal1, nVal2, ""); +} + +// Parse the Photoshop IRB Document-Specific Seed +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseDocSpecificSeed(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Base value", nVal, ""); +} + +// Parse the Photoshop IRB Grid and Guides +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseGridGuides(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Version", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Grid Horizontal", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Grid Vertical", nVal, ""); + uint32_t nNumGuides = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Number of Guide Resources", nNumGuides, ""); + + if(nNumGuides > 0) + PhotoshopParseReportNote(nIndent, "-----"); + for(uint32_t nInd = 0; nInd < nNumGuides; nInd++) + { + strVal = QString("Guide #%1:").arg(nInd); + PhotoshopParseReportNote(nIndent, strVal); + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent + 1, "Location", nVal, ""); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldEnum(nIndent + 1, "Direction", BIM_T_ENUM_GRID_GUIDE_DIR, nVal); + } + if(nNumGuides > 0) + PhotoshopParseReportNote(nIndent, "-----"); +} + +// Parse the Photoshop IRB Resolution Info +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseResolutionInfo(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal, nUnit; + + QString strVal, strUnit; + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nUnit = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + strUnit = PhotoshopParseLookupEnum(BIM_T_ENUM_RESOLUTION_INFO_RES_UNIT, nUnit); + PhotoshopParseReportFldFixPt(nIndent, "Horizontal resolution", nVal, strUnit); + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldEnum(nIndent, "Width unit", BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, nVal); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nUnit = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + strUnit = PhotoshopParseLookupEnum(BIM_T_ENUM_RESOLUTION_INFO_RES_UNIT, nUnit); + PhotoshopParseReportFldFixPt(nIndent, "Vertical resolution", nVal, strUnit); + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldEnum(nIndent, "Height unit", BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, nVal); +} + +// Parse the Photoshop IRB Layer State Info +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseLayerStateInfo(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Target layer", nVal, ""); +} + +// Parse the Photoshop IRB Layer Group Info +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// - nLen = Length of IRB entry (to determine number of layers) +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseLayerGroupInfo(uint32_t &nPos, uint32_t nIndent, uint32_t nLen) +{ + uint32_t nVal; + + QString strVal; + + // NOTE: + // According to the Photoshop documentation: + // - 2 bytes per layer containing a group ID for the dragging groups. + // - Layers in a group have the same group ID. + // It was not clear whether there was a separate indication of the number of layers + // For now, assume we can derive it from the total IRB length + uint32_t nNumLayers; + + nNumLayers = nLen / 2; + + for(uint32_t nInd = 0; nInd < nNumLayers; nInd++) + { + strVal = QString("Layer #%:").arg(nInd); + PhotoshopParseReportNote(nIndent, strVal); + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent + 1, "Layer Group", nVal, ""); + } +} + +// Parse the Photoshop IRB Layer Groups Enabled +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// - nLen = Length of IRB entry (to determine number of layers) +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseLayerGroupEnabled(uint32_t &nPos, uint32_t nIndent, uint32_t nLen) +{ + uint32_t nVal; + + QString strVal; + + // NOTE: + // According to the Photoshop documentation: + // - 1 byte for each layer in the document, repeated by length of the resource. + // - NOTE: Layer groups have start and end markers + // For now, assume we can derive it from the total IRB length + uint32_t nNumLayers; + + nNumLayers = nLen / 1; + + for(uint32_t nInd = 0; nInd < nNumLayers; nInd++) + { + strVal = QString("Layer #%1:").arg(nInd); + PhotoshopParseReportNote(nIndent, strVal); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent + 1, "Layer Group Enabled ID", nVal, ""); + } +} + +// Parse the Photoshop IRB Layer Select IDs +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseLayerSelectId(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + uint32_t nNumLayer = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Num selected", nNumLayer, ""); + for(uint32_t nInd = 0; nInd < nNumLayer; nInd++) + { + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent + 1, "Layer ID", nVal, ""); + } +} + +// Parse the Photoshop IRB File Header +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseFileHeader(uint32_t &nPos, uint32_t nIndent, tsImageInfo * psImageInfo) +{ + Q_ASSERT(psImageInfo); + + uint32_t nVal; + + QString strVal; + + PhotoshopParseReportNote(nIndent, "File Header Section:"); + nIndent++; + + QString strSig = m_pWBuf->BufReadStrn(nPos, 4); + + nPos += 4; + PhotoshopParseReportFldStr(nIndent, "Signature", strSig); + + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Version", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Reserved1", nVal, ""); + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Reserved2", nVal, ""); + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Num channels in image", nVal, ""); + psImageInfo->nNumChans = nVal; + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Image height", nVal, "pixels"); + psImageInfo->nImageHeight = nVal; + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Image width", nVal, "pixels"); + psImageInfo->nImageWidth = nVal; + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Depth", nVal, "bits per pixel"); + psImageInfo->nDepthBpp = nVal; + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + PhotoshopParseReportFldEnum(nIndent, "Color mode", BIM_T_ENUM_FILE_HDR_COL_MODE, nVal); + +} + +// Parse the Photoshop IRB Color Mode Section (from File Header) +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseColorModeSection(uint32_t &nPos, uint32_t nIndent) +{ + QString strVal; + + PhotoshopParseReportNote(nIndent, "Color Mode Data Section:"); + nIndent++; + + uint32_t nColModeLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Length", nColModeLen, ""); + if(nColModeLen != 0) + { + PhotoshopParseReportFldOffset(nIndent, "Color data", nPos); + } + + // Skip data + nPos += nColModeLen; +} + +// ------------- + +// Parse the Photoshop IRB Layer and Mask Info Section (from File Header) +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// - pDibTemp = DIB for image display +// OUTPUT: +// - nPos = File position after reading the block +// +bool CDecodePs::PhotoshopParseLayerMaskInfo(uint32_t &nPos, uint32_t nIndent, CDIB * pDibTemp) +{ + QString strVal; + + bool bDecOk = true; + + PhotoshopParseReportNote(nIndent, "Layer and Mask Information Section:"); + nIndent++; + + uint32_t nLayerMaskLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + uint32_t nPosStart = nPos; + + uint32_t nPosEnd = nPosStart + nLayerMaskLen; + + PhotoshopParseReportFldNum(nIndent, "Length", nLayerMaskLen, ""); + if(nLayerMaskLen == 0) + { + return true; + } + else + { + if(bDecOk) + bDecOk &= PhotoshopParseLayerInfo(nPos, nIndent, pDibTemp); + if(bDecOk) + bDecOk &= PhotoshopParseGlobalLayerMaskInfo(nPos, nIndent); + if(bDecOk) + { + //while ((bDecOk) && (nPos < nPosEnd)) { + //while ((bDecOk) && ((nPos+12) < nPosEnd)) { + while((bDecOk) && (nPosStart + nLayerMaskLen - nPos > 12)) + { + bDecOk &= PhotoshopParseAddtlLayerInfo(nPos, nIndent); + } + } + } + + if(bDecOk) + { + // Skip data + nPos = nPosEnd; + } + + return bDecOk; +} + +// Parse the Photoshop IRB Layer Info Section +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// - pDibTemp = DIB for image display +// OUTPUT: +// - nPos = File position after reading the block +// +bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * pDibTemp) +{ + QString strVal; + + bool bDecOk = true; + + PhotoshopParseReportNote(nIndent, "Layer Info:"); + nIndent++; + + uint32_t nLayerLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Length", nLayerLen, ""); + if(nLayerLen == 0) + { + return bDecOk; + } + + // Round up length to multiple of 2 + if(nLayerLen % 2 != 0) + { + nLayerLen++; + } + + // Save file position + uint32_t nPosStart = nPos; + + // According to Adobe, "Layer count" is defined as follows: + // - If it is a negative number, its absolute value is the number of layers and the + // first alpha channel contains the transparency data for the merged result. + // Therefore, we'll treat it as signed short and take absolute value + uint16_t nLayerCountU = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + + signed short nLayerCountS = (signed short) nLayerCountU; + + uint32_t nLayerCount = abs(nLayerCountS); + + PhotoshopParseReportFldNum(nIndent, "Layer count", nLayerCount, ""); + if(nLayerCountU & 0x8000) + { + PhotoshopParseReportNote(nIndent, "First alpha channel contains transparency for merged result"); + } + + tsLayerAllInfo sLayerAllInfo; + + sLayerAllInfo.nNumLayers = nLayerCount; + sLayerAllInfo.psLayers = new tsLayerInfo[nLayerCount]; + Q_ASSERT(sLayerAllInfo.psLayers); + + for(uint32_t nLayerInd = 0; (bDecOk) && (nLayerInd < nLayerCount); nLayerInd++) + { + // Clear the channel array + sLayerAllInfo.psLayers[nLayerInd].pnChanLen = NULL; + QString strTmp; + + strTmp = QString("Layer #%1").arg(nLayerInd); + PhotoshopParseReportFldOffset(nIndent, strTmp, nPos); + if(bDecOk) + bDecOk &= PhotoshopParseLayerRecord(nPos, nIndent, &sLayerAllInfo.psLayers[nLayerInd]); + } + + PhotoshopParseReportNote(nIndent, "Channel Image Data:"); + QString strLine; + + uint32_t nNumChans; + + uint32_t nWidth; + + uint32_t nHeight; + + uint32_t nPosLastLayer = 0; + + uint32_t nPosLastChan = 0; + + for(uint32_t nLayerInd = 0; (bDecOk) && (nLayerInd < nLayerCount); nLayerInd++) + { + nNumChans = sLayerAllInfo.psLayers[nLayerInd].nNumChans; + nWidth = sLayerAllInfo.psLayers[nLayerInd].nWidth; + nHeight = sLayerAllInfo.psLayers[nLayerInd].nHeight; + + unsigned char *pDibBits = NULL; + +#ifdef PS_IMG_DEC_EN + if((pDibTemp) && (m_bDisplayLayer) && (nLayerInd == m_nDisplayLayerInd)) + { + // Allocate the device-independent bitmap (DIB) + // - Although we are creating a 32-bit DIB, it should also + // work to run in 16- and 8-bit modes + + // Start by killing old DIB since we might be changing its dimensions +//@@ pDibTemp->Kill(); + + // Allocate the new DIB +//@@ bool bDibOk = pDibTemp->CreateDIB(nWidth, nHeight, 32); + + // Should only return false if already exists or failed to allocate +//@@ if(bDibOk) + { + // Fetch the actual pixel array +//@@ pDibBits = (unsigned char *) (pDibTemp->GetDIBBitArray()); + } + } +#endif + + nPosLastLayer = nPos; + for(uint32_t nChanInd = 0; (bDecOk) && (nChanInd < nNumChans); nChanInd++) + { + nPosLastChan = nPos; + strLine = + QString("Layer %1/%2, Channel %3/%4").arg(nLayerInd + 1, 3).arg(nLayerCount, 3).arg(nChanInd + 1, 2).arg(nNumChans, 2); + //m_pLog->AddLine(strLine); + PhotoshopParseReportNote(nIndent + 1, strLine); + if(bDecOk) + { + + // Fetch the channel ID to determine what RGB channel to map to + // - Layer 0 (background): 0->R, 1->G, 2->B + // - Layer n (other): 65535->A, 0->R, 1->G, 2->B + uint32_t nChanID = sLayerAllInfo.psLayers[nLayerInd].pnChanID[nChanInd]; + + // Parse, and optionally paint the DIB + // NOTE: For uncompressed channels, the width & height generally appear to be zero + // According to the spec: + // If the compression code is 0, the image data is just the raw image data, + // whose size is calculated as (LayerBottom-LayerTop)* (LayerRight-LayerLeft) + + bDecOk &= PhotoshopParseChannelImageData(nPos, nIndent + 1, nWidth, nHeight, nChanID, pDibBits); + } + strLine = + QString("CurPos @ 0x%1, bDecOk=%2, LastLayer @ 0x%3, LastChan @ 0x%4").arg(nPos, 8, 16, + QChar('0')).arg(bDecOk).arg(nPosLastLayer, 8, + 16, + QChar('0')). + arg(nPosLastChan, 8, 16, QChar('0')); + //m_pLog->AddLine(strLine); + //PhotoshopParseReportNote(nIndent+1,strLine); + } + } + + // Pad out to specified length + signed nPad; + + nPad = nPosStart + nLayerLen - nPos; + if(nPad > 0) + { + nPos += nPad; + } + + // Deallocate + if(sLayerAllInfo.psLayers) + { + for(uint32_t nLayerInd = 0; (nLayerInd < sLayerAllInfo.nNumLayers); nLayerInd++) + { + nNumChans = sLayerAllInfo.psLayers[nLayerInd].nNumChans; + for(uint32_t nChanInd = 0; (bDecOk) && (nChanInd < nNumChans); nChanInd++) + { + delete[]sLayerAllInfo.psLayers[nLayerInd].pnChanLen; + sLayerAllInfo.psLayers[nLayerInd].pnChanLen = NULL; + delete[]sLayerAllInfo.psLayers[nLayerInd].pnChanID; + sLayerAllInfo.psLayers[nLayerInd].pnChanID = NULL; + } + } + delete[]sLayerAllInfo.psLayers; + sLayerAllInfo.psLayers = NULL; + } + + return bDecOk; +} + +// Parse the Photoshop IRB Layer Record +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +bool CDecodePs::PhotoshopParseLayerRecord(uint32_t &nPos, uint32_t nIndent, tsLayerInfo * pLayerInfo) +{ + QString strVal; + + bool bDecOk = true; + + Q_ASSERT(pLayerInfo); + + PhotoshopParseReportNote(nIndent, "Layer Record:"); + nIndent++; + + uint32_t nRect1, nRect2, nRect3, nRect4; + + nRect1 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nRect2 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nRect3 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nRect4 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Rect Top", nRect1, ""); + PhotoshopParseReportFldNum(nIndent, "Rect Left", nRect2, ""); + PhotoshopParseReportFldNum(nIndent, "Rect Bottom", nRect3, ""); + PhotoshopParseReportFldNum(nIndent, "Rect Right", nRect4, ""); + + pLayerInfo->nHeight = nRect3 - nRect1; + pLayerInfo->nWidth = nRect4 - nRect2; + //nHeight = nRect3-nRect1; + + uint32_t nNumChans = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Number of channels", nNumChans, ""); + + //nChans = nNumChans; + pLayerInfo->nNumChans = nNumChans; + + Q_ASSERT(pLayerInfo->pnChanLen == NULL); + pLayerInfo->pnChanLen = new uint32_t[nNumChans]; + + Q_ASSERT(pLayerInfo->pnChanLen); + pLayerInfo->pnChanID = new uint32_t[nNumChans]; + + Q_ASSERT(pLayerInfo->pnChanID); + + for(uint32_t nChanInd = 0; nChanInd < nNumChans; nChanInd++) + { + uint32_t nChanID = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + + uint32_t nChanDataLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + QString strField; + + strField = QString("Channel index #%1").arg(nChanInd); + strVal = QString("ID=%1 DataLength=0x%2").arg(nChanID, 5).arg(nChanDataLen, 8, 16, QChar('0')); + PhotoshopParseReportFldStr(nIndent, strField, strVal); + pLayerInfo->pnChanID[nChanInd] = nChanID; + pLayerInfo->pnChanLen[nChanInd] = nChanDataLen; + } + QString strBlendModeSig = m_pWBuf->BufReadStrn(nPos, 4); + + nPos += 4; + PhotoshopParseReportFldStr(nIndent, "Blend mode signature", strBlendModeSig); + uint32_t nBlendModeKey = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + PhotoshopParseReportFldEnum(nIndent, "Blend mode key", BIM_T_ENUM_BLEND_MODE_KEY, nBlendModeKey); + uint32_t nOpacity = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Opacity", nOpacity, "(0=transparent ... 255=opaque)"); + m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); // unsigned nClipping + m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); // unsigned nFlags + m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); // unsigned nFiller + uint32_t nExtraDataLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + uint32_t nPosExtra = nPos; + + if(bDecOk) + bDecOk &= PhotoshopParseLayerMask(nPos, nIndent); + if(bDecOk) + bDecOk &= PhotoshopParseLayerBlendingRanges(nPos, nIndent); + + if(bDecOk) + { + uint32_t nLayerNameLen = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + + QString strLayerName = m_pWBuf->BufReadStrn(nPos, nLayerNameLen); + + nPos += nLayerNameLen; + // According to spec, length is padded to multiple of 4 bytes, + uint32_t nSkip = 0; + + nSkip = (4 - ((1 + nLayerNameLen) % 4)) % 4; + nPos += nSkip; + } + + // Now use up the "extra bytes" with "Additional Layer Info" + while((bDecOk) && (nPos < nPosExtra + nExtraDataLen)) + { + if(bDecOk) + bDecOk &= PhotoshopParseAddtlLayerInfo(nPos, nIndent); + } + + return bDecOk; +} + +// Parse the Photoshop IRB Layer Mask +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +bool CDecodePs::PhotoshopParseLayerMask(uint32_t &nPos, uint32_t nIndent) +{ + QString strVal; + + bool bDecOk = true; + + PhotoshopParseReportNote(nIndent, "Layer Mask / Adjustment layer data:"); + nIndent++; + + uint32_t nLayerMaskLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + if(nLayerMaskLen == 0) + { + return bDecOk; + } + + uint32_t nRectA1, nRectA2, nRectA3, nRectA4; + + uint32_t nRectB1, nRectB2, nRectB3, nRectB4; + + nRectA1 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nRectA2 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nRectA3 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nRectA4 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + uint32_t nTmp; + + m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); // unsigned nDefaultColor + uint32_t nFlags = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + + //FIXME: Is this correct? + if(nLayerMaskLen == 20) + { + m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); // unsigned nPad + } + + if(nFlags & (1 << 4)) + { + uint32_t nMaskParams = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + + if(nMaskParams & (1 << 0)) + { + // User mask density, 1 byte + nTmp = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + } + if(nMaskParams & (1 << 1)) + { + // User mask feather, 8 bytes, double + nTmp = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nTmp = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + } + if(nMaskParams & (1 << 2)) + { + // Vector mask density, 1 byte + nTmp = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + } + if(nMaskParams & (1 << 3)) + { + // Vector mask feather, 8 bytes, double + nTmp = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nTmp = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + } + + m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); // unsigned nPadding + m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); // unsigned nRealFlags + m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); // unsigned nRealUserMaskBackground + nRectB1 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nRectB2 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nRectB3 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + nRectB4 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + } + + return bDecOk; +} + +// Parse the Photoshop IRB Layer blending ranges data +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +bool CDecodePs::PhotoshopParseLayerBlendingRanges(uint32_t &nPos, uint32_t nIndent) +{ + QString strVal; + + bool bDecOk = true; + + PhotoshopParseReportNote(nIndent, "Layer blending ranges data:"); + nIndent++; + + uint32_t nLayerBlendLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + if(nLayerBlendLen == 0) + { + return bDecOk; + } + + m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); // unsigned nCompGrayBlendSrc + m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); // unsigned nCompGrayBlendDstRng + uint32_t nNumChans; + + nNumChans = (nLayerBlendLen - 8) / 8; + + for(uint32_t nChanInd = 0; nChanInd < nNumChans; nChanInd++) + { + m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); // unsigned nSrcRng + m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); // unsigned nDstRng + } + return bDecOk; +} + +// Parse the Photoshop IRB Channel image data +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// - nChan = Channel being parsed (used for DIB mapping) +// - pDibTemp = DIB for rendering (NULL if disabled) +// OUTPUT: +// - nPos = File position after reading the block +// +bool CDecodePs::PhotoshopParseChannelImageData(uint32_t &nPos, uint32_t nIndent, uint32_t nWidth, uint32_t nHeight, + uint32_t nChan, unsigned char *pDibBits) +{ + bool bDecOk = true; + + uint32_t nCompressionMethod = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent + 1, "Compression method", nCompressionMethod, ""); + + if(nCompressionMethod == 1) + { + // *** RLE Compression *** + if(nHeight == 0) + { + return true; + } + // Read the line lengths into an array + // - LOOP [nHeight] + // - 16-bit: row length + // - ENDLOOP + uint32_t *anRowLen; + + anRowLen = new uint32_t[nHeight]; + + Q_ASSERT(anRowLen); + for(uint32_t nRow = 0; nRow < nHeight; nRow++) + { + anRowLen[nRow] = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + } + + // Read the compressed data + for(uint32_t nRow = 0; (bDecOk) && (nRow < nHeight); nRow++) + { + uint32_t nRowLen = anRowLen[nRow]; + + bDecOk = PhotoshopDecodeRowRle(nPos, nWidth, nHeight, nRow, nRowLen, nChan, pDibBits); + } //nRow + + // Deallocate + if(anRowLen) + { + delete[]anRowLen; + anRowLen = NULL; + } + + } + else if(nCompressionMethod == 0) + { + // *** RAW (no compression) + if(nHeight == 0) + { + return true; + } + for(uint32_t nRow = 0; (bDecOk) && (nRow < nHeight); nRow++) + { + bDecOk = PhotoshopDecodeRowUncomp(nPos, nWidth, nHeight, nRow, nChan, pDibBits); + } + + } + else + { + m_pLog->AddLineWarn("Unsupported compression method. Stopping."); + bDecOk = false; + return bDecOk; + } + + return bDecOk; +} + +bool CDecodePs::PhotoshopDecodeRowUncomp(uint32_t &nPos, uint32_t nWidth, uint32_t nHeight, uint32_t nRow, uint32_t nChanID, + unsigned char *pDibBits) +{ + bool bDecOk = true; + + unsigned char nVal; + + uint32_t nRowActual; + + uint32_t nPixByte; + + for(uint32_t nCol = 0; (bDecOk) && (nCol < nWidth); nCol++) + { + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + +#ifdef PS_IMG_DEC_EN + if(pDibBits) + { + nRowActual = nHeight - nRow - 1; // Need to flip vertical for DIB + nPixByte = (nRowActual * nWidth + nCol) * sizeof(RGBQUAD); + + // Assign the RGB pixel map + pDibBits[nPixByte + 3] = 0; + if(nChanID == 0) + { + pDibBits[nPixByte + 2] = nVal; + } + else if(nChanID == 1) + { + pDibBits[nPixByte + 1] = nVal; + } + else if(nChanID == 2) + { + pDibBits[nPixByte + 0] = nVal; + } + else + { + } + } // pDibBits +#endif + + } // nCol + + return bDecOk; +} + +bool CDecodePs::PhotoshopDecodeRowRle(uint32_t &nPos, uint32_t nWidth, uint32_t nHeight, uint32_t nRow, uint32_t nRowLen, + uint32_t nChanID, unsigned char *pDibBits) +{ + bool bDecOk = true; + + unsigned char nRleRun; + + signed char nRleRunS; + + uint32_t nRleRunCnt; + + unsigned char nRleVal; + + uint32_t nRowOffsetComp; // Row offset (compressed size) + + uint32_t nRowOffsetDecomp; // Row offset (decompressed size) + + uint32_t nRowOffsetDecompLast; + + uint32_t nRowActual; + + uint32_t nPixByte; + + // Decompress the row data + nRowOffsetComp = 0; + nRowOffsetDecomp = 0; + nRowOffsetDecompLast = 0; + while((bDecOk) && (nRowOffsetComp < nRowLen)) + { + + // Save the position in the row before decompressing + // the current RLE encoded entry + nRowOffsetDecompLast = nRowOffsetDecomp; + + nRleRun = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + nRleRunS = (signed char) (nRleRun); + nRowOffsetComp++; + + if(nRleRunS < 0) + { + // Replicate the next byte + nRleRunCnt = 1 - nRleRunS; + nRleVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + nRowOffsetComp++; + nRowOffsetDecomp += nRleRunCnt; + +#ifdef PS_IMG_DEC_EN + if(pDibBits) + { + nRowActual = nHeight - nRow - 1; // Need to flip vertical for DIB + for(uint32_t nRunInd = 0; nRunInd < nRleRunCnt; nRunInd++) + { + nPixByte = (nRowActual * nWidth + nRowOffsetDecompLast + nRunInd) * sizeof(RGBQUAD); + + // Assign the RGB pixel map + pDibBits[nPixByte + 3] = 0; + if(nChanID == 0) + { + pDibBits[nPixByte + 2] = nRleVal; + } + else if(nChanID == 1) + { + pDibBits[nPixByte + 1] = nRleVal; + } + else if(nChanID == 2) + { + pDibBits[nPixByte + 0] = nRleVal; + } + else + { + } + } // nRunInd + } // pDibBits +#endif + + } + else + { + + // Copy the next bytes as-is + nRleRunCnt = 1 + nRleRunS; + for(uint32_t nRunInd = 0; nRunInd < nRleRunCnt; nRunInd++) + { + nRleVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + nRowOffsetComp++; + nRowOffsetDecomp++; + +#ifdef PS_IMG_DEC_EN + if(pDibBits) + { + nRowActual = nHeight - nRow - 1; // Need to flip vertical for DIB + nPixByte = (nRowActual * nWidth + nRowOffsetDecompLast + nRunInd) * sizeof(RGBQUAD); + + // Assign the RGB pixel map + pDibBits[nPixByte + 3] = 0; + if(nChanID == 0) + { + pDibBits[nPixByte + 2] = nRleVal; + } + else if(nChanID == 1) + { + pDibBits[nPixByte + 1] = nRleVal; + } + else if(nChanID == 2) + { + pDibBits[nPixByte + 0] = nRleVal; + } + else + { + } + } // pDibBits +#endif + + } // nRunInd + } // nRleRunS + + } // nRowOffsetComp + + // Now that we've finished the row, compare the decompressed size + // to the expected width + if(nRowOffsetDecomp != nWidth) + { + bDecOk = false; + Q_ASSERT(false); + } + + return bDecOk; +} + +// Parse the Photoshop IRB Layer and Mask Info Section (from File Header) +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +// NOTE: +// - Image decoding (into DIB) is enabled if pDibBits is not NULL +// +bool CDecodePs::PhotoshopParseImageData(uint32_t &nPos, uint32_t nIndent, tsImageInfo * psImageInfo, unsigned char *pDibBits) +{ + Q_ASSERT(psImageInfo); + + QString strVal; + + //PhotoshopParseReportNote(nIndent,"Image data section:"); + PhotoshopParseReportFldOffset(nIndent, "Image data section:", nPos); + + bool bDecOk = true; + + //---- + uint32_t nWidth = psImageInfo->nImageWidth; + + uint32_t nHeight = psImageInfo->nImageHeight; + + uint32_t nNumChans = psImageInfo->nNumChans; + + //---- + + uint32_t nCompressionMethod = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent + 1, "Compression method", nCompressionMethod, ""); + + // ----------------------------------------------------- + + if(nCompressionMethod == 1) + { + // *** RLE Compression *** + if(nHeight == 0) + { + return true; + } + + // Read the line lengths into an array + // - LOOP [nNumChans] + // - LOOP [nHeight] + // - 16-bit: row length + // - ENDLOOP + // - ENDLOOP + uint32_t *anRowLen; + + anRowLen = new uint32_t[nNumChans * nHeight]; + + Q_ASSERT(anRowLen); + for(uint32_t nRow = 0; nRow < (nNumChans * nHeight); nRow++) + { + anRowLen[nRow] = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + } + + // Read the compressed data + for(uint32_t nChan = 0; nChan < nNumChans; nChan++) + { + for(uint32_t nRow = 0; (bDecOk) && (nRow < nHeight); nRow++) + { + uint32_t nRowLen = anRowLen[(nChan * nHeight) + nRow]; + + bDecOk = PhotoshopDecodeRowRle(nPos, nWidth, nHeight, nRow, nRowLen, nChan, pDibBits); + } // nRow + } // nChan + + // Deallocate + if(anRowLen) + { + delete[]anRowLen; + anRowLen = NULL; + } + + } + else if(nCompressionMethod == 0) + { + // *** RAW (no compression) + + // NOTE: BUG BUG BUG + // It seems that most examples I see with RAW layers have nHeight=nWidth=0 + // or else the nChan=0xFFFF. Why aren't width & height defined? + + if(nHeight * nNumChans == 0) + { + return true; + } + for(uint32_t nChan = 0; nChan < nNumChans; nChan++) + { + for(uint32_t nRow = 0; (bDecOk) && (nRow < nHeight); nRow++) + { + bDecOk = PhotoshopDecodeRowUncomp(nPos, nWidth, nHeight, nRow, nChan, pDibBits); + } //nRow + } //nChan + + } + else + { + m_pLog->AddLineWarn("Unsupported compression method. Stopping."); + bDecOk = false; + return bDecOk; + } + + return bDecOk; + +} + +// Parse the Photoshop IRB Global layer mask info +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +bool CDecodePs::PhotoshopParseGlobalLayerMaskInfo(uint32_t &nPos, uint32_t nIndent) +{ + QString strVal; + + bool bDecOk = true; + + PhotoshopParseReportNote(nIndent, "Global layer mask info:"); + nIndent++; + + uint32_t nInfoLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + if(nInfoLen == 0) + { + return bDecOk; + } + uint32_t nPosStart = nPos; + + m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); // unsigned nOverlayColorSpace + m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); // unsigned nColComp1 + m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); // unsigned nColComp2 + m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); // unsigned nColComp3 + m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); // unsigned nColComp4 + m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); // unsigned nOpacity + m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); // unsigned nKind + + // Variable Filler: zeros + //nPos += nInfoLen - 17; + nPos = nPosStart + nInfoLen; + + return bDecOk; +} + +// Parse the Photoshop IRB Additional layer info +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +bool CDecodePs::PhotoshopParseAddtlLayerInfo(uint32_t &nPos, uint32_t nIndent) +{ + bool bDecOk = true; + + uint32_t nPosStart; + + PhotoshopParseReportNote(nIndent, "Additional layer info:"); + nIndent++; + + QString strSig = m_pWBuf->BufReadStrn(nPos, 4); + + nPos += 4; + + if(strSig != "8BIM") + { + // Signature did not match! + QString strError; + + strError = QString("ERROR: Addtl Layer Info signature unknown [%1] @ 0x%2").arg(strSig).arg(nPos - 4, 8, 16, QChar('0')); + PhotoshopParseReportNote(nIndent, strError); + +#ifdef DEBUG_LOG + QString strDebug; + + strDebug = + QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", -10).arg(strError); + qDebug() << (strDebug); +#else + Q_ASSERT(false); +#endif + bDecOk = false; + return false; + } + + QString strKey = m_pWBuf->BufReadStrn(nPos, 4); + + nPos += 4; + PhotoshopParseReportFldStr(nIndent, "Key", strKey); + bool bLen8B = false; + + if(strKey == "Lr16") + { + // FIXME: Might need some additional processing here? + Q_ASSERT(false); + } + /* + //CAL! FIXME: Empirically, I didn't see 8B length being used by "FMsk" in psd-flame-icon.psd @ 0x7A458 + if (strKey == "LMsk") { bLen8B = true; } + if (strKey == "Lr16") { bLen8B = true; } + if (strKey == "Lr32") { bLen8B = true; } + if (strKey == "Layr") { bLen8B = true; } + if (strKey == "Mt16") { bLen8B = true; } + if (strKey == "Mt32") { bLen8B = true; } + if (strKey == "Mtrn") { bLen8B = true; } + if (strKey == "Alph") { bLen8B = true; } + if (strKey == "FMsk") { bLen8B = true; } + if (strKey == "lnk2") { bLen8B = true; } + if (strKey == "FEid") { bLen8B = true; } + if (strKey == "FXid") { bLen8B = true; } + if (strKey == "PxSD") { bLen8B = true; } + */ + + uint32_t nLen; + + if(!bLen8B) + { + nLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + } + else + { + // DUMMY for now + //FIXME: Untested + nLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + Q_ASSERT(nLen == 0); + nLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + } + PhotoshopParseReportFldNum(nIndent, "Length", nLen, ""); + if(nLen > 0) + { + PhotoshopParseReportFldHex(nIndent, strKey, nPos, nLen); + } + + uint32_t nVal; + + QString sStr; + + uint32_t nPosOffset = 0; + + if(strKey == "luni") + { + sStr = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + PhotoshopParseReportFldStr(nIndent, "Layer Name (Unicode)", sStr); + } + else if(strKey == "lnsr") + { + nVal = m_pWBuf->BufX(nPos, 4, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Layer Name Source ID", nVal, ""); + } + else if(strKey == "lyid") + { + nVal = m_pWBuf->BufX(nPos, 4, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Layer ID", nVal, ""); + } + else if(strKey == "clbl") + { + nVal = m_pWBuf->BufX(nPos, 4, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Blend clipped elements", nVal); + } + else if(strKey == "infx") + { + nVal = m_pWBuf->BufX(nPos, 4, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Blend interior elements", nVal); + } + else if(strKey == "knko") + { + nVal = m_pWBuf->BufX(nPos, 4, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Knockout", nVal); + } + + nPosStart = nPos; + + // Skip data + nPos = nPosStart + nLen; + + // FIXME: It appears that we need to pad out to ensure that + // length is multiple of 4 (not file position). + uint32_t nMod; + + nMod = (nLen % 4); + if(nMod != 0) + { + nPos += (4 - nMod); + } + + return bDecOk; +} + +// ------------- + +// Parse the Photoshop IRB Image Resources Section +// - Iteratively works through the individual Image Resource Blocks (IRB) +// +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +bool CDecodePs::PhotoshopParseImageResourcesSection(uint32_t &nPos, uint32_t nIndent) +{ + QString strVal; + + bool bDecOk = true; + + PhotoshopParseReportNote(nIndent, "Image Resources Section:"); + nIndent++; + + uint32_t nPosSectionStart = 0; + + uint32_t nPosSectionEnd = 0; + + uint32_t nImgResLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Length", nImgResLen, ""); + + nPosSectionStart = nPos; + nPosSectionEnd = nPos + nImgResLen; + + while(nPos < nPosSectionEnd) + { + bDecOk &= PhotoshopParseImageResourceBlock(nPos, nIndent); + if(!bDecOk) + { + return false; + } + } + return bDecOk; +} + +// Parse the Photoshop IRB (Image Resource Block) +// - Decode the 8BIM ID and invoke the appropriate IRB parsing handler +// +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +bool CDecodePs::PhotoshopParseImageResourceBlock(uint32_t &nPos, uint32_t nIndent) +{ + QString strVal; + + //bool bDecOk = true; + + //PhotoshopParseReportNote(nIndent,"Image Resource Block:"); + //nIndent++; + + // + // - Signature (4B) "8BIM" + // - NameLen (2B) Generally 0 + // - Name (NameLen Bytes, min 1 Byte) Usually empty (NULL) + // - BimLen (4B) Length of 8BIM data + // - Data (1..BimLen) Field data + // + + QString strSig = m_pWBuf->BufReadStrn(nPos, 4); + + nPos += 4; + + if(strSig != "8BIM") + { + // Signature did not match! + QString strError; + + strError = QString("ERROR: IRB signature unknown [%1]").arg(strSig); + PhotoshopParseReportNote(nIndent, strError); + +#ifdef DEBUG_LOG + QString strDebug; + + strDebug = + QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", -10).arg(strError); + qDebug() << (strDebug); +#else + Q_ASSERT(false); +#endif + + return false;; + } + + uint32_t nBimId = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + + uint32_t nResNameLen = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + + QString strResName = m_pWBuf->BufReadStrn(nPos, nResNameLen); + + nPos += nResNameLen; + + // If size wasn't even, pad here + if((1 + nResNameLen) % 2 != 0) + { + nPos += 1; + } + uint32_t nBimLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + QString strTmp; + + QString strBimName; + + QString strByte; + + // Lookup 8BIM defined name + QString strBimDefName = ""; + + bool bBimKnown = false; + + uint32_t nFldInd = 0; + + bBimKnown = FindBimRecord(nBimId, nFldInd); + + if(bBimKnown) + { + strBimDefName = asBimRecords[nFldInd].strRecordName; + } + + strTmp = + QString("8BIM: [0x%1] Name=\"%2\" Len=[0x%3] DefinedName=\"%4\"").arg(nBimId, 4, 16, QChar('0')).arg(strBimName).arg(nBimLen, + 4, 16, + QChar + ('0')). + arg(strBimDefName); + PhotoshopParseReportNote(nIndent, strTmp); + + nIndent++; + + if(nBimLen == 0) + { + // If length is zero, then skip this block + PhotoshopParseReportNote(nIndent, "Length is zero. Skipping."); + + } + else if(bBimKnown) + { + + // Save the file pointer + uint32_t nPosSaved; + + nPosSaved = nPos; + + // Calculate the end of the record + // - This is used for parsing records that have a conditional parsing + // of additional fields "if length permits". + uint32_t nPosEnd; + + nPosEnd = nPos + nBimLen - 1; + + switch (asBimRecords[nFldInd].eBimType) + { + + case BIM_T_STR: + strVal = DecodeIptcValue(IPTC_T_STR, nBimLen, nPos); + PhotoshopParseReportFldStr(nIndent, strBimDefName, strVal); + break; + case BIM_T_HEX: + PhotoshopParseReportFldHex(nIndent, strBimDefName, nPos, nBimLen); + nPos += nBimLen; + break; + + case BIM_T_PS_THUMB_RES: + PhotoshopParseThumbnailResource(nPos, nIndent); + // Since this block has image data that we are not going to parse, + // force the end position to match the length + nPos = nPosSaved + nBimLen; + break; + case BIM_T_PS_SLICES: + PhotoshopParseSliceHeader(nPos, nIndent, nPosEnd); + break; + case BIM_T_PS_DESCRIPTOR: + PhotoshopParseDescriptor(nPos, nIndent); + break; + case BIM_T_PS_VER_INFO: + PhotoshopParseVersionInfo(nPos, nIndent); + break; + case BIM_T_PS_PRINT_SCALE: + PhotoshopParsePrintScale(nPos, nIndent); + break; + case BIM_T_PS_PIXEL_ASPECT_RATIO: + PhotoshopParsePixelAspectRatio(nPos, nIndent); + break; + case BIM_T_PS_DOC_SPECIFIC_SEED: + PhotoshopParseDocSpecificSeed(nPos, nIndent); + break; + case BIM_T_PS_RESOLUTION_INFO: + PhotoshopParseResolutionInfo(nPos, nIndent); + break; + case BIM_T_PS_GRID_GUIDES: + PhotoshopParseGridGuides(nPos, nIndent); + break; + case BIM_T_PS_GLOBAL_ANGLE: + PhotoshopParseGlobalAngle(nPos, nIndent); + break; + case BIM_T_PS_GLOBAL_ALTITUDE: + PhotoshopParseGlobalAltitude(nPos, nIndent); + break; + case BIM_T_PS_PRINT_FLAGS: + PhotoshopParsePrintFlags(nPos, nIndent); + break; + case BIM_T_PS_PRINT_FLAGS_INFO: + PhotoshopParsePrintFlagsInfo(nPos, nIndent); + break; + case BIM_T_PS_COPYRIGHT_FLAG: + PhotoshopParseCopyrightFlag(nPos, nIndent); + break; + case BIM_T_PS_LAYER_STATE_INFO: + PhotoshopParseLayerStateInfo(nPos, nIndent); + break; + case BIM_T_PS_LAYER_GROUP_INFO: + PhotoshopParseLayerGroupInfo(nPos, nIndent, nBimLen); + break; + case BIM_T_PS_LAYER_GROUP_ENABLED: + PhotoshopParseLayerGroupEnabled(nPos, nIndent, nBimLen); + break; + case BIM_T_PS_LAYER_SELECT_ID: + PhotoshopParseLayerSelectId(nPos, nIndent); + break; + + case BIM_T_PS_STR_UNI: + PhotoshopParseStringUni(nPos, nIndent); + break; + case BIM_T_PS_STR_ASC: + strVal += m_pWBuf->BufReadStrn(nPos, nBimLen); + nPos += nBimLen; + PhotoshopParseReportFldStr(nIndent, strBimDefName, strVal); + break; + case BIM_T_PS_STR_ASC_LONG: + strVal = "\n"; + strVal += m_pWBuf->BufReadStrn(nPos, nBimLen); + nPos += nBimLen; + PhotoshopParseReportFldStr(nIndent, strBimDefName, strVal); + break; + + case BIM_T_JPEG_QUAL: // (0x0406) + // JPEG Quality + PhotoshopParseJpegQuality(nPos, nIndent, nPosEnd); + break; + + case BIM_T_IPTC_NAA: // (0x0404) + // IPTC-NAA + DecodeIptc(nPos, nBimLen, nIndent); + break; + + default: + return false; + break; + } // switch + + // Check to see if we ended up with a length mismatch after decoding + if(nPos > nPosEnd + 1) + { + // Length mismatch detected: we read too much (versus length) + strTmp = + QString + ("ERROR: Parsing exceeded expected length. Stopping decode. BIM=[%s], CurPos=[0x%08X], ExpPosEnd=[0x%08X], ExpLen=[%u]"). + arg(strBimDefName).arg(nPos, 8, 16, QChar('0')).arg(nPosEnd + 1, 8, 16, QChar('0')).arg(nBimLen); + m_pLog->AddLineErr(strTmp); +#ifdef DEBUG_LOG + QString strDebug; + + strDebug = + QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", -10).arg(strTmp); + qDebug() << (strDebug); +#else + Q_ASSERT(false); +#endif + + // TODO: Add interactive error message here + + // Now we should roll-back the file position to the position indicated + // by the length. This will help us stay on track for next decoding. + nPos = nPosEnd + 1; + + return false; + } + else if(nPos != nPosEnd + 1) + { + // Length mismatch detected: we read too little (versus length) + // This is generally an indication that either I haven't accurately captured the + // specific block parsing format or else the specification is loose. + strTmp = + QString("WARNING: Parsing offset length mismatch. Current pos=[0x%1], expected end pos=[0x%2], expect length=[%3]"). + arg(nPos, 8, 16, QChar('0')).arg(nPosEnd + 1, 8, 16, QChar('0')).arg(nBimLen); + m_pLog->AddLineWarn(strTmp); +#ifdef DEBUG_LOG + QString strDebug; + + strDebug = + QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", -10).arg(strTmp); + qDebug() << (strDebug); +#endif + return false; + } + + // Reset the file marker + nPos = nPosSaved; + } // bBimKnown + + // Skip rest of 8BIM + nPos += nBimLen; + + // FIXME: correct to make for even parity? + if((nBimLen % 2) != 0) + nPos++; + + return true; +} + +// Parse the Photoshop IRB Slice Header +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// - nPosEnd = File position at end of block (last byte address) +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseSliceHeader(uint32_t &nPos, uint32_t nIndent, uint32_t nPosEnd) +{ + uint32_t nVal; + + QString strVal; + + uint32_t nPosOffset; + + PhotoshopParseReportNote(nIndent, "Slice Header:"); + nIndent++; + + uint32_t nSliceVer = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Version", nSliceVer, ""); + + if(nSliceVer == 6) + { + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Bound Rect (top)", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Bound Rect (left)", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Bound Rect (bottom)", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Bound Rect (right)", nVal, ""); + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "Name of group of slices", strVal); + uint32_t nNumSlices = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Number of slices", nNumSlices, ""); + + // Slice resource block + if(nNumSlices > 0) + PhotoshopParseReportNote(nIndent, "-----"); + for(uint32_t nSliceInd = 0; nSliceInd < nNumSlices; nSliceInd++) + { + QString strSliceInd; + + strSliceInd = QString("Slice #%1:").arg(nSliceInd); + PhotoshopParseReportNote(nIndent, strSliceInd); + PhotoshopParseSliceResource(nPos, nIndent + 1, nPosEnd); + } + if(nNumSlices > 0) + PhotoshopParseReportNote(nIndent, "-----"); + + } + else if((nSliceVer == 7) || (nSliceVer == 8)) + { + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Descriptor version", nVal, ""); + PhotoshopParseDescriptor(nPos, nIndent); + } + +} + +// Parse the Photoshop IRB Slice Resource +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// - nPosEnd = File position at end of block (last byte address) +// OUTPUT: +// - nPos = File position after reading the block +// NOTE: +// - The nPosEnd is supplied as this resource block depends on some +// conditional field parsing that is "as length allows" +// +void CDecodePs::PhotoshopParseSliceResource(uint32_t &nPos, uint32_t nIndent, uint32_t nPosEnd) +{ + uint32_t nVal; + + QString strVal; + + uint32_t nPosOffset; + + PhotoshopParseReportNote(nIndent, "Slice Resource:"); + nIndent++; + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "ID", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Group ID", nVal, ""); + uint32_t nOrigin = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Origin", nOrigin, ""); + if(nOrigin == 1) + { + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Associated Layer ID", nVal, ""); + } + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "Name", strVal); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Type", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Position (top)", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Position (left)", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Position (bottom)", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Position (right)", nVal, ""); + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "URL", strVal); + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "Target", strVal); + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "Message", strVal); + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "Alt Tag", strVal); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Cell text is HTML", nVal); + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "Cell text", strVal); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Horizontal alignment", nVal, ""); + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Vertical alignment", nVal, ""); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Alpha color", nVal, ""); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Red", nVal, ""); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Green", nVal, ""); + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Blue", nVal, ""); + + // Per standard, we are only supposed to parse additional fields + // "as length allows". This is not a particularly good format + // definition. At this point we'll perform a check to see if + // we have exhausted the length of the block. If not, continue + // to parse the next fields. + // TODO: Do we need to be any more precise than this? (ie. check + // after reading the descriptor version?) + if(nPos <= nPosEnd) + { + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Descriptor version", nVal, ""); + + PhotoshopParseDescriptor(nPos, nIndent); + } + else + { + // We ran out of space in the block so end now + } +} + +// Parse the Photoshop IRB JPEG Quality +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// - nPosEnd = File position at end of block (last byte address) +// OUTPUT: +// - nPos = File position after reading the block +// NOTE: +// - This IRB is private, so reverse-engineered and may not be per spec +// +void CDecodePs::PhotoshopParseJpegQuality(uint32_t &nPos, uint32_t nIndent, uint32_t nPosEnd) +{ + nPosEnd; // Unreferenced param + + uint32_t nVal; + + QString strVal; + + uint32_t nSaveFormat; + + // Save As Quality + // Index 0: Quality level + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + switch (nVal) + { + case 0xFFFD: + m_nQualitySaveAs = 1; + break; + case 0xFFFE: + m_nQualitySaveAs = 2; + break; + case 0xFFFF: + m_nQualitySaveAs = 3; + break; + case 0x0000: + m_nQualitySaveAs = 4; + break; + case 0x0001: + m_nQualitySaveAs = 5; + break; + case 0x0002: + m_nQualitySaveAs = 6; + break; + case 0x0003: + m_nQualitySaveAs = 7; + break; + case 0x0004: + m_nQualitySaveAs = 8; + break; + case 0x0005: + m_nQualitySaveAs = 9; + break; + case 0x0006: + m_nQualitySaveAs = 10; + break; + case 0x0007: + m_nQualitySaveAs = 11; + break; + case 0x0008: + m_nQualitySaveAs = 12; + break; + default: + m_nQualitySaveAs = 0; + break; + } + if(m_nQualitySaveAs != 0) + { + PhotoshopParseReportFldNum(nIndent, "Photoshop Save As Quality", m_nQualitySaveAs, ""); + } + + // TODO: I have observed a file that had this block with length=2, which would end here + // - Perhaps we should check against length in case some older files had a shorter format + // to this IRB? + + // Index 1: Format + nSaveFormat = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + switch (nSaveFormat) + { + case 0x0000: + strVal = "Standard"; + break; + case 0x0001: + strVal = "Optimized"; + break; + case 0x0101: + strVal = "Progressive"; + break; + default: + strVal = "???"; + break; + } + PhotoshopParseReportFldStr(nIndent, "Photoshop Save Format", strVal); + + // Index 2: Progressive Scans + // - Only meaningful if Progressive mode + nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + switch (nVal) + { + case 0x0001: + strVal = "3 Scans"; + break; + case 0x0002: + strVal = "4 Scans"; + break; + case 0x0003: + strVal = "5 Scans"; + break; + default: + strVal = "???"; + break; + } + PhotoshopParseReportFldStr(nIndent, "Photoshop Save Progressive Scans", strVal); + + // Not sure what this byte is for + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "???", nVal, ""); + +} + +// Decode the OSType field and invoke the appropriate IRB parsing handler +// +// INPUT: +// - nPos = File position at start of block +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the block +// +void CDecodePs::PhotoshopParseHandleOsType(QString strOsType, uint32_t &nPos, uint32_t nIndent) +{ + if(strOsType == "obj ") + { + //PhotoshopParseReference(nPos,nIndent); + } + else if(strOsType == "Objc") + { + PhotoshopParseDescriptor(nPos, nIndent); + } + else if(strOsType == "VlLs") + { + PhotoshopParseList(nPos, nIndent); + } + else if(strOsType == "doub") + { + //PhotoshopParseDouble(nPos,nIndent); + } + else if(strOsType == "UntF") + { + //PhotoshopParseUnitFloat(nPos,nIndent); + } + else if(strOsType == "TEXT") + { + PhotoshopParseStringUni(nPos, nIndent); + } + else if(strOsType == "enum") + { + PhotoshopParseEnum(nPos, nIndent); + } + else if(strOsType == "long") + { + PhotoshopParseInteger(nPos, nIndent); + } + else if(strOsType == "bool") + { + PhotoshopParseBool(nPos, nIndent); + } + else if(strOsType == "GlbO") + { + PhotoshopParseDescriptor(nPos, nIndent); + } + else if(strOsType == "type") + { + //PhotoshopParseClass(nPos,nIndent); + } + else if(strOsType == "GlbC") + { + //PhotoshopParseClass(nPos,nIndent); + } + else if(strOsType == "alis") + { + //PhotoshopParseAlias(nPos,nIndent); + } + else if(strOsType == "tdta") + { + //PhotoshopParseRawData(nPos,nIndent); + } + else + { + +#ifdef DEBUG_LOG + QString strError; + + QString strDebug; + + strError = QString("ERROR: Unsupported OSType [%1]").arg(strOsType); + strDebug = + QString("## File=[%-100s] Block=[%-10s] Error=[%s]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", + -10).arg(strError); + qDebug() << (strDebug); +#else + Q_ASSERT(false); +#endif + + } +} + +// Parse the Photoshop IRB OSType Descriptor +// INPUT: +// - nPos = File position at start of entry +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the entry +// +void CDecodePs::PhotoshopParseDescriptor(uint32_t &nPos, uint32_t nIndent) +{ + QString strVal; + + uint32_t nPosOffset; + + PhotoshopParseReportNote(nIndent, "Descriptor:"); + nIndent++; + + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "Name from classID", strVal); + + strVal = PhotoshopParseGetLStrAsc(nPos); + PhotoshopParseReportFldStr(nIndent, "classID", strVal); + + uint32_t nDescNumItems = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Num items in descriptor", nDescNumItems, ""); + + if(nDescNumItems > 0) + PhotoshopParseReportNote(nIndent, "-----"); + for(uint32_t nDescInd = 0; nDescInd < nDescNumItems; nDescInd++) + { + QString strDescInd; + + strDescInd = QString("Descriptor item #%1:").arg(nDescInd); + PhotoshopParseReportNote(nIndent, strDescInd); + + strVal = PhotoshopParseGetLStrAsc(nPos); + PhotoshopParseReportFldStr(nIndent + 1, "Key", strVal); + + QString strOsType; + + strOsType = QString("%1%2%3%4").arg(Buf(nPos + 0)).arg(Buf(nPos + 1)).arg(Buf(nPos + 2)).arg(Buf(nPos + 3)); + nPos += 4; + PhotoshopParseReportFldStr(nIndent + 1, "OSType key", strOsType); + + PhotoshopParseHandleOsType(strOsType, nPos, nIndent + 1); + } + if(nDescNumItems > 0) + PhotoshopParseReportNote(nIndent, "-----"); +} + +// Parse the Photoshop IRB OSType List +// INPUT: +// - nPos = File position at start of entry +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the entry +// +void CDecodePs::PhotoshopParseList(uint32_t &nPos, uint32_t nIndent) +{ + QString strVal; + + QString strLine; + + uint32_t nNumItems = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + + PhotoshopParseReportFldNum(nIndent, "Num items in list", nNumItems, ""); + + if(nNumItems > 0) + PhotoshopParseReportNote(nIndent, "-----"); + for(uint32_t nItemInd = 0; nItemInd < nNumItems; nItemInd++) + { + QString strItemInd; + + strItemInd = QString("Item #%1:").arg(nItemInd); + PhotoshopParseReportNote(nIndent, strItemInd); + + QString strOsType; + + strOsType = QString("%1%2%3%4").arg(Buf(nPos + 0)).arg(Buf(nPos + 1)).arg(Buf(nPos + 2)).arg(Buf(nPos + 3)); + nPos += 4; + PhotoshopParseReportFldStr(nIndent + 1, "OSType key", strVal); + + PhotoshopParseHandleOsType(strOsType, nPos, nIndent + 1); + } + if(nNumItems > 0) + PhotoshopParseReportNote(nIndent, "-----"); +} + +// Parse the Photoshop IRB OSType Integer +// INPUT: +// - nPos = File position at start of entry +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the entry +// +void CDecodePs::PhotoshopParseInteger(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + QString strLine; + + nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + PhotoshopParseReportFldNum(nIndent, "Value", nVal, ""); +} + +// Parse the Photoshop IRB OSType Boolean +// INPUT: +// - nPos = File position at start of entry +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the entry +// +void CDecodePs::PhotoshopParseBool(uint32_t &nPos, uint32_t nIndent) +{ + uint32_t nVal; + + QString strVal; + + QString strLine; + + nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); + PhotoshopParseReportFldBool(nIndent, "Value", nVal); +} + +// Parse the Photoshop IRB OSType Enumerated type +// INPUT: +// - nPos = File position at start of entry +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the entry +// +void CDecodePs::PhotoshopParseEnum(uint32_t &nPos, uint32_t nIndent) +{ + QString strVal; + + QString strLine; + + strVal = PhotoshopParseGetLStrAsc(nPos); + PhotoshopParseReportFldStr(nIndent, "Type", strVal); + + strVal = PhotoshopParseGetLStrAsc(nPos); + PhotoshopParseReportFldStr(nIndent, "Enum", strVal); + +} + +// Parse the Photoshop IRB Unicode String +// INPUT: +// - nPos = File position at start of entry +// - nIndent = Indent level for formatted output +// OUTPUT: +// - nPos = File position after reading the entry +// NOTE: +// - The string is in Photoshop Unicode format (length first) +// +void CDecodePs::PhotoshopParseStringUni(uint32_t &nPos, uint32_t nIndent) +{ + QString strVal; + + uint32_t nPosOffset; + + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); + nPos += nPosOffset; + PhotoshopParseReportFldStr(nIndent, "String", strVal); +} diff --git a/source/DecodePs.h b/source/DecodePs.h index ef6b6c9..030fcbb 100644 --- a/source/DecodePs.h +++ b/source/DecodePs.h @@ -1,233 +1,261 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - This module parses the Photoshop PSD and 8BIM segments (APP13) -// - No rendering is done -// -// ========================================================================== - -#pragma once - -#include "WindowBuf.h" -#include "snoop.h" -#include "SnoopConfig.h" - -#include "Dib.h" - -// -// Structure used for each IPTC field -// - NUM : binary number -// - STR : alphabetic characters, graphic characters, numeric character -// - HEX : -enum teIptcType { IPTC_T_NUM, IPTC_T_NUM1, IPTC_T_NUM2, IPTC_T_HEX, IPTC_T_STR, IPTC_T_UNK, IPTC_T_END }; -struct tsIptcField { - unsigned nRecord; - unsigned nDataSet; - teIptcType eFldType; - CString strFldName; -}; - -// Structure used for each Image Resource Block (8BIM) record -enum teBimType { BIM_T_UNK, BIM_T_STR, BIM_T_HEX, - BIM_T_IPTC_NAA, - BIM_T_JPEG_QUAL, - BIM_T_PS_SLICES, - BIM_T_PS_THUMB_RES, - BIM_T_PS_DESCRIPTOR, - BIM_T_PS_VER_INFO, - BIM_T_PS_RESOLUTION_INFO, - BIM_T_PS_PRINT_SCALE, - BIM_T_PS_PIXEL_ASPECT_RATIO, - BIM_T_PS_DOC_SPECIFIC_SEED, - BIM_T_PS_GRID_GUIDES, - BIM_T_PS_GLOBAL_ANGLE, - BIM_T_PS_GLOBAL_ALTITUDE, - BIM_T_PS_PRINT_FLAGS, - BIM_T_PS_PRINT_FLAGS_INFO, - BIM_T_PS_COPYRIGHT_FLAG, - BIM_T_PS_LAYER_STATE_INFO, - BIM_T_PS_LAYER_GROUP_INFO, - BIM_T_PS_LAYER_GROUP_ENABLED, - BIM_T_PS_LAYER_SELECT_ID, - BIM_T_PS_STR_UNI, - BIM_T_PS_STR_ASC, - BIM_T_PS_STR_ASC_LONG, - BIM_T_END -}; -struct tsBimRecord { - unsigned nCode; // Code value or start code for range - unsigned nCodeEnd; // 0x0000 if not a range, else specifies last code value - teBimType eBimType; - CString strRecordName; -}; - - -// Structure used for each enumerated field in IRB decoding -enum teBimEnumField { - BIM_T_ENUM_UNK, - BIM_T_ENUM_FILE_HDR_COL_MODE, - BIM_T_ENUM_RESOLUTION_INFO_RES_UNIT, - BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, - BIM_T_ENUM_PRINT_SCALE_STYLE, - BIM_T_ENUM_GRID_GUIDE_DIR, - BIM_T_ENUM_BLEND_MODE_KEY, - BIM_T_ENUM_END -}; -struct tsBimEnum { - teBimEnumField eBimEnum; - unsigned nVal; - CString strVal; -}; - -// Byte Swap enable for Photoshop decoding -#define PS_BSWAP false - -// Define the 8BIM/IRB hex output display characteristics -#define PS_HEX_MAX_INLINE 16 // Threshold for displaying hex in-line with field name -#define PS_HEX_MAX_ROW 16 // Maximum number of bytes to report per line -#define PS_HEX_TOTAL 128 // Total number of bytes to report before clipping - -// Define the maximum length Unicode string to display -#define PS_MAX_UNICODE_STRLEN 256 - -// Information about layer and channels within it -struct tsLayerInfo { - unsigned nNumChans; - unsigned* pnChanLen; - unsigned* pnChanID; - unsigned nWidth; - unsigned nHeight; -}; - -// From Layer Info -struct tsLayerAllInfo { - unsigned nNumLayers; - tsLayerInfo* psLayers; -}; - -// From File Header -struct tsImageInfo { - unsigned nImageWidth; - unsigned nImageHeight; - unsigned nNumChans; - unsigned nDepthBpp; -}; - -class CDecodePs -{ -public: - CDecodePs(CwindowBuf* pWBuf,CDocLog* pLog); - ~CDecodePs(void); - - void Reset(); - - bool DecodePsd(unsigned long nPos,CDIB* pDibTemp,unsigned &nWidth,unsigned &nHeight); - bool PhotoshopParseImageResourceBlock(unsigned long &nPos,unsigned nIndent); - -private: - CString PhotoshopParseGetLStrAsc(unsigned long &nPos); - CString PhotoshopParseIndent(unsigned nIndent); - void PhotoshopParseReportNote(unsigned nIndent,CString strNote); - CString PhotoshopParseLookupEnum(teBimEnumField eEnumField,unsigned nVal); - void PhotoshopParseReportFldNum(unsigned nIndent,CString strField,unsigned nVal,CString strUnits); - void PhotoshopParseReportFldBool(unsigned nIndent,CString strField,unsigned nVal); - void PhotoshopParseReportFldEnum(unsigned nIndent,CString strField,teBimEnumField eEnumField,unsigned nVal); - void PhotoshopParseReportFldFixPt(unsigned nIndent,CString strField,unsigned nVal,CString strUnits); - void PhotoshopParseReportFldFloatPt(unsigned nIndent,CString strField,unsigned nVal,CString strUnits); - void PhotoshopParseReportFldDoublePt(unsigned nIndent,CString strField,unsigned nVal1,unsigned nVal2,CString strUnits); - void PhotoshopParseReportFldStr(unsigned nIndent,CString strField,CString strVal); - void PhotoshopParseReportFldOffset(unsigned nIndent,CString strField,unsigned long nOffset); - void PhotoshopParseReportFldHex(unsigned nIndent,CString strField,unsigned long nPosStart,unsigned nLen); - void PhotoshopParseThumbnailResource(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseSliceHeader(unsigned long &nPos,unsigned nIndent,unsigned long nPosEnd); - void PhotoshopParseSliceResource(unsigned long &nPos,unsigned nIndent,unsigned long nPosEnd); - void PhotoshopParseDescriptor(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseList(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseInteger(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseBool(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseEnum(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseStringUni(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseHandleOsType(CString strOsType,unsigned long &nPos,unsigned nIndent); - void PhotoshopParseFileHeader(unsigned long &nPos,unsigned nIndent,tsImageInfo* psImageInfo); - void PhotoshopParseColorModeSection(unsigned long &nPos,unsigned nIndent); - bool PhotoshopParseImageResourcesSection(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseVersionInfo(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseResolutionInfo(unsigned long &nPos,unsigned nIndent); - void PhotoshopParsePrintScale(unsigned long &nPos,unsigned nIndent); - void PhotoshopParsePixelAspectRatio(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseDocSpecificSeed(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseGridGuides(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseGlobalAngle(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseGlobalAltitude(unsigned long &nPos,unsigned nIndent); - void PhotoshopParsePrintFlags(unsigned long &nPos,unsigned nIndent); - void PhotoshopParsePrintFlagsInfo(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseCopyrightFlag(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseLayerStateInfo(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseLayerGroupInfo(unsigned long &nPos,unsigned nIndent,unsigned nLen); - void PhotoshopParseLayerGroupEnabled(unsigned long &nPos,unsigned nIndent,unsigned nLen); - void PhotoshopParseLayerSelectId(unsigned long &nPos,unsigned nIndent); - void PhotoshopParseJpegQuality(unsigned long &nPos,unsigned nIndent,unsigned long nPosEnd); - - bool PhotoshopParseLayerMaskInfo(unsigned long &nPos,unsigned nIndent,CDIB* pDibTemp); - bool PhotoshopParseLayerInfo(unsigned long &nPos,unsigned nIndent,CDIB* pDibTemp); - bool PhotoshopParseLayerRecord(unsigned long &nPos,unsigned nIndent,tsLayerInfo* psLayerInfo); - bool PhotoshopParseLayerMask(unsigned long &nPos,unsigned nIndent); - bool PhotoshopParseLayerBlendingRanges(unsigned long &nPos,unsigned nIndent); - bool PhotoshopParseChannelImageData(unsigned long &nPos,unsigned nIndent,unsigned nWidth,unsigned nHeight,unsigned nChan,unsigned char* pDibBits); - bool PhotoshopParseGlobalLayerMaskInfo(unsigned long &nPos,unsigned nIndent); - bool PhotoshopParseAddtlLayerInfo(unsigned long &nPos,unsigned nIndent); - bool PhotoshopParseImageData(unsigned long &nPos,unsigned nIndent,tsImageInfo* psImageInfo,unsigned char* pDibBits); - - bool PhotoshopDecodeRowUncomp(unsigned long &nPos,unsigned nWidth,unsigned nHeight,unsigned nRow,unsigned nChanID,unsigned char* pDibBits); - bool PhotoshopDecodeRowRle(unsigned long &nPos,unsigned nWidth,unsigned nHeight,unsigned nRow,unsigned nRowLen,unsigned nChanID,unsigned char* pDibBits); - - CString PhotoshopDispHexWord(unsigned nVal); - - // 8BIM - CString PhotoshopParseGetBimLStrUni(unsigned long nPos,unsigned &nPosOffset); - bool FindBimRecord(unsigned nBimId,unsigned &nFldInd); - - // IPTC - void DecodeIptc(unsigned long &nPos,unsigned nLen,unsigned nIndent); - bool LookupIptcField(unsigned nRecord,unsigned nDataSet,unsigned &nFldInd); - CString DecodeIptcValue(teIptcType eIptcType,unsigned nFldCnt,unsigned long nPos); - - BYTE Buf(unsigned long offset,bool bClean); - -private: - // Configuration - CSnoopConfig* m_pAppConfig; - - // General classes required for decoding - CwindowBuf* m_pWBuf; - CDocLog* m_pLog; - - bool m_bAbort; // Abort continued decode? - -public: - bool m_bPsd; - unsigned m_nQualitySaveAs; - unsigned m_nQualitySaveForWeb; - - bool m_bDisplayLayer; - unsigned m_nDisplayLayerInd; - bool m_bDisplayImage; -}; - +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - This module parses the Photoshop PSD and 8BIM segments (APP13) +// - No rendering is done +// +// ========================================================================== + +#ifndef DECODEPS_H +#define DECODEPS_H + +#include "WindowBuf.h" +#include "snoop.h" +#include "SnoopConfig.h" + +#include "Dib.h" + +// +// Structure used for each IPTC field +// - NUM : binary number +// - STR : alphabetic characters, graphic characters, numeric character +// - HEX : +enum teIptcType +{ + IPTC_T_NUM, + IPTC_T_NUM1, + IPTC_T_NUM2, + IPTC_T_HEX, + IPTC_T_STR, + IPTC_T_UNK, + IPTC_T_END +}; + +struct tsIptcField +{ + uint32_t nRecord; + uint32_t nDataSet; + teIptcType eFldType; + QString strFldName; +}; + +// Structure used for each Image Resource Block (8BIM) record +enum teBimType +{ + BIM_T_UNK, BIM_T_STR, BIM_T_HEX, + BIM_T_IPTC_NAA, + BIM_T_JPEG_QUAL, + BIM_T_PS_SLICES, + BIM_T_PS_THUMB_RES, + BIM_T_PS_DESCRIPTOR, + BIM_T_PS_VER_INFO, + BIM_T_PS_RESOLUTION_INFO, + BIM_T_PS_PRINT_SCALE, + BIM_T_PS_PIXEL_ASPECT_RATIO, + BIM_T_PS_DOC_SPECIFIC_SEED, + BIM_T_PS_GRID_GUIDES, + BIM_T_PS_GLOBAL_ANGLE, + BIM_T_PS_GLOBAL_ALTITUDE, + BIM_T_PS_PRINT_FLAGS, + BIM_T_PS_PRINT_FLAGS_INFO, + BIM_T_PS_COPYRIGHT_FLAG, + BIM_T_PS_LAYER_STATE_INFO, + BIM_T_PS_LAYER_GROUP_INFO, + BIM_T_PS_LAYER_GROUP_ENABLED, + BIM_T_PS_LAYER_SELECT_ID, + BIM_T_PS_STR_UNI, + BIM_T_PS_STR_ASC, + BIM_T_PS_STR_ASC_LONG, + BIM_T_END +}; + +struct tsBimRecord +{ + uint32_t nCode; // Code value or start code for range + uint32_t nCodeEnd; // 0x0000 if not a range, else specifies last code value + teBimType eBimType; + QString strRecordName; +}; + +// Structure used for each enumerated field in IRB decoding +enum teBimEnumField +{ + BIM_T_ENUM_UNK, + BIM_T_ENUM_FILE_HDR_COL_MODE, + BIM_T_ENUM_RESOLUTION_INFO_RES_UNIT, + BIM_T_ENUM_RESOLUTION_INFO_WIDTH_UNIT, + BIM_T_ENUM_PRINT_SCALE_STYLE, + BIM_T_ENUM_GRID_GUIDE_DIR, + BIM_T_ENUM_BLEND_MODE_KEY, + BIM_T_ENUM_END +}; + +struct tsBimEnum +{ + teBimEnumField eBimEnum; + uint32_t nVal; + QString strVal; +}; + +// Byte Swap enable for Photoshop decoding +#define PS_BSWAP false + +// Define the 8BIM/IRB hex output display characteristics +static const uint32_t PS_HEX_MAX_INLINE = 16; // Threshold for displaying hex in-line with field name +static const uint32_t PS_HEX_MAX_ROW = 16; // Maximum number of bytes to report per line +static const uint32_t PS_HEX_TOTAL = 128; // Total number of bytes to report before clipping + +// Define the maximum length Unicode string to display +static const uint32_t PS_MAX_UNICODE_STRLEN = 256; + +// Information about layer and channels within it +struct tsLayerInfo +{ + uint32_t nNumChans; + uint32_t *pnChanLen; + uint32_t *pnChanID; + uint32_t nWidth; + uint32_t nHeight; +}; + +// From Layer Info +struct tsLayerAllInfo +{ + uint32_t nNumLayers; + tsLayerInfo *psLayers; +}; + +// From File Header +struct tsImageInfo +{ + uint32_t nImageWidth; + uint32_t nImageHeight; + uint32_t nNumChans; + uint32_t nDepthBpp; +}; + +class CDecodePs +{ +public: + CDecodePs(CwindowBuf * pWBuf, CDocLog * pLog); + ~CDecodePs(void); + + void Reset(); + + bool DecodePsd(uint32_t nPos, CDIB * pDibTemp, uint32_t &nWidth, uint32_t &nHeight); + bool PhotoshopParseImageResourceBlock(uint32_t &nPos, uint32_t nIndent); + +private: + CDecodePs &operator = (const CDecodePs&); + CDecodePs(CDecodePs&); + + QString PhotoshopParseGetLStrAsc(uint32_t &nPos); + QString PhotoshopParseIndent(uint32_t nIndent); + void PhotoshopParseReportNote(uint32_t nIndent, QString strNote); + QString PhotoshopParseLookupEnum(teBimEnumField eEnumField, uint32_t nVal); + void PhotoshopParseReportFldNum(uint32_t nIndent, QString strField, uint32_t nVal, QString strUnits); + void PhotoshopParseReportFldBool(uint32_t nIndent, QString strField, uint32_t nVal); + void PhotoshopParseReportFldEnum(uint32_t nIndent, QString strField, teBimEnumField eEnumField, uint32_t nVal); + void PhotoshopParseReportFldFixPt(uint32_t nIndent, QString strField, uint32_t nVal, QString strUnits); + void PhotoshopParseReportFldFloatPt(uint32_t nIndent, QString strField, uint32_t nVal, QString strUnits); + void PhotoshopParseReportFldDoublePt(uint32_t nIndent, QString strField, uint32_t nVal1, uint32_t nVal2, QString strUnits); + void PhotoshopParseReportFldStr(uint32_t nIndent, QString strField, QString strVal); + void PhotoshopParseReportFldOffset(uint32_t nIndent, QString strField, uint32_t nOffset); + void PhotoshopParseReportFldHex(uint32_t nIndent, QString strField, uint32_t nPosStart, uint32_t nLen); + void PhotoshopParseThumbnailResource(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseSliceHeader(uint32_t &nPos, uint32_t nIndent, uint32_t nPosEnd); + void PhotoshopParseSliceResource(uint32_t &nPos, uint32_t nIndent, uint32_t nPosEnd); + void PhotoshopParseDescriptor(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseList(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseInteger(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseBool(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseEnum(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseStringUni(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseHandleOsType(QString strOsType, uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseFileHeader(uint32_t &nPos, uint32_t nIndent, tsImageInfo * psImageInfo); + void PhotoshopParseColorModeSection(uint32_t &nPos, uint32_t nIndent); + bool PhotoshopParseImageResourcesSection(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseVersionInfo(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseResolutionInfo(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParsePrintScale(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParsePixelAspectRatio(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseDocSpecificSeed(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseGridGuides(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseGlobalAngle(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseGlobalAltitude(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParsePrintFlags(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParsePrintFlagsInfo(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseCopyrightFlag(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseLayerStateInfo(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseLayerGroupInfo(uint32_t &nPos, uint32_t nIndent, uint32_t nLen); + void PhotoshopParseLayerGroupEnabled(uint32_t &nPos, uint32_t nIndent, uint32_t nLen); + void PhotoshopParseLayerSelectId(uint32_t &nPos, uint32_t nIndent); + void PhotoshopParseJpegQuality(uint32_t &nPos, uint32_t nIndent, uint32_t nPosEnd); + + bool PhotoshopParseLayerMaskInfo(uint32_t &nPos, uint32_t nIndent, CDIB * pDibTemp); + bool PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * pDibTemp); + bool PhotoshopParseLayerRecord(uint32_t &nPos, uint32_t nIndent, tsLayerInfo * psLayerInfo); + bool PhotoshopParseLayerMask(uint32_t &nPos, uint32_t nIndent); + bool PhotoshopParseLayerBlendingRanges(uint32_t &nPos, uint32_t nIndent); + bool PhotoshopParseChannelImageData(uint32_t &nPos, uint32_t nIndent, uint32_t nWidth, uint32_t nHeight, uint32_t nChan, + unsigned char *pDibBits); + bool PhotoshopParseGlobalLayerMaskInfo(uint32_t &nPos, uint32_t nIndent); + bool PhotoshopParseAddtlLayerInfo(uint32_t &nPos, uint32_t nIndent); + bool PhotoshopParseImageData(uint32_t &nPos, uint32_t nIndent, tsImageInfo * psImageInfo, unsigned char *pDibBits); + + bool PhotoshopDecodeRowUncomp(uint32_t &nPos, uint32_t nWidth, uint32_t nHeight, uint32_t nRow, uint32_t nChanID, + unsigned char *pDibBits); + bool PhotoshopDecodeRowRle(uint32_t &nPos, uint32_t nWidth, uint32_t nHeight, uint32_t nRow, uint32_t nRowLen, + uint32_t nChanID, unsigned char *pDibBits); + + QString PhotoshopDispHexWord(uint32_t nVal); + + // 8BIM + QString PhotoshopParseGetBimLStrUni(uint32_t nPos, uint32_t &nPosOffset); + bool FindBimRecord(uint32_t nBimId, uint32_t &nFldInd); + + // IPTC + void DecodeIptc(uint32_t &nPos, uint32_t nLen, uint32_t nIndent); + bool LookupIptcField(uint32_t nRecord, uint32_t nDataSet, uint32_t &nFldInd); + QString DecodeIptcValue(teIptcType eIptcType, uint32_t nFldCnt, uint32_t nPos); + + quint8 Buf(uint32_t offset, bool bClean); + +private: + // Configuration + CSnoopConfig * m_pAppConfig; + + // General classes required for decoding + CwindowBuf *m_pWBuf; + CDocLog *m_pLog; + + bool m_bAbort; // Abort continued decode? + +public: + bool m_bPsd; + uint32_t m_nQualitySaveAs; + uint32_t m_nQualitySaveForWeb; + + bool m_bDisplayLayer; + uint32_t m_nDisplayLayerInd; + bool m_bDisplayImage; +}; + +#endif diff --git a/source/Dib.h b/source/Dib.h index f45214e..f904465 100644 --- a/source/Dib.h +++ b/source/Dib.h @@ -1,55 +1,125 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code was loosely based on an example CDIB class that appears in the following book: -// -// Title: Visual C++ 6 Unleashed -// Authors: Mickey Williams and David Bennett -// Publisher: Sams (July 24, 2000) -// ISBN-10: 0672312417 -// ISBN-13: 978-0672312410 -// ==================================================================================================== - -#pragma once - -class CDIB : public CObject -{ -public: - CDIB(); - virtual ~CDIB(); - - void Kill(); - bool CreateDIB(DWORD dwWidth,DWORD dwHeight,unsigned short nBits); - bool CreateDIBFromBitmap(CDC* pDC); - void InitializeColors(); - int GetDIBCols() const; - void* GetDIBBitArray() const; - bool CopyDIB(CDC* pDestDC,int x,int y,float scale=1); - bool CopyDibDblBuf(CDC* pDestDC, int x, int y,CRect* rectClient, float scale); - bool CopyDIBsmall(CDC* pDestDC,int x,int y,float scale=1); - bool CopyDibPart(CDC* pDestDC,CRect rectImg,CRect* rectClient, float scale); - -public: - CBitmap m_bmBitmap; - -private: - LPBITMAPINFO m_pDIB; -}; +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2017 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ==================================================================================================== +// SOURCE CODE ACKNOWLEDGEMENT +// ==================================================================================================== +// The following code was loosely based on an example CDIB class that appears in the following book: +// +// Title: Visual C++ 6 Unleashed +// Authors: Mickey Williams and David Bennett +// Publisher: Sams (July 24, 2000) +// ISBN-10: 0672312417 +// ISBN-13: 978-0672312410 +// ==================================================================================================== + +#ifndef DIB_H +#define DIB_H + +#include +#include +#include + +// TODO: Note that this file (Dib) will likely be removed soon +#include + +#define BI_RGB 0 + +// TODO: Confirm appropriate mapping (LONG & DWORD) +typedef long LONG; +typedef unsigned char BYTE; +typedef unsigned long DWORD; +typedef unsigned short WORD; + +// TODO: Remove the following as already defined in windows.h +#if 0 + +typedef struct tagBITMAPFILEHEADER +{ + WORD bfType; // 2 /* Magic identifier */ + DWORD bfSize; // 4 /* File size in bytes */ + WORD bfReserved1; // 2 + WORD bfReserved2; // 2 + DWORD bfOffBits; // 4 /* Offset to image data, bytes */ +} __attribute__((packed)) BITMAPFILEHEADER; + +typedef struct tagBITMAPINFOHEADER +{ + DWORD biSize; // 4 /* Header size in bytes */ + LONG biWidth; // 4 /* Width of image */ + LONG biHeight; // 4 /* Height of image */ + WORD biPlanes; // 2 /* Number of colour planes */ + WORD biBitCount; // 2 /* Bits per pixel */ + DWORD biCompression; // 4 /* Compression type */ + DWORD biSizeImage; // 4 /* Image size in bytes */ + LONG biXPelsPerMeter; // 4 + LONG biYPelsPerMeter; // 4 /* Pixels per meter */ + DWORD biClrUsed; // 4 /* Number of colours */ + DWORD biClrImportant; // 4 /* Important colours */ +} BITMAPINFOHEADER; + +typedef struct tagRGBQUAD +{ + unsigned char rgbBlue; + unsigned char rgbGreen; + unsigned char rgbRed; + unsigned char rgbReserved; +} RGBQUAD, *LPRGBQUAD; + +typedef struct tagBITMAPINFO +{ + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[1]; +} BITMAPINFO, *LPBITMAPINFO; + +#endif // + +typedef struct +{ + BYTE b; + BYTE g; + BYTE r; +} RGB_data; // RGB TYPE, plz also make sure the order + +class CDIB : public QObject +{ +public: + CDIB(); + virtual ~CDIB(); + + void Kill(); + bool CreateDIB(quint32 dwWidth,quint32 dwHeight,unsigned short nBits); +// bool CreateDIBFromBitmap(CDC* pDC); + void InitializeColors(); + int GetDIBCols() const; + void* GetDIBBitArray() const; +// bool CopyDIB(CDC* pDestDC,int x,int y,float scale=1); +// bool CopyDibDblBuf(CDC* pDestDC, int x, int y,QRect* rectClient, float scale); +// bool CopyDIBsmall(CDC* pDestDC,int x,int y,float scale=1); +// bool CopyDibPart(CDC* pDestDC,QRect rectImg,QRect* rectClient, float scale); + + QBitmap m_bmBitmap; + +private: + CDIB &operator = (const CDIB&); + CDIB(CDIB&); + + LPBITMAPINFO m_pDIB; +}; + +#endif diff --git a/source/DocLog.cpp b/source/DocLog.cpp index db4267e..41ad41b 100644 --- a/source/DocLog.cpp +++ b/source/DocLog.cpp @@ -1,314 +1,118 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "StdAfx.h" -#include ".\doclog.h" - -#include "JPEGsnoopDoc.h" - -// -// Initialize the log -// -CDocLog::CDocLog(void) -{ - m_pDoc = NULL; - m_bEn = true; - - // Default to local log - m_bUseDoc = false; - - // Start in quick mode -#ifdef QUICKLOG - m_bLogQuickMode = true; -#else - m_bLogQuickMode = false; -#endif - -} - -CDocLog::~CDocLog(void) -{ -} - - -// Enable logging -void CDocLog::Enable() { - m_bEn = true; -}; - -// Disable logging -void CDocLog::Disable() { - m_bEn = false; -}; - -// Enable or disable the quick log mode -// -// INPUT: -// - bQuick = If true, write to log buffer, if false, write to CDocument -// -void CDocLog::SetQuickMode(bool bQuick) -{ - m_bLogQuickMode = bQuick; -} - -// Get the current quick log mode -// -// RETURN: -// - Are we in quick mode? -// -bool CDocLog::GetQuickMode() -{ - return m_bLogQuickMode; -} - -void CDocLog::Clear() -{ - m_saLogQuickTxt.RemoveAll(); - m_naLogQuickCol.RemoveAll(); -} - -// Establish linkage between log and the CDocument -// Passing NULL will force use of local log instead -void CDocLog::SetDoc(CDocument* pDoc) -{ - m_pDoc = pDoc; - if (pDoc) { - // Use RichEditCtrl for the log - m_bUseDoc = true; - // Empty the buffer - Clear(); - } else { - // Use local log - m_bUseDoc = false; - } -} - -// Add a basic text line to the log -void CDocLog::AddLine(CString strTxt) -{ - COLORREF sCol; - if (m_bEn) { - sCol = RGB(1, 1, 1); - // TODO: Do I really need newline in these line outputs? - if (m_bUseDoc) { - if (m_bLogQuickMode) { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } else { - CJPEGsnoopDoc* pSnoopDoc = (CJPEGsnoopDoc*)m_pDoc; - pSnoopDoc->AppendToLog(strTxt+_T("\n"),sCol); - } - } else { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } - } -} - -// Add a header text line to the log -void CDocLog::AddLineHdr(CString strTxt) -{ - COLORREF sCol = RGB(1, 1, 255); - if (m_bEn) { - if (m_bUseDoc) { - if (m_bLogQuickMode) { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } else { - CJPEGsnoopDoc* pSnoopDoc = (CJPEGsnoopDoc*)m_pDoc; - pSnoopDoc->AppendToLog(strTxt+_T("\n"),sCol); - } - } else { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } - } -} - -// Add a header description text line to the log -void CDocLog::AddLineHdrDesc(CString strTxt) -{ - COLORREF sCol = RGB(32, 32, 255); - if (m_bEn) { - if (m_bUseDoc) { - if (m_bLogQuickMode) { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } else { - CJPEGsnoopDoc* pSnoopDoc = (CJPEGsnoopDoc*)m_pDoc; - pSnoopDoc->AppendToLog(strTxt+_T("\n"),sCol); - } - } else { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } - } -} - -// Add a warning text line to the log -void CDocLog::AddLineWarn(CString strTxt) -{ - COLORREF sCol = RGB(128, 1, 1); - if (m_bEn) { - if (m_bUseDoc) { - if (m_bLogQuickMode) { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } else { - CJPEGsnoopDoc* pSnoopDoc = (CJPEGsnoopDoc*)m_pDoc; - pSnoopDoc->AppendToLog(strTxt+_T("\n"),sCol); - } - } else { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } - } -} - -// Add an error text line to the log -void CDocLog::AddLineErr(CString strTxt) -{ - COLORREF sCol = RGB(255, 1, 1); - if (m_bEn) { - if (m_bUseDoc) { - if (m_bLogQuickMode) { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } else { - CJPEGsnoopDoc* pSnoopDoc = (CJPEGsnoopDoc*)m_pDoc; - pSnoopDoc->AppendToLog(strTxt+_T("\n"),sCol); - } - } else { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } - } -} - -// Add a "good" indicator text line to the log -void CDocLog::AddLineGood(CString strTxt) -{ - COLORREF sCol = RGB(16, 128, 16); - if (m_bEn) { - if (m_bUseDoc) { - if (m_bLogQuickMode) { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } else { - CJPEGsnoopDoc* pSnoopDoc = (CJPEGsnoopDoc*)m_pDoc; - pSnoopDoc->AppendToLog(strTxt+_T("\n"),sCol); - } - } else { - AppendToLogLocal(strTxt+_T("\n"),sCol); - } - } -} - -// ====================================================================== - -unsigned CDocLog::AppendToLogLocal(CString strTxt, COLORREF sColor) -{ - // Don't exceed a realistic maximum! - unsigned numLines = m_saLogQuickTxt.GetCount(); - if (numLines == DOCLOG_MAX_LINES) { - m_saLogQuickTxt.Add(_T("*** TOO MANY LINES IN REPORT -- TRUNCATING ***")); - m_naLogQuickCol.Add((unsigned)sColor); - return 0; - } else if (numLines > DOCLOG_MAX_LINES) { - return 0; - } - - m_saLogQuickTxt.Add(strTxt); - m_naLogQuickCol.Add((unsigned)sColor); - - return 0; -} - -// Get the number of lines in the local log or quick buffer -unsigned CDocLog::GetNumLinesLocal() -{ - return m_saLogQuickTxt.GetCount(); -} - -// Fetch a line from the local log -// Returns false if line number is out of range -bool CDocLog::GetLineLogLocal(unsigned nLine,CString &strOut,COLORREF &sCol) -{ - unsigned numLines = m_saLogQuickTxt.GetCount(); - if (nLine >= numLines) { - return false; - } - strOut = m_saLogQuickTxt[nLine]; - sCol = m_naLogQuickCol[nLine]; - return true; -} - -// Save the current log to text file with a simple implementation -// -// - This routine is implemented with a simple output mechanism rather -// than leveraging CRichEditCtrl::DoSave() so that we can perform -// this operation in command-line mode or batch mode operations. -// -void CDocLog::DoLogSave(CString strLogName) -{ - CStdioFile* pLog; - - // Open the file for output - ASSERT(strLogName != _T("")); - - // OLD COMMENTS FOLLOW - // This save method will only work if we were in Quick Log mode - // where we have recorded the log to a string buffer and not - // directly to the RichEdit - // Note that m_bLogQuickMode is only toggled on during processing - // so we can't check the status here (except seeing that there are no - // lines in the array) - - // TODO: Ensure file doesn't exist and only overwrite if specified in command-line? - - // TODO: - // Confirm that we are not writing to the same file we opened (m_strPathName) - // ASSERT(strLogName != m_strPathName); - - try - { - // Open specified file - pLog = new CStdioFile(strLogName, CFile::modeCreate| CFile::modeWrite | CFile::typeText | CFile::shareDenyNone); - } - catch (CFileException* e) - { - TCHAR msg[MAX_BUF_EX_ERR_MSG]; - CString strError; - e->GetErrorMessage(msg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - strError.Format(_T("ERROR: Couldn't open file for write [%s]: [%s]"), - (LPCTSTR)strLogName, (LPCTSTR)msg); - // FIXME: Find an alternate method of signaling error in command-line mode - AfxMessageBox(strError); - pLog = NULL; - - return; - - } - - // Step through the current log buffer - CString strLine; - COLORREF sCol; - unsigned nQuickLines = GetNumLinesLocal(); - for (unsigned nLine=0;nLineWriteString(strLine); - } - - // Close the file - if (pLog) { - pLog->Close(); - delete pLog; - } - -} +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include "DocLog.h" + +// +// Initialize the log +// +CDocLog::CDocLog(void) +{ + m_pDoc = NULL; +} + +CDocLog::CDocLog(QPlainTextEdit *pDoc) +{ + m_pDoc = NULL; + m_pDoc = pDoc; +} + +CDocLog::~CDocLog(void) +{ +} + +void CDocLog::Clear() +{ + m_pDoc->clear(); +} + +void CDocLog::setDoc(QPlainTextEdit *pDoc) +{ + m_pDoc = pDoc; +} + +void CDocLog::appendToLog(QString strTxt, QColor col) +{ + if(m_bEn) + { + QTextCharFormat format; + format.setForeground(QBrush(col)); + m_pDoc->setCurrentCharFormat(format); +// m_pDoc->appendPlainText(rTrim(strTxt)); + m_pDoc->appendPlainText(strTxt); +// qDebug() << strTxt; + } +} + +// Add a basic text line to the log +void CDocLog::AddLine(QString strTxt) +{ + QColor sCol(1, 1, 1); + appendToLog(strTxt, sCol); +} + +// Add a header text line to the log +void CDocLog::AddLineHdr(QString strTxt) +{ + QColor sCol(1, 1, 255); + appendToLog(strTxt, sCol); +} + +// Add a header description text line to the log +void CDocLog::AddLineHdrDesc(QString strTxt) +{ + QColor sCol(32, 32, 255); + appendToLog(strTxt, sCol); +} + +// Add a warning text line to the log +void CDocLog::AddLineWarn(QString strTxt) +{ + QColor sCol(128, 1, 1); + appendToLog(strTxt, sCol); +} + +// Add an error text line to the log +void CDocLog::AddLineErr(QString strTxt) +{ + QColor sCol(255, 1, 1); + appendToLog(strTxt, sCol); +} + +// Add a "good" indicator text line to the log +void CDocLog::AddLineGood(QString strTxt) +{ + QColor sCol(16, 128, 16); + appendToLog(strTxt, sCol); +} + +QString CDocLog::rTrim(const QString& str) +{ + int n = str.size() - 1; + + for (; n >= 0; --n) + { + if (!str.at(n).isSpace()) + { + return str.left(n + 1); + } + } + + return ""; +} diff --git a/source/DocLog.h b/source/DocLog.h index 38074b7..1d3b5ee 100644 --- a/source/DocLog.h +++ b/source/DocLog.h @@ -1,69 +1,63 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Simple wrapper for document log routines -// -// ========================================================================== - - -#pragma once - -class CDocLog -{ -public: - CDocLog(); - ~CDocLog(void); - - void AddLine(CString str); - void AddLineHdr(CString str); - void AddLineHdrDesc(CString str); - void AddLineWarn(CString str); - void AddLineErr(CString str); - void AddLineGood(CString str); - - void Enable(); - void Disable(); - void SetQuickMode(bool bQuick); - bool GetQuickMode(); - - void SetDoc(CDocument *pDoc); - void Clear(); - - unsigned GetNumLinesLocal(); - bool GetLineLogLocal(unsigned nLine,CString &strOut,COLORREF &sCol); - - void DoLogSave(CString strLogName); - -private: - unsigned AppendToLogLocal(CString strTxt, COLORREF sColor); - -private: - - bool m_bUseDoc; // Use Document or local buffer - CDocument* m_pDoc; - bool m_bEn; - - // Local buffer - CStringArray m_saLogQuickTxt; - CUIntArray m_naLogQuickCol; - - bool m_bLogQuickMode; // In m_bUseDoc=TRUE, do we write to local buffer instead? - -}; +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - Simple wrapper for document log routines +// +// ========================================================================== + +#ifndef DOCLOG_H +#define DOCLOG_H + +#include +#include + +class CDocLog +{ +public: + CDocLog(); + CDocLog(QPlainTextEdit *pDoc); + ~CDocLog(void); + + void setDoc(QPlainTextEdit *pDoc); + + void AddLine(QString str); + void AddLineHdr(QString str); + void AddLineHdrDesc(QString str); + void AddLineWarn(QString str); + void AddLineErr(QString str); + void AddLineGood(QString str); + + void Clear(); + + void Enable() { m_bEn = true; } + void Disable() { m_bEn = false; } + +private: + CDocLog &operator = (const CDocLog&); + CDocLog(CDocLog&); + + void appendToLog(QString strTxt, QColor col); + QString rTrim(const QString& str); + + QPlainTextEdit *m_pDoc; + bool m_bEn; +}; + +#endif diff --git a/source/General.cpp b/source/General.cpp index b0b6190..e802d22 100644 --- a/source/General.cpp +++ b/source/General.cpp @@ -1,327 +1,340 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "StdAfx.h" - -// --------------------------------------- -// Global functions -// --------------------------------------- - - -CString Dec2Bin(unsigned nVal,unsigned nLen,bool bSpace) -{ - unsigned nBit; - CString strBin = _T(""); - for (int nInd=nLen-1;nInd>=0;nInd--) - { - nBit = ( nVal & (1 << nInd) ) >> nInd; - strBin += (nBit==1)?_T("1"):_T("0"); - if ( ((nInd % 8) == 0) && (nInd != 0) ) { - if (bSpace) { - strBin += _T(" "); - } - } - } - return strBin; -} - -// Perform byteswap which is used to create packed image array -// before write-out of 16b values to disk -unsigned short Swap16(unsigned short nVal) -{ - BYTE nValHi,nValLo; - nValHi = static_cast((nVal & 0xFF00)>>8); - nValLo = static_cast((nVal & 0x00FF)); - return (nValLo<<8) + nValHi; -} - -// Simple helper routine to test whether an indexed bit is set -bool TestBit(unsigned nVal,unsigned nBit) -{ - unsigned nTmp; - nTmp = (nVal & (1<>24); - c2 = char((nVal & 0x00FF0000)>>16); - c1 = char((nVal & 0x0000FF00)>>8); - c0 = char(nVal & 0x000000FF); - c3 = (c3 == 0)?'.':c3; - c2 = (c2 == 0)?'.':c2; - c1 = (c1 == 0)?'.':c1; - c0 = (c0 == 0)?'.':c0; - strTmp.Format(_T("'%c%c%c%c' (0x%08X)"), - c3,c2,c1,c0,nVal); - return strTmp; -} - -// Convert between unsigned int and a dotted-byte notation -CString Uint2DotByte(unsigned nVal) -{ - CString strTmp; - strTmp.Format(_T("'%u.%u.%u.%u' (0x%08X)"), - ((nVal & 0xFF000000)>>24), - ((nVal & 0x00FF0000)>>16), - ((nVal & 0x0000FF00)>>8), - (nVal & 0x000000FF), - nVal); - return strTmp; -} - -/* -// Convert a byte array into a unicode CString -// - Clips to MAX_UNICODE_STRLEN -// -// INPUT: -// - pBuf = Byte array containing encoded unicode string -// - nBufLen = Number of unicode characters (16b) to read -// RETURN: -// - CString containing unicode characters -// -#define MAX_UNICODE_STRLEN 255 -CString ByteStr2Unicode(BYTE* pBuf, unsigned nBufLen) -{ - CString strUni; - BYTE anStrBuf[(MAX_UNICODE_STRLEN+1)*2]; - wchar_t acStrBuf[(MAX_UNICODE_STRLEN+1)]; - - // Copy bytes into local buffer to ensure it is truncated and - // properly terminated - unsigned nStrPos = 0; - BYTE nByte0,nByte1; - bool bDone = false; - while (!bDone) { - if (nStrPos>nBufLen) { - // Exceeded the indicated string length - bDone = true; - } else if (nStrPos>MAX_UNICODE_STRLEN) { - // Exceeded our maximum string conversion length - bDone = true; - } else { - // Fetch the next two bytes - nByte0 = pBuf[(nStrPos*2)+0]; - nByte1 = pBuf[(nStrPos*2)+1]; - // Check in case we see terminator - if ((nByte0==0) && (nByte1==0)) { - // Don't copy over it now as we always pad with terminator after - bDone = true; - } - } - // If we haven't found a reason to stop, copy over the bytes - if (!bDone) { - anStrBuf[(nStrPos*2)+0] = nByte0; - anStrBuf[(nStrPos*2)+1] = nByte1; - // Increment index - nStrPos++; - } - } - // Now ensure we are terminated properly by enforcing terminator - anStrBuf[(nStrPos*2)+0] = 0; - anStrBuf[(nStrPos*2)+1] = 0; - - // Copy into unicode string - // - This routine requires it to be terminated first! - lstrcpyW(acStrBuf,(LPCWSTR)anStrBuf); - - // Finally copy back into CString - strUni = acStrBuf; - return strUni; -} -*/ - -bool Str2Uint32(CString strVal,unsigned nBase,unsigned &nVal) -{ - // Convert to unsigned 32b - strVal.MakeUpper(); - if (nBase == 16) { - // Hex - if (strVal.Left(2) == _T("0X")) { - strVal = strVal.Mid(2,20); - } - if (strVal.SpanIncluding(_T("0123456789ABCDEF")) != strVal) { - return false; - } - nVal = _tcstoul(strVal,NULL,16); - } else if (nBase == 10) { - // Dec - if (strVal.SpanIncluding(_T("0123456789")) != strVal) { - return false; - } - nVal = _tcstoul(strVal,NULL,10); - } else { - return false; - } - return true; -} - - - -// UNUSED -// Convert a unicode string to ASCII and write into a buffer -// - Returns true if we successfully wrote entire string including terminator -bool Uni2AscBuf(PBYTE pBuf,CString strIn,unsigned nMaxBytes,unsigned &nOffsetBytes) -{ - ASSERT(pBuf); - - bool bRet = false; - char chAsc; - PBYTE pBufBase; - LPSTR pBufAsc; - - pBufBase = pBuf + nOffsetBytes; - pBufAsc = (LPSTR)pBufBase; - -#ifdef UNICODE - - CW2A pszNonUnicode(strIn); - -#endif // UNICODE - - - unsigned nStrLen; - unsigned nChInd; - nStrLen = strIn.GetLength(); - for (nChInd=0;(nChInd. +// + +// --------------------------------------- +// Global functions +// --------------------------------------- +#include + +QString Dec2Bin(unsigned nVal,unsigned nLen,bool bSpace) +{ + unsigned nBit; + QString strBin = ""; + + for (int nInd=nLen-1;nInd>=0;nInd--) + { + nBit = ( nVal & (1 << nInd) ) >> nInd; + strBin += (nBit==1)?"1":"0"; + + if ( ((nInd % 8) == 0) && (nInd != 0) ) + { + if (bSpace) + { + strBin += " "; + } + } + } + + return strBin; +} + +// Perform byteswap which is used to create packed image array +// before write-out of 16b values to disk +unsigned short Swap16(unsigned short nVal) +{ + quint8 nValHi,nValLo; + nValHi = static_cast((nVal & 0xFF00)>>8); + nValLo = static_cast((nVal & 0x00FF)); + return (nValLo<<8) + nValHi; +} + +// Simple helper routine to test whether an indexed bit is set +bool TestBit(unsigned nVal,unsigned nBit) +{ + unsigned nTmp; + nTmp = (nVal & (1<>24); + c2 = char((nVal & 0x00FF0000)>>16); + c1 = char((nVal & 0x0000FF00)>>8); + c0 = char(nVal & 0x000000FF); + c3 = (c3 == 0)?'.':c3; + c2 = (c2 == 0)?'.':c2; + c1 = (c1 == 0)?'.':c1; + c0 = (c0 == 0)?'.':c0; +// strTmp.Format(_T("'%c%c%c%c' (0x%08X)"), c3,c2,c1,c0,nVal); + strTmp = QString("'%1%2%3%4' (%5)").arg(c3).arg(c2).arg(c1).arg(c0).arg(nVal, 8, 16, QChar('0')); + return strTmp; +} + +// Convert between unsigned int and a dotted-byte notation +QString Uint2DotByte(unsigned nVal) +{ + QString strTmp; + strTmp = QString("'%1%2%3%4' (%5)") + .arg(nVal & 0xFF000000>>24) + .arg(nVal & 0x00FF0000>>16) + .arg(nVal & 0x0000FF00>>8) + .arg(nVal & 0x000000FF) + .arg(nVal, 8, 16, QChar('0')); +/* strTmp.Format(_T("'%u.%u.%u.%u' (0x%08X)"), + ((nVal & 0xFF000000)>>24), + ((nVal & 0x00FF0000)>>16), + ((nVal & 0x0000FF00)>>8), + (nVal & 0x000000FF), + nVal);*/ + return strTmp; +} + +/* +// Convert a byte array into a unicode QString +// - Clips to MAX_UNICODE_STRLEN +// +// INPUT: +// - pBuf = Byte array containing encoded unicode string +// - nBufLen = Number of unicode characters (16b) to read +// RETURN: +// - QString containing unicode characters +// +#define MAX_UNICODE_STRLEN 255 +QString ByteStr2Unicode(BYTE* pBuf, unsigned nBufLen) +{ + QString strUni; + BYTE anStrBuf[(MAX_UNICODE_STRLEN+1)*2]; + wchar_t acStrBuf[(MAX_UNICODE_STRLEN+1)]; + + // Copy bytes into local buffer to ensure it is truncated and + // properly terminated + unsigned nStrPos = 0; + BYTE nByte0,nByte1; + bool bDone = false; + while (!bDone) { + if (nStrPos>nBufLen) { + // Exceeded the indicated string length + bDone = true; + } else if (nStrPos>MAX_UNICODE_STRLEN) { + // Exceeded our maximum string conversion length + bDone = true; + } else { + // Fetch the next two bytes + nByte0 = pBuf[(nStrPos*2)+0]; + nByte1 = pBuf[(nStrPos*2)+1]; + // Check in case we see terminator + if ((nByte0==0) && (nByte1==0)) { + // Don't copy over it now as we always pad with terminator after + bDone = true; + } + } + // If we haven't found a reason to stop, copy over the bytes + if (!bDone) { + anStrBuf[(nStrPos*2)+0] = nByte0; + anStrBuf[(nStrPos*2)+1] = nByte1; + // Increment index + nStrPos++; + } + } + // Now ensure we are terminated properly by enforcing terminator + anStrBuf[(nStrPos*2)+0] = 0; + anStrBuf[(nStrPos*2)+1] = 0; + + // Copy into unicode string + // - This routine requires it to be terminated first! + lstrcpyW(acStrBuf,(LPCWSTR)anStrBuf); + + // Finally copy back into QString + strUni = acStrBuf; + return strUni; +} +*/ + +bool Str2Uint32(QString strVal,unsigned nBase,unsigned &nVal) +{ + // Convert to unsigned 32b +// strVal.MakeUpper(); + bool Ok; + + if (nBase == 16) + { + // Hex + if (strVal.startsWith("0X")) + { + strVal = strVal.mid(2,20); + } + + nVal = strVal.toUInt(&Ok, 16); + } + else if (nBase == 10) + { + // Dec + nVal = strVal.toUInt(&Ok, 10); + } + else + { + return false; + } + + return Ok; +} + + +/* +// UNUSED +// Convert a unicode string to ASCII and write into a buffer +// - Returns true if we successfully wrote entire string including terminator +bool Uni2AscBuf(PBYTE pBuf,QString strIn,unsigned nMaxBytes,unsigned &nOffsetBytes) +{ + ASSERT(pBuf); + + bool bRet = false; + char chAsc; + PBYTE pBufBase; + LPSTR pBufAsc; + + pBufBase = pBuf + nOffsetBytes; + pBufAsc = (LPSTR)pBufBase; + +#ifdef UNICODE + + CW2A pszNonUnicode(strIn); + +#endif // UNICODE + + + unsigned nStrLen; + unsigned nChInd; + nStrLen = strIn.GetLength(); + for (nChInd=0;(nChInd. -// - -#ifndef _GENERAL_H_ -#define _GENERAL_H_ - -// General Global Functions -CString Dec2Bin(unsigned nVal,unsigned nLen,bool bSpace=true); -unsigned short Swap16(unsigned short nVal); -CString Uint2Chars(unsigned nVal); -CString Uint2DotByte(unsigned nVal); -bool TestBit(unsigned nVal,unsigned nBit); -//CString ByteStr2Unicode(BYTE* pBuf, unsigned nBufLen); -bool Str2Uint32(CString strVal,unsigned nBase,unsigned &nVal); - -bool Uni2AscBuf(PBYTE pBuf,CString strIn,unsigned nMaxBytes,unsigned &nOffsetBytes); - -// General Global Constants -extern const unsigned glb_anZigZag[64]; -extern const unsigned glb_anUnZigZag[64]; - -extern const unsigned glb_anQuantRotate[64]; -extern const unsigned glb_anStdQuantLum[64]; -extern const unsigned glb_anStdQuantChr[64]; - -#endif \ No newline at end of file +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef _GENERAL_H_ +#define _GENERAL_H_ + +#include + +// General Global Functions +QString Dec2Bin(unsigned nVal,unsigned nLen,bool bSpace=true); +unsigned short Swap16(unsigned short nVal); +QString Uint2Chars(unsigned nVal); +QString Uint2DotByte(unsigned nVal); +bool TestBit(unsigned nVal,unsigned nBit); +//QString ByteStr2Unicode(quint8* pBuf, unsigned nBufLen); +bool Str2Uint32(QString strVal,unsigned nBase,unsigned &nVal); + +//bool Uni2AscBuf(quint8* pBuf,QString strIn,unsigned nMaxBytes,unsigned &nOffsetBytes); + +// General Global Constants +extern const unsigned glb_anZigZag[64]; +extern const unsigned glb_anUnZigZag[64]; + +extern const unsigned glb_anQuantRotate[64]; +extern const unsigned glb_anStdQuantLum[64]; +extern const unsigned glb_anStdQuantChr[64]; + +#endif diff --git a/source/ImgDecode.cpp b/source/ImgDecode.cpp index d7e61f8..c9324a7 100644 --- a/source/ImgDecode.cpp +++ b/source/ImgDecode.cpp @@ -1,5822 +1,6817 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "stdafx.h" - -#include "ImgDecode.h" -#include "snoop.h" -#include - -#include "JPEGsnoop.h" - - -// ------------------------------------------------------ -// Settings - -// Flag: Use fixed point arithmetic for IDCT? -//#define IDCT_FIXEDPT - -// Flag: Do we stop during scan decode if 0xFF (but not pad)? -// TODO: Make this a config option -//#define SCAN_BAD_MARKER_STOP - - -// ------------------------------------------------------ -// Main code - - - - -// Reset decoding state for start of new decode -// Note that we don't touch the DQT or DHT entries as -// those are set at different times versus reset (sometimes -// before Reset() ). -void CimgDecode::Reset() -{ - DecodeRestartScanBuf(0,false); - DecodeRestartDcState(); - - m_bRestartRead = false; // No restarts seen yet - m_nRestartRead = 0; - - m_nImgSizeXPartMcu = 0; - m_nImgSizeYPartMcu = 0; - m_nImgSizeX = 0; - m_nImgSizeY = 0; - m_nMcuXMax = 0; - m_nMcuYMax = 0; - m_nBlkXMax = 0; - m_nBlkYMax = 0; - - m_bBrightValid = false; - m_nBrightY = -32768; - m_nBrightCb = -32768; - m_nBrightCr = -32768; - m_nBrightR = 0; - m_nBrightG = 0; - m_nBrightB = 0; - m_ptBrightMcu.x = 0; - m_ptBrightMcu.y = 0; - - m_bAvgYValid = false; - m_nAvgY = 0; - - // If a DIB has been generated, release it! - if (m_bDibTempReady) { - m_pDibTemp.Kill(); - m_bDibTempReady = false; - } - - if (m_bDibHistRgbReady) { - m_pDibHistRgb.Kill(); - m_bDibHistRgbReady = false; - } - - if (m_bDibHistYReady) { - m_pDibHistY.Kill(); - m_bDibHistYReady = false; - } - - if (m_pMcuFileMap) { - delete [] m_pMcuFileMap; - m_pMcuFileMap = NULL; - } - - if (m_pBlkDcValY) { - delete [] m_pBlkDcValY; - m_pBlkDcValY = NULL; - } - if (m_pBlkDcValCb) { - delete [] m_pBlkDcValCb; - m_pBlkDcValCb = NULL; - } - if (m_pBlkDcValCr) { - delete [] m_pBlkDcValCr; - m_pBlkDcValCr = NULL; - } - - if (m_pPixValY) { - delete [] m_pPixValY; - m_pPixValY = NULL; - } - if (m_pPixValCb) { - delete [] m_pPixValCb; - m_pPixValCb = NULL; - } - if (m_pPixValCr) { - delete [] m_pPixValCr; - m_pPixValCr = NULL; - } - - // Haven't warned about anything yet - if (!m_bScanErrorsDisable) { - m_nWarnBadScanNum = 0; - } - m_nWarnYccClipNum = 0; - - // Reset the view - m_nPreviewPosX = 0; - m_nPreviewPosY = 0; - m_nPreviewSizeX = 0; - m_nPreviewSizeY = 0; - -} - -// Constructor for the Image Decoder -// - This constructor is called only once by Document class -CimgDecode::CimgDecode(CDocLog* pLog, CwindowBuf* pWBuf) -{ - // Ideally this would be passed by constructor, but simply access - // directly for now. - CJPEGsnoopApp* pApp; - pApp = (CJPEGsnoopApp*)AfxGetApp(); - m_pAppConfig = pApp->m_pAppConfig; - ASSERT(m_pAppConfig); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CimgDecode::CimgDecode() Begin")); - - m_bVerbose = false; - - ASSERT(pLog); - ASSERT(pWBuf); - m_pLog = pLog; - m_pWBuf = pWBuf; - - m_pStatBar = NULL; - m_bDibTempReady = false; - m_bPreviewIsJpeg = false; - m_bDibHistRgbReady = false; - m_bDibHistYReady = false; - - m_bHistEn = false; - m_bStatClipEn = false; // UNUSED - - m_pMcuFileMap = NULL; - m_pBlkDcValY = NULL; - m_pBlkDcValCb = NULL; - m_pBlkDcValCr = NULL; - m_pPixValY = NULL; - m_pPixValCb = NULL; - m_pPixValCr = NULL; - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CimgDecode::CimgDecode() Checkpoint 1")); - - // Reset the image decoding state - Reset(); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CimgDecode::CimgDecode() Checkpoint 2")); - - m_nImgSizeXPartMcu = 0; - m_nImgSizeYPartMcu = 0; - m_nImgSizeX = 0; - m_nImgSizeY = 0; - - // FIXME: Temporary hack to avoid divide-by-0 when displaying PSD (instead of JPEG) - m_nMcuWidth = 1; - m_nMcuHeight = 1; - - // Detailed VLC Decode mode - m_bDetailVlc = false; - m_nDetailVlcX = 0; - m_nDetailVlcY = 0; - m_nDetailVlcLen = 1; - - m_bDecodeScanAc = true; - - - // Set up the IDCT lookup tables - PrecalcIdct(); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CimgDecode::CimgDecode() Checkpoint 3")); - - GenLookupHuffMask(); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CimgDecode::CimgDecode() Checkpoint 4")); - - - - // The following contain information that is set by - // the JFIF Decoder. We can only reset them here during - // the constructor and later by explicit call by JFIF Decoder. - ResetState(); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CimgDecode::CimgDecode() Checkpoint 5")); - - // We don't call SetPreviewMode() here because it would - // automatically try to recalculate the view (but nothing ready yet) - m_nPreviewMode = PREVIEW_RGB; - SetPreviewZoom(false,false,true,PRV_ZOOM_12); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CimgDecode::CimgDecode() Checkpoint 6")); - - m_bViewOverlaysMcuGrid = false; - - // Start off with no YCC offsets for CalcChannelPreview() - SetPreviewYccOffset(0,0,0,0,0); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CimgDecode::CimgDecode() Checkpoint 7")); - - SetPreviewMcuInsert(0,0,0); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CimgDecode::CimgDecode() Checkpoint 8")); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CimgDecode::CimgDecode() End")); -} - - -// Destructor for Image Decode class -// - Deallocate any image-related dynamic storage -CimgDecode::~CimgDecode() -{ - if (m_pMcuFileMap) { - delete [] m_pMcuFileMap; - m_pMcuFileMap = NULL; - } - - if (m_pBlkDcValY) { - delete [] m_pBlkDcValY; - m_pBlkDcValY = NULL; - } - if (m_pBlkDcValCb) { - delete [] m_pBlkDcValCb; - m_pBlkDcValCb = NULL; - } - if (m_pBlkDcValCr) { - delete [] m_pBlkDcValCr; - m_pBlkDcValCr = NULL; - } - - if (m_pPixValY) { - delete [] m_pPixValY; - m_pPixValY = NULL; - } - if (m_pPixValCb) { - delete [] m_pPixValCb; - m_pPixValCb = NULL; - } - if (m_pPixValCr) { - delete [] m_pPixValCr; - m_pPixValCr = NULL; - } - -} - -// Reset the major parameters -// - Called by JFIF Decoder when we begin a new file -// TODO: Consider merging with Reset() -// POST: -// - m_anSofSampFactH[] -// - m_anSofSampFactV[] -// - m_bImgDetailsSet -// - m_nNumSofComps -// - m_nPrecision -// - m_bScanErrorsDisable -// - m_nMarkersBlkNum -// -void CimgDecode::ResetState() -{ - ResetDhtLookup(); - ResetDqtTables(); - - for (unsigned nCompInd=0;nCompIndSetPaneText(0,str); - } -} - -// Clears the DQT entries -// POST: -// - m_anDqtTblSel[] -// - m_anDqtCoeff[][] -// - m_anDqtCoeffZz[][] -void CimgDecode::ResetDqtTables() -{ - for (unsigned nDqtComp=0;nDqtCompstrCurFname, - _T("ImgDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return false; - } - return true; -} - - -// Fetch a DQT table entry -// -// INPUT: -// - nTblDestId = DQT Table Destination ID -// - nCoeffInd = Coefficient index in 8x8 matrix -// PRE: -// - m_anDqtCoeff[][] -// RETURN: -// - Returns the indexed DQT matrix entry -// -unsigned CimgDecode::GetDqtEntry(unsigned nTblDestId, unsigned nCoeffInd) -{ - if ((nTblDestId < MAX_DQT_DEST_ID) && (nCoeffInd < MAX_DQT_COEFF)) { - return m_anDqtCoeff[nTblDestId][nCoeffInd]; - } else { - // Should never get here! - CString strTmp; - strTmp.Format(_T("ERROR: GetDqtEntry(nTblDestId=%u, nCoeffInd=%u) out of indexed range"), - nTblDestId,nCoeffInd); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - -#ifdef DEBUG_LOG - CString strDebug; - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("ImgDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - - return 0; - } -} - - -// Set a DQT table for a frame image component identifier -// -// INPUT: -// - nCompInd = Component index. Based on m_nSofNumComps_Nf-1 (ie. 0..254) -// - nTbl = DQT Table number. Based on SOF:Tqi (ie. 0..3) -// POST: -// - m_anDqtTblSel[] -// RETURN: -// - Success if index and table are in range -// NOTE: -// - Asynchronously called by JFIF Decoder -// -bool CimgDecode::SetDqtTables(unsigned nCompId, unsigned nTbl) -{ - if ((nCompId < MAX_SOF_COMP_NF) && (nTbl < MAX_DQT_DEST_ID)) { - m_anDqtTblSel[nCompId] = (int)nTbl; - } else { - // Should never get here unless the JFIF SOF table has a bad entry! - CString strTmp; - strTmp.Format(_T("ERROR: SetDqtTables(Comp ID=%u, Table=%u) out of indexed range"), - nCompId,nTbl); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return false; - } - return true; -} - -// Set a DHT table for a scan image component index -// - The DHT Table select array is stored as: -// m_anDhtTblSel[0][1,2,3] for DC -// m_anDhtTblSel[1][1,2,3] for AC -// -// INPUT: -// - nCompInd = Component index (1-based). Range 1..4 -// - nTblDc = DHT table index for DC elements of component -// - nTblAc = DHT table index for AC elements of component -// POST: -// - m_anDhtTblSel[][] -// RETURN: -// - Success if indices are in range -// -bool CimgDecode::SetDhtTables(unsigned nCompInd, unsigned nTblDc, unsigned nTblAc) -{ - // Note use of (nCompInd < MAX_SOS_COMP_NS+1) as nCompInd is 1-based notation - if ((nCompInd>=1) && (nCompInd < MAX_SOS_COMP_NS+1) && (nTblDc < MAX_DHT_DEST_ID) && (nTblAc < MAX_DHT_DEST_ID)) { - m_anDhtTblSel[DHT_CLASS_DC][nCompInd] = (int)nTblDc; - m_anDhtTblSel[DHT_CLASS_AC][nCompInd] = (int)nTblAc; - } else { - // Should never get here! - CString strTmp; - strTmp.Format(_T("ERROR: SetDhtTables(comp=%u, TblDC=%u TblAC=%u) out of indexed range"), - nCompInd,nTblDc,nTblAc); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return false; - } - return true; -} - - - -// Get the precision field -// -// INPUT: -// - nPrecision = DCT sample precision (typically 8 or 12) -// POST: -// - m_nPrecision -// -void CimgDecode::SetPrecision(unsigned nPrecision) -{ - m_nPrecision = nPrecision; -} - - -// Set the general image details for the image decoder -// -// INPUT: -// - nDimX = Image dimension (X) -// - nDimY = Image dimension (Y) -// - nCompsSOF = Number of components in Frame -// - nCompsSOS = Number of components in Scan -// - bRstEn = Restart markers present? -// - nRstInterval = Restart marker interval -// POST: -// - m_bImgDetailsSet -// - m_nDimX -// - m_nDimY -// - m_nNumSofComps -// - m_nNumSosComps -// - m_bRestartEn -// - m_nRestartInterval -// NOTE: -// - Called asynchronously by the JFIF decoder -// -void CimgDecode::SetImageDetails(unsigned nDimX,unsigned nDimY,unsigned nCompsSOF,unsigned nCompsSOS, bool bRstEn,unsigned nRstInterval) -{ - m_bImgDetailsSet = true; - m_nDimX = nDimX; - m_nDimY = nDimY; - m_nNumSofComps = nCompsSOF; - m_nNumSosComps = nCompsSOS; - m_bRestartEn = bRstEn; - m_nRestartInterval = nRstInterval; -} - -// Reset the image content to prepare it for the upcoming scans -// - TODO: Migrate pixel bitmap allocation / clearing from DecodeScanImg() to here -void CimgDecode::ResetImageContent() -{ -} - -// Set the sampling factor for an image component -// -// INPUT: -// - nCompInd = Component index from Nf (ie. 1..255) -// - nSampFactH = Sampling factor in horizontal direction -// - nSampFactV = Sampling factor in vertical direction -// POST: -// - m_anSofSampFactH[] -// - m_anSofSampFactV[] -// NOTE: -// - Called asynchronously by the JFIF decoder in SOF -// -void CimgDecode::SetSofSampFactors(unsigned nCompInd,unsigned nSampFactH, unsigned nSampFactV) -{ - // TODO: Check range - m_anSofSampFactH[nCompInd] = nSampFactH; - m_anSofSampFactV[nCompInd] = nSampFactV; -} - - -// Update the preview mode (affects channel display) -// -// INPUT: -// - nMode = Mode used in channel display (eg. NONE, RGB, YCC) -// See PREVIEW_* constants -// -void CimgDecode::SetPreviewMode(unsigned nMode) -{ - // Need to check to see if mode has changed. If so, we - // need to recalculate the temporary preview. - m_nPreviewMode = nMode; - CalcChannelPreview(); -} - -// Update any level shifts for the preview display -// -// INPUT: -// - nMcuX = MCU index in X direction -// - nMcuY = MCU index in Y direction -// - nY = DC shift in Y component -// - nCb = DC shift in Cb component -// - nCr = DC shift in Cr component -// -void CimgDecode::SetPreviewYccOffset(unsigned nMcuX,unsigned nMcuY,int nY,int nCb,int nCr) -{ - m_nPreviewShiftY = nY; - m_nPreviewShiftCb = nCb; - m_nPreviewShiftCr = nCr; - m_nPreviewShiftMcuX = nMcuX; - m_nPreviewShiftMcuY = nMcuY; - - CalcChannelPreview(); -} - -// Fetch the current level shift setting for the preview display -// -// OUTPUT: -// - nMcuX = MCU index in X direction -// - nMcuY = MCU index in Y direction -// - nY = DC shift in Y component -// - nCb = DC shift in Cb component -// - nCr = DC shift in Cr component -// -void CimgDecode::GetPreviewYccOffset(unsigned &nMcuX,unsigned &nMcuY,int &nY,int &nCb,int &nCr) -{ - nY = m_nPreviewShiftY; - nCb = m_nPreviewShiftCb; - nCr = m_nPreviewShiftCr; - nMcuX = m_nPreviewShiftMcuX; - nMcuY = m_nPreviewShiftMcuY; -} - - -// Set the Preview MCU insert -// UNUSED -void CimgDecode::SetPreviewMcuInsert(unsigned nMcuX,unsigned nMcuY,int nLen) -{ - - m_nPreviewInsMcuX = nMcuX; - m_nPreviewInsMcuY = nMcuY; - m_nPreviewInsMcuLen = nLen; - - CalcChannelPreview(); -} - -// Get the Preview MCU insert -// UNUSED -void CimgDecode::GetPreviewMcuInsert(unsigned &nMcuX,unsigned &nMcuY,unsigned &nLen) -{ - nMcuX = m_nPreviewInsMcuX; - nMcuY = m_nPreviewInsMcuY; - nLen = m_nPreviewInsMcuLen; -} - -// Fetch the coordinate of the top-left corner of the preview image -// -// OUTPUT: -// - nX = X coordinate of top-left corner -// - nY = Y coordinate of top-left corner -// -void CimgDecode::GetPreviewPos(unsigned &nX,unsigned &nY) -{ - nX = m_nPreviewPosX; - nY = m_nPreviewPosY; -} - -// Fetch the dimensions of the preview image -// -// OUTPUT: -// - nX = X dimension of image -// - nY = Y dimension of iamge -// -void CimgDecode::GetPreviewSize(unsigned &nX,unsigned &nY) -{ - nX = m_nPreviewSizeX; - nY = m_nPreviewSizeY; -} - -// Set a DHT table entry and associated lookup table -// - Configures the fast lookup table for short code bitstrings -// -// INPUT: -// - nDestId = DHT destination table ID (0..3) -// - nClass = Select between DC and AC tables (0=DC, 1=AC) -// - nInd = Index into table -// - nLen = Huffman code length -// - nBits = Huffman code bitstring (left justified) -// - nMask = Huffman code bit mask (left justified) -// - nCode = Huffman code value -// POST: -// - m_anDhtLookup_bitlen[][][] -// - m_anDhtLookup_bits[][][] -// - m_anDhtLookup_mask[][][] -// - m_anDhtLookup_code[][][] -// - m_anDhtLookupSetMax[] -// - m_anDhtLookupfast[][][] -// RETURN: -// - Success if indices are in range -// NOTE: -// - Asynchronously called by JFIF Decoder -// -bool CimgDecode::SetDhtEntry(unsigned nDestId, unsigned nClass, unsigned nInd, unsigned nLen, - unsigned nBits, unsigned nMask, unsigned nCode) -{ - if ( (nDestId >= MAX_DHT_DEST_ID) || (nClass >= MAX_DHT_CLASS) || (nInd >= MAX_DHT_CODES) ) { - CString strTmp = _T("ERROR: Attempt to set DHT entry out of range"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); -#ifdef DEBUG_LOG - CString strDebug; - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("ImgDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - return false; - } - m_anDhtLookup_bitlen[nClass][nDestId][nInd] = nLen; - m_anDhtLookup_bits[nClass][nDestId][nInd] = nBits; - m_anDhtLookup_mask[nClass][nDestId][nInd] = nMask; - m_anDhtLookup_code[nClass][nDestId][nInd] = nCode; - - - // Record the highest numbered DHT set. - // TODO: Currently assuming that there are no missing tables in the sequence - if (nDestId > m_anDhtLookupSetMax[nClass]) { - m_anDhtLookupSetMax[nClass] = nDestId; - } - - unsigned nBitsMsb; - unsigned nBitsExtraLen; - unsigned nBitsExtraVal; - unsigned nBitsMax; - unsigned nFastVal; - - // If the variable-length code is short enough, add it to the - // fast lookup table. - if (nLen <= DHT_FAST_SIZE) { - // nBits is a left-justified number (assume right-most bits are zero) - // nLen is number of leading bits to compare - - // nLen = 5 - // nBits = 32'b1011_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx (0xB800_0000) - // nBitsMsb = 8'b1011_1xxx (0xB8) - // nBitsMsb = 8'b1011_1000 (0xB8) - // nBitsMax = 8'b1011_1111 (0xBF) - - // nBitsExtraLen = 8-len = 8-5 = 3 - - // nBitsExtraVal = (1<> (32-DHT_FAST_SIZE); - nBitsExtraLen = DHT_FAST_SIZE-nLen; - nBitsExtraVal = (1<= MAX_DHT_DEST_ID) || (nClass >= MAX_DHT_CLASS) || (nSize >= MAX_DHT_CODES) ) { - CString strTmp = _T("ERROR: Attempt to set DHT table size out of range"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return false; - } else { - m_anDhtLookupSize[nClass][nDestId] = nSize; - } - - return true; -} - - -// Convert huffman code (DC) to signed value -// - Convert according to ITU-T.81 Table 5 -// -// INPUT: -// - nVal = Huffman DC value (left justified) -// - nBits = Bitstring length of value -// RETURN: -// - Signed integer representing Huffman DC value -// -signed CimgDecode::HuffmanDc2Signed(unsigned nVal,unsigned nBits) -{ - if (nVal >= (unsigned)(1<<(nBits-1))) { - return (signed)(nVal); - } else { - return (signed)( nVal - ((1<> (32-nBits); - return nVal; -} - - -// Removes bits from the holding buffer -// - Discard the leftmost "nNumBits" of m_nScanBuff -// - And then realign file position pointers -// -// INPUT: -// - nNumBits = Number of left-most bits to consume -// POST: -// - m_nScanBuff -// - m_nScanBuff_vacant -// - m_nScanBuffPtr_align -// - m_anScanBuffPtr_pos[] -// - m_anScanBuffPtr_err[] -// - m_nScanBuffLatchErr -// - m_nScanBuffPtr_num -// -inline void CimgDecode::ScanBuffConsume(unsigned nNumBits) -{ - m_nScanBuff <<= nNumBits; - m_nScanBuff_vacant += nNumBits; - - // Need to latch any errors during consumption of multi-bytes - // otherwise we'll miss the error notification if we skip over - // it before we exit this routine! e.g if num_bytes=2 and error - // appears on first byte, then we want to retain it in pos[0] - - - // Now realign the file position pointers if necessary - unsigned nNumBytes = (m_nScanBuffPtr_align+nNumBits) / 8; - for (unsigned nInd=0;nInd=4) { return; } // Unexpected by design - m_anScanBuffPtr_err[m_nScanBuffPtr_num] = SCANBUF_OK; - m_anScanBuffPtr_pos[m_nScanBuffPtr_num++] = nPtr; - - // m_nScanBuffPtr_align stays the same as we add 8 bits -} - -// Augment the current scan buffer with another byte (but mark as error) -// -// INPUT: -// - nNewByte = 8-bit byte to add to buffer -// - nPtr = UNUSED -// - nErr = Error code to associate with this buffer byte -// POST: -// - m_anScanBuffPtr_err[] -// -inline void CimgDecode::ScanBuffAddErr(unsigned nNewByte,unsigned nPtr,unsigned nErr) -{ - ScanBuffAdd(nNewByte,nPtr); - m_anScanBuffPtr_err[m_nScanBuffPtr_num-1] = nErr; - -} - -// Disable any further reporting of scan errors -// -// PRE: -// - m_nScanErrMax -// POST: -// - m_nWarnBadScanNum -// - m_bScanErrorsDisable -// -void CimgDecode::ScanErrorsDisable() -{ - m_nWarnBadScanNum = m_nScanErrMax; - m_bScanErrorsDisable = true; -} - -// Enable reporting of scan errors -// -// POST: -// - m_nWarnBadScanNum -// - m_bScanErrorsDisable -// -void CimgDecode::ScanErrorsEnable() -{ - m_nWarnBadScanNum = 0; - m_bScanErrorsDisable = false; -} - - -// Read in bits from the buffer and find matching huffman codes -// - Input buffer is m_nScanBuff -// - Perform shift in buffer afterwards -// - Abort if there aren't enough bits (note that the scan buffer -// is almost empty when we reach the end of a scan segment) -// -// INPUT: -// - nClass = DHT Table class (0..1) -// - nTbl = DHT Destination ID (0..3) -// PRE: -// - Assume that dht_lookup_size[nTbl] != 0 (already checked) -// - m_bRestartRead -// - m_nScanBuff_vacant -// - m_nScanErrMax -// - m_nScanBuff -// - m_anDhtLookupFast[][][] -// - m_anDhtLookupSize[][] -// - m_anDhtLookup_mask[][][] -// - m_anDhtLookup_bits[][][] -// - m_anDhtLookup_bitlen[][][] -// - m_anDhtLookup_code[][][] -// - m_nPrecision -// POST: -// - m_nScanBitsUsed# is calculated -// - m_bScanEnd -// - m_bScanBad -// - m_nWarnBadScanNum -// - m_anDhtHisto[][][] -// OUTPUT: -// - rZrl = Zero run amount (if any) -// - rVal = Coefficient value -// RETURN: -// - Status from attempting to decode the current value -// -// PERFORMANCE: -// - Tried to unroll all function calls listed below, -// but performance was same before & after (27sec). -// - Calls unrolled: BuffTopup(), ScanBuffConsume(), -// ExtractBits(), HuffmanDc2Signed() -teRsvRet CimgDecode::ReadScanVal(unsigned nClass,unsigned nTbl,unsigned &rZrl,signed &rVal) -{ - bool bDone = false; - unsigned nInd = 0; - unsigned nCode = DHT_CODE_UNUSED; // Not a valid nCode - unsigned nVal; - - ASSERT(nClass < MAX_DHT_CLASS); - ASSERT(nTbl < MAX_DHT_DEST_ID); - - m_nScanBitsUsed1 = 0; // bits consumed for nCode - m_nScanBitsUsed2 = 0; - - rZrl = 0; - rVal = 0; - - // First check to see if we've entered here with a completely empty - // scan buffer with a restart marker already observed. In that case - // we want to exit with condition 3 (restart terminated) - if ( (m_nScanBuff_vacant == 32) && (m_bRestartRead) ) { - return RSV_RST_TERM; - } - - - // Has the scan buffer been depleted? - if (m_nScanBuff_vacant >= 32) { - // Trying to overread end of scan segment - - if (m_nWarnBadScanNum < m_nScanErrMax) { - CString strTmp; - strTmp.Format(_T("*** ERROR: Overread scan segment (before nCode)! @ Offset: %s"),(LPCTSTR)GetScanBufPos()); - m_pLog->AddLineErr(strTmp); - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - m_bScanEnd = true; - m_bScanBad = true; - return RSV_UNDERFLOW; - } - - // Top up the buffer just in case - BuffTopup(); - - bDone = false; - bool bFound = false; - - // Fast search for variable-length huffman nCode - // Do direct lookup for any codes DHT_FAST_SIZE bits or shorter - - unsigned nCodeMsb; - unsigned nCodeFastSearch; - - // Only enable this fast search if m_nScanBuff_vacant implies - // that we have at least DHT_FAST_SIZE bits available in the buffer! - if ((32-m_nScanBuff_vacant) >= DHT_FAST_SIZE) { - nCodeMsb = m_nScanBuff>>(32-DHT_FAST_SIZE); - nCodeFastSearch = m_anDhtLookupfast[nClass][nTbl][nCodeMsb]; - if (nCodeFastSearch != DHT_CODE_UNUSED) { - // We found the code! - m_nScanBitsUsed1 += (nCodeFastSearch>>8); - nCode = (nCodeFastSearch & 0xFF); - bDone = true; - bFound = true; - } - } - - - // Slow search for variable-length huffman nCode - while (!bDone) { - unsigned nBitLen; - if ((m_nScanBuff & m_anDhtLookup_mask[nClass][nTbl][nInd]) == m_anDhtLookup_bits[nClass][nTbl][nInd]) { - - nBitLen = m_anDhtLookup_bitlen[nClass][nTbl][nInd]; - // Just in case this VLC bit string is longer than the number of - // bits we have left in the buffer (due to restart marker or end - // of scan data), we need to double-check - if (nBitLen <= 32-m_nScanBuff_vacant) { - nCode = m_anDhtLookup_code[nClass][nTbl][nInd]; - m_nScanBitsUsed1 += nBitLen; - bDone = true; - bFound = true; - } - } - nInd++; - if (nInd >= m_anDhtLookupSize[nClass][nTbl]) { - bDone = true; - } - } - - // Could not find huffman nCode in table! - if (!bFound) { - - // If we didn't find the huffman nCode, it might be due to a - // restart marker that prematurely stopped the scan buffer filling. - // If so, return with an indication so that DecodeScanComp() can - // handle the restart marker, refill the scan buffer and then - // re-do ReadScanVal() - if (m_bRestartRead) { - return RSV_RST_TERM; - } - - // FIXME: - // What should we be consuming here? we need to make forward progress - // in file. Options: - // 1) Move forward to next byte in file - // 2) Move forward to next bit in file - // Currently moving 1 bit so that we have slightly more opportunities - // to re-align earlier. - m_nScanBitsUsed1 = 1; - nCode = DHT_CODE_UNUSED; - } - - // Log an entry into a histogram - if (m_nScanBitsUsed1 < MAX_DHT_CODELEN+1) { - m_anDhtHisto[nClass][nTbl][m_nScanBitsUsed1]++; - } else { - ASSERT(false); - // Somehow we got out of range - } - - - ScanBuffConsume(m_nScanBitsUsed1); - - // Did we overread the scan buffer? - if (m_nScanBuff_vacant > 32) { - // The nCode consumed more bits than we had! - CString strTmp; - strTmp.Format(_T("*** ERROR: Overread scan segment (after nCode)! @ Offset: %s"),(LPCTSTR)GetScanBufPos()); - m_pLog->AddLineErr(strTmp); - m_bScanEnd = true; - m_bScanBad = true; - return RSV_UNDERFLOW; - } - - // Replenish buffer after nCode extraction and before variable extra bits - // This is required because we may have a 12 bit nCode followed by a 16 bit var length bitstring - BuffTopup(); - - // Did we find the nCode? - if (nCode != DHT_CODE_UNUSED) { - rZrl = (nCode & 0xF0) >> 4; - m_nScanBitsUsed2 = nCode & 0x0F; - if ( (rZrl == 0) && (m_nScanBitsUsed2 == 0) ) { - // EOB (was bits_extra=0) - return RSV_EOB; - } else if (m_nScanBitsUsed2 == 0) { - // Zero rValue - rVal = 0; - return RSV_OK; - - } else { - // Normal nCode - nVal = ExtractBits(m_nScanBuff,m_nScanBitsUsed2); - rVal = HuffmanDc2Signed(nVal,m_nScanBitsUsed2); - - // Now handle the different precision values - // Treat 12-bit like 8-bit but scale values first (ie. drop precision down to 8-bit) - signed nPrecisionDivider = 1; - if (m_nPrecision >= 8) { - nPrecisionDivider = 1<<(m_nPrecision-8); - rVal /= nPrecisionDivider; - } else { - // Precision value seems out of range! - } - - ScanBuffConsume(m_nScanBitsUsed2); - - // Did we overread the scan buffer? - if (m_nScanBuff_vacant > 32) { - // The nCode consumed more bits than we had! - CString strTmp; - strTmp.Format(_T("*** ERROR: Overread scan segment (after bitstring)! @ Offset: %s"),(LPCTSTR)GetScanBufPos()); - m_pLog->AddLineErr(strTmp); - m_bScanEnd = true; - m_bScanBad = true; - return RSV_UNDERFLOW; - } - - return RSV_OK; - } - } else { - // ERROR: Invalid huffman nCode! - - // FIXME: We may also enter here if we are about to encounter a - // restart marker! Need to see if ScanBuf is terminated by - // restart marker; if so, then we simply flush the ScanBuf, - // consume the 2-byte RST marker, clear the ScanBuf terminate - // reason, then indicate to caller that they need to call ReadScanVal - // again. - - if (m_nWarnBadScanNum < m_nScanErrMax) { - CString strTmp; - strTmp.Format(_T("*** ERROR: Can't find huffman bitstring @ %s, table %u, value [0x%08x]"),(LPCTSTR)GetScanBufPos(),nTbl,m_nScanBuff); - m_pLog->AddLineErr(strTmp); - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - // TODO: What rValue and ZRL should we return? - m_bScanBad = true; - return RSV_UNDERFLOW; - } - - // NOTE: Can't reach here - // return RSV_UNDERFLOW; -} - - - -// Refill the scan buffer as needed -// -void CimgDecode::BuffTopup() -{ - unsigned nRetVal; - - // Do we have space to load another byte? - bool bDone = (m_nScanBuff_vacant < 8); - - // Have we already reached the end of the scan segment? - if (m_bScanEnd) { - bDone = true; - } - - while (!bDone) { - nRetVal = BuffAddByte(); - - // NOTE: If we have read in a restart marker, the above call will not - // read in any more bits into the scan buffer, so we should just simply - // say that we've done the best we can for the top up. - if (m_bRestartRead) { - bDone = true; - } - - if (m_nScanBuff_vacant < 8) { - bDone = true; - } - // If the buffer read returned an error or end of scan segment - // then stop filling buffer - if (nRetVal != 0) { - bDone = true; - } - } -} - -// Check for restart marker and compare the index against expected -// -// PRE: -// - m_nScanBuffPtr -// RETURN: -// - Restart marker found at the current buffer position -// NOTE: -// - This routine expects that we did not remove restart markers -// from the bytestream (in BuffAddByte). -// -bool CimgDecode::ExpectRestart() -{ - unsigned nMarker; - - unsigned nBuf0 = m_pWBuf->Buf(m_nScanBuffPtr); - unsigned nBuf1 = m_pWBuf->Buf(m_nScanBuffPtr+1); - - // Check for restart marker first. Assume none back-to-back. - if (nBuf0 == 0xFF) { - nMarker = nBuf1; - - // FIXME: Later, check that we are on the right marker! - if ((nMarker >= JFIF_RST0) && (nMarker <= JFIF_RST7)) { - - if (m_bVerbose) { - CString strTmp; - strTmp.Format(_T(" RESTART marker: @ 0x%08X.0 : RST%02u"), - m_nScanBuffPtr,nMarker-JFIF_RST0); - m_pLog->AddLine(strTmp); - } - - m_nRestartRead++; - - // FIXME: - // Later on, we should be checking for RST out of - // sequence! - - // Now we need to skip to the next bytes - m_nScanBuffPtr+=2; - - // Now refill in the buffer if we need to - BuffAddByte(); - - return true; - } - } - - return false; - -} - -// Add a byte to the scan buffer from the file -// - Handle stuff bytes -// - Handle restart markers -// -// PRE: -// - m_nScanBuffPtr -// POST: -// - m_nRestartRead -// - m_nRestartLastInd -// -unsigned CimgDecode::BuffAddByte() -{ - unsigned nMarker = 0x00; - unsigned nBuf0,nBuf1; - - // If we have already read in a restart marker but not - // handled it yet, then simply return without reading any - // more bytes - if (m_bRestartRead) { - return 0; - } - - nBuf0 = m_pWBuf->Buf(m_nScanBuffPtr); - nBuf1 = m_pWBuf->Buf(m_nScanBuffPtr+1); - - // Check for restart marker first. Assume none back-to-back. - if (nBuf0 == 0xFF) { - nMarker = nBuf1; - - if ((nMarker >= JFIF_RST0) && (nMarker <= JFIF_RST7)) { - - if (m_bVerbose) { - CString strTmp; - strTmp.Format(_T(" RESTART marker: @ 0x%08X.0 : RST%02u"), - m_nScanBuffPtr,nMarker-JFIF_RST0); - m_pLog->AddLine(strTmp); - } - - m_nRestartRead++; - m_nRestartLastInd = nMarker - JFIF_RST0; - if (m_nRestartLastInd != m_nRestartExpectInd) { - if (!m_bScanErrorsDisable) { - CString strTmp; - strTmp.Format(_T(" ERROR: Expected RST marker index RST%u got RST%u @ 0x%08X.0"), - m_nRestartExpectInd,m_nRestartLastInd,m_nScanBuffPtr); - m_pLog->AddLineErr(strTmp); - } - } - m_nRestartExpectInd = (m_nRestartLastInd+1)%8; - - // FIXME: Later on, we should be checking for RST out of sequence - - // END BUFFER READ HERE! - // Indicate that a Restart marker has been seen, which - // will prevent further reading of scan buffer until it - // has been handled. - m_bRestartRead = true; - - return 0; - -/* - // Now we need to skip to the next bytes - m_nScanBuffPtr+=2; - - // Update local saved buffer vars - nBuf0 = m_pWBuf->Buf(m_nScanBuffPtr); - nBuf1 = m_pWBuf->Buf(m_nScanBuffPtr+1); - - - // Use ScanBuffAddErr() to mark this byte as being after Restart marker! - m_anScanBuffPtr_err[m_nScanBuffPtr_num] = SCANBUF_RST; - - // FIXME: We should probably discontinue filling the scan - // buffer if we encounter a restart marker. This will stop us - // from reading past the restart marker and missing the necessary - // step in resetting the decoder accumulation state. - - // When we stop adding bytes to the buffer, we should also - // mark this scan buffer with a flag to indicate that it was - // ended by RST not by EOI or an Invalid Marker. - - // If the main decoder (in ReadScanVal) cannot find a VLC code - // match with the few bits left in the scan buffer - // (presumably padded with 1's), then it should check to see - // if the buffer is terminated by RST. If so, then it - // purges the scan buffer, advances to the next byte (after the - // RST marker) and does a fill, then re-invokes the ReadScanVal - // routine. At the level above, the Decoder that is calling - // ReadScanVal should be counting MCU rows and expect this error - // from ReadScanVal (no code match and buf terminated by RST). - // If it happened out of place, we have corruption somehow! - - // See IJG Code: - // jdmarker.c: - // read_restart_marker() - // jpeg_resync_to_restart() -*/ - } - - } - - - // Check for Byte Stuff - if ((nBuf0 == 0xFF) && (nBuf1 == 0x00)) { - - // Add byte to m_nScanBuff & record file position - ScanBuffAdd(nBuf0,m_nScanBuffPtr); - m_nScanBuffPtr+=2; - - - } else if ((nBuf0 == 0xFF) && (nBuf1 == 0xFF)) { - // NOTE: - // We should be checking for a run of 0xFF before EOI marker. - // It is possible that we could get marker padding on the end - // of the scan segment, so we'd want to handle it here, otherwise - // we'll report an error that we got a non-EOI Marker in scan - // segment. - - // The downside of this is that we don't detect errors if we have - // a run of 0xFF in the stream, until we leave the string of FF's. - // If it were followed by an 0x00, then we may not notice it at all. - // Probably OK. - - /* - if (m_nWarnBadScanNum < m_nScanErrMax) { - CString strTmp; - strTmp.Format(_T(" Scan Data encountered sequence 0xFFFF @ 0x%08X.0 - Assume start of marker pad at end of scan segment"), - m_nScanBuffPtr); - m_pLog->AddLineWarn(strTmp); - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - // Treat as single byte of byte stuff for now, since we don't - // know if FF bytes will arrive in pairs or not. - m_nScanBuffPtr+=1; - */ - - // NOTE: - // If I treat the 0xFFFF as a potential marker pad, we may not stop correctly - // upon error if we see this inside the image somewhere (not at end). - // Therefore, let's simply add these bytes to the buffer and let the DecodeScanImg() - // routine figure out when we're at the end, etc. - - ScanBuffAdd(nBuf0,m_nScanBuffPtr); - m_nScanBuffPtr+=1; - - } else if ((nBuf0 == 0xFF) && (nMarker != 0x00)) { - - // We have read a marker... don't assume that this is bad as it will - // always happen at the end of the scan segment. Therefore, we will - // assume this marker is valid (ie. not bit error in scan stream) - // and mark the end of the scan segment. - - if (m_nWarnBadScanNum < m_nScanErrMax) { - CString strTmp; - strTmp.Format(_T(" Scan Data encountered marker 0xFF%02X @ 0x%08X.0"), - nMarker,m_nScanBuffPtr); - m_pLog->AddLine(strTmp); - - if (nMarker != JFIF_EOI) { - m_pLog->AddLineErr(_T(" NOTE: Marker wasn't EOI (0xFFD9)")); - } - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - - // Optionally stop immediately upon a bad marker -#ifdef SCAN_BAD_MARKER_STOP - m_bScanEnd = true; - return 1; -#else - // Add byte to m_nScanBuff & record file position - ScanBuffAddErr(nBuf0,m_nScanBuffPtr,SCANBUF_BADMARK); - - m_nScanBuffPtr+=1; -#endif - - - } else { - // Normal byte - // Add byte to m_nScanBuff & record file position - ScanBuffAdd(nBuf0,m_nScanBuffPtr); - - m_nScanBuffPtr+=1; - } - - return 0; -} - - -// Define minimum value before we include DCT entry in -// the IDCT calcs. -// NOTE: Currently disabled -#define IDCT_COEF_THRESH 4 - - -// Decode a single component for one block of an MCU -// - Pull bits from the main buffer -// - Find matching huffman codes -// - Fill in the IDCT matrix (m_anDctBlock[]) -// - Perform the IDCT to create spatial domain -// -// INPUT: -// - nTblDhtDc = DHT table ID for DC component -// - nTblDhtAc = DHT talbe ID for AC component -// - nMcuX = UNUSED -// - nMcuY = UNUSED -// RETURN: -// - Indicate if the decode was successful -// POST: -// - m_nScanCurDc = DC component value -// Performance: -// - This routine is called on every block so it must be -// reasonably efficient. Only call string routines when we -// are sure that we have an error. -// -// FIXME: Consider adding checks for DHT table like in ReadScanVal() -// -bool CimgDecode::DecodeScanComp(unsigned nTblDhtDc,unsigned nTblDhtAc,unsigned nTblDqt,unsigned nMcuX,unsigned nMcuY) -{ - nMcuX; // Unreferenced param - nMcuY; // Unreferenced param - unsigned nZrl; - signed nVal; - bool bDone = false; - bool bDC = true; // Start with DC coeff - - teRsvRet eRsvRet; // Return value from ReadScanVal() - - unsigned nNumCoeffs = 0; - //unsigned nDctMax = 0; // Maximum DCT coefficient to use for IDCT - unsigned nSavedBufPos = 0; - unsigned nSavedBufErr = SCANBUF_OK; - unsigned nSavedBufAlign = 0; - - // Profiling: No difference noted - DecodeIdctClear(); - - while (!bDone) { - BuffTopup(); - - // Note that once we perform ReadScanVal(), then GetScanBufPos() will be - // after the decoded VLC - // Save old file position info in case we want accurate error positioning - nSavedBufPos = m_anScanBuffPtr_pos[0]; - nSavedBufErr = m_nScanBuffLatchErr; - nSavedBufAlign = m_nScanBuffPtr_align; - - // ReadScanVal return values: - // - RSV_OK OK - // - RSV_EOB End of block - // - RSV_UNDERFLOW Ran out of data in buffer - // - RSV_RST_TERM No huffman code found, but restart marker seen - // Assume nTblDht just points to DC tables, adjust for AC - // e.g. nTblDht = 0,2,4 - eRsvRet = ReadScanVal(bDC?0:1,bDC?nTblDhtDc:nTblDhtAc,nZrl,nVal); - - // Handle Restart marker first. - if (eRsvRet == RSV_RST_TERM) { - // Assume that m_bRestartRead is TRUE - // No huffman code found because either we ran out of bits - // in the scan buffer or the bits padded with 1's didn't result - // in a valid VLC code. - - // Steps: - // 1) Reset the decoder state (DC values) - // 2) Advance the buffer pointer (might need to handle the - // case of perfect alignment to byte boundary separately) - // 3) Flush the Scan Buffer - // 4) Clear m_bRestartRead - // 5) Refill Scan Buffer with BuffTopUp() - // 6) Re-invoke ReadScanVal() - - // Step 1: - DecodeRestartDcState(); - - // Step 2 - m_nScanBuffPtr += 2; - - // Step 3 - DecodeRestartScanBuf(m_nScanBuffPtr,true); - - // Step 4 - m_bRestartRead = false; - - // Step 5 - BuffTopup(); - - // Step 6 - // ASSERT is because we assume that we don't get 2 restart - // markers in a row! - eRsvRet = ReadScanVal(bDC?0:1,bDC?nTblDhtDc:nTblDhtAc,nZrl,nVal); - ASSERT(eRsvRet != RSV_RST_TERM); - - } - - // In case we encountered a restart marker or bad scan marker - if (nSavedBufErr == SCANBUF_BADMARK) { - - // Mark as scan error - m_nScanCurErr = true; - - m_bScanBad = true; - - if (m_nWarnBadScanNum < m_nScanErrMax) { - CString strPos = GetScanBufPos(nSavedBufPos,nSavedBufAlign); - CString strTmp; - strTmp.Format(_T("*** ERROR: Bad marker @ %s"),(LPCTSTR)strPos); - m_pLog->AddLineErr(strTmp); - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - // Reset the latched error now that we've dealt with it - m_nScanBuffLatchErr = SCANBUF_OK; - - } - - - short int nVal2; - nVal2 = static_cast(nVal & 0xFFFF); - - if (eRsvRet == RSV_OK) { - // DC entry is always one value only - if (bDC) { - DecodeIdctSet(nTblDqt,nNumCoeffs,nZrl,nVal2); //CALZ - bDC = false; // Now we will be on AC comps - } else { - // We're on AC entry, so keep looping until - // we have finished up to 63 entries - // Set entry in table - // PERFORMANCE: - // No noticeable difference if following is skipped - if (m_bDecodeScanAc) { - DecodeIdctSet(nTblDqt,nNumCoeffs,nZrl,nVal2); - } - } - } else if (eRsvRet == RSV_EOB) { - if (bDC) { - DecodeIdctSet(nTblDqt,nNumCoeffs,nZrl,nVal2); //CALZ - // Now that we have finished the DC coefficient, start on AC coefficients - bDC = false; - } else { - // Now that we have finished the AC coefficients, we are done - bDone = true; - } - // - } else if (eRsvRet == RSV_UNDERFLOW) { - // ERROR - - if (m_nWarnBadScanNum < m_nScanErrMax) { - CString strPos = GetScanBufPos(nSavedBufPos,nSavedBufAlign); - CString strTmp; - strTmp.Format(_T("*** ERROR: Bad huffman code @ %s"),(LPCTSTR)strPos); - m_pLog->AddLineErr(strTmp); - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - m_nScanCurErr = true; - bDone = true; - - return false; - } - - // Increment the number of coefficients - nNumCoeffs += 1+nZrl; - - // If we have filled out an entire 64 entries, then we move to - // the next block without an EOB - // NOTE: This is only 63 entries because we assume that we - // are doing the AC (DC was already bDone in a different pass) - - // FIXME: Would like to combine DC & AC in one pass so that - // we don't end up having to use 2 tables. The check below will - // also need to be changed to == 64. - // - // Currently, we will have to correct AC nNumCoeffs entries (in IDCT) to - // be +1 to get real index, as we are ignoring DC position 0. - - if (nNumCoeffs == 64) { - bDone = true; - } else if (nNumCoeffs > 64) { - // ERROR - - if (m_nWarnBadScanNum < m_nScanErrMax) { - CString strTmp; - CString strPos = GetScanBufPos(nSavedBufPos,nSavedBufAlign); - strTmp.Format(_T("*** ERROR: @ %s, nNumCoeffs>64 [%u]"),(LPCTSTR)strPos,nNumCoeffs); - m_pLog->AddLineErr(strTmp); - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - m_nScanCurErr = true; - m_bScanBad = true; - bDone = true; - - nNumCoeffs = 64; // Just to ensure we don't use an overrun value anywhere - } - - - } - - // We finished the MCU - // Now calc the IDCT matrix - - // The following code needs to be very efficient. - // A number of experiments have been carried out to determine - // the magnitude of speed improvements through various settings - // and IDCT methods: - // - // PERFORMANCE: - // Example file: canon_1dsmk2_ - // - // 0:06 Turn off m_bDecodeScanAc (so no array memset, etc.) - // 0:10 m_bDecodeScanAc=true, but DecodeIdctCalc() skipped - // 0:26 m_bDecodeScanAc=true and DecodeIdctCalcFixedpt() - // 0:27 m_bDecodeScanAc=true and DecodeIdctCalcFloat() - - if (m_bDecodeScanAc) { -#ifdef IDCT_FIXEDPT - DecodeIdctCalcFixedpt(); -#else - - // TODO: Select appropriate conversion routine based on performance -// DecodeIdctCalcFloat(nDctMax); -// DecodeIdctCalcFloat(nNumCoeffs); -// DecodeIdctCalcFloat(m_nDctCoefMax); - DecodeIdctCalcFloat(64); -// DecodeIdctCalcFloat(32); - -#endif - } - - - return true; -} - - -// Decode a single component for one block of an MCU with printing -// used for the Detailed Decode functionality -// - Same as DecodeScanComp() but adds reporting of variable length codes (VLC) -// -// INPUT: -// - nTblDhtDc = DHT table ID for DC component -// - nTblDhtAc = DHT talbe ID for AC component -// - nMcuX = Current MCU X coordinate (for reporting only) -// - nMcuY = Current MCU Y coordinate (for reporting only) -// RETURN: -// - Indicate if the decode was successful -// POST: -// - m_nScanCurDc = DC component value -// PERFORMANCE: -// - As this routine is called for every MCU, it is important -// for it to be efficient. However, we are in print mode, so -// we can afford to be slower. -// -// FIXME: need to fix like DecodeScanComp() (ordering of exit conditions, etc.) -// FIXME: Consider adding checks for DHT table like in ReadScanVal() -// -bool CimgDecode::DecodeScanCompPrint(unsigned nTblDhtDc,unsigned nTblDhtAc,unsigned nTblDqt,unsigned nMcuX,unsigned nMcuY) -{ - bool bPrint = true; - teRsvRet eRsvRet; - CString strTmp; - CString strTbl; - CString strSpecial; - CString strPos; - unsigned nZrl; - signed nVal; - bool bDone = false; - - bool bDC = true; // Start with DC component - - if (bPrint) { - switch(nTblDqt) { - case 0: - strTbl = _T("Lum"); - break; - case 1: - strTbl = _T("Chr(0)"); // Usually Cb - break; - case 2: - strTbl = _T("Chr(1)"); // Usually Cr - break; - default: - strTbl = _T("???"); - break; - } - strTmp.Format(_T(" %s (Tbl #%u), MCU=[%u,%u]"),(LPCTSTR)strTbl,nTblDqt,nMcuX,nMcuY); - m_pLog->AddLine(strTmp); - } - - unsigned nNumCoeffs = 0; - unsigned nSavedBufPos = 0; - unsigned nSavedBufErr = SCANBUF_OK; - unsigned nSavedBufAlign = 0; - - DecodeIdctClear(); - - while (!bDone) { - BuffTopup(); - - // Note that once we perform ReadScanVal(), then GetScanBufPos() will be - // after the decoded VLC - - // Save old file position info in case we want accurate error positioning - nSavedBufPos = m_anScanBuffPtr_pos[0]; - nSavedBufErr = m_nScanBuffLatchErr; - nSavedBufAlign = m_nScanBuffPtr_align; - - // Return values: - // 0 - OK - // 1 - EOB - // 2 - Overread error - // 3 - No huffman code found, but restart marker seen - eRsvRet = ReadScanVal(bDC?0:1,bDC?nTblDhtDc:nTblDhtAc,nZrl,nVal); - - // Handle Restart marker first. - if (eRsvRet == RSV_RST_TERM) { - // Assume that m_bRestartRead is TRUE - // No huffman code found because either we ran out of bits - // in the scan buffer or the bits padded with 1's didn't result - // in a valid VLC code. - - // Steps: - // 1) Reset the decoder state (DC values) - // 2) Advance the buffer pointer (might need to handle the - // case of perfect alignment to byte boundary separately) - // 3) Flush the Scan Buffer - // 4) Clear m_bRestartRead - // 5) Refill Scan Buffer with BuffTopUp() - // 6) Re-invoke ReadScanVal() - - // Step 1: - DecodeRestartDcState(); - - // Step 2 - m_nScanBuffPtr += 2; - - // Step 3 - DecodeRestartScanBuf(m_nScanBuffPtr,true); - - // Step 4 - m_bRestartRead = false; - - // Step 5 - BuffTopup(); - - // Step 6 - // ASSERT is because we assume that we don't get 2 restart - // markers in a row! - eRsvRet = ReadScanVal(bDC?0:1,bDC?nTblDhtDc:nTblDhtAc,nZrl,nVal); - ASSERT(eRsvRet != RSV_RST_TERM); - - } - - // In case we encountered a restart marker or bad scan marker - if (nSavedBufErr == SCANBUF_BADMARK) { - - // Mark as scan error - m_nScanCurErr = true; - - m_bScanBad = true; - - if (m_nWarnBadScanNum < m_nScanErrMax) { - strPos = GetScanBufPos(nSavedBufPos,nSavedBufAlign); - strTmp.Format(_T("*** ERROR: Bad marker @ %s"),(LPCTSTR)strPos); - m_pLog->AddLineErr(strTmp); - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - // Reset the latched error now that we've dealt with it - m_nScanBuffLatchErr = SCANBUF_OK; - - } - - - // Should this be before or after restart checks? - unsigned nCoeffStart = nNumCoeffs; - unsigned nCoeffEnd = nNumCoeffs+nZrl; - - short int nVal2; - nVal2 = static_cast(nVal & 0xFFFF); - - if (eRsvRet == RSV_OK) { - strSpecial = _T(""); - // DC entry is always one value only - // FIXME: Do I need nTblDqt == 4 as well? - if (bDC) { - DecodeIdctSet(nTblDqt,nNumCoeffs,nZrl,nVal2); - bDC = false; // Now we will be on AC comps - } else { - // We're on AC entry, so keep looping until - // we have finished up to 63 entries - // Set entry in table - DecodeIdctSet(nTblDqt,nNumCoeffs,nZrl,nVal2); - } - } else if (eRsvRet == RSV_EOB) { - if (bDC) { - DecodeIdctSet(nTblDqt,nNumCoeffs,nZrl,nVal2); - bDC = false; // Now we will be on AC comps - } else { - bDone = true; - } - strSpecial = _T("EOB"); - } else if (eRsvRet == RSV_UNDERFLOW) { - - if (m_nWarnBadScanNum < m_nScanErrMax) { - strSpecial = _T("ERROR"); - strPos = GetScanBufPos(nSavedBufPos,nSavedBufAlign); - - strTmp.Format(_T("*** ERROR: Bad huffman code @ %s"),(LPCTSTR)strPos); - m_pLog->AddLineErr(strTmp); - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - m_nScanCurErr = true; - bDone = true; - - // Print out before we leave - if (bPrint) { - ReportVlc(nSavedBufPos,nSavedBufAlign,nZrl,nVal2, - nCoeffStart,nCoeffEnd,strSpecial); - } - - - return false; - } - - // Increment the number of coefficients - nNumCoeffs += 1+nZrl; - // If we have filled out an entire 64 entries, then we move to - // the next block without an EOB - // NOTE: This is only 63 entries because we assume that we - // are doing the AC (DC was already done in a different pass) - if (nNumCoeffs == 64) { - strSpecial = _T("EOB64"); - bDone = true; - } else if (nNumCoeffs > 64) { - // ERROR - - if (m_nWarnBadScanNum < m_nScanErrMax) { - strPos = GetScanBufPos(nSavedBufPos,nSavedBufAlign); - strTmp.Format(_T("*** ERROR: @ %s, nNumCoeffs>64 [%u]"),(LPCTSTR)strPos,nNumCoeffs); - m_pLog->AddLineErr(strTmp); - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - m_nScanCurErr = true; - m_bScanBad = true; - bDone = true; - - nNumCoeffs = 64; // Just to ensure we don't use an overrun value anywhere - } - - if (bPrint) { - ReportVlc(nSavedBufPos,nSavedBufAlign,nZrl,nVal2, - nCoeffStart,nCoeffEnd,strSpecial); - } - - } - - // We finished the MCU component - - - // Now calc the IDCT matrix -#ifdef IDCT_FIXEDPT - DecodeIdctCalcFixedpt(); -#else -// DecodeIdctCalcFloat(nNumCoeffs); - DecodeIdctCalcFloat(64); -#endif - - // Now report the coefficient matrix (after zigzag reordering) - if (bPrint) { - ReportDctMatrix(); - } - - return true; -} - - - - -// Print out the DCT matrix for a given block -// -// PRE: -// - m_anDctBlock[] -// -void CimgDecode::ReportDctMatrix() -{ - CString strTmp; - CString strLine; - int nCoefVal; - - for (unsigned nY=0;nY<8;nY++) { - if (nY == 0) { - strLine = _T(" DCT Matrix=["); - } else { - strLine = _T(" ["); - } - for (unsigned nX=0;nX<8;nX++) { - strTmp = _T(""); - nCoefVal = m_anDctBlock[nY*8+nX]; - strTmp.Format(_T("%5d"),nCoefVal); - strLine.Append(strTmp); - - if (nX != 7) { - strLine.Append(_T(" ")); - } - } - strLine.Append(_T("]")); - m_pLog->AddLine(strLine); - } - m_pLog->AddLine(_T("")); - -} - - -// Report out the variable length codes (VLC) -// -// Need to consider impact of padding bytes... When pads get extracted, they -// will not appear in the binary display shown below. Might want the get buffer -// to do post-pad removal first. -// -// eg. file Dsc0019.jpg -// Overlay 0x4215 = 7FFF0000 len=4 -// -// INPUT: -// - nVlcPos = -// - nVlcAlign = -// - nZrl = -// - nVal = -// - nCoeffStart = -// - nCoeffEnd = -// - specialStr = -// -void CimgDecode::ReportVlc(unsigned nVlcPos, unsigned nVlcAlign, - unsigned nZrl, int nVal, - unsigned nCoeffStart,unsigned nCoeffEnd, - CString specialStr) -{ - CString strPos; - CString strTmp; - - unsigned nBufByte[4]; - unsigned nBufPosInd = nVlcPos; - CString strData = _T(""); - CString strByte1 = _T(""); - CString strByte2 = _T(""); - CString strByte3 = _T(""); - CString strByte4 = _T(""); - CString strBytes = _T(""); - CString strBytesOrig = _T(""); - CString strBinMarked = _T(""); - - strPos = GetScanBufPos(nVlcPos,nVlcAlign); - - // Read in the buffer bytes, but skip pad bytes (0xFF00 -> 0xFF) - - // We need to look at previous byte as it might have been - // start of stuff byte! If so, we need to ignore the byte - // and advance the pointers. - BYTE nBufBytePre = m_pWBuf->Buf(nBufPosInd-1); - nBufByte[0] = m_pWBuf->Buf(nBufPosInd++); - if ( (nBufBytePre == 0xFF) && (nBufByte[0] == 0x00) ) { - nBufByte[0] = m_pWBuf->Buf(nBufPosInd++); - } - - nBufByte[1] = m_pWBuf->Buf(nBufPosInd++); - if ( (nBufByte[0] == 0xFF) && (nBufByte[1] == 0x00) ) { - nBufByte[1] = m_pWBuf->Buf(nBufPosInd++); - } - nBufByte[2] = m_pWBuf->Buf(nBufPosInd++); - if ( (nBufByte[1] == 0xFF) && (nBufByte[2] == 0x00) ) { - nBufByte[2] = m_pWBuf->Buf(nBufPosInd++); - } - nBufByte[3] = m_pWBuf->Buf(nBufPosInd++); - if ( (nBufByte[2] == 0xFF) && (nBufByte[3] == 0x00) ) { - nBufByte[3] = m_pWBuf->Buf(nBufPosInd++); - } - - strByte1 = Dec2Bin(nBufByte[0],8,true); - strByte2 = Dec2Bin(nBufByte[1],8,true); - strByte3 = Dec2Bin(nBufByte[2],8,true); - strByte4 = Dec2Bin(nBufByte[3],8,true); - strBytesOrig = strByte1 + _T(" ") + strByte2 + _T(" ") + strByte3 + _T(" ") + strByte4; - strBytes = strByte1 + strByte2 + strByte3 + strByte4; - - for (unsigned ind=0;indAddLine(strTmp); - -} - - -// Clear input and output matrix -// -// POST: -// - m_anDctBlock[] -// - m_afIdctBlock[] -// - m_anIdctBlock[] -// - m_nDctCoefMax -// -void CimgDecode::DecodeIdctClear() -{ - memset(m_anDctBlock, 0, sizeof m_anDctBlock); - memset(m_afIdctBlock, 0, sizeof m_afIdctBlock); - memset(m_anIdctBlock, 0, sizeof m_anIdctBlock); - - m_nDctCoefMax = 0; -} - -// Set the DCT matrix entry -// - Fills in m_anDctBlock[] with the unquantized coefficients -// - Reversing the quantization is done using m_anDqtCoeffZz[][] -// -// INPUT: -// - nDqtTbl = -// - num_coeffs = -// - zrl = -// - val = -// PRE: -// - glb_anZigZag[] -// - m_anDqtCoeffZz[][] -// - m_nDctCoefMax -// POST: -// - m_anDctBlock[] -// NOTE: -// - We need to convert between the zigzag order and the normal order -// -void CimgDecode::DecodeIdctSet(unsigned nDqtTbl,unsigned num_coeffs,unsigned zrl,short int val) -{ - unsigned ind = num_coeffs+zrl; - if (ind >= 64) { - // We have an error! Don't set the block. Skip this comp for now - // After this call, we will likely trap the error. - } else { - unsigned nDctInd = glb_anZigZag[ind]; - short int nValUnquant = val * m_anDqtCoeffZz[nDqtTbl][ind]; - - /* - // NOTE: - // To test steganography analysis, we can experiment with dropping - // specific components of the image. - unsigned nRow = nDctInd/8; - unsigned nCol = nDctInd - (nRow*8); - if ((nRow == 0) && (nCol>=0 && nCol<=7)) { - nValUnquant = 0; - } - */ - - m_anDctBlock[nDctInd] = nValUnquant; - - // Update max DCT coef # (after unzigzag) so that we can save - // some work when performing IDCT. - // FIXME: The following doesn't seem to work when we later - // restrict DecodeIdctCalc() to only m_nDctCoefMax coefs! - -// if ( (nDctInd > m_nDctCoefMax) && (abs(nValUnquant) >= IDCT_COEF_THRESH) ) { - if (nDctInd > m_nDctCoefMax) { - m_nDctCoefMax = nDctInd; - } - } -} - -// Precalculate the IDCT lookup tables -// -// POST: -// - m_afIdctLookup[] -// - m_anIdctLookup[] -// NOTE: -// - This is 4k entries @ 4B each = 16KB -// -void CimgDecode::PrecalcIdct() -{ - unsigned nX,nY,nU,nV; - unsigned nYX,nVU; - float fCu,fCv; - float fCosProd; - float fInsideProd; - - float fPi = (float)3.141592654; - float fSqrtHalf = (float)0.707106781; - - for (nY=0;nYint is very slow! - // Should consider using fixed point instead! - m_afIdctBlock[nYX] = fSum; - } - -} - -// Fixed point version of DecodeIdctCalcFloat() -// -// PRE: -// - m_anIdctLookup[][] -// - m_anDctBlock[] -// POST: -// - m_anIdctBlock[] -// -void CimgDecode::DecodeIdctCalcFixedpt() -{ - unsigned nYX,nVU; - int nSum; - - for (nYX=0;nYXint is very slow! - // Should consider using fixed point instead! - m_anIdctBlock[nYX] = nSum >> 10; - - } - -} - -// Clear the entire pixel image arrays for all three components (YCC) -// -// INPUT: -// - nWidth = Current allocated image width -// - nHeight = Current allocated image height -// POST: -// - m_pPixValY -// - m_pPixValCb -// - m_pPixValCr -// -void CimgDecode::ClrFullRes(unsigned nWidth,unsigned nHeight) -{ - ASSERT(m_pPixValY); - if (m_nNumSosComps == NUM_CHAN_YCC) { - ASSERT(m_pPixValCb); - ASSERT(m_pPixValCr); - } - // FIXME: Add in range checking here - memset(m_pPixValY, 0, (nWidth * nHeight * sizeof(short)) ); - if (m_nNumSosComps == NUM_CHAN_YCC) { - memset(m_pPixValCb, 0, (nWidth * nHeight * sizeof(short)) ); - memset(m_pPixValCr, 0, (nWidth * nHeight * sizeof(short)) ); - } -} - -// Generate a single component's pixel content for one MCU -// - Fetch content from the 8x8 IDCT block (m_afIdctBlock[]) -// for the specified component (nComp) -// - Transfer the pixel content to the specified component's -// pixel map (m_pPixValY[],m_pPixValCb[],m_pPixValCr[]) -// - DC level shifting is performed (nDcOffset) -// - Replication of pixels according to Chroma Subsampling (sampling factors) -// -// INPUT: -// - nMcuX = -// - nMcuY = -// - nComp = Component index (1,2,3) -// - nCssXInd = -// - nCssYInd = -// - nDcOffset = -// PRE: -// - DecodeIdctCalc() already called on Lum AC, and Lum DC already done -// -void CimgDecode::SetFullRes(unsigned nMcuX,unsigned nMcuY,unsigned nComp,unsigned nCssXInd,unsigned nCssYInd,short int nDcOffset) -{ - unsigned nYX; - float fVal; - short int nVal; - unsigned nChan; - - // Convert from Component index (1-based) to Channel index (0-based) - // Component index is direct from SOF/SOS - // Channel index is used for internal display representation - if (nComp <= 0) { -#ifdef DEBUG_LOG - CString strTmp; - CString strDebug; - strTmp.Format(_T("SetFullRes() with nComp <= 0 [%d]"),nComp); - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("ImgDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - return; - } - nChan = nComp - 1; - - unsigned nPixMapW = m_nBlkXMax*BLK_SZ_X; // Width of pixel map - unsigned nOffsetBlkCorner; // Linear offset to top-left corner of block - unsigned nOffsetPixCorner; // Linear offset to top-left corner of pixel (start point for expansion) - - // Calculate the linear pixel offset for the top-left corner of the block in the MCU - nOffsetBlkCorner = ((nMcuY*m_nMcuHeight) + nCssYInd*BLK_SZ_X) * nPixMapW + - ((nMcuX*m_nMcuWidth) + nCssXInd*BLK_SZ_Y); - - // Use the expansion factor to determine how many bits to replicate - // Typically for luminance (Y) this will be 1 & 1 - // The replication factor is available in m_anExpandBitsMcuH[] and m_anExpandBitsMcuV[] - - // Step through all pixels in the block - for (unsigned nY=0;nYAddLineErr(errStr); - errStr.Format(_T(" MCU located at pixel=(%u,%u)"),err_pos_x,err_pos_y); - m_pLog->AddLineErr(errStr); - - //errStr.Format(_T("*** Resetting Error state to continue ***")); - //m_pLog->AddLineErr(errStr); - - m_nWarnBadScanNum++; - if (m_nWarnBadScanNum >= m_nScanErrMax) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),m_nScanErrMax); - m_pLog->AddLineErr(strTmp); - } - } - - // TODO: Should we reset m_nScanCurErr? - m_nScanCurErr = false; - - //errStr.Format(_T("*** Resetting Error state to continue ***")); - //m_pLog->AddLineErr(errStr); - - } // Error? - -} - - - -// Report the cumulative DC value -// -// INPUT: -// - nMcuX = MCU x coordinate -// - nMcuY = MCU y coordinate -// - nVal = DC value -// -void CimgDecode::PrintDcCumVal(unsigned nMcuX,unsigned nMcuY,int nVal) -{ - nMcuX; // Unreferenced param - nMcuY; // Unreferenced param - CString strTmp; -// strTmp.Format(_T(" MCU [%4u,%4u] DC Cumulative Val = [%5d]"),nMcuX,nMcuY,nVal); - strTmp.Format(_T(" Cumulative DC Val=[%5d]"),nVal); - m_pLog->AddLine(strTmp); -} - - -// Reset the DC values in the decoder (e.g. at start and -// after restart markers) -// -// POST: -// - m_nDcLum -// - m_nDcChrCb -// - m_nDcChrCr -// - m_anDcLumCss[] -// - m_anDcChrCbCss[] -// - m_anDcChrCrCss[] -// -void CimgDecode::DecodeRestartDcState() -{ - m_nDcLum = 0; - m_nDcChrCb = 0; - m_nDcChrCr = 0; - for (unsigned nInd=0;nIndbDumpHistoY; - bool bDecodeScanAc; - unsigned nScanErrMax = m_pAppConfig->nErrMaxDecodeScan; - - // Add some extra speed-up in hidden mode (we don't need AC) - if (bDisplay) { - bDecodeScanAc = m_pAppConfig->bDecodeScanImgAc; - } else { - bDecodeScanAc = false; - } - m_bHistEn = m_pAppConfig->bHistoEn; - m_bStatClipEn = m_pAppConfig->bStatClipEn; - - - unsigned nPixMapW = 0; - unsigned nPixMapH = 0; - - // Reset the decoder state variables - Reset(); - - m_nScanErrMax = nScanErrMax; - m_bDecodeScanAc = bDecodeScanAc; - - // Detect the scenario where the image component details haven't been set yet - // The image details are set via SetImageDetails() - if (!m_bImgDetailsSet) { - m_pLog->AddLineErr(_T("*** ERROR: Decoding image before Image components defined ***")); - return; - } - - - - // Even though we support decoding of MAX_SOS_COMP_NS we limit - // the component flexibility further - if ( (m_nNumSosComps != NUM_CHAN_GRAYSCALE) && (m_nNumSosComps != NUM_CHAN_YCC) ) { - strTmp.Format(_T(" NOTE: Number of SOS components not supported [%u]"),m_nNumSosComps); - m_pLog->AddLineWarn(strTmp); -#ifndef DEBUG_YCCK - return; -#endif - } - - // Determine the maximum sampling factor and min sampling factor for this scan - m_nSosSampFactHMax = 0; - m_nSosSampFactVMax = 0; - m_nSosSampFactHMin = 0xFF; - m_nSosSampFactVMin = 0xFF; - - for (unsigned nComp=1;nComp<=m_nNumSosComps;nComp++) { - m_nSosSampFactHMax = max(m_nSosSampFactHMax,m_anSofSampFactH[nComp]); - m_nSosSampFactVMax = max(m_nSosSampFactVMax,m_anSofSampFactV[nComp]); - m_nSosSampFactHMin = min(m_nSosSampFactHMin,m_anSofSampFactH[nComp]); - m_nSosSampFactVMin = min(m_nSosSampFactVMin,m_anSofSampFactV[nComp]); - ASSERT(m_nSosSampFactHMin != 0); - ASSERT(m_nSosSampFactVMin != 0); - } - - - // ITU-T.81 clause A.2.2 "Non-interleaved order (Ns=1)" - // - In some cases an image may have a single component in a scan but with sampling factors other than 1: - // Number of Img components = 1 - // Component[1]: ID=0x01, Samp Fac=0x22 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) - // - This could either be in a 3-component SOF with multiple 1-component SOS or a 1-component SOF (monochrome image) - // - In general, grayscale images exhibit a sampling factor of 0x11 - // - Per ITU-T.81 A.2.2: - // When Ns = 1 (where Ns is the number of components in a scan), the order of data units - // within a scan shall be left-to-right and top-to-bottom, as shown in Figure A.2. This - // ordering applies whenever Ns = 1, regardless of the values of H1 and V1. - // - Thus, instead of the usual decoding sequence for 0x22: - // [ 0 1 ] [ 4 5 ] - // [ 2 3 ] [ 6 7 ] - // - The sequence for decode should be: - // [ 0 ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] ... - // - Which is equivalent to the non-subsampled ordering (ie. 0x11) - // - Apply a correction for such images to remove the sampling factor - if ( m_nNumSosComps == 1) { - // TODO: Need to confirm if component index needs to be looked up - // in the case of multiple SOS or if [1] is the correct index - if ( (m_anSofSampFactH[1] != 1) || (m_anSofSampFactV[1] != 1) ) { - m_pLog->AddLineWarn(_T(" Altering sampling factor for single component scan to 0x11")); - } - m_anSofSampFactH[1] = 1; - m_anSofSampFactV[1] = 1; - m_nSosSampFactHMax = 1; - m_nSosSampFactVMax = 1; - m_nSosSampFactHMin = 1; - m_nSosSampFactVMin = 1; - } - - - // Perform additional range checks - if ( (m_nSosSampFactHMax==0) || (m_nSosSampFactVMax==0) || (m_nSosSampFactHMax>MAX_SAMP_FACT_H) || (m_nSosSampFactVMax>MAX_SAMP_FACT_V)) { - strTmp.Format(_T(" NOTE: Degree of subsampling factor not supported [HMax=%u, VMax=%u]"),m_nSosSampFactHMax,m_nSosSampFactVMax); - m_pLog->AddLineWarn(strTmp); - return; - } - - // Calculate the MCU size for this scan. We do it here rather - // than at the time of SOF (ie. SetImageDetails) for the reason - // that under some circumstances we need to override the sampling - // factor in single-component scans. This is done earlier. - m_nMcuWidth = m_nSosSampFactHMax * BLK_SZ_X; - m_nMcuHeight = m_nSosSampFactVMax * BLK_SZ_Y; - - - // Calculate the number of bits to replicate when we generate the pixel map - for (unsigned nComp=1;nComp<=m_nNumSosComps;nComp++) { - m_anExpandBitsMcuH[nComp] = m_nSosSampFactHMax / m_anSofSampFactH[nComp]; - m_anExpandBitsMcuV[nComp] = m_nSosSampFactVMax / m_anSofSampFactV[nComp]; - } - - // Calculate the number of component samples per MCU - for (unsigned nComp=1;nComp<=m_nNumSosComps;nComp++) { - m_anSampPerMcuH[nComp] = m_anSofSampFactH[nComp]; - m_anSampPerMcuV[nComp] = m_anSofSampFactV[nComp]; - } - - - // Determine the MCU ranges - m_nMcuXMax = (m_nDimX/m_nMcuWidth); - m_nMcuYMax = (m_nDimY/m_nMcuHeight); - - m_nImgSizeXPartMcu = m_nMcuXMax * m_nMcuWidth; - m_nImgSizeYPartMcu = m_nMcuYMax * m_nMcuHeight; - - // Detect incomplete (partial) MCUs and round-up the MCU - // ranges if necessary. - if ((m_nDimX%m_nMcuWidth) != 0) m_nMcuXMax++; - if ((m_nDimY%m_nMcuHeight) != 0) m_nMcuYMax++; - - // Save the maximum 8x8 block dimensions - m_nBlkXMax = m_nMcuXMax * m_nSosSampFactHMax; - m_nBlkYMax = m_nMcuYMax * m_nSosSampFactVMax; - - - // Ensure the image has a size - if ( (m_nBlkXMax == 0) || (m_nBlkYMax == 0) ) { - return; - } - - // Set the decoded size and before scaling - m_nImgSizeX = m_nMcuXMax * m_nMcuWidth; - m_nImgSizeY = m_nMcuYMax * m_nMcuHeight; - - m_rectImgBase = CRect(CPoint(0,0),CSize(m_nImgSizeX,m_nImgSizeY)); - - - // Determine decoding range - unsigned nDecMcuRowStart; - unsigned nDecMcuRowEnd; // End to AC scan decoding - unsigned nDecMcuRowEndFinal; // End to general decoding - nDecMcuRowStart = 0; - nDecMcuRowEnd = m_nMcuYMax; - nDecMcuRowEndFinal = m_nMcuYMax; - - // Limit the decoding range to valid range - nDecMcuRowEnd = min(nDecMcuRowEnd,m_nMcuYMax); - nDecMcuRowEndFinal = min(nDecMcuRowEndFinal,m_nMcuYMax); - - - // Allocate the MCU File Map - ASSERT(m_pMcuFileMap == NULL); - m_pMcuFileMap = new unsigned[m_nMcuYMax*m_nMcuXMax]; - if (!m_pMcuFileMap) { - strTmp = _T("ERROR: Not enough memory for Image Decoder MCU File Pos Map"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return; - } - memset(m_pMcuFileMap, 0, (m_nMcuYMax*m_nMcuXMax*sizeof(unsigned)) ); - - - // Allocate the 8x8 Block DC Map - m_pBlkDcValY = new short[m_nBlkYMax*m_nBlkXMax]; - if ( (!m_pBlkDcValY) ) { - strTmp = _T("ERROR: Not enough memory for Image Decoder Blk DC Value Map"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return; - } - if (m_nNumSosComps == NUM_CHAN_YCC) { - m_pBlkDcValCb = new short[m_nBlkYMax*m_nBlkXMax]; - m_pBlkDcValCr = new short[m_nBlkYMax*m_nBlkXMax]; - if ( (!m_pBlkDcValCb) || (!m_pBlkDcValCr) ) { - strTmp = _T("ERROR: Not enough memory for Image Decoder Blk DC Value Map"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return; - } - } - - memset(m_pBlkDcValY, 0, (m_nBlkYMax*m_nBlkXMax*sizeof(short)) ); - if (m_nNumSosComps == NUM_CHAN_YCC) { - memset(m_pBlkDcValCb, 0, (m_nBlkYMax*m_nBlkXMax*sizeof(short)) ); - memset(m_pBlkDcValCr, 0, (m_nBlkYMax*m_nBlkXMax*sizeof(short)) ); - } - - // Allocate the real YCC pixel Map - nPixMapH = m_nBlkYMax*BLK_SZ_Y; - nPixMapW = m_nBlkXMax*BLK_SZ_X; - - // Ensure no image allocated yet - ASSERT(m_pPixValY==NULL); - if (m_nNumSosComps == NUM_CHAN_YCC) { - ASSERT(m_pPixValCb==NULL); - ASSERT(m_pPixValCr==NULL); - } - - - // Allocate image (YCC) - m_pPixValY = new short[nPixMapW * nPixMapH]; - if ( (!m_pPixValY) ) { - strTmp = _T("ERROR: Not enough memory for Image Decoder Pixel YCC Value Map"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return; - } - if (m_nNumSosComps == NUM_CHAN_YCC) { - m_pPixValCb = new short[nPixMapW * nPixMapH]; - m_pPixValCr = new short[nPixMapW * nPixMapH]; - if ( (!m_pPixValCb) || (!m_pPixValCr) ) { - strTmp = _T("ERROR: Not enough memory for Image Decoder Pixel YCC Value Map"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return; - } - } - - // Reset pixel map - if (bDisplay) { - ClrFullRes(nPixMapW,nPixMapH); - } - - - // ------------------------------------- - // Allocate the device-independent bitmap (DIB) - - unsigned char * pDibImgTmpBits = NULL; - unsigned nDibImgRowBytes; - - // If a previous bitmap was created, deallocate it and start fresh - m_pDibTemp.Kill(); - m_bDibTempReady = false; - m_bPreviewIsJpeg = false; - - // Create the DIB - // Although we are creating a 32-bit DIB, it should also - // work to run in 16- and 8-bit modes - - bool bDoImage = false; // Are we safe to set bits? - - if (bDisplay) { - m_pDibTemp.CreateDIB(m_nImgSizeX,m_nImgSizeY,32); - nDibImgRowBytes = m_nImgSizeX * sizeof(RGBQUAD); - pDibImgTmpBits = (unsigned char*) ( m_pDibTemp.GetDIBBitArray() ); - - if (pDibImgTmpBits) { - bDoImage = true; - } else { - // TODO: Should we be exiting here instead? - } - - } - // ------------------------------------- - - - CString picStr; - - // Reset the DC cumulative state - DecodeRestartDcState(); - - // Reset the scan buffer - DecodeRestartScanBuf(nStart,false); - - // Load the buffer - m_pWBuf->BufLoadWindow(nStart); - - // Expect that we start with RST0 - m_nRestartExpectInd = 0; - m_nRestartLastInd = 0; - - // Load the first data into the scan buffer - // This is done so that the MCU map will already - // have access to the data. - BuffTopup(); - - if (!bQuiet) { - m_pLog->AddLineHdr(_T("*** Decoding SCAN Data ***")); - strTmp.Format(_T(" OFFSET: 0x%08X"),nStart); - m_pLog->AddLine(strTmp); - } - - - // TODO: Might be more appropriate to check against m_nNumSosComps instead? - if ( (m_nNumSofComps != NUM_CHAN_GRAYSCALE) && (m_nNumSofComps != NUM_CHAN_YCC) ) { - strTmp.Format(_T(" NOTE: Number of Image Components not supported [%u]"),m_nNumSofComps); - m_pLog->AddLineWarn(strTmp); -#ifndef DEBUG_YCCK - return; -#endif - } - - // Check DQT tables - // We need to ensure that the DQT Table selection has already - // been done (via a call from JfifDec to SetDqtTables() ). - unsigned nDqtTblY =0; - unsigned nDqtTblCr =0; - unsigned nDqtTblCb =0; -#ifdef DEBUG_YCCK - unsigned nDqtTblK =0; -#endif - bool bDqtReady = true; - for (unsigned ind=1;ind<=m_nNumSosComps;ind++) { - if (m_anDqtTblSel[ind]<0) bDqtReady = false; - } - if (!bDqtReady) - { - m_pLog->AddLineErr(_T("*** ERROR: Decoding image before DQT Table Selection via JFIF_SOF ***")); - // TODO: Is more error handling required? - return; - } else { - // FIXME: Not sure that we can always depend on the indices to appear - // in this order. May need another layer of indirection to get at the - // frame image component index. - nDqtTblY = m_anDqtTblSel[DQT_DEST_Y]; - nDqtTblCb = m_anDqtTblSel[DQT_DEST_CB]; - nDqtTblCr = m_anDqtTblSel[DQT_DEST_CR]; -#ifdef DEBUG_YCCK - if (m_nNumSosComps==4) { - nDqtTblK = m_anDqtTblSel[DQT_DEST_K]; - } -#endif - } - - // Now check DHT tables - bool bDhtReady = true; - unsigned nDhtTblDcY,nDhtTblDcCb,nDhtTblDcCr; - unsigned nDhtTblAcY,nDhtTblAcCb,nDhtTblAcCr; -#ifdef DEBUG_YCCK - unsigned nDhtTblDcK,nDhtTblAcK; -#endif - for (unsigned nClass=DHT_CLASS_DC;nClass<=DHT_CLASS_AC;nClass++) { - for (unsigned nCompInd=1;nCompInd<=m_nNumSosComps;nCompInd++) { - if (m_anDhtTblSel[nClass][nCompInd]<0) bDhtReady = false; - } - } - - // Ensure that the table has been defined already! - unsigned nSel; - for (unsigned nCompInd=1;nCompInd<=m_nNumSosComps;nCompInd++) { - // Check for DC DHT table - nSel = m_anDhtTblSel[DHT_CLASS_DC][nCompInd]; - if (m_anDhtLookupSize[DHT_CLASS_DC][nSel] == 0) { - bDhtReady = false; - } - // Check for AC DHT table - nSel = m_anDhtTblSel[DHT_CLASS_AC][nCompInd]; - if (m_anDhtLookupSize[DHT_CLASS_AC][nSel] == 0) { - bDhtReady = false; - } - } - - - if (!bDhtReady) - { - m_pLog->AddLineErr(_T("*** ERROR: Decoding image before DHT Table Selection via JFIF_SOS ***")); - // TODO: Is more error handling required here? - return; - } else { - // Define the huffman table indices that are selected for each - // image component index and class (AC,DC). - // - // No need to check if a table is valid here since we have - // previously checked to ensure that all required tables - // exist. - // NOTE: If the table has not been defined, then the index - // will be 0xFFFFFFFF. ReadScanVal() will trap this with ASSERT - // should it ever be used. - nDhtTblDcY = m_anDhtTblSel[DHT_CLASS_DC][COMP_IND_YCC_Y]; - nDhtTblAcY = m_anDhtTblSel[DHT_CLASS_AC][COMP_IND_YCC_Y]; - nDhtTblDcCb = m_anDhtTblSel[DHT_CLASS_DC][COMP_IND_YCC_CB]; - nDhtTblAcCb = m_anDhtTblSel[DHT_CLASS_AC][COMP_IND_YCC_CB]; - nDhtTblDcCr = m_anDhtTblSel[DHT_CLASS_DC][COMP_IND_YCC_CR]; - nDhtTblAcCr = m_anDhtTblSel[DHT_CLASS_AC][COMP_IND_YCC_CR]; -#ifdef DEBUG_YCCK - nDhtTblDcK = m_anDhtTblSel[DHT_CLASS_DC][COMP_IND_YCC_K]; - nDhtTblAcK = m_anDhtTblSel[DHT_CLASS_AC][COMP_IND_YCC_K]; -#endif - } - - // Done checks - - - // Inform if they are in AC+DC/DC mode - if (!bQuiet) { - if (m_bDecodeScanAc) { - m_pLog->AddLine(_T(" Scan Decode Mode: Full IDCT (AC + DC)")); - } else { - m_pLog->AddLine(_T(" Scan Decode Mode: No IDCT (DC only)")); - m_pLog->AddLineWarn(_T(" NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT]")); - } - m_pLog->AddLine(_T("")); - } - - // Report any Buffer overlays - m_pWBuf->ReportOverlays(m_pLog); - - m_nNumPixels = 0; - - // Clear the histogram and color correction clipping stats - if (bDisplay) { - memset(&m_sStatClip,0,sizeof(m_sStatClip)); - memset(&m_sHisto,0,sizeof(m_sHisto)); - - // FIXME: Histo should now be done after color convert - memset(&m_anCcHisto_r,0,sizeof(m_anCcHisto_r)); - memset(&m_anCcHisto_g,0,sizeof(m_anCcHisto_g)); - memset(&m_anCcHisto_b,0,sizeof(m_anCcHisto_b)); - - memset(&m_anHistoYFull,0,sizeof(m_anHistoYFull)); - memset(&m_anHistoYSubset,0,sizeof(m_anHistoYSubset)); - } - - - - // ----------------------------------------------------------------------- - // Process all scan MCUs - // ----------------------------------------------------------------------- - - for (unsigned nMcuY=nDecMcuRowStart;nMcuYAddLine(strTmp); - } - */ - if (m_bRestartRead) { - /* - // FIXME: Check for restart counter value match - if (m_bVerbose) { - strTmp.Format(_T(" Restart marker matched")); - m_pLog->AddLine(strTmp); - } - */ - } else { - strTmp.Format(_T(" Expect Restart interval elapsed @ %s"),(LPCTSTR)GetScanBufPos()); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" ERROR: Restart marker not detected")); - m_pLog->AddLineErr(strTmp); - } - /* - if (ExpectRestart()) { - if (m_bVerbose) { - strTmp.Format(_T(" Restart marker detected")); - m_pLog->AddLine(strTmp); - } - } else { - strTmp.Format(_T(" ERROR: Restart marker expected but not found @ %s"),GetScanBufPos()); - m_pLog->AddLineErr(strTmp); - } - */ - - - } - - // To support a fast decode mode, allow for a subset of the - // image to have DC+AC decoding, while the remainder is only DC decoding - if ((nMcuYnDecMcuRowEnd)) { - m_bDecodeScanAc = false; - } else { - m_bDecodeScanAc = bDecodeScanAc; - } - - - // Precalculate MCU matrix index - unsigned nMcuXY = nMcuY*m_nMcuXMax+nMcuX; - - // Mark the start of the MCU in the file map - m_pMcuFileMap[nMcuXY] = PackFileOffset(m_anScanBuffPtr_pos[0],m_nScanBuffPtr_align); - - // Is this an MCU that we want full printing of decode process? - bool bVlcDump = false; - unsigned nRangeBase; - unsigned nRangeCur; - if (m_bDetailVlc) { - nRangeBase = (m_nDetailVlcY * m_nMcuXMax) + m_nDetailVlcX; - nRangeCur = nMcuXY; - if ( (nRangeCur >= nRangeBase) && (nRangeCur < nRangeBase+m_nDetailVlcLen) ) { - bVlcDump = true; - } - } - - // Luminance - // If there is chroma subsampling, then this block will have - // (css_x * css_y) luminance blocks to process - // We store them all in an array m_anDcLumCss[] - - // Give separator line between MCUs - if (bVlcDump) { - m_pLog->AddLine(_T("")); - } - - // CSS array indices - unsigned nCssIndH; - unsigned nCssIndV; - unsigned nComp; - - // No need to reset the IDCT output matrix for this MCU - // since we are going to be generating it here. This help - // maintain performance. - - // -------------------------------------------------------------- - nComp = SCAN_COMP_Y; - - // Step through the sampling factors per image component - // TODO: Could rewrite this to use single loop across each image component - for (nCssIndV=0;nCssIndV= m_nBlkXMax*m_nBlkYMax) { -#ifdef DEBUG_LOG - CString strDebug; - strTmp.Format(_T("DecodeScanImg() with nBlkXY out of range. nBlkXY=[%u] m_nBlkXMax=[%u] m_nBlkYMax=[%u]"),nBlkXY,m_nBlkXMax,m_nBlkYMax); - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("ImgDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - } else { - m_pBlkDcValY [nBlkXY] = m_anDcLumCss[nCssIndV*MAX_SAMP_FACT_H+nCssIndH]; - } - } - } - // Only process the chrominance if it is YCC - if (m_nNumSosComps == NUM_CHAN_YCC) { - - // -------------------------------------------------------------- - nComp = SCAN_COMP_CB; - - for (nCssIndV=0;nCssIndV= m_nBlkXMax*m_nBlkYMax) { -#ifdef DEBUG_LOG - CString strDebug; - strTmp.Format(_T("DecodeScanImg() with nBlkXY out of range. nBlkXY=[%u] m_nBlkXMax=[%u] m_nBlkYMax=[%u]"),nBlkXY,m_nBlkXMax,m_nBlkYMax); - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("ImgDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - } else { - m_pBlkDcValCb [nBlkXY] = m_anDcChrCbCss[nCssIndV*MAX_SAMP_FACT_H+nCssIndH]; - } - } - } - - // -------------------------------------------------------------- - nComp = SCAN_COMP_CR; - - for (nCssIndV=0;nCssIndV= m_nBlkXMax*m_nBlkYMax) { -#ifdef DEBUG_LOG - CString strDebug; - strTmp.Format(_T("DecodeScanImg() with nBlkXY out of range. nBlkXY=[%u] m_nBlkXMax=[%u] m_nBlkYMax=[%u]"),nBlkXY,m_nBlkXMax,m_nBlkYMax); - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("ImgDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - } else { - m_pBlkDcValCr [nBlkXY] = m_anDcChrCrCss[nCssIndV*MAX_SAMP_FACT_H+nCssIndH]; - } - } - } - } - - - - - // Now that we finished an MCU, decrement the restart interval counter - if (m_bRestartEn) { - m_nRestartMcusLeft--; - } - - // Check to see if we need to abort for some reason. - // Note that only check m_bScanEnd if we have a failure. - // m_bScanEnd is asserted during normal out-of-data when scan - // segment ends with marker. We don't want to abort early - // or else we'll not decode the last MCU or two! - if (m_bScanEnd && m_bScanBad) { - bScanStop = true; - } - - } // nMcuX - - - } // nMcuY - if (!bQuiet) { - m_pLog->AddLine(_T("")); - } - - // --------------------------------------------------------- - - // Now we can create the final preview. Since we have just finished - // decoding a new image, we need to ensure that we invalidate - // the temporary preview (multi-channel option). Done earlier - // with PREVIEW_NONE - if (bDisplay) { - CalcChannelPreview(); - } - - // DIB is ready for display now - if (bDisplay) { - m_bDibTempReady = true; - m_bPreviewIsJpeg = true; - } - - - // ------------------------------------ - // Report statistics - - if (!bQuiet) { - - // Report Compression stats - // TODO: Should we use m_nNumSofComps? - strTmp.Format(_T(" Compression stats:")); - m_pLog->AddLine(strTmp); - float nCompressionRatio = (float)(m_nDimX*m_nDimY*m_nNumSosComps*8) / (float)((m_anScanBuffPtr_pos[0]-m_nScanBuffPtr_first)*8); - strTmp.Format(_T(" Compression Ratio: %5.2f:1"),nCompressionRatio); - m_pLog->AddLine(strTmp); - float nBitsPerPixel = (float)((m_anScanBuffPtr_pos[0]-m_nScanBuffPtr_first)*8) / (float)(m_nDimX*m_nDimY); - strTmp.Format(_T(" Bits per pixel: %5.2f:1"),nBitsPerPixel); - m_pLog->AddLine(strTmp); - m_pLog->AddLine(_T("")); - - - // Report Huffman stats - strTmp.Format(_T(" Huffman code histogram stats:")); - m_pLog->AddLine(strTmp); - - unsigned nDhtHistoTotal; - for (unsigned nClass=DHT_CLASS_DC;nClass<=DHT_CLASS_AC;nClass++) { - for (unsigned nDhtDestId=0;nDhtDestId<=m_anDhtLookupSetMax[nClass];nDhtDestId++) { - nDhtHistoTotal = 0; - for (unsigned nBitLen=1;nBitLen<=MAX_DHT_CODELEN;nBitLen++) { - nDhtHistoTotal += m_anDhtHisto[nClass][nDhtDestId][nBitLen]; - } - - strTmp.Format(_T(" Huffman Table: (Dest ID: %u, Class: %s)"),nDhtDestId,(nClass?_T("AC"):_T("DC"))); - m_pLog->AddLine(strTmp); - for (unsigned nBitLen=1;nBitLen<=MAX_DHT_CODELEN;nBitLen++) { - strTmp.Format(_T(" # codes of length %02u bits: %8u (%3.0f%%)"), - nBitLen,m_anDhtHisto[nClass][nDhtDestId][nBitLen],(m_anDhtHisto[nClass][nDhtDestId][nBitLen]*100.0)/nDhtHistoTotal); - m_pLog->AddLine(strTmp); - } - m_pLog->AddLine(_T("")); - } - } - - // Report YCC stats - ReportColorStats(); - - } // !bQuiet - - // ------------------------------------ - - // Display the image histogram if enabled - if (bDisplay && m_bHistEn) { - DrawHistogram(bQuiet,bDumpHistoY); - } - - if (bDisplay && m_bAvgYValid) { - m_pLog->AddLine(_T(" Average Pixel Luminance (Y):")); - strTmp.Format(_T(" Y=[%3u] (range: 0..255)"), - m_nAvgY); - m_pLog->AddLine(strTmp); - m_pLog->AddLine(_T("")); - } - - if (bDisplay && m_bBrightValid) { - m_pLog->AddLine(_T(" Brightest Pixel Search:")); - strTmp.Format(_T(" YCC=[%5d,%5d,%5d] RGB=[%3u,%3u,%3u] @ MCU[%3u,%3u]"), - m_nBrightY,m_nBrightCb,m_nBrightCr,m_nBrightR,m_nBrightG,m_nBrightB, - m_ptBrightMcu.x,m_ptBrightMcu.y); - m_pLog->AddLine(strTmp); - m_pLog->AddLine(_T("")); - } - - - // -------------------------------------- - - if (!bQuiet) { - m_pLog->AddLine(_T(" Finished Decoding SCAN Data")); - strTmp.Format(_T(" Number of RESTART markers decoded: %u"),m_nRestartRead); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Next position in scan buffer: Offset %s"),(LPCTSTR)GetScanBufPos()); - m_pLog->AddLine(strTmp); - - m_pLog->AddLine(_T("")); - } - - // -------------------------------------- - // Write out the full Y histogram if requested! - - CString strFull; - - if (bDisplay && m_bHistEn && bDumpHistoY) { - ReportHistogramY(); - } - - -} - -// -// Report if image preview is ready to display -// -// RETURN: -// - True if image preview is ready -// -bool CimgDecode::IsPreviewReady() -{ - return m_bPreviewIsJpeg; -} - -// Report out the color conversion statistics -// -// PRE: -// - m_sStatClip -// - m_sHisto -// -void CimgDecode::ReportColorStats() -{ - CString strTmp; - - // Report YCC stats - if (CC_CLIP_YCC_EN) { - strTmp.Format(_T(" YCC clipping in DC:")); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Y component: [<0=%5u] [>255=%5u]"),m_sStatClip.nClipYUnder,m_sStatClip.nClipYOver); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Cb component: [<0=%5u] [>255=%5u]"),m_sStatClip.nClipCbUnder,m_sStatClip.nClipCbOver); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Cr component: [<0=%5u] [>255=%5u]"),m_sStatClip.nClipCrUnder,m_sStatClip.nClipCrOver); - m_pLog->AddLine(strTmp); - m_pLog->AddLine(_T("")); - } - - if (m_bHistEn) { - - strTmp.Format(_T(" YCC histogram in DC (DCT sums : pre-ranged:")); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Y component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nPreclipYMin,m_sHisto.nPreclipYMax,(float)m_sHisto.nPreclipYSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Cb component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nPreclipCbMin,m_sHisto.nPreclipCbMax,(float)m_sHisto.nPreclipCbSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Cr component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nPreclipCrMin,m_sHisto.nPreclipCrMax,(float)m_sHisto.nPreclipCrSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - m_pLog->AddLine(_T("")); - - strTmp.Format(_T(" YCC histogram in DC:")); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Y component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nClipYMin,m_sHisto.nClipYMax,(float)m_sHisto.nClipYSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Cb component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nClipCbMin,m_sHisto.nClipCbMax,(float)m_sHisto.nClipCbSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Cr component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nClipCrMin,m_sHisto.nClipCrMax,(float)m_sHisto.nClipCrSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - m_pLog->AddLine(_T("")); - - - strTmp.Format(_T(" RGB histogram in DC (before clip):")); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" R component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nPreclipRMin,m_sHisto.nPreclipRMax,(float)m_sHisto.nPreclipRSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" G component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nPreclipGMin,m_sHisto.nPreclipGMax,(float)m_sHisto.nPreclipGSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" B component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nPreclipBMin,m_sHisto.nPreclipBMax,(float)m_sHisto.nPreclipBSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - m_pLog->AddLine(_T("")); - } - - strTmp.Format(_T(" RGB clipping in DC:")); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" R component: [<0=%5u] [>255=%5u]"),m_sStatClip.nClipRUnder,m_sStatClip.nClipROver); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" G component: [<0=%5u] [>255=%5u]"),m_sStatClip.nClipGUnder,m_sStatClip.nClipGOver); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" B component: [<0=%5u] [>255=%5u]"),m_sStatClip.nClipBUnder,m_sStatClip.nClipBOver); - m_pLog->AddLine(strTmp); - /* - strTmp.Format(_T(" White Highlight: [>255=%5u]"),m_sStatClip.nClipWhiteOver); - m_pLog->AddLine(strTmp); - */ - m_pLog->AddLine(_T("")); -} - - -// Report the histogram stats from the Y component -// -// PRE: -// - m_anHistoYFull -// -void CimgDecode::ReportHistogramY() -{ - CString strFull; - CString strTmp; - - m_pLog->AddLine(_T(" Y Histogram in DC: (DCT sums) Full")); - for (unsigned row=0;row<2048/8;row++) { - strFull.Format(_T(" Y=%5d..%5d: "),-1024+(row*8),-1024+(row*8)+7); - for (unsigned col=0;col<8;col++) { - strTmp.Format(_T("0x%06x, "),m_anHistoYFull[col+row*8]); - strFull += strTmp; - } - m_pLog->AddLine(strFull); - } -} - - -// Draw the histograms (RGB and/or Y) -// -// INPUT: -// - bQuiet = Calculate stats without reporting to log? -// - bDumpHistoY = Generate the Y histogram? -// PRE: -// - m_sHisto -// -void CimgDecode::DrawHistogram(bool bQuiet,bool bDumpHistoY) -{ - CString strTmp; - - if (!bQuiet) { - strTmp.Format(_T(" RGB histogram in DC (after clip):")); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" R component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nClipRMin,m_sHisto.nClipRMax,(float)m_sHisto.nClipRSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" G component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nClipGMin,m_sHisto.nClipGMax,(float)m_sHisto.nClipGSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" B component histo: [min=%5d max=%5d avg=%7.1f]"), - m_sHisto.nClipBMin,m_sHisto.nClipBMax,(float)m_sHisto.nClipBSum / (float)m_sHisto.nCount); - m_pLog->AddLine(strTmp); - m_pLog->AddLine(_T("")); - } - - // -------------------------------------- - // Now draw the RGB histogram! - - unsigned nCoordY; - unsigned nHistoBinHeight; - unsigned nHistoPeakVal; - unsigned nHistoX; - unsigned nHistoCurVal; - unsigned nDibHistoRowBytes; - unsigned char* pDibHistoBits; - - m_pDibHistRgb.Kill(); - m_bDibHistRgbReady = false; - - m_pDibHistRgb.CreateDIB(HISTO_BINS*HISTO_BIN_WIDTH,3*HISTO_BIN_HEIGHT_MAX,32); - nDibHistoRowBytes = (HISTO_BINS*HISTO_BIN_WIDTH) * 4; - pDibHistoBits = (unsigned char*) ( m_pDibHistRgb.GetDIBBitArray() ); - - m_rectHistBase = CRect(CPoint(0,0),CSize(HISTO_BINS*HISTO_BIN_WIDTH,3*HISTO_BIN_HEIGHT_MAX)); - - if (pDibHistoBits != NULL) { - memset(pDibHistoBits,0,3*HISTO_BIN_HEIGHT_MAX*nDibHistoRowBytes); - - // Do peak detect first - // Don't want to reset peak value to 0 as otherwise we might get - // division by zero later when we calculate nHistoBinHeight - nHistoPeakVal = 1; - - // Peak value is across all three channels! - for (unsigned nHistChan=0;nHistChan<3;nHistChan++) { - - for (unsigned i=0;i nHistoPeakVal)?nHistoCurVal:nHistoPeakVal; - } - } - - for (unsigned nHistChan=0;nHistChan<3;nHistChan++) { - for (unsigned i=0;i nHistoPeakVal)?nHistoCurVal:nHistoPeakVal; - } - - for (unsigned i=0;i -128..127 - sPix.nPreclipY = sPix.nPrerangeY >> 3; - sPix.nPreclipCb = sPix.nPrerangeCb >> 3; - sPix.nPreclipCr = sPix.nPrerangeCr >> 3; - - // Limit on YCC input - // The y/cb/nPreclipCr values should already be 0..255 unless we have a - // decode error where DC value gets out of range! - //CapYccRange(nMcuX,nMcuY,sPix); - nValY = (sPix.nPreclipY<-128)?-128:(sPix.nPreclipY>127)?127:sPix.nPreclipY; - nValCb = (sPix.nPreclipCb<-128)?-128:(sPix.nPreclipCb>127)?127:sPix.nPreclipCb; - nValCr = (sPix.nPreclipCr<-128)?-128:(sPix.nPreclipCr>127)?127:sPix.nPreclipCr; - - // Save the YCC values (0..255) - sPix.nFinalY = static_cast(nValY + 128); - sPix.nFinalCb = static_cast(nValCb + 128); - sPix.nFinalCr = static_cast(nValCr + 128); - - // Convert - // Since the following seems to preserve the multiplies and subtractions - // we could expand this out manually - float fConstRed = 0.299f; - float fConstGreen = 0.587f; - float fConstBlue = 0.114f; - // r = cr * 1.402 + y; - // b = cb * 1.772 + y; - // g = (y - 0.03409 * r) / 0.587; - nValR = nValCr*(2-2*fConstRed)+nValY; - nValB = nValCb*(2-2*fConstBlue)+nValY; - nValG = (nValY-fConstBlue*nValB-fConstRed*nValR)/fConstGreen; - - // Level shift - nValR += 128; - nValB += 128; - nValG += 128; - - // --------------- Finshed the color conversion - - - // Limit - // r/g/nPreclipB -> r/g/b - //CapRgbRange(nMcuX,nMcuY,sPix); - sPix.nFinalR = (nValR<0)?0:(nValR>255)?255:(BYTE)nValR; - sPix.nFinalG = (nValG<0)?0:(nValG>255)?255:(BYTE)nValG; - sPix.nFinalB = (nValB<0)?0:(nValB>255)?255:(BYTE)nValB; - -} - -// Color conversion from YCC to RGB -// -// INPUT: -// - sPix = Structure for color conversion -// OUTPUT: -// - sPix = Structure for color conversion -// -void CimgDecode::ConvertYCCtoRGBFastFixed(PixelCc &sPix) -{ - int nPreclipY,nPreclipCb,nPreclipCr; - int nValY,nValCb,nValCr; - int nValR,nValG,nValB; - - // Perform ranging to adjust from Huffman sums to reasonable range - // -1024..+1024 -> -128..+127 - nPreclipY = sPix.nPrerangeY >> 3; - nPreclipCb = sPix.nPrerangeCb >> 3; - nPreclipCr = sPix.nPrerangeCr >> 3; - - - // Limit on YCC input - // The nPreclip* values should already be 0..255 unless we have a - // decode error where DC value gets out of range! - - //CapYccRange(nMcuX,nMcuY,sPix); - nValY = (nPreclipY<-128)?-128:(nPreclipY>127)?127:nPreclipY; - nValCb = (nPreclipCb<-128)?-128:(nPreclipCb>127)?127:nPreclipCb; - nValCr = (nPreclipCr<-128)?-128:(nPreclipCr>127)?127:nPreclipCr; - - // Save the YCC values (0..255) - sPix.nFinalY = static_cast(nValY + 128); - sPix.nFinalCb = static_cast(nValCb + 128); - sPix.nFinalCr = static_cast(nValCr + 128); - - // -------------- - - // Convert - // Fixed values is x 1024 (10 bits). Leaves 22 bits for integer - //r2 = 1024*cr1*(2-2*fConstRed)+1024*y1; - //b2 = 1024*cb1*(2-2*fConstBlue)+1024*y1; - //g2 = 1024*(y1-fConstBlue*b2/1024-fConstRed*r2/1024)/fConstGreen; - const long int CFIX_R = 306; - const long int CFIX_G = 601; - const long int CFIX_B = 116; - const long int CFIX2_R = 1436; // 2*(1024-cfix_red) - const long int CFIX2_B = 1816; // 2*(1024-cfix_blue) - const long int CFIX2_G = 1048576; // 1024*1024 - - nValR = CFIX2_R*nValCr + 1024*nValY; - nValB = CFIX2_B*nValCb + 1024*nValY; - nValG = (CFIX2_G*nValY - CFIX_B*nValB - CFIX_R*nValR) / CFIX_G; - - nValR >>= 10; - nValG >>= 10; - nValB >>= 10; - - // Level shift - nValR += 128; - nValB += 128; - nValG += 128; - - - // Limit - // r/g/nPreclipB -> r/g/b - sPix.nFinalR = (nValR<0)?0:(nValR>255)?255:static_cast(nValR); - sPix.nFinalG = (nValG<0)?0:(nValG>255)?255:static_cast(nValG); - sPix.nFinalB = (nValB<0)?0:(nValB>255)?255:static_cast(nValB); - -} - - - -// Color conversion from YCC to RGB -// - CC: y/cb/cr -> r/g/b -// -// INPUT: -// - nMcuX = MCU x coordinate -// - nMcuY = MCU y coordinate -// - sPix = Structure for color conversion -// OUTPUT: -// - sPix = Structure for color conversion -// POST: -// - m_sHisto -// - m_anHistoYFull[] -// - m_anCcHisto_r[] -// - m_anCcHisto_g[] -// - m_anCcHisto_b[] -// -void CimgDecode::ConvertYCCtoRGB(unsigned nMcuX,unsigned nMcuY,PixelCc &sPix) -{ - float fConstRed = (float)0.299; - float fConstGreen = (float)0.587; - float fConstBlue = (float)0.114; - int nByteY,nByteCb,nByteCr; - int nValY,nValCb,nValCr; - float nValR,nValG,nValB; - - if (m_bHistEn) { - // Calc stats on preranged YCC (direct from huffman DC sums) - m_sHisto.nPreclipYMin = (sPix.nPrerangeYm_sHisto.nPreclipYMax)?sPix.nPrerangeY:m_sHisto.nPreclipYMax; - m_sHisto.nPreclipYSum += sPix.nPrerangeY; - m_sHisto.nPreclipCbMin = (sPix.nPrerangeCbm_sHisto.nPreclipCbMax)?sPix.nPrerangeCb:m_sHisto.nPreclipCbMax; - m_sHisto.nPreclipCbSum += sPix.nPrerangeCb; - m_sHisto.nPreclipCrMin = (sPix.nPrerangeCrm_sHisto.nPreclipCrMax)?sPix.nPrerangeCr:m_sHisto.nPreclipCrMax; - m_sHisto.nPreclipCrSum += sPix.nPrerangeCr; - } - - if (m_bHistEn) { - // Now generate the Y histogram, if requested - // Add the Y value to the full histogram (for image similarity calcs) - //if (bDumpHistoY) { - int histo_index = sPix.nPrerangeY; - if (histo_index < -1024) histo_index = -1024; - if (histo_index > 1023) histo_index = 1023; - histo_index += 1024; - m_anHistoYFull[histo_index]++; - //} - } - - // Perform ranging to adjust from Huffman sums to reasonable range - // -1024..+1024 -> 0..255 - // Add 1024 then / 8 - sPix.nPreclipY = (sPix.nPrerangeY+1024)/8; - sPix.nPreclipCb = (sPix.nPrerangeCb+1024)/8; - sPix.nPreclipCr = (sPix.nPrerangeCr+1024)/8; - - - // Limit on YCC input - // The y/cb/nPreclipCr values should already be 0..255 unless we have a - // decode error where DC value gets out of range! - CapYccRange(nMcuX,nMcuY,sPix); - - // --------------- Perform the color conversion - nByteY = sPix.nFinalY; - nByteCb = sPix.nFinalCb; - nByteCr = sPix.nFinalCr; - - // Level shift - nValY = nByteY - 128; - nValCb = nByteCb - 128; - nValCr = nByteCr - 128; - - // Convert - nValR = nValCr*(2-2*fConstRed)+nValY; - nValB = nValCb*(2-2*fConstBlue)+nValY; - nValG = (nValY-fConstBlue*nValB-fConstRed*nValR)/fConstGreen; - - // Level shift - nValR += 128; - nValB += 128; - nValG += 128; - - sPix.nPreclipR = nValR; - sPix.nPreclipG = nValG; - sPix.nPreclipB = nValB; - // --------------- Finshed the color conversion - - - // Limit - // - Preclip RGB to Final RGB - CapRgbRange(nMcuX,nMcuY,sPix); - - // Display - /* - strTmp.Format(_T("* (YCC->RGB) @ (%03u,%03u): YCC=(%4d,%4d,%4d) RGB=(%03u,%03u,%u)"), - nMcuX,nMcuY,y,cb,cr,r_limb,g_limb,b_limb); - m_pLog->AddLine(strTmp); - */ - - if (m_bHistEn) { - // Bin the result into a histogram! - // value = 0..255 - // bin = 0..7, 8..15, ..., 248..255 - // Channel: Red - unsigned bin_divider = 256/HISTO_BINS; - m_anCcHisto_r[sPix.nFinalR/bin_divider]++; - m_anCcHisto_g[sPix.nFinalG/bin_divider]++; - m_anCcHisto_b[sPix.nFinalB/bin_divider]++; - - - } - -} - -// Color conversion clipping -// - Process the pre-clipped YCC values and ensure they -// have been clipped into the valid region -// -// INPUT: -// - nMcuX = MCU x coordinate -// - nMcuY = MCU y coordinate -// - sPix = Structure for color conversion -// OUTPUT: -// - sPix = Structure for color conversion -// POST: -// - m_sHisto -// -void CimgDecode::CapYccRange(unsigned nMcuX,unsigned nMcuY,PixelCc &sPix) -{ - // Check the bounds on the YCC value - // It should probably be 0..255 unless our DC - // values got really messed up in a corrupt file - // Perhaps it might be best to reset it to 0? Otherwise - // it will continuously report an out-of-range value. - int nCurY,nCurCb,nCurCr; - - nCurY = sPix.nPreclipY; - nCurCb = sPix.nPreclipCb; - nCurCr = sPix.nPreclipCr; - - if (m_bHistEn) { - m_sHisto.nClipYMin = (nCurYm_sHisto.nClipYMax)?nCurY:m_sHisto.nClipYMax; - m_sHisto.nClipYSum += nCurY; - m_sHisto.nClipCbMin = (nCurCbm_sHisto.nClipCbMax)?nCurCb:m_sHisto.nClipCbMax; - m_sHisto.nClipCbSum += nCurCb; - m_sHisto.nClipCrMin = (nCurCrm_sHisto.nClipCrMax)?nCurCr:m_sHisto.nClipCrMax; - m_sHisto.nClipCrSum += nCurCr; - m_sHisto.nCount++; - } - - - if (CC_CLIP_YCC_EN) - { - - if (nCurY > CC_CLIP_YCC_MAX) { - if (YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) { - CString strTmp; - strTmp.Format(_T("*** NOTE: YCC Clipped. MCU=(%4u,%4u) YCC=(%5d,%5d,%5d) Y Overflow @ Offset %s"), - nMcuX,nMcuY,nCurY,nCurCb,nCurCr,(LPCTSTR)GetScanBufPos()); - m_pLog->AddLineWarn(strTmp); - m_nWarnYccClipNum++; - m_sStatClip.nClipYOver++; - if (m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),YCC_CLIP_REPORT_MAX); - m_pLog->AddLineWarn(strTmp); - } - } - sPix.nClip |= CC_CLIP_Y_OVER; - nCurY = CC_CLIP_YCC_MAX; - } - if (nCurY < CC_CLIP_YCC_MIN) { - if (YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) { - CString strTmp; - strTmp.Format(_T("*** NOTE: YCC Clipped. MCU=(%4u,%4u) YCC=(%5d,%5d,%5d) Y Underflow @ Offset %s"), - nMcuX,nMcuY,nCurY,nCurCb,nCurCr,(LPCTSTR)GetScanBufPos()); - m_pLog->AddLineWarn(strTmp); - m_nWarnYccClipNum++; - m_sStatClip.nClipYUnder++; - if (m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),YCC_CLIP_REPORT_MAX); - m_pLog->AddLineWarn(strTmp); - } - } - sPix.nClip |= CC_CLIP_Y_UNDER; - nCurY = CC_CLIP_YCC_MIN; - } - if (nCurCb > CC_CLIP_YCC_MAX) { - if (YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) { - CString strTmp; - strTmp.Format(_T("*** NOTE: YCC Clipped. MCU=(%4u,%4u) YCC=(%5d,%5d,%5d) Cb Overflow @ Offset %s"), - nMcuX,nMcuY,nCurY,nCurCb,nCurCr,(LPCTSTR)GetScanBufPos()); - m_pLog->AddLineWarn(strTmp); - m_nWarnYccClipNum++; - m_sStatClip.nClipCbOver++; - if (m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),YCC_CLIP_REPORT_MAX); - m_pLog->AddLineWarn(strTmp); - } - } - sPix.nClip |= CC_CLIP_CB_OVER; - nCurCb = CC_CLIP_YCC_MAX; - } - if (nCurCb < CC_CLIP_YCC_MIN) { - if (YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) { - CString strTmp; - strTmp.Format(_T("*** NOTE: YCC Clipped. MCU=(%4u,%4u) YCC=(%5d,%5d,%5d) Cb Underflow @ Offset %s"), - nMcuX,nMcuY,nCurY,nCurCb,nCurCr,(LPCTSTR)GetScanBufPos()); - m_pLog->AddLineWarn(strTmp); - m_nWarnYccClipNum++; - m_sStatClip.nClipCbUnder++; - if (m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),YCC_CLIP_REPORT_MAX); - m_pLog->AddLineWarn(strTmp); - } - } - sPix.nClip |= CC_CLIP_CB_UNDER; - nCurCb = CC_CLIP_YCC_MIN; - } - if (nCurCr > CC_CLIP_YCC_MAX) { - if (YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) { - CString strTmp; - strTmp.Format(_T("*** NOTE: YCC Clipped. MCU=(%4u,%4u) YCC=(%5d,%5d,%5d) Cr Overflow @ Offset %s"), - nMcuX,nMcuY,nCurY,nCurCb,nCurCr,(LPCTSTR)GetScanBufPos()); - m_pLog->AddLineWarn(strTmp); - m_nWarnYccClipNum++; - m_sStatClip.nClipCrOver++; - if (m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),YCC_CLIP_REPORT_MAX); - m_pLog->AddLineWarn(strTmp); - } - } - sPix.nClip |= CC_CLIP_CR_OVER; - nCurCr = CC_CLIP_YCC_MAX; - } - if (nCurCr < CC_CLIP_YCC_MIN) { - if (YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) { - CString strTmp; - strTmp.Format(_T("*** NOTE: YCC Clipped. MCU=(%4u,%4u) YCC=(%5d,%5d,%5d) Cr Underflow @ Offset %s"), - nMcuX,nMcuY,nCurY,nCurCb,nCurCr,(LPCTSTR)GetScanBufPos()); - m_pLog->AddLineWarn(strTmp); - m_nWarnYccClipNum++; - m_sStatClip.nClipCrUnder++; - if (m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) { - strTmp.Format(_T(" Only reported first %u instances of this message..."),YCC_CLIP_REPORT_MAX); - m_pLog->AddLineWarn(strTmp); - } - } - sPix.nClip |= CC_CLIP_CR_UNDER; - nCurCr = CC_CLIP_YCC_MIN; - } - } // YCC clip enabled? - - // Perform color conversion: YCC->RGB - // The nCurY/cb/cr values should already be clipped to BYTE size - sPix.nFinalY = static_cast(nCurY); - sPix.nFinalCb = static_cast(nCurCb); - sPix.nFinalCr = static_cast(nCurCr); - -} - - - -// Color conversion clipping (RGB) -// - Input RGB triplet in floats -// - Expect range to be 0..255 -// - Return RGB triplet in bytes -// - Report if it is out of range -// - Converts from Preclip RGB to Final RGB -// -// INPUT: -// - nMcuX = MCU x coordinate -// - nMcuY = MCU y coordinate -// - sPix = Structure for color conversion -// OUTPUT: -// - sPix = Structure for color conversion -// POST: -// - m_sHisto -// -void CimgDecode::CapRgbRange(unsigned nMcuX,unsigned nMcuY,PixelCc &sPix) -{ - int nLimitR,nLimitG,nLimitB; - - // Truncate - nLimitR = (int)(sPix.nPreclipR); - nLimitG = (int)(sPix.nPreclipG); - nLimitB = (int)(sPix.nPreclipB); - - if (m_bHistEn) { - m_sHisto.nPreclipRMin = (nLimitRm_sHisto.nPreclipRMax)?nLimitR:m_sHisto.nPreclipRMax; - m_sHisto.nPreclipRSum += nLimitR; - m_sHisto.nPreclipGMin = (nLimitGm_sHisto.nPreclipGMax)?nLimitG:m_sHisto.nPreclipGMax; - m_sHisto.nPreclipGSum += nLimitG; - m_sHisto.nPreclipBMin = (nLimitBm_sHisto.nPreclipBMax)?nLimitB:m_sHisto.nPreclipBMax; - m_sHisto.nPreclipBSum += nLimitB; - } - - if (nLimitR < 0) { - if (m_bVerbose) { - CString strTmp; - strTmp.Format(_T(" YCC->RGB Clipped. MCU=(%4u,%4u) RGB=(%5d,%5d,%5d) Red Underflow"), - nMcuX,nMcuY,nLimitR,nLimitG,nLimitB); - m_pLog->AddLineWarn(strTmp); - } - sPix.nClip |= CC_CLIP_R_UNDER; - m_sStatClip.nClipRUnder++; - nLimitR = 0; - } - if (nLimitG < 0) { - if (m_bVerbose) { - CString strTmp; - strTmp.Format(_T(" YCC->RGB Clipped. MCU=(%4u,%4u) RGB=(%5d,%5d,%5d) Green Underflow"), - nMcuX,nMcuY,nLimitR,nLimitG,nLimitB); - m_pLog->AddLineWarn(strTmp); - } - sPix.nClip |= CC_CLIP_G_UNDER; - m_sStatClip.nClipGUnder++; - nLimitG = 0; - } - if (nLimitB < 0) { - if (m_bVerbose) { - CString strTmp; - strTmp.Format(_T(" YCC->RGB Clipped. MCU=(%4u,%4u) RGB=(%5d,%5d,%5d) Blue Underflow"), - nMcuX,nMcuY,nLimitR,nLimitG,nLimitB); - m_pLog->AddLineWarn(strTmp); - } - sPix.nClip |= CC_CLIP_B_UNDER; - m_sStatClip.nClipBUnder++; - nLimitB = 0; - } - if (nLimitR > 255) { - if (m_bVerbose) { - CString strTmp; - strTmp.Format(_T(" YCC->RGB Clipped. MCU=(%4u,%4u) RGB=(%5d,%5d,%5d) Red Overflow"), - nMcuX,nMcuY,nLimitR,nLimitG,nLimitB); - m_pLog->AddLineWarn(strTmp); - } - sPix.nClip |= CC_CLIP_R_OVER; - m_sStatClip.nClipROver++; - nLimitR = 255; - } - if (nLimitG > 255) { - if (m_bVerbose) { - CString strTmp; - strTmp.Format(_T(" YCC->RGB Clipped. MCU=(%4u,%4u) RGB=(%5d,%5d,%5d) Green Overflow"), - nMcuX,nMcuY,nLimitR,nLimitG,nLimitB); - m_pLog->AddLineWarn(strTmp); - } - sPix.nClip |= CC_CLIP_G_OVER; - m_sStatClip.nClipGOver++; - nLimitG = 255; - } - if (nLimitB > 255) { - if (m_bVerbose) { - CString strTmp; - strTmp.Format(_T(" YCC->RGB Clipped. MCU=(%4u,%4u) RGB=(%5d,%5d,%5d) Blue Overflow"), - nMcuX,nMcuY,nLimitR,nLimitG,nLimitB); - m_pLog->AddLineWarn(strTmp); - } - sPix.nClip |= CC_CLIP_B_OVER; - m_sStatClip.nClipBOver++; - nLimitB = 255; - } - - if (m_bHistEn) { - m_sHisto.nClipRMin = (nLimitRm_sHisto.nClipRMax)?nLimitR:m_sHisto.nClipRMax; - m_sHisto.nClipRSum += nLimitR; - m_sHisto.nClipGMin = (nLimitGm_sHisto.nClipGMax)?nLimitG:m_sHisto.nClipGMax; - m_sHisto.nClipGSum += nLimitG; - m_sHisto.nClipBMin = (nLimitBm_sHisto.nClipBMax)?nLimitB:m_sHisto.nClipBMax; - m_sHisto.nClipBSum += nLimitB; - } - - - // Now convert to BYTE - sPix.nFinalR = (byte)nLimitR; - sPix.nFinalG = (byte)nLimitG; - sPix.nFinalB = (byte)nLimitB; - -} - - -// Recalcs the full image based on the original YCC pixmap -// - Also locate the brightest pixel. -// - Note that we cannot do the brightest pixel search when we called SetFullRes() -// because we need to have access to all of the channel components at once to do this. -// -// INPUT: -// - pRectView = UNUSED. Intended to limit updates to visible region -// (Range of real image that is visibile / cropped) -// PRE: -// - m_pPixValY[] -// - m_pPixValCb[] -// - m_pPixValCr[] -// OUTPUT: -// - pTmp = RGB pixel map (32-bit per pixel, [0x00,R,G,B]) -// -void CimgDecode::CalcChannelPreviewFull(CRect* pRectView,unsigned char* pTmp) -{ - pRectView; // Unreferenced param - PixelCc sPixSrc,sPixDst; - CString strTmp; - - unsigned nRowBytes; - nRowBytes = m_nImgSizeX * sizeof(RGBQUAD); - - - // Color conversion process - - unsigned nPixMapW = m_nBlkXMax*BLK_SZ_X; - unsigned nPixmapInd; - - unsigned nRngX1,nRngX2,nRngY1,nRngY2; - unsigned nSumY; - unsigned long nNumPixels = 0; - - // TODO: Update ranges to take into account the visible view region - // The approach might include: - // nRngX1 = pRectView->left; - // nRngX2 = pRectView->right; - // nRngY1 = pRectView->top; - // nRngY2 = pRectView->bottom; - // - // These co-ords will define range in nPixX,nPixY that get drawn - // This will help YCC Adjust display react much faster. Only recalc - // visible portion of image, but then recalc entire one once Adjust - // dialog is closed. - // - // NOTE: if we were to make these ranges a subset of the - // full image dimensions, then we'd have to determine the best - // way to handle the brightest pixel search & average luminance logic - // since those appear in the nRngX/Y loops. - - nRngX1 = 0; - nRngX2 = m_nImgSizeX; - nRngY1 = 0; - nRngY2 = m_nImgSizeY; - - - - // Brightest pixel values were already reset during Reset() call, but for - // safety, do it again here. - m_bBrightValid = false; - m_nBrightY = -32768; - m_nBrightCb = -32768; - m_nBrightCr = -32768; - - // Average luminance calculation - m_bAvgYValid = false; - m_nAvgY = 0; - nSumY = 0; - - // For IDCT RGB Printout: - bool bRowStart = false; - CString strLine; - - - unsigned nMcuShiftInd = m_nPreviewShiftMcuY * (m_nImgSizeX/m_nMcuWidth) + m_nPreviewShiftMcuX; - - SetStatusText(_T("Color conversion...")); - - if (m_bDetailVlc) { - m_pLog->AddLine(_T(" Detailed IDCT Dump (RGB):")); - strTmp.Format(_T(" MCU [%3u,%3u]:"),m_nDetailVlcX,m_nDetailVlcY); - m_pLog->AddLine(strTmp); - } - - // Determine pixel count - nNumPixels = (nRngY2-nRngY1+1) * (nRngX2-nRngX1+1); - - // Step through the image - for (unsigned nPixY=nRngY1;nPixY m_nBrightY) { - m_nBrightY = nTmpY; - m_nBrightCb = nTmpCb; - m_nBrightCr = nTmpCr; - m_ptBrightMcu.x = nMcuX; - m_ptBrightMcu.y = nMcuY; - } - - // FIXME - // Could speed this up by adding boolean check to see if we are - // truly needing to do any shifting! - if (nMcuInd >= nMcuShiftInd) { - sPixSrc.nPrerangeY += m_nPreviewShiftY; - sPixSrc.nPrerangeCb += m_nPreviewShiftCb; - sPixSrc.nPrerangeCr += m_nPreviewShiftCr; - } - - // Invoke the appropriate color conversion routine - if (m_bHistEn || m_bStatClipEn) { - ConvertYCCtoRGB(nMcuX,nMcuY,sPixSrc); - } else { - ConvertYCCtoRGBFastFloat(sPixSrc); - //ConvertYCCtoRGBFastFixed(sPixSrc); - } - - // Accumulate the luminance value for this pixel - // after we have converted it to the range 0..255 - nSumY += sPixSrc.nFinalY; - - - // If we want a detailed decode of RGB, print it out - // now if we are on the correct MCU. - // NOTE: The level shift (adjust) will affect this report! - if (m_bDetailVlc) { - if (nMcuY == m_nDetailVlcY) { - - if (nMcuX == m_nDetailVlcX) { - //if ((nMcuX >= m_nDetailVlcX) && (nMcuX < m_nDetailVlcX+m_nDetailVlcLen)) { - if (!bRowStart) { - bRowStart = true; - strLine.Format(_T(" [ ")); - } - strTmp.Format(_T("x%02X%02X%02X "),sPixSrc.nFinalR,sPixSrc.nFinalG,sPixSrc.nFinalB); - strLine.Append(strTmp); - } else { - if (bRowStart) { - // We had started a row, but we are now out of range, so we - // need to close up! - strTmp.Format(_T(" ]")); - strLine.Append(strTmp); - m_pLog->AddLine(strLine); - bRowStart = false; - } - } - } - - } - - // Perform any channel filtering if enabled - ChannelExtract(m_nPreviewMode,sPixSrc,sPixDst); - - // Assign the RGB pixel map - pTmp[nPixByte+3] = 0; - pTmp[nPixByte+2] = sPixDst.nFinalR; - pTmp[nPixByte+1] = sPixDst.nFinalG; - pTmp[nPixByte+0] = sPixDst.nFinalB; - - } // x - } // y - - SetStatusText(_T("")); - // --------------------------------------------------------- - - if (m_bDetailVlc) { - m_pLog->AddLine(_T("")); - } - - - // Assume that brightest pixel search was successful - // Now compute the RGB value for this pixel! - m_bBrightValid = true; - sPixSrc.nPrerangeY = m_nBrightY; - sPixSrc.nPrerangeCb = m_nBrightCb; - sPixSrc.nPrerangeCr = m_nBrightCr; - ConvertYCCtoRGBFastFloat(sPixSrc); - m_nBrightR = sPixSrc.nFinalR; - m_nBrightG = sPixSrc.nFinalG; - m_nBrightB = sPixSrc.nFinalB; - - // Now perform average luminance calculation - // NOTE: This will result in a value in the range 0..255 - ASSERT(nNumPixels > 0); - // Avoid divide by zero - if (nNumPixels == 0) { nNumPixels = 1; } - m_nAvgY = nSumY / nNumPixels; - m_bAvgYValid = true; - -} - - -// Extract the specified channel -// -// INPUT: -// - nMode = Channel(s) to extract from -// - sSrc = Color representations (YCC & RGB) for pixel -// OUTPUT: -// - sDst = Resulting RGB output after filtering -// -void CimgDecode::ChannelExtract(unsigned nMode,PixelCc &sSrc,PixelCc &sDst) -{ - if (nMode == PREVIEW_RGB) { - sDst.nFinalR = sSrc.nFinalR; - sDst.nFinalG = sSrc.nFinalG; - sDst.nFinalB = sSrc.nFinalB; - } else if (nMode == PREVIEW_YCC) { - sDst.nFinalR = sSrc.nFinalCr; - sDst.nFinalG = sSrc.nFinalY; - sDst.nFinalB = sSrc.nFinalCb; - } else if (nMode == PREVIEW_R) { - sDst.nFinalR = sSrc.nFinalR; - sDst.nFinalG = sSrc.nFinalR; - sDst.nFinalB = sSrc.nFinalR; - } else if (nMode == PREVIEW_G) { - sDst.nFinalR = sSrc.nFinalG; - sDst.nFinalG = sSrc.nFinalG; - sDst.nFinalB = sSrc.nFinalG; - } else if (nMode == PREVIEW_B) { - sDst.nFinalR = sSrc.nFinalB; - sDst.nFinalG = sSrc.nFinalB; - sDst.nFinalB = sSrc.nFinalB; - } else if (nMode == PREVIEW_Y) { - sDst.nFinalR = sSrc.nFinalY; - sDst.nFinalG = sSrc.nFinalY; - sDst.nFinalB = sSrc.nFinalY; - } else if (nMode == PREVIEW_CB) { - sDst.nFinalR = sSrc.nFinalCb; - sDst.nFinalG = sSrc.nFinalCb; - sDst.nFinalB = sSrc.nFinalCb; - } else if (nMode == PREVIEW_CR) { - sDst.nFinalR = sSrc.nFinalCr; - sDst.nFinalG = sSrc.nFinalCr; - sDst.nFinalB = sSrc.nFinalCr; - } else { - sDst.nFinalR = sSrc.nFinalR; - sDst.nFinalG = sSrc.nFinalG; - sDst.nFinalB = sSrc.nFinalB; - } - -} - -// Fetch the detailed decode settings (VLC) -// -// OUTPUT: -// - bDetail = Enable for detailed scan VLC reporting -// - nX = Start of detailed scan decode MCU X coordinate -// - nY = Start of detailed scan decode MCU Y coordinate -// - nLen = Number of MCUs to parse in detailed scan decode -// -void CimgDecode::GetDetailVlc(bool &bDetail,unsigned &nX,unsigned &nY,unsigned &nLen) -{ - bDetail = m_bDetailVlc; - nX = m_nDetailVlcX; - nY = m_nDetailVlcY; - nLen = m_nDetailVlcLen; -} - -// Set the detailed scan decode settings (VLC) -// -// INPUT: -// - bDetail = Enable for detailed scan VLC reporting -// - nX = Start of detailed scan decode MCU X coordinate -// - nY = Start of detailed scan decode MCU Y coordinate -// - nLen = Number of MCUs to parse in detailed scan decode -// -void CimgDecode::SetDetailVlc(bool bDetail,unsigned nX,unsigned nY,unsigned nLen) -{ - m_bDetailVlc = bDetail; - m_nDetailVlcX = nX; - m_nDetailVlcY = nY; - m_nDetailVlcLen = nLen; -} - -// Fetch the pointers for the pixel map -// -// OUTPUT: -// - pMayY = Pointer to pixel map for Y component -// - pMapCb = Pointer to pixel map for Cb component -// - pMapCr = Pointer to pixel map for Cr component -// -void CimgDecode::GetPixMapPtrs(short* &pMapY,short* &pMapCb,short* &pMapCr) -{ - ASSERT(m_pPixValY); - ASSERT(m_pPixValCb); - ASSERT(m_pPixValCr); - pMapY = m_pPixValY; - pMapCb = m_pPixValCb; - pMapCr = m_pPixValCr; -} - -// Get image pixel dimensions rounded up to nearest MCU -// -// OUTPUT: -// - nX = X dimension of preview image -// - nY = Y dimension of preview image -// -void CimgDecode::GetImageSize(unsigned &nX,unsigned &nY) -{ - nX = m_nImgSizeX; - nY = m_nImgSizeY; -} - -// Get the bitmap pointer -// -// OUTPUT: -// - pBitmap = Bitmap (DIB) of preview -// -void CimgDecode::GetBitmapPtr(unsigned char* &pBitmap) -{ - unsigned char * pDibImgTmpBits = NULL; - - pDibImgTmpBits = (unsigned char*) ( m_pDibTemp.GetDIBBitArray() ); - - // Ensure that the pointers are available! - if ( !pDibImgTmpBits ) { - pBitmap = NULL; - } else { - pBitmap = pDibImgTmpBits; - } -} - -// Calculate RGB pixel map from selected channels of YCC pixel map -// -// PRE: -// - m_pPixValY -// - m_pPixValCb -// - m_pPixValCr -// POST: -// - m_pDibTemp -// NOTE: -// - Channels are selected in CalcChannelPreviewFull() -// -void CimgDecode::CalcChannelPreview() -{ - unsigned char * pDibImgTmpBits = NULL; - - pDibImgTmpBits = (unsigned char*) ( m_pDibTemp.GetDIBBitArray() ); - - // Ensure that the pointers are available! - if ( !pDibImgTmpBits ) { - return; - } - - - // If we need to do a YCC shift, then do full recalc into tmp array - CalcChannelPreviewFull(NULL,pDibImgTmpBits); - - // Since this was a complex mod, we don't mark this channel as - // being "done", so we will need to recalculate any time we change - // the channel display. - - // Force an update of the view to be sure - //m_pDoc->UpdateAllViews(NULL); - - return; - -} - - -// Determine the file position from a pixel coordinate -// -// INPUT: -// - nPixX = Pixel coordinate (x) -// - nPixY = Pixel coordinate (y) -// OUTPUT: -// - nByte = File offset (byte) -// - nBit = File offset (bit) -// -void CimgDecode::LookupFilePosPix(unsigned nPixX,unsigned nPixY, unsigned &nByte, unsigned &nBit) -{ - unsigned nMcuX,nMcuY; - unsigned nPacked; - nMcuX = nPixX / m_nMcuWidth; - nMcuY = nPixY / m_nMcuHeight; - nPacked = m_pMcuFileMap[nMcuX + nMcuY*m_nMcuXMax]; - UnpackFileOffset(nPacked,nByte,nBit); -} - -// Determine the file position from a MCU coordinate -// -// INPUT: -// - nMcuX = MCU coordinate (x) -// - nMcuY = MCU coordinate (y) -// OUTPUT: -// - nByte = File offset (byte) -// - nBit = File offset (bit) -// -void CimgDecode::LookupFilePosMcu(unsigned nMcuX,unsigned nMcuY, unsigned &nByte, unsigned &nBit) -{ - unsigned nPacked; - nPacked = m_pMcuFileMap[nMcuX + nMcuY*m_nMcuXMax]; - UnpackFileOffset(nPacked,nByte,nBit); -} - -// Determine the YCC DC value of a specified block -// -// INPUT: -// - nBlkX = 8x8 block coordinate (x) -// - nBlkY = 8x8 block coordinate (y) -// OUTPUT: -// - nY = Y channel value -// - nCb = Cb channel value -// - nCr = Cr channel value -// -void CimgDecode::LookupBlkYCC(unsigned nBlkX,unsigned nBlkY,int &nY,int &nCb,int &nCr) -{ - nY = m_pBlkDcValY [nBlkX + nBlkY*m_nBlkXMax]; - if (m_nNumSosComps == NUM_CHAN_YCC) { - nCb = m_pBlkDcValCb[nBlkX + nBlkY*m_nBlkXMax]; - nCr = m_pBlkDcValCr[nBlkX + nBlkY*m_nBlkXMax]; - } else { - nCb = 0; // FIXME - nCr = 0; // FIXME - } -} - -// Convert pixel coordinate to MCU coordinate -// -// INPUT: -// - ptPix = Pixel coordinate -// RETURN: -// - MCU coordinate -// -CPoint CimgDecode::PixelToMcu(CPoint ptPix) -{ - CPoint ptMcu; - ptMcu.x = ptPix.x / m_nMcuWidth; - ptMcu.y = ptPix.y / m_nMcuHeight; - return ptMcu; -} - -// Convert pixel coordinate to block coordinate -// -// INPUT: -// - ptPix = Pixel coordinate -// RETURN: -// - 8x8 block coordinate -// -CPoint CimgDecode::PixelToBlk(CPoint ptPix) -{ - CPoint ptBlk; - ptBlk.x = ptPix.x / BLK_SZ_X; - ptBlk.y = ptPix.y / BLK_SZ_Y; - return ptBlk; -} - -// Return the linear MCU offset from an MCU X,Y coord -// -// INPUT: -// - ptMcu = MCU coordinate -// PRE: -// - m_nMcuXMax -// RETURN: -// - Index of MCU from start of MCUs -// -unsigned CimgDecode::McuXyToLinear(CPoint ptMcu) -{ - unsigned nLinear; - nLinear = ( (ptMcu.y * m_nMcuXMax) + ptMcu.x); - return nLinear; -} - -// Create a file offset notation that represents bytes and bits -// - Essentially a fixed-point notation -// -// INPUT: -// - nByte = File byte position -// - nBit = File bit position -// RETURN: -// - Fixed-point file offset (29b for bytes, 3b for bits) -// -unsigned CimgDecode::PackFileOffset(unsigned nByte,unsigned nBit) -{ - unsigned nTmp; - // Note that we only really need 3 bits, but I'll keep 4 - // so that the file offset is human readable. We will only - // handle files up to 2^28 bytes (256MB), so this is probably - // fine! - nTmp = (nByte << 4) + nBit; - return nTmp; -} - -// Convert from file offset notation to bytes and bits -// -// INPUT: -// - nPacked = Fixed-point file offset (29b for bytes, 3b for bits) -// OUTPUT: -// - nByte = File byte position -// - nBit = File bit position -// -void CimgDecode::UnpackFileOffset(unsigned nPacked, unsigned &nByte, unsigned &nBit) -{ - nBit = nPacked & 0x7; - nByte = nPacked >> 4; -} - - -// Fetch the number of block markers assigned -// -// RETURN: -// - Number of marker blocks -// -unsigned CimgDecode::GetMarkerCount() -{ - return m_nMarkersBlkNum; -} - -// Fetch an indexed block marker -// -// INPUT: -// - nInd = Index into marker block array -// RETURN: -// - Point (8x8 block) from marker array -// -CPoint CimgDecode::GetMarkerBlk(unsigned nInd) -{ - CPoint myPt(0,0); - if (nInd < m_nMarkersBlkNum) { - myPt = m_aptMarkersBlk[nInd]; - } else { - ASSERT(false); - } - return myPt; -} - - - -// Add a block to the block marker list -// - Also report out the YCC DC value for the block -// -// INPUT: -// - nBlkX = 8x8 block X coordinate -// - nBlkY = 8x8 block Y coordinate -// POST: -// - m_nMarkersBlkNum -// - m_aptMarkersBlk[] -// -void CimgDecode::SetMarkerBlk(unsigned nBlkX,unsigned nBlkY) -{ - if (m_nMarkersBlkNum == MAX_BLOCK_MARKERS) { - // Shift them down by 1. Last entry will be deleted next - for (unsigned ind=1;indGetQuickMode(); - m_pLog->SetQuickMode(false); - strTmp.Format(_T("Position Marked @ MCU=[%4u,%4u](%u,%u) Block=[%4u,%4u] YCC=[%5d,%5d,%5d]"), - nMcuX,nMcuY,nCssX,nCssY,nBlkX,nBlkY,nY,nCb,nCr); - m_pLog->AddLine(strTmp); - m_pLog->AddLine(_T("")); - m_pLog->SetQuickMode(bQuickModeSaved); - - - m_aptMarkersBlk[m_nMarkersBlkNum].x = nBlkX; - m_aptMarkersBlk[m_nMarkersBlkNum].y = nBlkY; - m_nMarkersBlkNum++; -} - - - -// Fetch the preview zoom mode -// -// RETURN: -// - The zoom mode enumeration -// -unsigned CimgDecode::GetPreviewZoomMode() -{ - return m_nZoomMode; -} - -// Fetch the preview mode -// -// RETURN: -// - The image preview mode enumeration -// -unsigned CimgDecode::GetPreviewMode() -{ - return m_nPreviewMode; -} - -// Fetch the preview zoom level -// -// RETURN: -// - The preview zoom level enumeration -// -float CimgDecode::GetPreviewZoom() -{ - return m_nZoom; -} - -// Change the current zoom level -// - Supports either direct setting of the level -// or an increment/decrement operation -// -// INPUT: -// - bInc = Flag to increment the zoom level -// - bDec = Flag to decrement the zoom level -// - bSet = Flag to set the zoom level -// - nVal = Zoom level for "set" operation -// POST: -// - m_nZoomMode -// -void CimgDecode::SetPreviewZoom(bool bInc,bool bDec,bool bSet,unsigned nVal) -{ - if (bInc) { - if (m_nZoomMode+1 < PRV_ZOOMEND) { - m_nZoomMode++; - - } - } else if (bDec) { - if (m_nZoomMode-1 > PRV_ZOOMBEGIN) { - m_nZoomMode--; - } - } else if (bSet) { - m_nZoomMode = nVal; - } - switch(m_nZoomMode) { - case PRV_ZOOM_12: m_nZoom = 0.125; break; - case PRV_ZOOM_25: m_nZoom = 0.25; break; - case PRV_ZOOM_50: m_nZoom = 0.5; break; - case PRV_ZOOM_100: m_nZoom = 1.0; break; - case PRV_ZOOM_150: m_nZoom = 1.5; break; - case PRV_ZOOM_200: m_nZoom = 2.0; break; - case PRV_ZOOM_300: m_nZoom = 3.0; break; - case PRV_ZOOM_400: m_nZoom = 4.0; break; - case PRV_ZOOM_800: m_nZoom = 8.0; break; - default: m_nZoom = 1.0; break; - } - -} - -// Main draw routine for the image -// - Draws the preview image with frame -// - Draws any histogram -// - Draws a title -// - Draws any MCU overlays / grid -// -// INPUT: -// - pDC = The device context pointer -// - rectClient = From GetClientRect() -// - ptScrolledPos = From GetScrollPosition() -// - pFont = Pointer to the font used for title/lables -// OUTPUT: -// - szNewScrollSize = New dimension used for SetScrollSizes() -// -void CimgDecode::ViewOnDraw(CDC* pDC,CRect rectClient,CPoint ptScrolledPos, - CFont* pFont, CSize &szNewScrollSize) -{ - - unsigned nBorderLeft = 10; - unsigned nBorderBottom = 10; - unsigned nTitleHeight = 20; - unsigned nTitleIndent = 5; - unsigned nTitleLowGap = 3; - - m_nPageWidth = 600; - m_nPageHeight = 10; // Start with some margin - - - CString strTmp; - CString strRender; - int nHeight; - - - unsigned nYPosImgTitle = 0; - unsigned nYPosImg = 0; - unsigned nYPosHistTitle = 0; - unsigned nYPosHist = 0; - unsigned nYPosHistYTitle = 0; - unsigned nYPosHistY = 0; // Y position of Img & Histogram - - CRect rectTmp; - - // If we have displayed an image, make sure to allow for - // the additional space! - - bool bImgDrawn = false; - - CBrush brGray( RGB(128, 128, 128)); - CBrush brGrayLt1( RGB(210, 210, 210)); - CBrush brGrayLt2( RGB(240, 240, 240)); - CBrush brBlueLt( RGB(240, 240, 255)); - CPen penRed(PS_DOT,1,RGB(255,0,0)); - - - if (m_bDibTempReady) { - - nYPosImgTitle = m_nPageHeight; - m_nPageHeight += nTitleHeight; // Margin at top for title - - m_rectImgReal.SetRect(0,0, - (int)(m_rectImgBase.right*m_nZoom), - (int)(m_rectImgBase.bottom*m_nZoom) ); - - nYPosImg = m_nPageHeight; - m_nPageHeight += m_rectImgReal.Height(); - m_nPageHeight += nBorderBottom; // Margin at bottom - bImgDrawn = true; - - m_rectImgReal.OffsetRect(nBorderLeft,nYPosImg); - - // Now create the shadow of the main image - rectTmp = m_rectImgReal; - rectTmp.OffsetRect(4,4); - pDC->FillRect(rectTmp,&brGrayLt1); - rectTmp.InflateRect(1,1,1,1); - pDC->FrameRect(rectTmp,&brGrayLt2); - - } - - if (m_bHistEn) { - - if (m_bDibHistRgbReady) { - - nYPosHistTitle = m_nPageHeight; - m_nPageHeight += nTitleHeight; // Margin at top for title - - m_rectHistReal = m_rectHistBase; - - nYPosHist = m_nPageHeight; - m_nPageHeight += m_rectHistReal.Height(); - m_nPageHeight += nBorderBottom; // Margin at bottom - bImgDrawn = true; - - m_rectHistReal.OffsetRect(nBorderLeft,nYPosHist); - - // Create the border - rectTmp = m_rectHistReal; - rectTmp.InflateRect(1,1,1,1); - pDC->FrameRect(rectTmp,&brGray); - } - - if (m_bDibHistYReady) { - - nYPosHistYTitle = m_nPageHeight; - m_nPageHeight += nTitleHeight; // Margin at top for title - - m_rectHistYReal = m_rectHistYBase; - - nYPosHistY = m_nPageHeight; - m_nPageHeight += m_rectHistYReal.Height(); - m_nPageHeight += nBorderBottom; // Margin at bottom - bImgDrawn = true; - - m_rectHistYReal.OffsetRect(nBorderLeft,nYPosHistY); - - // Create the border - rectTmp = m_rectHistYReal; - rectTmp.InflateRect(1,1,1,1); - pDC->FrameRect(rectTmp,&brGray); - - - } - - } - - - // Find a starting line based on scrolling - // and current client size - - - CRect rectClientScrolled = rectClient; - rectClientScrolled.OffsetRect(ptScrolledPos); - - // Change the font - CFont* pOldFont; - pOldFont = pDC->SelectObject(pFont); - - CString strTitle; - - // Draw the bitmap if ready - if (m_bDibTempReady) { - - // Print label - - if (!m_bPreviewIsJpeg) { - // For all non-JPEG images, report with simple title - strTitle = _T("Image"); - } else { - strTitle = _T("Image ("); - switch (m_nPreviewMode) { - case PREVIEW_RGB: strTitle += _T("RGB"); break; - case PREVIEW_YCC: strTitle += _T("YCC"); break; - case PREVIEW_R: strTitle += _T("R"); break; - case PREVIEW_G: strTitle += _T("G"); break; - case PREVIEW_B: strTitle += _T("B"); break; - case PREVIEW_Y: strTitle += _T("Y"); break; - case PREVIEW_CB: strTitle += _T("Cb"); break; - case PREVIEW_CR: strTitle += _T("Cr"); break; - default: strTitle += _T("???"); break; - } - if (m_bDecodeScanAc) { - strTitle += _T(", DC+AC)"); - } else { - strTitle += _T(", DC)"); - } - } - - - switch (m_nZoomMode) { - case PRV_ZOOM_12: strTitle += " @ 12.5% (1/8)"; break; - case PRV_ZOOM_25: strTitle += " @ 25% (1/4)"; break; - case PRV_ZOOM_50: strTitle += " @ 50% (1/2)"; break; - case PRV_ZOOM_100: strTitle += _T(" @ 100% (1:1)"); break; - case PRV_ZOOM_150: strTitle += _T(" @ 150% (3:2)"); break; - case PRV_ZOOM_200: strTitle += _T(" @ 200% (2:1)"); break; - case PRV_ZOOM_300: strTitle += _T(" @ 300% (3:1)"); break; - case PRV_ZOOM_400: strTitle += _T(" @ 400% (4:1)"); break; - case PRV_ZOOM_800: strTitle += _T(" @ 800% (8:1)"); break; - default: strTitle += _T(""); break; - } - - - // Calculate the title width - CRect rectCalc = CRect(0,0,0,0); - nHeight = pDC->DrawText(strTitle,-1,&rectCalc, - DT_CALCRECT | DT_TOP | DT_NOPREFIX | DT_SINGLELINE); - int nWidth = rectCalc.Width() + 2*nTitleIndent; - - // Determine the title area (could be larger than the image - // if the image zoom is < 100% or sized small) - - // Draw title background - rectTmp = CRect(m_rectImgReal.left,nYPosImgTitle, - max(m_rectImgReal.right,m_rectImgReal.left+nWidth),m_rectImgReal.top-nTitleLowGap); - pDC->FillRect(rectTmp,&brBlueLt); - - // Draw the title - int nBkMode = pDC->GetBkMode(); - pDC->SetBkMode(TRANSPARENT); - rectTmp.OffsetRect(nTitleIndent,0); - nHeight = pDC->DrawText(strTitle,-1,&rectTmp, - DT_TOP | DT_NOPREFIX | DT_SINGLELINE); - pDC->SetBkMode(nBkMode); - - // Draw image - - // Assume that the temp image has already been generated! - // For speed purposes, we use m_pDibTemp only when we are - // in a mode other than RGB or YCC. In the RGB/YCC modes, - // we skip the CalcChannelPreview() step. - - // TODO: Improve redraw time by only redrawing the currently visible - // region. Requires a different CopyDIB routine with a subset region. - // Needs to take into account zoom setting (eg. intersection between - // rectClient and m_rectImgReal). - - // Use a common DIB instead of creating/swapping tmp / ycc and rgb. - // This way we can also have more flexibility in modifying RGB & YCC displays. - // Time calling CalcChannelPreview() seems small, so no real impact. - - // Image member usage: - // m_pDibTemp: - - m_pDibTemp.CopyDIB(pDC,m_rectImgReal.left,m_rectImgReal.top,m_nZoom); - - // Now create overlays - - // Only draw overlay (eg. actual image boundary overlay) if the values - // have been set properly. Note that PSD decode currently sets these - // values to zero. - if ((m_nDimX != 0) && (m_nDimY != 0)) { - CPen* pPen = pDC->SelectObject(&penRed); - - // Draw boundary for end of valid data (inside partial MCU) - int nXZoomed = (int)(m_nDimX*m_nZoom); - int nYZoomed = (int)(m_nDimY*m_nZoom); - - pDC->MoveTo(m_rectImgReal.left+nXZoomed,m_rectImgReal.top); - pDC->LineTo(m_rectImgReal.left+nXZoomed,m_rectImgReal.top+nYZoomed); - - pDC->MoveTo(m_rectImgReal.left,m_rectImgReal.top+nYZoomed); - pDC->LineTo(m_rectImgReal.left+nXZoomed,m_rectImgReal.top+nYZoomed); - - pDC->SelectObject(pPen); - } - - // Before we frame the region, let's draw any remaining overlays - - // Only draw the MCU overlay if zoom is > 100%, otherwise we will have - // replaced entire image with the boundary lines! - if ( m_bViewOverlaysMcuGrid && (m_nZoomMode >= PRV_ZOOM_25)) { - ViewMcuOverlay(pDC); - } - - // Always draw the markers - ViewMcuMarkedOverlay(pDC); - - - // Final frame border - rectTmp = m_rectImgReal; - rectTmp.InflateRect(1,1,1,1); - pDC->FrameRect(rectTmp,&brGray); - - - // Preserve the image placement (for other functions, such as click detect) - m_nPreviewPosX = m_rectImgReal.left; - m_nPreviewPosY = m_rectImgReal.top; - m_nPreviewSizeX = m_rectImgReal.Width(); - m_nPreviewSizeY = m_rectImgReal.Height(); - - // m_nPageWidth is already hardcoded above - ASSERT(m_nPageWidth>=0); - m_nPageWidth = max((unsigned)m_nPageWidth, m_nPreviewPosX + m_nPreviewSizeX); - - - } - - if (m_bHistEn) { - - if (m_bDibHistRgbReady) { - - // Draw title background - rectTmp = CRect(m_rectHistReal.left,nYPosHistTitle, - m_rectHistReal.right,m_rectHistReal.top-nTitleLowGap); - pDC->FillRect(rectTmp,&brBlueLt); - - // Draw the title - int nBkMode = pDC->GetBkMode(); - pDC->SetBkMode(TRANSPARENT); - rectTmp.OffsetRect(nTitleIndent,0); - nHeight = pDC->DrawText(_T("Histogram (RGB)"),-1,&rectTmp, - DT_TOP | DT_NOPREFIX | DT_SINGLELINE); - pDC->SetBkMode(nBkMode); - - // Draw image - m_pDibHistRgb.CopyDIB(pDC,m_rectHistReal.left,m_rectHistReal.top); - } - - if (m_bDibHistYReady) { - - // Draw title background - rectTmp = CRect(m_rectHistYReal.left,nYPosHistYTitle, - m_rectHistYReal.right,m_rectHistYReal.top-nTitleLowGap); - pDC->FillRect(rectTmp,&brBlueLt); - - // Draw the title - int nBkMode = pDC->GetBkMode(); - pDC->SetBkMode(TRANSPARENT); - rectTmp.OffsetRect(nTitleIndent,0); - nHeight = pDC->DrawText(_T("Histogram (Y)"),-1,&rectTmp, - DT_TOP | DT_NOPREFIX | DT_SINGLELINE); - pDC->SetBkMode(nBkMode); - - // Draw image - m_pDibHistY.CopyDIB(pDC,m_rectHistYReal.left,m_rectHistYReal.top); - //m_pDibHistY.CopyDIB(pDC,nBorderLeft,nYPosHistY); - } - } - - // If no image has been drawn, indicate to user why! - if (!bImgDrawn) { - //ScrollRect.top = m_nPageHeight; // FIXME:? - - // Print label - //nHeight = pDC->DrawText(_T("Image Decode disabled. Enable with [Options->Decode Scan Image]"), -1,&ScrollRect, - // DT_TOP | DT_NOPREFIX | DT_SINGLELINE); - - } - - // Restore the original font - pDC->SelectObject(pOldFont); - - // Set scroll bars accordingly. We use the page dimensions here. - CSize sizeTotal(m_nPageWidth+nBorderLeft,m_nPageHeight); - - szNewScrollSize = sizeTotal; -} - -// Draw an overlay that shows the MCU grid -// -// INPUT: -// - pDC = The device context pointer -// -void CimgDecode::ViewMcuOverlay(CDC* pDC) -{ - // Now create overlays - unsigned nXZoomed,nYZoomed; - - CPen penDot(PS_DOT,1,RGB(32,32,32)); - - int nBkModeOld = pDC->GetBkMode(); - CPen* pPenOld = pDC->SelectObject(&penDot); - pDC->SetBkMode(TRANSPARENT); - - // Draw vertical lines - for (unsigned nMcuX=0;nMcuXMoveTo(m_rectImgReal.left+nXZoomed,m_rectImgReal.top); - pDC->LineTo(m_rectImgReal.left+nXZoomed,m_rectImgReal.bottom); - } - - for (unsigned nMcuY=0;nMcuYMoveTo(m_rectImgReal.left,m_rectImgReal.top+nYZoomed); - pDC->LineTo(m_rectImgReal.right,m_rectImgReal.top+nYZoomed); - } - - pDC->SelectObject(pPenOld); - pDC->SetBkMode(nBkModeOld); - -} - -// Draw an overlay that highlights the marked MCUs -// -// INPUT: -// - pDC = The device context pointer -// -void CimgDecode::ViewMcuMarkedOverlay(CDC* pDC) -{ - pDC; // Unreferenced param - - // Now draw a simple MCU Marker overlay - CRect my_rect; - CBrush my_brush(RGB(255, 0, 255)); - for (unsigned nMcuY=0;nMcuYFrameRect(my_rect,&my_brush); - } - */ - - } - } - -} - - -// Draw an overlay for the indexed block -// -// INPUT: -// - pDC = The device context pointer -// - nBlkX = 8x8 block X coordinate -// - nBlkY = 8x8 block Y coordinate -// -void CimgDecode::ViewMarkerOverlay(CDC* pDC,unsigned nBlkX,unsigned nBlkY) -{ - CRect my_rect; - CBrush my_brush(RGB(255, 0, 255)); - - // Note that drawing is an overlay, so we are dealing with real - // pixel coordinates, not preview image coords - my_rect = CRect( (unsigned)(m_nZoom*(nBlkX+0)), - (unsigned)(m_nZoom*(nBlkY+0)), - (unsigned)(m_nZoom*(nBlkX+1)), - (unsigned)(m_nZoom*(nBlkY+1))); - my_rect.OffsetRect(m_nPreviewPosX,m_nPreviewPosY); - pDC->FillRect(my_rect,&my_brush); -} - - -// Get the preview MCU grid setting -// -// OUTPUT: -// - The MCU grid enabled flag -// -bool CimgDecode::GetPreviewOverlayMcuGrid() -{ - return m_bViewOverlaysMcuGrid; -} - -// Toggle the preview MCU grid setting -// -// POST: -// - m_bViewOverlaysMcuGrid -// -void CimgDecode::SetPreviewOverlayMcuGridToggle() -{ - if (m_bViewOverlaysMcuGrid) { - m_bViewOverlaysMcuGrid = false; - } else { - m_bViewOverlaysMcuGrid = true; - } -} - -// Report the DC levels -// - UNUSED -// -// INPUT: -// - nMcuX = MCU x coordinate -// - nMcuY = MCU y coordinate -// - nMcuLen = Number of MCUs to report -// -void CimgDecode::ReportDcRun(unsigned nMcuX, unsigned nMcuY, unsigned nMcuLen) -{ - // FIXME: Should I be working on MCU level or block level? - CString strTmp; - m_pLog->AddLine(_T("")); - m_pLog->AddLineHdr(_T("*** Reporting DC Levels ***")); - strTmp.Format(_T(" Starting MCU = [%u,%u]"),nMcuX,nMcuY); - strTmp.Format(_T(" Number of MCUs = %u"),nMcuLen); - m_pLog->AddLine(strTmp); - for (unsigned ind=0;ind. +// + +#include +#include + +#include "ImgDecode.h" +#include "snoop.h" +#include + +#include "JPEGsnoop.h" + +// ------------------------------------------------------ +// Settings + +// Flag: Use fixed point arithmetic for IDCT? +//#define IDCT_FIXEDPT + +// Flag: Do we stop during scan decode if 0xFF (but not pad)? +// TODO: Make this a config option +//#define SCAN_BAD_MARKER_STOP + +// ------------------------------------------------------ +// Main code + +// Reset decoding state for start of new decode +// Note that we don't touch the DQT or DHT entries as +// those are set at different times versus reset (sometimes +// before Reset() ). +void CimgDecode::Reset() +{ + DecodeRestartScanBuf(0, false); + DecodeRestartDcState(); + + m_bRestartRead = false; // No restarts seen yet + m_nRestartRead = 0; + + m_nImgSizeXPartMcu = 0; + m_nImgSizeYPartMcu = 0; + m_nImgSizeX = 0; + m_nImgSizeY = 0; + m_nMcuXMax = 0; + m_nMcuYMax = 0; + m_nBlkXMax = 0; + m_nBlkYMax = 0; + + m_bBrightValid = false; + m_nBrightY = -32768; + m_nBrightCb = -32768; + m_nBrightCr = -32768; + m_nBrightR = 0; + m_nBrightG = 0; + m_nBrightB = 0; + m_ptBrightMcu.setX(0); + m_ptBrightMcu.setY(0); + + m_bAvgYValid = false; + m_nAvgY = 0; + + // If a DIB has been generated, release it! + if(m_bDibTempReady) + { +//@@ m_pDibTemp.Kill(); + m_bDibTempReady = false; + } + + if(m_bDibHistRgbReady) + { +//@@ m_pDibHistRgb.Kill(); + m_bDibHistRgbReady = false; + } + + if(m_bDibHistYReady) + { +//@@ m_pDibHistY.Kill(); + m_bDibHistYReady = false; + } + + if(m_pMcuFileMap) + { + delete[]m_pMcuFileMap; + m_pMcuFileMap = NULL; + } + + if(m_pBlkDcValY) + { + delete[]m_pBlkDcValY; + m_pBlkDcValY = NULL; + } + + if(m_pBlkDcValCb) + { + delete[]m_pBlkDcValCb; + m_pBlkDcValCb = NULL; + } + + if(m_pBlkDcValCr) + { + delete[]m_pBlkDcValCr; + m_pBlkDcValCr = NULL; + } + + if(m_pPixValY) + { + delete[]m_pPixValY; + m_pPixValY = NULL; + } + if(m_pPixValCb) + { + delete[]m_pPixValCb; + m_pPixValCb = NULL; + } + if(m_pPixValCr) + { + delete[]m_pPixValCr; + m_pPixValCr = NULL; + } + + // Haven't warned about anything yet + if(!m_bScanErrorsDisable) + { + m_nWarnBadScanNum = 0; + } + m_nWarnYccClipNum = 0; + + // Reset the view + m_nPreviewPosX = 0; + m_nPreviewPosY = 0; + m_nPreviewSizeX = 0; + m_nPreviewSizeY = 0; +} + +// Constructor for the Image Decoder +// - This constructor is called only once by Document class +CimgDecode::CimgDecode(CDocLog *pLog, CwindowBuf *pWBuf, QWidget *parent) : QWidget(parent) +{ + // Ideally this would be passed by constructor, but simply access directly for now. +// CJPEGsnoopApp *pApp; + +//@@ pApp = (CJPEGsnoopApp*)AfxGetApp(); +//@@ m_pAppConfig = pApp->m_pAppConfig; +//@@ Q_ASSERT(m_pAppConfig); + + m_bVerbose = false; + + Q_ASSERT(pLog); + Q_ASSERT(pWBuf); + m_pLog = pLog; + m_pWBuf = pWBuf; + + m_pStatBar = NULL; + m_bDibTempReady = false; + m_bPreviewIsJpeg = false; + m_bDibHistRgbReady = false; + m_bDibHistYReady = false; + + m_bHistEn = false; + m_bStatClipEn = false; // UNUSED + + m_pMcuFileMap = NULL; + m_pBlkDcValY = NULL; + m_pBlkDcValCb = NULL; + m_pBlkDcValCr = NULL; + m_pPixValY = NULL; + m_pPixValCb = NULL; + m_pPixValCr = NULL; + + // Reset the image decoding state + Reset(); + + m_nImgSizeXPartMcu = 0; + m_nImgSizeYPartMcu = 0; + m_nImgSizeX = 0; + m_nImgSizeY = 0; + + // FIXME: Temporary hack to avoid divide-by-0 when displaying PSD (instead of JPEG) + m_nMcuWidth = 1; + m_nMcuHeight = 1; + + // Detailed VLC Decode mode + m_bDetailVlc = false; + m_nDetailVlcX = 0; + m_nDetailVlcY = 0; + m_nDetailVlcLen = 1; + + m_bDecodeScanAc = true; + + m_sHisto.nClipYMin = 0; + + // Set up the IDCT lookup tables + PrecalcIdct(); + + GenLookupHuffMask(); + + // The following contain information that is set by + // the JFIF Decoder. We can only reset them here during + // the constructor and later by explicit call by JFIF Decoder. + ResetState(); + + // We don't call SetPreviewMode() here because it would + // automatically try to recalculate the view (but nothing ready yet) + m_nPreviewMode = PREVIEW_RGB; + SetPreviewZoom(false, false, true, PRV_ZOOM_12); + + m_bViewOverlaysMcuGrid = false; + + // Start off with no YCC offsets for CalcChannelPreview() + SetPreviewYccOffset(0, 0, 0, 0, 0); + + SetPreviewMcuInsert(0, 0, 0); + + setStyleSheet("background-color: white"); +} + +// Destructor for Image Decode class +// - Deallocate any image-related dynamic storage +CimgDecode::~CimgDecode() +{ + if(m_pMcuFileMap) + { + delete[]m_pMcuFileMap; + m_pMcuFileMap = NULL; + } + + if(m_pBlkDcValY) + { + delete[]m_pBlkDcValY; + m_pBlkDcValY = NULL; + } + if(m_pBlkDcValCb) + { + delete[]m_pBlkDcValCb; + m_pBlkDcValCb = NULL; + } + + if(m_pBlkDcValCr) + { + delete[]m_pBlkDcValCr; + m_pBlkDcValCr = NULL; + } + + if(m_pPixValY) + { + delete[]m_pPixValY; + m_pPixValY = NULL; + } + + if(m_pPixValCb) + { + delete[]m_pPixValCb; + m_pPixValCb = NULL; + } + + if(m_pPixValCr) + { + delete[]m_pPixValCr; + m_pPixValCr = NULL; + } +} + +// Reset the major parameters +// - Called by JFIF Decoder when we begin a new file +// TODO: Consider merging with Reset() +// POST: +// - m_anSofSampFactH[] +// - m_anSofSampFactV[] +// - m_bImgDetailsSet +// - m_nNumSofComps +// - m_nPrecision +// - m_bScanErrorsDisable +// - m_nMarkersBlkNum +// +void CimgDecode::ResetState() +{ + ResetDhtLookup(); + ResetDqtTables(); + + for(uint32_t nCompInd = 0; nCompInd < MAX_SOF_COMP_NF; nCompInd++) + { + m_anSofSampFactH[nCompInd] = 0; + m_anSofSampFactV[nCompInd] = 0; + } + + m_bImgDetailsSet = false; + m_nNumSofComps = 0; + + m_nPrecision = 0; // Default to "precision not set" + + m_bScanErrorsDisable = false; + + // Reset the markers + m_nMarkersBlkNum = 0; +} + +void CimgDecode::paintEvent(QPaintEvent *) +{ + int32_t top = 0; + + QRect bRect; + + QStyleOption opt; + opt.init(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); + p.setFont(QFont("Courier New", 14)); + + p.fillRect(0, 0, width(), height(), QColor(Qt::white)); + + if(m_bDibTempReady) + { + if(!m_bPreviewIsJpeg) + { + // For all non-JPEG images, report with simple title + m_strTitle = "Image"; + } + else + { + m_strTitle = "Image ("; + + switch (m_nPreviewMode) + { + case PREVIEW_RGB: + m_strTitle += "RGB"; + break; + + case PREVIEW_YCC: + m_strTitle += "YCC"; + break; + + case PREVIEW_R: + m_strTitle += "R"; + break; + + case PREVIEW_G: + m_strTitle += "G"; + break; + + case PREVIEW_B: + m_strTitle += "B"; + break; + + case PREVIEW_Y: + m_strTitle += "Y"; + break; + + case PREVIEW_CB: + m_strTitle += "Cb"; + break; + + case PREVIEW_CR: + m_strTitle += "Cr"; + break; + + default: + m_strTitle += "???"; + break; + } + + if(m_bDecodeScanAc) + { + m_strTitle += ", DC+AC)"; + } + else + { + m_strTitle += ", DC)"; + } + } + + switch (m_nZoomMode) + { + case PRV_ZOOM_12: + m_strTitle += " @ 12.5% (1/8)"; + break; + + case PRV_ZOOM_25: + m_strTitle += " @ 25% (1/4)"; + break; + + case PRV_ZOOM_50: + m_strTitle += " @ 50% (1/2)"; + break; + + case PRV_ZOOM_100: + m_strTitle += " @ 100% (1:1)"; + break; + + case PRV_ZOOM_150: + m_strTitle += " @ 150% (3:2)"; + break; + + case PRV_ZOOM_200: + m_strTitle += " @ 200% (2:1)"; + break; + + case PRV_ZOOM_300: + m_strTitle += " @ 300% (3:1)"; + break; + + case PRV_ZOOM_400: + m_strTitle += " @ 400% (4:1)"; + break; + + case PRV_ZOOM_800: + m_strTitle += " @ 800% (8:1)"; + break; + + default: + m_strTitle += ""; + break; + } + + // Draw image title + bRect = p.boundingRect(QRect(nTitleIndent, top, width(), 100), Qt::AlignLeft | Qt::AlignTop, m_strTitle); + p.drawText(bRect, Qt::AlignLeft | Qt::AlignCenter, m_strTitle); + + top = bRect.height() + nTitleLowGap; +// p.drawImage(nTitleIndent, top, m_pDibTemp->scaled(m_pDibTemp->width() / 4, m_pDibTemp->height() / 4, Qt::KeepAspectRatio)); + +// top += m_pDibTemp->height() + nTitleLowGap; + top += nTitleLowGap; + } + + if(m_bHistEn) + { + if(m_bDibHistRgbReady) + { + bRect = p.boundingRect(QRect(nTitleIndent, top, width(), 100), Qt::AlignLeft | Qt::AlignTop, "Histogram (RGB)"); + p.drawText(bRect, Qt::AlignLeft | Qt::AlignCenter, "Histogram (RGB)"); + + top += bRect.height() + nTitleLowGap; + p.drawImage(nTitleIndent, top, *m_pDibHistRgb); + top += m_pDibHistRgb->height() + nTitleLowGap; + } + + if(m_bDibHistYReady) + { + bRect = p.boundingRect(QRect(nTitleIndent, top, width(), 100), Qt::AlignLeft | Qt::AlignTop, "Histogram (Y)"); + p.drawText(bRect, Qt::AlignLeft | Qt::AlignCenter, "Histogram (Y)"); + + top += bRect.height() + nTitleLowGap; + p.drawImage(nTitleIndent, top, *m_pDibHistY); + } + } +} + +// Save a copy of the status bar control +// +// INPUT: +// - pStatBar = Pointer to status bar +// POST: +// - m_pStatBar +// +void CimgDecode::SetStatusBar(QStatusBar * pStatBar) +{ + m_pStatBar = pStatBar; +} + +// Update the status bar text +// +// INPUT: +// - str = New text to display on status bar +// PRE: +// - m_pStatBar +// +void CimgDecode::SetStatusText(QString str) +{ + // Make sure that we have been connected to the status + // bar of the main window first! Note that it is jpegsnoopDoc + // that sets this variable. + if(m_pStatBar) + { + m_pStatBar->showMessage(str); + } +} + +// Clears the DQT entries +// POST: +// - m_anDqtTblSel[] +// - m_anDqtCoeff[][] +// - m_anDqtCoeffZz[][] +void CimgDecode::ResetDqtTables() +{ + for(uint32_t nDqtComp = 0; nDqtComp < MAX_DQT_COMP; nDqtComp++) + { + // Force entries to an invalid value. This makes + // sure that we have to get a valid SetDqtTables() call + // from JfifDecode first. + m_anDqtTblSel[nDqtComp] = -1; + } + + for(uint32_t nDestId = 0; nDestId < MAX_DQT_DEST_ID; nDestId++) + { + for(uint32_t nCoeff = 0; nCoeff < MAX_DQT_COEFF; nCoeff++) + { + m_anDqtCoeff[nDestId][nCoeff] = 0; + m_anDqtCoeffZz[nDestId][nCoeff] = 0; + } + } + + m_nNumSofComps = 0; +} + +// Reset the DHT lookup tables +// - These tables are used to speed up VLC lookups +// - This should be called by the JFIF decoder any time we start a new file +// POST: +// - m_anDhtLookupSetMax[] +// - m_anDhtLookupSize[][] +// - m_anDhtLookup_bitlen[][][] +// - m_anDhtLookup_bits[][][] +// - m_anDhtLookup_code[][][] +// - m_anDhtLookupfast[][][] +// +void CimgDecode::ResetDhtLookup() +{ + memset(m_anDhtHisto, 0, sizeof(m_anDhtHisto)); + + // Use explicit loop ranges instead of memset + for(uint32_t nClass = DHT_CLASS_DC; nClass <= DHT_CLASS_AC; nClass++) + { + m_anDhtLookupSetMax[nClass] = 0; + // DHT table destination ID is range 0..3 + for(uint32_t nDestId = 0; nDestId < MAX_DHT_DEST_ID; nDestId++) + { + m_anDhtLookupSize[nClass][nDestId] = 0; + + for(uint32_t nCodeInd = 0; nCodeInd < MAX_DHT_CODES; nCodeInd++) + { + m_anDhtLookup_bitlen[nClass][nDestId][nCodeInd] = 0; + m_anDhtLookup_bits[nClass][nDestId][nCodeInd] = 0; + m_anDhtLookup_mask[nClass][nDestId][nCodeInd] = 0; + m_anDhtLookup_code[nClass][nDestId][nCodeInd] = 0; + } + + for(uint32_t nElem = 0; nElem < (2 << DHT_FAST_SIZE); nElem++) + { + // Mark with invalid value + m_anDhtLookupfast[nClass][nDestId][nElem] = DHT_CODE_UNUSED; + } + } + + for(uint32_t nCompInd = 0; nCompInd < 1 + MAX_SOS_COMP_NS; nCompInd++) + { + // Force entries to an invalid value. This makes + // sure that we have to get a valid SetDhtTables() call + // from JfifDecode first. + // Even though nCompInd is supposed to be 1-based numbering, + // we start at index 0 to ensure it is marked as invalid. + m_anDhtTblSel[nClass][nCompInd] = -1; + } + } + + m_nNumSosComps = 0; +} + +// Configure an entry in a quantization table +// +// INPUT: +// - nSet = Quant table dest ID (from DQT:Tq) +// - nInd = Coeff index (normal order) +// - nIndzz = Coeff index (zigzag order) +// - nCoeff = Coeff value +// POST: +// - m_anDqtCoeff[] +// - m_anDqtCoeffZz[] +// RETURN: +// - True if params in range, false otherwise +// +// NOTE: Asynchronously called by JFIF Decoder +// +bool CimgDecode::SetDqtEntry(uint32_t nTblDestId, uint32_t nCoeffInd, uint32_t nCoeffIndZz, uint16_t nCoeffVal) +{ + if((nTblDestId < MAX_DQT_DEST_ID) && (nCoeffInd < MAX_DQT_COEFF)) + { + m_anDqtCoeff[nTblDestId][nCoeffInd] = nCoeffVal; + + // Save a copy that represents the original zigzag order + // This is used by the IDCT logic + m_anDqtCoeffZz[nTblDestId][nCoeffIndZz] = nCoeffVal; + + } + else + { + // Should never get here! + QString strTmp; + + strTmp = QString("ERROR: Attempt to set DQT entry out of range (nTblDestId = %1, nCoeffInd = %2, nCoeffVal = %3") + .arg(nTblDestId) + .arg(nCoeffInd) + .arg(nCoeffVal); + +#ifdef DEBUG_LOG + QString strDebug; + + strDebug = QString("## File = %1 Block = %2 Error = %3") + .arg(m_pAppConfig->strCurFname, -100) + .arg("ImgDecode", -10) + .arg(strTmp); + qDebug() << strDebug; +#else + Q_ASSERT(false); +#endif + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return false; + } + + return true; +} + +// Fetch a DQT table entry +// +// INPUT: +// - nTblDestId = DQT Table Destination ID +// - nCoeffInd = Coefficient index in 8x8 matrix +// PRE: +// - m_anDqtCoeff[][] +// RETURN: +// - Returns the indexed DQT matrix entry +// +uint32_t CimgDecode::GetDqtEntry(uint32_t nTblDestId, uint32_t nCoeffInd) +{ + if((nTblDestId < MAX_DQT_DEST_ID) && (nCoeffInd < MAX_DQT_COEFF)) + { + return m_anDqtCoeff[nTblDestId][nCoeffInd]; + } + else + { + // Should never get here! + QString strTmp; + + strTmp = QString("ERROR: GetDqtEntry(nTblDestId = %1, nCoeffInd = %2").arg(nTblDestId).arg(nCoeffInd); + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + +#ifdef DEBUG_LOG + qDebug() << QString("## File = %1 Block = %2 Error = %3").arg(m_pAppConfig->strCurFname).arg("ImgDecode").arg(strTmp); +#else + Q_ASSERT(false); +#endif + + return 0; + } +} + +// Set a DQT table for a frame image component identifier +// +// INPUT: +// - nCompInd = Component index. Based on m_nSofNumComps_Nf-1 (ie. 0..254) +// - nTbl = DQT Table number. Based on SOF:Tqi (ie. 0..3) +// POST: +// - m_anDqtTblSel[] +// RETURN: +// - Success if index and table are in range +// NOTE: +// - Asynchronously called by JFIF Decoder +// +bool CimgDecode::SetDqtTables(uint32_t nCompId, uint32_t nTbl) +{ + QString strTmp; + + if((nCompId < MAX_SOF_COMP_NF) && (nTbl < MAX_DQT_DEST_ID)) + { + m_anDqtTblSel[nCompId] = static_cast(nTbl); + } + else + { + // Should never get here unless the JFIF SOF table has a bad entry! + strTmp = QString("ERROR: SetDqtTables(Comp ID = %1, Table = %2") + .arg(nCompId) + .arg(nTbl); + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return false; + } + + return true; +} + +// Set a DHT table for a scan image component index +// - The DHT Table select array is stored as: +// m_anDhtTblSel[0][1,2,3] for DC +// m_anDhtTblSel[1][1,2,3] for AC +// +// INPUT: +// - nCompInd = Component index (1-based). Range 1..4 +// - nTblDc = DHT table index for DC elements of component +// - nTblAc = DHT table index for AC elements of component +// POST: +// - m_anDhtTblSel[][] +// RETURN: +// - Success if indices are in range +// +bool CimgDecode::SetDhtTables(uint32_t nCompInd, uint32_t nTblDc, uint32_t nTblAc) +{ + QString strTmp; + + // Note use of (nCompInd < MAX_SOS_COMP_NS+1) as nCompInd is 1-based notation + if((nCompInd >= 1) && (nCompInd < MAX_SOS_COMP_NS + 1) && (nTblDc < MAX_DHT_DEST_ID) && (nTblAc < MAX_DHT_DEST_ID)) + { + m_anDhtTblSel[DHT_CLASS_DC][nCompInd] = static_cast(nTblDc); + m_anDhtTblSel[DHT_CLASS_AC][nCompInd] = static_cast(nTblAc); + } + else + { + // Should never get here! + strTmp = QString("ERROR: SetDhtTables(comp = %1, TblDC = %2 TblAC = %3) out of indexed range") + .arg(nCompInd) + .arg(nTblDc) + .arg(nTblAc); + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return false; + } + + return true; +} + +// Get the precision field +// +// INPUT: +// - nPrecision = DCT sample precision (typically 8 or 12) +// POST: +// - m_nPrecision +// +void CimgDecode::SetPrecision(uint32_t nPrecision) +{ + m_nPrecision = nPrecision; +} + +// Set the general image details for the image decoder +// +// INPUT: +// - nDimX = Image dimension (X) +// - nDimY = Image dimension (Y) +// - nCompsSOF = Number of components in Frame +// - nCompsSOS = Number of components in Scan +// - bRstEn = Restart markers present? +// - nRstInterval = Restart marker interval +// POST: +// - m_bImgDetailsSet +// - m_nDimX +// - m_nDimY +// - m_nNumSofComps +// - m_nNumSosComps +// - m_bRestartEn +// - m_nRestartInterval +// NOTE: +// - Called asynchronously by the JFIF decoder +// +void CimgDecode::SetImageDetails(uint32_t nDimX, uint32_t nDimY, uint32_t nCompsSOF, uint32_t nCompsSOS, bool bRstEn, + uint32_t nRstInterval) +{ + m_bImgDetailsSet = true; + m_nDimX = nDimX; + m_nDimY = nDimY; + m_nNumSofComps = nCompsSOF; + m_nNumSosComps = nCompsSOS; + m_bRestartEn = bRstEn; + m_nRestartInterval = nRstInterval; +} + +// Reset the image content to prepare it for the upcoming scans +// - TODO: Migrate pixel bitmap allocation / clearing from DecodeScanImg() to here +void CimgDecode::ResetImageContent() +{ +} + +// Set the sampling factor for an image component +// +// INPUT: +// - nCompInd = Component index from Nf (ie. 1..255) +// - nSampFactH = Sampling factor in horizontal direction +// - nSampFactV = Sampling factor in vertical direction +// POST: +// - m_anSofSampFactH[] +// - m_anSofSampFactV[] +// NOTE: +// - Called asynchronously by the JFIF decoder in SOF +// +void CimgDecode::SetSofSampFactors(uint32_t nCompInd, uint32_t nSampFactH, uint32_t nSampFactV) +{ + // TODO: Check range + m_anSofSampFactH[nCompInd] = nSampFactH; + m_anSofSampFactV[nCompInd] = nSampFactV; +} + +// Update the preview mode (affects channel display) +// +// INPUT: +// - nMode = Mode used in channel display (eg. NONE, RGB, YCC) +// See PREVIEW_* constants +// +void CimgDecode::SetPreviewMode(uint32_t nMode) +{ + // Need to check to see if mode has changed. If so, we + // need to recalculate the temporary preview. + m_nPreviewMode = nMode; + CalcChannelPreview(); +} + +// Update any level shifts for the preview display +// +// INPUT: +// - nMcuX = MCU index in X direction +// - nMcuY = MCU index in Y direction +// - nY = DC shift in Y component +// - nCb = DC shift in Cb component +// - nCr = DC shift in Cr component +// +void CimgDecode::SetPreviewYccOffset(uint32_t nMcuX, uint32_t nMcuY, int32_t nY, int32_t nCb, int32_t nCr) +{ + m_nPreviewShiftY = nY; + m_nPreviewShiftCb = nCb; + m_nPreviewShiftCr = nCr; + m_nPreviewShiftMcuX = nMcuX; + m_nPreviewShiftMcuY = nMcuY; + + CalcChannelPreview(); +} + +// Fetch the current level shift setting for the preview display +// +// OUTPUT: +// - nMcuX = MCU index in X direction +// - nMcuY = MCU index in Y direction +// - nY = DC shift in Y component +// - nCb = DC shift in Cb component +// - nCr = DC shift in Cr component +// +void CimgDecode::GetPreviewYccOffset(uint32_t &nMcuX, uint32_t &nMcuY, int32_t &nY, int32_t &nCb, int32_t &nCr) +{ + nY = m_nPreviewShiftY; + nCb = m_nPreviewShiftCb; + nCr = m_nPreviewShiftCr; + nMcuX = m_nPreviewShiftMcuX; + nMcuY = m_nPreviewShiftMcuY; +} + +// Set the Preview MCU insert +// UNUSED +void CimgDecode::SetPreviewMcuInsert(uint32_t nMcuX, uint32_t nMcuY, int32_t nLen) +{ + + m_nPreviewInsMcuX = nMcuX; + m_nPreviewInsMcuY = nMcuY; + m_nPreviewInsMcuLen = nLen; + + CalcChannelPreview(); +} + +// Get the Preview MCU insert +// UNUSED +void CimgDecode::GetPreviewMcuInsert(uint32_t &nMcuX, uint32_t &nMcuY, uint32_t &nLen) +{ + nMcuX = m_nPreviewInsMcuX; + nMcuY = m_nPreviewInsMcuY; + nLen = m_nPreviewInsMcuLen; +} + +// Fetch the coordinate of the top-left corner of the preview image +// +// OUTPUT: +// - nX = X coordinate of top-left corner +// - nY = Y coordinate of top-left corner +// +void CimgDecode::GetPreviewPos(uint32_t &nX, uint32_t &nY) +{ + nX = m_nPreviewPosX; + nY = m_nPreviewPosY; +} + +// Fetch the dimensions of the preview image +// +// OUTPUT: +// - nX = X dimension of image +// - nY = Y dimension of iamge +// +void CimgDecode::GetPreviewSize(uint32_t &nX, uint32_t &nY) +{ + nX = m_nPreviewSizeX; + nY = m_nPreviewSizeY; +} + +// Set a DHT table entry and associated lookup table +// - Configures the fast lookup table for short code bitstrings +// +// INPUT: +// - nDestId = DHT destination table ID (0..3) +// - nClass = Select between DC and AC tables (0=DC, 1=AC) +// - nInd = Index into table +// - nLen = Huffman code length +// - nBits = Huffman code bitstring (left justified) +// - nMask = Huffman code bit mask (left justified) +// - nCode = Huffman code value +// POST: +// - m_anDhtLookup_bitlen[][][] +// - m_anDhtLookup_bits[][][] +// - m_anDhtLookup_mask[][][] +// - m_anDhtLookup_code[][][] +// - m_anDhtLookupSetMax[] +// - m_anDhtLookupfast[][][] +// RETURN: +// - Success if indices are in range +// NOTE: +// - Asynchronously called by JFIF Decoder +// +bool CimgDecode::SetDhtEntry(uint32_t nDestId, uint32_t nClass, uint32_t nInd, uint32_t nLen, + uint32_t nBits, uint32_t nMask, uint32_t nCode) +{ + if((nDestId >= MAX_DHT_DEST_ID) || (nClass >= MAX_DHT_CLASS) || (nInd >= MAX_DHT_CODES)) + { + QString strTmp = "ERROR: Attempt to set DHT entry out of range"; + + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } +#ifdef DEBUG_LOG + QString strDebug; + + strDebug = QString("## File = %1 Block = %2 Error = %3") + .arg(m_pAppConfig->strCurFname, -100) + .arg("ImgDecode", -10) + .arg(strTmp); + qDebug() << strDebug; +#else + Q_ASSERT(false); +#endif + return false; + } + + m_anDhtLookup_bitlen[nClass][nDestId][nInd] = nLen; + m_anDhtLookup_bits[nClass][nDestId][nInd] = nBits; + m_anDhtLookup_mask[nClass][nDestId][nInd] = nMask; + m_anDhtLookup_code[nClass][nDestId][nInd] = nCode; + + // Record the highest numbered DHT set. + // TODO: Currently assuming that there are no missing tables in the sequence + if(nDestId > m_anDhtLookupSetMax[nClass]) + { + m_anDhtLookupSetMax[nClass] = nDestId; + } + + uint32_t nBitsMsb; + uint32_t nBitsExtraLen; + uint32_t nBitsExtraVal; + uint32_t nBitsMax; + uint32_t nFastVal; + + // If the variable-length code is short enough, add it to the + // fast lookup table. + if(nLen <= DHT_FAST_SIZE) + { + // nBits is a left-justified number (assume right-most bits are zero) + // nLen is number of leading bits to compare + + // nLen = 5 + // nBits = 32'b1011_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx (0xB800_0000) + // nBitsMsb = 8'b1011_1xxx (0xB8) + // nBitsMsb = 8'b1011_1000 (0xB8) + // nBitsMax = 8'b1011_1111 (0xBF) + + // nBitsExtraLen = 8-len = 8-5 = 3 + + // nBitsExtraVal = (1<> (32 - DHT_FAST_SIZE); + nBitsExtraLen = DHT_FAST_SIZE - nLen; + nBitsExtraVal = (1 << nBitsExtraLen) - 1; + nBitsMax = nBitsMsb + nBitsExtraVal; + + for(uint32_t ind1 = nBitsMsb; ind1 <= nBitsMax; ind1++) + { + // The arrangement of the dht_lookupfast[] values: + // 0xFFFF_FFFF = No entry, resort to slow search + // m_anDhtLookupfast[nClass][nDestId] [15: 8] = nLen + // m_anDhtLookupfast[nClass][nDestId] [ 7: 0] = nCode + // + //Q_ASSERT(code <= 0xFF); + //Q_ASSERT(ind1 <= 0xFF); + nFastVal = nCode + (nLen << 8); + m_anDhtLookupfast[nClass][nDestId][ind1] = nFastVal; + } + } + + return true; +} + +// Assign the size of the DHT table +// +// INPUT: +// - nDestId = Destination DHT table ID (From DHT:Th, range 0..3) +// - nClass = Select between DC and AC tables (0=DC, 1=AC) (From DHT:Tc, range 0..1) +// - nSize = Number of entries in the DHT table +// POST: +// - m_anDhtLookupSize[][] +// RETURN: +// - Success if indices are in range +// +bool CimgDecode::SetDhtSize(uint32_t nDestId, uint32_t nClass, uint32_t nSize) +{ + if((nDestId >= MAX_DHT_DEST_ID) || (nClass >= MAX_DHT_CLASS) || (nSize >= MAX_DHT_CODES)) + { + QString strTmp = "ERROR: Attempt to set DHT table size out of range"; + + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return false; + } + else + { + m_anDhtLookupSize[nClass][nDestId] = nSize; + } + + return true; +} + +// Convert huffman code (DC) to signed value +// - Convert according to ITU-T.81 Table 5 +// +// INPUT: +// - nVal = Huffman DC value (left justified) +// - nBits = Bitstring length of value +// RETURN: +// - Signed integer representing Huffman DC value +// +int32_t CimgDecode::HuffmanDc2Signed(uint32_t nVal, uint32_t nBits) +{ + if(nVal >= (1 << (nBits - 1))) + { + return static_cast(nVal); + } + else + { + return static_cast(nVal - ((1 << nBits) - 1)); + } +} + +// Generate the Huffman code lookup table mask +// +// POST: +// - m_anHuffMaskLookup[] +// +void CimgDecode::GenLookupHuffMask() +{ + uint32_t nMask; + + for(uint32_t nLen = 0; nLen < 32; nLen++) + { + nMask = (1 << (nLen)) - 1; + nMask <<= 32 - nLen; + m_anHuffMaskLookup[nLen] = nMask; + } +} + +// Extract a specified number of bits from a 32-bit holding register +// +// INPUT: +// - nWord = The 32-bit holding register +// - nBits = Number of bits (leftmost) to extract from the holding register +// PRE: +// - m_anHuffMaskLookup[] +// RETURN: +// - The subset of bits extracted from the holding register +// NOTE: +// - This routine is inlined for speed +// +inline uint32_t CimgDecode::ExtractBits(uint32_t nWord, uint32_t nBits) +{ + uint32_t nVal; + + nVal = (nWord & m_anHuffMaskLookup[nBits]) >> (32 - nBits); + return nVal; +} + +// Removes bits from the holding buffer +// - Discard the leftmost "nNumBits" of m_nScanBuff +// - And then realign file position pointers +// +// INPUT: +// - nNumBits = Number of left-most bits to consume +// POST: +// - m_nScanBuff +// - m_nScanBuff_vacant +// - m_nScanBuffPtr_align +// - m_anScanBuffPtr_pos[] +// - m_anScanBuffPtr_err[] +// - m_nScanBuffLatchErr +// - m_nScanBuffPtr_num +// +inline void CimgDecode::ScanBuffConsume(uint32_t nNumBits) +{ + m_nScanBuff <<= nNumBits; + m_nScanBuff_vacant += nNumBits; + + // Need to latch any errors during consumption of multi-bytes + // otherwise we'll miss the error notification if we skip over + // it before we exit this routine! e.g if num_bytes=2 and error + // appears on first byte, then we want to retain it in pos[0] + + // Now realign the file position pointers if necessary + uint32_t nNumBytes = (m_nScanBuffPtr_align + nNumBits) / 8; + + for(uint32_t nInd = 0; nInd < nNumBytes; nInd++) + { + m_anScanBuffPtr_pos[0] = m_anScanBuffPtr_pos[1]; + m_anScanBuffPtr_pos[1] = m_anScanBuffPtr_pos[2]; + m_anScanBuffPtr_pos[2] = m_anScanBuffPtr_pos[3]; + // Don't clear the last ptr position because during an overread + // this will be the only place that the last position was preserved + //m_anScanBuffPtr_pos[3] = 0; + + m_anScanBuffPtr_err[0] = m_anScanBuffPtr_err[1]; + m_anScanBuffPtr_err[1] = m_anScanBuffPtr_err[2]; + m_anScanBuffPtr_err[2] = m_anScanBuffPtr_err[3]; + m_anScanBuffPtr_err[3] = SCANBUF_OK; + + if(m_anScanBuffPtr_err[0] != SCANBUF_OK) + { + m_nScanBuffLatchErr = m_anScanBuffPtr_err[0]; + } + + m_nScanBuffPtr_num--; + } + + m_nScanBuffPtr_align = (m_nScanBuffPtr_align + nNumBits) % 8; +} + +// Augment the current scan buffer with another byte +// - Extra bits are added to right side of existing bitstring +// +// INPUT: +// - nNewByte = 8-bit byte to add to buffer +// - nPtr = UNUSED +// PRE: +// - m_nScanBuff +// - m_nScanBuff_vacant +// - m_nScanBuffPtr_num +// POST: +// - m_nScanBuff +// - m_nScanBuff_vacant +// - m_anScanBuffPtr_err[] +// - m_anScanBuffPtr_pos[] +// +inline void CimgDecode::ScanBuffAdd(uint32_t nNewByte, uint32_t nPtr) +{ + // Add the new byte to the buffer + // Assume that m_nScanBuff has already been shifted to be + // aligned to bit 31 as first bit. + m_nScanBuff += (nNewByte << (m_nScanBuff_vacant - 8)); + m_nScanBuff_vacant -= 8; + + Q_ASSERT(m_nScanBuffPtr_num < 4); + + if(m_nScanBuffPtr_num >= 4) + { + return; + } // Unexpected by design + + m_anScanBuffPtr_err[m_nScanBuffPtr_num] = SCANBUF_OK; + m_anScanBuffPtr_pos[m_nScanBuffPtr_num++] = nPtr; + + // m_nScanBuffPtr_align stays the same as we add 8 bits +} + +// Augment the current scan buffer with another byte (but mark as error) +// +// INPUT: +// - nNewByte = 8-bit byte to add to buffer +// - nPtr = UNUSED +// - nErr = Error code to associate with this buffer byte +// POST: +// - m_anScanBuffPtr_err[] +// +inline void CimgDecode::ScanBuffAddErr(uint32_t nNewByte, uint32_t nPtr, uint32_t nErr) +{ + ScanBuffAdd(nNewByte, nPtr); + m_anScanBuffPtr_err[m_nScanBuffPtr_num - 1] = nErr; +} + +// Disable any further reporting of scan errors +// +// PRE: +// - m_nScanErrMax +// POST: +// - m_nWarnBadScanNum +// - m_bScanErrorsDisable +// +void CimgDecode::ScanErrorsDisable() +{ + m_nWarnBadScanNum = m_nScanErrMax; + m_bScanErrorsDisable = true; +} + +// Enable reporting of scan errors +// +// POST: +// - m_nWarnBadScanNum +// - m_bScanErrorsDisable +// +void CimgDecode::ScanErrorsEnable() +{ + m_nWarnBadScanNum = 0; + m_bScanErrorsDisable = false; +} + +// Read in bits from the buffer and find matching huffman codes +// - Input buffer is m_nScanBuff +// - Perform shift in buffer afterwards +// - Abort if there aren't enough bits (note that the scan buffer +// is almost empty when we reach the end of a scan segment) +// +// INPUT: +// - nClass = DHT Table class (0..1) +// - nTbl = DHT Destination ID (0..3) +// PRE: +// - Assume that dht_lookup_size[nTbl] != 0 (already checked) +// - m_bRestartRead +// - m_nScanBuff_vacant +// - m_nScanErrMax +// - m_nScanBuff +// - m_anDhtLookupFast[][][] +// - m_anDhtLookupSize[][] +// - m_anDhtLookup_mask[][][] +// - m_anDhtLookup_bits[][][] +// - m_anDhtLookup_bitlen[][][] +// - m_anDhtLookup_code[][][] +// - m_nPrecision +// POST: +// - m_nScanBitsUsed# is calculated +// - m_bScanEnd +// - m_bScanBad +// - m_nWarnBadScanNum +// - m_anDhtHisto[][][] +// OUTPUT: +// - rZrl = Zero run amount (if any) +// - rVal = Coefficient value +// RETURN: +// - Status from attempting to decode the current value +// +// PERFORMANCE: +// - Tried to unroll all function calls listed below, +// but performance was same before & after (27sec). +// - Calls unrolled: BuffTopup(), ScanBuffConsume(), +// ExtractBits(), HuffmanDc2Signed() +teRsvRet CimgDecode::ReadScanVal(uint32_t nClass, uint32_t nTbl, uint32_t &rZrl, int32_t &rVal) +{ + bool bDone = false; + + uint32_t nInd = 0; + + uint32_t nCode = DHT_CODE_UNUSED; // Not a valid nCode + + uint32_t nVal; + + Q_ASSERT(nClass < MAX_DHT_CLASS); + Q_ASSERT(nTbl < MAX_DHT_DEST_ID); + + m_nScanBitsUsed1 = 0; // bits consumed for nCode + m_nScanBitsUsed2 = 0; + + rZrl = 0; + rVal = 0; + + // First check to see if we've entered here with a completely empty + // scan buffer with a restart marker already observed. In that case + // we want to exit with condition 3 (restart terminated) + if((m_nScanBuff_vacant == 32) && (m_bRestartRead)) + { + return RSV_RST_TERM; + } + + // Has the scan buffer been depleted? + if(m_nScanBuff_vacant >= 32) + { + // Trying to overread end of scan segment + + if(m_nWarnBadScanNum < m_nScanErrMax) + { + QString strTmp; + + strTmp = QString("*** ERROR: Overread scan segment (before nCode)! @ Offset: %1").arg(GetScanBufPos()); + m_pLog->AddLineErr(strTmp); + + m_nWarnBadScanNum++; + + if(m_nWarnBadScanNum >= m_nScanErrMax) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(m_nScanErrMax); + m_pLog->AddLineErr(strTmp); + } + } + + m_bScanEnd = true; + m_bScanBad = true; + return RSV_UNDERFLOW; + } + + // Top up the buffer just in case + BuffTopup(); + + bDone = false; + bool bFound = false; + + // Fast search for variable-length huffman nCode + // Do direct lookup for any codes DHT_FAST_SIZE bits or shorter + + uint32_t nCodeMsb; + + uint32_t nCodeFastSearch; + + // Only enable this fast search if m_nScanBuff_vacant implies + // that we have at least DHT_FAST_SIZE bits available in the buffer! + if((32 - m_nScanBuff_vacant) >= DHT_FAST_SIZE) + { + nCodeMsb = m_nScanBuff >> (32 - DHT_FAST_SIZE); + nCodeFastSearch = m_anDhtLookupfast[nClass][nTbl][nCodeMsb]; + + if(nCodeFastSearch != DHT_CODE_UNUSED) + { + // We found the code! + m_nScanBitsUsed1 += (nCodeFastSearch >> 8); + nCode = (nCodeFastSearch & 0xFF); + bDone = true; + bFound = true; + } + } + + // Slow search for variable-length huffman nCode + while(!bDone) + { + uint32_t nBitLen; + + if((m_nScanBuff & m_anDhtLookup_mask[nClass][nTbl][nInd]) == m_anDhtLookup_bits[nClass][nTbl][nInd]) + { + + nBitLen = m_anDhtLookup_bitlen[nClass][nTbl][nInd]; + + // Just in case this VLC bit string is longer than the number of + // bits we have left in the buffer (due to restart marker or end + // of scan data), we need to double-check + if(nBitLen <= 32 - m_nScanBuff_vacant) + { + nCode = m_anDhtLookup_code[nClass][nTbl][nInd]; + m_nScanBitsUsed1 += nBitLen; + bDone = true; + bFound = true; + } + } + + nInd++; + + if(nInd >= m_anDhtLookupSize[nClass][nTbl]) + { + bDone = true; + } + } + + // Could not find huffman nCode in table! + if(!bFound) + { + // If we didn't find the huffman nCode, it might be due to a + // restart marker that prematurely stopped the scan buffer filling. + // If so, return with an indication so that DecodeScanComp() can + // handle the restart marker, refill the scan buffer and then + // re-do ReadScanVal() + if(m_bRestartRead) + { + return RSV_RST_TERM; + } + + // FIXME: + // What should we be consuming here? we need to make forward progress + // in file. Options: + // 1) Move forward to next byte in file + // 2) Move forward to next bit in file + // Currently moving 1 bit so that we have slightly more opportunities + // to re-align earlier. + m_nScanBitsUsed1 = 1; + nCode = DHT_CODE_UNUSED; + } + + // Log an entry into a histogram + if(m_nScanBitsUsed1 < MAX_DHT_CODELEN + 1) + { + m_anDhtHisto[nClass][nTbl][m_nScanBitsUsed1]++; + } + else + { + Q_ASSERT(false); + // Somehow we got out of range + } + + ScanBuffConsume(m_nScanBitsUsed1); + + // Did we overread the scan buffer? + if(m_nScanBuff_vacant > 32) + { + // The nCode consumed more bits than we had! + QString strTmp; + + strTmp = QString("*** ERROR: Overread scan segment (after nCode)! @ Offset: %1").arg(GetScanBufPos()); + m_pLog->AddLineErr(strTmp); + m_bScanEnd = true; + m_bScanBad = true; + return RSV_UNDERFLOW; + } + + // Replenish buffer after nCode extraction and before variable extra bits + // This is required because we may have a 12 bit nCode followed by a 16 bit var length bitstring + BuffTopup(); + + // Did we find the nCode? + if(nCode != DHT_CODE_UNUSED) + { + rZrl = (nCode & 0xF0) >> 4; + m_nScanBitsUsed2 = nCode & 0x0F; + + if((rZrl == 0) && (m_nScanBitsUsed2 == 0)) + { + // EOB (was bits_extra=0) + return RSV_EOB; + } + else if(m_nScanBitsUsed2 == 0) + { + // Zero rValue + rVal = 0; + return RSV_OK; + + } + else + { + // Normal nCode + nVal = ExtractBits(m_nScanBuff, m_nScanBitsUsed2); + rVal = HuffmanDc2Signed(nVal, m_nScanBitsUsed2); + + // Now handle the different precision values + // Treat 12-bit like 8-bit but scale values first (ie. drop precision down to 8-bit) + int32_t nPrecisionDivider = 1; + + if(m_nPrecision >= 8) + { + nPrecisionDivider = 1 << (m_nPrecision - 8); + rVal /= nPrecisionDivider; + } + else + { + // Precision value seems out of range! + } + + ScanBuffConsume(m_nScanBitsUsed2); + + // Did we overread the scan buffer? + if(m_nScanBuff_vacant > 32) + { + // The nCode consumed more bits than we had! + QString strTmp; + + strTmp = QString("*** ERROR: Overread scan segment (after bitstring)! @ Offset: %1").arg(GetScanBufPos()); + m_pLog->AddLineErr(strTmp); + m_bScanEnd = true; + m_bScanBad = true; + return RSV_UNDERFLOW; + } + + return RSV_OK; + } + } + else + { + // ERROR: Invalid huffman nCode! + + // FIXME: We may also enter here if we are about to encounter a + // restart marker! Need to see if ScanBuf is terminated by + // restart marker; if so, then we simply flush the ScanBuf, + // consume the 2-byte RST marker, clear the ScanBuf terminate + // reason, then indicate to caller that they need to call ReadScanVal + // again. + + if(m_nWarnBadScanNum < m_nScanErrMax) + { + QString strTmp; + + strTmp = + QString("*** ERROR: Can't find huffman bitstring @ %1, table %2, value 0x%3").arg(GetScanBufPos()).arg(nTbl). + arg(m_nScanBuff, 8, 16, QChar('0')); + m_pLog->AddLineErr(strTmp); + + m_nWarnBadScanNum++; + + if(m_nWarnBadScanNum >= m_nScanErrMax) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(m_nScanErrMax); + m_pLog->AddLineErr(strTmp); + } + } + + // TODO: What rValue and ZRL should we return? + m_bScanBad = true; + return RSV_UNDERFLOW; + } + + // NOTE: Can't reach here + // return RSV_UNDERFLOW; +} + +// Refill the scan buffer as needed +// +void CimgDecode::BuffTopup() +{ + uint32_t nRetVal; + + // Do we have space to load another byte? + bool bDone = (m_nScanBuff_vacant < 8); + + // Have we already reached the end of the scan segment? + if(m_bScanEnd) + { + bDone = true; + } + + while(!bDone) + { + nRetVal = BuffAddByte(); + + // NOTE: If we have read in a restart marker, the above call will not + // read in any more bits into the scan buffer, so we should just simply + // say that we've done the best we can for the top up. + if(m_bRestartRead) + { + bDone = true; + } + + if(m_nScanBuff_vacant < 8) + { + bDone = true; + } + + // If the buffer read returned an error or end of scan segment + // then stop filling buffer + if(nRetVal != 0) + { + bDone = true; + } + } +} + +// Check for restart marker and compare the index against expected +// +// PRE: +// - m_nScanBuffPtr +// RETURN: +// - Restart marker found at the current buffer position +// NOTE: +// - This routine expects that we did not remove restart markers +// from the bytestream (in BuffAddByte). +// +bool CimgDecode::ExpectRestart() +{ + uint32_t nMarker; + uint32_t nBuf0 = m_pWBuf->Buf(m_nScanBuffPtr); + uint32_t nBuf1 = m_pWBuf->Buf(m_nScanBuffPtr + 1); + + // Check for restart marker first. Assume none back-to-back. + if(nBuf0 == 0xFF) + { + nMarker = nBuf1; + + // FIXME: Later, check that we are on the right marker! + if((nMarker >= JFIF_RST0) && (nMarker <= JFIF_RST7)) + { + if(m_bVerbose) + { + QString strTmp; + + strTmp = + QString(" RESTART marker: @ 0x%1.0 : RST%2") + .arg(m_nScanBuffPtr, 8, 16, QChar('0')) + .arg(nMarker - JFIF_RST0, 2, 10, QChar('0')); + m_pLog->AddLine(strTmp); + } + + m_nRestartRead++; + + // FIXME: + // Later on, we should be checking for RST out of + // sequence! + + // Now we need to skip to the next bytes + m_nScanBuffPtr += 2; + + // Now refill in the buffer if we need to + BuffAddByte(); + + return true; + } + } + + return false; +} + +// Add a byte to the scan buffer from the file +// - Handle stuff bytes +// - Handle restart markers +// +// PRE: +// - m_nScanBuffPtr +// POST: +// - m_nRestartRead +// - m_nRestartLastInd +// +uint32_t CimgDecode::BuffAddByte() +{ + uint32_t nMarker = 0x00; + uint32_t nBuf0, nBuf1; + + // If we have already read in a restart marker but not + // handled it yet, then simply return without reading any + // more bytes + if(m_bRestartRead) + { + return 0; + } + + nBuf0 = m_pWBuf->Buf(m_nScanBuffPtr); + nBuf1 = m_pWBuf->Buf(m_nScanBuffPtr + 1); + + // Check for restart marker first. Assume none back-to-back. + if(nBuf0 == 0xFF) + { + nMarker = nBuf1; + + if((nMarker >= JFIF_RST0) && (nMarker <= JFIF_RST7)) + { + if(m_bVerbose) + { + QString strTmp; + + strTmp = + QString(" RESTART marker: @ 0x%1.0 : RST%2") + .arg(m_nScanBuffPtr, 8, 16, QChar('0')) + .arg(nMarker - JFIF_RST0, 2, 10, QChar('0')); + m_pLog->AddLine(strTmp); + } + + m_nRestartRead++; + m_nRestartLastInd = nMarker - JFIF_RST0; + + if(m_nRestartLastInd != m_nRestartExpectInd) + { + if(!m_bScanErrorsDisable) + { + QString strTmp; + + strTmp = + QString(" ERROR: Expected RST marker index RST%1 got RST%2 @ 0x%3.0") + .arg(m_nRestartExpectInd) + .arg(m_nRestartLastInd) + .arg(m_nScanBuffPtr, 8, 16, QChar('0')); + m_pLog->AddLineErr(strTmp); + } + } + + m_nRestartExpectInd = (m_nRestartLastInd + 1) % 8; + + // FIXME: Later on, we should be checking for RST out of sequence + + // END BUFFER READ HERE! + // Indicate that a Restart marker has been seen, which + // will prevent further reading of scan buffer until it + // has been handled. + m_bRestartRead = true; + + return 0; + +/* + // Now we need to skip to the next bytes + m_nScanBuffPtr+=2; + + // Update local saved buffer vars + nBuf0 = m_pWBuf->Buf(m_nScanBuffPtr); + nBuf1 = m_pWBuf->Buf(m_nScanBuffPtr+1); + + // Use ScanBuffAddErr() to mark this byte as being after Restart marker! + m_anScanBuffPtr_err[m_nScanBuffPtr_num] = SCANBUF_RST; + + // FIXME: We should probably discontinue filling the scan + // buffer if we encounter a restart marker. This will stop us + // from reading past the restart marker and missing the necessary + // step in resetting the decoder accumulation state. + + // When we stop adding bytes to the buffer, we should also + // mark this scan buffer with a flag to indicate that it was + // ended by RST not by EOI or an Invalid Marker. + + // If the main decoder (in ReadScanVal) cannot find a VLC code + // match with the few bits left in the scan buffer + // (presumably padded with 1's), then it should check to see + // if the buffer is terminated by RST. If so, then it + // purges the scan buffer, advances to the next byte (after the + // RST marker) and does a fill, then re-invokes the ReadScanVal + // routine. At the level above, the Decoder that is calling + // ReadScanVal should be counting MCU rows and expect this error + // from ReadScanVal (no code match and buf terminated by RST). + // If it happened out of place, we have corruption somehow! + + // See IJG Code: + // jdmarker.c: + // read_restart_marker() + // jpeg_resync_to_restart() +*/ + } + } + + // Check for byte Stuff + if((nBuf0 == 0xFF) && (nBuf1 == 0x00)) + { + // Add byte to m_nScanBuff & record file position + ScanBuffAdd(nBuf0, m_nScanBuffPtr); + m_nScanBuffPtr += 2; + } + else if((nBuf0 == 0xFF) && (nBuf1 == 0xFF)) + { + // NOTE: + // We should be checking for a run of 0xFF before EOI marker. + // It is possible that we could get marker padding on the end + // of the scan segment, so we'd want to handle it here, otherwise + // we'll report an error that we got a non-EOI Marker in scan + // segment. + + // The downside of this is that we don't detect errors if we have + // a run of 0xFF in the stream, until we leave the string of FF's. + // If it were followed by an 0x00, then we may not notice it at all. + // Probably OK. + + /* + if (m_nWarnBadScanNum < m_nScanErrMax) { + QString strTmp; + strTmp = QString(" Scan Data encountered sequence 0xFFFF @ 0x%08X.0 - Assume start of marker pad at end of scan segment", + m_nScanBuffPtr); + m_pLog->AddLineWarn(strTmp); + + m_nWarnBadScanNum++; + if (m_nWarnBadScanNum >= m_nScanErrMax) { + strTmp = QString(" Only reported first %u instances of this message..."),m_nScanErrMax; + m_pLog->AddLineErr(strTmp); + } + } + + // Treat as single byte of byte stuff for now, since we don't + // know if FF bytes will arrive in pairs or not. + m_nScanBuffPtr+=1; + */ + + // NOTE: + // If I treat the 0xFFFF as a potential marker pad, we may not stop correctly + // upon error if we see this inside the image somewhere (not at end). + // Therefore, let's simply add these bytes to the buffer and let the DecodeScanImg() + // routine figure out when we're at the end, etc. + + ScanBuffAdd(nBuf0, m_nScanBuffPtr); + m_nScanBuffPtr += 1; + } + else if((nBuf0 == 0xFF) && (nMarker != 0x00)) + { + // We have read a marker... don't assume that this is bad as it will + // always happen at the end of the scan segment. Therefore, we will + // assume this marker is valid (ie. not bit error in scan stream) + // and mark the end of the scan segment. + + if(m_nWarnBadScanNum < m_nScanErrMax) + { + QString strTmp; + + strTmp = QString(" Scan Data encountered marker 0xFF%1 @ 0x%2.0") + .arg(nMarker, 2, 16, QChar('0')) + .arg(m_nScanBuffPtr, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + if(nMarker != JFIF_EOI) + { + m_pLog->AddLineErr(" NOTE: Marker wasn't EOI (0xFFD9)"); + } + + m_nWarnBadScanNum++; + + if(m_nWarnBadScanNum >= m_nScanErrMax) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(m_nScanErrMax); + m_pLog->AddLineErr(strTmp); + } + } + + // Optionally stop immediately upon a bad marker +#ifdef SCAN_BAD_MARKER_STOP + m_bScanEnd = true; + return 1; +#else + // Add byte to m_nScanBuff & record file position + ScanBuffAddErr(nBuf0, m_nScanBuffPtr, SCANBUF_BADMARK); + + m_nScanBuffPtr += 1; +#endif + } + else + { + // Normal byte + // Add byte to m_nScanBuff & record file position + ScanBuffAdd(nBuf0, m_nScanBuffPtr); + + m_nScanBuffPtr += 1; + } + + return 0; +} + +// Define minimum value before we include DCT entry in +// the IDCT calcs. +// NOTE: Currently disabled +#define IDCT_COEF_THRESH 4 + +// Decode a single component for one block of an MCU +// - Pull bits from the main buffer +// - Find matching huffman codes +// - Fill in the IDCT matrix (m_anDctBlock[]) +// - Perform the IDCT to create spatial domain +// +// INPUT: +// - nTblDhtDc = DHT table ID for DC component +// - nTblDhtAc = DHT talbe ID for AC component +// - nMcuX = UNUSED +// - nMcuY = UNUSED +// RETURN: +// - Indicate if the decode was successful +// POST: +// - m_nScanCurDc = DC component value +// Performance: +// - This routine is called on every block so it must be +// reasonably efficient. Only call string routines when we +// are sure that we have an error. +// +// FIXME: Consider adding checks for DHT table like in ReadScanVal() +// +bool CimgDecode::DecodeScanComp(uint32_t nTblDhtDc, uint32_t nTblDhtAc, uint32_t nTblDqt, uint32_t, uint32_t) +{ + uint32_t nZrl; + + int32_t nVal; + + bool bDone = false; + bool bDC = true; // Start with DC coeff + + teRsvRet eRsvRet; // Return value from ReadScanVal() + + uint32_t nNumCoeffs = 0; + + //uint32_t nDctMax = 0; // Maximum DCT coefficient to use for IDCT + uint32_t nSavedBufPos = 0; + + uint32_t nSavedBufErr = SCANBUF_OK; + + uint32_t nSavedBufAlign = 0; + + // Profiling: No difference noted + DecodeIdctClear(); + + while(!bDone) + { + BuffTopup(); + + // Note that once we perform ReadScanVal(), then GetScanBufPos() will be + // after the decoded VLC + // Save old file position info in case we want accurate error positioning + nSavedBufPos = m_anScanBuffPtr_pos[0]; + nSavedBufErr = m_nScanBuffLatchErr; + nSavedBufAlign = m_nScanBuffPtr_align; + + // ReadScanVal return values: + // - RSV_OK OK + // - RSV_EOB End of block + // - RSV_UNDERFLOW Ran out of data in buffer + // - RSV_RST_TERM No huffman code found, but restart marker seen + // Assume nTblDht just points to DC tables, adjust for AC + // e.g. nTblDht = 0,2,4 + eRsvRet = ReadScanVal(bDC ? 0 : 1, bDC ? nTblDhtDc : nTblDhtAc, nZrl, nVal); + + // Handle Restart marker first. + if(eRsvRet == RSV_RST_TERM) + { + // Assume that m_bRestartRead is TRUE + // No huffman code found because either we ran out of bits + // in the scan buffer or the bits padded with 1's didn't result + // in a valid VLC code. + + // Steps: + // 1) Reset the decoder state (DC values) + // 2) Advance the buffer pointer (might need to handle the + // case of perfect alignment to byte boundary separately) + // 3) Flush the Scan Buffer + // 4) Clear m_bRestartRead + // 5) Refill Scan Buffer with BuffTopUp() + // 6) Re-invoke ReadScanVal() + + // Step 1: + DecodeRestartDcState(); + + // Step 2 + m_nScanBuffPtr += 2; + + // Step 3 + DecodeRestartScanBuf(m_nScanBuffPtr, true); + + // Step 4 + m_bRestartRead = false; + + // Step 5 + BuffTopup(); + + // Step 6 + // Q_ASSERT is because we assume that we don't get 2 restart + // markers in a row! + eRsvRet = ReadScanVal(bDC ? 0 : 1, bDC ? nTblDhtDc : nTblDhtAc, nZrl, nVal); + Q_ASSERT(eRsvRet != RSV_RST_TERM); + } + + // In case we encountered a restart marker or bad scan marker + if(nSavedBufErr == SCANBUF_BADMARK) + { + // Mark as scan error + m_nScanCurErr = true; + + m_bScanBad = true; + + if(m_nWarnBadScanNum < m_nScanErrMax) + { + QString strPos = GetScanBufPos(nSavedBufPos, nSavedBufAlign); + + QString strTmp; + + strTmp = QString("*** ERROR: Bad marker @ %1").arg(strPos); + m_pLog->AddLineErr(strTmp); + + m_nWarnBadScanNum++; + + if(m_nWarnBadScanNum >= m_nScanErrMax) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(m_nScanErrMax); + m_pLog->AddLineErr(strTmp); + } + } + + // Reset the latched error now that we've dealt with it + m_nScanBuffLatchErr = SCANBUF_OK; + } + + int16_t nVal2; + + nVal2 = static_cast(nVal & 0xFFFF); + + if(eRsvRet == RSV_OK) + { + // DC entry is always one value only + if(bDC) + { + DecodeIdctSet(nTblDqt, nNumCoeffs, nZrl, nVal2); //CALZ + bDC = false; // Now we will be on AC comps + } + else + { + // We're on AC entry, so keep looping until + // we have finished up to 63 entries + // Set entry in table + // PERFORMANCE: + // No noticeable difference if following is skipped + if(m_bDecodeScanAc) + { + DecodeIdctSet(nTblDqt, nNumCoeffs, nZrl, nVal2); + } + } + } + else if(eRsvRet == RSV_EOB) + { + if(bDC) + { + DecodeIdctSet(nTblDqt, nNumCoeffs, nZrl, nVal2); //CALZ + // Now that we have finished the DC coefficient, start on AC coefficients + bDC = false; + } + else + { + // Now that we have finished the AC coefficients, we are done + bDone = true; + } + } + else if(eRsvRet == RSV_UNDERFLOW) + { + // ERROR + + if(m_nWarnBadScanNum < m_nScanErrMax) + { + QString strPos = GetScanBufPos(nSavedBufPos, nSavedBufAlign); + + QString strTmp; + + strTmp = QString("*** ERROR: Bad huffman code @ %1").arg(strPos); + m_pLog->AddLineErr(strTmp); + + m_nWarnBadScanNum++; + + if(m_nWarnBadScanNum >= m_nScanErrMax) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(m_nScanErrMax); + m_pLog->AddLineErr(strTmp); + } + } + + m_nScanCurErr = true; + bDone = true; + + return false; + } + + // Increment the number of coefficients + nNumCoeffs += 1 + nZrl; + + // If we have filled out an entire 64 entries, then we move to + // the next block without an EOB + // NOTE: This is only 63 entries because we assume that we + // are doing the AC (DC was already bDone in a different pass) + + // FIXME: Would like to combine DC & AC in one pass so that + // we don't end up having to use 2 tables. The check below will + // also need to be changed to == 64. + // + // Currently, we will have to correct AC nNumCoeffs entries (in IDCT) to + // be +1 to get real index, as we are ignoring DC position 0. + + if(nNumCoeffs == 64) + { + bDone = true; + } + else if(nNumCoeffs > 64) + { + // ERROR + + if(m_nWarnBadScanNum < m_nScanErrMax) + { + QString strTmp; + + QString strPos = GetScanBufPos(nSavedBufPos, nSavedBufAlign); + + strTmp = QString("*** ERROR: @ %1, nNumCoeffs>64 [%2]").arg(strPos).arg(nNumCoeffs); + m_pLog->AddLineErr(strTmp); + + m_nWarnBadScanNum++; + + if(m_nWarnBadScanNum >= m_nScanErrMax) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(m_nScanErrMax); + m_pLog->AddLineErr(strTmp); + } + } + + m_nScanCurErr = true; + m_bScanBad = true; + bDone = true; + + nNumCoeffs = 64; // Just to ensure we don't use an overrun value anywhere + } + } + + // We finished the MCU + // Now calc the IDCT matrix + + // The following code needs to be very efficient. + // A number of experiments have been carried out to determine + // the magnitude of speed improvements through various settings + // and IDCT methods: + // + // PERFORMANCE: + // Example file: canon_1dsmk2_ + // + // 0:06 Turn off m_bDecodeScanAc (so no array memset, etc.) + // 0:10 m_bDecodeScanAc=true, but DecodeIdctCalc() skipped + // 0:26 m_bDecodeScanAc=true and DecodeIdctCalcFixedpt() + // 0:27 m_bDecodeScanAc=true and DecodeIdctCalcFloat() + + if(m_bDecodeScanAc) + { +#ifdef IDCT_FIXEDPT + DecodeIdctCalcFixedpt(); +#else + + // TODO: Select appropriate conversion routine based on performance +// DecodeIdctCalcFloat(nDctMax); +// DecodeIdctCalcFloat(nNumCoeffs); +// DecodeIdctCalcFloat(m_nDctCoefMax); + DecodeIdctCalcFloat(64); +// DecodeIdctCalcFloat(32); +#endif + } + + return true; +} + +// Decode a single component for one block of an MCU with printing +// used for the Detailed Decode functionality +// - Same as DecodeScanComp() but adds reporting of variable length codes (VLC) +// +// INPUT: +// - nTblDhtDc = DHT table ID for DC component +// - nTblDhtAc = DHT talbe ID for AC component +// - nMcuX = Current MCU X coordinate (for reporting only) +// - nMcuY = Current MCU Y coordinate (for reporting only) +// RETURN: +// - Indicate if the decode was successful +// POST: +// - m_nScanCurDc = DC component value +// PERFORMANCE: +// - As this routine is called for every MCU, it is important +// for it to be efficient. However, we are in print mode, so +// we can afford to be slower. +// +// FIXME: need to fix like DecodeScanComp() (ordering of exit conditions, etc.) +// FIXME: Consider adding checks for DHT table like in ReadScanVal() +// +bool CimgDecode::DecodeScanCompPrint(uint32_t nTblDhtDc, uint32_t nTblDhtAc, uint32_t nTblDqt, uint32_t nMcuX, uint32_t nMcuY) +{ + bool bPrint = true; + + teRsvRet eRsvRet; + + QString strTmp; + QString strTbl; + QString strSpecial; + QString strPos; + + uint32_t nZrl; + int32_t nVal; + + bool bDone = false; + bool bDC = true; // Start with DC component + + if(bPrint) + { + switch (nTblDqt) + { + case 0: + strTbl = "Lum"; + break; + + case 1: + strTbl = "Chr(0)"; // Usually Cb + break; + + case 2: + strTbl = "Chr(1)"; // Usually Cr + break; + + default: + strTbl = "???"; + break; + } + + strTmp = QString(" %1 (Tbl #%2), MCU=[%3,%4]").arg(strTbl).arg(nTblDqt).arg(nMcuX).arg(nMcuY); + m_pLog->AddLine(strTmp); + } + + uint32_t nNumCoeffs = 0; + uint32_t nSavedBufPos = 0; + uint32_t nSavedBufErr = SCANBUF_OK; + uint32_t nSavedBufAlign = 0; + + DecodeIdctClear(); + + while(!bDone) + { + BuffTopup(); + + // Note that once we perform ReadScanVal(), then GetScanBufPos() will be + // after the decoded VLC + + // Save old file position info in case we want accurate error positioning + nSavedBufPos = m_anScanBuffPtr_pos[0]; + nSavedBufErr = m_nScanBuffLatchErr; + nSavedBufAlign = m_nScanBuffPtr_align; + + // Return values: + // 0 - OK + // 1 - EOB + // 2 - Overread error + // 3 - No huffman code found, but restart marker seen + eRsvRet = ReadScanVal(bDC ? 0 : 1, bDC ? nTblDhtDc : nTblDhtAc, nZrl, nVal); + + // Handle Restart marker first. + if(eRsvRet == RSV_RST_TERM) + { + // Assume that m_bRestartRead is TRUE + // No huffman code found because either we ran out of bits + // in the scan buffer or the bits padded with 1's didn't result + // in a valid VLC code. + + // Steps: + // 1) Reset the decoder state (DC values) + // 2) Advance the buffer pointer (might need to handle the + // case of perfect alignment to byte boundary separately) + // 3) Flush the Scan Buffer + // 4) Clear m_bRestartRead + // 5) Refill Scan Buffer with BuffTopUp() + // 6) Re-invoke ReadScanVal() + + // Step 1: + DecodeRestartDcState(); + + // Step 2 + m_nScanBuffPtr += 2; + + // Step 3 + DecodeRestartScanBuf(m_nScanBuffPtr, true); + + // Step 4 + m_bRestartRead = false; + + // Step 5 + BuffTopup(); + + // Step 6 + // Q_ASSERT is because we assume that we don't get 2 restart + // markers in a row! + eRsvRet = ReadScanVal(bDC ? 0 : 1, bDC ? nTblDhtDc : nTblDhtAc, nZrl, nVal); + Q_ASSERT(eRsvRet != RSV_RST_TERM); + } + + // In case we encountered a restart marker or bad scan marker + if(nSavedBufErr == SCANBUF_BADMARK) + { + // Mark as scan error + m_nScanCurErr = true; + + m_bScanBad = true; + + if(m_nWarnBadScanNum < m_nScanErrMax) + { + strPos = GetScanBufPos(nSavedBufPos, nSavedBufAlign); + strTmp = QString("*** ERROR: Bad marker @ %1").arg(strPos); + m_pLog->AddLineErr(strTmp); + + m_nWarnBadScanNum++; + + if(m_nWarnBadScanNum >= m_nScanErrMax) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(m_nScanErrMax); + m_pLog->AddLineErr(strTmp); + } + } + + // Reset the latched error now that we've dealt with it + m_nScanBuffLatchErr = SCANBUF_OK; + } + + // Should this be before or after restart checks? + uint32_t nCoeffStart = nNumCoeffs; + uint32_t nCoeffEnd = nNumCoeffs + nZrl; + + int16_t nVal2; + + nVal2 = static_cast(nVal & 0xFFFF); + + if(eRsvRet == RSV_OK) + { + strSpecial = ""; + // DC entry is always one value only + // FIXME: Do I need nTblDqt == 4 as well? + if(bDC) + { + DecodeIdctSet(nTblDqt, nNumCoeffs, nZrl, nVal2); + bDC = false; // Now we will be on AC comps + } + else + { + // We're on AC entry, so keep looping until + // we have finished up to 63 entries + // Set entry in table + DecodeIdctSet(nTblDqt, nNumCoeffs, nZrl, nVal2); + } + } + else if(eRsvRet == RSV_EOB) + { + if(bDC) + { + DecodeIdctSet(nTblDqt, nNumCoeffs, nZrl, nVal2); + bDC = false; // Now we will be on AC comps + } + else + { + bDone = true; + } + strSpecial = "EOB"; + } + else if(eRsvRet == RSV_UNDERFLOW) + { + if(m_nWarnBadScanNum < m_nScanErrMax) + { + strSpecial = "ERROR"; + strPos = GetScanBufPos(nSavedBufPos, nSavedBufAlign); + + strTmp = QString("*** ERROR: Bad huffman code @ %1").arg(strPos); + m_pLog->AddLineErr(strTmp); + + m_nWarnBadScanNum++; + + if(m_nWarnBadScanNum >= m_nScanErrMax) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(m_nScanErrMax); + m_pLog->AddLineErr(strTmp); + } + } + + m_nScanCurErr = true; + bDone = true; + + // Print out before we leave + if(bPrint) + { + ReportVlc(nSavedBufPos, nSavedBufAlign, nZrl, nVal2, nCoeffStart, nCoeffEnd, strSpecial); + } + + return false; + } + + // Increment the number of coefficients + nNumCoeffs += 1 + nZrl; + // If we have filled out an entire 64 entries, then we move to + // the next block without an EOB + // NOTE: This is only 63 entries because we assume that we + // are doing the AC (DC was already done in a different pass) + if(nNumCoeffs == 64) + { + strSpecial = "EOB64"; + bDone = true; + } + else if(nNumCoeffs > 64) + { + // ERROR + + if(m_nWarnBadScanNum < m_nScanErrMax) + { + strPos = GetScanBufPos(nSavedBufPos, nSavedBufAlign); + strTmp = QString("*** ERROR: @ %1, nNumCoeffs>64 [%2]").arg(strPos).arg(nNumCoeffs); + m_pLog->AddLineErr(strTmp); + + m_nWarnBadScanNum++; + + if(m_nWarnBadScanNum >= m_nScanErrMax) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(m_nScanErrMax); + m_pLog->AddLineErr(strTmp); + } + } + + m_nScanCurErr = true; + m_bScanBad = true; + bDone = true; + + nNumCoeffs = 64; // Just to ensure we don't use an overrun value anywhere + } + + if(bPrint) + { + ReportVlc(nSavedBufPos, nSavedBufAlign, nZrl, nVal2, nCoeffStart, nCoeffEnd, strSpecial); + } + } + + // We finished the MCU component + + // Now calc the IDCT matrix +#ifdef IDCT_FIXEDPT + DecodeIdctCalcFixedpt(); +#else +// DecodeIdctCalcFloat(nNumCoeffs); + DecodeIdctCalcFloat(64); +#endif + + // Now report the coefficient matrix (after zigzag reordering) + if(bPrint) + { + ReportDctMatrix(); + } + + return true; +} + +// Print out the DCT matrix for a given block +// +// PRE: +// - m_anDctBlock[] +// +void CimgDecode::ReportDctMatrix() +{ + QString strTmp; + QString strLine; + + int32_t nCoefVal; + + for(uint32_t nY = 0; nY < 8; nY++) + { + if(nY == 0) + { + strLine = " DCT Matrix=["; + } + else + { + strLine = " ["; + } + + for(uint32_t nX = 0; nX < 8; nX++) + { + strTmp = ""; + nCoefVal = m_anDctBlock[nY * 8 + nX]; + strTmp = QString("%1").arg(nCoefVal, 5); + strLine.append(strTmp); + + if(nX != 7) + { + strLine.append(" "); + } + } + + strLine.append("]"); + m_pLog->AddLine(strLine); + } + + m_pLog->AddLine(""); +} + +// Report out the variable length codes (VLC) +// +// Need to consider impact of padding bytes... When pads get extracted, they +// will not appear in the binary display shown below. Might want the get buffer +// to do post-pad removal first. +// +// eg. file Dsc0019.jpg +// Overlay 0x4215 = 7FFF0000 len=4 +// +// INPUT: +// - nVlcPos = +// - nVlcAlign = +// - nZrl = +// - nVal = +// - nCoeffStart = +// - nCoeffEnd = +// - specialStr = +// +void CimgDecode::ReportVlc(uint32_t nVlcPos, uint32_t nVlcAlign, + uint32_t nZrl, int32_t nVal, uint32_t nCoeffStart, uint32_t nCoeffEnd, QString specialStr) +{ + QString strPos; + QString strTmp; + + uint32_t nBufByte[4]; + uint32_t nBufPosInd = nVlcPos; + + QString strData = ""; + QString strByte1 = ""; + QString strByte2 = ""; + QString strByte3 = ""; + QString strByte4 = ""; + QString strBytes = ""; + QString strBytesOrig = ""; + QString strBinMarked = ""; + + strPos = GetScanBufPos(nVlcPos, nVlcAlign); + + // Read in the buffer bytes, but skip pad bytes (0xFF00 -> 0xFF) + + // We need to look at previous byte as it might have been + // start of stuff byte! If so, we need to ignore the byte + // and advance the pointers. + uint8_t nBufBytePre = m_pWBuf->Buf(nBufPosInd - 1); + + nBufByte[0] = m_pWBuf->Buf(nBufPosInd++); + + if((nBufBytePre == 0xFF) && (nBufByte[0] == 0x00)) + { + nBufByte[0] = m_pWBuf->Buf(nBufPosInd++); + } + + nBufByte[1] = m_pWBuf->Buf(nBufPosInd++); + + if((nBufByte[0] == 0xFF) && (nBufByte[1] == 0x00)) + { + nBufByte[1] = m_pWBuf->Buf(nBufPosInd++); + } + + nBufByte[2] = m_pWBuf->Buf(nBufPosInd++); + + if((nBufByte[1] == 0xFF) && (nBufByte[2] == 0x00)) + { + nBufByte[2] = m_pWBuf->Buf(nBufPosInd++); + } + + nBufByte[3] = m_pWBuf->Buf(nBufPosInd++); + + if((nBufByte[2] == 0xFF) && (nBufByte[3] == 0x00)) + { + nBufByte[3] = m_pWBuf->Buf(nBufPosInd++); + } + + strByte1 = Dec2Bin(nBufByte[0], 8, true); + strByte2 = Dec2Bin(nBufByte[1], 8, true); + strByte3 = Dec2Bin(nBufByte[2], 8, true); + strByte4 = Dec2Bin(nBufByte[3], 8, true); + strBytesOrig = strByte1 + " " + strByte2 + " " + strByte3 + " " + strByte4; + strBytes = strByte1 + strByte2 + strByte3 + strByte4; + + for(uint32_t ind = 0; ind < nVlcAlign; ind++) + { + strBinMarked += "-"; + } + + strBinMarked += strBytes.mid(nVlcAlign, m_nScanBitsUsed1 + m_nScanBitsUsed2); + + for(uint32_t ind = nVlcAlign + m_nScanBitsUsed1 + m_nScanBitsUsed2; ind < 32; ind++) + { + strBinMarked += "-"; + } + + strBinMarked.insert(24, " "); + strBinMarked.insert(16, " "); + strBinMarked.insert(8, " "); + + strData = QString("0x %1 %2 %3 %4 = 0b (%5)") + .arg(nBufByte[0], 2, 16, QChar('0')) + .arg(nBufByte[1], 2, 16, QChar('0')) + .arg(nBufByte[2], 2, 16, QChar('0')) + .arg(nBufByte[3], 2, 16, QChar('0')) + .arg(strBinMarked); + + if((nCoeffStart == 0) && (nCoeffEnd == 0)) + { + strTmp = QString(" [%1]: ZRL=[%2] Val=[%3] Coef=[%4= DC] Data=[%5] %6") + .arg(strPos) + .arg(nZrl, 2) + .arg(nVal, 5) + .arg(nCoeffStart, 2, 10, QChar('0')) + .arg(strData) + .arg(specialStr); + } + else + { + strTmp = QString(" [%1]: ZRL=[%2] Val=[%3] Coef=[%4..%5] Data=[%6] %7") + .arg(strPos) + .arg(nZrl, 2) + .arg(nVal, 5) + .arg(nCoeffStart, 2, 10, QChar('0')) + .arg(nCoeffEnd, 2, 10, QChar('0')) + .arg(strData) + .arg(specialStr); + } + + m_pLog->AddLine(strTmp); +} + +// Clear input and output matrix +// +// POST: +// - m_anDctBlock[] +// - m_afIdctBlock[] +// - m_anIdctBlock[] +// - m_nDctCoefMax +// +void CimgDecode::DecodeIdctClear() +{ + memset(m_anDctBlock, 0, sizeof m_anDctBlock); + memset(m_afIdctBlock, 0, sizeof m_afIdctBlock); + memset(m_anIdctBlock, 0, sizeof m_anIdctBlock); + + m_nDctCoefMax = 0; +} + +// Set the DCT matrix entry +// - Fills in m_anDctBlock[] with the unquantized coefficients +// - Reversing the quantization is done using m_anDqtCoeffZz[][] +// +// INPUT: +// - nDqtTbl = +// - num_coeffs = +// - zrl = +// - val = +// PRE: +// - glb_anZigZag[] +// - m_anDqtCoeffZz[][] +// - m_nDctCoefMax +// POST: +// - m_anDctBlock[] +// NOTE: +// - We need to convert between the zigzag order and the normal order +// +void CimgDecode::DecodeIdctSet(uint32_t nDqtTbl, uint32_t num_coeffs, uint32_t zrl, int16_t val) +{ + uint32_t ind = num_coeffs + zrl; + + if(ind >= 64) + { + // We have an error! Don't set the block. Skip this comp for now + // After this call, we will likely trap the error. + } + else + { + uint32_t nDctInd = glb_anZigZag[ind]; + + int16_t nValUnquant = val * m_anDqtCoeffZz[nDqtTbl][ind]; + + /* + // NOTE: + // To test steganography analysis, we can experiment with dropping + // specific components of the image. + uint32_t nRow = nDctInd/8; + uint32_t nCol = nDctInd - (nRow*8); + if ((nRow == 0) && (nCol>=0 && nCol<=7)) { + nValUnquant = 0; + } + */ + + m_anDctBlock[nDctInd] = nValUnquant; + + // Update max DCT coef # (after unzigzag) so that we can save + // some work when performing IDCT. + // FIXME: The following doesn't seem to work when we later + // restrict DecodeIdctCalc() to only m_nDctCoefMax coefs! + +// if ( (nDctInd > m_nDctCoefMax) && (abs(nValUnquant) >= IDCT_COEF_THRESH) ) { + if(nDctInd > m_nDctCoefMax) + { + m_nDctCoefMax = nDctInd; + } + } +} + +// Precalculate the IDCT lookup tables +// +// POST: +// - m_afIdctLookup[] +// - m_anIdctLookup[] +// NOTE: +// - This is 4k entries @ 4B each = 16KB +// +void CimgDecode::PrecalcIdct() +{ + uint32_t nX, nY, nU, nV; + + uint32_t nYX, nVU; + + double fCu, fCv; + double fCosProd; + double fInsideProd; + double fPi = 3.141592654; + double fSqrtHalf = 0.707106781; + + for(nY = 0; nY < DCT_SZ_Y; nY++) + { + for(nX = 0; nX < DCT_SZ_X; nX++) + { + nYX = nY * DCT_SZ_X + nX; + + for(nV = 0; nV < DCT_SZ_Y; nV++) + { + for(nU = 0; nU < DCT_SZ_X; nU++) + { + + nVU = nV * DCT_SZ_X + nU; + + fCu = (nU == 0) ? fSqrtHalf : 1; + fCv = (nV == 0) ? fSqrtHalf : 1; + fCosProd = cos((2 * nX + 1) * nU * fPi / 16) * cos((2 * nY + 1) * nV * fPi / 16); + // Note that the only part we are missing from + // the "Inside Product" is the "m_afDctBlock[nV*8+nU]" term + fInsideProd = fCu * fCv * fCosProd; + + // Store the Lookup result + m_afIdctLookup[nYX][nVU] = fInsideProd; + + // Store a fixed point Lookup as well + m_anIdctLookup[nYX][nVU] = static_cast(fInsideProd * (1 << 10)); + } + } + } + } +} + +// Perform IDCT +// +// Formula: +// See itu-t81.pdf, section A.3.3 +// +// s(yx) = 1/4*Sum(u=0..7)[ Sum(v=0..7)[ C(u) * C(v) * S(vu) * +// cos( (2x+1)*u*Pi/16 ) * cos( (2y+1)*v*Pi/16 ) ] ] +// Cu, Cv = 1/sqrt(2) for u,v=0 +// Cu, Cv = 1 else +// +// INPUT: +// - nCoefMax = Maximum number of coefficients to calculate +// PRE: +// - m_afIdctLookup[][] +// - m_anDctBlock[] +// POST: +// - m_afIdctBlock[] +// +void CimgDecode::DecodeIdctCalcFloat(uint32_t nCoefMax) +{ + uint32_t nYX, nVU; + + double fSum; + + for(nYX = 0; nYX < DCT_SZ_ALL; nYX++) + { + fSum = 0; + + // Skip DC coefficient! + for(nVU = 1; nVU < nCoefMax; nVU++) + { + fSum += m_afIdctLookup[nYX][nVU] * m_anDctBlock[nVU]; + } + + fSum *= 0.25; + + // Store the result + // FIXME: Note that float->int is very slow! + // Should consider using fixed point instead! + m_afIdctBlock[nYX] = fSum; + } +} + +// Fixed point version of DecodeIdctCalcFloat() +// +// PRE: +// - m_anIdctLookup[][] +// - m_anDctBlock[] +// POST: +// - m_anIdctBlock[] +// +void CimgDecode::DecodeIdctCalcFixedpt() +{ + uint32_t nYX, nVU; + + int32_t nSum; + + for(nYX = 0; nYX < DCT_SZ_ALL; nYX++) + { + nSum = 0; + + // Skip DC coefficient! + for(nVU = 1; nVU < DCT_SZ_ALL; nVU++) + { + nSum += m_anIdctLookup[nYX][nVU] * m_anDctBlock[nVU]; + } + + nSum /= 4; + + // Store the result + // FIXME: Note that float->int is very slow! + // Should consider using fixed point instead! + m_anIdctBlock[nYX] = nSum >> 10; + } +} + +// Clear the entire pixel image arrays for all three components (YCC) +// +// INPUT: +// - nWidth = Current allocated image width +// - nHeight = Current allocated image height +// POST: +// - m_pPixValY +// - m_pPixValCb +// - m_pPixValCr +// +void CimgDecode::ClrFullRes(uint32_t nWidth, uint32_t nHeight) +{ + Q_ASSERT(m_pPixValY); + + if(m_nNumSosComps == NUM_CHAN_YCC) + { + Q_ASSERT(m_pPixValCb); + Q_ASSERT(m_pPixValCr); + } + + // FIXME: Add in range checking here + memset(m_pPixValY, 0, (nWidth * nHeight * sizeof(short))); + + if(m_nNumSosComps == NUM_CHAN_YCC) + { + memset(m_pPixValCb, 0, (nWidth * nHeight * sizeof(short))); + memset(m_pPixValCr, 0, (nWidth * nHeight * sizeof(short))); + } +} + +// Generate a single component's pixel content for one MCU +// - Fetch content from the 8x8 IDCT block (m_afIdctBlock[]) +// for the specified component (nComp) +// - Transfer the pixel content to the specified component's +// pixel map (m_pPixValY[],m_pPixValCb[],m_pPixValCr[]) +// - DC level shifting is performed (nDcOffset) +// - Replication of pixels according to Chroma Subsampling (sampling factors) +// +// INPUT: +// - nMcuX = +// - nMcuY = +// - nComp = Component index (1,2,3) +// - nCssXInd = +// - nCssYInd = +// - nDcOffset = +// PRE: +// - DecodeIdctCalc() already called on Lum AC, and Lum DC already done +// +void CimgDecode::SetFullRes(uint32_t nMcuX, uint32_t nMcuY, uint32_t nComp, uint32_t nCssXInd, uint32_t nCssYInd, int16_t nDcOffset) +{ + uint32_t nYX; + + double fVal; + + int16_t nVal; + + uint32_t nChan; + + // Convert from Component index (1-based) to Channel index (0-based) + // Component index is direct from SOF/SOS + // Channel index is used for internal display representation + if(nComp <= 0) + { +#ifdef DEBUG_LOG + QString strTmp; + QString strDebug; + + strTmp = QString("SetFullRes() with nComp <= 0 [%1]").arg(nComp); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("ImgDecode", -10).arg(strTmp); + qDebug() << strDebug; +#else + Q_ASSERT(false); +#endif + return; + } + + nChan = nComp - 1; + + uint32_t nPixMapW = m_nBlkXMax * BLK_SZ_X; // Width of pixel map + uint32_t nOffsetBlkCorner; // Linear offset to top-left corner of block + uint32_t nOffsetPixCorner; // Linear offset to top-left corner of pixel (start point for expansion) + + // Calculate the linear pixel offset for the top-left corner of the block in the MCU + nOffsetBlkCorner = ((nMcuY * m_nMcuHeight) + nCssYInd * BLK_SZ_X) * nPixMapW + ((nMcuX * m_nMcuWidth) + nCssXInd * BLK_SZ_Y); + + // Use the expansion factor to determine how many bits to replicate + // Typically for luminance (Y) this will be 1 & 1 + // The replication factor is available in m_anExpandBitsMcuH[] and m_anExpandBitsMcuV[] + + // Step through all pixels in the block + for(uint32_t nY = 0; nY < BLK_SZ_Y; nY++) + { + for(uint32_t nX = 0; nX < BLK_SZ_X; nX++) + { + nYX = nY * BLK_SZ_X + nX; + + // Fetch the pixel value from the IDCT 8x8 block + // and perform DC level shift +#ifdef IDCT_FIXEDPT + nVal = m_anIdctBlock[nYX]; + // TODO: Why do I need AC value x8 multiplier? + nVal = (nVal * 8) + nDcOffset; +#else + fVal = m_afIdctBlock[nYX]; + // TODO: Why do I need AC value x8 multiplier? + nVal = (static_cast(fVal * 8) + nDcOffset); +#endif + + // NOTE: These range checks were already done in DecodeScanImg() + Q_ASSERT(nCssXInd < MAX_SAMP_FACT_H); + Q_ASSERT(nCssYInd < MAX_SAMP_FACT_V); + Q_ASSERT(nY < BLK_SZ_Y); + Q_ASSERT(nX < BLK_SZ_X); + + // Set the pixel value for the component + + // We start with the linear offset into the pixel map for the top-left + // corner of the block. Then we adjust to determine the top-left corner + // of the pixel that we may optionally expand in subsampling scenarios. + + // Calculate the top-left corner pixel linear offset after taking + // into account any expansion in the X direction + nOffsetPixCorner = nOffsetBlkCorner + nX * m_anExpandBitsMcuH[nComp]; + + // Replication the pixels as specified in the sampling factor + // This is typically done for the chrominance channels when + // chroma subsamping is used. + for(uint32_t nIndV = 0; nIndV < m_anExpandBitsMcuV[nComp]; nIndV++) + { + for(uint32_t nIndH = 0; nIndH < m_anExpandBitsMcuH[nComp]; nIndH++) + { + if(nChan == CHAN_Y) + { + m_pPixValY[nOffsetPixCorner + (nIndV * nPixMapW) + nIndH] = nVal; + } + else if(nChan == CHAN_CB) + { + m_pPixValCb[nOffsetPixCorner + (nIndV * nPixMapW) + nIndH] = nVal; + } + else if(nChan == CHAN_CR) + { + m_pPixValCr[nOffsetPixCorner + (nIndV * nPixMapW) + nIndH] = nVal; + } + else + { + Q_ASSERT(false); + } + } // nIndH + } // nIndV + } // nX + + nOffsetBlkCorner += (nPixMapW * m_anExpandBitsMcuV[nComp]); + } // nY +} + +// Calculates the actual byte offset (from start of file) for +// the current position in the m_nScanBuff. +// +// PRE: +// - m_anScanBuffPtr_pos[] +// - m_nScanBuffPtr_align +// RETURN: +// - File position +// +QString CimgDecode::GetScanBufPos() +{ + return GetScanBufPos(m_anScanBuffPtr_pos[0], m_nScanBuffPtr_align); +} + +// Generate a file position string that also indicates bit alignment +// +// INPUT: +// - pos = File position (byte) +// - align = File position (bit) +// RETURN: +// - Formatted string +// +QString CimgDecode::GetScanBufPos(uint32_t pos, uint32_t align) +{ + return QString("0x%1.%2") + .arg(pos, 8, 16, QChar('0')) + .arg(align);; +} + +// Test the scan error flag and, if set, report out the position +// +// INPUT: +// - nMcuX = MCU x coordinate +// - nMcuY = MCU y coordinate +// - nCssIndH = Chroma subsampling (horizontal) +// - nCssIndV = Chroma subsampling (vertical) +// - nComp = Image component +// +void CimgDecode::CheckScanErrors(uint32_t nMcuX, uint32_t nMcuY, uint32_t nCssIndH, uint32_t nCssIndV, uint32_t nComp) +{ + //uint32_t mcu_x_max = (m_nDimX/m_nMcuWidth); + //uint32_t mcu_y_max = (m_nDimY/m_nMcuHeight); + + // Determine pixel position, taking into account sampling quadrant as well + uint32_t err_pos_x = m_nMcuWidth * nMcuX + nCssIndH * BLK_SZ_X; + + uint32_t err_pos_y = m_nMcuHeight * nMcuY + nCssIndV * BLK_SZ_Y; + + if(m_nScanCurErr) + { + QString strTmp, errStr; + + // Report component and subsampling quadrant + switch (nComp) + { + case SCAN_COMP_Y: + strTmp = QString("Lum CSS(%1,%2)") + .arg(nCssIndH) + .arg(nCssIndV); + break; + + case SCAN_COMP_CB: + strTmp = QString("Chr(Cb) CSS(%1,%2)") + .arg(nCssIndH) + .arg(nCssIndV); + break; + + case SCAN_COMP_CR: + strTmp = QString("Chr(Cr) CSS(%1,%2)") + .arg(nCssIndH) + .arg(nCssIndV); + break; + + default: + // Unknown component + strTmp = QString("??? CSS(%1,%2)") + .arg(nCssIndH) + .arg(nCssIndV); + break; + } + + if(m_nWarnBadScanNum < m_nScanErrMax) + { + errStr = QString("*** ERROR: Bad scan data in MCU(%1,%2): %3 @ Offset %4") + .arg(nMcuX) + .arg(nMcuY) + .arg(strTmp) + .arg(GetScanBufPos()); + m_pLog->AddLineErr(errStr); + errStr = QString(" MCU located at pixel=(%1, %2)") + .arg(err_pos_x) + .arg(err_pos_y); + m_pLog->AddLineErr(errStr); + + //errStr = QString("*** Resetting Error state to continue ***"); + //m_pLog->AddLineErr(errStr); + + m_nWarnBadScanNum++; + + if(m_nWarnBadScanNum >= m_nScanErrMax) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(m_nScanErrMax); + m_pLog->AddLineErr(strTmp); + } + } + + // TODO: Should we reset m_nScanCurErr? + m_nScanCurErr = false; + + //errStr = QString("*** Resetting Error state to continue ***"); + //m_pLog->AddLineErr(errStr); + } // Error? +} + +// Report the cumulative DC value +// +// INPUT: +// - nMcuX = MCU x coordinate +// - nMcuY = MCU y coordinate +// - nVal = DC value +// +void CimgDecode::PrintDcCumVal(uint32_t, uint32_t, int32_t nVal) +{ + QString strTmp; + +/* strTmp = QString(" MCU [%1,%2] DC Cumulative Val = [%3]") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nVal, 5); */ + strTmp = QString(" Cumulative DC Val=[%1]").arg(nVal, 5); + m_pLog->AddLine(strTmp); +} + +// Reset the DC values in the decoder (e.g. at start and +// after restart markers) +// +// POST: +// - m_nDcLum +// - m_nDcChrCb +// - m_nDcChrCr +// - m_anDcLumCss[] +// - m_anDcChrCbCss[] +// - m_anDcChrCrCss[] +// +void CimgDecode::DecodeRestartDcState() +{ + m_nDcLum = 0; + m_nDcChrCb = 0; + m_nDcChrCr = 0; + + for(uint32_t nInd = 0; nInd < MAX_SAMP_FACT_V * MAX_SAMP_FACT_H; nInd++) + { + m_anDcLumCss[nInd] = 0; + m_anDcChrCbCss[nInd] = 0; + m_anDcChrCrCss[nInd] = 0; + } +} + +//TODO +void CimgDecode::SetImageDimensions(uint32_t nWidth, uint32_t nHeight) +{ + m_rectImgBase = QRect(QPoint(0, 0), QSize(nWidth, nHeight)); +} + +// Process the entire scan segment and optionally render the image +// - Reset and clear the output structures +// - Loop through each MCU and read each component +// - Maintain running DC level accumulator +// - Call SetFullRes() to transfer IDCT output to YCC Pixel Map +// +// INPUT: +// - nStart = File position at start of scan +// - bDisplay = Generate a preview image? +// - bQuiet = Disable output of certain messages during decode? +// +void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) +{ + QString strTmp; + + bool bDieOnFirstErr = false; // FIXME: do we want this? It makes it less useful for corrupt jpegs + + // Fetch configuration values locally + bool bDumpHistoY = m_pAppConfig->bDumpHistoY; + bool bDecodeScanAc; + + uint32_t nScanErrMax = m_pAppConfig->nErrMaxDecodeScan; + + // Add some extra speed-up in hidden mode (we don't need AC) + if(bDisplay) + { + bDecodeScanAc = m_pAppConfig->bDecodeScanImgAc; + } + else + { + bDecodeScanAc = false; + } + + m_bHistEn = m_pAppConfig->bHistoEn; + m_bStatClipEn = m_pAppConfig->bStatClipEn; + + uint32_t nPixMapW = 0; + uint32_t nPixMapH = 0; + + // Reset the decoder state variables + Reset(); + + m_nScanErrMax = nScanErrMax; + m_bDecodeScanAc = bDecodeScanAc; + + // Detect the scenario where the image component details haven't been set yet + // The image details are set via SetImageDetails() + if(!m_bImgDetailsSet) + { + m_pLog->AddLineErr("*** ERROR: Decoding image before Image components defined ***"); + return; + } + + // Even though we support decoding of MAX_SOS_COMP_NS we limit + // the component flexibility further + if((m_nNumSosComps != NUM_CHAN_GRAYSCALE) && (m_nNumSosComps != NUM_CHAN_YCC)) + { + strTmp = QString(" NOTE: Number of SOS components not supported [%1]").arg(m_nNumSosComps); + m_pLog->AddLineWarn(strTmp); +#ifndef DEBUG_YCCK + return; +#endif + } + + // Determine the maximum sampling factor and min sampling factor for this scan + m_nSosSampFactHMax = 0; + m_nSosSampFactVMax = 0; + m_nSosSampFactHMin = 0xFF; + m_nSosSampFactVMin = 0xFF; + + for(uint32_t nComp = 1; nComp <= m_nNumSosComps; nComp++) + { + m_nSosSampFactHMax = qMax(m_nSosSampFactHMax, m_anSofSampFactH[nComp]); + m_nSosSampFactVMax = qMax(m_nSosSampFactVMax, m_anSofSampFactV[nComp]); + m_nSosSampFactHMin = qMin(m_nSosSampFactHMin, m_anSofSampFactH[nComp]); + m_nSosSampFactVMin = qMin(m_nSosSampFactVMin, m_anSofSampFactV[nComp]); + Q_ASSERT(m_nSosSampFactHMin != 0); + Q_ASSERT(m_nSosSampFactVMin != 0); + } + + // ITU-T.81 clause A.2.2 "Non-interleaved order (Ns=1)" + // - In some cases an image may have a single component in a scan but with sampling factors other than 1: + // Number of Img components = 1 + // Component[1]: ID=0x01, Samp Fac=0x22 (Subsamp 1 x 1), Quant Tbl Sel=0x00 (Lum: Y) + // - This could either be in a 3-component SOF with multiple 1-component SOS or a 1-component SOF (monochrome image) + // - In general, grayscale images exhibit a sampling factor of 0x11 + // - Per ITU-T.81 A.2.2: + // When Ns = 1 (where Ns is the number of components in a scan), the order of data units + // within a scan shall be left-to-right and top-to-bottom, as shown in Figure A.2. This + // ordering applies whenever Ns = 1, regardless of the values of H1 and V1. + // - Thus, instead of the usual decoding sequence for 0x22: + // [ 0 1 ] [ 4 5 ] + // [ 2 3 ] [ 6 7 ] + // - The sequence for decode should be: + // [ 0 ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] ... + // - Which is equivalent to the non-subsampled ordering (ie. 0x11) + // - Apply a correction for such images to remove the sampling factor + if(m_nNumSosComps == 1) + { + // TODO: Need to confirm if component index needs to be looked up + // in the case of multiple SOS or if [1] is the correct index + if((m_anSofSampFactH[1] != 1) || (m_anSofSampFactV[1] != 1)) + { + m_pLog->AddLineWarn(" Altering sampling factor for single component scan to 0x11"); + } + + m_anSofSampFactH[1] = 1; + m_anSofSampFactV[1] = 1; + m_nSosSampFactHMax = 1; + m_nSosSampFactVMax = 1; + m_nSosSampFactHMin = 1; + m_nSosSampFactVMin = 1; + } + + // Perform additional range checks + if((m_nSosSampFactHMax == 0) || (m_nSosSampFactVMax == 0) || (m_nSosSampFactHMax > MAX_SAMP_FACT_H) + || (m_nSosSampFactVMax > MAX_SAMP_FACT_V)) + { + strTmp = QString(" NOTE: Degree of subsampling factor not supported [HMax=%1, VMax=%2]") + .arg(m_nSosSampFactHMax) + .arg(m_nSosSampFactVMax); + m_pLog->AddLineWarn(strTmp); + return; + } + + // Calculate the MCU size for this scan. We do it here rather + // than at the time of SOF (ie. SetImageDetails) for the reason + // that under some circumstances we need to override the sampling + // factor in single-component scans. This is done earlier. + m_nMcuWidth = m_nSosSampFactHMax * BLK_SZ_X; + m_nMcuHeight = m_nSosSampFactVMax * BLK_SZ_Y; + + // Calculate the number of bits to replicate when we generate the pixel map + for(uint32_t nComp = 1; nComp <= m_nNumSosComps; nComp++) + { + m_anExpandBitsMcuH[nComp] = m_nSosSampFactHMax / m_anSofSampFactH[nComp]; + m_anExpandBitsMcuV[nComp] = m_nSosSampFactVMax / m_anSofSampFactV[nComp]; + } + + // Calculate the number of component samples per MCU + for(uint32_t nComp = 1; nComp <= m_nNumSosComps; nComp++) + { + m_anSampPerMcuH[nComp] = m_anSofSampFactH[nComp]; + m_anSampPerMcuV[nComp] = m_anSofSampFactV[nComp]; + } + + // Determine the MCU ranges + m_nMcuXMax = (m_nDimX / m_nMcuWidth); + m_nMcuYMax = (m_nDimY / m_nMcuHeight); + + m_nImgSizeXPartMcu = m_nMcuXMax * m_nMcuWidth; + m_nImgSizeYPartMcu = m_nMcuYMax * m_nMcuHeight; + + // Detect incomplete (partial) MCUs and round-up the MCU + // ranges if necessary. + if((m_nDimX % m_nMcuWidth) != 0) + { + m_nMcuXMax++; + } + if((m_nDimY % m_nMcuHeight) != 0) + { + m_nMcuYMax++; + } + + // Save the maximum 8x8 block dimensions + m_nBlkXMax = m_nMcuXMax * m_nSosSampFactHMax; + m_nBlkYMax = m_nMcuYMax * m_nSosSampFactVMax; + + // Ensure the image has a size + if((m_nBlkXMax == 0) || (m_nBlkYMax == 0)) + { + return; + } + + // Set the decoded size and before scaling + m_nImgSizeX = m_nMcuXMax * m_nMcuWidth; + m_nImgSizeY = m_nMcuYMax * m_nMcuHeight; + + m_rectImgBase = QRect(QPoint(0, 0), QSize(m_nImgSizeX, m_nImgSizeY)); + + // Determine decoding range + uint32_t nDecMcuRowStart; + uint32_t nDecMcuRowEnd; // End to AC scan decoding + uint32_t nDecMcuRowEndFinal; // End to general decoding + + nDecMcuRowStart = 0; + nDecMcuRowEnd = m_nMcuYMax; + nDecMcuRowEndFinal = m_nMcuYMax; + + // Limit the decoding range to valid range + nDecMcuRowEnd = qMin(nDecMcuRowEnd, m_nMcuYMax); + nDecMcuRowEndFinal = qMin(nDecMcuRowEndFinal, m_nMcuYMax); + + // Allocate the MCU File Map + Q_ASSERT(m_pMcuFileMap == NULL); + m_pMcuFileMap = new uint32_t[m_nMcuYMax * m_nMcuXMax]; + + if(!m_pMcuFileMap) + { + strTmp = "ERROR: Not enough memory for Image Decoder MCU File Pos Map"; + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return; + } + + memset(m_pMcuFileMap, 0, (m_nMcuYMax * m_nMcuXMax * sizeof(uint32_t))); + + // Allocate the 8x8 Block DC Map + m_pBlkDcValY = new short[m_nBlkYMax * m_nBlkXMax]; + + if((!m_pBlkDcValY)) + { + strTmp = "ERROR: Not enough memory for Image Decoder Blk DC Value Map"; + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return; + } + + if(m_nNumSosComps == NUM_CHAN_YCC) + { + m_pBlkDcValCb = new short[m_nBlkYMax * m_nBlkXMax]; + + m_pBlkDcValCr = new short[m_nBlkYMax * m_nBlkXMax]; + + if((!m_pBlkDcValCb) || (!m_pBlkDcValCr)) + { + strTmp = "ERROR: Not enough memory for Image Decoder Blk DC Value Map"; + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return; + } + } + + memset(m_pBlkDcValY, 0, (m_nBlkYMax * m_nBlkXMax * sizeof(int16_t))); + + if(m_nNumSosComps == NUM_CHAN_YCC) + { + memset(m_pBlkDcValCb, 0, (m_nBlkYMax * m_nBlkXMax * sizeof(int16_t))); + memset(m_pBlkDcValCr, 0, (m_nBlkYMax * m_nBlkXMax * sizeof(int16_t))); + } + + // Allocate the real YCC pixel Map + nPixMapH = m_nBlkYMax * BLK_SZ_Y; + nPixMapW = m_nBlkXMax * BLK_SZ_X; + + // Ensure no image allocated yet + Q_ASSERT(m_pPixValY == NULL); + + if(m_nNumSosComps == NUM_CHAN_YCC) + { + Q_ASSERT(m_pPixValCb == NULL); + Q_ASSERT(m_pPixValCr == NULL); + } + + // Allocate image (YCC) + m_pPixValY = new short[nPixMapW * nPixMapH]; + + if((!m_pPixValY)) + { + strTmp = "ERROR: Not enough memory for Image Decoder Pixel YCC Value Map"; + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return; + } + + if(m_nNumSosComps == NUM_CHAN_YCC) + { + m_pPixValCb = new short[nPixMapW * nPixMapH]; + + m_pPixValCr = new short[nPixMapW * nPixMapH]; + + if((!m_pPixValCb) || (!m_pPixValCr)) + { + strTmp = "ERROR: Not enough memory for Image Decoder Pixel YCC Value Map"; + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return; + } + } + + // Reset pixel map + if(bDisplay) + { + ClrFullRes(nPixMapW, nPixMapH); + } + + // ------------------------------------- + // Allocate the device-independent bitmap (DIB) + + uint8_t *pDibImgTmpBits = NULL; + uint32_t nDibImgRowBytes; + + // If a previous bitmap was created, deallocate it and start fresh +//@@ m_pDibTemp.Kill(); + m_bDibTempReady = false; + m_bPreviewIsJpeg = false; + + // Create the DIB + // Although we are creating a 32-bit DIB, it should also + // work to run in 16- and 8-bit modes + + bool bDoImage = false; // Are we safe to set bits? + + if(bDisplay) + { +//@@ m_pDibTemp.CreateDIB(m_nImgSizeX, m_nImgSizeY, 32); + nDibImgRowBytes = m_nImgSizeX * sizeof(QRgb); +//@@ pDibImgTmpBits = (uint8_t *) (m_pDibTemp.GetDIBBitArray()); + +// if(pDibImgTmpBits) +// { +// bDoImage = true; +// } +// else +// { +// // TODO: Should we be exiting here instead? +// } + } + + // ------------------------------------- + + QString picStr; + + // Reset the DC cumulative state + DecodeRestartDcState(); + + // Reset the scan buffer + DecodeRestartScanBuf(nStart, false); + + // Load the buffer + m_pWBuf->BufLoadWindow(nStart); + + // Expect that we start with RST0 + m_nRestartExpectInd = 0; + m_nRestartLastInd = 0; + + // Load the first data into the scan buffer + // This is done so that the MCU map will already + // have access to the data. + BuffTopup(); + + if(!bQuiet) + { + m_pLog->AddLineHdr("*** Decoding SCAN Data ***"); + strTmp = QString(" OFFSET: 0x%1").arg(nStart, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + } + + // TODO: Might be more appropriate to check against m_nNumSosComps instead? + if((m_nNumSofComps != NUM_CHAN_GRAYSCALE) && (m_nNumSofComps != NUM_CHAN_YCC)) + { + strTmp = QString(" NOTE: Number of Image Components not supported [%1]").arg(m_nNumSofComps); + m_pLog->AddLineWarn(strTmp); +#ifndef DEBUG_YCCK + return; +#endif + } + + // Check DQT tables + // We need to ensure that the DQT Table selection has already + // been done (via a call from JfifDec to SetDqtTables() ). + uint32_t nDqtTblY = 0; + uint32_t nDqtTblCr = 0; + uint32_t nDqtTblCb = 0; + +#ifdef DEBUG_YCCK + uint32_t nDqtTblK = 0; +#endif + bool bDqtReady = true; + + for(uint32_t ind = 1; ind <= m_nNumSosComps; ind++) + { + if(m_anDqtTblSel[ind] < 0) + { + bDqtReady = false; + } + } + if(!bDqtReady) + { + m_pLog->AddLineErr("*** ERROR: Decoding image before DQT Table Selection via JFIF_SOF ***"); + // TODO: Is more error handling required? + return; + } + else + { + // FIXME: Not sure that we can always depend on the indices to appear + // in this order. May need another layer of indirection to get at the + // frame image component index. + nDqtTblY = m_anDqtTblSel[DQT_DEST_Y]; + nDqtTblCb = m_anDqtTblSel[DQT_DEST_CB]; + nDqtTblCr = m_anDqtTblSel[DQT_DEST_CR]; +#ifdef DEBUG_YCCK + if(m_nNumSosComps == 4) + { + nDqtTblK = m_anDqtTblSel[DQT_DEST_K]; + } +#endif + } + + // Now check DHT tables + bool bDhtReady = true; + + uint32_t nDhtTblDcY, nDhtTblDcCb, nDhtTblDcCr; + uint32_t nDhtTblAcY, nDhtTblAcCb, nDhtTblAcCr; + +#ifdef DEBUG_YCCK + uint32_t nDhtTblDcK, nDhtTblAcK; +#endif + for(uint32_t nClass = DHT_CLASS_DC; nClass <= DHT_CLASS_AC; nClass++) + { + for(uint32_t nCompInd = 1; nCompInd <= m_nNumSosComps; nCompInd++) + { + if(m_anDhtTblSel[nClass][nCompInd] < 0) + bDhtReady = false; + } + } + + // Ensure that the table has been defined already! + uint32_t nSel; + + for(uint32_t nCompInd = 1; nCompInd <= m_nNumSosComps; nCompInd++) + { + // Check for DC DHT table + nSel = m_anDhtTblSel[DHT_CLASS_DC][nCompInd]; + if(m_anDhtLookupSize[DHT_CLASS_DC][nSel] == 0) + { + bDhtReady = false; + } + // Check for AC DHT table + nSel = m_anDhtTblSel[DHT_CLASS_AC][nCompInd]; + if(m_anDhtLookupSize[DHT_CLASS_AC][nSel] == 0) + { + bDhtReady = false; + } + } + + if(!bDhtReady) + { + m_pLog->AddLineErr("*** ERROR: Decoding image before DHT Table Selection via JFIF_SOS ***"); + // TODO: Is more error handling required here? + return; + } + else + { + // Define the huffman table indices that are selected for each + // image component index and class (AC,DC). + // + // No need to check if a table is valid here since we have + // previously checked to ensure that all required tables + // exist. + // NOTE: If the table has not been defined, then the index + // will be 0xFFFFFFFF. ReadScanVal() will trap this with Q_ASSERT + // should it ever be used. + nDhtTblDcY = m_anDhtTblSel[DHT_CLASS_DC][COMP_IND_YCC_Y]; + nDhtTblAcY = m_anDhtTblSel[DHT_CLASS_AC][COMP_IND_YCC_Y]; + nDhtTblDcCb = m_anDhtTblSel[DHT_CLASS_DC][COMP_IND_YCC_CB]; + nDhtTblAcCb = m_anDhtTblSel[DHT_CLASS_AC][COMP_IND_YCC_CB]; + nDhtTblDcCr = m_anDhtTblSel[DHT_CLASS_DC][COMP_IND_YCC_CR]; + nDhtTblAcCr = m_anDhtTblSel[DHT_CLASS_AC][COMP_IND_YCC_CR]; +#ifdef DEBUG_YCCK + nDhtTblDcK = m_anDhtTblSel[DHT_CLASS_DC][COMP_IND_YCC_K]; + nDhtTblAcK = m_anDhtTblSel[DHT_CLASS_AC][COMP_IND_YCC_K]; +#endif + } + + // Done checks + + // Inform if they are in AC+DC/DC mode + if(!bQuiet) + { + if(m_bDecodeScanAc) + { + m_pLog->AddLine(" Scan Decode Mode: Full IDCT (AC + DC)"); + } + else + { + m_pLog->AddLine(" Scan Decode Mode: No IDCT (DC only)"); + m_pLog-> + AddLineWarn(" NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT]"); + } + m_pLog->AddLine(""); + } + + // Report any Buffer overlays + m_pWBuf->ReportOverlays(m_pLog); + + m_nNumPixels = 0; + + // Clear the histogram and color correction clipping stats + if(bDisplay) + { + memset(&m_sStatClip, 0, sizeof(m_sStatClip)); + memset(&m_sHisto, 0, sizeof(m_sHisto)); + + // FIXME: Histo should now be done after color convert + memset(&m_anCcHisto_r, 0, sizeof(m_anCcHisto_r)); + memset(&m_anCcHisto_g, 0, sizeof(m_anCcHisto_g)); + memset(&m_anCcHisto_b, 0, sizeof(m_anCcHisto_b)); + + memset(&m_anHistoYFull, 0, sizeof(m_anHistoYFull)); + memset(&m_anHistoYSubset, 0, sizeof(m_anHistoYSubset)); + } + + // ----------------------------------------------------------------------- + // Process all scan MCUs + // ----------------------------------------------------------------------- + + for(uint32_t nMcuY = nDecMcuRowStart; nMcuY < nDecMcuRowEndFinal; nMcuY++) + { + // Set the statusbar text to Processing... + strTmp = QString("Decoding Scan Data... Row %1 of %2 (%3%%)") + .arg(nMcuY, 4, 10, QChar('0')) + .arg(m_nMcuYMax, 4, 10, QChar('0')) + .arg(nMcuY * 100.0 / m_nMcuYMax, 3, 'f', 0); + SetStatusText(strTmp); + + // TODO: Trap escape keypress here (or run as thread) + + bool bDscRet; // Return value for DecodeScanComp() + + bool bScanStop = false; + + for(uint32_t nMcuX = 0; (nMcuX < m_nMcuXMax) && (!bScanStop); nMcuX++) + { + + // Check to see if we should expect a restart marker! + // FIXME: Should actually check to ensure that we do in + // fact get a restart marker, and that it was the right + // one! + if((m_bRestartEn) && (m_nRestartMcusLeft == 0)) + { + /* + if (m_bVerbose) { + strTmp = QString(" Expect Restart interval elapsed @ %s"),GetScanBufPos(); + m_pLog->AddLine(strTmp); + } + */ + if(m_bRestartRead) + { + /* + // FIXME: Check for restart counter value match + if (m_bVerbose) { + strTmp = QString(" Restart marker matched"); + m_pLog->AddLine(strTmp); + } + */ + } + else + { + strTmp = QString(" Expect Restart interval elapsed @ %1").arg(GetScanBufPos()); + m_pLog->AddLine(strTmp); + strTmp = QString(" ERROR: Restart marker not detected"); + m_pLog->AddLineErr(strTmp); + } + /* + if (ExpectRestart()) { + if (m_bVerbose) { + strTmp = QString(" Restart marker detected"); + m_pLog->AddLine(strTmp); + } + } else { + strTmp = QString(" ERROR: Restart marker expected but not found @ %s"),GetScanBufPos(); + m_pLog->AddLineErr(strTmp); + } + */ + + } + + // To support a fast decode mode, allow for a subset of the + // image to have DC+AC decoding, while the remainder is only DC decoding + if((nMcuY < nDecMcuRowStart) || (nMcuY > nDecMcuRowEnd)) + { + m_bDecodeScanAc = false; + } + else + { + m_bDecodeScanAc = bDecodeScanAc; + } + + // Precalculate MCU matrix index + uint32_t nMcuXY = nMcuY * m_nMcuXMax + nMcuX; + + // Mark the start of the MCU in the file map + m_pMcuFileMap[nMcuXY] = PackFileOffset(m_anScanBuffPtr_pos[0], m_nScanBuffPtr_align); + + // Is this an MCU that we want full printing of decode process? + bool bVlcDump = false; + + uint32_t nRangeBase; + uint32_t nRangeCur; + + if(m_bDetailVlc) + { + nRangeBase = (m_nDetailVlcY * m_nMcuXMax) + m_nDetailVlcX; + nRangeCur = nMcuXY; + + if((nRangeCur >= nRangeBase) && (nRangeCur < nRangeBase + m_nDetailVlcLen)) + { + bVlcDump = true; + } + } + + // Luminance + // If there is chroma subsampling, then this block will have + // (css_x * css_y) luminance blocks to process + // We store them all in an array m_anDcLumCss[] + + // Give separator line between MCUs + if(bVlcDump) + { + m_pLog->AddLine(""); + } + + // CSS array indices + uint32_t nCssIndH; + uint32_t nCssIndV; + uint32_t nComp; + + // No need to reset the IDCT output matrix for this MCU + // since we are going to be generating it here. This help + // maintain performance. + + // -------------------------------------------------------------- + nComp = SCAN_COMP_Y; + + // Step through the sampling factors per image component + // TODO: Could rewrite this to use single loop across each image component + for(nCssIndV = 0; nCssIndV < m_anSampPerMcuV[nComp]; nCssIndV++) + { + for(nCssIndH = 0; nCssIndH < m_anSampPerMcuH[nComp]; nCssIndH++) + { + if(!bVlcDump) + { + bDscRet = DecodeScanComp(nDhtTblDcY, nDhtTblAcY, nDqtTblY, nMcuX, nMcuY); // Lum DC+AC + } + else + { + bDscRet = DecodeScanCompPrint(nDhtTblDcY, nDhtTblAcY, nDqtTblY, nMcuX, nMcuY); // Lum DC+AC + } + + if(m_nScanCurErr) + { + CheckScanErrors(nMcuX, nMcuY, nCssIndH, nCssIndV, nComp); + } + + if(!bDscRet && bDieOnFirstErr) + { + return; + } + + // The DCT Block matrix has already been dezigzagged + // and multiplied against quantization table entry + m_nDcLum += m_anDctBlock[DCT_COEFF_DC]; + + if(bVlcDump) + { +// PrintDcCumVal(nMcuX,nMcuY,m_nDcLum); + } + + // Now take a snapshot of the current cumulative DC value + m_anDcLumCss[nCssIndV * MAX_SAMP_FACT_H + nCssIndH] = m_nDcLum; + + // At this point we have one of the luminance comps + // fully decoded (with IDCT if enabled). The result is + // currently in the array: m_afIdctBlock[] + // The next step would be to move these elements into + // the 3-channel MCU image map + + // Store the pixels associated with this channel into + // the full-res pixel map. IDCT has already been computed + // on the 8x8 (or larger) MCU block region. + +#if 1 + if(bDisplay) + SetFullRes(nMcuX, nMcuY, nComp, nCssIndH, nCssIndV, m_nDcLum); +#else + // FIXME + // Temporarily experiment with trying to handle multiple scans + // by converting sampling factor of luminance scan back to 1x1 + uint32_t nNewMcuX, nNewMcuY, nNewCssX, nNewCssY; + + if(nCssIndV == 0) + { + if(nMcuX < m_nMcuXMax / 2) + { + nNewMcuX = nMcuX; + nNewMcuY = nMcuY; + nNewCssY = 0; + } + else + { + nNewMcuX = nMcuX - (m_nMcuXMax / 2); + nNewMcuY = nMcuY; + nNewCssY = 1; + } + nNewCssX = nCssIndH; + SetFullRes(nNewMcuX, nNewMcuY, SCAN_COMP_Y, nNewCssX, nNewCssY, m_nDcLum); + } + else + { + nNewMcuX = (nMcuX / 2) + 1; + nNewMcuY = (nMcuY / 2); + nNewCssX = nCssIndH; + nNewCssY = nMcuY % 2; + } +#endif + + // --------------- + + // TODO: Counting pixels makes assumption that luminance is + // not subsampled, so we increment by 64. + m_nNumPixels += BLK_SZ_X * BLK_SZ_Y; + + } + } + + // In a grayscale image, we don't do this part! + //if (m_nNumSofComps == NUM_CHAN_YCC) { + if(m_nNumSosComps == NUM_CHAN_YCC) + { + // -------------------------------------------------------------- + nComp = SCAN_COMP_CB; + + // Chrominance Cb + for(nCssIndV = 0; nCssIndV < m_anSampPerMcuV[nComp]; nCssIndV++) + { + for(nCssIndH = 0; nCssIndH < m_anSampPerMcuH[nComp]; nCssIndH++) + { + if(!bVlcDump) + { + bDscRet = DecodeScanComp(nDhtTblDcCb, nDhtTblAcCb, nDqtTblCb, nMcuX, nMcuY); // Chr Cb DC+AC + } + else + { + bDscRet = DecodeScanCompPrint(nDhtTblDcCb, nDhtTblAcCb, nDqtTblCb, nMcuX, nMcuY); // Chr Cb DC+AC + } + + if(m_nScanCurErr) + { + CheckScanErrors(nMcuX, nMcuY, nCssIndH, nCssIndV, nComp); + } + + if(!bDscRet && bDieOnFirstErr) + { + return; + } + + m_nDcChrCb += m_anDctBlock[DCT_COEFF_DC]; + + if(bVlcDump) + { + //PrintDcCumVal(nMcuX,nMcuY,m_nDcChrCb); + } + + // Now take a snapshot of the current cumulative DC value + m_anDcChrCbCss[nCssIndV * MAX_SAMP_FACT_H + nCssIndH] = m_nDcChrCb; + + // Store fullres value + if(bDisplay) + { + SetFullRes(nMcuX, nMcuY, nComp, nCssIndH, nCssIndV, m_nDcChrCb); + } + } + } + + // -------------------------------------------------------------- + nComp = SCAN_COMP_CR; + + // Chrominance Cr + for(nCssIndV = 0; nCssIndV < m_anSampPerMcuV[nComp]; nCssIndV++) + { + for(nCssIndH = 0; nCssIndH < m_anSampPerMcuH[nComp]; nCssIndH++) + { + if(!bVlcDump) + { + bDscRet = DecodeScanComp(nDhtTblDcCr, nDhtTblAcCr, nDqtTblCr, nMcuX, nMcuY); // Chr Cr DC+AC + } + else + { + bDscRet = DecodeScanCompPrint(nDhtTblDcCr, nDhtTblAcCr, nDqtTblCr, nMcuX, nMcuY); // Chr Cr DC+AC + } + + if(m_nScanCurErr) + { + CheckScanErrors(nMcuX, nMcuY, nCssIndH, nCssIndV, nComp); + } + + if(!bDscRet && bDieOnFirstErr) + { + return; + } + + m_nDcChrCr += m_anDctBlock[DCT_COEFF_DC]; + + if(bVlcDump) + { + //PrintDcCumVal(nMcuX,nMcuY,m_nDcChrCr); + } + + // Now take a snapshot of the current cumulative DC value + m_anDcChrCrCss[nCssIndV * MAX_SAMP_FACT_H + nCssIndH] = m_nDcChrCr; + + // Store fullres value + if(bDisplay) + { + SetFullRes(nMcuX, nMcuY, nComp, nCssIndH, nCssIndV, m_nDcChrCr); + } + } + } + + } +#ifdef DEBUG_YCCK + else if(m_nNumSosComps == NUM_CHAN_YCCK) + { + + // -------------------------------------------------------------- + nComp = SCAN_COMP_CB; + + // Chrominance Cb + for(nCssIndV = 0; nCssIndV < m_anSampPerMcuV[nComp]; nCssIndV++) + { + for(nCssIndH = 0; nCssIndH < m_anSampPerMcuH[nComp]; nCssIndH++) + { + if(!bVlcDump) + { + bDscRet = DecodeScanComp(nDhtTblDcCb, nDhtTblAcCb, nDqtTblCb, nMcuX, nMcuY); // Chr Cb DC+AC + } + else + { + bDscRet = DecodeScanCompPrint(nDhtTblDcCb, nDhtTblAcCb, nDqtTblCb, nMcuX, nMcuY); // Chr Cb DC+AC + } + + if(m_nScanCurErr) + { + CheckScanErrors(nMcuX, nMcuY, nCssIndH, nCssIndV, nComp); + } + + if(!bDscRet && bDieOnFirstErr) + { + return; + } + + m_nDcChrCb += m_anDctBlock[DCT_COEFF_DC]; + + if(bVlcDump) + { + //PrintDcCumVal(nMcuX,nMcuY,m_nDcChrCb); + } + + // Now take a snapshot of the current cumulative DC value + m_anDcChrCbCss[nCssIndV * MAX_SAMP_FACT_H + nCssIndH] = m_nDcChrCb; + + // Store fullres value + if(bDisplay) + { + SetFullRes(nMcuX, nMcuY, nComp, 0, 0, m_nDcChrCb); + } + } + } + + // -------------------------------------------------------------- + nComp = SCAN_COMP_CR; + + // Chrominance Cr + for(nCssIndV = 0; nCssIndV < m_anSampPerMcuV[nComp]; nCssIndV++) + { + for(nCssIndH = 0; nCssIndH < m_anSampPerMcuH[nComp]; nCssIndH++) + { + if(!bVlcDump) + { + bDscRet = DecodeScanComp(nDhtTblDcCr, nDhtTblAcCr, nDqtTblCr, nMcuX, nMcuY); // Chr Cr DC+AC + } + else + { + bDscRet = DecodeScanCompPrint(nDhtTblDcCr, nDhtTblAcCr, nDqtTblCr, nMcuX, nMcuY); // Chr Cr DC+AC + } + + if(m_nScanCurErr) + CheckScanErrors(nMcuX, nMcuY, nCssIndH, nCssIndV, nComp); + + if(!bDscRet && bDieOnFirstErr) + return; + + m_nDcChrCr += m_anDctBlock[DCT_COEFF_DC]; + + if(bVlcDump) + { + //PrintDcCumVal(nMcuX,nMcuY,m_nDcChrCr); + } + + // Now take a snapshot of the current cumulative DC value + m_anDcChrCrCss[nCssIndV * MAX_SAMP_FACT_H + nCssIndH] = m_nDcChrCr; + + // Store fullres value + if(bDisplay) + SetFullRes(nMcuX, nMcuY, nComp, 0, 0, m_nDcChrCr); + } + } + + // -------------------------------------------------------------- + // IGNORED + nComp = SCAN_COMP_K; + + // Black K + for(nCssIndV = 0; nCssIndV < m_anSampPerMcuV[nComp]; nCssIndV++) + { + for(nCssIndH = 0; nCssIndH < m_anSampPerMcuH[nComp]; nCssIndH++) + { + + if(!bVlcDump) + { + bDscRet = DecodeScanComp(nDhtTblDcK, nDhtTblAcK, nDqtTblK, nMcuX, nMcuY); // K DC+AC + } + else + { + bDscRet = DecodeScanCompPrint(nDhtTblDcK, nDhtTblAcK, nDqtTblK, nMcuX, nMcuY); // K DC+AC + } + + if(m_nScanCurErr) + CheckScanErrors(nMcuX, nMcuY, nCssIndH, nCssIndV, nComp); + + if(!bDscRet && bDieOnFirstErr) + return; + +/* + m_nDcChrK += m_anDctBlock[DCT_COEFF_DC]; + + if (bVlcDump) { + //PrintDcCumVal(nMcuX,nMcuY,m_nDcChrCb); + } + + // Now take a snapshot of the current cumulative DC value + m_anDcChrKCss[nCssIndV*MAX_SAMP_FACT_H+nCssIndH] = m_nDcChrK; + + // Store fullres value + if (bDisplay) + SetFullRes(nMcuX,nMcuY,nComp,0,0,m_nDcChrK); +*/ + + } + } + } +#endif + // -------------------------------------------------------------------- + + uint32_t nBlkXY; + + // Now save the DC YCC values (expanded per 8x8 block) + // without ranging or translation into RGB. + // + // We enter this code once per MCU so we need to expand + // out to cover all blocks in this MCU. + + // -------------------------------------------------------------- + nComp = SCAN_COMP_Y; + + // Calculate top-left corner of MCU in block map + // and then linear offset into block map + uint32_t nBlkCornerMcuX, nBlkCornerMcuY, nBlkCornerMcuLinear; + + nBlkCornerMcuX = nMcuX * m_anExpandBitsMcuH[nComp]; + nBlkCornerMcuY = nMcuY * m_anExpandBitsMcuV[nComp]; + nBlkCornerMcuLinear = (nBlkCornerMcuY * m_nBlkXMax) + nBlkCornerMcuX; + + // Now step through each block in the MCU per subsampling + for(nCssIndV = 0; nCssIndV < m_anSampPerMcuV[nComp]; nCssIndV++) + { + for(nCssIndH = 0; nCssIndH < m_anSampPerMcuH[nComp]; nCssIndH++) + { + // Calculate upper-left Blk index + // FIXME: According to code analysis the following write assignment + // to m_pBlkDcValY[] can apparently exceed the buffer bounds (C6386). + // I have not yet determined what scenario can lead to + // this. So for now, add in specific clause to trap and avoid. + nBlkXY = nBlkCornerMcuLinear + (nCssIndV * m_nBlkXMax) + nCssIndH; + + // FIXME: Temporarily catch any range issue + if(nBlkXY >= m_nBlkXMax * m_nBlkYMax) + { +#ifdef DEBUG_LOG + QString strDebug; + + strTmp = + QString("DecodeScanImg() with nBlkXY out of range. nBlkXY=[%1] m_nBlkXMax=[%2] m_nBlkYMax=[%3]").arg(nBlkXY). + arg(m_nBlkXMax).arg(m_nBlkYMax); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("ImgDecode", -10).arg(strTmp); + qDebug() << strDebug; +#else + Q_ASSERT(false); +#endif + } + else + { + m_pBlkDcValY[nBlkXY] = m_anDcLumCss[nCssIndV * MAX_SAMP_FACT_H + nCssIndH]; + } + } + } + + // Only process the chrominance if it is YCC + if(m_nNumSosComps == NUM_CHAN_YCC) + { + // -------------------------------------------------------------- + nComp = SCAN_COMP_CB; + + for(nCssIndV = 0; nCssIndV < m_anSampPerMcuV[nComp]; nCssIndV++) + { + for(nCssIndH = 0; nCssIndH < m_anSampPerMcuH[nComp]; nCssIndH++) + { + // Calculate upper-left Blk index + nBlkXY = (nMcuY * m_anExpandBitsMcuV[nComp] + nCssIndV) * m_nBlkXMax + (nMcuX * m_anExpandBitsMcuH[nComp] + nCssIndH); + + // FIXME: Temporarily catch any range issue + if(nBlkXY >= m_nBlkXMax * m_nBlkYMax) + { +#ifdef DEBUG_LOG + QString strDebug; + + strTmp = QString("DecodeScanImg() with nBlkXY out of range. nBlkXY=[%1] m_nBlkXMax=[%2] m_nBlkYMax=[%3]").arg(nBlkXY).arg(m_nBlkXMax).arg(m_nBlkYMax); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("ImgDecode", -10).arg(strTmp); + qDebug() << strDebug; +#else + Q_ASSERT(false); +#endif + } + else + { + m_pBlkDcValCb[nBlkXY] = m_anDcChrCbCss[nCssIndV * MAX_SAMP_FACT_H + nCssIndH]; + } + } + } + + // -------------------------------------------------------------- + nComp = SCAN_COMP_CR; + + for(nCssIndV = 0; nCssIndV < m_anSampPerMcuV[nComp]; nCssIndV++) + { + for(nCssIndH = 0; nCssIndH < m_anSampPerMcuH[nComp]; nCssIndH++) + { + // Calculate upper-left Blk index + nBlkXY = (nMcuY * m_anExpandBitsMcuV[nComp] + nCssIndV) * m_nBlkXMax + (nMcuX * m_anExpandBitsMcuH[nComp] + nCssIndH); + + // FIXME: Temporarily catch any range issue + if(nBlkXY >= m_nBlkXMax * m_nBlkYMax) + { +#ifdef DEBUG_LOG + QString strDebug; + + strTmp = QString("DecodeScanImg() with nBlkXY out of range. nBlkXY=[%1] m_nBlkXMax=[%2] m_nBlkYMax=[%3]").arg(nBlkXY).arg(m_nBlkXMax).arg(m_nBlkYMax); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("ImgDecode", -10).arg(strTmp); + qDebug() << strDebug; +#else + Q_ASSERT(false); +#endif + } + else + { + m_pBlkDcValCr[nBlkXY] = m_anDcChrCrCss[nCssIndV * MAX_SAMP_FACT_H + nCssIndH]; + } + } + } + } + + // Now that we finished an MCU, decrement the restart interval counter + if(m_bRestartEn) + { + m_nRestartMcusLeft--; + } + + // Check to see if we need to abort for some reason. + // Note that only check m_bScanEnd if we have a failure. + // m_bScanEnd is Q_ASSERTed during normal out-of-data when scan + // segment ends with marker. We don't want to abort early + // or else we'll not decode the last MCU or two! + if(m_bScanEnd && m_bScanBad) + { + bScanStop = true; + } + } // nMcuX + + } // nMcuY + + if(!bQuiet) + { + m_pLog->AddLine(""); + } + + // --------------------------------------------------------- + + // Now we can create the final preview. Since we have just finished + // decoding a new image, we need to ensure that we invalidate + // the temporary preview (multi-channel option). Done earlier + // with PREVIEW_NONE + if(bDisplay) + { + CalcChannelPreview(); + } + + // DIB is ready for display now + if(bDisplay) + { + m_bDibTempReady = true; + m_bPreviewIsJpeg = true; + update(); + } + + // ------------------------------------ + // Report statistics + + if(!bQuiet) + { + // Report Compression stats + // TODO: Should we use m_nNumSofComps? + strTmp = QString(" Compression stats:"); + m_pLog->AddLine(strTmp); + double nCompressionRatio = + static_cast(m_nDimX * m_nDimY * m_nNumSosComps * 8) / + static_cast((m_anScanBuffPtr_pos[0] - m_nScanBuffPtr_first) * 8); + strTmp = QString(" Compression Ratio: %1:1").arg(nCompressionRatio, 5, 'f', 2); + m_pLog->AddLine(strTmp); + double nBitsPerPixel = static_cast((m_anScanBuffPtr_pos[0] - m_nScanBuffPtr_first) * 8) / + static_cast(m_nDimX * m_nDimY); + + strTmp = QString(" Bits per pixel: %1:1").arg(nBitsPerPixel, 5, 'f', 2); + m_pLog->AddLine(strTmp); + m_pLog->AddLine(""); + + // Report Huffman stats + strTmp = QString(" Huffman code histogram stats:"); + m_pLog->AddLine(strTmp); + + uint32_t nDhtHistoTotal; + + for(uint32_t nClass = DHT_CLASS_DC; nClass <= DHT_CLASS_AC; nClass++) + { + for(uint32_t nDhtDestId = 0; nDhtDestId <= m_anDhtLookupSetMax[nClass]; nDhtDestId++) + { + nDhtHistoTotal = 0; + + for(uint32_t nBitLen = 1; nBitLen <= MAX_DHT_CODELEN; nBitLen++) + { + nDhtHistoTotal += m_anDhtHisto[nClass][nDhtDestId][nBitLen]; + } + + strTmp = QString(" Huffman Table: (Dest ID: %1, Class: %2)").arg(nDhtDestId).arg(nClass?"AC":"DC"); + m_pLog->AddLine(strTmp); + + for(uint32_t nBitLen = 1; nBitLen <= MAX_DHT_CODELEN; nBitLen++) + { + strTmp = QString(" # codes of length %1 bits: %2 (%3%)") + .arg(nBitLen, 2, 10, QChar('0')) + .arg(m_anDhtHisto[nClass][nDhtDestId][nBitLen], 8) + .arg((m_anDhtHisto[nClass][nDhtDestId][nBitLen]*100.0)/nDhtHistoTotal, 3, 'f', 0); + m_pLog->AddLine(strTmp); + } + + m_pLog->AddLine(""); + } + } + + // Report YCC stats + ReportColorStats(); + } // !bQuiet + + // ------------------------------------ + + // Display the image histogram if enabled + if(bDisplay && m_bHistEn) + { + DrawHistogram(bQuiet, bDumpHistoY); + } + + if(bDisplay && m_bAvgYValid) + { + m_pLog->AddLine(" Average Pixel Luminance (Y):"); + strTmp = QString(" Y=[%1] (range: 0..255)").arg(m_nAvgY, 3); + m_pLog->AddLine(strTmp); + m_pLog->AddLine(""); + } + + if(bDisplay && m_bBrightValid) + { + m_pLog->AddLine(" Brightest Pixel Search:"); + strTmp = QString(" YCC=[%1,%2,%3] RGB=[%4,%5,%6] @ MCU[%7,%8]") + .arg(m_nBrightY, 5) + .arg(m_nBrightCb, 5) + .arg(m_nBrightCr, 5) + .arg(m_nBrightR, 3) + .arg(m_nBrightG, 3) + .arg(m_nBrightB, 3) + .arg(m_ptBrightMcu.x(), 3) + .arg(m_ptBrightMcu.y(), 3); + m_pLog->AddLine(strTmp); + m_pLog->AddLine(""); + } + + // -------------------------------------- + + if(!bQuiet) + { + m_pLog->AddLine(" Finished Decoding SCAN Data"); + strTmp = QString(" Number of RESTART markers decoded: %1").arg(m_nRestartRead); + m_pLog->AddLine(strTmp); + strTmp = QString(" Next position in scan buffer: Offset %1").arg(GetScanBufPos()); + m_pLog->AddLine(strTmp); + + m_pLog->AddLine(""); + } + + // -------------------------------------- + // Write out the full Y histogram if requested! + + QString strFull; + + if(bDisplay && m_bHistEn && bDumpHistoY) + { + ReportHistogramY(); + } +} + +// +// Report if image preview is ready to display +// +// RETURN: +// - True if image preview is ready +// +bool CimgDecode::IsPreviewReady() +{ + return m_bPreviewIsJpeg; +} + +// Report out the color conversion statistics +// +// PRE: +// - m_sStatClip +// - m_sHisto +// +void CimgDecode::ReportColorStats() +{ + QString strTmp; + + // Report YCC stats + if(CC_CLIP_YCC_EN) + { + strTmp = QString(" YCC clipping in DC:"); + m_pLog->AddLine(strTmp); + strTmp = QString(" Y component: [<0=%1] [>255=%2]").arg(m_sStatClip.nClipYUnder, 5).arg( m_sStatClip.nClipYOver, 5); + m_pLog->AddLine(strTmp); + strTmp = QString(" Cb component: [<0=%1] [>255=%2]").arg(m_sStatClip.nClipCbUnder, 5).arg( m_sStatClip.nClipCbOver, 5); + m_pLog->AddLine(strTmp); + strTmp = QString(" Cr component: [<0=%1] [>255=%2]").arg(m_sStatClip.nClipCrUnder, 5).arg( m_sStatClip.nClipCrOver, 5); + m_pLog->AddLine(strTmp); + m_pLog->AddLine(""); + } + + if(m_bHistEn) + { + strTmp = QString(" YCC histogram in DC (DCT sums : pre-ranged:"); + m_pLog->AddLine(strTmp); + strTmp = QString(" Y component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nPreclipYMin, 5) + .arg(m_sHisto.nPreclipYMax, 5) + .arg(static_cast(m_sHisto.nPreclipYSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + strTmp = QString(" Cb component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nPreclipCbMin, 5) + .arg(m_sHisto.nPreclipCbMax, 5) + .arg(static_cast(m_sHisto.nPreclipCbSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + strTmp = QString(" Cr component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nPreclipCrMin, 5) + .arg(m_sHisto.nPreclipCrMax, 5) + .arg(static_cast(m_sHisto.nPreclipCrSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + m_pLog->AddLine(""); + + strTmp = QString(" YCC histogram in DC:"); + m_pLog->AddLine(strTmp); + strTmp = QString(" Y component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nClipYMin, 5) + .arg(m_sHisto.nClipYMax, 5) + .arg(static_cast(m_sHisto.nClipYSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + strTmp = QString(" Cb component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nClipCbMin, 5) + .arg(m_sHisto.nClipCbMax, 5) + .arg(static_cast(m_sHisto.nClipCbSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + strTmp = QString(" Cr component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nClipCrMin, 5) + .arg(m_sHisto.nClipCrMax, 5) + .arg(static_cast(m_sHisto.nClipCrSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + m_pLog->AddLine(""); + + strTmp = QString(" RGB histogram in DC (before clip):"); + m_pLog->AddLine(strTmp); + strTmp = QString(" R component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nPreclipRMin, 5) + .arg(m_sHisto.nPreclipRMax, 5) + .arg(static_cast(m_sHisto.nPreclipRSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + strTmp = QString(" G component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nPreclipGMin, 5) + .arg(m_sHisto.nPreclipGMax, 5) + .arg(static_cast(m_sHisto.nPreclipGSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + strTmp = QString(" B component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nPreclipBMin, 5) + .arg(m_sHisto.nPreclipBMax, 5) + .arg(static_cast(m_sHisto.nPreclipBSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + m_pLog->AddLine(""); + } + + strTmp = QString(" RGB clipping in DC:"); + m_pLog->AddLine(strTmp); + strTmp = QString(" R component: [<0=%1] [>255=%2]") + .arg(m_sStatClip.nClipRUnder, 5) + .arg(m_sStatClip.nClipROver, 5); + m_pLog->AddLine(strTmp); + strTmp = QString(" G component: [<0=%1] [>255=%2]") + .arg(m_sStatClip.nClipGUnder, 5) + .arg(m_sStatClip.nClipGOver, 5); + m_pLog->AddLine(strTmp); + strTmp = QString(" B component: [<0=%1] [>255=%2]") + .arg(m_sStatClip.nClipBUnder, 5) + .arg(m_sStatClip.nClipBOver, 5); + m_pLog->AddLine(strTmp); + /* + strTmp = QString(" White Highlight: [>255=%5u]")).arg(m_sStatClip.nClipWhiteOver; + m_pLog->AddLine(strTmp); + */ + m_pLog->AddLine(""); +} + +// Report the histogram stats from the Y component +// +// PRE: +// - m_anHistoYFull +// +void CimgDecode::ReportHistogramY() +{ + QString strFull; + QString strTmp; + + m_pLog->AddLine(" Y Histogram in DC: (DCT sums) Full"); + + for(uint32_t row = 0; row < 2048 / 8; row++) + { + strFull = QString(" Y=%1..%2: ") + .arg(-1024 + (static_cast(row) * 8), 5) + .arg(-1024 + (static_cast(row) * 8) + 7, 5); + + for(uint32_t col = 0; col < 8; col++) + { + strTmp = QString("0x%1, ").arg(m_anHistoYFull[col + row * 8], 6, 16, QChar('0')); + strFull += strTmp; + } + + m_pLog->AddLine(strFull); + } +} + +// Draw the histograms (RGB and/or Y) +// +// INPUT: +// - bQuiet = Calculate stats without reporting to log? +// - bDumpHistoY = Generate the Y histogram? +// PRE: +// - m_sHisto +// +void CimgDecode::DrawHistogram(bool bQuiet, bool bDumpHistoY) +{ + QString strTmp; + + if(!bQuiet) + { + strTmp = QString(" RGB histogram in DC (after clip):"); + m_pLog->AddLine(strTmp); + strTmp = QString(" R component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nClipRMin, 5) + .arg(m_sHisto.nClipRMax, 5) + .arg(static_cast(m_sHisto.nClipRSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + strTmp = QString(" G component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nClipGMin, 5) + .arg(m_sHisto.nClipGMax, 5) + .arg(static_cast(m_sHisto.nClipGSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + strTmp = QString(" B component histo: [min=%1 max=%2 avg=%3]") + .arg(m_sHisto.nClipBMin, 5) + .arg(m_sHisto.nClipBMax, 5) + .arg(static_cast(m_sHisto.nClipBSum) / static_cast(m_sHisto.nCount), 7, 'f', 1); + m_pLog->AddLine(strTmp); + m_pLog->AddLine(""); + } + + // -------------------------------------- + // Now draw the RGB histogram! + + int32_t nCoordY; + int32_t rgbHistOffset; + int32_t nHistoBinHeight; + int32_t nHistoPeakVal; + int32_t nHistoX; + int32_t nHistoCurVal; +// int32_t nDibHistoRowBytes; +// int8_t *pDibHistoBits; + +//@@ m_pDibHistRgb.Kill(); + m_bDibHistRgbReady = false; + + m_pDibHistRgb = new QImage(HISTO_BINS * HISTO_BIN_WIDTH, 3 * HISTO_BIN_HEIGHT_MAX, QImage::Format_RGB32); + +//@@ m_pDibHistRgb.CreateDIB(HISTO_BINS * HISTO_BIN_WIDTH, 3 * HISTO_BIN_HEIGHT_MAX, 32); +// nDibHistoRowBytes = (HISTO_BINS * HISTO_BIN_WIDTH) * 4; +//@@ pDibHistoBits = (uint8_t *) (m_pDibHistRgb.GetDIBBitArray()); + +// m_rectHistBase = QRect(QPoint(0, 0), QSize(HISTO_BINS * HISTO_BIN_WIDTH, 3 * HISTO_BIN_HEIGHT_MAX)); + +// if(pDibHistoBits != NULL) +// { +// memset(pDibHistoBits, 0, 3 * HISTO_BIN_HEIGHT_MAX * nDibHistoRowBytes); + + // Do peak detect first + // Don't want to reset peak value to 0 as otherwise we might get + // division by zero later when we calculate nHistoBinHeight + nHistoPeakVal = 1; + + // Peak value is across all three channels! + for(int32_t nHistChan = 0; nHistChan < 3; nHistChan++) + { + for(int32_t i = 0; i < HISTO_BINS; i++) + { + if(nHistChan == 0) + { + nHistoCurVal = m_anCcHisto_r[i]; + } + else if(nHistChan == 1) + { + nHistoCurVal = m_anCcHisto_g[i]; + } + else + { + nHistoCurVal = m_anCcHisto_b[i]; + } + + nHistoPeakVal = (nHistoCurVal > nHistoPeakVal) ? nHistoCurVal : nHistoPeakVal; + } + } + + for(int32_t nHistChan = 0; nHistChan < 3; nHistChan++) + { + for(int32_t i = 0; i < HISTO_BINS; i++) + { + // Calculate bin's height (max HISTO_BIN_HEIGHT_MAX) + if(nHistChan == CHAN_R) + { + nHistoCurVal = m_anCcHisto_r[i]; + rgbHistOffset = HISTO_BIN_HEIGHT_MAX - 1; + } + else if(nHistChan == CHAN_G) + { + nHistoCurVal = m_anCcHisto_g[i]; + rgbHistOffset = HISTO_BIN_HEIGHT_MAX * 2 - 1; + } + else + { + nHistoCurVal = m_anCcHisto_b[i]; + rgbHistOffset = HISTO_BIN_HEIGHT_MAX * 3 - 1; + } + + nHistoBinHeight = HISTO_BIN_HEIGHT_MAX * nHistoCurVal / nHistoPeakVal; + + for(int32_t y = 0; y < nHistoBinHeight; y++) + { + // Store the RGB triplet + for(int32_t bin_width = 0; bin_width < HISTO_BIN_WIDTH; bin_width++) + { + nHistoX = (i * HISTO_BIN_WIDTH) + bin_width; +// nCoordY = ((2 - nHistChan) * HISTO_BIN_HEIGHT_MAX) + y; + nCoordY = (rgbHistOffset - y) -1; + m_pDibHistRgb->setPixelColor(nHistoX, nCoordY, QColor((nHistChan == CHAN_R) ? 255 : 0, (nHistChan == CHAN_G) ? 255 : 0, (nHistChan == CHAN_B) ? 255 : 0)); + +// pDibHistoBits[(nHistoX * 4) + 3 + (nCoordY * nDibHistoRowBytes)] = 0; +// pDibHistoBits[(nHistoX * 4) + 2 + (nCoordY * nDibHistoRowBytes)] = (nHistChan == 0) ? 255 : 0; +// pDibHistoBits[(nHistoX * 4) + 1 + (nCoordY * nDibHistoRowBytes)] = (nHistChan == 1) ? 255 : 0; +// pDibHistoBits[(nHistoX * 4) + 0 + (nCoordY * nDibHistoRowBytes)] = (nHistChan == 2) ? 255 : 0; + } + } + } // i: 0..HISTO_BINS-1 +// } // nHistChan + + m_bDibHistRgbReady = true; + } + + // Only create the Y DC Histogram if requested + m_bDibHistYReady = false; + + if(bDumpHistoY) + { +//@@ m_pDibHistY.Kill(); + +//@@ m_pDibHistY.CreateDIB(SUBSET_HISTO_BINS * HISTO_BIN_WIDTH, SUBSET_HISTO_BINS * HISTO_BIN_WIDTH, 32); +// nDibHistoRowBytes = (SUBSET_HISTO_BINS * HISTO_BIN_WIDTH) * 4; +//@@ pDibHistoBits = (uint8_t *) (m_pDibHistY.GetDIBBitArray()); + + m_pDibHistY = new QImage(SUBSET_HISTO_BINS * HISTO_BIN_WIDTH, HISTO_BIN_HEIGHT_MAX, QImage::Format_RGB32); +// m_rectHistYBase = QRect(QPoint(0, 0), QSize(SUBSET_HISTO_BINS * HISTO_BIN_WIDTH, HISTO_BIN_HEIGHT_MAX)); + +// if(pDibHistoBits != NULL) +// { +// memset(pDibHistoBits, 0, HISTO_BIN_HEIGHT_MAX * nDibHistoRowBytes); + + // Do peak detect first + // Don't want to reset peak value to 0 as otherwise we might get + // division by zero later when we calculate nHistoBinHeight + nHistoPeakVal = 1; + + // TODO: Temporarily made quarter width - need to resample instead + + // Peak value + for(uint32_t i = 0; i < SUBSET_HISTO_BINS; i++) + { + nHistoCurVal = m_anHistoYFull[i * 4 + 0]; + nHistoCurVal += m_anHistoYFull[i * 4 + 1]; + nHistoCurVal += m_anHistoYFull[i * 4 + 2]; + nHistoCurVal += m_anHistoYFull[i * 4 + 3]; + nHistoPeakVal = (nHistoCurVal > nHistoPeakVal) ? nHistoCurVal : nHistoPeakVal; + } + + for(int32_t i = 0; i < SUBSET_HISTO_BINS; i++) + { + // Calculate bin's height (max HISTO_BIN_HEIGHT_MAX) + nHistoCurVal = m_anHistoYFull[i * 4 + 0]; + nHistoCurVal += m_anHistoYFull[i * 4 + 1]; + nHistoCurVal += m_anHistoYFull[i * 4 + 2]; + nHistoCurVal += m_anHistoYFull[i * 4 + 3]; + nHistoBinHeight = HISTO_BIN_HEIGHT_MAX * nHistoCurVal / nHistoPeakVal; + + for(int32_t y = 0; y < nHistoBinHeight; y++) + { + // Store the RGB triplet + for(int32_t bin_width = 0; bin_width < HISTO_BIN_WIDTH; bin_width++) + { + nHistoX = (i * HISTO_BIN_WIDTH) + bin_width; + nCoordY = (HISTO_BIN_HEIGHT_MAX - y) - 1; + m_pDibHistY->setPixelColor(nHistoX, nCoordY, QColor(0, 255, 255)); +// pDibHistoBits[(nHistoX * 4) + 3 + (nCoordY * nDibHistoRowBytes)] = 0; +// pDibHistoBits[(nHistoX * 4) + 2 + (nCoordY * nDibHistoRowBytes)] = 255; +// pDibHistoBits[(nHistoX * 4) + 1 + (nCoordY * nDibHistoRowBytes)] = 255; +// pDibHistoBits[(nHistoX * 4) + 0 + (nCoordY * nDibHistoRowBytes)] = 0; + } + } + } // i: 0..HISTO_BINS-1 + + m_bDibHistYReady = true; + } +// } // bDumpHistoY + +} + +// Reset the decoder Scan Buff (at start of scan and +// after any restart markers) +// +// INPUT: +// - nFilePos = File position at start of scan +// - bRestart = Is this a reset due to RSTn marker? +// PRE: +// - m_nRestartInterval +// POST: +// - m_bScanEnd +// - m_bScanBad +// - m_nScanBuff +// - m_nScanBuffPtr_first +// - m_nScanBuffPtr_start +// - m_nScanBuffPtr_align +// - m_anScanBuffPtr_pos[] +// - m_anScanBuffPtr_err[] +// - m_nScanBuffLatchErr +// - m_nScanBuffPtr_num +// - m_nScanBuff_vacant +// - m_nScanCurErr +// - m_bRestartRead +// - m_nRestartMcusLeft +// +void CimgDecode::DecodeRestartScanBuf(uint32_t nFilePos, bool bRestart) +{ + // Reset the state + m_bScanEnd = false; + m_bScanBad = false; + m_nScanBuff = 0x00000000; + m_nScanBuffPtr = nFilePos; + + if(!bRestart) + { + // Only reset the scan buffer pointer at the start of the file, + // not after any RSTn markers. This is only used for the compression + // ratio calculations. + m_nScanBuffPtr_first = nFilePos; + } + m_nScanBuffPtr_start = nFilePos; + m_nScanBuffPtr_align = 0; // Start with byte alignment (0) + m_anScanBuffPtr_pos[0] = 0; + m_anScanBuffPtr_pos[1] = 0; + m_anScanBuffPtr_pos[2] = 0; + m_anScanBuffPtr_pos[3] = 0; + m_anScanBuffPtr_err[0] = SCANBUF_OK; + m_anScanBuffPtr_err[1] = SCANBUF_OK; + m_anScanBuffPtr_err[2] = SCANBUF_OK; + m_anScanBuffPtr_err[3] = SCANBUF_OK; + m_nScanBuffLatchErr = SCANBUF_OK; + + m_nScanBuffPtr_num = 0; // Empty m_nScanBuff + m_nScanBuff_vacant = 32; + + m_nScanCurErr = false; + + // + m_nScanBuffPtr = nFilePos; + + // Reset RST Interval checking + m_bRestartRead = false; + m_nRestartMcusLeft = m_nRestartInterval; +} + +// Color conversion from YCC to RGB +// +// INPUT: +// - sPix = Structure for color conversion +// OUTPUT: +// - sPix = Structure for color conversion +// +void CimgDecode::ConvertYCCtoRGBFastFloat(PixelCc & sPix) +{ + int32_t nValY, nValCb, nValCr; + + double nValR, nValG, nValB; + + // Perform ranging to adjust from Huffman sums to reasonable range + // -1024..+1024 -> -128..127 + sPix.nPreclipY = sPix.nPrerangeY >> 3; + sPix.nPreclipCb = sPix.nPrerangeCb >> 3; + sPix.nPreclipCr = sPix.nPrerangeCr >> 3; + + // Limit on YCC input + // The y/cb/nPreclipCr values should already be 0..255 unless we have a + // decode error where DC value gets out of range! + //CapYccRange(nMcuX,nMcuY,sPix); + nValY = (sPix.nPreclipY < -128) ? -128 : (sPix.nPreclipY > 127) ? 127 : sPix.nPreclipY; + nValCb = (sPix.nPreclipCb < -128) ? -128 : (sPix.nPreclipCb > 127) ? 127 : sPix.nPreclipCb; + nValCr = (sPix.nPreclipCr < -128) ? -128 : (sPix.nPreclipCr > 127) ? 127 : sPix.nPreclipCr; + + // Save the YCC values (0..255) + sPix.nFinalY = static_cast < uint8_t > (nValY + 128); + sPix.nFinalCb = static_cast < uint8_t > (nValCb + 128); + sPix.nFinalCr = static_cast < uint8_t > (nValCr + 128); + + // Convert + // Since the following seems to preserve the multiplies and subtractions + // we could expand this out manually + double fConstRed = 0.299f; + + double fConstGreen = 0.587f; + + double fConstBlue = 0.114f; + + // r = cr * 1.402 + y; + // b = cb * 1.772 + y; + // g = (y - 0.03409 * r) / 0.587; + nValR = nValCr * (2 - 2 * fConstRed) + nValY; + nValB = nValCb * (2 - 2 * fConstBlue) + nValY; + nValG = (nValY - fConstBlue * nValB - fConstRed * nValR) / fConstGreen; + + // Level shift + nValR += 128; + nValB += 128; + nValG += 128; + + // --------------- Finshed the color conversion + + // Limit + // r/g/nPreclipB -> r/g/b + //CapRgbRange(nMcuX,nMcuY,sPix); + sPix.nFinalR = (nValR < 0) ? 0 : (nValR > 255) ? 255 : (uint8_t) nValR; + sPix.nFinalG = (nValG < 0) ? 0 : (nValG > 255) ? 255 : (uint8_t) nValG; + sPix.nFinalB = (nValB < 0) ? 0 : (nValB > 255) ? 255 : (uint8_t) nValB; +} + +// Color conversion from YCC to RGB +// +// INPUT: +// - sPix = Structure for color conversion +// OUTPUT: +// - sPix = Structure for color conversion +// +void CimgDecode::ConvertYCCtoRGBFastFixed(PixelCc & sPix) +{ + int32_t nPreclipY, nPreclipCb, nPreclipCr; + int32_t nValY, nValCb, nValCr; + int32_t nValR, nValG, nValB; + + // Perform ranging to adjust from Huffman sums to reasonable range + // -1024..+1024 -> -128..+127 + nPreclipY = sPix.nPrerangeY >> 3; + nPreclipCb = sPix.nPrerangeCb >> 3; + nPreclipCr = sPix.nPrerangeCr >> 3; + + // Limit on YCC input + // The nPreclip* values should already be 0..255 unless we have a + // decode error where DC value gets out of range! + + //CapYccRange(nMcuX,nMcuY,sPix); + nValY = (nPreclipY < -128) ? -128 : (nPreclipY > 127) ? 127 : nPreclipY; + nValCb = (nPreclipCb < -128) ? -128 : (nPreclipCb > 127) ? 127 : nPreclipCb; + nValCr = (nPreclipCr < -128) ? -128 : (nPreclipCr > 127) ? 127 : nPreclipCr; + + // Save the YCC values (0..255) + sPix.nFinalY = static_cast < uint8_t > (nValY + 128); + sPix.nFinalCb = static_cast < uint8_t > (nValCb + 128); + sPix.nFinalCr = static_cast < uint8_t > (nValCr + 128); + + // -------------- + + // Convert + // Fixed values is x 1024 (10 bits). Leaves 22 bits for integer + //r2 = 1024*cr1*(2-2*fConstRed)+1024*y1; + //b2 = 1024*cb1*(2-2*fConstBlue)+1024*y1; + //g2 = 1024*(y1-fConstBlue*b2/1024-fConstRed*r2/1024)/fConstGreen; + + const int32_t CFIX_R = 306; + const int32_t CFIX_G = 601; + const int32_t CFIX_B = 116; + const int32_t CFIX2_R = 1436; // 2*(1024-cfix_red) + const int32_t CFIX2_B = 1816; // 2*(1024-cfix_blue) + const int32_t CFIX2_G = 1048576; // 1024*1024 + + nValR = CFIX2_R * nValCr + 1024 * nValY; + nValB = CFIX2_B * nValCb + 1024 * nValY; + nValG = (CFIX2_G * nValY - CFIX_B * nValB - CFIX_R * nValR) / CFIX_G; + + nValR >>= 10; + nValG >>= 10; + nValB >>= 10; + + // Level shift + nValR += 128; + nValB += 128; + nValG += 128; + + // Limit + // r/g/nPreclipB -> r/g/b + sPix.nFinalR = (nValR < 0) ? 0 : (nValR > 255) ? 255 : static_cast < uint8_t > (nValR); + sPix.nFinalG = (nValG < 0) ? 0 : (nValG > 255) ? 255 : static_cast < uint8_t > (nValG); + sPix.nFinalB = (nValB < 0) ? 0 : (nValB > 255) ? 255 : static_cast < uint8_t > (nValB); +} + +// Color conversion from YCC to RGB +// - CC: y/cb/cr -> r/g/b +// +// INPUT: +// - nMcuX = MCU x coordinate +// - nMcuY = MCU y coordinate +// - sPix = Structure for color conversion +// OUTPUT: +// - sPix = Structure for color conversion +// POST: +// - m_sHisto +// - m_anHistoYFull[] +// - m_anCcHisto_r[] +// - m_anCcHisto_g[] +// - m_anCcHisto_b[] +// +void CimgDecode::ConvertYCCtoRGB(uint32_t nMcuX, uint32_t nMcuY, PixelCc & sPix) +{ + double fConstRed = 0.299; + double fConstGreen = 0.587; + double fConstBlue = 0.114; + + int32_t nByteY, nByteCb, nByteCr; + int32_t nValY, nValCb, nValCr; + + double nValR, nValG, nValB; + + if(m_bHistEn) + { + // Calc stats on preranged YCC (direct from huffman DC sums) + m_sHisto.nPreclipYMin = (sPix.nPrerangeY < m_sHisto.nPreclipYMin) ? sPix.nPrerangeY : m_sHisto.nPreclipYMin; + m_sHisto.nPreclipYMax = (sPix.nPrerangeY > m_sHisto.nPreclipYMax) ? sPix.nPrerangeY : m_sHisto.nPreclipYMax; + m_sHisto.nPreclipYSum += sPix.nPrerangeY; + m_sHisto.nPreclipCbMin = (sPix.nPrerangeCb < m_sHisto.nPreclipCbMin) ? sPix.nPrerangeCb : m_sHisto.nPreclipCbMin; + m_sHisto.nPreclipCbMax = (sPix.nPrerangeCb > m_sHisto.nPreclipCbMax) ? sPix.nPrerangeCb : m_sHisto.nPreclipCbMax; + m_sHisto.nPreclipCbSum += sPix.nPrerangeCb; + m_sHisto.nPreclipCrMin = (sPix.nPrerangeCr < m_sHisto.nPreclipCrMin) ? sPix.nPrerangeCr : m_sHisto.nPreclipCrMin; + m_sHisto.nPreclipCrMax = (sPix.nPrerangeCr > m_sHisto.nPreclipCrMax) ? sPix.nPrerangeCr : m_sHisto.nPreclipCrMax; + m_sHisto.nPreclipCrSum += sPix.nPrerangeCr; + } + + if(m_bHistEn) + { + // Now generate the Y histogram, if requested + // Add the Y value to the full histogram (for image similarity calcs) + //if (bDumpHistoY) { + int32_t histo_index = sPix.nPrerangeY; + + if(histo_index < -1024) + histo_index = -1024; + + if(histo_index > 1023) + histo_index = 1023; + + histo_index += 1024; + m_anHistoYFull[histo_index]++; + //} + } + + // Perform ranging to adjust from Huffman sums to reasonable range + // -1024..+1024 -> 0..255 + // Add 1024 then / 8 + sPix.nPreclipY = (sPix.nPrerangeY + 1024) / 8; + sPix.nPreclipCb = (sPix.nPrerangeCb + 1024) / 8; + sPix.nPreclipCr = (sPix.nPrerangeCr + 1024) / 8; + + // Limit on YCC input + // The y/cb/nPreclipCr values should already be 0..255 unless we have a + // decode error where DC value gets out of range! + CapYccRange(nMcuX, nMcuY, sPix); + + // --------------- Perform the color conversion + nByteY = sPix.nFinalY; + nByteCb = sPix.nFinalCb; + nByteCr = sPix.nFinalCr; + + // Level shift + nValY = nByteY - 128; + nValCb = nByteCb - 128; + nValCr = nByteCr - 128; + + // Convert + nValR = nValCr * (2.0 - 2.0 * fConstRed) + nValY; + nValB = nValCb * (2.0 - 2.0 * fConstBlue) + nValY; + nValG = (nValY - fConstBlue * nValB - fConstRed * nValR) / fConstGreen; + + // Level shift + nValR += 128; + nValB += 128; + nValG += 128; + + sPix.nPreclipR = nValR; + sPix.nPreclipG = nValG; + sPix.nPreclipB = nValB; + // --------------- Finshed the color conversion + + // Limit + // - Preclip RGB to Final RGB + CapRgbRange(nMcuX, nMcuY, sPix); + + // Display + /* + strTmp = QString("* (YCC->RGB) @ (%03u,%03u): YCC=(%4d,%4d,%4d) RGB=(%03u,%03u,%u)", + nMcuX,nMcuY,y,cb,cr,r_limb,g_limb,b_limb); + m_pLog->AddLine(strTmp); + */ + + if(m_bHistEn) + { + // Bin the result into a histogram! + // value = 0..255 + // bin = 0..7, 8..15, ..., 248..255 + // Channel: Red + uint32_t bin_divider = 256 / HISTO_BINS; + + m_anCcHisto_r[sPix.nFinalR / bin_divider]++; + m_anCcHisto_g[sPix.nFinalG / bin_divider]++; + m_anCcHisto_b[sPix.nFinalB / bin_divider]++; + } +} + +// Color conversion clipping +// - Process the pre-clipped YCC values and ensure they +// have been clipped into the valid region +// +// INPUT: +// - nMcuX = MCU x coordinate +// - nMcuY = MCU y coordinate +// - sPix = Structure for color conversion +// OUTPUT: +// - sPix = Structure for color conversion +// POST: +// - m_sHisto +// +void CimgDecode::CapYccRange(uint32_t nMcuX, uint32_t nMcuY, PixelCc & sPix) +{ + // Check the bounds on the YCC value. It should probably be 0..255 unless our DC + // values got really messed up in a corrupt file. Perhaps it might be best to reset it to 0? Otherwise + // it will continuously report an out-of-range value. + int32_t nCurY, nCurCb, nCurCr; + + nCurY = sPix.nPreclipY; + nCurCb = sPix.nPreclipCb; + nCurCr = sPix.nPreclipCr; + + if(m_bHistEn) + { + m_sHisto.nClipYMin = (nCurY < m_sHisto.nClipYMin) ? nCurY : m_sHisto.nClipYMin; + m_sHisto.nClipYMax = (nCurY > m_sHisto.nClipYMax) ? nCurY : m_sHisto.nClipYMax; + m_sHisto.nClipYSum += nCurY; + m_sHisto.nClipCbMin = (nCurCb < m_sHisto.nClipCbMin) ? nCurCb : m_sHisto.nClipCbMin; + m_sHisto.nClipCbMax = (nCurCb > m_sHisto.nClipCbMax) ? nCurCb : m_sHisto.nClipCbMax; + m_sHisto.nClipCbSum += nCurCb; + m_sHisto.nClipCrMin = (nCurCr < m_sHisto.nClipCrMin) ? nCurCr : m_sHisto.nClipCrMin; + m_sHisto.nClipCrMax = (nCurCr > m_sHisto.nClipCrMax) ? nCurCr : m_sHisto.nClipCrMax; + m_sHisto.nClipCrSum += nCurCr; + m_sHisto.nCount++; + } + + if(CC_CLIP_YCC_EN) + { + if(nCurY > CC_CLIP_YCC_MAX) + { + if(YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) + { + QString strTmp; + + strTmp = QString("*** NOTE: YCC Clipped. MCU=(%1,%2) YCC=(%3,%4,%5) Y Overflow @ Offset %6") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nCurY, 5) + .arg(nCurCb, 5) + .arg(nCurCr, 5) + .arg(GetScanBufPos()); + m_pLog->AddLineWarn(strTmp); + m_nWarnYccClipNum++; + m_sStatClip.nClipYOver++; + + if(m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(YCC_CLIP_REPORT_MAX); + m_pLog->AddLineWarn(strTmp); + } + } + + sPix.nClip |= CC_CLIP_Y_OVER; + nCurY = CC_CLIP_YCC_MAX; + } + + if(nCurY < CC_CLIP_YCC_MIN) + { + if(YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) + { + QString strTmp; + + strTmp = QString("*** NOTE: YCC Clipped. MCU=(%1,%2) YCC=(%3,%4,%5) Y Underflow @ Offset %6") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nCurY, 5) + .arg(nCurCb, 5) + .arg(nCurCr, 5) + .arg(GetScanBufPos()); + m_pLog->AddLineWarn(strTmp); + m_nWarnYccClipNum++; + m_sStatClip.nClipYUnder++; + + if(m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(YCC_CLIP_REPORT_MAX); + m_pLog->AddLineWarn(strTmp); + } + } + + sPix.nClip |= CC_CLIP_Y_UNDER; + nCurY = CC_CLIP_YCC_MIN; + } + + if(nCurCb > CC_CLIP_YCC_MAX) + { + if(YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) + { + QString strTmp; + + strTmp = QString("*** NOTE: YCC Clipped. MCU=(%1,%2) YCC=(%3,%4,%5) Cb Overflow @ Offset %6") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nCurY, 5) + .arg(nCurCb, 5) + .arg(nCurCr, 5) + .arg(GetScanBufPos()); + m_pLog->AddLineWarn(strTmp); + m_nWarnYccClipNum++; + m_sStatClip.nClipCbOver++; + + if(m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(YCC_CLIP_REPORT_MAX); + m_pLog->AddLineWarn(strTmp); + } + } + + sPix.nClip |= CC_CLIP_CB_OVER; + nCurCb = CC_CLIP_YCC_MAX; + } + + if(nCurCb < CC_CLIP_YCC_MIN) + { + if(YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) + { + QString strTmp; + + strTmp = QString("*** NOTE: YCC Clipped. MCU=(%1,%2) YCC=(%3,%4,%5) Cb Underflow @ Offset %6") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nCurY, 5) + .arg(nCurCb, 5) + .arg(nCurCr, 5) + .arg(GetScanBufPos()); + m_pLog->AddLineWarn(strTmp); + m_nWarnYccClipNum++; + m_sStatClip.nClipCbUnder++; + + if(m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(YCC_CLIP_REPORT_MAX); + m_pLog->AddLineWarn(strTmp); + } + } + + sPix.nClip |= CC_CLIP_CB_UNDER; + nCurCb = CC_CLIP_YCC_MIN; + } + + if(nCurCr > CC_CLIP_YCC_MAX) + { + if(YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) + { + QString strTmp; + + strTmp = QString("*** NOTE: YCC Clipped. MCU=(%1,%2) YCC=(%3,%4,%5) Cr Overflow @ Offset %6") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nCurY, 5) + .arg(nCurCb, 5) + .arg(nCurCr, 5) + .arg(GetScanBufPos()); + m_pLog->AddLineWarn(strTmp); + m_nWarnYccClipNum++; + m_sStatClip.nClipCrOver++; + + if(m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(YCC_CLIP_REPORT_MAX); + m_pLog->AddLineWarn(strTmp); + } + } + + sPix.nClip |= CC_CLIP_CR_OVER; + nCurCr = CC_CLIP_YCC_MAX; + } + + if(nCurCr < CC_CLIP_YCC_MIN) + { + if(YCC_CLIP_REPORT_ERR && (m_nWarnYccClipNum < YCC_CLIP_REPORT_MAX)) + { + QString strTmp; + + strTmp = QString("*** NOTE: YCC Clipped. MCU=(%1,%2) YCC=(%3,%4,%5) Cr Underflow @ Offset %6") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nCurY, 5) + .arg(nCurCb, 5) + .arg(nCurCr, 5) + .arg(GetScanBufPos()); + m_pLog->AddLineWarn(strTmp); + m_nWarnYccClipNum++; + m_sStatClip.nClipCrUnder++; + + if(m_nWarnYccClipNum == YCC_CLIP_REPORT_MAX) + { + strTmp = QString(" Only reported first %1 instances of this message...").arg(YCC_CLIP_REPORT_MAX); + m_pLog->AddLineWarn(strTmp); + } + } + + sPix.nClip |= CC_CLIP_CR_UNDER; + nCurCr = CC_CLIP_YCC_MIN; + } + } // YCC clip enabled? + + // Perform color conversion: YCC->RGB + // The nCurY/cb/cr values should already be clipped to byte size + sPix.nFinalY = static_cast < uint8_t > (nCurY); + sPix.nFinalCb = static_cast < uint8_t > (nCurCb); + sPix.nFinalCr = static_cast < uint8_t > (nCurCr); +} + +// Color conversion clipping (RGB) +// - Input RGB triplet in floats +// - Expect range to be 0..255 +// - Return RGB triplet in byteuis +// - Report if it is out of range +// - Converts from Preclip RGB to Final RGB +// +// INPUT: +// - nMcuX = MCU x coordinate +// - nMcuY = MCU y coordinate +// - sPix = Structure for color conversion +// OUTPUT: +// - sPix = Structure for color conversion +// POST: +// - m_sHisto +// +void CimgDecode::CapRgbRange(uint32_t nMcuX, uint32_t nMcuY, PixelCc & sPix) +{ + int32_t nLimitR, nLimitG, nLimitB; + + // Truncate + nLimitR = static_cast(sPix.nPreclipR); + nLimitG = static_cast(sPix.nPreclipG); + nLimitB = static_cast(sPix.nPreclipB); + + if(m_bHistEn) + { + m_sHisto.nPreclipRMin = (nLimitR < m_sHisto.nPreclipRMin) ? nLimitR : m_sHisto.nPreclipRMin; + m_sHisto.nPreclipRMax = (nLimitR > m_sHisto.nPreclipRMax) ? nLimitR : m_sHisto.nPreclipRMax; + m_sHisto.nPreclipRSum += nLimitR; + m_sHisto.nPreclipGMin = (nLimitG < m_sHisto.nPreclipGMin) ? nLimitG : m_sHisto.nPreclipGMin; + m_sHisto.nPreclipGMax = (nLimitG > m_sHisto.nPreclipGMax) ? nLimitG : m_sHisto.nPreclipGMax; + m_sHisto.nPreclipGSum += nLimitG; + m_sHisto.nPreclipBMin = (nLimitB < m_sHisto.nPreclipBMin) ? nLimitB : m_sHisto.nPreclipBMin; + m_sHisto.nPreclipBMax = (nLimitB > m_sHisto.nPreclipBMax) ? nLimitB : m_sHisto.nPreclipBMax; + m_sHisto.nPreclipBSum += nLimitB; + } + + if(nLimitR < 0) + { + if(m_bVerbose) + { + QString strTmp; + + strTmp = QString(" YCC->RGB Clipped. MCU=(%1,%2) RGB=(%3,%4,%5) Red Underflow") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nLimitR, 5) + .arg(nLimitG, 5) + .arg(nLimitB, 5); + m_pLog->AddLineWarn(strTmp); + } + + sPix.nClip |= CC_CLIP_R_UNDER; + m_sStatClip.nClipRUnder++; + nLimitR = 0; + } + + if(nLimitG < 0) + { + if(m_bVerbose) + { + QString strTmp; + + strTmp = QString(" YCC->RGB Clipped. MCU=(%1,%2) RGB=(%3,%4,%5) Green Underflow") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nLimitR, 5) + .arg(nLimitG, 5) + .arg(nLimitB, 5); + m_pLog->AddLineWarn(strTmp); + } + + sPix.nClip |= CC_CLIP_G_UNDER; + m_sStatClip.nClipGUnder++; + nLimitG = 0; + } + + if(nLimitB < 0) + { + if(m_bVerbose) + { + QString strTmp; + + strTmp = QString(" YCC->RGB Clipped. MCU=(%1,%2) RGB=(%3,%4,%5) Blue Underflow") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nLimitR, 5) + .arg(nLimitG, 5) + .arg(nLimitB, 5); + m_pLog->AddLineWarn(strTmp); + } + + sPix.nClip |= CC_CLIP_B_UNDER; + m_sStatClip.nClipBUnder++; + nLimitB = 0; + } + + if(nLimitR > 255) + { + if(m_bVerbose) + { + QString strTmp; + + strTmp = QString(" YCC->RGB Clipped. MCU=(%1,%2) RGB=(%3,%4,%5) Red Overflow") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nLimitR, 5) + .arg(nLimitG, 5) + .arg(nLimitB, 5); + m_pLog->AddLineWarn(strTmp); + } + + sPix.nClip |= CC_CLIP_R_OVER; + m_sStatClip.nClipROver++; + nLimitR = 255; + } + + if(nLimitG > 255) + { + if(m_bVerbose) + { + QString strTmp; + + strTmp = QString(" YCC->RGB Clipped. MCU=(%1,%2) RGB=(%3,%4,%5) Green Overflow") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nLimitR, 5) + .arg(nLimitG, 5) + .arg(nLimitB, 5); + m_pLog->AddLineWarn(strTmp); + } + + sPix.nClip |= CC_CLIP_G_OVER; + m_sStatClip.nClipGOver++; + nLimitG = 255; + } + + if(nLimitB > 255) + { + if(m_bVerbose) + { + QString strTmp; + + strTmp = QString(" YCC->RGB Clipped. MCU=(%1,%2) RGB=(%3,%4,%5) Blue Overflow") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nLimitR, 5) + .arg(nLimitG, 5) + .arg(nLimitB, 5); + m_pLog->AddLineWarn(strTmp); + } + + sPix.nClip |= CC_CLIP_B_OVER; + m_sStatClip.nClipBOver++; + nLimitB = 255; + } + + if(m_bHistEn) + { + m_sHisto.nClipRMin = (nLimitR < m_sHisto.nClipRMin) ? nLimitR : m_sHisto.nClipRMin; + m_sHisto.nClipRMax = (nLimitR > m_sHisto.nClipRMax) ? nLimitR : m_sHisto.nClipRMax; + m_sHisto.nClipRSum += nLimitR; + m_sHisto.nClipGMin = (nLimitG < m_sHisto.nClipGMin) ? nLimitG : m_sHisto.nClipGMin; + m_sHisto.nClipGMax = (nLimitG > m_sHisto.nClipGMax) ? nLimitG : m_sHisto.nClipGMax; + m_sHisto.nClipGSum += nLimitG; + m_sHisto.nClipBMin = (nLimitB < m_sHisto.nClipBMin) ? nLimitB : m_sHisto.nClipBMin; + m_sHisto.nClipBMax = (nLimitB > m_sHisto.nClipBMax) ? nLimitB : m_sHisto.nClipBMax; + m_sHisto.nClipBSum += nLimitB; + } + + // Now convert to byteui + sPix.nFinalR = (uint8_t) nLimitR; + sPix.nFinalG = (uint8_t) nLimitG; + sPix.nFinalB = (uint8_t) nLimitB; +} + +// Recalcs the full image based on the original YCC pixmap +// - Also locate the brightest pixel. +// - Note that we cannot do the brightest pixel search when we called SetFullRes() +// because we need to have access to all of the channel components at once to do this. +// +// INPUT: +// - pRectView = UNUSED. Intended to limit updates to visible region +// (Range of real image that is visibile / cropped) +// PRE: +// - m_pPixValY[] +// - m_pPixValCb[] +// - m_pPixValCr[] +// OUTPUT: +// - pTmp = RGB pixel map (32-bit per pixel, [0x00,R,G,B]) +// +void CimgDecode::CalcChannelPreviewFull(QRect *, uint8_t *pTmp) +{ + PixelCc sPixSrc, sPixDst; + + QString strTmp; + + uint32_t nRowBytes; + + nRowBytes = m_nImgSizeX * sizeof(QRgb); + + // Color conversion process + + uint32_t nPixMapW = m_nBlkXMax * BLK_SZ_X; + uint32_t nPixmapInd; + uint32_t nRngX1, nRngX2, nRngY1, nRngY2; + uint32_t nSumY; + uint32_t nNumPixels = 0; + + // TODO: Update ranges to take into account the visible view region + // The approach might include: + // nRngX1 = pRectView->left; + // nRngX2 = pRectView->right; + // nRngY1 = pRectView->top; + // nRngY2 = pRectView->bottom; + // + // These co-ords will define range in nPixX,nPixY that get drawn + // This will help YCC Adjust display react much faster. Only recalc + // visible portion of image, but then recalc entire one once Adjust + // dialog is closed. + // + // NOTE: if we were to make these ranges a subset of the + // full image dimensions, then we'd have to determine the best + // way to handle the brightest pixel search & average luminance logic + // since those appear in the nRngX/Y loops. + + nRngX1 = 0; + nRngX2 = m_nImgSizeX; + nRngY1 = 0; + nRngY2 = m_nImgSizeY; + + // Brightest pixel values were already reset during Reset() call, but for + // safety, do it again here. + m_bBrightValid = false; + m_nBrightY = -32768; + m_nBrightCb = -32768; + m_nBrightCr = -32768; + + // Average luminance calculation + m_bAvgYValid = false; + m_nAvgY = 0; + nSumY = 0; + + // For IDCT RGB Printout: + bool bRowStart = false; + + QString strLine; + + uint32_t nMcuShiftInd = m_nPreviewShiftMcuY * (m_nImgSizeX / m_nMcuWidth) + m_nPreviewShiftMcuX; + + m_pDibTemp = new QImage(m_nImgSizeX, m_nImgSizeY, QImage::Format_RGB32); + + SetStatusText("Color conversion..."); + + if(m_bDetailVlc) + { + m_pLog->AddLine(" Detailed IDCT Dump (RGB):"); + strTmp = QString(" MCU [%1,%2]:") + .arg(m_nDetailVlcX, 3) + .arg(m_nDetailVlcY, 3); + m_pLog->AddLine(strTmp); + } + + // Determine pixel count + nNumPixels = (nRngY2 - nRngY1 + 1) * (nRngX2 - nRngX1 + 1); + + // Step through the image + for(int32_t nPixY = nRngY1; nPixY < nRngY2; nPixY++) + { + uint32_t nMcuY = nPixY / m_nMcuHeight; + + // DIBs appear to be stored up-side down, so correct Y + uint32_t nCoordYInv = (m_nImgSizeY - 1) - nPixY; + + for(int32_t nPixX = nRngX1; nPixX < nRngX2; nPixX++) + { + nPixmapInd = nPixY * nPixMapW + nPixX; + uint32_t nPixByte = nPixX * 4 + 0 + nCoordYInv * nRowBytes; + + uint32_t nMcuX = nPixX / m_nMcuWidth; + uint32_t nMcuInd = nMcuY * (m_nImgSizeX / m_nMcuWidth) + nMcuX; + + int32_t nTmpY, nTmpCb, nTmpCr; + + nTmpY = m_pPixValY[nPixmapInd]; + + if(m_nNumSosComps == NUM_CHAN_YCC) + { + nTmpCb = m_pPixValCb[nPixmapInd]; + nTmpCr = m_pPixValCr[nPixmapInd]; + } + else + { + nTmpCb = 0; + nTmpCr = 0; + } + + // Load the YCC value + sPixSrc.nPrerangeY = nTmpY; + sPixSrc.nPrerangeCb = nTmpCb; + sPixSrc.nPrerangeCr = nTmpCr; + + // Update brightest pixel search here + int32_t nBrightness = nTmpY; + + if(nBrightness > m_nBrightY) + { + m_nBrightY = nTmpY; + m_nBrightCb = nTmpCb; + m_nBrightCr = nTmpCr; + m_ptBrightMcu.setX(nMcuX); + m_ptBrightMcu.setY(nMcuY); + } + + // FIXME + // Could speed this up by adding boolean check to see if we are truly needing to do any shifting! + if(nMcuInd >= nMcuShiftInd) + { + sPixSrc.nPrerangeY += m_nPreviewShiftY; + sPixSrc.nPrerangeCb += m_nPreviewShiftCb; + sPixSrc.nPrerangeCr += m_nPreviewShiftCr; + } + + // Invoke the appropriate color conversion routine + if(m_bHistEn || m_bStatClipEn) + { + ConvertYCCtoRGB(nMcuX, nMcuY, sPixSrc); + } + else + { + ConvertYCCtoRGBFastFloat(sPixSrc); + //ConvertYCCtoRGBFastFixed(sPixSrc); + } + + // Accumulate the luminance value for this pixel + // after we have converted it to the range 0..255 + nSumY += sPixSrc.nFinalY; + + // If we want a detailed decode of RGB, print it out + // now if we are on the correct MCU. + // NOTE: The level shift (adjust) will affect this report! + if(m_bDetailVlc) + { + if(nMcuY == m_nDetailVlcY) + { + if(nMcuX == m_nDetailVlcX) + { + //if ((nMcuX >= m_nDetailVlcX) && (nMcuX < m_nDetailVlcX+m_nDetailVlcLen)) { + if(!bRowStart) + { + bRowStart = true; + strLine = QString(" [ "); + } + + strTmp = QString("x%1%2%3 ") + .arg(sPixSrc.nFinalR, 2, 16, QChar('0')) + .arg(sPixSrc.nFinalG, 2, 16, QChar('0')) + .arg(sPixSrc.nFinalB, 2, 16, QChar('0')); + strLine.append(strTmp); + } + else + { + if(bRowStart) + { + // We had started a row, but we are now out of range, so we + // need to close up! + strTmp = QString(" ]"); + strLine.append(strTmp); + m_pLog->AddLine(strLine); + bRowStart = false; + } + } + } + } + + // Perform any channel filtering if enabled + ChannelExtract(m_nPreviewMode, sPixSrc, sPixDst); + + m_pDibTemp->setPixelColor(nPixX, nPixY, QColor(sPixDst.nFinalR, sPixDst.nFinalG, sPixDst.nFinalB)); + // Assign the RGB pixel map +// pTmp[nPixByte + 3] = 0; +// pTmp[nPixByte + 2] = sPixDst.nFinalR; +// pTmp[nPixByte + 1] = sPixDst.nFinalG; +// pTmp[nPixByte + 0] = sPixDst.nFinalB; + } // x + } // y + + SetStatusText(""); + // --------------------------------------------------------- + + if(m_bDetailVlc) + { + m_pLog->AddLine(""); + } + + // Assume that brightest pixel search was successful + // Now compute the RGB value for this pixel! + m_bBrightValid = true; + sPixSrc.nPrerangeY = m_nBrightY; + sPixSrc.nPrerangeCb = m_nBrightCb; + sPixSrc.nPrerangeCr = m_nBrightCr; + ConvertYCCtoRGBFastFloat(sPixSrc); + m_nBrightR = sPixSrc.nFinalR; + m_nBrightG = sPixSrc.nFinalG; + m_nBrightB = sPixSrc.nFinalB; + + // Now perform average luminance calculation + // NOTE: This will result in a value in the range 0..255 + Q_ASSERT(nNumPixels > 0); + + // Avoid divide by zero + if(nNumPixels == 0) + { + nNumPixels = 1; + } + + m_nAvgY = nSumY / nNumPixels; + m_bAvgYValid = true; +} + +// Extract the specified channel +// +// INPUT: +// - nMode = Channel(s) to extract from +// - sSrc = Color representations (YCC & RGB) for pixel +// OUTPUT: +// - sDst = Resulting RGB output after filtering +// +void CimgDecode::ChannelExtract(uint32_t nMode, PixelCc & sSrc, PixelCc & sDst) +{ + if(nMode == PREVIEW_RGB) + { + sDst.nFinalR = sSrc.nFinalR; + sDst.nFinalG = sSrc.nFinalG; + sDst.nFinalB = sSrc.nFinalB; + } + else if(nMode == PREVIEW_YCC) + { + sDst.nFinalR = sSrc.nFinalCr; + sDst.nFinalG = sSrc.nFinalY; + sDst.nFinalB = sSrc.nFinalCb; + } + else if(nMode == PREVIEW_R) + { + sDst.nFinalR = sSrc.nFinalR; + sDst.nFinalG = sSrc.nFinalR; + sDst.nFinalB = sSrc.nFinalR; + } + else if(nMode == PREVIEW_G) + { + sDst.nFinalR = sSrc.nFinalG; + sDst.nFinalG = sSrc.nFinalG; + sDst.nFinalB = sSrc.nFinalG; + } + else if(nMode == PREVIEW_B) + { + sDst.nFinalR = sSrc.nFinalB; + sDst.nFinalG = sSrc.nFinalB; + sDst.nFinalB = sSrc.nFinalB; + } + else if(nMode == PREVIEW_Y) + { + sDst.nFinalR = sSrc.nFinalY; + sDst.nFinalG = sSrc.nFinalY; + sDst.nFinalB = sSrc.nFinalY; + } + else if(nMode == PREVIEW_CB) + { + sDst.nFinalR = sSrc.nFinalCb; + sDst.nFinalG = sSrc.nFinalCb; + sDst.nFinalB = sSrc.nFinalCb; + } + else if(nMode == PREVIEW_CR) + { + sDst.nFinalR = sSrc.nFinalCr; + sDst.nFinalG = sSrc.nFinalCr; + sDst.nFinalB = sSrc.nFinalCr; + } + else + { + sDst.nFinalR = sSrc.nFinalR; + sDst.nFinalG = sSrc.nFinalG; + sDst.nFinalB = sSrc.nFinalB; + } +} + +// Fetch the detailed decode settings (VLC) +// +// OUTPUT: +// - bDetail = Enable for detailed scan VLC reporting +// - nX = Start of detailed scan decode MCU X coordinate +// - nY = Start of detailed scan decode MCU Y coordinate +// - nLen = Number of MCUs to parse in detailed scan decode +// +void CimgDecode::GetDetailVlc(bool & bDetail, uint32_t &nX, uint32_t &nY, uint32_t &nLen) +{ + bDetail = m_bDetailVlc; + nX = m_nDetailVlcX; + nY = m_nDetailVlcY; + nLen = m_nDetailVlcLen; +} + +// Set the detailed scan decode settings (VLC) +// +// INPUT: +// - bDetail = Enable for detailed scan VLC reporting +// - nX = Start of detailed scan decode MCU X coordinate +// - nY = Start of detailed scan decode MCU Y coordinate +// - nLen = Number of MCUs to parse in detailed scan decode +// +void CimgDecode::SetDetailVlc(bool bDetail, uint32_t nX, uint32_t nY, uint32_t nLen) +{ + m_bDetailVlc = bDetail; + m_nDetailVlcX = nX; + m_nDetailVlcY = nY; + m_nDetailVlcLen = nLen; +} + +// Fetch the pointers for the pixel map +// +// OUTPUT: +// - pMayY = Pointer to pixel map for Y component +// - pMapCb = Pointer to pixel map for Cb component +// - pMapCr = Pointer to pixel map for Cr component +// +void CimgDecode::GetPixMapPtrs(short *&pMapY, short *&pMapCb, short *&pMapCr) +{ + Q_ASSERT(m_pPixValY); + Q_ASSERT(m_pPixValCb); + Q_ASSERT(m_pPixValCr); + pMapY = m_pPixValY; + pMapCb = m_pPixValCb; + pMapCr = m_pPixValCr; +} + +// Get image pixel dimensions rounded up to nearest MCU +// +// OUTPUT: +// - nX = X dimension of preview image +// - nY = Y dimension of preview image +// +void CimgDecode::GetImageSize(uint32_t &nX, uint32_t &nY) +{ + nX = m_nImgSizeX; + nY = m_nImgSizeY; +} + +// Get the bitmap pointer +// +// OUTPUT: +// - pBitmap = Bitmap (DIB) of preview +// +void CimgDecode::GetBitmapPtr(uint8_t *&pBitmap) +{ + uint8_t *pDibImgTmpBits = NULL; + +//@@ pDibImgTmpBits = (uint8_t *) (m_pDibTemp.GetDIBBitArray()); + + // Ensure that the pointers are available! + if(!pDibImgTmpBits) + { + pBitmap = NULL; + } + else + { + pBitmap = pDibImgTmpBits; + } +} + +// Calculate RGB pixel map from selected channels of YCC pixel map +// +// PRE: +// - m_pPixValY +// - m_pPixValCb +// - m_pPixValCr +// POST: +// - m_pDibTemp +// NOTE: +// - Channels are selected in CalcChannelPreviewFull() +// +void CimgDecode::CalcChannelPreview() +{ + uint8_t *pDibImgTmpBits = NULL; + +//@@ pDibImgTmpBits = (uint8_t *) (m_pDibTemp.GetDIBBitArray()); + + // Ensure that the pointers are available! +// if(!pDibImgTmpBits) +// { +// return; +// } + + // If we need to do a YCC shift, then do full recalc into tmp array + CalcChannelPreviewFull(NULL, pDibImgTmpBits); + + // Since this was a complex mod, we don't mark this channel as + // being "done", so we will need to recalculate any time we change + // the channel display. + + // Force an update of the view to be sure + //m_pDoc->UpdateAllViews(NULL); + + return; +} + +// Determine the file position from a pixel coordinate +// +// INPUT: +// - nPixX = Pixel coordinate (x) +// - nPixY = Pixel coordinate (y) +// OUTPUT: +// - nByte = File offset (byte) +// - nBit = File offset (bit) +// +void CimgDecode::LookupFilePosPix(uint32_t nPixX, uint32_t nPixY, uint32_t &nByte, uint32_t &nBit) +{ + uint32_t nMcuX, nMcuY; + + uint32_t nPacked; + + nMcuX = nPixX / m_nMcuWidth; + nMcuY = nPixY / m_nMcuHeight; + nPacked = m_pMcuFileMap[nMcuX + nMcuY * m_nMcuXMax]; + UnpackFileOffset(nPacked, nByte, nBit); +} + +// Determine the file position from a MCU coordinate +// +// INPUT: +// - nMcuX = MCU coordinate (x) +// - nMcuY = MCU coordinate (y) +// OUTPUT: +// - nByte = File offset (byte) +// - nBit = File offset (bit) +// +void CimgDecode::LookupFilePosMcu(uint32_t nMcuX, uint32_t nMcuY, uint32_t &nByte, uint32_t &nBit) +{ + uint32_t nPacked; + + nPacked = m_pMcuFileMap[nMcuX + nMcuY * m_nMcuXMax]; + UnpackFileOffset(nPacked, nByte, nBit); +} + +// Determine the YCC DC value of a specified block +// +// INPUT: +// - nBlkX = 8x8 block coordinate (x) +// - nBlkY = 8x8 block coordinate (y) +// OUTPUT: +// - nY = Y channel value +// - nCb = Cb channel value +// - nCr = Cr channel value +// +void CimgDecode::LookupBlkYCC(uint32_t nBlkX, uint32_t nBlkY, int32_t &nY, int32_t &nCb, int32_t &nCr) +{ + nY = m_pBlkDcValY[nBlkX + nBlkY * m_nBlkXMax]; + if(m_nNumSosComps == NUM_CHAN_YCC) + { + nCb = m_pBlkDcValCb[nBlkX + nBlkY * m_nBlkXMax]; + nCr = m_pBlkDcValCr[nBlkX + nBlkY * m_nBlkXMax]; + } + else + { + nCb = 0; // FIXME + nCr = 0; // FIXME + } +} + +// Convert pixel coordinate to MCU coordinate +// +// INPUT: +// - ptPix = Pixel coordinate +// RETURN: +// - MCU coordinate +// +QPoint CimgDecode::PixelToMcu(QPoint ptPix) +{ + QPoint ptMcu; + + ptMcu.setX(ptPix.x() / m_nMcuWidth); + ptMcu.setY(ptPix.y() / m_nMcuHeight); + return ptMcu; +} + +// Convert pixel coordinate to block coordinate +// +// INPUT: +// - ptPix = Pixel coordinate +// RETURN: +// - 8x8 block coordinate +// +QPoint CimgDecode::PixelToBlk(QPoint ptPix) +{ + QPoint ptBlk; + + ptBlk.setX(ptPix.x() / BLK_SZ_X); + ptBlk.setY(ptPix.y() / BLK_SZ_Y); + return ptBlk; +} + +// Return the linear MCU offset from an MCU X,Y coord +// +// INPUT: +// - ptMcu = MCU coordinate +// PRE: +// - m_nMcuXMax +// RETURN: +// - Index of MCU from start of MCUs +// +uint32_t CimgDecode::McuXyToLinear(QPoint ptMcu) +{ + uint32_t nLinear; + + nLinear = ((ptMcu.y() * m_nMcuXMax) + ptMcu.x()); + return nLinear; +} + +// Create a file offset notation that represents bytes and bits +// - Essentially a fixed-point notation +// +// INPUT: +// - nByte = File byte position +// - nBit = File bit position +// RETURN: +// - Fixed-point file offset (29b for bytes, 3b for bits) +// +uint32_t CimgDecode::PackFileOffset(uint32_t nByte, uint32_t nBit) +{ + uint32_t nTmp; + + // Note that we only really need 3 bits, but I'll keep 4 + // so that the file offset is human readable. We will only + // handle files up to 2^28 bytes (256MB), so this is probably + // fine! + nTmp = (nByte << 4) + nBit; + return nTmp; +} + +// Convert from file offset notation to bytes and bits +// +// INPUT: +// - nPacked = Fixed-point file offset (29b for bytes, 3b for bits) +// OUTPUT: +// - nByte = File byte position +// - nBit = File bit position +// +void CimgDecode::UnpackFileOffset(uint32_t nPacked, uint32_t &nByte, uint32_t &nBit) +{ + nBit = nPacked & 0x7; + nByte = nPacked >> 4; +} + +// Fetch the number of block markers assigned +// +// RETURN: +// - Number of marker blocks +// +uint32_t CimgDecode::GetMarkerCount() +{ + return m_nMarkersBlkNum; +} + +// Fetch an indexed block marker +// +// INPUT: +// - nInd = Index into marker block array +// RETURN: +// - Point (8x8 block) from marker array +// +QPoint CimgDecode::GetMarkerBlk(uint32_t nInd) +{ + QPoint myPt(0, 0); + + if(nInd < m_nMarkersBlkNum) + { + myPt = m_aptMarkersBlk[nInd]; + } + else + { + Q_ASSERT(false); + } + return myPt; +} + +// Add a block to the block marker list +// - Also report out the YCC DC value for the block +// +// INPUT: +// - nBlkX = 8x8 block X coordinate +// - nBlkY = 8x8 block Y coordinate +// POST: +// - m_nMarkersBlkNum +// - m_aptMarkersBlk[] +// +void CimgDecode::SetMarkerBlk(uint32_t nBlkX, uint32_t nBlkY) +{ + if(m_nMarkersBlkNum == MAX_BLOCK_MARKERS) + { + // Shift them down by 1. Last entry will be deleted next + for(uint32_t ind = 1; ind < MAX_BLOCK_MARKERS; ind++) + { + m_aptMarkersBlk[ind - 1] = m_aptMarkersBlk[ind]; + } + // Reflect new reduced count + m_nMarkersBlkNum--; + } + + QString strTmp; + + int32_t nY, nCb, nCr; + + uint32_t nMcuX, nMcuY; + + uint32_t nCssX, nCssY; + + // Determine the YCC of the block + // Then calculate the MCU coordinate and the block coordinate within the MCU + LookupBlkYCC(nBlkX, nBlkY, nY, nCb, nCr); + nMcuX = nBlkX / (m_nMcuWidth / BLK_SZ_X); + nMcuY = nBlkY / (m_nMcuHeight / BLK_SZ_Y); + nCssX = nBlkX % (m_nMcuWidth / BLK_SZ_X); + nCssY = nBlkY % (m_nMcuHeight / BLK_SZ_X); + + // Force text out to log +// bool bQuickModeSaved = m_pLog->GetQuickMode(); + +// m_pLog->SetQuickMode(false); + strTmp = QString("Position Marked @ MCU=[%1,%2](%3,%4) Block=[%5,%6] YCC=[%7,%8,%9]") + .arg(nMcuX, 4) + .arg(nMcuY, 4) + .arg(nCssX) + .arg(nCssY) + .arg(nBlkX) + .arg(nBlkY) + .arg(nY, 5) + .arg(nCb, 5) + .arg(nCr, 5); + m_pLog->AddLine(strTmp); + m_pLog->AddLine(""); +// m_pLog->SetQuickMode(bQuickModeSaved); + + m_aptMarkersBlk[m_nMarkersBlkNum].setX(nBlkX); + m_aptMarkersBlk[m_nMarkersBlkNum].setY(nBlkY); + m_nMarkersBlkNum++; +} + +// Fetch the preview zoom mode +// +// RETURN: +// - The zoom mode enumeration +// +uint32_t CimgDecode::GetPreviewZoomMode() +{ + return m_nZoomMode; +} + +// Fetch the preview mode +// +// RETURN: +// - The image preview mode enumeration +// +uint32_t CimgDecode::GetPreviewMode() +{ + return m_nPreviewMode; +} + +// Fetch the preview zoom level +// +// RETURN: +// - The preview zoom level enumeration +// +double CimgDecode::GetPreviewZoom() +{ + return m_nZoom; +} + +// Change the current zoom level +// - Supports either direct setting of the level +// or an increment/decrement operation +// +// INPUT: +// - bInc = Flag to increment the zoom level +// - bDec = Flag to decrement the zoom level +// - bSet = Flag to set the zoom level +// - nVal = Zoom level for "set" operation +// POST: +// - m_nZoomMode +// +void CimgDecode::SetPreviewZoom(bool bInc, bool bDec, bool bSet, uint32_t nVal) +{ + if(bInc) + { + if(m_nZoomMode + 1 < PRV_ZOOMEND) + { + m_nZoomMode++; + + } + } + else if(bDec) + { + if(m_nZoomMode - 1 > PRV_ZOOMBEGIN) + { + m_nZoomMode--; + } + } + else if(bSet) + { + m_nZoomMode = nVal; + } + + switch (m_nZoomMode) + { + case PRV_ZOOM_12: + m_nZoom = 0.125; + break; + + case PRV_ZOOM_25: + m_nZoom = 0.25; + break; + + case PRV_ZOOM_50: + m_nZoom = 0.5; + break; + + case PRV_ZOOM_100: + m_nZoom = 1.0; + break; + + case PRV_ZOOM_150: + m_nZoom = 1.5; + break; + + case PRV_ZOOM_200: + m_nZoom = 2.0; + break; + + case PRV_ZOOM_300: + m_nZoom = 3.0; + break; + + case PRV_ZOOM_400: + m_nZoom = 4.0; + break; + + case PRV_ZOOM_800: + m_nZoom = 8.0; + break; + + default: + m_nZoom = 1.0; + break; + } +} + +// Main draw routine for the image +// - Draws the preview image with frame +// - Draws any histogram +// - Draws a title +// - Draws any MCU overlays / grid +// +// INPUT: +// - pDC = The device context pointer +// - rectClient = From GetClientRect() +// - ptScrolledPos = From GetScrollPosition() +// - pFont = Pointer to the font used for title/lables +// OUTPUT: +// - szNewScrollSize = New dimension used for SetScrollSizes() +// +void CimgDecode::ViewOnDraw(QPainter * pDC, QRect rectClient, QPoint ptScrolledPos, QFont * pFont, QSize & szNewScrollSize) +{ + m_nPageWidth = 600; + m_nPageHeight = 10; // Start with some margin + + QString strTmp; + QString strRender; + + int32_t nHeight; + + uint32_t nYPosImgTitle = 0; + uint32_t nYPosImg = 0; + uint32_t nYPosHistTitle = 0; + uint32_t nYPosHist = 0; + uint32_t nYPosHistYTitle = 0; + uint32_t nYPosHistY = 0; // Y position of Img & Histogram + + QRect rectTmp; + + qDebug() << "CimgDecode::ViewOnDraw Start"; + + // If we have displayed an image, make sure to allow for + // the additional space! + + bool bImgDrawn = false; + +// QBrush brGray(QColor(128, 128, 128)); +// QBrush brGrayLt1(QColor(210, 210, 210)); +// QBrush brGrayLt2(QColor(240, 240, 240)); +// QBrush brBlueLt(QColor(240, 240, 255)); + + QColor brGray = QColor(128, 128, 128); + QColor brGrayLt1 = QColor(210, 210, 210); + QColor brGrayLt2 = QColor(240, 240, 240); + QColor brBlueLt = QColor(240, 240, 255); + + QPen penRed(Qt::red, 1, Qt::DotLine); + + if(m_bDibTempReady) + { + qDebug() << "CimgDecode::ViewOnDraw CP1"; + + nYPosImgTitle = m_nPageHeight; + m_nPageHeight += nTitleHeight; // Margin at top for title + + m_rectImgReal = QRect(0, 0, static_cast(m_rectImgBase.right() * m_nZoom), static_cast(m_rectImgBase.bottom() * m_nZoom)); + + nYPosImg = m_nPageHeight; + m_nPageHeight += m_rectImgReal.height(); + m_nPageHeight += nBorderBottom; // Margin at bottom + bImgDrawn = true; + + m_rectImgReal.adjust(nBorderLeft, nYPosImg, 0, 0); + + // Now create the shadow of the main image +//!! rectTmp = m_rectImgReal; +//!! rectTmp.adjust(4, 4, 0, 0); +//!! pDC->fillRect(rectTmp, QBrush(brGrayLt1)); +//!! rectTmp.adjust(-1, -1, 1, 1); +//!! pDC->FrameRect(rectTmp, &brGrayLt2); + } + + if(m_bHistEn) + { + if(m_bDibHistRgbReady) + { + nYPosHistTitle = m_nPageHeight; + m_nPageHeight += nTitleHeight; // Margin at top for title + + m_rectHistReal = m_rectHistBase; + + nYPosHist = m_nPageHeight; + m_nPageHeight += m_rectHistReal.height(); + m_nPageHeight += nBorderBottom; // Margin at bottom + bImgDrawn = true; + + m_rectHistReal.adjust(nBorderLeft, nYPosHist, 0, 0); + + // Create the border + rectTmp = m_rectHistReal; + rectTmp.adjust(-1, -1, 1, 1); + pDC->setPen(QPen(brGray)); + pDC->drawRect(rectTmp); + } + + if(m_bDibHistYReady) + { + nYPosHistYTitle = m_nPageHeight; + m_nPageHeight += nTitleHeight; // Margin at top for title + + m_rectHistYReal = m_rectHistYBase; + + nYPosHistY = m_nPageHeight; + m_nPageHeight += m_rectHistYReal.height(); + m_nPageHeight += nBorderBottom; // Margin at bottom + bImgDrawn = true; + + m_rectHistYReal.adjust(nBorderLeft, nYPosHistY, 0, 0); + + // Create the border + rectTmp = m_rectHistYReal; + rectTmp.adjust(-1, -1, 1, 1); + pDC->setPen(QPen(brGray)); + pDC->drawRect(rectTmp); + } + } + + // Find a starting line based on scrolling + // and current client size + + QRect rectClientScrolled = rectClient; + + rectClientScrolled.adjust(ptScrolledPos.x(), ptScrolledPos.y(), 0, 0); + + // Change the font + QFont pOldFont; + + pOldFont = pDC->font(); + + qDebug() << "Title 1"; + + // Draw the bitmap if ready + if(m_bDibTempReady) + { + // Print label + qDebug() << "Title 2 m_bDibTempReady"; + + if(!m_bPreviewIsJpeg) + { + // For all non-JPEG images, report with simple title + m_strTitle = "Image"; + } + else + { + qDebug() << "Title 3 m_bPreviewIsJpeg"; + m_strTitle = "Image ("; + + switch (m_nPreviewMode) + { + case PREVIEW_RGB: + m_strTitle += "RGB"; + break; + + case PREVIEW_YCC: + m_strTitle += "YCC"; + break; + + case PREVIEW_R: + m_strTitle += "R"; + break; + + case PREVIEW_G: + m_strTitle += "G"; + break; + + case PREVIEW_B: + m_strTitle += "B"; + break; + + case PREVIEW_Y: + m_strTitle += "Y"; + break; + + case PREVIEW_CB: + m_strTitle += "Cb"; + break; + + case PREVIEW_CR: + m_strTitle += "Cr"; + break; + + default: + m_strTitle += "???"; + break; + } + + if(m_bDecodeScanAc) + { + m_strTitle += ", DC+AC)"; + } + else + { + m_strTitle += ", DC)"; + } + } + + switch (m_nZoomMode) + { + case PRV_ZOOM_12: + m_strTitle += " @ 12.5% (1/8)"; + break; + + case PRV_ZOOM_25: + m_strTitle += " @ 25% (1/4)"; + break; + + case PRV_ZOOM_50: + m_strTitle += " @ 50% (1/2)"; + break; + + case PRV_ZOOM_100: + m_strTitle += " @ 100% (1:1)"; + break; + + case PRV_ZOOM_150: + m_strTitle += " @ 150% (3:2)"; + break; + + case PRV_ZOOM_200: + m_strTitle += " @ 200% (2:1)"; + break; + + case PRV_ZOOM_300: + m_strTitle += " @ 300% (3:1)"; + break; + + case PRV_ZOOM_400: + m_strTitle += " @ 400% (4:1)"; + break; + + case PRV_ZOOM_800: + m_strTitle += " @ 800% (8:1)"; + break; + + default: + m_strTitle += ""; + break; + } + + // Calculate the title width + QRect rectCalc = QRect(0, 0, 0, 0); + +//@@ nHeight = pDC->DrawText(m_strTitle,-1,&rectCalc,DT_CALQRect | DT_TOP | DT_NOPREFIX | DT_SINGLELINE); + int32_t nWidth = rectCalc.width() + 2 * nTitleIndent; + + // Determine the title area (could be larger than the image + // if the image zoom is < 100% or sized small) + + // Draw title background + rectTmp = QRect(m_rectImgReal.left(), nYPosImgTitle, + qMax(m_rectImgReal.right(), m_rectImgReal.left() + nWidth), m_rectImgReal.top() - nTitleLowGap); + pDC->fillRect(rectTmp, brBlueLt); + + // Draw the title + Qt::BGMode nBkMode = pDC->backgroundMode(); + + pDC->setBackgroundMode(Qt::TransparentMode); + rectTmp.adjust(nTitleIndent, 0, 0, 0); +//@@ nHeight = pDC->DrawText(m_strTitle,-1,&rectTmp,DT_TOP | DT_NOPREFIX | DT_SINGLELINE); + pDC->setBackgroundMode(nBkMode); + + // Draw image + + // Assume that the temp image has already been generated! + // For speed purposes, we use m_pDibTemp only when we are + // in a mode other than RGB or YCC. In the RGB/YCC modes, + // we skip the CalcChannelPreview() step. + + // TODO: Improve redraw time by only redrawing the currently visible + // region. Requires a different CopyDIB routine with a subset region. + // Needs to take into account zoom setting (eg. intersection between + // rectClient and m_rectImgReal). + + // Use a common DIB instead of creating/swapping tmp / ycc and rgb. + // This way we can also have more flexibility in modifying RGB & YCC displays. + // Time calling CalcChannelPreview() seems small, so no real impact. + + // Image member usage: + // m_pDibTemp: + +//@@ m_pDibTemp.CopyDIB(pDC,m_rectImgReal.left,m_rectImgReal.top,m_nZoom); + + // Now create overlays + + // Only draw overlay (eg. actual image boundary overlay) if the values + // have been set properly. Note that PSD decode currently sets these + // values to zero. + if((m_nDimX != 0) && (m_nDimY != 0)) + { + pDC->setPen(penRed); + + // Draw boundary for end of valid data (inside partial MCU) + int32_t nXZoomed = static_cast(m_nDimX * m_nZoom); + + int32_t nYZoomed = static_cast(m_nDimY * m_nZoom); + + pDC->drawLine(m_rectImgReal.left() + nXZoomed, m_rectImgReal.top(), m_rectImgReal.left() + nXZoomed, m_rectImgReal.top() + nYZoomed); + pDC->drawLine(m_rectImgReal.left(), m_rectImgReal.top() + nYZoomed, m_rectImgReal.left() + nXZoomed, m_rectImgReal.top() + nYZoomed); +//!! pDC->setPen(pPen); + } + + // Before we frame the region, let's draw any remaining overlays + + // Only draw the MCU overlay if zoom is > 100%, otherwise we will have + // replaced entire image with the boundary lines! + if(m_bViewOverlaysMcuGrid && (m_nZoomMode >= PRV_ZOOM_25)) + { + ViewMcuOverlay(pDC); + } + + // Always draw the markers + ViewMcuMarkedOverlay(pDC); + + // Final frame border + rectTmp = m_rectImgReal; + rectTmp.adjust(-1, -1, 1, 1); +//@@ pDC->setPen(brGray); + pDC->drawRect(rectTmp); + + // Preserve the image placement (for other functions, such as click detect) + m_nPreviewPosX = m_rectImgReal.left(); + m_nPreviewPosY = m_rectImgReal.top(); + m_nPreviewSizeX = m_rectImgReal.width(); + m_nPreviewSizeY = m_rectImgReal.height(); + + // m_nPageWidth is already hardcoded above + Q_ASSERT(m_nPageWidth >= 0); + m_nPageWidth = qMax(static_cast(m_nPageWidth), m_nPreviewPosX + m_nPreviewSizeX); + + update(); + } + + if(m_bHistEn) + { + if(m_bDibHistRgbReady) + { + // Draw title background + rectTmp = QRect(m_rectHistReal.left(), nYPosHistTitle, m_rectHistReal.right(), m_rectHistReal.top() - nTitleLowGap); + pDC->fillRect(rectTmp, brBlueLt); + + // Draw the title + QRect boundingRect; + Qt::BGMode nBkMode = pDC->backgroundMode(); + pDC->setBackgroundMode(Qt::TransparentMode); + rectTmp.adjust(nTitleIndent, 0, 0, 0); + pDC->drawText(rectTmp, Qt::AlignLeft | Qt::AlignTop, "Histogram (RGB)", &boundingRect); + pDC->setBackgroundMode(nBkMode); + + // Draw image +//@@ m_pDibHistRgb.CopyDIB(pDC,m_rectHistReal.left,m_rectHistReal.top); + } + + if(m_bDibHistYReady) + { + // Draw title background + rectTmp = QRect(m_rectHistYReal.left(), nYPosHistYTitle, m_rectHistYReal.right(), m_rectHistYReal.top() - nTitleLowGap); + pDC->fillRect(rectTmp, brBlueLt); + + // Draw the title + Qt::BGMode nBkMode = pDC->backgroundMode(); + pDC->setBackgroundMode(Qt::TransparentMode); + rectTmp.adjust(nTitleIndent, 0, 0, 0); +//@@ nHeight = pDC->DrawText("Histogram (Y)",-1,&rectTmp,DT_TOP | DT_NOPREFIX | DT_SINGLELINE); + pDC->setBackgroundMode(nBkMode); + + // Draw image +//@@ m_pDibHistY.CopyDIB(pDC,m_rectHistYReal.left,m_rectHistYReal.top); + //m_pDibHistY.CopyDIB(pDC,nBorderLeft,nYPosHistY); + } + + update(); + } + + // If no image has been drawn, indicate to user why! + if(!bImgDrawn) + { + //ScrollRect.top = m_nPageHeight; // FIXME:? + + // Print label + //nHeight = pDC->DrawText("Image Decode disabled. Enable with [Options->Decode Scan Image]", -1,&ScrollRect, + // DT_TOP | DT_NOPREFIX | DT_SINGLELINE); + + } + + // Restore the original font + pDC->setFont(pOldFont); + + // Set scroll bars accordingly. We use the page dimensions here. + QSize sizeTotal(m_nPageWidth + nBorderLeft, m_nPageHeight); + + szNewScrollSize = sizeTotal; +} + +// Draw an overlay that shows the MCU grid +// +// INPUT: +// - pDC = The device context pointer +// +void CimgDecode::ViewMcuOverlay(QPainter * pDC) +{ + // Now create overlays + uint32_t nXZoomed, nYZoomed; + + QPen penDot(QColor(32, 32, 32), 1, Qt::DotLine); + + Qt::BGMode nBkModeOld = pDC->backgroundMode(); + QPen pPenOld = pDC->pen(); + + pDC->setBackgroundMode(Qt::TransparentMode); + + // Draw vertical lines + for(uint32_t nMcuX = 0; nMcuX < m_nMcuXMax; nMcuX++) + { + nXZoomed = static_cast(nMcuX * m_nMcuWidth * m_nZoom); + pDC->drawLine(m_rectImgReal.left() + nXZoomed, m_rectImgReal.top(), m_rectImgReal.left() + nXZoomed, m_rectImgReal.bottom()); + } + + for(uint32_t nMcuY = 0; nMcuY < m_nMcuYMax; nMcuY++) + { + nYZoomed = static_cast(nMcuY * m_nMcuHeight * m_nZoom); + pDC->drawLine(m_rectImgReal.left(), m_rectImgReal.top() + nYZoomed, m_rectImgReal.right(), m_rectImgReal.top() + nYZoomed); + } + + pDC->setPen(pPenOld); + pDC->setBackgroundMode(nBkModeOld); +} + +// Draw an overlay that highlights the marked MCUs +// +// INPUT: +// - pDC = The device context pointer +// +void CimgDecode::ViewMcuMarkedOverlay(QPainter * pDC) +{ + pDC; // Unreferenced param + + // Now draw a simple MCU Marker overlay + QRect my_rect; + + QBrush my_brush(QColor(255, 0, 255)); + + for(uint32_t nMcuY = 0; nMcuY < m_nMcuYMax; nMcuY++) + { + for(uint32_t nMcuX = 0; nMcuX < m_nMcuXMax; nMcuX++) + { + //uint32_t nXY = nMcuY*m_nMcuXMax + nMcuX; + //uint32_t nXZoomed = (uint32_t)(nMcuX*m_nMcuWidth*m_nZoom); + //uint32_t nYZoomed = (uint32_t)(nMcuY*m_nMcuHeight*m_nZoom); + + /* + // TODO: Implement an overlay function + if (m_bMarkedMcuMapEn && m_abMarkedMcuMap && m_abMarkedMcuMap[nXY]) { + // Note that drawing is an overlay, so we are dealing with real + // pixel coordinates, not preview image coords + my_rect = QRect(nXZoomed,nYZoomed,nXZoomed+(uint32_t)(m_nMcuWidth*m_nZoom), + nYZoomed+(uint32_t)(m_nMcuHeight*m_nZoom)); + my_rect.adjust(m_rectImgReal.left,m_rectImgReal.top); + pDC->FrameRect(my_rect,&my_brush); + } + */ + + } + } + +} + +// Draw an overlay for the indexed block +// +// INPUT: +// - pDC = The device context pointer +// - nBlkX = 8x8 block X coordinate +// - nBlkY = 8x8 block Y coordinate +// +void CimgDecode::ViewMarkerOverlay(QPainter * pDC, uint32_t nBlkX, uint32_t nBlkY) +{ + QRect my_rect; + + // Note that drawing is an overlay, so we are dealing with real + // pixel coordinates, not preview image coords + my_rect = QRect(static_cast(m_nZoom * (nBlkX + 0)), + static_cast(m_nZoom * (nBlkY + 0)), + static_cast(m_nZoom * (nBlkX + 1)), + static_cast(m_nZoom * (nBlkY + 1))); + my_rect.adjust(m_nPreviewPosX, m_nPreviewPosY, 0, 0); + pDC->fillRect(my_rect, QColor(255, 0, 255)); +} + +// Get the preview MCU grid setting +// +// OUTPUT: +// - The MCU grid enabled flag +// +bool CimgDecode::GetPreviewOverlayMcuGrid() +{ + return m_bViewOverlaysMcuGrid; +} + +// Toggle the preview MCU grid setting +// +// POST: +// - m_bViewOverlaysMcuGrid +// +void CimgDecode::SetPreviewOverlayMcuGridToggle() +{ + if(m_bViewOverlaysMcuGrid) + { + m_bViewOverlaysMcuGrid = false; + } + else + { + m_bViewOverlaysMcuGrid = true; + } +} + +// Report the DC levels +// - UNUSED +// +// INPUT: +// - nMcuX = MCU x coordinate +// - nMcuY = MCU y coordinate +// - nMcuLen = Number of MCUs to report +// +void CimgDecode::ReportDcRun(uint32_t nMcuX, uint32_t nMcuY, uint32_t nMcuLen) +{ + // FIXME: Should I be working on MCU level or block level? + QString strTmp; + + m_pLog->AddLine(""); + m_pLog->AddLineHdr("*** Reporting DC Levels ***"); + strTmp = QString(" Starting MCU = [%1,%2]") + .arg(nMcuX) + .arg(nMcuY); + strTmp = QString(" Number of MCUs = %1").arg(nMcuLen); + m_pLog->AddLine(strTmp); + for(uint32_t ind = 0; ind < nMcuLen; ind++) + { + // TODO: Need some way of getting these values + // For now, just rely on bDetailVlcEn & PrintDcCumVal() to report this... + } +} + +// Update the YCC status text +// +// INPUT: +// - strText = Status text to display +// +void CimgDecode::SetStatusYccText(QString strText) +{ + m_strStatusYcc = strText; +} + +// Fetch the YCC status text +// +// RETURN: +// - Status text currently displayed +// +QString CimgDecode::GetStatusYccText() +{ + return m_strStatusYcc; +} + +// Update the MCU status text +// +// INPUT: +// - strText = MCU indicator text +// +void CimgDecode::SetStatusMcuText(QString strText) +{ + m_strStatusMcu = strText; +} + +// Fetch the MCU status text +// +// RETURN: +// - MCU indicator text +// +QString CimgDecode::GetStatusMcuText() +{ + return m_strStatusMcu; +} + +// Update the file position text +// +// INPUT: +// - strText = File position text +// +void CimgDecode::SetStatusFilePosText(QString strText) +{ + m_strStatusFilePos = strText; +} + +// Fetch the file position text +// +// RETURN: +// - File position text +// +QString CimgDecode::GetStatusFilePosText() +{ + return m_strStatusFilePos; +} diff --git a/source/ImgDecode.h b/source/ImgDecode.h index 6688e82..689efef 100644 --- a/source/ImgDecode.h +++ b/source/ImgDecode.h @@ -1,680 +1,684 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - This module decodes the scan segment (SOS) -// - Depends on quantization tables and huffman tables -// - At this time, only a single scan per frame/file is decoded -// - Chroma subsampling -// - Color conversion and bitmap display output -// - Channel selection for output -// - Statistics: histogram, brightest pixel, etc. -// -// ========================================================================== - - -#pragma once - -#include "SnoopConfig.h" - -#include "snoop.h" - -#include "DocLog.h" -#include "WindowBuf.h" -#include "afxwin.h" -#include "Dib.h" - -#include - -#include "General.h" - - -// Color conversion clipping (YCC) reporting -#define YCC_CLIP_REPORT_ERR true // Are YCC clips an error? -#define YCC_CLIP_REPORT_MAX 10 // Number of same error to report - -// Scan image component indices for known arrangements -#define COMP_IND_YCC_Y 1 -#define COMP_IND_YCC_CB 2 -#define COMP_IND_YCC_CR 3 -#define COMP_IND_YCC_K 4 -#define COMP_IND_CMYK_C 1 -#define COMP_IND_CMYK_M 2 -#define COMP_IND_CMYK_Y 3 -#define COMP_IND_CMYK_K 3 - -// Definitions for DHT array indices m_anDhtTblSel[][] -#define MAX_DHT_CLASS 2 -#define MAX_DHT_DEST_ID 4 // Maximum range for DHT Destination ID (ie. DHT:Th). Range 0..3 -#define DHT_CLASS_DC 0 -#define DHT_CLASS_AC 1 - -#define MAX_DHT_CODES 260 // Was 180, but with 12-bit DHT, we may have nearly all 0xFF codes -#define MAX_DHT_CODELEN 16 // Max number of bits in a code -#define DHT_CODE_UNUSED 0xFFFFFFFF // Mark table entry as unused - - -#define MAX_DQT_DEST_ID 4 // Maximum range for DQT Destination ID (ie. DQT:Tq). Range 0..3 -#define MAX_DQT_COEFF 64 // Number of coefficients in DQT matrix -#define MAX_DQT_COMP 256 // Max range of frame component identifier (SOF:Ci, 0..255) - -#define DCT_COEFF_DC 0 // DCT matrix coefficient index for DC component - -#define MAX_SAMP_FACT_H 4 // Maximum sampling factor supported -#define MAX_SAMP_FACT_V 4 // Maximum sampling factor supported - -#define DQT_DEST_Y 1 -#define DQT_DEST_CB 2 -#define DQT_DEST_CR 3 -#define DQT_DEST_K 4 - -#define BLK_SZ_X 8 // JPEG block size (x) -#define BLK_SZ_Y 8 // JPEG block size (y) - -#define DCT_SZ_X 8 // IDCT matrix size (x) -#define DCT_SZ_Y 8 // IDCT matrix size (y) -#define DCT_SZ_ALL (DCT_SZ_X*DCT_SZ_Y) // IDCT matrix all coeffs - -#define IMG_BLK_SZ 1 // Size of each MCU in image display -#define MAX_SCAN_DECODED_DIM 512 // X & Y dimension for top-left image display -#define DHT_FAST_SIZE 9 // Number of bits for DHT direct lookup - -// FIXME: MAX_SOF_COMP_NF per spec might actually be 255 -#define MAX_SOF_COMP_NF 256 // Maximum number of Image Components in Frame (Nf) [from SOF] (Nf range 1..255) -#define MAX_SOS_COMP_NS 4 // Maximum number of Image Components in Scan (Ns) [from SOS] (Ns range 1..4) - -// TODO: Merge with COMP_IND_YCC_*? -#define SCAN_COMP_Y 1 -#define SCAN_COMP_CB 2 -#define SCAN_COMP_CR 3 -#define SCAN_COMP_K 4 - - - -// Number of image channels supported for image output -#define NUM_CHAN_GRAYSCALE 1 -#define NUM_CHAN_YCC 3 -#define NUM_CHAN_YCCK 4 - -// Image channel indices (after converting component index to channel index) -#define CHAN_Y 0 -#define CHAN_CB 1 -#define CHAN_CR 2 - -// Maximum number of blocks that can be marked -// - This feature is generally used to mark ranges for the detailed scan decode feature -#define MAX_BLOCK_MARKERS 10 - -// JFIF Markers relevant for Scan Decoder -// - Restart markers -// - EOI -#define JFIF_RST0 0xD0 -#define JFIF_RST1 0xD1 -#define JFIF_RST2 0xD2 -#define JFIF_RST3 0xD3 -#define JFIF_RST4 0xD4 -#define JFIF_RST5 0xD5 -#define JFIF_RST6 0xD6 -#define JFIF_RST7 0xD7 -#define JFIF_EOI 0xD9 - -// Color correction clipping indicator -#define CC_CLIP_NONE 0x00000000 -#define CC_CLIP_Y_UNDER 0x80000000 -#define CC_CLIP_Y_OVER 0x00800000 -#define CC_CLIP_CB_UNDER 0x40000000 -#define CC_CLIP_CB_OVER 0x00400000 -#define CC_CLIP_CR_UNDER 0x20000000 -#define CC_CLIP_CR_OVER 0x00200000 -#define CC_CLIP_R_UNDER 0x00008000 -#define CC_CLIP_R_OVER 0x00000080 -#define CC_CLIP_G_UNDER 0x00004000 -#define CC_CLIP_G_OVER 0x00000040 -#define CC_CLIP_B_UNDER 0x00002000 -#define CC_CLIP_B_OVER 0x00000020 - -#define CC_CLIP_YCC_EN true -#define CC_CLIP_YCC_MIN 0 -#define CC_CLIP_YCC_MAX 255 - -// Image histogram definitions -#define HISTO_BINS 128 -#define HISTO_BIN_WIDTH 1 -#define HISTO_BIN_HEIGHT_MAX 30 - -// Histogram of Y component (-1024..+1023) = 2048 bins -#define FULL_HISTO_BINS 2048 -#define SUBSET_HISTO_BINS 512 - -// Return values for ReadScanVal() -enum teRsvRet { - RSV_OK, // OK - RSV_EOB, // End of Block - RSV_UNDERFLOW, // Ran out of data in buffer - RSV_RST_TERM // No huffman code found, but restart marker seen -}; - -// Scan decode errors (in m_anScanBuffPtr_err[] buffer array) -enum teScanBufStatus { - SCANBUF_OK, - SCANBUF_BADMARK, - SCANBUF_RST -}; - - -// Per-pixel color conversion structure -// - Records each stage of the process and associated clipping/ranging -typedef struct { - - // Pre-ranged YCC - // - Raw YCC value from pixel map before any adjustment - // - Example range: -1024...1023 - int nPrerangeY; - int nPrerangeCb; - int nPrerangeCr; - // Pre-clip YCC - // - After scaling pre-ranged values - // - Typical range should be 0..255 - int nPreclipY; - int nPreclipCb; - int nPreclipCr; - // Final YCC - // - After clipping to ensure we are in range 0..255 - BYTE nFinalY; - BYTE nFinalCr; - BYTE nFinalCb; - - // Pre-clip RGB - // - After color conversion and level shifting - float nPreclipR; - float nPreclipG; - float nPreclipB; - // Final RGB - // - After clipping to 0..255 - BYTE nFinalR; - BYTE nFinalG; - BYTE nFinalB; - - // Any YCC or RGB clipping performed? - unsigned nClip; // Multi-bit indicator of clipping (CC_CLIP_*) -} PixelCc; - - -// Per-pixel stats: clipping (overflow and underflow) in YCC and RGB -typedef struct { - unsigned nClipYUnder; - unsigned nClipYOver; - unsigned nClipCbUnder; - unsigned nClipCbOver; - unsigned nClipCrUnder; - unsigned nClipCrOver; - unsigned nClipRUnder; - unsigned nClipROver; - unsigned nClipGUnder; - unsigned nClipGOver; - unsigned nClipBUnder; - unsigned nClipBOver; - unsigned nClipWhiteOver; -} PixelCcClip; - - -// Min-max and average pixel stats for histogram -typedef struct { - int nPreclipYMin; - int nPreclipYMax; - int nPreclipYSum; - int nPreclipCbMin; - int nPreclipCbMax; - int nPreclipCbSum; - int nPreclipCrMin; - int nPreclipCrMax; - int nPreclipCrSum; - - int nClipYMin; - int nClipYMax; - int nClipYSum; - int nClipCbMin; - int nClipCbMax; - int nClipCbSum; - int nClipCrMin; - int nClipCrMax; - int nClipCrSum; - - int nClipRMin; - int nClipRMax; - int nClipRSum; - int nClipGMin; - int nClipGMax; - int nClipGSum; - int nClipBMin; - int nClipBMax; - int nClipBSum; - - int nPreclipRMin; - int nPreclipRMax; - int nPreclipRSum; - int nPreclipGMin; - int nPreclipGMax; - int nPreclipGSum; - int nPreclipBMin; - int nPreclipBMax; - int nPreclipBSum; - - unsigned nCount; -} PixelCcHisto; - - - -class CimgDecode -{ -public: - CimgDecode(CDocLog* pLog, CwindowBuf* pWBuf); - ~CimgDecode(); - - void Reset(); // Called during start of SOS decode - void ResetState(); // Called at start of new JFIF Decode - - void SetStatusBar(CStatusBar* pStatBar); - void DecodeScanImg(unsigned bStart,bool bDisplay,bool bQuiet); - - void DrawHistogram(bool bQuiet,bool bDumpHistoY); - void ReportHistogramY(); - void ReportColorStats(); - - bool IsPreviewReady(); - - // Config - void SetImageDimensions(unsigned nWidth,unsigned nHeight); - void SetImageDetails(unsigned nDimX,unsigned nDimY,unsigned nCompsSOF,unsigned nCompsSOS,bool bRstEn,unsigned nRstInterval); - void SetSofSampFactors(unsigned nCompInd, unsigned nSampFactH, unsigned nSampFactV); - void ResetImageContent(); - - bool SetDqtEntry(unsigned nTblDestId, unsigned nCoeffInd, unsigned nCoeffIndZz, unsigned short nCoeffVal); - bool SetDqtTables(unsigned nCompInd, unsigned nTbl); - unsigned GetDqtEntry(unsigned nTblDestId, unsigned nCoeffInd); - bool SetDhtTables(unsigned nCompInd, unsigned nTblDc, unsigned nTblAc); - bool SetDhtEntry(unsigned nDestId, unsigned nClass, unsigned nInd, unsigned nLen, - unsigned nBits, unsigned nMask, unsigned nCode); - bool SetDhtSize(unsigned nDestId,unsigned nClass,unsigned nSize); - void SetPrecision(unsigned nPrecision); - - - // Modes -- accessed from Doc - void SetPreviewMode(unsigned nMode); - unsigned GetPreviewMode(); - void SetPreviewYccOffset(unsigned nMcuX,unsigned nMcuY,int nY,int nCb,int nCr); - void GetPreviewYccOffset(unsigned &nMcuX,unsigned &nMcuY,int &nY,int &nCb,int &nCr); - void SetPreviewMcuInsert(unsigned nMcuX,unsigned nMcuY,int nLen); - void GetPreviewMcuInsert(unsigned &nMcuX,unsigned &nMcuY,unsigned &nLen); - void SetPreviewZoom(bool bInc,bool bDec,bool bSet,unsigned nVal); - unsigned GetPreviewZoomMode(); - float GetPreviewZoom(); - bool GetPreviewOverlayMcuGrid(); - void SetPreviewOverlayMcuGridToggle(); - - // Utilities - void LookupFilePosPix(unsigned nPixX,unsigned nPixY, unsigned &nByte, unsigned &nBit); - void LookupFilePosMcu(unsigned nMcuX,unsigned nMcuY, unsigned &nByte, unsigned &nBit); - void LookupBlkYCC(unsigned nBlkX,unsigned nBlkY,int &nY,int &nCb,int &nCr); - - void SetMarkerBlk(unsigned nBlkX,unsigned nBlkY); - unsigned GetMarkerCount(); - CPoint GetMarkerBlk(unsigned nInd); - - CPoint PixelToMcu(CPoint ptPix); - CPoint PixelToBlk(CPoint ptPix); - unsigned McuXyToLinear(CPoint ptMcu); - void GetImageSize(unsigned &nX,unsigned &nY); - - // View helper routines - void ViewOnDraw(CDC* pDC,CRect rectClient,CPoint ptScrolledPos,CFont* pFont, CSize &szNewScrollSize); - void ViewMcuOverlay(CDC* pDC); - void ViewMcuMarkedOverlay(CDC* pDC); - void ViewMarkerOverlay(CDC* pDC,unsigned nBlkX,unsigned nBlkY); // UNUSED? - - void GetPixMapPtrs(short* &pMapY,short* &pMapCb,short* &pMapCr); - void GetDetailVlc(bool &bDetail,unsigned &nX,unsigned &nY,unsigned &nLen); - void SetDetailVlc(bool bDetail,unsigned nX,unsigned nY,unsigned nLen); - - void GetPreviewPos(unsigned &nX,unsigned &nY); - void GetPreviewSize(unsigned &nX,unsigned &nY); - -private: - - void ResetDqtTables(); - void ResetDhtLookup(); - - CString GetScanBufPos(); - CString GetScanBufPos(unsigned pos, unsigned align); - - void ConvertYCCtoRGB(unsigned nMcuX,unsigned nMcuY,PixelCc &sPix); - void ConvertYCCtoRGBFastFloat(PixelCc &sPix); - void ConvertYCCtoRGBFastFixed(PixelCc &sPix); - - void ScanYccToRgb(); - void CapYccRange(unsigned nMcuX,unsigned nMcuY,PixelCc &sPix); - void CapRgbRange(unsigned nMcuX,unsigned nMcuY,PixelCc &sPix); - - void GenLookupHuffMask(); - unsigned ExtractBits(unsigned nWord,unsigned nBits); - teRsvRet ReadScanVal(unsigned nClass,unsigned nTbl,unsigned &rZrl,signed &rVal); - bool DecodeScanComp(unsigned nTblDhtDc,unsigned nTblDhtAc,unsigned nTblDqt,unsigned nMcuX,unsigned nMcuY); - bool DecodeScanCompPrint(unsigned nTblDhtDc,unsigned nTblDhtAc,unsigned nTblDqt,unsigned nMcuX,unsigned nMcuY); - signed HuffmanDc2Signed(unsigned nVal,unsigned nBits); - void CheckScanErrors(unsigned nMcuX,unsigned nMcuY,unsigned nCssX,unsigned nCssY,unsigned nComp); - - -public: - void ScanErrorsDisable(); - void ScanErrorsEnable(); -private: - - bool ExpectRestart(); - void DecodeRestartDcState(); - void DecodeRestartScanBuf(unsigned nFilePos,bool bRestart); - unsigned BuffAddByte(); - void BuffTopup(); - void ScanBuffConsume(unsigned nNumBits); - void ScanBuffAdd(unsigned nNewByte,unsigned nPtr); - void ScanBuffAddErr(unsigned nNewByte,unsigned nPtr,unsigned nErr); - - // IDCT calcs - void PrecalcIdct(); - void DecodeIdctClear(); - void DecodeIdctSet(unsigned nTbl,unsigned num_coeffs,unsigned zrl,short int val); - void DecodeIdctCalcFloat(unsigned nCoefMax); - void DecodeIdctCalcFixedpt(); - void ClrFullRes(unsigned nWidth,unsigned nHeight); - void SetFullRes(unsigned nMcuX,unsigned nMcuY,unsigned nComp,unsigned nCssXInd,unsigned nCssYInd,short int nDcOffset); - -public: // For ImgMod - unsigned PackFileOffset(unsigned nByte,unsigned nBit); - void UnpackFileOffset(unsigned nPacked, unsigned &nByte, unsigned &nBit); -private: - - void ChannelExtract(unsigned nMode,PixelCc &sSrc,PixelCc &sDst); - void CalcChannelPreviewFull(CRect* pRectView,unsigned char* pTmp); - void CalcChannelPreview(); - -public: // For Export - void GetBitmapPtr(unsigned char* &pBitmap); - - // Miscellaneous - void SetStatusText(CString strText); - void SetStatusYccText(CString strText); - CString GetStatusYccText(); - void SetStatusMcuText(CString strText); - CString GetStatusMcuText(); - void SetStatusFilePosText(CString strText); - CString GetStatusFilePosText(); - - void ReportDctMatrix(); - void ReportDctYccMatrix(); - void ReportVlc(unsigned nVlcPos, unsigned nVlcAlign, - unsigned nZrl, int nVal, - unsigned nCoeffStart,unsigned nCoeffEnd, - CString specialStr); - void PrintDcCumVal(unsigned nMcuX,unsigned nMcuY,int nVal); - void ReportDcRun(unsigned nMcuX, unsigned nMcuY, unsigned nMcuLen); - - - // ------------------------------------------------------------- - // Member variables - // ------------------------------------------------------------- - -private: - CSnoopConfig* m_pAppConfig; // Pointer to application config - - unsigned * m_pMcuFileMap; - unsigned m_nMcuWidth; // Width (pix) of MCU (e.g. 8,16) - unsigned m_nMcuHeight; // Height (pix) of MCU (e.g. 8,16) - unsigned m_nMcuXMax; // Number of MCUs across - unsigned m_nMcuYMax; // Number of MCUs vertically - unsigned m_nBlkXMax; // Number of 8x8 blocks across - unsigned m_nBlkYMax; // Number of 8x8 blocks vertically - - // Fill these with the cumulative values so that we can do - // a YCC to RGB conversion (for level shift previews, etc.) - short * m_pPixValY; // Pixel value - short * m_pPixValCb; // Pixel value - short * m_pPixValCr; // Pixel value - - // Array of block DC values. Only used for under-cursor reporting. - short * m_pBlkDcValY; // Block DC value - short * m_pBlkDcValCb; // Block DC value - short * m_pBlkDcValCr; // Block DC value - - // TODO: Later use these to support frequency spectrum - // display of image data - short * m_pBlkFreqY; // 8x8 Block frequency value - short * m_pBlkFreqCb; // 8x8 Block frequency value - short * m_pBlkFreqCr; // 8x8 Block frequency value - - - // Array that indicates whether or not a block has been marked - // This is generally used to mark ranges for the detailed scan decode feature - unsigned m_nMarkersBlkNum; // Number of 8x8 Block markers - CPoint m_aptMarkersBlk[MAX_BLOCK_MARKERS]; // MCU Markers - - - CStatusBar* m_pStatBar; // Link to status bar - CString m_strStatusYcc; // Status bar text: YCC - CString m_strStatusMcu; // Status bar text: MCU - CString m_strStatusFilePos; // Status bar text: File Position - - unsigned m_nImgSizeXPartMcu; // Image size with possible partial MCU - unsigned m_nImgSizeYPartMcu; - unsigned int m_nImgSizeX; // Image size rounding up to full MCU - unsigned int m_nImgSizeY; - - // Image rects - CRect m_rectImgBase; // Image with no offset, no scaling - CRect m_rectImgReal; // Image with scaling & offset - CRect m_rectHistBase; // Hist with no offset - CRect m_rectHistReal; // Hist with offset - CRect m_rectHistYBase; // HistY with no offset - CRect m_rectHistYReal; // HistY with offset - - // Decoder DC state - // Tables use signed to help flag undefined table indices - signed short m_nDcLum; - signed short m_nDcChrCb; - signed short m_nDcChrCr; - signed short m_anDcLumCss[MAX_SAMP_FACT_V*MAX_SAMP_FACT_H]; // Need 4x2 at least. Support up to 4x4 - signed short m_anDcChrCbCss[MAX_SAMP_FACT_V*MAX_SAMP_FACT_H]; - signed short m_anDcChrCrCss[MAX_SAMP_FACT_V*MAX_SAMP_FACT_H]; - - - bool m_bScanBad; // Any errors found? - unsigned m_nScanErrMax; // Max # scan decode errors shown - -public: // FIXME (workaround) - bool m_bDibTempReady; - CDIB m_pDibTemp; // Temporary version for display - bool m_bPreviewIsJpeg; // Is the preview image from decoded JPEG? -private: - - bool m_bDibHistRgbReady; - CDIB m_pDibHistRgb; - - bool m_bDibHistYReady; - CDIB m_pDibHistY; - - bool m_bDetailVlc; - unsigned m_nDetailVlcX; - unsigned m_nDetailVlcY; - unsigned m_nDetailVlcLen; - - unsigned m_nZoomMode; - float m_nZoom; - - // Logger connection - CDocLog* m_pLog; - CwindowBuf* m_pWBuf; - - // Image details (from JFIF decode) set by SetImageDetails() - bool m_bImgDetailsSet; // Have image details been set yet (from SOS) - unsigned m_nDimX; // Image Dimension in X - unsigned m_nDimY; // Image Dimension in Y - unsigned m_nNumSosComps; // Number of Image Components (DHT?) - unsigned m_nNumSofComps; // Number of Image Components (DQT?) - unsigned m_nPrecision; // 8-bit or 12-bit (defined in JFIF_SOF1) - unsigned m_anSofSampFactH[MAX_SOF_COMP_NF]; // Sampling factor per component ID in frame from SOF - unsigned m_anSofSampFactV[MAX_SOF_COMP_NF]; // Sampling factor per component ID in frame from SOF - unsigned m_nSosSampFactHMax; // Maximum sampling factor for scan - unsigned m_nSosSampFactVMax; // Maximum sampling factor for scan - unsigned m_nSosSampFactHMin; // Minimum sampling factor for scan - unsigned m_nSosSampFactVMin; // Minimum sampling factor for scan - unsigned m_anSampPerMcuH[MAX_SOF_COMP_NF]; // Number of samples of component ID per MCU - unsigned m_anSampPerMcuV[MAX_SOF_COMP_NF]; // Number of samples of component ID per MCU - unsigned m_anExpandBitsMcuH[MAX_SOF_COMP_NF]; // Number of bits to replicate in SetFullRes() due to sampling factor - unsigned m_anExpandBitsMcuV[MAX_SOF_COMP_NF]; // Number of bits to replicate in SetFullRes() due to sampling factor - - bool m_bRestartEn; // Did decoder see DRI? - unsigned m_nRestartInterval; // ... if so, what is the MCU interval - unsigned m_nRestartRead; // Number RST read during m_nScanBuff - unsigned m_nPreviewMode; // Preview mode - - // Test shifting of YCC for ChannelPreview() - int m_nPreviewShiftY; - int m_nPreviewShiftCb; - int m_nPreviewShiftCr; - unsigned m_nPreviewShiftMcuX; // Start co-ords of shift - unsigned m_nPreviewShiftMcuY; - - unsigned m_nPreviewInsMcuX; // Test blank MCU insert - unsigned m_nPreviewInsMcuY; - unsigned m_nPreviewInsMcuLen; - - - - // DQT Table -public: - unsigned short m_anDqtCoeff[MAX_DQT_DEST_ID][MAX_DQT_COEFF]; // Normal ordering - unsigned short m_anDqtCoeffZz[MAX_DQT_DEST_ID][MAX_DQT_COEFF]; // Original zigzag ordering - int m_anDqtTblSel[MAX_DQT_COMP]; // DQT table selector for image component in frame - -private: - - - bool m_bDecodeScanAc; // User request decode of AC components? - - // Brightest pixel detection - int m_nBrightY; - int m_nBrightCb; - int m_nBrightCr; - unsigned m_nBrightR; - unsigned m_nBrightG; - unsigned m_nBrightB; - CPoint m_ptBrightMcu; - bool m_bBrightValid; - - // Average pixel intensity - long m_nAvgY; - bool m_bAvgYValid; - - - bool m_bScanErrorsDisable; // Disable scan errors reporting - - // Temporary processing of IDCT per block - float m_afIdctLookup[DCT_SZ_ALL][DCT_SZ_ALL]; // IDCT lookup table (floating point) - int m_anIdctLookup[DCT_SZ_ALL][DCT_SZ_ALL]; // IDCT lookup table (fixed point) - unsigned m_nDctCoefMax; // Largest DCT coeff to process - signed short m_anDctBlock[DCT_SZ_ALL]; // Input block for IDCT process - float m_afIdctBlock[DCT_SZ_ALL]; // Output block after IDCT (via floating point) - int m_anIdctBlock[DCT_SZ_ALL]; // Output block after IDCT (via fixed point) - - // DHT Lookup table for real decode - // Note: Component destination index is 1-based; first entry [0] is unused - int m_anDhtTblSel [MAX_DHT_CLASS][1+MAX_SOS_COMP_NS]; // DHT table selected for image component index (1..4) - unsigned m_anHuffMaskLookup[32]; - // Huffman lookup table for current scan - unsigned m_anDhtLookupSetMax [MAX_DHT_CLASS]; // Highest DHT table index (ie. 0..3) per class - unsigned m_anDhtLookupSize [MAX_DHT_CLASS][MAX_DHT_DEST_ID]; // Number of entries in each lookup table - unsigned m_anDhtLookup_bitlen[MAX_DHT_CLASS][MAX_DHT_DEST_ID][MAX_DHT_CODES]; // Number of compare bits in MSB - unsigned m_anDhtLookup_bits [MAX_DHT_CLASS][MAX_DHT_DEST_ID][MAX_DHT_CODES]; // Compare bits in MSB - unsigned m_anDhtLookup_mask [MAX_DHT_CLASS][MAX_DHT_DEST_ID][MAX_DHT_CODES]; // Mask of compare bits - unsigned m_anDhtLookup_code [MAX_DHT_CLASS][MAX_DHT_DEST_ID][MAX_DHT_CODES]; // Resulting code - unsigned m_anDhtLookupfast [MAX_DHT_CLASS][MAX_DHT_DEST_ID][2<= 8) - unsigned long m_nScanBuffPtr; // Next byte position to load - unsigned long m_nScanBuffPtr_start; // Saved first position of scan data (reset by RSTn markers) - unsigned long m_nScanBuffPtr_first; // Saved first position of scan data in file (not reset by RSTn markers). For comp ratio. - - bool m_nScanCurErr; // Mark as soon as error occurs - unsigned m_anScanBuffPtr_pos[4]; // File posn for each byte in buffer - unsigned m_anScanBuffPtr_err[4]; // Does this byte have an error? - unsigned m_nScanBuffLatchErr; - unsigned m_nScanBuffPtr_num; // Number of bytes in buffer - unsigned m_nScanBuffPtr_align; // Bit alignment in file for 1st byte in buffer - bool m_bScanEnd; // Reached end of scan segment? - - bool m_bRestartRead; // Have we seen a restart marker? - unsigned m_nRestartLastInd; // Last Restart marker read (0..7) - unsigned m_nRestartExpectInd; // Next Restart marker expected (0..7) - unsigned m_nRestartMcusLeft; // How many MCUs until next RST? - - bool m_bSkipDone; - unsigned m_nSkipCount; - unsigned m_nSkipData; - - bool m_bVerbose; - unsigned m_nWarnYccClipNum; - unsigned m_nWarnBadScanNum; - - unsigned m_nScanBitsUsed1; - unsigned m_nScanBitsUsed2; - - // Image Analysis, histograms - bool m_bHistEn; // Histograms enabled? (by AppConfig) - bool m_bStatClipEn; // UNUSED: Enable scan clipping stats? - unsigned m_nNumPixels; - PixelCcHisto m_sHisto; // YCC/RGB histogram (min/max/avg) - PixelCcClip m_sStatClip; // YCC/RGB clipping stats - - unsigned m_anCcHisto_r[HISTO_BINS]; - unsigned m_anCcHisto_g[HISTO_BINS]; - unsigned m_anCcHisto_b[HISTO_BINS]; - - // For image similarity analysis - unsigned m_anHistoYFull[FULL_HISTO_BINS]; - unsigned m_anHistoYSubset[FULL_HISTO_BINS]; - - - // For View management - int m_nPageHeight; - int m_nPageWidth; - - unsigned m_nPreviewPosX; // Top-left coord of preview image - unsigned m_nPreviewPosY; // Top-left coord of preview image - unsigned m_nPreviewSizeX; // X dimension of preview image - unsigned m_nPreviewSizeY; // Y dimension of preview image - - bool m_bViewOverlaysMcuGrid; // Do we enable MCU Grid Overlay - -}; - - - - +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - This module decodes the scan segment (SOS) +// - Depends on quantization tables and huffman tables +// - At this time, only a single scan per frame/file is decoded +// - Chroma subsampling +// - Color conversion and bitmap display output +// - Channel selection for output +// - Statistics: histogram, brightest pixel, etc. +// +// ========================================================================== + +#ifndef IMGDECODE_H +#define IMGDECODE_H + +#include +#include +#include +#include +#include + +#include "SnoopConfig.h" + +#include "snoop.h" + +#include "DocLog.h" +#include "WindowBuf.h" +//#include "afxwin.h" +//#include "Dib.h" + +#include + +#include "General.h" + +// Color conversion clipping (YCC) reporting +#define YCC_CLIP_REPORT_ERR true // Are YCC clips an error? +#define YCC_CLIP_REPORT_MAX 10 // Number of same error to report + +// Scan image component indices for known arrangements +#define COMP_IND_YCC_Y 1 +#define COMP_IND_YCC_CB 2 +#define COMP_IND_YCC_CR 3 +#define COMP_IND_YCC_K 4 +#define COMP_IND_CMYK_C 1 +#define COMP_IND_CMYK_M 2 +#define COMP_IND_CMYK_Y 3 +#define COMP_IND_CMYK_K 3 + +// Definitions for DHT array indices m_anDhtTblSel[][] +#define MAX_DHT_CLASS 2 +#define MAX_DHT_DEST_ID 4 // Maximum range for DHT Destination ID (ie. DHT:Th). Range 0..3 +#define DHT_CLASS_DC 0 +#define DHT_CLASS_AC 1 + +#define MAX_DHT_CODES 260 // Was 180, but with 12-bit DHT, we may have nearly all 0xFF codes +#define MAX_DHT_CODELEN 16 // Max number of bits in a code +#define DHT_CODE_UNUSED 0xFFFFFFFF // Mark table entry as unused + +#define MAX_DQT_DEST_ID 4 // Maximum range for DQT Destination ID (ie. DQT:Tq). Range 0..3 +#define MAX_DQT_COEFF 64 // Number of coefficients in DQT matrix +#define MAX_DQT_COMP 256 // Max range of frame component identifier (SOF:Ci, 0..255) + +#define DCT_COEFF_DC 0 // DCT matrix coefficient index for DC component + +#define MAX_SAMP_FACT_H 4 // Maximum sampling factor supported +#define MAX_SAMP_FACT_V 4 // Maximum sampling factor supported + +#define DQT_DEST_Y 1 +#define DQT_DEST_CB 2 +#define DQT_DEST_CR 3 +#define DQT_DEST_K 4 + +#define BLK_SZ_X 8 // JPEG block size (x) +#define BLK_SZ_Y 8 // JPEG block size (y) + +#define DCT_SZ_X 8 // IDCT matrix size (x) +#define DCT_SZ_Y 8 // IDCT matrix size (y) +#define DCT_SZ_ALL (DCT_SZ_X*DCT_SZ_Y) // IDCT matrix all coeffs + +#define IMG_BLK_SZ 1 // Size of each MCU in image display +#define MAX_SCAN_DECODED_DIM 512 // X & Y dimension for top-left image display +#define DHT_FAST_SIZE 9 // Number of bits for DHT direct lookup + +// FIXME: MAX_SOF_COMP_NF per spec might actually be 255 +#define MAX_SOF_COMP_NF 256 // Maximum number of Image Components in Frame (Nf) [from SOF] (Nf range 1..255) +#define MAX_SOS_COMP_NS 4 // Maximum number of Image Components in Scan (Ns) [from SOS] (Ns range 1..4) + +// TODO: Merge with COMP_IND_YCC_*? +#define SCAN_COMP_Y 1 +#define SCAN_COMP_CB 2 +#define SCAN_COMP_CR 3 +#define SCAN_COMP_K 4 + +// Number of image channels supported for image output +#define NUM_CHAN_GRAYSCALE 1 +#define NUM_CHAN_YCC 3 +#define NUM_CHAN_YCCK 4 + +// Image channel indices (after converting component index to channel index) +#define CHAN_Y 0 +#define CHAN_CB 1 +#define CHAN_CR 2 + +#define CHAN_R 0 +#define CHAN_G 1 +#define CHAN_B 2 + +// Maximum number of blocks that can be marked +// - This feature is generally used to mark ranges for the detailed scan decode feature +#define MAX_BLOCK_MARKERS 10 + +// JFIF Markers relevant for Scan Decoder +// - Restart markers +// - EOI +static const uint32_t JFIF_RST0 = 0xD0; +static const uint32_t JFIF_RST1 = 0xD1; +static const uint32_t JFIF_RST2 = 0xD2; +static const uint32_t JFIF_RST3 = 0xD3; +static const uint32_t JFIF_RST4 = 0xD4; +static const uint32_t JFIF_RST5 = 0xD5; +static const uint32_t JFIF_RST6 = 0xD6; +static const uint32_t JFIF_RST7 = 0xD7; +static const uint32_t JFIF_EOI = 0xD9; + +// Color correction clipping indicator +#define CC_CLIP_NONE 0x00000000 +#define CC_CLIP_Y_UNDER 0x80000000 +#define CC_CLIP_Y_OVER 0x00800000 +#define CC_CLIP_CB_UNDER 0x40000000 +#define CC_CLIP_CB_OVER 0x00400000 +#define CC_CLIP_CR_UNDER 0x20000000 +#define CC_CLIP_CR_OVER 0x00200000 +#define CC_CLIP_R_UNDER 0x00008000 +#define CC_CLIP_R_OVER 0x00000080 +#define CC_CLIP_G_UNDER 0x00004000 +#define CC_CLIP_G_OVER 0x00000040 +#define CC_CLIP_B_UNDER 0x00002000 +#define CC_CLIP_B_OVER 0x00000020 + +#define CC_CLIP_YCC_EN true +#define CC_CLIP_YCC_MIN 0 +#define CC_CLIP_YCC_MAX 255 + +// Image histogram definitions +static const int32_t HISTO_BINS = 128; +static const int32_t HISTO_BIN_WIDTH = 1; +static const int32_t HISTO_BIN_HEIGHT_MAX = 30; + +// Histogram of Y component (-1024..+1023) = 2048 bins +static const int32_t FULL_HISTO_BINS = 2048; +static const int32_t SUBSET_HISTO_BINS = 512; + +// Image locations +static const int32_t nBorderLeft = 10; +static const int32_t nBorderBottom = 10; +static const int32_t nTitleHeight = 20; +static const int32_t nTitleIndent = 5; +static const int32_t nTitleLowGap = 3; + +// Return values for ReadScanVal() +enum teRsvRet +{ + RSV_OK, // OK + RSV_EOB, // End of Block + RSV_UNDERFLOW, // Ran out of data in buffer + RSV_RST_TERM // No huffman code found, but restart marker seen +}; + +// Scan decode errors (in m_anScanBuffPtr_err[] buffer array) +enum teScanBufStatus +{ + SCANBUF_OK, + SCANBUF_BADMARK, + SCANBUF_RST +}; + +// Per-pixel color conversion structure +// - Records each stage of the process and associated clipping/ranging +typedef struct +{ + // Pre-ranged YCC + // - Raw YCC value from pixel map before any adjustment + // - Example range: -1024...1023 + int32_t nPrerangeY; + int32_t nPrerangeCb; + int32_t nPrerangeCr; + + // Pre-clip YCC + // - After scaling pre-ranged values + // - Typical range should be 0..255 + int32_t nPreclipY; + int32_t nPreclipCb; + int32_t nPreclipCr; + + // Final YCC + // - After clipping to ensure we are in range 0..255 + uint8_t nFinalY; + uint8_t nFinalCr; + uint8_t nFinalCb; + + // Pre-clip RGB + // - After color conversion and level shifting + double nPreclipR; + double nPreclipG; + double nPreclipB; + + // Final RGB + // - After clipping to 0..255 + uint8_t nFinalR; + uint8_t nFinalG; + uint8_t nFinalB; + + // Any YCC or RGB clipping performed? + uint32_t nClip; // Multi-bit indicator of clipping (CC_CLIP_*) +} PixelCc; + +// Per-pixel stats: clipping (overflow and underflow) in YCC and RGB +typedef struct +{ + uint32_t nClipYUnder; + uint32_t nClipYOver; + uint32_t nClipCbUnder; + uint32_t nClipCbOver; + uint32_t nClipCrUnder; + uint32_t nClipCrOver; + uint32_t nClipRUnder; + uint32_t nClipROver; + uint32_t nClipGUnder; + uint32_t nClipGOver; + uint32_t nClipBUnder; + uint32_t nClipBOver; + uint32_t nClipWhiteOver; +} PixelCcClip; + +// Min-max and average pixel stats for histogram +typedef struct +{ + int32_t nPreclipYMin; + int32_t nPreclipYMax; + int32_t nPreclipYSum; + int32_t nPreclipCbMin; + int32_t nPreclipCbMax; + int32_t nPreclipCbSum; + int32_t nPreclipCrMin; + int32_t nPreclipCrMax; + int32_t nPreclipCrSum; + + int32_t nClipYMin; + int32_t nClipYMax; + int32_t nClipYSum; + int32_t nClipCbMin; + int32_t nClipCbMax; + int32_t nClipCbSum; + int32_t nClipCrMin; + int32_t nClipCrMax; + int32_t nClipCrSum; + + int32_t nClipRMin; + int32_t nClipRMax; + int32_t nClipRSum; + int32_t nClipGMin; + int32_t nClipGMax; + int32_t nClipGSum; + int32_t nClipBMin; + int32_t nClipBMax; + int32_t nClipBSum; + + int32_t nPreclipRMin; + int32_t nPreclipRMax; + int32_t nPreclipRSum; + int32_t nPreclipGMin; + int32_t nPreclipGMax; + int32_t nPreclipGSum; + int32_t nPreclipBMin; + int32_t nPreclipBMax; + int32_t nPreclipBSum; + + uint32_t nCount; +} PixelCcHisto; + +class CimgDecode : public QWidget +{ + Q_OBJECT + +public: + CimgDecode(CDocLog * pLog, CwindowBuf * pWBuf, QWidget *parent); + ~CimgDecode(); + + void Reset(); // Called during start of SOS decode + void ResetState(); // Called at start of new JFIF Decode + + void SetStatusBar(QStatusBar *pStatBar); + void DecodeScanImg(uint32_t bStart, bool bDisplay, bool bQuiet); + + void DrawHistogram(bool bQuiet, bool bDumpHistoY); + void ReportHistogramY(); + void ReportColorStats(); + + bool IsPreviewReady(); + + // Config + void SetImageDimensions(uint32_t nWidth, uint32_t nHeight); + void SetImageDetails(uint32_t nDimX, uint32_t nDimY, uint32_t nCompsSOF, uint32_t nCompsSOS, bool bRstEn, + uint32_t nRstInterval); + void SetSofSampFactors(uint32_t nCompInd, uint32_t nSampFactH, uint32_t nSampFactV); + void ResetImageContent(); + + bool SetDqtEntry(uint32_t nTblDestId, uint32_t nCoeffInd, uint32_t nCoeffIndZz, uint16_t nCoeffVal); + bool SetDqtTables(uint32_t nCompInd, uint32_t nTbl); + uint32_t GetDqtEntry(uint32_t nTblDestId, uint32_t nCoeffInd); + bool SetDhtTables(uint32_t nCompInd, uint32_t nTblDc, uint32_t nTblAc); + bool SetDhtEntry(uint32_t nDestId, uint32_t nClass, uint32_t nInd, uint32_t nLen, + uint32_t nBits, uint32_t nMask, uint32_t nCode); + bool SetDhtSize(uint32_t nDestId, uint32_t nClass, uint32_t nSize); + void SetPrecision(uint32_t nPrecision); + + // Modes -- accessed from Doc + void SetPreviewMode(uint32_t nMode); + uint32_t GetPreviewMode(); + void SetPreviewYccOffset(uint32_t nMcuX, uint32_t nMcuY, int32_t nY, int32_t nCb, int32_t nCr); + void GetPreviewYccOffset(uint32_t & nMcuX, uint32_t & nMcuY, int32_t &nY, int32_t &nCb, int32_t &nCr); + void SetPreviewMcuInsert(uint32_t nMcuX, uint32_t nMcuY, int32_t nLen); + void GetPreviewMcuInsert(uint32_t & nMcuX, uint32_t & nMcuY, uint32_t & nLen); + void SetPreviewZoom(bool bInc, bool bDec, bool bSet, uint32_t nVal); + uint32_t GetPreviewZoomMode(); + double GetPreviewZoom(); + bool GetPreviewOverlayMcuGrid(); + void SetPreviewOverlayMcuGridToggle(); + + // Utilities + void LookupFilePosPix(uint32_t nPixX, uint32_t nPixY, uint32_t & nByte, uint32_t & nBit); + void LookupFilePosMcu(uint32_t nMcuX, uint32_t nMcuY, uint32_t & nByte, uint32_t & nBit); + void LookupBlkYCC(uint32_t nBlkX, uint32_t nBlkY, int32_t &nY, int32_t &nCb, int32_t &nCr); + + void SetMarkerBlk(uint32_t nBlkX, uint32_t nBlkY); + uint32_t GetMarkerCount(); + QPoint GetMarkerBlk(uint32_t nInd); + + QPoint PixelToMcu(QPoint ptPix); + QPoint PixelToBlk(QPoint ptPix); + uint32_t McuXyToLinear(QPoint ptMcu); + void GetImageSize(uint32_t & nX, uint32_t & nY); + + // View helper routines + void ViewOnDraw(QPainter * pDC, QRect rectClient, QPoint ptScrolledPos, QFont * pFont, QSize & szNewScrollSize); + void ViewMcuOverlay(QPainter * pDC); + void ViewMcuMarkedOverlay(QPainter * pDC); + void ViewMarkerOverlay(QPainter * pDC, uint32_t nBlkX, uint32_t nBlkY); // UNUSED? + + void GetPixMapPtrs(int16_t *&pMapY, int16_t *&pMapCb, int16_t *&pMapCr); + void GetDetailVlc(bool & bDetail, uint32_t & nX, uint32_t & nY, uint32_t & nLen); + void SetDetailVlc(bool bDetail, uint32_t nX, uint32_t nY, uint32_t nLen); + + void GetPreviewPos(uint32_t & nX, uint32_t & nY); + void GetPreviewSize(uint32_t & nX, uint32_t & nY); + + void ScanErrorsDisable(); + void ScanErrorsEnable(); + + uint32_t PackFileOffset(uint32_t nByte, uint32_t nBit); + void UnpackFileOffset(uint32_t nPacked, uint32_t & nByte, uint32_t & nBit); + + void GetBitmapPtr(uint8_t * &pBitmap); + + // Miscellaneous + void SetStatusText(QString strText); + void SetStatusYccText(QString strText); + QString GetStatusYccText(); + void SetStatusMcuText(QString strText); + QString GetStatusMcuText(); + void SetStatusFilePosText(QString strText); + QString GetStatusFilePosText(); + + void ReportDctMatrix(); + void ReportDctYccMatrix(); + void ReportVlc(uint32_t nVlcPos, uint32_t nVlcAlign, + uint32_t nZrl, int32_t nVal, uint32_t nCoeffStart, uint32_t nCoeffEnd, QString specialStr); + void PrintDcCumVal(uint32_t nMcuX, uint32_t nMcuY, int32_t nVal); + void ReportDcRun(uint32_t nMcuX, uint32_t nMcuY, uint32_t nMcuLen); + + bool m_bDibTempReady; + + QImage *m_pDibTemp; // Temporary version for display + bool m_bPreviewIsJpeg; // Is the preview image from decoded JPEG? + + // DQT Table + uint16_t m_anDqtCoeff[MAX_DQT_DEST_ID][MAX_DQT_COEFF]; // Normal ordering + uint16_t m_anDqtCoeffZz[MAX_DQT_DEST_ID][MAX_DQT_COEFF]; // Original zigzag ordering + int32_t m_anDqtTblSel[MAX_DQT_COMP]; // DQT table selector for image component in frame + +protected: + void paintEvent(QPaintEvent *event) override; + +signals: + void updateStatus(QString statusMsg, int); + +private: + CimgDecode &operator = (const CimgDecode&); + CimgDecode(CimgDecode&); + + void ResetDqtTables(); + void ResetDhtLookup(); + + QString GetScanBufPos(); + QString GetScanBufPos(uint32_t pos, uint32_t align); + + void ConvertYCCtoRGB(uint32_t nMcuX, uint32_t nMcuY, PixelCc & sPix); + void ConvertYCCtoRGBFastFloat(PixelCc & sPix); + void ConvertYCCtoRGBFastFixed(PixelCc & sPix); + + void ScanYccToRgb(); + void CapYccRange(uint32_t nMcuX, uint32_t nMcuY, PixelCc & sPix); + void CapRgbRange(uint32_t nMcuX, uint32_t nMcuY, PixelCc & sPix); + + void GenLookupHuffMask(); + uint32_t ExtractBits(uint32_t nWord, uint32_t nBits); + teRsvRet ReadScanVal(uint32_t nClass, uint32_t nTbl, uint32_t & rZrl, int32_t &rVal); + bool DecodeScanComp(uint32_t nTblDhtDc, uint32_t nTblDhtAc, uint32_t nTblDqt, uint32_t nMcuX, uint32_t nMcuY); + bool DecodeScanCompPrint(uint32_t nTblDhtDc, uint32_t nTblDhtAc, uint32_t nTblDqt, uint32_t nMcuX, uint32_t nMcuY); + int32_t HuffmanDc2Signed(uint32_t nVal, uint32_t nBits); + void CheckScanErrors(uint32_t nMcuX, uint32_t nMcuY, uint32_t nCssX, uint32_t nCssY, uint32_t nComp); + + bool ExpectRestart(); + void DecodeRestartDcState(); + void DecodeRestartScanBuf(uint32_t nFilePos, bool bRestart); + uint32_t BuffAddByte(); + void BuffTopup(); + void ScanBuffConsume(uint32_t nNumBits); + void ScanBuffAdd(uint32_t nNewByte, uint32_t nPtr); + void ScanBuffAddErr(uint32_t nNewByte, uint32_t nPtr, uint32_t nErr); + + // IDCT calcs + void PrecalcIdct(); + void DecodeIdctClear(); + void DecodeIdctSet(uint32_t nTbl, uint32_t num_coeffs, uint32_t zrl, int16_t val); + void DecodeIdctCalcFloat(uint32_t nCoefMax); + void DecodeIdctCalcFixedpt(); + void ClrFullRes(uint32_t nWidth, uint32_t nHeight); + void SetFullRes(uint32_t nMcuX, uint32_t nMcuY, uint32_t nComp, uint32_t nCssXInd, uint32_t nCssYInd, int16_t nDcOffset); + + void ChannelExtract(uint32_t nMode, PixelCc & sSrc, PixelCc & sDst); + void CalcChannelPreviewFull(QRect * pRectView, uint8_t * pTmp); + void CalcChannelPreview(); + + // ------------------------------------------------------------- + // Member variables + // ------------------------------------------------------------- + +// CSnoopConfig * m_pAppConfig; // Pointer to application config + + QMessageBox msgBox; + + uint32_t *m_pMcuFileMap; + uint32_t m_nMcuWidth; // Width (pix) of MCU (e.g. 8,16) + uint32_t m_nMcuHeight; // Height (pix) of MCU (e.g. 8,16) + uint32_t m_nMcuXMax; // Number of MCUs across + uint32_t m_nMcuYMax; // Number of MCUs vertically + uint32_t m_nBlkXMax; // Number of 8x8 blocks across + uint32_t m_nBlkYMax; // Number of 8x8 blocks vertically + + // Fill these with the cumulative values so that we can do + // a YCC to RGB conversion (for level shift previews, etc.) + int16_t *m_pPixValY; // Pixel value + int16_t *m_pPixValCb; // Pixel value + int16_t *m_pPixValCr; // Pixel value + + // Array of block DC values. Only used for under-cursor reporting. + int16_t *m_pBlkDcValY; // Block DC value + int16_t *m_pBlkDcValCb; // Block DC value + int16_t *m_pBlkDcValCr; // Block DC value + + // TODO: Later use these to support frequency spectrum + // display of image data + int16_t *m_pBlkFreqY; // 8x8 Block frequency value + int16_t *m_pBlkFreqCb; // 8x8 Block frequency value + int16_t *m_pBlkFreqCr; // 8x8 Block frequency value + + // Array that indicates whether or not a block has been marked + // This is generally used to mark ranges for the detailed scan decode feature + uint32_t m_nMarkersBlkNum; // Number of 8x8 Block markers + QPoint m_aptMarkersBlk[MAX_BLOCK_MARKERS]; // MCU Markers + + QStatusBar *m_pStatBar; // Link to status bar + QString m_strStatusYcc; // Status bar text: YCC + QString m_strStatusMcu; // Status bar text: MCU + QString m_strStatusFilePos; // Status bar text: File Position + QString m_strTitle; // Image title + + + uint32_t m_nImgSizeXPartMcu; // Image size with possible partial MCU + uint32_t m_nImgSizeYPartMcu; + uint32_t m_nImgSizeX; // Image size rounding up to full MCU + uint32_t m_nImgSizeY; + + // Image rects + QRect m_rectImgBase; // Image with no offset, no scaling + QRect m_rectImgReal; // Image with scaling & offset + QRect m_rectHistBase; // Hist with no offset + QRect m_rectHistReal; // Hist with offset + QRect m_rectHistYBase; // HistY with no offset + QRect m_rectHistYReal; // HistY with offset + + // Decoder DC state + // Tables use signed to help flag undefined table indices + int16_t m_nDcLum; + int16_t m_nDcChrCb; + int16_t m_nDcChrCr; + int16_t m_anDcLumCss[MAX_SAMP_FACT_V * MAX_SAMP_FACT_H]; // Need 4x2 at least. Support up to 4x4 + int16_t m_anDcChrCbCss[MAX_SAMP_FACT_V * MAX_SAMP_FACT_H]; + int16_t m_anDcChrCrCss[MAX_SAMP_FACT_V * MAX_SAMP_FACT_H]; + + bool m_bScanBad; // Any errors found? + uint32_t m_nScanErrMax; // Max # scan decode errors shown + + bool m_bDibHistRgbReady; + QImage *m_pDibHistRgb; + + bool m_bDibHistYReady; + QImage *m_pDibHistY; + + bool m_bDetailVlc; + uint32_t m_nDetailVlcX; + uint32_t m_nDetailVlcY; + uint32_t m_nDetailVlcLen; + + uint32_t m_nZoomMode; + double m_nZoom; + + // Logger connection + CDocLog *m_pLog; + CwindowBuf *m_pWBuf; + + // Image details (from JFIF decode) set by SetImageDetails() + bool m_bImgDetailsSet; // Have image details been set yet (from SOS) + uint32_t m_nDimX; // Image Dimension in X + uint32_t m_nDimY; // Image Dimension in Y + uint32_t m_nNumSosComps; // Number of Image Components (DHT?) + uint32_t m_nNumSofComps; // Number of Image Components (DQT?) + uint32_t m_nPrecision; // 8-bit or 12-bit (defined in JFIF_SOF1) + uint32_t m_anSofSampFactH[MAX_SOF_COMP_NF]; // Sampling factor per component ID in frame from SOF + uint32_t m_anSofSampFactV[MAX_SOF_COMP_NF]; // Sampling factor per component ID in frame from SOF + uint32_t m_nSosSampFactHMax; // Maximum sampling factor for scan + uint32_t m_nSosSampFactVMax; // Maximum sampling factor for scan + uint32_t m_nSosSampFactHMin; // Minimum sampling factor for scan + uint32_t m_nSosSampFactVMin; // Minimum sampling factor for scan + uint32_t m_anSampPerMcuH[MAX_SOF_COMP_NF]; // Number of samples of component ID per MCU + uint32_t m_anSampPerMcuV[MAX_SOF_COMP_NF]; // Number of samples of component ID per MCU + uint32_t m_anExpandBitsMcuH[MAX_SOF_COMP_NF]; // Number of bits to replicate in SetFullRes() due to sampling factor + uint32_t m_anExpandBitsMcuV[MAX_SOF_COMP_NF]; // Number of bits to replicate in SetFullRes() due to sampling factor + + bool m_bRestartEn; // Did decoder see DRI? + uint32_t m_nRestartInterval; // ... if so, what is the MCU interval + uint32_t m_nRestartRead; // Number RST read during m_nScanBuff + uint32_t m_nPreviewMode; // Preview mode + + // Test shifting of YCC for ChannelPreview() + int32_t m_nPreviewShiftY; + int32_t m_nPreviewShiftCb; + int32_t m_nPreviewShiftCr; + uint32_t m_nPreviewShiftMcuX; // Start co-ords of shift + uint32_t m_nPreviewShiftMcuY; + + uint32_t m_nPreviewInsMcuX; // Test blank MCU insert + uint32_t m_nPreviewInsMcuY; + uint32_t m_nPreviewInsMcuLen; + + bool m_bDecodeScanAc; // User request decode of AC components? + + // Brightest pixel detection + int32_t m_nBrightY; + int32_t m_nBrightCb; + int32_t m_nBrightCr; + uint32_t m_nBrightR; + uint32_t m_nBrightG; + uint32_t m_nBrightB; + QPoint m_ptBrightMcu; + bool m_bBrightValid; + + // Average pixel intensity + int32_t m_nAvgY; + bool m_bAvgYValid; + + bool m_bScanErrorsDisable; // Disable scan errors reporting + + // Temporary processing of IDCT per block + double m_afIdctLookup[DCT_SZ_ALL][DCT_SZ_ALL]; // IDCT lookup table (doubleing point) + int32_t m_anIdctLookup[DCT_SZ_ALL][DCT_SZ_ALL]; // IDCT lookup table (fixed point) + uint32_t m_nDctCoefMax; // Largest DCT coeff to process + int16_t m_anDctBlock[DCT_SZ_ALL]; // Input block for IDCT process + double m_afIdctBlock[DCT_SZ_ALL]; // Output block after IDCT (via doubleing point) + int32_t m_anIdctBlock[DCT_SZ_ALL]; // Output block after IDCT (via fixed point) + + // DHT Lookup table for real decode + // Note: Component destination index is 1-based; first entry [0] is unused + int32_t m_anDhtTblSel[MAX_DHT_CLASS][1 + MAX_SOS_COMP_NS]; // DHT table selected for image component index (1..4) + uint32_t m_anHuffMaskLookup[32]; + // Huffman lookup table for current scan + uint32_t m_anDhtLookupSetMax[MAX_DHT_CLASS]; // Highest DHT table index (ie. 0..3) per class + uint32_t m_anDhtLookupSize[MAX_DHT_CLASS][MAX_DHT_DEST_ID]; // Number of entries in each lookup table + uint32_t m_anDhtLookup_bitlen[MAX_DHT_CLASS][MAX_DHT_DEST_ID][MAX_DHT_CODES]; // Number of compare bits in MSB + uint32_t m_anDhtLookup_bits[MAX_DHT_CLASS][MAX_DHT_DEST_ID][MAX_DHT_CODES]; // Compare bits in MSB + uint32_t m_anDhtLookup_mask[MAX_DHT_CLASS][MAX_DHT_DEST_ID][MAX_DHT_CODES]; // Mask of compare bits + uint32_t m_anDhtLookup_code[MAX_DHT_CLASS][MAX_DHT_DEST_ID][MAX_DHT_CODES]; // Resulting code + uint32_t m_anDhtLookupfast[MAX_DHT_CLASS][MAX_DHT_DEST_ID][2 << DHT_FAST_SIZE]; // Fast direct lookup for codes <= 10 bits + uint32_t m_anDhtHisto[MAX_DHT_CLASS][MAX_DHT_DEST_ID][MAX_DHT_CODELEN + 1]; + // Note: MAX_DHT_CODELEN is +1 because this array index is 1-based since there are no codes of length 0 bits + + uint32_t m_nScanBuff; // 32 bits of scan data after removing stuffs + + uint32_t m_nScanBuff_vacant; // Bits unused in LSB after shifting (add if >= 8) + uint32_t m_nScanBuffPtr; // Next uint8_t position to load + uint32_t m_nScanBuffPtr_start; // Saved first position of scan data (reset by RSTn markers) + uint32_t m_nScanBuffPtr_first; // Saved first position of scan data in file (not reset by RSTn markers). For comp ratio. + + bool m_nScanCurErr; // Mark as soon as error occurs + uint32_t m_anScanBuffPtr_pos[4]; // File posn for each uint8_t in buffer + uint32_t m_anScanBuffPtr_err[4]; // Does this uint8_t have an error? + uint32_t m_nScanBuffLatchErr; + uint32_t m_nScanBuffPtr_num; // Number of uint8_ts in buffer + uint32_t m_nScanBuffPtr_align; // Bit alignment in file for 1st uint8_t in buffer + bool m_bScanEnd; // Reached end of scan segment? + + bool m_bRestartRead; // Have we seen a restart marker? + uint32_t m_nRestartLastInd; // Last Restart marker read (0..7) + uint32_t m_nRestartExpectInd; // Next Restart marker expected (0..7) + uint32_t m_nRestartMcusLeft; // How many MCUs until next RST? + + bool m_bSkipDone; + uint32_t m_nSkipCount; + uint32_t m_nSkipData; + + bool m_bVerbose; + uint32_t m_nWarnYccClipNum; + uint32_t m_nWarnBadScanNum; + + uint32_t m_nScanBitsUsed1; + uint32_t m_nScanBitsUsed2; + + // Image Analysis, histograms + bool m_bHistEn; // Histograms enabled? (by AppConfig) + bool m_bStatClipEn; // UNUSED: Enable scan clipping stats? + uint32_t m_nNumPixels; + PixelCcHisto m_sHisto; // YCC/RGB histogram (min/max/avg) + PixelCcClip m_sStatClip; // YCC/RGB clipping stats + + uint32_t m_anCcHisto_r[HISTO_BINS]; + uint32_t m_anCcHisto_g[HISTO_BINS]; + uint32_t m_anCcHisto_b[HISTO_BINS]; + + // For image similarity analysis + uint32_t m_anHistoYFull[FULL_HISTO_BINS]; + uint32_t m_anHistoYSubset[FULL_HISTO_BINS]; + + // For View management + int32_t m_nPageHeight; + int32_t m_nPageWidth; + + uint32_t m_nPreviewPosX; // Top-left coord of preview image + uint32_t m_nPreviewPosY; // Top-left coord of preview image + uint32_t m_nPreviewSizeX; // X dimension of preview image + uint32_t m_nPreviewSizeY; // Y dimension of preview image + + bool m_bViewOverlaysMcuGrid; // Do we enable MCU Grid Overlay +}; + +#endif diff --git a/source/JPEGsnoop.h b/source/JPEGsnoop.h index 4131ab4..7eeecbc 100644 --- a/source/JPEGsnoop.h +++ b/source/JPEGsnoop.h @@ -1,137 +1,136 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Main application code entry-point -// -// ========================================================================== - - -// JPEGsnoop.h : main header file for the JPEGsnoop application -// -#pragma once - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols - -#include "snoop.h" -#include "JPEGsnoopDoc.h" -#include "SnoopConfig.h" - -#include "afxwinappex.h" //xxx - -#include "JPEGsnoopCore.h" - -// CJPEGsnoopApp: -// See JPEGsnoop.cpp for the implementation of this class -// - -// Define global variable for application log -extern CDocLog* glb_pDocLog; - - -class CJPEGsnoopApp : public CWinApp -{ -public: - CJPEGsnoopApp(); - ~CJPEGsnoopApp(); - - -// Overrides -public: - virtual BOOL InitInstance(); - -// Implementation - afx_msg void OnAppAbout(); - - DECLARE_MESSAGE_MAP() - -private: - void MyOnFileOpen(); - void MyOnFileNew(); - - void DoCmdLineCore(); - void CmdLineHelp(); - void CmdLineMessage(CString strMsg); - void CmdLineDoneMessage(); - - void CheckUpdates(bool bForceNow); - bool CheckUpdatesWww(); - bool CheckEula(); - CString RemoveTokenWithSeparators(CString& strText, LPCTSTR szCharSet); - CString RemoveTokenFromCharset(CString& strText, LPCTSTR szCharSet); - CJPEGsnoopDoc* GetCurDoc(); - void DocReprocess(); - void DocImageDirty(); - void HandleAutoReprocess(); - - HINSTANCE LoadAppLangResourceDLL(); // MFC override - - afx_msg void OnOptionsDhtexpand(); - afx_msg void OnOptionsMakernotes(); - afx_msg void OnOptionsScandump(); - afx_msg void OnOptionsDecodescan(); - afx_msg void OnOptionsHistoydump(); - afx_msg void OnUpdateOptionsDhtexpand(CCmdUI *pCmdUI); - afx_msg void OnUpdateOptionsMakernotes(CCmdUI *pCmdUI); - afx_msg void OnUpdateOptionsScandump(CCmdUI *pCmdUI); - afx_msg void OnUpdateOptionsDecodescan(CCmdUI *pCmdUI); - afx_msg void OnUpdateOptionsHistoydump(CCmdUI *pCmdUI); - afx_msg void OnOptionsConfiguration(); - afx_msg void OnOptionsCheckforupdates(); - afx_msg void OnToolsManagelocaldb(); - afx_msg void OnOptionsSignaturesearch(); - afx_msg void OnUpdateOptionsSignaturesearch(CCmdUI *pCmdUI); - afx_msg void OnOptionsDecodeac(); - afx_msg void OnUpdateOptionsDecodeac(CCmdUI *pCmdUI); - afx_msg void OnScansegmentDecodeimage(); - afx_msg void OnScansegmentFullidct(); - afx_msg void OnScansegmentHistogramy(); - afx_msg void OnScansegmentDump(); - afx_msg void OnUpdateScansegmentDecodeimage(CCmdUI *pCmdUI); - afx_msg void OnUpdateScansegmentFullidct(CCmdUI *pCmdUI); - afx_msg void OnUpdateScansegmentHistogramy(CCmdUI *pCmdUI); - afx_msg void OnUpdateScansegmentDump(CCmdUI *pCmdUI); - afx_msg void OnScansegmentNoidct(); - afx_msg void OnUpdateScansegmentNoidct(CCmdUI *pCmdUI); - afx_msg void OnScansegmentHistogram(); - afx_msg void OnUpdateScansegmentHistogram(CCmdUI *pCmdUI); - afx_msg void OnOptionsHideuknownexiftags(); - afx_msg void OnUpdateOptionsHideuknownexiftags(CCmdUI *pCmdUI); - afx_msg void OnFileBatchprocess(); - -public: - // Main config options - CSnoopConfig* m_pAppConfig; - - // Needs to be accessed by JfifDec - CDbSigs* m_pDbSigs; - -private: - bool m_bFatal; // Fatal error occurred (e.g. mem alloc) - -public: - afx_msg void OnOptionsRelaxedparsing(); - afx_msg void OnUpdateOptionsRelaxedparsing(CCmdUI *pCmdUI); -}; - -extern CJPEGsnoopApp theApp; \ No newline at end of file +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - Main application code entry-point +// +// ========================================================================== + + +// JPEGsnoop.h : main header file for the JPEGsnoop application +// +#pragma once + +//#ifndef __AFXWIN_H__ +// #error include 'stdafx.h' before including this file for PCH +//#endif + +#include "resource.h" // main symbols + +#include "snoop.h" +#include "JPEGsnoopCore.h" +//#include "JPEGsnoopDoc.h" +#include "SnoopConfig.h" + + +#include "JPEGsnoopCore.h" + +// CJPEGsnoopApp: +// See JPEGsnoop.cpp for the implementation of this class +// + +// Define global variable for application log +extern CDocLog* glb_pDocLog; +// Main config options +extern CSnoopConfig *m_pAppConfig; +// Needs to be accessed by JfifDec +extern CDbSigs* m_pDbSigs; + +extern CJPEGsnoopCore *pJPEGsnoopCore; + +class CJPEGsnoopApp // : public CWinApp +{ +public: + CJPEGsnoopApp(); + ~CJPEGsnoopApp(); + +// Overrides +public: + virtual bool InitInstance(); + +// Implementation +// afx_msg void OnAppAbout(); + +// DECLARE_MESSAGE_MAP() + +private: + void MyOnFileOpen(); + void MyOnFileNew(); + + void DoCmdLineCore(); + void CmdLineHelp(); + void CmdLineMessage(QString strMsg); + void CmdLineDoneMessage(); + + void CheckUpdates(bool bForceNow); + bool CheckUpdatesWww(); + bool CheckEula(); + QString RemoveTokenWithSeparators(QString& strText, QString szCharSet); + QString RemoveTokenFromCharset(QString& strText, QString szCharSet); +// CJPEGsnoopDoc* GetCurDoc(); + void DocReprocess(); + void DocImageDirty(); + void HandleAutoReprocess(); + +// HINSTANCE LoadAppLangResourceDLL(); // MFC override + +/* afx_msg void OnOptionsDhtexpand(); + afx_msg void OnOptionsMakernotes(); + afx_msg void OnOptionsScandump(); + afx_msg void OnOptionsDecodescan(); + afx_msg void OnOptionsHistoydump(); + afx_msg void OnUpdateOptionsDhtexpand(CCmdUI *pCmdUI); + afx_msg void OnUpdateOptionsMakernotes(CCmdUI *pCmdUI); + afx_msg void OnUpdateOptionsScandump(CCmdUI *pCmdUI); + afx_msg void OnUpdateOptionsDecodescan(CCmdUI *pCmdUI); + afx_msg void OnUpdateOptionsHistoydump(CCmdUI *pCmdUI); + afx_msg void OnOptionsConfiguration(); + afx_msg void OnOptionsCheckforupdates(); + afx_msg void OnToolsManagelocaldb(); + afx_msg void OnOptionsSignaturesearch(); + afx_msg void OnUpdateOptionsSignaturesearch(CCmdUI *pCmdUI); + afx_msg void OnOptionsDecodeac(); + afx_msg void OnUpdateOptionsDecodeac(CCmdUI *pCmdUI); + afx_msg void OnScansegmentDecodeimage(); + afx_msg void OnScansegmentFullidct(); + afx_msg void OnScansegmentHistogramy(); + afx_msg void OnScansegmentDump(); + afx_msg void OnUpdateScansegmentDecodeimage(CCmdUI *pCmdUI); + afx_msg void OnUpdateScansegmentFullidct(CCmdUI *pCmdUI); + afx_msg void OnUpdateScansegmentHistogramy(CCmdUI *pCmdUI); + afx_msg void OnUpdateScansegmentDump(CCmdUI *pCmdUI); + afx_msg void OnScansegmentNoidct(); + afx_msg void OnUpdateScansegmentNoidct(CCmdUI *pCmdUI); + afx_msg void OnScansegmentHistogram(); + afx_msg void OnUpdateScansegmentHistogram(CCmdUI *pCmdUI); + afx_msg void OnOptionsHideuknownexiftags(); + afx_msg void OnUpdateOptionsHideuknownexiftags(CCmdUI *pCmdUI); + afx_msg void OnFileBatchprocess(); */ + +public: + +private: + bool m_bFatal; // Fatal error occurred (e.g. mem alloc) + +public: +// afx_msg void OnOptionsRelaxedparsing(); +// afx_msg void OnUpdateOptionsRelaxedparsing(CCmdUI *pCmdUI); +}; + +extern CJPEGsnoopApp theApp; diff --git a/source/JPEGsnoopCore.cpp b/source/JPEGsnoopCore.cpp index 4981d28..50d3594 100644 --- a/source/JPEGsnoopCore.cpp +++ b/source/JPEGsnoopCore.cpp @@ -1,1399 +1,1495 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "stdafx.h" -#include "JPEGsnoopCore.h" - -// For glb_pDocLog -#include "JPEGsnoop.h" - -CJPEGsnoopCore::CJPEGsnoopCore(void) -{ - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopCore::CJPEGsnoopCore() Begin")); - // Initialize processing classes - - // Save a local copy of the config struct pointer - m_pAppConfig = theApp.m_pAppConfig; - - // Ensure the local log isn't linked to a CDocument - glb_pDocLog->SetDoc(NULL); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 1")); - - // Allocate the file window buffer - m_pWBuf = new CwindowBuf(); - if (!m_pWBuf) { - AfxMessageBox(_T("ERROR: Not enough memory for File Buffer")); - exit(1); - } - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 2")); - - // Allocate the JPEG decoder - m_pImgDec = new CimgDecode(glb_pDocLog,m_pWBuf); - if (!m_pWBuf) { - AfxMessageBox(_T("ERROR: Not enough memory for Image Decoder")); - exit(1); - } - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 3")); - - m_pJfifDec = new CjfifDecode(glb_pDocLog,m_pWBuf,m_pImgDec); - if (!m_pWBuf) { - AfxMessageBox(_T("ERROR: Not enough memory for JFIF Decoder")); - exit(1); - } - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 4")); - - - // Reset all members - Reset(); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 5")); - - // Start in quick mode -#ifdef QUICKLOG - glb_pDocLog->SetQuickMode(true); -#else - glb_pDocLog->SetQuickMode(false); -#endif - - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopCore::CJPEGsnoopCore() End")); -} - - -CJPEGsnoopCore::~CJPEGsnoopCore(void) -{ - if (m_pJfifDec != NULL) - { - delete m_pJfifDec; - m_pJfifDec = NULL; - } - - if (m_pWBuf != NULL) { - delete m_pWBuf; - m_pWBuf = NULL; - } - - if (m_pImgDec != NULL) { - delete m_pImgDec; - m_pImgDec = NULL; - } - -} - -// Reset all state -void CJPEGsnoopCore::Reset() -{ - // Reset all members - m_pFile = NULL; - m_lFileSize = 0L; - m_strPathName = _T(""); - - // No log data available until we open & process a file - m_bFileOpened = false; - m_bFileAnalyzed = false; - - // FIXME: Should we be calling Reset on the JfifDecoder, ImgDecoder and WBuf? - - // Indicate to JFIF ProcessFile() that document has changed - // and that the scan decode needs to be redone if it - // is to be displayed. - m_pJfifDec->ImgSrcChanged(); - - // Clean up the quick log - glb_pDocLog->Clear(); - -} - -void CJPEGsnoopCore::SetStatusBar(CStatusBar* pStatBar) -{ - // Save a copy of the status bar - //xxx m_pStatBar = pStatBar; - - // Now update the JFIF decoder and Image Decoder with the - // revised status bar pointer (or NULL) - m_pJfifDec->SetStatusBar(pStatBar); - m_pImgDec->SetStatusBar(pStatBar); -} - -// -// Has a file been analyzed previously? -// - This indicator is used extensively in the CJPEGsnoopDoc -// to determine whether menu items are enabled or not -// -BOOL CJPEGsnoopCore::IsAnalyzed() -{ - return m_bFileAnalyzed; -} - -// Open the file named in m_strPathName -// - Close / cleanup if another file was already open -// -// INPUT: -// - strFname = File to open -// -// POST: -// - m_pFile -// - m_lFileSize -// - m_pWBuf loaded -// -// RETURN: -// - Indicates if file open was successful -// -BOOL CJPEGsnoopCore::AnalyzeOpen() -{ - ASSERT(m_strPathName != _T("")); - if (m_strPathName == _T("")) { - // Force dialog box to show as this is a major error - // TODO: Handle non-GUI mode - AfxMessageBox(_T("ERROR: AnalyzeOpen() but m_strPathName empty")); - return false; - } - - // Clean up if a file is already open - if (m_pFile != NULL) - { - // Mark previous buffer as closed - m_pWBuf->BufFileUnset(); - m_pFile->Close(); - delete m_pFile; - m_pFile = NULL; - m_lFileSize = 0L; - } - - try - { - // Open specified file - // Added in shareDenyNone as this apparently helps resolve some people's troubles - // with an error showing: Couldn't open file "Sharing Violation" - m_pFile = new CFile(m_strPathName, CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone); - } - catch (CFileException* e) - { - TCHAR strMsg[MAX_BUF_EX_ERR_MSG]; - CString strError; - e->GetErrorMessage(strMsg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - // Note: msg includes m_strPathName - strError.Format(_T("ERROR: Couldn't open file: [%s]"),strMsg); - glb_pDocLog->AddLineErr(strError); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strError); - m_pFile = NULL; - - return FALSE; - - } - - - // Set the file size variable - m_lFileSize = m_pFile->GetLength(); - - // Don't attempt to load buffer with zero length file! - if (m_lFileSize==0) { - return TRUE; - } - - // Open up the buffer - m_pWBuf->BufFileSet(m_pFile); - m_pWBuf->BufLoadWindow(0); - - // Mark file as opened - m_bFileOpened = true; - - return TRUE; - -} - -// Close the current file -// - Invalidate the buffer -// -// POST: -// - m_bFileOpened -// -void CJPEGsnoopCore::AnalyzeClose() -{ - // Indicate no file is currently opened - // Note that we don't clear m_bFileAnalyzed as the last - // decoder state is still available - m_bFileOpened = false; - - // Close the buffer window - m_pWBuf->BufFileUnset(); - - // Now that we've finished parsing the file, close it! - if (m_pFile != NULL) - { - m_pFile->Close(); - delete m_pFile; - m_pFile = NULL; - } - - -} - -// Perform the file analysis -// - Output the log header text -// - Process the current file via ProcessFile() -// - Dump the output to the log (if in QuickLog mode) -// -// PRE: -// - m_strPathname -// -// PRE: -// - m_bFileOpened -// - m_pFile -// - m_pJfifDec -// - m_pImgDec -// - m_lFileSize -// - m_pAppConfig->nPosStart = Starting file offset for decode -// -// POST: -// - m_bFileAnalyzed -// -void CJPEGsnoopCore::AnalyzeFileDo() -{ - // Ensure file was already opened - ASSERT(m_pFile); - ASSERT(m_bFileOpened); - - // Reset the analyzed state in case this file is invalid (eg. zero length) - m_bFileAnalyzed = false; - - // Start in Quick mode (probably don't care for command-line mode) - glb_pDocLog->SetQuickMode(true); - - // Clear the document log - glb_pDocLog->Clear(); - - CString strTmp; - glb_pDocLog->AddLine(_T("")); - strTmp.Format(_T("JPEGsnoop %s by Calvin Hass"),VERSION_STR); - glb_pDocLog->AddLine(strTmp); - glb_pDocLog->AddLine(_T(" http://www.impulseadventure.com/photo/")); - glb_pDocLog->AddLine(_T(" -------------------------------------")); - glb_pDocLog->AddLine(_T("")); - strTmp.Format(_T(" Filename: [%s]"),(LPCTSTR)m_strPathName); - glb_pDocLog->AddLine(strTmp); - strTmp.Format(_T(" Filesize: [%llu] Bytes"),m_lFileSize); - glb_pDocLog->AddLine(strTmp); - glb_pDocLog->AddLine(_T("")); - - - // Perform the actual decoding - if (m_lFileSize > 0xFFFFFFFFULL) { - strTmp.Format(_T("ERROR: File too large for this version of JPEGsnoop. [Size=0x%I64X]"), m_lFileSize); - glb_pDocLog->AddLineErr(strTmp); - } else if (m_lFileSize == 0) { - glb_pDocLog->AddLineErr(_T("ERROR: File length is zero, no decoding done.")); - } else { - m_pJfifDec->ProcessFile(m_pFile); - // Now indicate that the file has been processed - m_bFileAnalyzed = true; - } - -} - -// Analyze the current file -// - Open file -// - Analyze file -// - Close file -// -// INPUT: -// - strFname = File to analyze -// -// PRE: -// - m_pAppConfig->nPosStart = Starting file offset for decode -// -// RETURN: -// - Status from opening file -// -BOOL CJPEGsnoopCore::AnalyzeFile(CString strFname) -{ - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::AnalyzeFile() Begin")); - - BOOL bRetVal; - - // Save the input filename - // This filename is used later to confirm that output filename doesn't - // match input filename when we save the log - m_strPathName = strFname; - - // Assumes that we have set up the member vars already - // Perform the actual processing. We have this in a routine - // so that we can quickly recalculate the log file again - // if an option changes. - - bRetVal = AnalyzeOpen(); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::AnalyzeFile() Checkpoint 1")); - if (bRetVal) { - // Only now that we have successfully opened the document - // should be mark the flag as such. This flag is used by - // other menu items to know whether or not the file is ready. - AnalyzeFileDo(); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::AnalyzeFile() Checkpoint 2")); - } - AnalyzeClose(); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::AnalyzeFile() Checkpoint 3")); - - // In the last part of AnalyzeClose(), we mark the file - // as not modified, so that we don't get prompted to save. - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::AnalyzeFile() End")); - - return bRetVal; - -} - -// Save the current log to text file with a simple implementation -// -// - This routine is implemented with a simple output mechanism rather -// than leveraging CRichEditCtrl::DoSave() so that we can perform -// this operation in command-line mode or batch mode operations. -// -// TODO: Should this be moved into CDocLog? -// -void CJPEGsnoopCore::DoLogSave(CString strLogName) -{ - CStdioFile* pLog; - - // Open the file for output - ASSERT(strLogName != _T("")); - - // OLD COMMENTS FOLLOW - // This save method will only work if we were in Quick Log mode - // where we have recorded the log to a string buffer and not - // directly to the RichEdit - // Note that m_bLogQuickMode is only toggled on during processing - // so we can't check the status here (except seeing that there are no - // lines in the array) - - // TODO: Ensure file doesn't exist and only overwrite if specified in command-line? - - // TODO: Confirm that we are not writing to the same file we opened (m_strPathName) - ASSERT(strLogName != m_strPathName); - - try - { - // Open specified file - pLog = new CStdioFile(strLogName, CFile::modeCreate| CFile::modeWrite | CFile::typeText | CFile::shareDenyNone); - } - catch (CFileException* e) - { - TCHAR msg[MAX_BUF_EX_ERR_MSG]; - CString strError; - e->GetErrorMessage(msg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - strError.Format(_T("ERROR: Couldn't open file for write [%s]: [%s]"), - (LPCTSTR)strLogName, (LPCTSTR)msg); - // FIXME: Find an alternate method of signaling error in command-line mode - AfxMessageBox(strError); - pLog = NULL; - - return; - - } - - // Step through the current log buffer - CString strLine; - COLORREF sCol; - unsigned nQuickLines = glb_pDocLog->GetNumLinesLocal(); - for (unsigned nLine=0;nLineGetLineLogLocal(nLine,strLine,sCol); - - // NOTE: At this time, batch file processing uses an 8-bit text file output format - // rather than the Unicode-supporting CRichEdit that is used when we manually - // save the log file. - // - // If we pass extended characters to WriteString() when the CStdioFile has been - // opened as CFile::typeText, the extended characters will terminate the lines - // early. - // - // Therefore, we will convert all extended characters back to ASCII here. - // - // TODO: Revise this logic so that we can have more foreign-character support - // in the batch output files. - CW2A strAscii(strLine); - CString strConv(strAscii); - pLog->WriteString(strConv); - } - - // Close the file - if (pLog) { - pLog->Close(); - delete pLog; - } - -} - -// -------------------------------------------------------------------- -// --- START OF BATCH PROCESSING -// -------------------------------------------------------------------- - -// -// Generate a list of files for a batch processing operation -// -// POST: -// - m_asBatchFiles = Contains list of full file paths -// -void CJPEGsnoopCore::GenBatchFileList(CString strDirSrc,CString strDirDst,bool bRecSubdir,bool bExtractAll) -{ - // TODO: - // - What is the best way to provide a "Cancel Dialog" for a - // recursive operation? I can easily create the cancel / progress - // dialog with operations that have can be single-stepped, but - // not ones that require accumulation on the stack. - // - For now, just leave as-is. - - // Example code that I can use for single-stepping the operation: - // - // // === START - // COperationDlg LengthyOp(this); - // LengthyOp.SetFunctions( PrepareOperation, NextIteration, GetProgress ); - // - // // Until-done based - // BOOL bOk = LengthyOp.RunUntilDone( true ); - // // === END - - m_asBatchFiles.RemoveAll(); - m_asBatchOutputs.RemoveAll(); - - // Start the batch operation - GenBatchFileListRecurse(strDirSrc,strDirDst,_T(""),bRecSubdir,bExtractAll); - -} - -// Recursive routine that searches for files and folders -// Used in batch file processing mode -// -// INPUT: -// - strSrcRootName Starting path for input files -// - strDstRootName Starting path for output files -// - strPathName Path (below strSrcRootName) and filename for current input file -// - bSubdirs Flag to descend into all sub-directories -// - bExtractAll Flag to extract all JPEG from file -// -void CJPEGsnoopCore::GenBatchFileListRecurse(CString strSrcRootName,CString strDstRootName,CString strPathName,bool bSubdirs,bool bExtractAll) -{ - // The following code snippet is based on MSDN code: - // http://msdn.microsoft.com/en-us/library/scx99850%28VS.80%29.aspx - - CFileFind finder; - CString strWildcard; - CString strDirName; - CString strSubPath; - CString strPath; - - // build a string with wildcards - if (strPathName.IsEmpty()) { - strWildcard.Format(_T("%s\\*.*"),(LPCTSTR)strSrcRootName); - } else { - strWildcard.Format(_T("%s\\%s\\*.*"),(LPCTSTR)strSrcRootName,(LPCTSTR)strPathName); - } - - // start working for files - BOOL bWorking = finder.FindFile(strWildcard); - - while (bWorking) - { - bWorking = finder.FindNextFile(); - - // skip . and .. files; otherwise, we'd - // recur infinitely! - - if (finder.IsDots()) - continue; - - strPath = finder.GetFilePath(); - - // Now need to remove "root" from "path" to recalculate - // new relative subpath - strDirName = finder.GetFileName(); - if (strPathName.IsEmpty()) { - strSubPath = strDirName; - } else { - strSubPath.Format(_T("%s\\%s"),(LPCTSTR)strPathName,(LPCTSTR)strDirName); - } - - // if it's a directory, recursively search it - if (finder.IsDirectory()) - { - if (bSubdirs) { - GenBatchFileListRecurse(strSrcRootName,strDstRootName,strSubPath,bSubdirs,bExtractAll); - } - } else { - // GetFilePath() includes both the path & filename - // when called on a file entry, so there is no need - // to specifically call GetFileName() - // CString strFname = finder.GetFileName(); - - // Now perform final filtering check on file - // and add to batch file list - GenBatchFileListSingle(strSrcRootName,strDstRootName,strSubPath,bExtractAll); - } - } - - finder.Close(); -} - - -// Perform processing on file selected by the batch recursion -// process GenBatchFileListRecurse(). -// -// INPUT: -// - strSrcRootName Starting path for input files -// - strDstRootName Starting path for output files -// - strPathName Path (below szSrcRootName) and filename for current input file -// - bExtractAll Flag to extract all JPEG from file -// -void CJPEGsnoopCore::GenBatchFileListSingle(CString strSrcRootName,CString strDstRootName,CString strPathName,bool bExtractAll) -{ - //bool bDoSubmit = false; - unsigned nInd; - - CString strFnameSrc; - CString strFnameDst; - CString strFnameOnly; - CString strFnameExt; - CString strFnameLog; - CString strFnameEmbed; - - strFnameSrc.Format(_T("%s\\%s"),(LPCTSTR)strSrcRootName,(LPCTSTR)strPathName); - strFnameDst.Format(_T("%s\\%s"),(LPCTSTR)strDstRootName,(LPCTSTR)strPathName); - - // Extract the filename (without extension) and extension from - // the full pathname. - // - // FIXME: Rewrite to use Windows APIs to do this or else - // use the boost library as they will be more robust than - // the simple searches for '\' and '.' that are done here. - // -#if 1 - // ----------- - strFnameOnly = strFnameSrc.Mid(strFnameSrc.ReverseFind('\\')+1); - nInd = strFnameOnly.ReverseFind('.'); - strFnameOnly = strFnameOnly.Mid(0,nInd); - - - // Extract the file extension - nInd = strFnameSrc.ReverseFind('.'); - strFnameExt = strFnameSrc.Mid(nInd); - strFnameExt.MakeLower(); - // ----------- -#else - unsigned nLen = strFnameSrc.GetLength(); - LPTSTR lpstrSrcFullpath = new TCHAR[nLen+1]; - _tcscpy_s(lpstrSrcFullpath,nLen+1,strFnameSrc); - - LPTSTR lpstrSrcFnameAndExt = NULL; - lpstrSrcFnameAndExt = PathFindFileName(lpstrSrcFullpath); - ... -#endif - - // Only process files that have an extension that implies JPEG - // Batch processing is generally limited to files that appear to - // represent a JPEG image (ie. ".jpg" an ".jpeg"). - // - // TODO: Enable user to present list of extensions or disable - // the check altogether. - - // TODO: Add Batch processing support for .PSD? - - bool bProcessFile = false; - - // TODO: Support m_pAppConfig->strBatchExtensions - if ((strFnameExt == _T(".jpg")) || (strFnameExt == _T(".jpeg"))) { - bProcessFile = true; - } - if (bExtractAll) { - - // In the "Extract all" mode during batch processing, we disable - // the extension check altogether as "Extract all" mode generally - // implies that the files may not be standalone JPEG image files. - // They could also be corrupt files that contain JPEG images. - // - // TODO: Provide additional configuration options ahead of time. - bProcessFile = true; - } - - if (bProcessFile) { - - // Generate the output log file name - // - // IMPORTANT NOTE: - // It is *essential* that this Append function work properly - // as it is used to generate the log filename from the - // image filename. Since we may be automatically overwriting - // the logfile, it is imperative that we ensure that there is - // no chance that the log filename happens to be the original - // JPEG filename. - // - // In the interests of paranoia, we perform some extra checks - // here to ensure that this doesn't happen. - - strFnameLog = strFnameDst; - strFnameLog.Append(_T(".txt")); - - // Now double check the filenames to ensure they don't match the image - - // - Is the last 4 characters of the strFname ".txt"? - if (strFnameLog.Right(4) != _T(".txt")) { - // Report error message and skip logfile save - // TODO: Handle non-GUI mode - AfxMessageBox(_T("ERROR: Internal error #10100")); - return; - } - // - Is the strFnameLog different from the input filename (strFname)? - if (strFnameLog == strPathName) { - // Report error message and skip logfile save - // TODO: Handle non-GUI mode - AfxMessageBox(_T("ERROR: Internal error #10101")); - return; - } - - // Add filename pair to the list - // - Input filename to analyze - // - Output filename for associated log/report - m_asBatchFiles.Add(strFnameSrc); - m_asBatchDest.Add(strFnameDst); - m_asBatchOutputs.Add(strFnameLog); - } - -} - -// Return the number of files in the batch list -unsigned CJPEGsnoopCore::GetBatchFileCount() -{ - return m_asBatchFiles.GetCount(); -} - -// Return the filename at the batch index specified -CString CJPEGsnoopCore::GetBatchFileInfo(unsigned nFileInd) -{ - if (nFileInd < GetBatchFileCount()) { - return m_asBatchFiles.GetAt(nFileInd); - } else { - return _T("???"); - } -} - -// Perform AnalyzeFile() but handle any search modes first -// -// RETURN: -// - TRUE if file opened OK, FALSE if issue during open -// -BOOL CJPEGsnoopCore::DoAnalyzeOffset(CString strFname) -{ - // Handle the different file offset / search modes - BOOL bStatus = false; - bool bSearchResult = false; - unsigned long nStartPos = 0; - unsigned long nSearchPos = 0; - if (m_pAppConfig->eCmdLineOffset == DEC_OFFSET_START) { - // Decode at start of file - m_pAppConfig->nPosStart = 0; - bStatus = AnalyzeFile(strFname); - } else if (m_pAppConfig->eCmdLineOffset == DEC_OFFSET_SRCH1) { - // Decode at 1st SOI found in file - m_pAppConfig->nPosStart = 0; - bStatus = AnalyzeFile(strFname); - if (bStatus) { - if (!m_pJfifDec->GetDecodeStatus()) { - // SOI not found at start, so begin search - bStatus = AnalyzeOpen(); - nStartPos = m_pAppConfig->nPosStart; - bSearchResult = B_BufSearch(nStartPos,0xFFD8FF,3,true,nSearchPos); - AnalyzeClose(); - if (bSearchResult) { - // If found, update offset & re-analyze - m_pAppConfig->nPosStart = nSearchPos; - bStatus = AnalyzeFile(strFname); - } - } - } - } else if (m_pAppConfig->eCmdLineOffset == DEC_OFFSET_SRCH2) { - // Decode at 1st SOI found after start of file - // Force a search - m_pAppConfig->nPosStart = 0; - bStatus = AnalyzeFile(strFname); - if (bStatus) { - bStatus = AnalyzeOpen(); - nStartPos = m_pAppConfig->nPosStart; - bSearchResult = B_BufSearch(nStartPos,0xFFD8FF,3,true,nSearchPos); - AnalyzeClose(); - if (bSearchResult) { - // If found, update offset & re-analyze - m_pAppConfig->nPosStart = nSearchPos; - bStatus = AnalyzeFile(strFname); - } - } - } else if (m_pAppConfig->eCmdLineOffset == DEC_OFFSET_POS) { - // Decode from byte ### in file - m_pAppConfig->nPosStart = m_pAppConfig->nCmdLineOffsetPos; - bStatus = AnalyzeFile(strFname); - } else { - ASSERT(FALSE); - } - - // bStatus reports the success in opening the file - - return bStatus; -} - -// Process a file in the batch file list -// -// INPUT: -// - nFileInd = Index into batch file list -// - bWriteLog = Write out log file after processing file? -// - bExtractAll = Perform extract-all on this file? -// -void CJPEGsnoopCore::DoBatchFileProcess(unsigned nFileInd,bool bWriteLog,bool bExtractAll) -{ - BOOL bStatus = false; - unsigned nBatchFileCount; - CString strFnameFile; - CString strFnameDst; - CString strFnameLog; - CString strFnameEmbed; - nBatchFileCount = GetBatchFileCount(); - if (nFileInd>=nBatchFileCount) { - ASSERT(false); - return; - } - - //TODO: strFnameDst is not really used as it is base destination filename - strFnameFile = m_asBatchFiles.GetAt(nFileInd); - strFnameDst = m_asBatchDest.GetAt(nFileInd); - strFnameLog = m_asBatchOutputs.GetAt(nFileInd); - - // Indicate that the file source has changed so that any image decoding is enabled - J_ImgSrcChanged(); - - // Save the current filename into the temporary config space - // This is only done to assist debugging reporting - m_pAppConfig->strCurFname = strFnameFile; - - // Handle the different file offset / search modes - bStatus = DoAnalyzeOffset(strFnameFile); - - if (!bStatus) { - // If we had an issue opening the file, abort here - // TODO: Consider whether we should alert the user (perhaps in direct window log write) - return; - } - - if (bWriteLog || bExtractAll) { - // Now we need to ensure that the destination directory has been created - // Build up the subdirectories as required - BuildDirPath(strFnameDst); - } - - // Save the output log - if (bWriteLog) { - DoLogSave(strFnameLog); - } - - if (bExtractAll) { - // - // TODO: In the "Extract all" mode we should ask the - // user for the full configuration ahead of the batch - // process. - - // Create the filepath for any batch embedded JPEG extraction - strFnameEmbed = strFnameDst; - strFnameEmbed.Append(_T(".export.jpg")); - - CString strInputFname = strFnameFile; - CString strExportFname = strFnameEmbed; - bool bOverlayEn = false; - bool bForceSoi = false; - bool bForceEoi = false; - bool bIgnoreEoi = false; - bool bExtractAllEn = true; - bool bDhtAviInsert = false; - CString strOutPath = _T(""); // unused - - DoExtractEmbeddedJPEG(strInputFname,strExportFname,bOverlayEn,bForceSoi,bForceEoi,bIgnoreEoi,bExtractAllEn,bDhtAviInsert,strOutPath); - } - - - // Now submit entry to database! -#if 0 // Not supported currently -#ifdef BATCH_DO_DBSUBMIT - bDoSubmit = m_pJfifDec->CompareSignature(true); - if (bDoSubmit) { - // FIXME: Check function param values. Might be outdated - m_pJfifDec->PrepareSendSubmit(m_pJfifDec->m_strImgQualExif,m_pJfifDec->m_eDbReqSuggest,_T(""),_T("BATCH")); - } -#endif -#endif -} - - -// -------------------------------------------------------------------- -// --- END OF BATCH PROCESSING -// -------------------------------------------------------------------- - -// Ensure that the file system path exists, -// create the nested subdirectories as required -void CJPEGsnoopCore::BuildDirPath(CString strPath) -{ - // Now we need to ensure that the destination directory has been created - // Build up the subdirectories as required - // - // Use PathRemoveFileSpec() to find the directory path instead of - // simply looking for the last '\'. This should be safer. - unsigned nLen = strPath.GetLength(); - LPTSTR lpstrDstPathOnly = new TCHAR[nLen+1]; - _tcscpy_s(lpstrDstPathOnly,nLen+1,strPath); - PathRemoveFileSpec(lpstrDstPathOnly); - - SHCreateDirectoryEx(NULL,lpstrDstPathOnly,NULL); - - if (lpstrDstPathOnly) { - delete [] lpstrDstPathOnly; - lpstrDstPathOnly = NULL; - } -} - - -#if 0 //xxx -// Placeholder code for command-line call to extract JPEGs -void CJPEGsnoopCore::DoExtractEmbeddedJPEGCmdLine() -{ - // Determine if file is AVI - // If so, default to DHT AVI insert mode - // NOTE: Calling GetAviMode() requires that the CDocument JFIF decoder - // instance has processed the file. - bool bIsAvi,bIsMjpeg; - m_pJfifDec->GetAviMode(bIsAvi,bIsMjpeg); - dlgExport.m_bDhtAviInsert = bIsMjpeg; - - bExtractAllEn = true; - bForceSoi = false; - bForceEoi = false; - bIgnoreEoi = false; - bOverlayEn = false; - bDhtAviInsert = bInsDhtAvi; - - DoExtractEmbeddedJPEG1(..); -} -#endif - - -// Extracts an embedded JPEG from the current file -// Also support extraction of all embedded JPEG from the file -// -// NOTE: In "Extract All" mode, all file types are processed. -// -// TODO: -// - strOutPath unused -void CJPEGsnoopCore::DoExtractEmbeddedJPEG(CString strInputFname,CString strOutputFname, - bool bOverlayEn,bool bForceSoi,bool bForceEoi,bool bIgnoreEoi,bool bExtractAllEn,bool bDhtAviInsert, - CString strOutPath) -{ - unsigned int nFileSize = 0; - BOOL bRet; - - if (!bExtractAllEn) { - - // ======================================================== - // Extract Single mode - // ======================================================== - - // For export, we need to analyze first to get some info - // including suitability for export - // AnalyzeOpen() calls require m_strPathName to be set - m_strPathName = strInputFname; - bRet = AnalyzeOpen(); - - if (bRet) { - AnalyzeFileDo(); - } - - // FIXME: Is this being used anywhere? - // strTmp.Format(_T("0x%08X"),m_pJfifDec->GetPosEmbedStart()); - - // If we are not in "extract all" mode, then check now to see if - // the current file position looks OK to extract a valid JPEG. - - // Is the currently-decoded file in a suitable - // state for JPEG extraction (ie. have we seen all - // the necessary markers?) - bRet = m_pJfifDec->ExportJpegPrepare(strInputFname,bForceSoi,bForceEoi,bIgnoreEoi); - if (!bRet) { - return; - } - - // -------------------------------------------------------- - // Perform extraction of single embedded JPEG - // -------------------------------------------------------- - - if (m_lFileSize > 0xFFFFFFFFUL) { - CString strTmp = _T("Extract file too large. Skipping."); - glb_pDocLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - - } else { - // Extract the JPEG file - nFileSize = static_cast(m_lFileSize); - bRet = m_pJfifDec->ExportJpegDo(strInputFname,strOutputFname,nFileSize, - bOverlayEn,bDhtAviInsert,bForceSoi,bForceEoi); - } - - AnalyzeClose(); - - - } else { - - // ======================================================== - // Extract All mode - // ======================================================== - - ASSERT(strOutputFname != _T("")); - - // In extract-all, start at file offset 0 - m_pAppConfig->nPosStart = 0; - - // For added safety, reset the JFIF decoder state - // Note that this is already covered by the AnalyzeFileDo() call to JFIF Process() later - m_pJfifDec->Reset(); - - - // -------------------------------------------------------- - // Perform batch extraction of all embedded JPEGs - // -------------------------------------------------------- - - // Ensure we have no file state left over - // FIXME: Do I really need this here? - AnalyzeClose(); - - bool bDoneBatch = false; - unsigned nExportCnt = 1; - - unsigned nStartPos = 0; - bool bSearchResult = false; - unsigned long nSearchPos = 0; - bool bSkipFrame = false; - - - // Determine the root filename - // Filename selected by user: strEmbedFileName - CString strRootFileName; - int nExtInd; - - - // FIXME: Do I really want to use strOutputFname? That is typically the log file - nExtInd = strOutputFname.ReverseFind('.'); - ASSERT(nExtInd != -1); - if (nExtInd == -1) { - CString strTmp; - strTmp.Format(_T("ERROR: Invalid filename [%s]"),(LPCTSTR)strOutputFname); - glb_pDocLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return; - } - strRootFileName = strOutputFname.Left(nExtInd); - CString strOutputFnameTemp = _T(""); - - // Loop through file until done - while (!bDoneBatch) { - - bSkipFrame = false; - - // Create filename - // 6 digits of numbering will support videos at 60 fps for over 4.5hrs. - strOutputFnameTemp.Format(_T("%s.%06u.jpg"),(LPCTSTR)strRootFileName,nExportCnt); - - // Opens file (m_strPathName), resets window buffer, file size, etc. - AnalyzeOpen(); - - // AnalyzeFileDo() also resets all JFIF decoder state for us - // Perform the JFIF parsing & decoding - // Decoding starts at file offset m_pAppConfig->nPosStart - AnalyzeFileDo(); - - // Is the currently-decoded file in a suitable state for JPEG extraction? - // (ie. have we seen all the necessary markers?) - bRet = m_pJfifDec->ExportJpegPrepare(strInputFname,bForceSoi,bForceEoi,bIgnoreEoi); - if (!bRet) { - // Skip this particular frame - bSkipFrame = true; - } - - if (!bSkipFrame) { - - if (m_lFileSize > 0xFFFFFFFFULL) { - CString strTmp; - strTmp.Format(_T("ERROR: Extract file too large. Skipping. [Size=0x%I64X]"), m_lFileSize); - glb_pDocLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - } else { - // Extract the JPEG file - nFileSize = static_cast(m_lFileSize); - bRet = m_pJfifDec->ExportJpegDo(strInputFname,strOutputFnameTemp,nFileSize, - bOverlayEn,bDhtAviInsert,bForceSoi,bForceEoi); - } - - // Still increment frame # even if we skipped export (due to file size) - nExportCnt++; - } - - - // See if we can find the next embedded JPEG (file must still be open for this) - ASSERT(m_bFileOpened); - nStartPos = m_pAppConfig->nPosStart; - m_pJfifDec->ImgSrcChanged(); - - bSearchResult = m_pWBuf->BufSearch(nStartPos,0xFFD8FF,3,true,nSearchPos); - if (bSearchResult) { - - // Set starting file offset - m_pAppConfig->nPosStart = nSearchPos; - - // AnalyzeFileDo() also resets all JFIF decoder state for us - AnalyzeFileDo(); - - } else { - // No SOI Marker found in Forward search -> Stop batch - bDoneBatch = true; - } - - // For export, we need to call AnalyzeClose() - AnalyzeClose(); - - } // bDoneBatch - - // Close the file in case we aborted above - AnalyzeClose(); - - } // bExtractAllEn - - -} - -// ============================================== - -// ---------------------------------------------- -// Accessors for CjfifDecode -// ---------------------------------------------- - -void CJPEGsnoopCore::J_GetAviMode(bool &bIsAvi,bool &bIsMjpeg) -{ - m_pJfifDec->GetAviMode(bIsAvi,bIsMjpeg); -} - -void CJPEGsnoopCore::J_SetAviMode(bool bIsAvi,bool bIsMjpeg) -{ - m_pJfifDec->SetAviMode(bIsAvi,bIsMjpeg); -} - -void CJPEGsnoopCore::J_ImgSrcChanged() -{ - m_pJfifDec->ImgSrcChanged(); -} - -unsigned long CJPEGsnoopCore::J_GetPosEmbedStart() -{ - return m_pJfifDec->GetPosEmbedStart(); -} - -unsigned long CJPEGsnoopCore::J_GetPosEmbedEnd() -{ - return m_pJfifDec->GetPosEmbedEnd(); -} - -void CJPEGsnoopCore::J_GetDecodeSummary(CString &strHash,CString &strHashRot,CString &strImgExifMake,CString &strImgExifModel, - CString &strImgQualExif,CString &strSoftware,teDbAdd &eDbReqSuggest) -{ - m_pJfifDec->GetDecodeSummary(strHash,strHashRot,strImgExifMake,strImgExifModel,strImgQualExif,strSoftware,eDbReqSuggest); -} - -unsigned CJPEGsnoopCore::J_GetDqtZigZagIndex(unsigned nInd,bool bZigZag) -{ - return m_pJfifDec->GetDqtZigZagIndex(nInd,bZigZag); -} - -unsigned CJPEGsnoopCore::J_GetDqtQuantStd(unsigned nInd) -{ - return m_pJfifDec->GetDqtQuantStd(nInd); -} - -void CJPEGsnoopCore::J_SetStatusBar(CStatusBar* pStatBar) -{ - m_pJfifDec->SetStatusBar(pStatBar); -} - -void CJPEGsnoopCore::J_ProcessFile(CFile* inFile) -{ - m_pJfifDec->ProcessFile(inFile); -} - -void CJPEGsnoopCore::J_PrepareSendSubmit(CString strQual,teSource eUserSource,CString strUserSoftware,CString strUserNotes) -{ - m_pJfifDec->PrepareSendSubmit(strQual,eUserSource,strUserSoftware,strUserNotes); -} - - -// ---------------------------------------------- -// Accessors for CwindowBuf -// ---------------------------------------------- - -void CJPEGsnoopCore::B_SetStatusBar(CStatusBar* pStatBar) -{ - m_pWBuf->SetStatusBar(pStatBar); -} - -void CJPEGsnoopCore::B_BufLoadWindow(unsigned long nPosition) -{ - m_pWBuf->BufLoadWindow(nPosition); -} - -void CJPEGsnoopCore::B_BufFileSet(CFile* inFile) -{ - m_pWBuf->BufFileSet(inFile); -} - -void CJPEGsnoopCore::B_BufFileUnset() -{ - m_pWBuf->BufFileUnset(); -} - -BYTE CJPEGsnoopCore::B_Buf(unsigned long nOffset,bool bClean) -{ - return m_pWBuf->Buf(nOffset,bClean); -} - -bool CJPEGsnoopCore::B_BufSearch(unsigned long nStartPos, unsigned nSearchVal, unsigned nSearchLen, - bool bDirFwd, unsigned long &nFoundPos) -{ - return m_pWBuf->BufSearch(nStartPos,nSearchVal,nSearchLen,bDirFwd,nFoundPos); -} - -bool CJPEGsnoopCore::B_OverlayInstall(unsigned nOvrInd, BYTE* pOverlay,unsigned nLen,unsigned nBegin, - unsigned nMcuX,unsigned nMcuY,unsigned nMcuLen,unsigned nMcuLenIns, - int nAdjY,int nAdjCb,int nAdjCr) -{ - return m_pWBuf->OverlayInstall(nOvrInd,pOverlay,nLen,nBegin,nMcuX,nMcuY,nMcuLen,nMcuLenIns,nAdjY,nAdjCb,nAdjCr); -} - -void CJPEGsnoopCore::B_OverlayRemoveAll() -{ - m_pWBuf->OverlayRemoveAll(); -} - -bool CJPEGsnoopCore::B_OverlayGet(unsigned nOvrInd, BYTE* &pOverlay,unsigned &nLen,unsigned &nBegin) -{ - return m_pWBuf->OverlayGet(nOvrInd,pOverlay,nLen,nBegin); -} - -// ---------------------------------------------- -// Accessors for CImgDec -// ---------------------------------------------- -void CJPEGsnoopCore::I_SetStatusBar(CStatusBar* pStatBar) -{ - m_pImgDec->SetStatusBar(pStatBar); -} - -unsigned CJPEGsnoopCore::I_GetDqtEntry(unsigned nTblDestId, unsigned nCoeffInd) -{ - return m_pImgDec->GetDqtEntry(nTblDestId,nCoeffInd); -} - -void CJPEGsnoopCore::I_SetPreviewMode(unsigned nMode) -{ - m_pImgDec->SetPreviewMode(nMode); -} - -unsigned CJPEGsnoopCore::I_GetPreviewMode() -{ - return m_pImgDec->GetPreviewMode(); -} - -void CJPEGsnoopCore::I_SetPreviewYccOffset(unsigned nMcuX,unsigned nMcuY,int nY,int nCb,int nCr) -{ - m_pImgDec->SetPreviewYccOffset(nMcuX,nMcuY,nY,nCb,nCr); -} - -void CJPEGsnoopCore::I_GetPreviewYccOffset(unsigned &nMcuX,unsigned &nMcuY,int &nY,int &nCb,int &nCr) -{ - m_pImgDec->GetPreviewYccOffset(nMcuX,nMcuY,nY,nCb,nCr); -} - -void CJPEGsnoopCore::I_SetPreviewMcuInsert(unsigned nMcuX,unsigned nMcuY,int nLen) -{ - m_pImgDec->SetPreviewMcuInsert(nMcuX,nMcuY,nLen); -} - -void CJPEGsnoopCore::I_GetPreviewMcuInsert(unsigned &nMcuX,unsigned &nMcuY,unsigned &nLen) -{ - m_pImgDec -> GetPreviewMcuInsert(nMcuX,nMcuY,nLen); -} - -void CJPEGsnoopCore::I_SetPreviewZoom(bool bInc,bool bDec,bool bSet,unsigned nVal) -{ - m_pImgDec->SetPreviewZoom(bInc,bDec,bSet,nVal); -} - -unsigned CJPEGsnoopCore::I_GetPreviewZoomMode() -{ - return m_pImgDec->GetPreviewZoomMode(); -} - -float CJPEGsnoopCore::I_GetPreviewZoom() -{ - return m_pImgDec->GetPreviewZoom(); -} - -bool CJPEGsnoopCore::I_GetPreviewOverlayMcuGrid() -{ - return m_pImgDec->GetPreviewOverlayMcuGrid(); -} - -void CJPEGsnoopCore::I_SetPreviewOverlayMcuGridToggle() -{ - m_pImgDec->SetPreviewOverlayMcuGridToggle(); -} - -CPoint CJPEGsnoopCore::I_PixelToMcu(CPoint ptPix) -{ - return m_pImgDec->PixelToMcu(ptPix); -} - -CPoint CJPEGsnoopCore::I_PixelToBlk(CPoint ptPix) -{ - return m_pImgDec->PixelToBlk(ptPix); -} - -unsigned CJPEGsnoopCore::I_McuXyToLinear(CPoint ptMcu) -{ - return m_pImgDec->McuXyToLinear(ptMcu); -} - -void CJPEGsnoopCore::I_GetImageSize(unsigned &nX,unsigned &nY) -{ - m_pImgDec->GetImageSize(nX,nY); -} - -void CJPEGsnoopCore::I_GetPixMapPtrs(short* &pMapY,short* &pMapCb,short* &pMapCr) -{ - m_pImgDec->GetPixMapPtrs(pMapY,pMapCb,pMapCr); -} - -void CJPEGsnoopCore::I_GetDetailVlc(bool &bDetail,unsigned &nX,unsigned &nY,unsigned &nLen) -{ - m_pImgDec->GetDetailVlc(bDetail,nX,nY,nLen); -} - -void CJPEGsnoopCore::I_SetDetailVlc(bool bDetail,unsigned nX,unsigned nY,unsigned nLen) -{ - m_pImgDec->SetDetailVlc(bDetail,nX,nY,nLen); -} - -unsigned CJPEGsnoopCore::I_GetMarkerCount() -{ - return m_pImgDec->GetMarkerCount(); -} - -void CJPEGsnoopCore::I_SetMarkerBlk(unsigned nBlkX,unsigned nBlkY) -{ - m_pImgDec->SetMarkerBlk(nBlkX,nBlkY); -} - -CPoint CJPEGsnoopCore::I_GetMarkerBlk(unsigned nInd) -{ - return m_pImgDec->GetMarkerBlk(nInd); -} - -void CJPEGsnoopCore::I_SetStatusText(CString strText) -{ - m_pImgDec->SetStatusText(strText); -} - -CString CJPEGsnoopCore::I_GetStatusYccText() -{ - return m_pImgDec->GetStatusYccText(); -} - -void CJPEGsnoopCore::I_SetStatusYccText(CString strText) -{ - m_pImgDec->SetStatusYccText(strText); -} - -CString CJPEGsnoopCore::I_GetStatusMcuText() -{ - return m_pImgDec->GetStatusMcuText(); -} - -void CJPEGsnoopCore::I_SetStatusMcuText(CString strText) -{ - m_pImgDec->SetStatusMcuText(strText); -} - -CString CJPEGsnoopCore::I_GetStatusFilePosText() -{ - return m_pImgDec->GetStatusFilePosText(); -} - -void CJPEGsnoopCore::I_SetStatusFilePosText(CString strText) -{ - m_pImgDec->SetStatusFilePosText(strText); -} - -void CJPEGsnoopCore::I_GetBitmapPtr(unsigned char* &pBitmap) -{ - m_pImgDec->GetBitmapPtr(pBitmap); -} - -void CJPEGsnoopCore::I_LookupFilePosMcu(unsigned nMcuX,unsigned nMcuY, unsigned &nByte, unsigned &nBit) -{ - m_pImgDec->LookupFilePosMcu(nMcuX,nMcuY,nByte,nBit); -} - -void CJPEGsnoopCore::I_LookupFilePosPix(unsigned nPixX,unsigned nPixY, unsigned &nByte, unsigned &nBit) -{ - m_pImgDec->LookupFilePosPix(nPixX,nPixY,nByte,nBit); -} - -void CJPEGsnoopCore::I_LookupBlkYCC(unsigned nBlkX,unsigned nBlkY,int &nY,int &nCb,int &nCr) -{ - m_pImgDec->LookupBlkYCC(nBlkX,nBlkY,nY,nCb,nCr); -} - -void CJPEGsnoopCore::I_ViewOnDraw(CDC* pDC,CRect rectClient,CPoint ptScrolledPos,CFont* pFont, CSize &szNewScrollSize) -{ - m_pImgDec->ViewOnDraw(pDC,rectClient,ptScrolledPos,pFont,szNewScrollSize); -} - -void CJPEGsnoopCore::I_GetPreviewPos(unsigned &nX,unsigned &nY) -{ - m_pImgDec->GetPreviewPos(nX,nY); -} - -void CJPEGsnoopCore::I_GetPreviewSize(unsigned &nX,unsigned &nY) -{ - m_pImgDec->GetPreviewSize(nX,nY); -} - -bool CJPEGsnoopCore::I_IsPreviewReady() -{ - return m_pImgDec->IsPreviewReady(); -} \ No newline at end of file +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include + +//#include "stdafx.h" +#include "JPEGsnoopCore.h" + +// For glb_pDocLog +#include "JPEGsnoop.h" + +CJPEGsnoopCore::CJPEGsnoopCore(void) +{ + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Begin"); + // Initialize processing classes + + // Save a local copy of the config struct pointer +//@@ m_pAppConfig = theApp.m_pAppConfig; + + // Ensure the local log isn't linked to a CDocument +// glb_pDocLog->SetDoc(NULL); + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 1"); + + // Allocate the file window buffer + m_pWBuf = new CwindowBuf(); + + if(!m_pWBuf) + { + msgBox.setText("ERROR: Not enough memory for File Buffer"); + exit(1); + } + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 2"); + + // Allocate the JPEG decoder +// m_pImgDec = new CimgDecode(glb_pDocLog, m_pWBuf); + + if(!m_pWBuf) + { + msgBox.setText("ERROR: Not enough memory for Image Decoder"); + exit(1); + } + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 3"); + + m_pJfifDec = new CjfifDecode(glb_pDocLog, m_pWBuf, m_pImgDec); + + if(!m_pWBuf) + { + msgBox.setText("ERROR: Not enough memory for JFIF Decoder"); + exit(1); + } + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 4"); + + // Reset all members + Reset(); + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 5"); + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() End"); +} + +CJPEGsnoopCore::~CJPEGsnoopCore(void) +{ + if(m_pJfifDec != NULL) + { + delete m_pJfifDec; + m_pJfifDec = NULL; + } + + if(m_pWBuf != NULL) + { + delete m_pWBuf; + m_pWBuf = NULL; + } + + if(m_pImgDec != NULL) + { + delete m_pImgDec; + m_pImgDec = NULL; + } +} + +// Reset all state +void CJPEGsnoopCore::Reset() +{ + // Reset all members + m_pFile = NULL; + m_lFileSize = 0L; + m_strPathName = ""; + + // No log data available until we open & process a file + m_bFileOpened = false; + m_bFileAnalyzed = false; + + // FIXME: Should we be calling Reset on the JfifDecoder, ImgDecoder and WBuf? + + // Indicate to JFIF ProcessFile() that document has changed + // and that the scan decode needs to be redone if it + // is to be displayed. + m_pJfifDec->ImgSrcChanged(); + + // Clean up the quick log + glb_pDocLog->Clear(); +} + +void CJPEGsnoopCore::SetStatusBar(QStatusBar * pStatBar) +{ + // Save a copy of the status bar + //xxx m_pStatBar = pStatBar; + + // Now update the JFIF decoder and Image Decoder with the + // revised status bar pointer (or NULL) + m_pJfifDec->SetStatusBar(pStatBar); + m_pImgDec->SetStatusBar(pStatBar); +} + +// +// Has a file been analyzed previously? +// - This indicator is used extensively in the CJPEGsnoopDoc +// to determine whether menu items are enabled or not +// +bool CJPEGsnoopCore::IsAnalyzed() +{ + return m_bFileAnalyzed; +} + +// Open the file named in m_strPathName +// - Close / cleanup if another file was already open +// +// INPUT: +// - strFname = File to open +// +// POST: +// - m_pFile +// - m_lFileSize +// - m_pWBuf loaded +// +// RETURN: +// - Indicates if file open was successful +// +bool CJPEGsnoopCore::AnalyzeOpen() +{ + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeOpen() Begin"); + + Q_ASSERT(m_strPathName != ""); + + if(m_strPathName == "") + { + // Force dialog box to show as this is a major error + // TODO: Handle non-GUI mode + msgBox.setText("ERROR: AnalyzeOpen() but m_strPathName empty"); + return false; + } + + // Clean up if a file is already open + if(m_pFile != NULL) + { + // Mark previous buffer as closed + m_pWBuf->BufFileUnset(); + m_pFile->close(); + delete m_pFile; + + m_pFile = NULL; + m_lFileSize = 0L; + } + + // Open specified file + // Added in shareDenyNone as this apparently helps resolve some people's troubles + // with an error showing: Couldn't open file "Sharing Violation" + + m_pFile = new QFile(m_strPathName); + + if(m_pFile->open(QIODevice::ReadOnly) == false) + { + QString strError; + + // Note: msg includes m_strPathName + strError = QString("ERROR: Couldn't open file: [%1]").arg(m_strPathName); + glb_pDocLog->AddLineErr(strError); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strError); + msgBox.exec(); + } + + m_pFile = NULL; + + return false; + } + + // Set the file size variable + m_lFileSize = m_pFile->size(); + + // Don't attempt to load buffer with zero length file! + if(m_lFileSize == 0) + { + return true; + } + + // Open up the buffer + m_pWBuf->BufFileSet(m_pFile); + m_pWBuf->BufLoadWindow(0); + + // Mark file as opened + m_bFileOpened = true; + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeOpen() End"); + + return true; +} + +// Close the current file +// - Invalidate the buffer +// +// POST: +// - m_bFileOpened +// +void CJPEGsnoopCore::AnalyzeClose() +{ + // Indicate no file is currently opened + // Note that we don't clear m_bFileAnalyzed as the last + // decoder state is still available + m_bFileOpened = false; + + // Close the buffer window + m_pWBuf->BufFileUnset(); + + // Now that we've finished parsing the file, close it! + if(m_pFile != NULL) + { + m_pFile->close(); + delete m_pFile; + + m_pFile = NULL; + } +} + +// Perform the file analysis +// - Output the log header text +// - Process the current file via ProcessFile() +// - Dump the output to the log (if in QuickLog mode) +// +// PRE: +// - m_strPathname +// +// PRE: +// - m_bFileOpened +// - m_pFile +// - m_pJfifDec +// - m_pImgDec +// - m_lFileSize +// - m_pAppConfig->nPosStart = Starting file offset for decode +// +// POST: +// - m_bFileAnalyzed +// +void CJPEGsnoopCore::AnalyzeFileDo() +{ + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeFileDo() Checkpoint 1"); + + // Ensure file was already opened + Q_ASSERT(m_pFile); + Q_ASSERT(m_bFileOpened); + + // Reset the analyzed state in case this file is invalid (eg. zero length) + m_bFileAnalyzed = false; + + // Start in Quick mode (probably don't care for command-line mode) +// glb_pDocLog->SetQuickMode(true); + + // Clear the document log + glb_pDocLog->Clear(); + + QString strTmp; + + glb_pDocLog->AddLine(""); + strTmp = QString("JPEGsnoop %1 by Calvin Hass").arg(QString(VERSION_STR)); + glb_pDocLog->AddLine(strTmp); + glb_pDocLog->AddLine(" http://www.impulseadventure.com/photo/"); + glb_pDocLog->AddLine(" -------------------------------------"); + glb_pDocLog->AddLine(""); + strTmp = QString(" Filename: [%1]").arg(m_strPathName); + glb_pDocLog->AddLine(strTmp); + strTmp = QString(" Filesize: [%1] bytes").arg(m_lFileSize); + glb_pDocLog->AddLine(strTmp); + glb_pDocLog->AddLine(""); + + // Perform the actual decoding + if(m_lFileSize > 0xFFFFFFFFULL) + { + strTmp = QString("ERROR: File too large for this version of JPEGsnoop. [Size=0x%1]").arg(m_lFileSize); + glb_pDocLog->AddLineErr(strTmp); + } + else if(m_lFileSize == 0) + { + glb_pDocLog->AddLineErr("ERROR: File length is zero, no decoding done."); + } + else + { + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeFileDo() Checkpoint 2"); + + m_pJfifDec->ProcessFile(m_pFile); + // Now indicate that the file has been processed + m_bFileAnalyzed = true; + } +} + +// Analyze the current file +// - Open file +// - Analyze file +// - Close file +// +// INPUT: +// - strFname = File to analyze +// +// PRE: +// - m_pAppConfig->nPosStart = Starting file offset for decode +// +// RETURN: +// - Status from opening file +// +bool CJPEGsnoopCore::AnalyzeFile(QString strFname) +{ + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeFile() Begin"); + + bool bRetVal; + + // Save the input filename + // This filename is used later to confirm that output filename doesn't + // match input filename when we save the log + m_strPathName = strFname; + + // Assumes that we have set up the member vars already + // Perform the actual processing. We have this in a routine + // so that we can quickly recalculate the log file again + // if an option changes. + + bRetVal = AnalyzeOpen(); + + if(bRetVal) + { + // Only now that we have successfully opened the document + // should be mark the flag as such. This flag is used by + // other menu items to know whether or not the file is ready. + AnalyzeFileDo(); + } + + AnalyzeClose(); + + // In the last part of AnalyzeClose(), we mark the file + // as not modified, so that we don't get prompted to save. + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopDoc::AnalyzeFile() End"); + + return bRetVal; +} + +// Save the current log to text file with a simple implementation +// +// - This routine is implemented with a simple output mechanism rather +// than leveraging CRichEditCtrl::DoSave() so that we can perform +// this operation in command-line mode or batch mode operations. +// +// TODO: Should this be moved into CDocLog? +// +void CJPEGsnoopCore::DoLogSave(QString strLogName) +{ + QFile *pLog; + + // Open the file for output + Q_ASSERT(strLogName != ""); + + // OLD COMMENTS FOLLOW + // This save method will only work if we were in Quick Log mode + // where we have recorded the log to a string buffer and not + // directly to the RichEdit + // Note that m_bLogQuickMode is only toggled on during processing + // so we can't check the status here (except seeing that there are no + // lines in the array) + + // TODO: Ensure file doesn't exist and only overwrite if specified in command-line? + + // TODO: Confirm that we are not writing to the same file we opened (m_strPathName) +/* Q_ASSERT(strLogName != m_strPathName); + + pLog = new QFile(strLogName); + // Open specified file + + if(pLog->open(QIODevice::WriteOnly | QIODevice::Text) == false) + { + QString strError; + + strError = QString("ERROR: Couldn't open file for write [%s]: [%s]").arg(strLogName); + // FIXME: Find an alternate method of signaling error in command-line mode + msgBox.setText(strError); + pLog = NULL; + + return; + } + + // Step through the current log buffer + QString strLine; + + QColor sCol; + + unsigned nQuickLines = glb_pDocLog->GetNumLinesLocal(); + + for(unsigned nLine = 0; nLine < nQuickLines; nLine++) + { + glb_pDocLog->GetLineLogLocal(nLine, strLine, sCol); + + // NOTE: At this time, batch file processing uses an 8-bit text file output format + // rather than the Unicode-supporting CRichEdit that is used when we manually + // save the log file. + // + // If we pass extended characters to WriteString() when the CStdioFile has been + // opened as CFile::typeText, the extended characters will terminate the lines + // early. + // + // Therefore, we will convert all extended characters back to ASCII here. + // + // TODO: Revise this logic so that we can have more foreign-character support + // in the batch output files. +// CW2A strAscii(strLine); +// QString strConv(strAscii); + pLog->write(strLine.toLatin1().data()); + } */ + + // Close the file + if(pLog) + { + pLog->close(); + delete pLog; + } +} + +// -------------------------------------------------------------------- +// --- START OF BATCH PROCESSING +// -------------------------------------------------------------------- + +// +// Generate a list of files for a batch processing operation +// +// POST: +// - m_asBatchFiles = Contains list of full file paths +// +void CJPEGsnoopCore::GenBatchFileList(QString strDirSrc, QString strDirDst, bool bRecSubdir, bool bExtractAll) +{ + // TODO: + // - What is the best way to provide a "Cancel Dialog" for a + // recursive operation? I can easily create the cancel / progress + // dialog with operations that have can be single-stepped, but + // not ones that require accumulation on the stack. + // - For now, just leave as-is. + + // Example code that I can use for single-stepping the operation: + // + // // === START + // COperationDlg LengthyOp(this); + // LengthyOp.SetFunctions( PrepareOperation, NextIteration, GetProgress ); + // + // // Until-done based + // bool bOk = LengthyOp.RunUntilDone( true ); + // // === END + + m_asBatchFiles.clear(); + m_asBatchOutputs.clear(); + + // Start the batch operation + GenBatchFileListRecurse(strDirSrc, strDirDst, "", bRecSubdir, bExtractAll); +} + +// Recursive routine that searches for files and folders +// Used in batch file processing mode +// +// INPUT: +// - strSrcRootName Starting path for input files +// - strDstRootName Starting path for output files +// - strPathName Path (below strSrcRootName) and filename for current input file +// - bSubdirs Flag to descend into all sub-directories +// - bExtractAll Flag to extract all JPEG from file +// +void CJPEGsnoopCore::GenBatchFileListRecurse(QString strSrcRootName, QString strDstRootName, QString strPathName, bool bSubdirs, + bool bExtractAll) +{ + // The following code snippet is based on MSDN code: + // http://msdn.microsoft.com/en-us/library/scx99850%28VS.80%29.aspx + +// CFileFind finder; + + QString strWildcard; + QString strDirName; + QString strSubPath; + QString strPath; + + // build a string with wildcards + if(strPathName.isEmpty()) + { + strWildcard = QString("%1\\*.*").arg(strSrcRootName); + } + else + { + strWildcard = QString("%1\\%2\\*.*").arg(strSrcRootName).arg(strPathName); + } + + // start working for files +// bool bWorking = finder.FindFile(strWildcard); +/* + while(bWorking) + { + bWorking = finder.FindNextFile(); + + // skip . and .. files; otherwise, we'd + // recur infinitely! + + if(finder.IsDots()) + continue; + + strPath = finder.GetFilePath(); + + // Now need to remove "root" from "path" to recalculate + // new relative subpath + strDirName = finder.GetFileName(); + + if(strPathName.isEmpty()) + { + strSubPath = strDirName; + } + else + { + strSubPath = QString("%s\\%s").arg(strPathName).arg(strDirName); + } + + // if it's a directory, recursively search it + if(finder.IsDirectory()) + { + if(bSubdirs) + { + GenBatchFileListRecurse(strSrcRootName, strDstRootName, strSubPath, bSubdirs, bExtractAll); + } + } + else + { + // GetFilePath() includes both the path & filename + // when called on a file entry, so there is no need + // to specifically call GetFileName() + // QString strFname = finder.GetFileName(); + + // Now perform final filtering check on file + // and add to batch file list + GenBatchFileListSingle(strSrcRootName, strDstRootName, strSubPath, bExtractAll); + } + } + + finder.Close(); */ +} + +// Perform processing on file selected by the batch recursion +// process GenBatchFileListRecurse(). +// +// INPUT: +// - strSrcRootName Starting path for input files +// - strDstRootName Starting path for output files +// - strPathName Path (below szSrcRootName) and filename for current input file +// - bExtractAll Flag to extract all JPEG from file +// +void CJPEGsnoopCore::GenBatchFileListSingle(QString strSrcRootName, QString strDstRootName, QString strPathName, bool bExtractAll) +{ + //bool bDoSubmit = false; + uint32_t nInd; + + QString strFnameSrc; + QString strFnameDst; + QString strFnameOnly; + QString strFnameExt; + QString strFnameLog; + QString strFnameEmbed; + + strFnameSrc = QString("%1\\%2").arg(strSrcRootName).arg(strPathName); + strFnameDst = QString("%1\\%2").arg(strDstRootName).arg(strPathName); + + // Extract the filename (without extension) and extension from + // the full pathname. + // + // FIXME: Rewrite to use Windows APIs to do this or else + // use the boost library as they will be more robust than + // the simple searches for '\' and '.' that are done here. + // +#if 1 + // ----------- + strFnameOnly = strFnameSrc.mid(strFnameSrc.lastIndexOf('\\') + 1); + nInd = strFnameOnly.lastIndexOf('.'); + strFnameOnly = strFnameOnly.mid(0, nInd); + + // Extract the file extension + nInd = strFnameSrc.lastIndexOf('.'); + strFnameExt = strFnameSrc.mid(nInd); + strFnameExt = strFnameExt.toLower(); + // ----------- +#else + uint32_t nLen = strFnameSrc.GetLength(); + + LPTSTR lpstrSrcFullpath = new TCHAR[nLen + 1]; + + _tcscpy_s(lpstrSrcFullpath, nLen + 1, strFnameSrc); + + LPTSTR lpstrSrcFnameAndExt = NULL; + + lpstrSrcFnameAndExt = PathFindFileName(lpstrSrcFullpath); + ... +#endif + // Only process files that have an extension that implies JPEG + // Batch processing is generally limited to files that appear to + // represent a JPEG image (ie. ".jpg" an ".jpeg"). + // + // TODO: Enable user to present list of extensions or disable + // the check altogether. + // TODO: Add Batch processing support for .PSD? + bool bProcessFile = false; + + // TODO: Support m_pAppConfig->strBatchExtensions + if((strFnameExt == ".jpg") || (strFnameExt == ".jpeg")) + { + bProcessFile = true; + } + + if(bExtractAll) + { + // In the "Extract all" mode during batch processing, we disable + // the extension check altogether as "Extract all" mode generally + // implies that the files may not be standalone JPEG image files. + // They could also be corrupt files that contain JPEG images. + // + // TODO: Provide additional configuration options ahead of time. + bProcessFile = true; + } + + if(bProcessFile) + { + // Generate the output log file name + // + // IMPORTANT NOTE: + // It is *essential* that this Append function work properly + // as it is used to generate the log filename from the + // image filename. Since we may be automatically overwriting + // the logfile, it is imperative that we ensure that there is + // no chance that the log filename happens to be the original + // JPEG filename. + // + // In the interests of paranoia, we perform some extra checks + // here to ensure that this doesn't happen. + + strFnameLog = strFnameDst; + strFnameLog.append(".txt"); + + // Now double check the filenames to ensure they don't match the image + + // - Is the last 4 characters of the strFname ".txt"? + if(strFnameLog.right(4) != ".txt") + { + // Report error message and skip logfile save + // TODO: Handle non-GUI mode + msgBox.setText("ERROR: Internal error #10100"); + return; + } + + // - Is the strFnameLog different from the input filename (strFname)? + if(strFnameLog == strPathName) + { + // Report error message and skip logfile save + // TODO: Handle non-GUI mode + msgBox.setText("ERROR: Internal error #10101"); + return; + } + + // Add filename pair to the list + // - Input filename to analyze + // - Output filename for associated log/report + m_asBatchFiles.append(strFnameSrc); + m_asBatchDest.append(strFnameDst); + m_asBatchOutputs.append(strFnameLog); + } +} + +// Return the number of files in the batch list +uint32_t CJPEGsnoopCore::GetBatchFileCount() +{ + return m_asBatchFiles.count(); +} + +// Return the filename at the batch index specified +QString CJPEGsnoopCore::GetBatchFileInfo(uint32_t nFileInd) +{ + if(nFileInd < GetBatchFileCount()) + { + return m_asBatchFiles[nFileInd]; + } + else + { + return "???"; + } +} + +// Perform AnalyzeFile() but handle any search modes first +// +// RETURN: +// - true if file opened OK, false if issue during open +// +bool CJPEGsnoopCore::DoAnalyzeOffset(QString strFname) +{ + // Handle the different file offset / search modes + bool bStatus = false; + bool bSearchResult = false; + + uint32_t nStartPos = 0; + uint32_t nSearchPos = 0; + + if(m_pAppConfig->eCmdLineOffset == DEC_OFFSET_START) + { + // Decode at start of file + m_pAppConfig->nPosStart = 0; + bStatus = AnalyzeFile(strFname); + } + else if(m_pAppConfig->eCmdLineOffset == DEC_OFFSET_SRCH1) + { + // Decode at 1st SOI found in file + m_pAppConfig->nPosStart = 0; + bStatus = AnalyzeFile(strFname); + + if(bStatus) + { + if(!m_pJfifDec->GetDecodeStatus()) + { + // SOI not found at start, so begin search + bStatus = AnalyzeOpen(); + nStartPos = m_pAppConfig->nPosStart; + bSearchResult = B_BufSearch(nStartPos, 0xFFD8FF, 3, true, nSearchPos); + AnalyzeClose(); + + if(bSearchResult) + { + // If found, update offset & re-analyze + m_pAppConfig->nPosStart = nSearchPos; + bStatus = AnalyzeFile(strFname); + } + } + } + } + else if(m_pAppConfig->eCmdLineOffset == DEC_OFFSET_SRCH2) + { + // Decode at 1st SOI found after start of file + // Force a search + m_pAppConfig->nPosStart = 0; + bStatus = AnalyzeFile(strFname); + + if(bStatus) + { + bStatus = AnalyzeOpen(); + nStartPos = m_pAppConfig->nPosStart; + bSearchResult = B_BufSearch(nStartPos, 0xFFD8FF, 3, true, nSearchPos); + AnalyzeClose(); + + if(bSearchResult) + { + // If found, update offset & re-analyze + m_pAppConfig->nPosStart = nSearchPos; + bStatus = AnalyzeFile(strFname); + } + } + } + else if(m_pAppConfig->eCmdLineOffset == DEC_OFFSET_POS) + { + // Decode from quint8 ### in file + m_pAppConfig->nPosStart = m_pAppConfig->nCmdLineOffsetPos; + bStatus = AnalyzeFile(strFname); + } + else + { + Q_ASSERT(false); + } + + // bStatus reports the success in opening the file + + return bStatus; +} + +// Process a file in the batch file list +// +// INPUT: +// - nFileInd = Index into batch file list +// - bWriteLog = Write out log file after processing file? +// - bExtractAll = Perform extract-all on this file? +// +void CJPEGsnoopCore::DoBatchFileProcess(uint32_t nFileInd, bool bWriteLog, bool bExtractAll) +{ + bool bStatus = false; + + uint32_t nBatchFileCount; + + QString strFnameFile; + QString strFnameDst; + QString strFnameLog; + QString strFnameEmbed; + + nBatchFileCount = GetBatchFileCount(); + + if(nFileInd >= nBatchFileCount) + { + Q_ASSERT(false); + return; + } + + //TODO: strFnameDst is not really used as it is base destination filename + strFnameFile = m_asBatchFiles[nFileInd]; + strFnameDst = m_asBatchDest[nFileInd]; + strFnameLog = m_asBatchOutputs[nFileInd]; + + // Indicate that the file source has changed so that any image decoding is enabled + J_ImgSrcChanged(); + + // Save the current filename into the temporary config space + // This is only done to assist debugging reporting + m_pAppConfig->strCurFname = strFnameFile; + + // Handle the different file offset / search modes + bStatus = DoAnalyzeOffset(strFnameFile); + + if(!bStatus) + { + // If we had an issue opening the file, abort here + // TODO: Consider whether we should alert the user (perhaps in direct window log write) + return; + } + + if(bWriteLog || bExtractAll) + { + // Now we need to ensure that the destination directory has been created + // Build up the subdirectories as required + BuildDirPath(strFnameDst); + } + + // Save the output log + if(bWriteLog) + { + DoLogSave(strFnameLog); + } + + if(bExtractAll) + { + // + // TODO: In the "Extract all" mode we should ask the + // user for the full configuration ahead of the batch + // process. + + // Create the filepath for any batch embedded JPEG extraction + strFnameEmbed = strFnameDst; + strFnameEmbed.append(".export.jpg"); + + QString strInputFname = strFnameFile; + QString strExportFname = strFnameEmbed; + + bool bOverlayEn = false; + bool bForceSoi = false; + bool bForceEoi = false; + bool bIgnoreEoi = false; + bool bExtractAllEn = true; + bool bDhtAviInsert = false; + + QString strOutPath = ""; // unused + + DoExtractEmbeddedJPEG(strInputFname, strExportFname, bOverlayEn, bForceSoi, bForceEoi, bIgnoreEoi, bExtractAllEn, + bDhtAviInsert, strOutPath); + } + + // Now submit entry to database! +#if 0 // Not supported currently +#ifdef BATCH_DO_DBSUBMIT + bDoSubmit = m_pJfifDec->CompareSignature(true); + if(bDoSubmit) + { + // FIXME: Check function param values. Might be outdated + m_pJfifDec->PrepareSendSubmit(m_pJfifDec->m_strImgQualExif, m_pJfifDec->m_eDbReqSuggest, ""), "BATCH"; + } +#endif +#endif +} + +// -------------------------------------------------------------------- +// --- END OF BATCH PROCESSING +// -------------------------------------------------------------------- + +// Ensure that the file system path exists, +// create the nested subdirectories as required +void CJPEGsnoopCore::BuildDirPath(QString strPath) +{ + // Now we need to ensure that the destination directory has been created + // Build up the subdirectories as required + // + // Use PathRemoveFileSpec() to find the directory path instead of + // simply looking for the last '\'. This should be safer. +// unsigned nLen = strPath.length(); + +// char *lpstrDstPathOnly = new char[nLen + 1]; + +// strcpy(lpstrDstPathOnly, strPath.toLatin1().data()); +// PathRemoveFileSpec(lpstrDstPathOnly); + +// SHCreateDirectoryEx(NULL, lpstrDstPathOnly, NULL); + QDir dir; + strPath = dir.filePath(strPath); + dir.mkdir(strPath); +// if(lpstrDstPathOnly) +// { +// delete[]lpstrDstPathOnly; +// lpstrDstPathOnly = NULL; +// } +} + +#if 0 //xxx +// Placeholder code for command-line call to extract JPEGs +void CJPEGsnoopCore::DoExtractEmbeddedJPEGCmdLine() +{ + // Determine if file is AVI + // If so, default to DHT AVI insert mode + // NOTE: Calling GetAviMode() requires that the CDocument JFIF decoder + // instance has processed the file. + bool bIsAvi, bIsMjpeg; + + m_pJfifDec->GetAviMode(bIsAvi, bIsMjpeg); + dlgExport.m_bDhtAviInsert = bIsMjpeg; + + bExtractAllEn = true; + bForceSoi = false; + bForceEoi = false; + bIgnoreEoi = false; + bOverlayEn = false; + bDhtAviInsert = bInsDhtAvi; + + DoExtractEmbeddedJPEG1(..); +} +#endif + +// Extracts an embedded JPEG from the current file +// Also support extraction of all embedded JPEG from the file +// +// NOTE: In "Extract All" mode, all file types are processed. +// +// TODO: +// - strOutPath unused +void CJPEGsnoopCore::DoExtractEmbeddedJPEG(QString strInputFname, QString strOutputFname, + bool bOverlayEn, bool bForceSoi, bool bForceEoi, bool bIgnoreEoi, bool bExtractAllEn, + bool bDhtAviInsert, QString strOutPath) +{ + unsigned int nFileSize = 0; + + bool bRet; + + if(!bExtractAllEn) + { + // ======================================================== + // Extract Single mode + // ======================================================== + + // For export, we need to analyze first to get some info + // including suitability for export + // AnalyzeOpen() calls require m_strPathName to be set + m_strPathName = strInputFname; + bRet = AnalyzeOpen(); + + if(bRet) + { + AnalyzeFileDo(); + } + + // FIXME: Is this being used anywhere? + // strTmp = QString("0x%08X",m_pJfifDec->GetPosEmbedStart()); + + // If we are not in "extract all" mode, then check now to see if + // the current file position looks OK to extract a valid JPEG. + + // Is the currently-decoded file in a suitable + // state for JPEG extraction (ie. have we seen all + // the necessary markers?) + bRet = m_pJfifDec->ExportJpegPrepare(strInputFname, bForceSoi, bForceEoi, bIgnoreEoi); + + if(!bRet) + { + return; + } + + // -------------------------------------------------------- + // Perform extraction of single embedded JPEG + // -------------------------------------------------------- + + if(m_lFileSize > 0xFFFFFFFFUL) + { + QString strTmp = "Extract file too large. Skipping."; + + glb_pDocLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + msgBox.setText(strTmp); + } + else + { + // Extract the JPEG file + nFileSize = static_cast < uint32_t >(m_lFileSize); + + bRet = m_pJfifDec->ExportJpegDo(strInputFname, strOutputFname, nFileSize, bOverlayEn, bDhtAviInsert, bForceSoi, bForceEoi); + } + + AnalyzeClose(); + + } + else + { + // ======================================================== + // Extract All mode + // ======================================================== + + Q_ASSERT(strOutputFname != ""); + + // In extract-all, start at file offset 0 + m_pAppConfig->nPosStart = 0; + + // For added safety, reset the JFIF decoder state + // Note that this is already covered by the AnalyzeFileDo() call to JFIF Process() later + m_pJfifDec->Reset(); + + // -------------------------------------------------------- + // Perform batch extraction of all embedded JPEGs + // -------------------------------------------------------- + + // Ensure we have no file state left over + // FIXME: Do I really need this here? + AnalyzeClose(); + + bool bDoneBatch = false; + + uint32_t nExportCnt = 1; + + uint32_t nStartPos = 0; + + bool bSearchResult = false; + + uint32_t nSearchPos = 0; + + bool bSkipFrame = false; + + // Determine the root filename + // Filename selected by user: strEmbedFileName + QString strRootFileName; + + int nExtInd; + + // FIXME: Do I really want to use strOutputFname? That is typically the log file + nExtInd = strOutputFname.lastIndexOf('.'); + Q_ASSERT(nExtInd != -1); + + if(nExtInd == -1) + { + QString strTmp; + + strTmp = QString("ERROR: Invalid filename [%1]").arg(strOutputFname); + glb_pDocLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + msgBox.setText(strTmp); + return; + } + + strRootFileName = strOutputFname.left(nExtInd); + QString strOutputFnameTemp = ""; + + // Loop through file until done + while(!bDoneBatch) + { + + bSkipFrame = false; + + // Create filename + // 6 digits of numbering will support videos at 60 fps for over 4.5hrs. + strOutputFnameTemp = QString("%1.%06u.jpg").arg(strRootFileName).arg(nExportCnt); + + // Opens file (m_strPathName), resets window buffer, file size, etc. + AnalyzeOpen(); + + // AnalyzeFileDo() also resets all JFIF decoder state for us + // Perform the JFIF parsing & decoding + // Decoding starts at file offset m_pAppConfig->nPosStart + AnalyzeFileDo(); + + // Is the currently-decoded file in a suitable state for JPEG extraction? + // (ie. have we seen all the necessary markers?) + bRet = m_pJfifDec->ExportJpegPrepare(strInputFname, bForceSoi, bForceEoi, bIgnoreEoi); + + if(!bRet) + { + // Skip this particular frame + bSkipFrame = true; + } + + if(!bSkipFrame) + { + if(m_lFileSize > 0xFFFFFFFFULL) + { + QString strTmp; + + strTmp = QString("ERROR: Extract file too large. Skipping. [Size=0x%1]").arg(m_lFileSize); + glb_pDocLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + msgBox.setText(strTmp); + } + else + { + // Extract the JPEG file + nFileSize = static_cast < uint32_t >(m_lFileSize); + + bRet = m_pJfifDec->ExportJpegDo(strInputFname, strOutputFnameTemp, nFileSize, + bOverlayEn, bDhtAviInsert, bForceSoi, bForceEoi); + } + + // Still increment frame # even if we skipped export (due to file size) + nExportCnt++; + } + + // See if we can find the next embedded JPEG (file must still be open for this) + Q_ASSERT(m_bFileOpened); + nStartPos = m_pAppConfig->nPosStart; + m_pJfifDec->ImgSrcChanged(); + + bSearchResult = m_pWBuf->BufSearch(nStartPos, 0xFFD8FF, 3, true, nSearchPos); + + if(bSearchResult) + { + // Set starting file offset + m_pAppConfig->nPosStart = nSearchPos; + + // AnalyzeFileDo() also resets all JFIF decoder state for us + AnalyzeFileDo(); + + } + else + { + // No SOI Marker found in Forward search -> Stop batch + bDoneBatch = true; + } + + // For export, we need to call AnalyzeClose() + AnalyzeClose(); + } // bDoneBatch + + // Close the file in case we aborted above + AnalyzeClose(); + } // bExtractAllEn +} + +// ============================================== + +// ---------------------------------------------- +// Accessors for CjfifDecode +// ---------------------------------------------- + +void CJPEGsnoopCore::J_GetAviMode(bool & bIsAvi, bool & bIsMjpeg) +{ + m_pJfifDec->GetAviMode(bIsAvi, bIsMjpeg); +} + +void CJPEGsnoopCore::J_SetAviMode(bool bIsAvi, bool bIsMjpeg) +{ + m_pJfifDec->SetAviMode(bIsAvi, bIsMjpeg); +} + +void CJPEGsnoopCore::J_ImgSrcChanged() +{ + m_pJfifDec->ImgSrcChanged(); +} + +uint32_t CJPEGsnoopCore::J_GetPosEmbedStart() +{ + return m_pJfifDec->GetPosEmbedStart(); +} + +uint32_t CJPEGsnoopCore::J_GetPosEmbedEnd() +{ + return m_pJfifDec->GetPosEmbedEnd(); +} + +void CJPEGsnoopCore::J_GetDecodeSummary(QString & strHash, QString & strHashRot, QString & strImgExifMake, + QString & strImgExifModel, QString & strImgQualExif, QString & strSoftware, + teDbAdd & eDbReqSuggest) +{ + m_pJfifDec->GetDecodeSummary(strHash, strHashRot, strImgExifMake, strImgExifModel, strImgQualExif, strSoftware, eDbReqSuggest); +} + +uint32_t CJPEGsnoopCore::J_GetDqtZigZagIndex(uint32_t nInd, bool bZigZag) +{ + return m_pJfifDec->GetDqtZigZagIndex(nInd, bZigZag); +} + +uint32_t CJPEGsnoopCore::J_GetDqtQuantStd(uint32_t nInd) +{ + return m_pJfifDec->GetDqtQuantStd(nInd); +} + +void CJPEGsnoopCore::J_SetStatusBar(QStatusBar * pStatBar) +{ + m_pJfifDec->SetStatusBar(pStatBar); +} + +void CJPEGsnoopCore::J_ProcessFile(QFile * inFile) +{ + m_pJfifDec->ProcessFile(inFile); +} + +void CJPEGsnoopCore::J_PrepareSendSubmit(QString strQual, teSource eUserSource, QString strUserSoftware, QString strUserNotes) +{ + m_pJfifDec->PrepareSendSubmit(strQual, eUserSource, strUserSoftware, strUserNotes); +} + +// ---------------------------------------------- +// Accessors for CwindowBuf +// ---------------------------------------------- + +void CJPEGsnoopCore::B_SetStatusBar(QStatusBar * pStatBar) +{ + m_pWBuf->SetStatusBar(pStatBar); +} + +void CJPEGsnoopCore::B_BufLoadWindow(uint32_t nPosition) +{ + m_pWBuf->BufLoadWindow(nPosition); +} + +void CJPEGsnoopCore::B_BufFileSet(QFile * inFile) +{ + m_pWBuf->BufFileSet(inFile); +} + +void CJPEGsnoopCore::B_BufFileUnset() +{ + m_pWBuf->BufFileUnset(); +} + +quint8 CJPEGsnoopCore::B_Buf(uint32_t nOffset, bool bClean) +{ + return m_pWBuf->Buf(nOffset, bClean); +} + +bool CJPEGsnoopCore::B_BufSearch(uint32_t nStartPos, uint32_t nSearchVal, uint32_t nSearchLen, + bool bDirFwd, uint32_t &nFoundPos) +{ + return m_pWBuf->BufSearch(nStartPos, nSearchVal, nSearchLen, bDirFwd, nFoundPos); +} + +bool CJPEGsnoopCore::B_OverlayInstall(uint32_t nOvrInd, quint8 * pOverlay, uint32_t nLen, uint32_t nBegin, + uint32_t nMcuX, uint32_t nMcuY, uint32_t nMcuLen, uint32_t nMcuLenIns, + int nAdjY, int nAdjCb, int nAdjCr) +{ + return m_pWBuf->OverlayInstall(nOvrInd, pOverlay, nLen, nBegin, nMcuX, nMcuY, nMcuLen, nMcuLenIns, nAdjY, nAdjCb, nAdjCr); +} + +void CJPEGsnoopCore::B_OverlayRemoveAll() +{ + m_pWBuf->OverlayRemoveAll(); +} + +bool CJPEGsnoopCore::B_OverlayGet(uint32_t nOvrInd, quint8 * &pOverlay, uint32_t &nLen, uint32_t &nBegin) +{ + return m_pWBuf->OverlayGet(nOvrInd, pOverlay, nLen, nBegin); +} + +// ---------------------------------------------- +// Accessors for CImgDec +// ---------------------------------------------- +void CJPEGsnoopCore::I_SetStatusBar(QStatusBar * pStatBar) +{ + m_pImgDec->SetStatusBar(pStatBar); +} + +uint32_t CJPEGsnoopCore::I_GetDqtEntry(uint32_t nTblDestId, uint32_t nCoeffInd) +{ + return m_pImgDec->GetDqtEntry(nTblDestId, nCoeffInd); +} + +void CJPEGsnoopCore::I_SetPreviewMode(uint32_t nMode) +{ + m_pImgDec->SetPreviewMode(nMode); +} + +uint32_t CJPEGsnoopCore::I_GetPreviewMode() +{ + return m_pImgDec->GetPreviewMode(); +} + +void CJPEGsnoopCore::I_SetPreviewYccOffset(uint32_t nMcuX, uint32_t nMcuY, int nY, int nCb, int nCr) +{ + m_pImgDec->SetPreviewYccOffset(nMcuX, nMcuY, nY, nCb, nCr); +} + +void CJPEGsnoopCore::I_GetPreviewYccOffset(uint32_t &nMcuX, uint32_t &nMcuY, int &nY, int &nCb, int &nCr) +{ + m_pImgDec->GetPreviewYccOffset(nMcuX, nMcuY, nY, nCb, nCr); +} + +void CJPEGsnoopCore::I_SetPreviewMcuInsert(uint32_t nMcuX, uint32_t nMcuY, int nLen) +{ + m_pImgDec->SetPreviewMcuInsert(nMcuX, nMcuY, nLen); +} + +void CJPEGsnoopCore::I_GetPreviewMcuInsert(uint32_t &nMcuX, uint32_t &nMcuY, uint32_t &nLen) +{ + m_pImgDec->GetPreviewMcuInsert(nMcuX, nMcuY, nLen); +} + +void CJPEGsnoopCore::I_SetPreviewZoom(bool bInc, bool bDec, bool bSet, uint32_t nVal) +{ + m_pImgDec->SetPreviewZoom(bInc, bDec, bSet, nVal); +} + +uint32_t CJPEGsnoopCore::I_GetPreviewZoomMode() +{ + return m_pImgDec->GetPreviewZoomMode(); +} + +float CJPEGsnoopCore::I_GetPreviewZoom() +{ + return m_pImgDec->GetPreviewZoom(); +} + +bool CJPEGsnoopCore::I_GetPreviewOverlayMcuGrid() +{ + return m_pImgDec->GetPreviewOverlayMcuGrid(); +} + +void CJPEGsnoopCore::I_SetPreviewOverlayMcuGridToggle() +{ + m_pImgDec->SetPreviewOverlayMcuGridToggle(); +} + +QPoint CJPEGsnoopCore::I_PixelToMcu(QPoint ptPix) +{ + return m_pImgDec->PixelToMcu(ptPix); +} + +QPoint CJPEGsnoopCore::I_PixelToBlk(QPoint ptPix) +{ + return m_pImgDec->PixelToBlk(ptPix); +} + +uint32_t CJPEGsnoopCore::I_McuXyToLinear(QPoint ptMcu) +{ + return m_pImgDec->McuXyToLinear(ptMcu); +} + +void CJPEGsnoopCore::I_GetImageSize(uint32_t &nX, uint32_t &nY) +{ + m_pImgDec->GetImageSize(nX, nY); +} + +void CJPEGsnoopCore::I_GetPixMapPtrs(short *&pMapY, short *&pMapCb, short *&pMapCr) +{ + m_pImgDec->GetPixMapPtrs(pMapY, pMapCb, pMapCr); +} + +void CJPEGsnoopCore::I_GetDetailVlc(bool & bDetail, uint32_t &nX, uint32_t &nY, uint32_t &nLen) +{ + m_pImgDec->GetDetailVlc(bDetail, nX, nY, nLen); +} + +void CJPEGsnoopCore::I_SetDetailVlc(bool bDetail, uint32_t nX, uint32_t nY, uint32_t nLen) +{ + m_pImgDec->SetDetailVlc(bDetail, nX, nY, nLen); +} + +uint32_t CJPEGsnoopCore::I_GetMarkerCount() +{ + return m_pImgDec->GetMarkerCount(); +} + +void CJPEGsnoopCore::I_SetMarkerBlk(uint32_t nBlkX, uint32_t nBlkY) +{ + m_pImgDec->SetMarkerBlk(nBlkX, nBlkY); +} + +QPoint CJPEGsnoopCore::I_GetMarkerBlk(uint32_t nInd) +{ + return m_pImgDec->GetMarkerBlk(nInd); +} + +void CJPEGsnoopCore::I_SetStatusText(QString strText) +{ + m_pImgDec->SetStatusText(strText); +} + +QString CJPEGsnoopCore::I_GetStatusYccText() +{ + return m_pImgDec->GetStatusYccText(); +} + +void CJPEGsnoopCore::I_SetStatusYccText(QString strText) +{ + m_pImgDec->SetStatusYccText(strText); +} + +QString CJPEGsnoopCore::I_GetStatusMcuText() +{ + return m_pImgDec->GetStatusMcuText(); +} + +void CJPEGsnoopCore::I_SetStatusMcuText(QString strText) +{ + m_pImgDec->SetStatusMcuText(strText); +} + +QString CJPEGsnoopCore::I_GetStatusFilePosText() +{ + return m_pImgDec->GetStatusFilePosText(); +} + +void CJPEGsnoopCore::I_SetStatusFilePosText(QString strText) +{ + m_pImgDec->SetStatusFilePosText(strText); +} + +void CJPEGsnoopCore::I_GetBitmapPtr(unsigned char *&pBitmap) +{ + m_pImgDec->GetBitmapPtr(pBitmap); +} + +void CJPEGsnoopCore::I_LookupFilePosMcu(uint32_t nMcuX, uint32_t nMcuY, uint32_t &nquint8, uint32_t &nBit) +{ + m_pImgDec->LookupFilePosMcu(nMcuX, nMcuY, nquint8, nBit); +} + +void CJPEGsnoopCore::I_LookupFilePosPix(uint32_t nPixX, uint32_t nPixY, uint32_t &nquint8, uint32_t &nBit) +{ + m_pImgDec->LookupFilePosPix(nPixX, nPixY, nquint8, nBit); +} + +void CJPEGsnoopCore::I_LookupBlkYCC(uint32_t nBlkX, uint32_t nBlkY, int &nY, int &nCb, int &nCr) +{ + m_pImgDec->LookupBlkYCC(nBlkX, nBlkY, nY, nCb, nCr); +} + +void CJPEGsnoopCore::I_ViewOnDraw(QPainter *pDC, QRect rectClient, QPoint ptScrolledPos, QFont *pFont, QSize & szNewScrollSize) +{ + m_pImgDec->ViewOnDraw(pDC, rectClient, ptScrolledPos, pFont, szNewScrollSize); +} + +void CJPEGsnoopCore::I_GetPreviewPos(uint32_t &nX, uint32_t &nY) +{ + m_pImgDec->GetPreviewPos(nX, nY); +} + +void CJPEGsnoopCore::I_GetPreviewSize(uint32_t &nX, uint32_t &nY) +{ + m_pImgDec->GetPreviewSize(nX, nY); +} + +bool CJPEGsnoopCore::I_IsPreviewReady() +{ + return m_pImgDec->IsPreviewReady(); +} diff --git a/source/JPEGsnoopCore.h b/source/JPEGsnoopCore.h index 5c4f534..a674d2b 100644 --- a/source/JPEGsnoopCore.h +++ b/source/JPEGsnoopCore.h @@ -1,166 +1,164 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - This module performs all of the main decoding and processing functions -// - It contains the major context (m_pWBuf, m_pImgDec, m_pJfifDec) -// -// ========================================================================== - -#pragma once - -#include "JfifDecode.h" -#include "ImgDecode.h" -#include "WindowBuf.h" -#include "SnoopConfig.h" - - -class CJPEGsnoopCore -{ -public: - CJPEGsnoopCore(void); - ~CJPEGsnoopCore(void); - - void Reset(); - - void SetStatusBar(CStatusBar* pStatBar); - - BOOL AnalyzeFile(CString strFname); - void AnalyzeFileDo(); - BOOL AnalyzeOpen(); - void AnalyzeClose(); - BOOL IsAnalyzed(); - BOOL DoAnalyzeOffset(CString strFname); - - void DoLogSave(CString strLogName); - - void GenBatchFileList(CString strDirSrc,CString strDirDst,bool bRecSubdir,bool bExtractAll); - unsigned GetBatchFileCount(); - void DoBatchFileProcess(unsigned nFileInd,bool bWriteLog,bool bExtractAll); - CString GetBatchFileInfo(unsigned nFileInd); - - void BuildDirPath(CString strPath); - - void DoExtractEmbeddedJPEG(CString strInputFname,CString strOutputFname, - bool bOverlayEn,bool bForceSoi,bool bForceEoi,bool bIgnoreEoi,bool bExtractAllEn,bool bDhtAviInsert, - CString strOutPath); - - - // Accessor wrappers for CjfifDecode - void J_GetAviMode(bool &bIsAvi,bool &bIsMjpeg); - void J_SetAviMode(bool bIsAvi,bool bIsMjpeg); - void J_ImgSrcChanged(); - unsigned long J_GetPosEmbedStart(); - unsigned long J_GetPosEmbedEnd(); - void J_GetDecodeSummary(CString &strHash,CString &strHashRot,CString &strImgExifMake,CString &strImgExifModel, - CString &strImgQualExif,CString &strSoftware,teDbAdd &eDbReqSuggest); - unsigned J_GetDqtZigZagIndex(unsigned nInd,bool bZigZag); - unsigned J_GetDqtQuantStd(unsigned nInd); - void J_SetStatusBar(CStatusBar* pStatBar); - void J_ProcessFile(CFile* inFile); - void J_PrepareSendSubmit(CString strQual,teSource eUserSource,CString strUserSoftware,CString strUserNotes); - - // Accessor wrappers for CImgDec - void I_SetStatusBar(CStatusBar* pStatBar); - unsigned I_GetDqtEntry(unsigned nTblDestId, unsigned nCoeffInd); - void I_SetPreviewMode(unsigned nMode); - unsigned I_GetPreviewMode(); - void I_SetPreviewYccOffset(unsigned nMcuX,unsigned nMcuY,int nY,int nCb,int nCr); - void I_GetPreviewYccOffset(unsigned &nMcuX,unsigned &nMcuY,int &nY,int &nCb,int &nCr); - void I_SetPreviewMcuInsert(unsigned nMcuX,unsigned nMcuY,int nLen); - void I_GetPreviewMcuInsert(unsigned &nMcuX,unsigned &nMcuY,unsigned &nLen); - void I_SetPreviewZoom(bool bInc,bool bDec,bool bSet,unsigned nVal); - unsigned I_GetPreviewZoomMode(); - float I_GetPreviewZoom(); - bool I_GetPreviewOverlayMcuGrid(); - void I_SetPreviewOverlayMcuGridToggle(); - CPoint I_PixelToMcu(CPoint ptPix); - CPoint I_PixelToBlk(CPoint ptPix); - unsigned I_McuXyToLinear(CPoint ptMcu); - void I_GetImageSize(unsigned &nX,unsigned &nY); - void I_GetPixMapPtrs(short* &pMapY,short* &pMapCb,short* &pMapCr); - void I_GetDetailVlc(bool &bDetail,unsigned &nX,unsigned &nY,unsigned &nLen); - void I_SetDetailVlc(bool bDetail,unsigned nX,unsigned nY,unsigned nLen); - unsigned I_GetMarkerCount(); - void I_SetMarkerBlk(unsigned nBlkX,unsigned nBlkY); - CPoint I_GetMarkerBlk(unsigned nInd); - void I_SetStatusText(CString strText); - CString I_GetStatusYccText(); - void I_SetStatusYccText(CString strText); - CString I_GetStatusMcuText(); - void I_SetStatusMcuText(CString strText); - CString I_GetStatusFilePosText(); - void I_SetStatusFilePosText(CString strText); - void I_GetBitmapPtr(unsigned char* &pBitmap); - void I_LookupFilePosMcu(unsigned nMcuX,unsigned nMcuY, unsigned &nByte, unsigned &nBit); - void I_LookupFilePosPix(unsigned nPixX,unsigned nPixY, unsigned &nByte, unsigned &nBit); - void I_LookupBlkYCC(unsigned nBlkX,unsigned nBlkY,int &nY,int &nCb,int &nCr); - void I_ViewOnDraw(CDC* pDC,CRect rectClient,CPoint ptScrolledPos,CFont* pFont, CSize &szNewScrollSize); - void I_GetPreviewPos(unsigned &nX,unsigned &nY); - void I_GetPreviewSize(unsigned &nX,unsigned &nY); - bool I_IsPreviewReady(); - - // Accessor wrappers for CwindowBuf - void B_SetStatusBar(CStatusBar* pStatBar); - void B_BufLoadWindow(unsigned long nPosition); - void B_BufFileSet(CFile* inFile); - void B_BufFileUnset(); - BYTE B_Buf(unsigned long nOffset,bool bClean=false); - bool B_BufSearch(unsigned long nStartPos, unsigned nSearchVal, unsigned nSearchLen, - bool bDirFwd, unsigned long &nFoundPos); - bool B_OverlayInstall(unsigned nOvrInd, BYTE* pOverlay,unsigned nLen,unsigned nBegin, - unsigned nMcuX,unsigned nMcuY,unsigned nMcuLen,unsigned nMcuLenIns, - int nAdjY,int nAdjCb,int nAdjCr); - void B_OverlayRemoveAll(); - bool B_OverlayGet(unsigned nOvrInd, BYTE* &pOverlay,unsigned &nLen,unsigned &nBegin); - -private: - - // Batch processing - void GenBatchFileListRecurse(CString strSrcRootName,CString strDstRootName,CString strPathName,bool bSubdirs,bool bExtractAll); - void GenBatchFileListSingle(CString strSrcRootName,CString strDstRootName,CString strPathName,bool bExtractAll); - - -private: - - // Config - CSnoopConfig* m_pAppConfig; // Pointer to application config - - // Input JPEG file - CFile* m_pFile; - ULONGLONG m_lFileSize; - - - CString m_strPathName; - BOOL m_bFileAnalyzed; // Have we opened and analyzed a file? - BOOL m_bFileOpened; // Is a file currently opened? - - // Decoders and Buffers - CjfifDecode* m_pJfifDec; - CimgDecode* m_pImgDec; - CwindowBuf* m_pWBuf; - - - // Batch processing - CStringArray m_asBatchFiles; - CStringArray m_asBatchDest; - CStringArray m_asBatchOutputs; - -}; - +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - This module performs all of the main decoding and processing functions +// - It contains the major context (m_pWBuf, m_pImgDec, m_pJfifDec) +// +// ========================================================================== + +#pragma once + +#include +#include + +#include "JfifDecode.h" +#include "ImgDecode.h" +#include "WindowBuf.h" +#include "SnoopConfig.h" + +class CJPEGsnoopCore +{ +public: + CJPEGsnoopCore(void); + ~CJPEGsnoopCore(void); + + void Reset(); + + void SetStatusBar(QStatusBar * pStatBar); + + bool AnalyzeFile(QString strFname); + void AnalyzeFileDo(); + bool AnalyzeOpen(); + void AnalyzeClose(); + bool IsAnalyzed(); + bool DoAnalyzeOffset(QString strFname); + + void DoLogSave(QString strLogName); + + void GenBatchFileList(QString strDirSrc, QString strDirDst, bool bRecSubdir, bool bExtractAll); + uint32_t GetBatchFileCount(); + void DoBatchFileProcess(uint32_t nFileInd, bool bWriteLog, bool bExtractAll); + QString GetBatchFileInfo(uint32_t nFileInd); + + void BuildDirPath(QString strPath); + + void DoExtractEmbeddedJPEG(QString strInputFname, QString strOutputFname, + bool bOverlayEn, bool bForceSoi, bool bForceEoi, bool bIgnoreEoi, bool bExtractAllEn, + bool bDhtAviInsert, QString strOutPath); + + // Accessor wrappers for CjfifDecode + void J_GetAviMode(bool & bIsAvi, bool & bIsMjpeg); + void J_SetAviMode(bool bIsAvi, bool bIsMjpeg); + void J_ImgSrcChanged(); + uint32_t J_GetPosEmbedStart(); + uint32_t J_GetPosEmbedEnd(); + void J_GetDecodeSummary(QString & strHash, QString & strHashRot, QString & strImgExifMake, QString & strImgExifModel, + QString & strImgQualExif, QString & strSoftware, teDbAdd & eDbReqSuggest); + uint32_t J_GetDqtZigZagIndex(uint32_t nInd, bool bZigZag); + uint32_t J_GetDqtQuantStd(uint32_t nInd); + void J_SetStatusBar(QStatusBar * pStatBar); + void J_ProcessFile(QFile * inFile); + void J_PrepareSendSubmit(QString strQual, teSource eUserSource, QString strUserSoftware, QString strUserNotes); + + // Accessor wrappers for CImgDec + void I_SetStatusBar(QStatusBar * pStatBar); + uint32_t I_GetDqtEntry(uint32_t nTblDestId, uint32_t nCoeffInd); + void I_SetPreviewMode(uint32_t nMode); + uint32_t I_GetPreviewMode(); + void I_SetPreviewYccOffset(uint32_t nMcuX, uint32_t nMcuY, int nY, int nCb, int nCr); + void I_GetPreviewYccOffset(uint32_t &nMcuX, uint32_t &nMcuY, int &nY, int &nCb, int &nCr); + void I_SetPreviewMcuInsert(uint32_t nMcuX, uint32_t nMcuY, int nLen); + void I_GetPreviewMcuInsert(uint32_t &nMcuX, uint32_t &nMcuY, uint32_t &nLen); + void I_SetPreviewZoom(bool bInc, bool bDec, bool bSet, uint32_t nVal); + uint32_t I_GetPreviewZoomMode(); + float I_GetPreviewZoom(); + bool I_GetPreviewOverlayMcuGrid(); + void I_SetPreviewOverlayMcuGridToggle(); + QPoint I_PixelToMcu(QPoint ptPix); + QPoint I_PixelToBlk(QPoint ptPix); + uint32_t I_McuXyToLinear(QPoint ptMcu); + void I_GetImageSize(uint32_t &nX, uint32_t &nY); + void I_GetPixMapPtrs(short *&pMapY, short *&pMapCb, short *&pMapCr); + void I_GetDetailVlc(bool & bDetail, uint32_t &nX, uint32_t &nY, uint32_t &nLen); + void I_SetDetailVlc(bool bDetail, uint32_t nX, uint32_t nY, uint32_t nLen); + uint32_t I_GetMarkerCount(); + void I_SetMarkerBlk(uint32_t nBlkX, uint32_t nBlkY); + QPoint I_GetMarkerBlk(uint32_t nInd); + void I_SetStatusText(QString strText); + QString I_GetStatusYccText(); + void I_SetStatusYccText(QString strText); + QString I_GetStatusMcuText(); + void I_SetStatusMcuText(QString strText); + QString I_GetStatusFilePosText(); + void I_SetStatusFilePosText(QString strText); + void I_GetBitmapPtr(unsigned char *&pBitmap); + void I_LookupFilePosMcu(uint32_t nMcuX, uint32_t nMcuY, uint32_t &nByte, uint32_t &nBit); + void I_LookupFilePosPix(uint32_t nPixX, uint32_t nPixY, uint32_t &nByte, uint32_t &nBit); + void I_LookupBlkYCC(uint32_t nBlkX, uint32_t nBlkY, int &nY, int &nCb, int &nCr); + void I_ViewOnDraw(QPainter* pDC,QRect rectClient,QPoint ptScrolledPos,QFont* pFont, QSize &szNewScrollSize); + void I_GetPreviewPos(uint32_t &nX, uint32_t &nY); + void I_GetPreviewSize(uint32_t &nX, uint32_t &nY); + bool I_IsPreviewReady(); + + // Accessor wrappers for CwindowBuf + void B_SetStatusBar(QStatusBar * pStatBar); + void B_BufLoadWindow(uint32_t nPosition); + void B_BufFileSet(QFile * inFile); + void B_BufFileUnset(); + quint8 B_Buf(uint32_t nOffset, bool bClean = false); + bool B_BufSearch(uint32_t nStartPos, uint32_t nSearchVal, uint32_t nSearchLen, bool bDirFwd, uint32_t &nFoundPos); + bool B_OverlayInstall(uint32_t nOvrInd, quint8 * pOverlay, uint32_t nLen, uint32_t nBegin, + uint32_t nMcuX, uint32_t nMcuY, uint32_t nMcuLen, uint32_t nMcuLenIns, int nAdjY, int nAdjCb, int nAdjCr); + void B_OverlayRemoveAll(); + bool B_OverlayGet(uint32_t nOvrInd, quint8 * &pOverlay, uint32_t &nLen, uint32_t &nBegin); + + CimgDecode *imgDecoder() { return m_pImgDec; } +private: + + // Batch processing + void GenBatchFileListRecurse(QString strSrcRootName, QString strDstRootName, QString strPathName, bool bSubdirs, + bool bExtractAll); + void GenBatchFileListSingle(QString strSrcRootName, QString strDstRootName, QString strPathName, bool bExtractAll); + +private: + QMessageBox msgBox; + + // Config + CSnoopConfig *m_pAppConfig; // Pointer to application config + + // Input JPEG file + QFile *m_pFile; + quint64 m_lFileSize; + + QString m_strPathName; + bool m_bFileAnalyzed; // Have we opened and analyzed a file? + bool m_bFileOpened; // Is a file currently opened? + + // Decoders and Buffers + CjfifDecode *m_pJfifDec; + CimgDecode *m_pImgDec; + CwindowBuf *m_pWBuf; + + // Batch processing + QStringList m_asBatchFiles; + QStringList m_asBatchDest; + QStringList m_asBatchOutputs; + +}; diff --git a/source/JfifDecode.cpp b/source/JfifDecode.cpp index 63afc79..308a5c8 100644 --- a/source/JfifDecode.cpp +++ b/source/JfifDecode.cpp @@ -1,8021 +1,10505 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - - -#include "stdafx.h" - -#include "JfifDecode.h" -#include "snoop.h" -#include "JPEGsnoop.h" // for m_pAppConfig get - -#include "WindowBuf.h" - -#include "Md5.h" - -#include "afxinet.h" - -#include "windows.h" -#include "UrlString.h" -#include "DbSigs.h" - -#include "General.h" - - - -// Maximum number of component values to extract into array for display -#define MAX_anValues 64 - - -// Clear out internal members -void CjfifDecode::Reset() -{ - // File handling - m_nPos = 0; - m_nPosSos = 0; - m_nPosEoi = 0; - m_nPosEmbedStart = 0; - m_nPosEmbedEnd = 0; - m_nPosFileEnd = 0; - - // SOS / SOF handling - m_nSofNumLines_Y = 0; - m_nSofSampsPerLine_X = 0; - m_nSofNumComps_Nf = 0; - - // Quantization tables - ClearDQT(); - - // Photoshop - m_nImgQualPhotoshopSfw = 0; - m_nImgQualPhotoshopSa = 0; - - m_nApp14ColTransform = -1; - - // Restart marker - m_nImgRstEn = false; - m_nImgRstInterval = 0; - - // Basic metadata - m_strImgExifMake = _T("???"); - m_nImgExifMakeSubtype = 0; - m_strImgExifModel = _T("???"); - m_bImgExifMakernotes = false; - m_strImgExtras = _T(""); - m_strComment = _T(""); - m_strSoftware = _T(""); - m_bImgProgressive = false; - m_bImgSofUnsupported = false; - _tcscpy_s(m_acApp0Identifier,_T("")); - - // Derived metadata - m_strHash = _T("NONE"); - m_strHashRot = _T("NONE"); - m_eImgLandscape = ENUM_LANDSCAPE_UNSET; - m_strImgQualExif = _T(""); - m_bAvi = false; - m_bAviMjpeg = false; - m_bPsd = false; - - // Misc - m_bImgOK = false; // Set during SOF to indicate further proc OK - m_bBufFakeDHT = false; // Start in normal Buf mode - m_eImgEdited = EDITED_UNSET; - m_eDbReqSuggest = DB_ADD_SUGGEST_UNSET; - m_bSigExactInDB = false; - - // Embedded thumbnail - m_nImgExifThumbComp = 0; - m_nImgExifThumbOffset = 0; - m_nImgExifThumbLen = 0; - m_strHashThumb = _T("NONE"); // Will go into DB to say NONE! - m_strHashThumbRot = _T("NONE"); // Will go into DB to say NONE! - m_nImgThumbNumLines = 0; - m_nImgThumbSampsPerLine = 0; - - // Now clear out any previously generated bitmaps - // or image decoding parameters - if (m_pImgDec) { - if (m_pImgSrcDirty) { - m_pImgDec->Reset(); - } - } - - // Reset the decoding state checks - // These are to help ensure we don't start decoding SOS - // if we haven't seen other valid markers yet! Otherwise - // we could run into very bad loops (e.g. .PSD files) - // just because we saw FFD8FF first then JFIF_SOS - m_bStateAbort = false; - m_bStateSoi = false; - m_bStateDht = false; - m_bStateDhtOk = false; - m_bStateDhtFake = false; - m_bStateDqt = false; - m_bStateDqtOk = false; - m_bStateSof = false; - m_bStateSofOk = false; - m_bStateSos = false; - m_bStateSosOk = false; - m_bStateEoi = false; - -} - - -// Initialize the JFIF decoder. Several class pointers are provided -// as parameters, so that we can directly access the output log, the -// file buffer and the image scan decoder. -// Loads up the signature database. -// -// INPUT: -// - pLog Ptr to log file class -// - pWBuf Ptr to Window Buf class -// - pImgDec Ptr to Image Decoder class -// -// PRE: -// - Requires that CDocLog, CwindowBuf and CimgDecode classes -// are already initialized -// -CjfifDecode::CjfifDecode(CDocLog* pLog,CwindowBuf* pWBuf,CimgDecode* pImgDec) -{ - // Ideally this would be passed by constructor, but simply access - // directly for now. - CJPEGsnoopApp* pApp; - pApp = (CJPEGsnoopApp*)AfxGetApp(); - m_pAppConfig = pApp->m_pAppConfig; - ASSERT(m_pAppConfig); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CjfifDecode::CjfifDecode() Begin")); - - ASSERT(pLog); - ASSERT(pWBuf); - ASSERT(pImgDec); - - // Need to zero out the private members - m_bOutputDB = FALSE; // mySQL output for web - - // Enable verbose reporting - m_bVerbose = FALSE; - - m_pImgSrcDirty = TRUE; - - // Generate lookup tables for Huffman codes - GenLookupHuffMask(); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CjfifDecode::CjfifDecode() Checkpoint 1")); - - // Window status bar is not ready yet, wait for call to SetStatusBar() - m_pStatBar = NULL; - - // Save copies of other class pointers - m_pLog = pLog; - m_pWBuf = pWBuf; - m_pImgDec = pImgDec; - - // Reset decoding state - Reset(); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CjfifDecode::CjfifDecode() Checkpoint 2")); - - // Load the local database (if it exists) - theApp.m_pDbSigs->DatabaseExtraLoad(); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CjfifDecode::CjfifDecode() Checkpoint 3")); - - // Allocate the Photoshop decoder - m_pPsDec = new CDecodePs(pWBuf,pLog); - if (!m_pPsDec) { - ASSERT(false); - return; - } - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CjfifDecode::CjfifDecode() Checkpoint 4")); - -#ifdef SUPPORT_DICOM - // Allocate the DICOM decoder - m_pDecDicom = new CDecodeDicom(pWBuf,pLog); - if (!m_pDecDicom) { - ASSERT(false); - return; - } - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CjfifDecode::CjfifDecode() Checkpoint 5")); -#endif - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CjfifDecode::CjfifDecode() End")); -} - -// Destructor -CjfifDecode::~CjfifDecode() -{ - // Free the Photoshop decoder - if (m_pPsDec) { - delete m_pPsDec; - m_pPsDec = NULL; - } - -#ifdef SUPPORT_DICOM - // Free the DICOM decoder - if (m_pDecDicom) { - delete m_pDecDicom; - m_pDecDicom = NULL; - } -#endif - -} - -// Asynchronously update a local pointer to the status bar once -// it becomes available. Note that the status bar is not ready by -// the time of the CjfifDecode class constructor call. -// -// INPUT: -// - pStatBar Ptr to status bar -// -// POST: -// - m_pStatBar -// -void CjfifDecode::SetStatusBar(CStatusBar* pStatBar) -{ - m_pStatBar = pStatBar; -} - - -// Indicate that the source of the image scan data -// has been dirtied. Either the source has changed -// or some of the View2 options have changed. -// -// POST: -// - m_pImgSrcDirty -// -void CjfifDecode::ImgSrcChanged() -{ - m_pImgSrcDirty = true; -} - - -// Set the AVI mode flag for this file -// -// POST: -// - m_bAvi -// - m_bAviMjpeg -// -void CjfifDecode::SetAviMode(bool bIsAvi,bool bIsMjpeg) -{ - m_bAvi = bIsAvi; - m_bAviMjpeg = bIsMjpeg; -} - -// Fetch the AVI mode flag for this file -// -// PRE: -// - m_bAvi -// - m_bAviMjpeg -// -// OUTPUT: -// - bIsAvi -// - bIsMjpeg -// -void CjfifDecode::GetAviMode(bool &bIsAvi,bool &bIsMjpeg) -{ - bIsAvi = m_bAvi; - bIsMjpeg = m_bAviMjpeg; -} - -// Fetch the starting file position of the embedded thumbnail -// -// PRE: -// - m_nPosEmbedStart -// -// RETURN: -// - File position -// -unsigned long CjfifDecode::GetPosEmbedStart() -{ - return m_nPosEmbedStart; -} - -// Fetch the ending file position of the embedded thumbnail -// -// PRE: -// - m_nPosEmbedEnd -// -// RETURN: -// - File position -// -unsigned long CjfifDecode::GetPosEmbedEnd() -{ - return m_nPosEmbedEnd; -} - -// Determine if the last analysis revealed a JFIF with known markers -// -// RETURN: -// - TRUE if file (at position during analysis) appeared to decode OK -// -bool CjfifDecode::GetDecodeStatus() -{ - return m_bImgOK; -} - -// Fetch a summary of the JFIF decoder results -// These details are used in preparation of signature submission to the DB -// -// PRE: -// - m_strHash -// - m_strHashRot -// - m_strImgExifMake -// - m_strImgExifModel -// - m_strImgQualExif -// - m_strSoftware -// - m_eDbReqSuggest -// -// OUTPUT: -// - strHash -// - strHashRot -// - strImgExifMake -// - strImgExifModel -// - strImgQualExif -// - strSoftware -// - nDbReqSuggest -// -void CjfifDecode::GetDecodeSummary(CString &strHash,CString &strHashRot,CString &strImgExifMake,CString &strImgExifModel, - CString &strImgQualExif,CString &strSoftware,teDbAdd &eDbReqSuggest) -{ - strHash = m_strHash; - strHashRot = m_strHashRot; - strImgExifMake = m_strImgExifMake; - strImgExifModel = m_strImgExifModel; - strImgQualExif = m_strImgQualExif; - strSoftware = m_strSoftware; - eDbReqSuggest = m_eDbReqSuggest; -} - -// Fetch an element from the "standard" luminance quantization table -// -// PRE: -// - glb_anStdQuantLum[] -// -// RETURN: -// - DQT matrix element -// -unsigned CjfifDecode::GetDqtQuantStd(unsigned nInd) -{ - if (nInd < MAX_DQT_COEFF) { - return glb_anStdQuantLum[nInd]; - } else { -#ifdef DEBUG_LOG - CString strTmp; - CString strDebug; - strTmp.Format(_T("GetDqtQuantStd() with nInd out of range. nInd=[%u]"),nInd); - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("JfifDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - return 0; - } -} - -// Fetch the DQT ordering index (with optional zigzag sequence) -// -// INPUT: -// - nInd Coefficient index -// - bZigZag Use zig-zag ordering -// -// RETURN: -// - Sequence index -// -unsigned CjfifDecode::GetDqtZigZagIndex(unsigned nInd,bool bZigZag) -{ - if (nInd < MAX_DQT_COEFF) { - if (bZigZag) { - return nInd; - } else { - return glb_anZigZag[nInd]; - } - } else { -#ifdef DEBUG_LOG - CString strTmp; - CString strDebug; - strTmp.Format(_T("GetDqtZigZagIndex() with nInd out of range. nInd=[%u]"),nInd); - strDebug.Format(_T("## File=[%-100s] Block=[%-10s] Error=[%s]\n"),(LPCTSTR)m_pAppConfig->strCurFname, - _T("JfifDecode"),(LPCTSTR)strTmp); - OutputDebugString(strDebug); -#else - ASSERT(false); -#endif - return 0; - } -} - -// Reset the DQT tables -// -// POST: -// - m_anImgDqtTbl[][] -// - m_anImgThumbDqt[][] -// - m_adImgDqtQual[] -// - m_abImgDqtSet[] -// - m_abImgDqtThumbSet[] -// -void CjfifDecode::ClearDQT() -{ - for (unsigned nTblInd=0;nTblIndBuf(nOffset,bClean); - } -} - -// Write out a line to the log buffer if we are in verbose mode -// -// PRE: -// - m_bVerbose Verbose mode -// -// INPUT: -// - strLine String to output -// -// OUTPUT: -// - none -// -// POST: -// - m_pLog -// -// RETURN: -// - none -// -void CjfifDecode::DbgAddLine(LPCTSTR strLine) -{ - if (m_bVerbose) - { - m_pLog->AddLine(strLine); - } -} - -// Convert a UINT32 and decompose into 4 bytes, but support -// either endian byte-swap mode -// -// PRE: -// - m_nImgExifEndian Byte swap mode (0=little, 1=big) -// -// INPUT: -// - nVal Input UINT32 -// -// OUTPUT: -// - nByte0 Byte #1 -// - nByte1 Byte #2 -// - nByte2 Byte #3 -// - nByte3 Byte #4 -// -// RETURN: -// - none -// -void CjfifDecode::UnByteSwap4(unsigned nVal,unsigned &nByte0,unsigned &nByte1,unsigned &nByte2,unsigned &nByte3) -{ - if (m_nImgExifEndian == 0) { - // Little Endian - nByte3 = (nVal & 0xFF000000) >> 24; - nByte2 = (nVal & 0x00FF0000) >> 16; - nByte1 = (nVal & 0x0000FF00) >> 8; - nByte0 = (nVal & 0x000000FF); - } else { - // Big Endian - nByte0 = (nVal & 0xFF000000) >> 24; - nByte1 = (nVal & 0x00FF0000) >> 16; - nByte2 = (nVal & 0x0000FF00) >> 8; - nByte3 = (nVal & 0x000000FF); - } -} - -// Perform conversion from 4 bytes into UINT32 with -// endian byte-swapping support -// -// PRE: -// - m_nImgExifEndian Byte swap mode (0=little, 1=big) -// -// INPUT: -// - nByte0 Byte #1 -// - nByte1 Byte #2 -// - nByte2 Byte #3 -// - nByte3 Byte #4 -// -// RETURN: -// - UINT32 -// -unsigned CjfifDecode::ByteSwap4(unsigned nByte0,unsigned nByte1, unsigned nByte2, unsigned nByte3) -{ - unsigned nVal; - - if (m_nImgExifEndian == 0) { - // Little endian, byte swap required - nVal = (nByte3<<24) + (nByte2<<16) + (nByte1<<8) + nByte0; - } else { - // Big endian, no swap required - nVal = (nByte0<<24) + (nByte1<<16) + (nByte2<<8) + nByte3; - } - return nVal; -} - -// Perform conversion from 2 bytes into half-word with -// endian byte-swapping support -// -// PRE: -// - m_nImgExifEndian Byte swap mode (0=little, 1=big) -// -// INPUT: -// - nByte0 Byte #1 -// - nByte1 Byte #2 -// -// RETURN: -// - UINT16 -// -unsigned CjfifDecode::ByteSwap2(unsigned nByte0,unsigned nByte1) -{ - unsigned nVal; - if (m_nImgExifEndian == 0) { - // Little endian, byte swap required - nVal = (nByte1<<8) + nByte0; - } else { - // Big endian, no swap required - nVal = (nByte0<<8) + nByte1; - } - return nVal; -} - -// Decode Canon Makernotes -// Only the most common makernotes are supported; there are a large -// number of makernotes that have not been documented anywhere. -CStr2 CjfifDecode::LookupMakerCanonTag(unsigned nMainTag,unsigned nSubTag,unsigned nVal) -{ - CString strTmp; - CStr2 sRetVal; - - sRetVal.strTag = _T("???"); - sRetVal.bUnknown = false; // Set to true in default clauses - sRetVal.strVal.Format(_T("%u"),nVal); // Provide default value - - unsigned nValHi,nValLo; - nValHi = (nVal & 0xff00) >> 8; - nValLo = (nVal & 0x00ff); - - switch(nMainTag) - { - - case 0x0001: - - switch(nSubTag) - { - case 0x0001: sRetVal.strTag = _T("Canon.Cs1.Macro");break; // Short Macro mode - case 0x0002: sRetVal.strTag = _T("Canon.Cs1.Selftimer");break; // Short Self timer - case 0x0003: sRetVal.strTag = _T("Canon.Cs1.Quality"); - if (nVal == 2) { sRetVal.strVal = _T("norm"); } - else if (nVal == 3) { sRetVal.strVal = _T("fine"); } - else if (nVal == 5) { sRetVal.strVal = _T("superfine"); } - else { - sRetVal.strVal = _T("?"); - } - // Save the quality string for later - m_strImgQualExif = sRetVal.strVal; - break; // Short Quality - case 0x0004: sRetVal.strTag = _T("Canon.Cs1.FlashMode");break; // Short Flash mode setting - case 0x0005: sRetVal.strTag = _T("Canon.Cs1.DriveMode");break; // Short Drive mode setting - case 0x0007: sRetVal.strTag = _T("Canon.Cs1.FocusMode"); // Short Focus mode setting - switch(nVal) { - case 0 : sRetVal.strVal = _T("One-shot");break; - case 1 : sRetVal.strVal = _T("AI Servo");break; - case 2 : sRetVal.strVal = _T("AI Focus");break; - case 3 : sRetVal.strVal = _T("Manual Focus");break; - case 4 : sRetVal.strVal = _T("Single");break; - case 5 : sRetVal.strVal = _T("Continuous");break; - case 6 : sRetVal.strVal = _T("Manual Focus");break; - default : sRetVal.strVal = _T("?");break; - } - break; - case 0x000a: sRetVal.strTag = _T("Canon.Cs1.ImageSize"); // Short Image size - if (nVal == 0) { sRetVal.strVal = _T("Large"); } - else if (nVal == 1) { sRetVal.strVal = _T("Medium"); } - else if (nVal == 2) { sRetVal.strVal = _T("Small"); } - else { - sRetVal.strVal = _T("?"); - } - break; - case 0x000b: sRetVal.strTag = _T("Canon.Cs1.EasyMode");break; // Short Easy shooting mode - case 0x000c: sRetVal.strTag = _T("Canon.Cs1.DigitalZoom");break; // Short Digital zoom - case 0x000d: sRetVal.strTag = _T("Canon.Cs1.Contrast");break; // Short Contrast setting - case 0x000e: sRetVal.strTag = _T("Canon.Cs1.Saturation");break; // Short Saturation setting - case 0x000f: sRetVal.strTag = _T("Canon.Cs1.Sharpness");break; // Short Sharpness setting - case 0x0010: sRetVal.strTag = _T("Canon.Cs1.ISOSpeed");break; // Short ISO speed setting - case 0x0011: sRetVal.strTag = _T("Canon.Cs1.MeteringMode");break; // Short Metering mode setting - case 0x0012: sRetVal.strTag = _T("Canon.Cs1.FocusType");break; // Short Focus type setting - case 0x0013: sRetVal.strTag = _T("Canon.Cs1.AFPoint");break; // Short AF point selected - case 0x0014: sRetVal.strTag = _T("Canon.Cs1.ExposureProgram");break; // Short Exposure mode setting - case 0x0016: sRetVal.strTag = _T("Canon.Cs1.LensType");break; // - case 0x0017: sRetVal.strTag = _T("Canon.Cs1.Lens");break; // Short 'long' and 'short' focal length of lens (in 'focal m_nImgUnits') and 'focal m_nImgUnits' per mm - case 0x001a: sRetVal.strTag = _T("Canon.Cs1.MaxAperture");break; // - case 0x001b: sRetVal.strTag = _T("Canon.Cs1.MinAperture");break; // - case 0x001c: sRetVal.strTag = _T("Canon.Cs1.FlashActivity");break; // Short Flash activity - case 0x001d: sRetVal.strTag = _T("Canon.Cs1.FlashDetails");break; // Short Flash details - case 0x0020: sRetVal.strTag = _T("Canon.Cs1.FocusMode");break; // Short Focus mode setting - default: - sRetVal.strTag.Format(_T("Canon.Cs1.x%04X"),nSubTag); - sRetVal.bUnknown = true; - break; - } // switch nSubTag - break; - - case 0x0004: - - switch(nSubTag) - { - case 0x0002: sRetVal.strTag = _T("Canon.Cs2.ISOSpeed");break; // Short ISO speed used - case 0x0004: sRetVal.strTag = _T("Canon.Cs2.TargetAperture");break; // Short Target Aperture - case 0x0005: sRetVal.strTag = _T("Canon.Cs2.TargetShutterSpeed");break; // Short Target shutter speed - case 0x0007: sRetVal.strTag = _T("Canon.Cs2.WhiteBalance");break; // Short White balance setting - case 0x0009: sRetVal.strTag = _T("Canon.Cs2.Sequence");break; // Short Sequence number (if in a continuous burst) - case 0x000e: sRetVal.strTag = _T("Canon.Cs2.AFPointUsed");break; // Short AF point used - case 0x000f: sRetVal.strTag = _T("Canon.Cs2.FlashBias");break; // Short Flash bias - case 0x0013: sRetVal.strTag = _T("Canon.Cs2.SubjectDistance");break; // Short Subject distance (m_nImgUnits are not clear) - case 0x0015: sRetVal.strTag = _T("Canon.Cs2.ApertureValue");break; // Short Aperture - case 0x0016: sRetVal.strTag = _T("Canon.Cs2.ShutterSpeedValue");break; // Short Shutter speed - default: - sRetVal.strTag.Format(_T("Canon.Cs2.x%04X"),nSubTag); - sRetVal.bUnknown = true; - break; - } // switch nSubTag - break; - - case 0x000F: - - // CustomFunctions are different! Tag given by high byte, value by low - // Index order (usually the nSubTag) is not used. - sRetVal.strVal.Format(_T("%u"),nValLo); // Provide default value - switch(nValHi) - { - - case 0x0001: sRetVal.strTag = _T("Canon.Cf.NoiseReduction");break; // Short Long exposure noise reduction - case 0x0002: sRetVal.strTag = _T("Canon.Cf.ShutterAeLock");break; // Short Shutter/AE lock buttons - case 0x0003: sRetVal.strTag = _T("Canon.Cf.MirrorLockup");break; // Short Mirror lockup - case 0x0004: sRetVal.strTag = _T("Canon.Cf.ExposureLevelIncrements");break; // Short Tv/Av and exposure level - case 0x0005: sRetVal.strTag = _T("Canon.Cf.AFAssist");break; // Short AF assist light - case 0x0006: sRetVal.strTag = _T("Canon.Cf.FlashSyncSpeedAv");break; // Short Shutter speed in Av mode - case 0x0007: sRetVal.strTag = _T("Canon.Cf.AEBSequence");break; // Short AEB sequence/auto cancellation - case 0x0008: sRetVal.strTag = _T("Canon.Cf.ShutterCurtainSync");break; // Short Shutter curtain sync - case 0x0009: sRetVal.strTag = _T("Canon.Cf.LensAFStopButton");break; // Short Lens AF stop button Fn. Switch - case 0x000a: sRetVal.strTag = _T("Canon.Cf.FillFlashAutoReduction");break; // Short Auto reduction of fill flash - case 0x000b: sRetVal.strTag = _T("Canon.Cf.MenuButtonReturn");break; // Short Menu button return position - case 0x000c: sRetVal.strTag = _T("Canon.Cf.SetButtonFunction");break; // Short SET button func. when shooting - case 0x000d: sRetVal.strTag = _T("Canon.Cf.SensorCleaning");break; // Short Sensor cleaning - case 0x000e: sRetVal.strTag = _T("Canon.Cf.SuperimposedDisplay");break; // Short Superimposed display - case 0x000f: sRetVal.strTag = _T("Canon.Cf.ShutterReleaseNoCFCard");break; // Short Shutter Release W/O CF Card - default: - sRetVal.strTag.Format(_T("Canon.Cf.x%04X"),nValHi); - sRetVal.bUnknown = true; - break; - } // switch nSubTag - break; - -/* - // Other ones assumed to use high-byte/low-byte method: - case 0x00C0: - sRetVal.strVal.Format(_T("%u"),nValLo); // Provide default value - switch(nValHi) - { - //case 0x0001: sRetVal.strTag = _T("Canon.x00C0.???");break; // - default: - sRetVal.strTag.Format(_T("Canon.x00C0.x%04X"),nValHi); - break; - } - break; - - case 0x00C1: - sRetVal.strVal.Format(_T("%u"),nValLo); // Provide default value - switch(nValHi) - { - //case 0x0001: sRetVal.strTag = _T("Canon.x00C1.???");break; // - default: - sRetVal.strTag.Format(_T("Canon.x00C1.x%04X"),nValHi); - break; - } - break; -*/ - - case 0x0012: - - switch(nSubTag) - { - case 0x0002: sRetVal.strTag = _T("Canon.Pi.ImageWidth");break; // - case 0x0003: sRetVal.strTag = _T("Canon.Pi.ImageHeight");break; // - case 0x0004: sRetVal.strTag = _T("Canon.Pi.ImageWidthAsShot");break; // - case 0x0005: sRetVal.strTag = _T("Canon.Pi.ImageHeightAsShot");break; // - case 0x0016: sRetVal.strTag = _T("Canon.Pi.AFPointsUsed");break; // - case 0x001a: sRetVal.strTag = _T("Canon.Pi.AFPointsUsed20D");break; // - default: - sRetVal.strTag.Format(_T("Canon.Pi.x%04X"),nSubTag); - sRetVal.bUnknown = true; - break; - } // switch nSubTag - break; - - default: - sRetVal.strTag.Format(_T("Canon.x%04X.x%04X"),nMainTag,nSubTag); - sRetVal.bUnknown = true; - break; - - } // switch mainTag - - return sRetVal; -} - - -// Perform decode of EXIF IFD tags including MakerNote tags -// -// PRE: -// - m_strImgExifMake Used for MakerNote decode -// -// INPUT: -// - strSect IFD section -// - nTag Tag code value -// -// OUTPUT: -// - bUnknown Was the tag unknown? -// -// RETURN: -// - Formatted string -// -CString CjfifDecode::LookupExifTag(CString strSect,unsigned nTag,bool &bUnknown) -{ - CString strTmp; - bUnknown = false; - - if (strSect == _T("IFD0")) - { - - switch(nTag) - { - - case 0x010E: return _T("ImageDescription");break; // ascii string Describes image - case 0x010F: return _T("Make");break; // ascii string Shows manufacturer of digicam - case 0x0110: return _T("Model");break; // ascii string Shows model number of digicam - case 0x0112: return _T("Orientation");break; // unsigned short 1 The orientation of the camera relative to the scene, when the image was captured. The start point of stored data is, '1' means upper left, '3' lower right, '6' upper right, '8' lower left, '9' undefined. - case 0x011A: return _T("XResolution");break; // unsigned rational 1 Display/Print resolution of image. Large number of digicam uses 1/72inch, but it has no mean because personal computer doesn't use this value to display/print out. - case 0x011B: return _T("YResolution");break; // unsigned rational 1 - case 0x0128: return _T("ResolutionUnit");break; // unsigned short 1 Unit of XResolution(0x011a)/YResolution(0x011b). '1' means no-unit, '2' means inch, '3' means centimeter. - case 0x0131: return _T("Software");break; // ascii string Shows firmware(internal software of digicam) version number. - case 0x0132: return _T("DateTime");break; // ascii string 20 Date/Time of image was last modified. Data format is "YYYY:MM:DD HH:MM:SS"+0x00, total 20bytes. In usual, it has the same value of DateTimeOriginal(0x9003) - case 0x013B: return _T("Artist");break; // Seems to be here and not only in SubIFD (maybe instead of SubIFD) - case 0x013E: return _T("WhitePoint");break; // unsigned rational 2 Defines chromaticity of white point of the image. If the image uses CIE Standard Illumination D65(known as international standard of 'daylight'), the values are '3127/10000,3290/10000'. - case 0x013F: return _T("PrimChromaticities");break; // unsigned rational 6 Defines chromaticity of the primaries of the image. If the image uses CCIR Recommendation 709 primearies, values are '640/1000,330/1000,300/1000,600/1000,150/1000,0/1000'. - case 0x0211: return _T("YCbCrCoefficients");break; // unsigned rational 3 When image format is YCbCr, this value shows a constant to translate it to RGB format. In usual, values are '0.299/0.587/0.114'. - case 0x0213: return _T("YCbCrPositioning");break; // unsigned short 1 When image format is YCbCr and uses 'Subsampling'(cropping of chroma data, all the digicam do that), defines the chroma sample point of subsampling pixel array. '1' means the center of pixel array, '2' means the datum point. - case 0x0214: return _T("ReferenceBlackWhite");break; // unsigned rational 6 Shows reference value of black point/white point. In case of YCbCr format, first 2 show black/white of Y, next 2 are Cb, last 2 are Cr. In case of RGB format, first 2 show black/white of R, next 2 are G, last 2 are B. - case 0x8298: return _T("Copyright");break; // ascii string Shows copyright information - case 0x8769: return _T("ExifOffset");break; //unsigned long 1 Offset to Exif Sub IFD - case 0x8825: return _T("GPSOffset");break; //unsigned long 1 Offset to Exif GPS IFD -//NEW: - case 0x9C9B: return _T("XPTitle");break; - case 0x9C9C: return _T("XPComment");break; - case 0x9C9D: return _T("XPAuthor");break; - case 0x9C9e: return _T("XPKeywords");break; - case 0x9C9f: return _T("XPSubject");break; -//NEW: The following were found in IFD0 even though they should just be SubIFD? - case 0xA401: return _T("CustomRendered");break; - case 0xA402: return _T("ExposureMode");break; - case 0xA403: return _T("WhiteBalance");break; - case 0xA406: return _T("SceneCaptureType");break; - - default: - strTmp.Format(_T("IFD0.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - } - - } else if (strSect == _T("SubIFD")) { - - switch(nTag) - { - case 0x00fe: return _T("NewSubfileType");break; // unsigned long 1 - case 0x00ff: return _T("SubfileType");break; // unsigned short 1 - case 0x012d: return _T("TransferFunction");break; // unsigned short 3 - case 0x013b: return _T("Artist");break; // ascii string - case 0x013d: return _T("Predictor");break; // unsigned short 1 - case 0x0142: return _T("TileWidth");break; // unsigned short 1 - case 0x0143: return _T("TileLength");break; // unsigned short 1 - case 0x0144: return _T("TileOffsets");break; // unsigned long - case 0x0145: return _T("TileByteCounts");break; // unsigned short - case 0x014a: return _T("SubIFDs");break; // unsigned long - case 0x015b: return _T("JPEGTables");break; // undefined - case 0x828d: return _T("CFARepeatPatternDim");break; // unsigned short 2 - case 0x828e: return _T("CFAPattern");break; // unsigned byte - case 0x828f: return _T("BatteryLevel");break; // unsigned rational 1 - case 0x829A: return _T("ExposureTime");break; - case 0x829D: return _T("FNumber");break; - case 0x83bb: return _T("IPTC/NAA");break; // unsigned long - case 0x8773: return _T("InterColorProfile");break; // undefined - case 0x8822: return _T("ExposureProgram");break; - case 0x8824: return _T("SpectralSensitivity");break; // ascii string - case 0x8825: return _T("GPSInfo");break; // unsigned long 1 - case 0x8827: return _T("ISOSpeedRatings");break; - case 0x8828: return _T("OECF");break; // undefined - case 0x8829: return _T("Interlace");break; // unsigned short 1 - case 0x882a: return _T("TimeZoneOffset");break; // signed short 1 - case 0x882b: return _T("SelfTimerMode");break; // unsigned short 1 - case 0x9000: return _T("ExifVersion");break; - case 0x9003: return _T("DateTimeOriginal");break; - case 0x9004: return _T("DateTimeDigitized");break; - case 0x9101: return _T("ComponentsConfiguration");break; - case 0x9102: return _T("CompressedBitsPerPixel");break; - case 0x9201: return _T("ShutterSpeedValue");break; - case 0x9202: return _T("ApertureValue");break; - case 0x9203: return _T("BrightnessValue");break; - case 0x9204: return _T("ExposureBiasValue");break; - case 0x9205: return _T("MaxApertureValue");break; - case 0x9206: return _T("SubjectDistance");break; - case 0x9207: return _T("MeteringMode");break; - case 0x9208: return _T("LightSource");break; - case 0x9209: return _T("Flash");break; - case 0x920A: return _T("FocalLength");break; - case 0x920b: return _T("FlashEnergy");break; // unsigned rational 1 - case 0x920c: return _T("SpatialFrequencyResponse");break; // undefined - case 0x920d: return _T("Noise");break; // undefined - case 0x9211: return _T("ImageNumber");break; // unsigned long 1 - case 0x9212: return _T("SecurityClassification");break; // ascii string 1 - case 0x9213: return _T("ImageHistory");break; // ascii string - case 0x9214: return _T("SubjectLocation");break; // unsigned short 4 - case 0x9215: return _T("ExposureIndex");break; // unsigned rational 1 - case 0x9216: return _T("TIFF/EPStandardID");break; // unsigned byte 4 - case 0x927C: return _T("MakerNote");break; - case 0x9286: return _T("UserComment");break; - case 0x9290: return _T("SubSecTime");break; // ascii string - case 0x9291: return _T("SubSecTimeOriginal");break; // ascii string - case 0x9292: return _T("SubSecTimeDigitized");break; // ascii string - case 0xA000: return _T("FlashPixVersion");break; - case 0xA001: return _T("ColorSpace");break; - case 0xA002: return _T("ExifImageWidth");break; - case 0xA003: return _T("ExifImageHeight");break; - case 0xA004: return _T("RelatedSoundFile");break; - case 0xA005: return _T("ExifInteroperabilityOffset");break; - case 0xa20b: return _T("FlashEnergy unsigned");break; // rational 1 - case 0xa20c: return _T("SpatialFrequencyResponse");break; // unsigned short 1 - case 0xA20E: return _T("FocalPlaneXResolution");break; - case 0xA20F: return _T("FocalPlaneYResolution");break; - case 0xA210: return _T("FocalPlaneResolutionUnit");break; - case 0xa214: return _T("SubjectLocation");break; // unsigned short 1 - case 0xa215: return _T("ExposureIndex");break; // unsigned rational 1 - case 0xA217: return _T("SensingMethod");break; - case 0xA300: return _T("FileSource");break; - case 0xA301: return _T("SceneType");break; - case 0xa302: return _T("CFAPattern");break; // undefined 1 - case 0xa401: return _T("CustomRendered");break; // Short Custom image processing - case 0xa402: return _T("ExposureMode");break; // Short Exposure mode - case 0xa403: return _T("WhiteBalance");break; // Short White balance - case 0xa404: return _T("DigitalZoomRatio");break; // Rational Digital zoom ratio - case 0xa405: return _T("FocalLengthIn35mmFilm");break; // Short Focal length in 35 mm film - case 0xa406: return _T("SceneCaptureType");break; // Short Scene capture type - case 0xa407: return _T("GainControl");break; // Rational Gain control - case 0xa408: return _T("Contrast");break; // Short Contrast - case 0xa409: return _T("Saturation");break; // Short Saturation - case 0xa40a: return _T("Sharpness");break; // Short Sharpness - case 0xa40b: return _T("DeviceSettingDescription");break; // Undefined Device settings description - case 0xa40c: return _T("SubjectDistanceRange");break; // Short Subject distance range - case 0xa420: return _T("ImageUniqueID");break; // Ascii Unique image ID - - default: - strTmp.Format(_T("SubIFD.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - - } - - } else if (strSect == _T("IFD1")) { - - switch(nTag) - { - case 0x0100: return _T("ImageWidth");break; // unsigned short/long 1 Shows size of thumbnail image. - case 0x0101: return _T("ImageLength");break; // unsigned short/long 1 - case 0x0102: return _T("BitsPerSample");break; // unsigned short 3 When image format is no compression, this value shows the number of bits per component for each pixel. Usually this value is '8,8,8' - case 0x0103: return _T("Compression");break; // unsigned short 1 Shows compression method. '1' means no compression, '6' means JPEG compression. - case 0x0106: return _T("PhotometricInterpretation");break; // unsigned short 1 Shows the color space of the image data components. '1' means monochrome, '2' means RGB, '6' means YCbCr. - case 0x0111: return _T("StripOffsets");break; // unsigned short/long When image format is no compression, this value shows offset to image data. In some case image data is striped and this value is plural. - case 0x0115: return _T("SamplesPerPixel");break; // unsigned short 1 When image format is no compression, this value shows the number of components stored for each pixel. At color image, this value is '3'. - case 0x0116: return _T("RowsPerStrip");break; // unsigned short/long 1 When image format is no compression and image has stored as strip, this value shows how many rows stored to each strip. If image has not striped, this value is the same as ImageLength(0x0101). - case 0x0117: return _T("StripByteConunts");break; // unsigned short/long When image format is no compression and stored as strip, this value shows how many bytes used for each strip and this value is plural. If image has not stripped, this value is single and means whole data size of image. - case 0x011a: return _T("XResolution");break; // unsigned rational 1 Display/Print resolution of image. Large number of digicam uses 1/72inch, but it has no mean because personal computer doesn't use this value to display/print out. - case 0x011b: return _T("YResolution");break; // unsigned rational 1 - case 0x011c: return _T("PlanarConfiguration");break; // unsigned short 1 When image format is no compression YCbCr, this value shows byte aligns of YCbCr data. If value is '1', Y/Cb/Cr value is chunky format, contiguous for each subsampling pixel. If value is '2', Y/Cb/Cr value is separated and stored to Y plane/Cb plane/Cr plane format. - case 0x0128: return _T("ResolutionUnit");break; // unsigned short 1 Unit of XResolution(0x011a)/YResolution(0x011b). '1' means inch, '2' means centimeter. - case 0x0201: return _T("JpegIFOffset");break; // unsigned long 1 When image format is JPEG, this value show offset to JPEG data stored. - case 0x0202: return _T("JpegIFByteCount");break; // unsigned long 1 When image format is JPEG, this value shows data size of JPEG image. - case 0x0211: return _T("YCbCrCoefficients");break; // unsigned rational 3 When image format is YCbCr, this value shows constants to translate it to RGB format. In usual, '0.299/0.587/0.114' are used. - case 0x0212: return _T("YCbCrSubSampling");break; // unsigned short 2 When image format is YCbCr and uses subsampling(cropping of chroma data, all the digicam do that), this value shows how many chroma data subsampled. First value shows horizontal, next value shows vertical subsample rate. - case 0x0213: return _T("YCbCrPositioning");break; // unsigned short 1 When image format is YCbCr and uses 'Subsampling'(cropping of chroma data, all the digicam do that), this value defines the chroma sample point of subsampled pixel array. '1' means the center of pixel array, '2' means the datum point(0,0). - case 0x0214: return _T("ReferenceBlackWhite");break; // unsigned rational 6 Shows reference value of black point/white point. In case of YCbCr format, first 2 show black/white of Y, next 2 are Cb, last 2 are Cr. In case of RGB format, first 2 show black/white of R, next 2 are G, last 2 are B. - - default: - strTmp.Format(_T("IFD1.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - - } - - } else if (strSect == _T("InteropIFD")) { - switch(nTag) { - case 0x0001: return _T("InteroperabilityIndex");break; - case 0x0002: return _T("InteroperabilityVersion");break; - case 0x1000: return _T("RelatedImageFileFormat");break; - case 0x1001: return _T("RelatedImageWidth");break; - case 0x1002: return _T("RelatedImageLength");break; - - default: - strTmp.Format(_T("Interop.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - } - } else if (strSect == _T("GPSIFD")) { - switch(nTag) { - case 0x0000: return _T("GPSVersionID");break; - case 0x0001: return _T("GPSLatitudeRef");break; - case 0x0002: return _T("GPSLatitude");break; - case 0x0003: return _T("GPSLongitudeRef");break; - case 0x0004: return _T("GPSLongitude");break; - case 0x0005: return _T("GPSAltitudeRef");break; - case 0x0006: return _T("GPSAltitude");break; - case 0x0007: return _T("GPSTimeStamp");break; - case 0x0008: return _T("GPSSatellites");break; - case 0x0009: return _T("GPSStatus");break; - case 0x000A: return _T("GPSMeasureMode");break; - case 0x000B: return _T("GPSDOP");break; - case 0x000C: return _T("GPSSpeedRef");break; - case 0x000D: return _T("GPSSpeed");break; - case 0x000E: return _T("GPSTrackRef");break; - case 0x000F: return _T("GPSTrack");break; - case 0x0010: return _T("GPSImgDirectionRef");break; - case 0x0011: return _T("GPSImgDirection");break; - case 0x0012: return _T("GPSMapDatum");break; - case 0x0013: return _T("GPSDestLatitudeRef");break; - case 0x0014: return _T("GPSDestLatitude");break; - case 0x0015: return _T("GPSDestLongitudeRef");break; - case 0x0016: return _T("GPSDestLongitude");break; - case 0x0017: return _T("GPSDestBearingRef");break; - case 0x0018: return _T("GPSDestBearing");break; - case 0x0019: return _T("GPSDestDistanceRef");break; - case 0x001A: return _T("GPSDestDistance");break; - case 0x001B: return _T("GPSProcessingMethod");break; - case 0x001C: return _T("GPSAreaInformation");break; - case 0x001D: return _T("GPSDateStamp");break; - case 0x001E: return _T("GPSDifferential");break; - - default: - strTmp.Format(_T("GPS.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - } - } else if (strSect == _T("MakerIFD")) { - - // Makernotes need special handling - // We only support a few different manufacturers for makernotes. - - // A few Canon tags are supported in this routine, the rest are - // handled by the LookupMakerCanonTag() call. - if (m_strImgExifMake == _T("Canon")) { - - switch(nTag) - { - case 0x0001: return _T("Canon.CameraSettings1");break; - case 0x0004: return _T("Canon.CameraSettings2");break; - case 0x0006: return _T("Canon.ImageType");break; - case 0x0007: return _T("Canon.FirmwareVersion");break; - case 0x0008: return _T("Canon.ImageNumber");break; - case 0x0009: return _T("Canon.OwnerName");break; - case 0x000C: return _T("Canon.SerialNumber");break; - case 0x000F: return _T("Canon.CustomFunctions");break; - case 0x0012: return _T("Canon.PictureInfo");break; - case 0x00A9: return _T("Canon.WhiteBalanceTable");break; - - default: - strTmp.Format(_T("Canon.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - } - - } // Canon - - else if (m_strImgExifMake == _T("SIGMA")) - { - switch(nTag) - { - case 0x0002: return _T("Sigma.SerialNumber");break; // Ascii Camera serial number - case 0x0003: return _T("Sigma.DriveMode");break; // Ascii Drive Mode - case 0x0004: return _T("Sigma.ResolutionMode");break; // Ascii Resolution Mode - case 0x0005: return _T("Sigma.AutofocusMode");break; // Ascii Autofocus mode - case 0x0006: return _T("Sigma.FocusSetting");break; // Ascii Focus setting - case 0x0007: return _T("Sigma.WhiteBalance");break; // Ascii White balance - case 0x0008: return _T("Sigma.ExposureMode");break; // Ascii Exposure mode - case 0x0009: return _T("Sigma.MeteringMode");break; // Ascii Metering mode - case 0x000a: return _T("Sigma.LensRange");break; // Ascii Lens focal length range - case 0x000b: return _T("Sigma.ColorSpace");break; // Ascii Color space - case 0x000c: return _T("Sigma.Exposure");break; // Ascii Exposure - case 0x000d: return _T("Sigma.Contrast");break; // Ascii Contrast - case 0x000e: return _T("Sigma.Shadow");break; // Ascii Shadow - case 0x000f: return _T("Sigma.Highlight");break; // Ascii Highlight - case 0x0010: return _T("Sigma.Saturation");break; // Ascii Saturation - case 0x0011: return _T("Sigma.Sharpness");break; // Ascii Sharpness - case 0x0012: return _T("Sigma.FillLight");break; // Ascii X3 Fill light - case 0x0014: return _T("Sigma.ColorAdjustment");break; // Ascii Color adjustment - case 0x0015: return _T("Sigma.AdjustmentMode");break; // Ascii Adjustment mode - case 0x0016: return _T("Sigma.Quality");break; // Ascii Quality - case 0x0017: return _T("Sigma.Firmware");break; // Ascii Firmware - case 0x0018: return _T("Sigma.Software");break; // Ascii Software - case 0x0019: return _T("Sigma.AutoBracket");break; // Ascii Auto bracket - default: - strTmp.Format(_T("Sigma.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - } - } // SIGMA - - else if (m_strImgExifMake == _T("SONY")) - { - - switch(nTag) - { - case 0xb021: return _T("Sony.ColorTemperature");break; - case 0xb023: return _T("Sony.SceneMode");break; - case 0xb024: return _T("Sony.ZoneMatching");break; - case 0xb025: return _T("Sony.DynamicRangeOptimizer");break; - case 0xb026: return _T("Sony.ImageStabilization");break; - case 0xb027: return _T("Sony.LensID");break; - case 0xb029: return _T("Sony.ColorMode");break; - case 0xb040: return _T("Sony.Macro");break; - case 0xb041: return _T("Sony.ExposureMode");break; - case 0xb047: return _T("Sony.Quality");break; - case 0xb04e: return _T("Sony.LongExposureNoiseReduction");break; - default: - // No real info is known - strTmp.Format(_T("Sony.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - } - } // SONY - - else if (m_strImgExifMake == _T("FUJIFILM")) - { - switch(nTag) - { - case 0x0000: return _T("Fujifilm.Version");break; // Undefined Fujifilm Makernote version - case 0x1000: return _T("Fujifilm.Quality");break; // Ascii Image quality setting - case 0x1001: return _T("Fujifilm.Sharpness");break; // Short Sharpness setting - case 0x1002: return _T("Fujifilm.WhiteBalance");break; // Short White balance setting - case 0x1003: return _T("Fujifilm.Color");break; // Short Chroma saturation setting - case 0x1004: return _T("Fujifilm.Tone");break; // Short Contrast setting - case 0x1010: return _T("Fujifilm.FlashMode");break; // Short Flash firing mode setting - case 0x1011: return _T("Fujifilm.FlashStrength");break; // SRational Flash firing strength compensation setting - case 0x1020: return _T("Fujifilm.Macro");break; // Short Macro mode setting - case 0x1021: return _T("Fujifilm.FocusMode");break; // Short Focusing mode setting - case 0x1030: return _T("Fujifilm.SlowSync");break; // Short Slow synchro mode setting - case 0x1031: return _T("Fujifilm.PictureMode");break; // Short Picture mode setting - case 0x1100: return _T("Fujifilm.Continuous");break; // Short Continuous shooting or auto bracketing setting - case 0x1210: return _T("Fujifilm.FinePixColor");break; // Short Fuji FinePix Color setting - case 0x1300: return _T("Fujifilm.BlurWarning");break; // Short Blur warning status - case 0x1301: return _T("Fujifilm.FocusWarning");break; // Short Auto Focus warning status - case 0x1302: return _T("Fujifilm.AeWarning");break; // Short Auto Exposure warning status - default: - strTmp.Format(_T("Fujifilm.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - } - } // FUJIFILM - - else if (m_strImgExifMake == _T("NIKON")) - { - if (m_nImgExifMakeSubtype == 1) { - // Type 1 - switch(nTag) - { - case 0x0001: return _T("Nikon1.Version");break; // Undefined Nikon Makernote version - case 0x0002: return _T("Nikon1.ISOSpeed");break; // Short ISO speed setting - case 0x0003: return _T("Nikon1.ColorMode");break; // Ascii Color mode - case 0x0004: return _T("Nikon1.Quality");break; // Ascii Image quality setting - case 0x0005: return _T("Nikon1.WhiteBalance");break; // Ascii White balance - case 0x0006: return _T("Nikon1.Sharpening");break; // Ascii Image sharpening setting - case 0x0007: return _T("Nikon1.Focus");break; // Ascii Focus mode - case 0x0008: return _T("Nikon1.Flash");break; // Ascii Flash mode - case 0x000f: return _T("Nikon1.ISOSelection");break; // Ascii ISO selection - case 0x0010: return _T("Nikon1.DataDump");break; // Undefined Data dump - case 0x0080: return _T("Nikon1.ImageAdjustment");break; // Ascii Image adjustment setting - case 0x0082: return _T("Nikon1.Adapter");break; // Ascii Adapter used - case 0x0085: return _T("Nikon1.FocusDistance");break; // Rational Manual focus distance - case 0x0086: return _T("Nikon1.DigitalZoom");break; // Rational Digital zoom setting - case 0x0088: return _T("Nikon1.AFFocusPos");break; // Undefined AF focus position - default: - strTmp.Format(_T("Nikon1.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - } - } - else if (m_nImgExifMakeSubtype == 2) - { - // Type 2 - switch(nTag) - { - case 0x0003: return _T("Nikon2.Quality");break; // Short Image quality setting - case 0x0004: return _T("Nikon2.ColorMode");break; // Short Color mode - case 0x0005: return _T("Nikon2.ImageAdjustment");break; // Short Image adjustment setting - case 0x0006: return _T("Nikon2.ISOSpeed");break; // Short ISO speed setting - case 0x0007: return _T("Nikon2.WhiteBalance");break; // Short White balance - case 0x0008: return _T("Nikon2.Focus");break; // Rational Focus mode - case 0x000a: return _T("Nikon2.DigitalZoom");break; // Rational Digital zoom setting - case 0x000b: return _T("Nikon2.Adapter");break; // Short Adapter used - default: - strTmp.Format(_T("Nikon2.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - } - } - else if (m_nImgExifMakeSubtype == 3) - { - // Type 3 - switch(nTag) - { - case 0x0001: return _T("Nikon3.Version");break; // Undefined Nikon Makernote version - case 0x0002: return _T("Nikon3.ISOSpeed");break; // Short ISO speed used - case 0x0003: return _T("Nikon3.ColorMode");break; // Ascii Color mode - case 0x0004: return _T("Nikon3.Quality");break; // Ascii Image quality setting - case 0x0005: return _T("Nikon3.WhiteBalance");break; // Ascii White balance - case 0x0006: return _T("Nikon3.Sharpening");break; // Ascii Image sharpening setting - case 0x0007: return _T("Nikon3.Focus");break; // Ascii Focus mode - case 0x0008: return _T("Nikon3.FlashSetting");break; // Ascii Flash setting - case 0x0009: return _T("Nikon3.FlashMode");break; // Ascii Flash mode - case 0x000b: return _T("Nikon3.WhiteBalanceBias");break; // SShort White balance bias - case 0x000e: return _T("Nikon3.ExposureDiff");break; // Undefined Exposure difference - case 0x000f: return _T("Nikon3.ISOSelection");break; // Ascii ISO selection - case 0x0010: return _T("Nikon3.DataDump");break; // Undefined Data dump - case 0x0011: return _T("Nikon3.ThumbOffset");break; // Long Thumbnail IFD offset - case 0x0012: return _T("Nikon3.FlashComp");break; // Undefined Flash compensation setting - case 0x0013: return _T("Nikon3.ISOSetting");break; // Short ISO speed setting - case 0x0016: return _T("Nikon3.ImageBoundary");break; // Short Image boundry - case 0x0018: return _T("Nikon3.FlashBracketComp");break; // Undefined Flash bracket compensation applied - case 0x0019: return _T("Nikon3.ExposureBracketComp");break; // SRational AE bracket compensation applied - case 0x0080: return _T("Nikon3.ImageAdjustment");break; // Ascii Image adjustment setting - case 0x0081: return _T("Nikon3.ToneComp");break; // Ascii Tone compensation setting (contrast) - case 0x0082: return _T("Nikon3.AuxiliaryLens");break; // Ascii Auxiliary lens (adapter) - case 0x0083: return _T("Nikon3.LensType");break; // Byte Lens type - case 0x0084: return _T("Nikon3.Lens");break; // Rational Lens - case 0x0085: return _T("Nikon3.FocusDistance");break; // Rational Manual focus distance - case 0x0086: return _T("Nikon3.DigitalZoom");break; // Rational Digital zoom setting - case 0x0087: return _T("Nikon3.FlashType");break; // Byte Type of flash used - case 0x0088: return _T("Nikon3.AFFocusPos");break; // Undefined AF focus position - case 0x0089: return _T("Nikon3.Bracketing");break; // Short Bracketing - case 0x008b: return _T("Nikon3.LensFStops");break; // Undefined Number of lens stops - case 0x008c: return _T("Nikon3.ToneCurve");break; // Undefined Tone curve - case 0x008d: return _T("Nikon3.ColorMode");break; // Ascii Color mode - case 0x008f: return _T("Nikon3.SceneMode");break; // Ascii Scene mode - case 0x0090: return _T("Nikon3.LightingType");break; // Ascii Lighting type - case 0x0092: return _T("Nikon3.HueAdjustment");break; // SShort Hue adjustment - case 0x0094: return _T("Nikon3.Saturation");break; // SShort Saturation adjustment - case 0x0095: return _T("Nikon3.NoiseReduction");break; // Ascii Noise reduction - case 0x0096: return _T("Nikon3.CompressionCurve");break; // Undefined Compression curve - case 0x0097: return _T("Nikon3.ColorBalance2");break; // Undefined Color balance 2 - case 0x0098: return _T("Nikon3.LensData");break; // Undefined Lens data - case 0x0099: return _T("Nikon3.NEFThumbnailSize");break; // Short NEF thumbnail size - case 0x009a: return _T("Nikon3.SensorPixelSize");break; // Rational Sensor pixel size - case 0x00a0: return _T("Nikon3.SerialNumber");break; // Ascii Camera serial number - case 0x00a7: return _T("Nikon3.ShutterCount");break; // Long Number of shots taken by camera - case 0x00a9: return _T("Nikon3.ImageOptimization");break; // Ascii Image optimization - case 0x00aa: return _T("Nikon3.Saturation");break; // Ascii Saturation - case 0x00ab: return _T("Nikon3.VariProgram");break; // Ascii Vari program - - default: - strTmp.Format(_T("Nikon3.0x%04X"),nTag); - bUnknown = true; - return strTmp; - break; - } - - } - } // NIKON - - } // if strSect - - bUnknown = true; - return _T("???"); -} - - -// Interpret the MakerNote header to determine any applicable MakerNote subtype. -// -// PRE: -// - m_strImgExifMake -// - buffer -// -// INPUT: -// - none -// -// RETURN: -// - Decode success -// -// POST: -// - m_nImgExifMakeSubtype -// -bool CjfifDecode::DecodeMakerSubType() -{ - CString strTmp; - - m_nImgExifMakeSubtype = 0; - - if (m_strImgExifMake == _T("NIKON")) - { - strTmp = _T(""); - for (unsigned nInd=0;nInd<5;nInd++) { - strTmp += Buf(m_nPos+nInd); - } - - if (strTmp == _T("Nikon")) { - if (Buf(m_nPos+6) == 1) { - // Type 1 - m_pLog->AddLine(_T(" Nikon Makernote Type 1 detected")); - m_nImgExifMakeSubtype = 1; - m_nPos += 8; - } else if (Buf(m_nPos+6) == 2) { - // Type 3 - m_pLog->AddLine(_T(" Nikon Makernote Type 3 detected")); - m_nImgExifMakeSubtype = 3; - m_nPos += 18; - } else { - strTmp = _T("ERROR: Unknown Nikon Makernote Type"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return FALSE; - } - } else { - // Type 2 - m_pLog->AddLine(_T(" Nikon Makernote Type 2 detected")); - //m_nImgExifMakeSubtype = 2; - // tests on D1 seem to indicate that it uses Type 1 headers - m_nImgExifMakeSubtype = 1; - m_nPos += 0; - } - - } - else if (m_strImgExifMake == _T("SIGMA")) - { - strTmp = _T(""); - for (unsigned ind=0;ind<8;ind++) { - if (Buf(m_nPos+ind) != 0) - strTmp += Buf(m_nPos+ind); - } - if ( (strTmp == _T("SIGMA")) || - (strTmp == _T("FOVEON")) ) - { - // Valid marker - // Now skip over the 8-chars and 2 unknown chars - m_nPos += 10; - } else { - strTmp = _T("ERROR: Unknown SIGMA Makernote identifier"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return FALSE; - } - - } // SIGMA - else if (m_strImgExifMake == _T("FUJIFILM")) - { - strTmp = _T(""); - for (unsigned ind=0;ind<8;ind++) { - if (Buf(m_nPos+ind) != 0) - strTmp += Buf(m_nPos+ind); - } - if (strTmp == _T("FUJIFILM")) - { - // Valid marker - // Now skip over the 8-chars and 4 Pointer chars - // FIXME: Do I need to dereference this pointer? - m_nPos += 12; - } else { - strTmp = _T("ERROR: Unknown FUJIFILM Makernote identifier"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return FALSE; - } - - } // FUJIFILM - else if (m_strImgExifMake == _T("SONY")) - { - strTmp = _T(""); - for (unsigned ind=0;ind<12;ind++) { - if (Buf(m_nPos+ind) != 0) - strTmp += Buf(m_nPos+ind); - } - if (strTmp == _T("SONY DSC ")) - { - // Valid marker - // Now skip over the 9-chars and 3 null chars - m_nPos += 12; - } else { - strTmp = _T("ERROR: Unknown SONY Makernote identifier"); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return FALSE; - } - - } // SONY - - - return TRUE; - -} - -// Read two UINT32 from the buffer (8B) and interpret -// as a rational entry. Convert to floating point. -// Byte swap as required -// -// INPUT: -// - pos Buffer position -// - val Floating point value -// -// RETURN: -// - Was the conversion successful? -// -bool CjfifDecode::DecodeValRational(unsigned nPos,float &nVal) -{ - int nValNumer; - int nValDenom; - nVal = 0; - - nValNumer = ByteSwap4(Buf(nPos+0),Buf(nPos+1),Buf(nPos+2),Buf(nPos+3)); - nValDenom = ByteSwap4(Buf(nPos+4),Buf(nPos+5),Buf(nPos+6),Buf(nPos+7)); - - if (nValDenom == 0) { - // Divide by zero! - return false; - } else { - nVal = (float)nValNumer/(float)nValDenom; - return true; - } -} - -// Read two UINT32 from the buffer (8B) to create a formatted -// fraction string. Byte swap as required -// -// INPUT: -// - pos Buffer position -// -// RETURN: -// - Formatted string -// -CString CjfifDecode::DecodeValFraction(unsigned nPos) -{ - CString strTmp; - int nValNumer = ReadSwap4(nPos+0); - int nValDenom = ReadSwap4(nPos+4); - strTmp.Format(_T("%d/%d"),nValNumer,nValDenom); - return strTmp; -} - - -// Convert multiple coordinates into a formatted GPS string -// -// INPUT: -// - nCount Number of coordinates (1,2,3) -// - fCoord1 Coordinate #1 -// - fCoord2 Coordinate #2 -// - fCoord3 Coordinate #3 -// -// OUTPUT: -// - strCoord The formatted GPS string -// -// RETURN: -// - Was the conversion successful? -// -bool CjfifDecode::PrintValGPS(unsigned nCount, float fCoord1, float fCoord2, float fCoord3,CString &strCoord) -{ - float fTemp; - unsigned nCoordDeg; - unsigned nCoordMin; - float fCoordSec; - - // TODO: Extend to support 1 & 2 coordinate GPS entries - if (nCount == 3) { - nCoordDeg = unsigned(fCoord1); - nCoordMin = unsigned(fCoord2); - if (fCoord3 == 0) { - fTemp = fCoord2 - (float)nCoordMin; - fCoordSec = fTemp * (float)60.0; - } else { - fCoordSec = fCoord3; - } - - strCoord.Format(_T("%u deg %u' %.3f\""),nCoordDeg,nCoordMin,fCoordSec); - return true; - } else { - strCoord.Format(_T("ERROR: Can't handle %u-comonent GPS coords"),nCount); - return false; - } - -} - -// Read in 3 rational values from the buffer and output as a formatted GPS string -// -// INPUT: -// - pos Buffer position -// -// OUTPUT: -// - strCoord The formatted GPS string -// -// RETURN: -// - Was the conversion successful? -// -bool CjfifDecode::DecodeValGPS(unsigned nPos,CString &strCoord) -{ - float fCoord1=0; - float fCoord2=0; - float fCoord3=0; - bool bRet; - - bRet = true; - if (bRet) { bRet = DecodeValRational(nPos,fCoord1); nPos += 8; } - if (bRet) { bRet = DecodeValRational(nPos,fCoord2); nPos += 8; } - if (bRet) { bRet = DecodeValRational(nPos,fCoord3); nPos += 8; } - - if (!bRet) { - strCoord.Format(_T("???")); - return false; - } else { - return PrintValGPS(3,fCoord1,fCoord2,fCoord3,strCoord); - } -} - -// Read a UINT16 from the buffer, byte swap as required -// -// INPUT: -// - nPos Buffer position -// -// RETURN: -// - UINT16 from buffer -// -unsigned CjfifDecode::ReadSwap2(unsigned nPos) -{ - return ByteSwap2(Buf(nPos+0),Buf(nPos+1)); -} - -// Read a UINT32 from the buffer, byte swap as required -// -// INPUT: -// - nPos Buffer position -// -// RETURN: -// - UINT32 from buffer -// -unsigned CjfifDecode::ReadSwap4(unsigned nPos) -{ - return ByteSwap4(Buf(nPos),Buf(nPos+1),Buf(nPos+2),Buf(nPos+3)); -} - -// Read a UINT32 from the buffer, force as big endian -// -// INPUT: -// - nPos Buffer position -// -// RETURN: -// - UINT32 from buffer -// -unsigned CjfifDecode::ReadBe4(unsigned nPos) -{ - // Big endian, no swap required - return (Buf(nPos)<<24) + (Buf(nPos+1)<<16) + (Buf(nPos+2)<<8) + Buf(nPos+3); -} - -// Print hex from array of unsigned char -// -// INPUT: -// - anBytes Array of unsigned chars -// - nCount Indicates the number of array entries originally specified -// but the printing routine limits it to the maximum array depth -// allocated (MAX_anValues) and add an ellipsis "..." -// RETURN: -// - A formatted string -// -CString CjfifDecode::PrintAsHexUC(unsigned char* anBytes,unsigned nCount) -{ - CString strVal; - CString strFull; - strFull = _T("0x["); - unsigned nMaxDisplay = MAX_anValues; - bool bExceedMaxDisplay; - bExceedMaxDisplay = (nCount > nMaxDisplay); - for (unsigned nInd=0;nInd nMaxDisplay); - for (unsigned nInd=0;nInd nMaxDisplay); - for (unsigned nInd=0;nIndAddLine(strTmp); - - //////////// - - // NOTE: Nikon type 3 starts out with the ASCII string "Nikon\0" - // before the rest of the items. - // TODO: need to process type1,type2,type3 - // see: http://www.gvsoft.homedns.org/exif/makernote-nikon.html - - strTmp.Format(_T("strIfd=[%s] m_strImgExifMake=[%s]"),(LPCTSTR)strIfd,(LPCTSTR)m_strImgExifMake); - DbgAddLine(strTmp); - - - // If this is the MakerNotes section, then we may want to skip - // altogether. Check to see if we are configured to process this - // section or if it is a supported manufacturer. - - if (strIfd == _T("MakerIFD")) - { - // Mark the image as containing Makernotes - m_bImgExifMakernotes = true; - - if (!m_pAppConfig->bDecodeMaker) { - strTmp.Format(_T(" Makernote decode option not enabled.")); - m_pLog->AddLine(strTmp); - - // If user didn't enable makernote decode, don't exit, just - // hide output. We still want to get at some info (such as Quality setting). - // At end, we'll need to re-enable it again. - m_pLog->Disable(); - } - - // If this Make is not supported, we'll need to exit - if (!m_bImgExifMakeSupported) { - strTmp.Format(_T(" Makernotes not yet supported for [%s]"),(LPCTSTR)m_strImgExifMake); - m_pLog->AddLine(strTmp); - - m_pLog->Enable(); - return 2; - } - - // Determine the sub-type of the Maker field (if applicable) - // and advance the m_nPos pointer past the custom header. - // This call uses the class members: Buf(),m_nPos - if (!DecodeMakerSubType()) - { - // If the subtype decode failed, skip the processing - m_pLog->Enable(); - return 2; - } - - } - - // ========================================================================== - // Process IFD directory entries - // ========================================================================== - - CString strIfdTag; - - // =========== EXIF IFD Header (Start) =========== - // - Defined in Exif 2.2 Standard (JEITA CP-3451) section 4.6.2 - // - Contents (2 bytes total) - // - Number of fields (2 bytes) - - nIfdDirLen = ReadSwap2(m_nPos); - m_nPos+=2; - strTmp.Format(_T(" Dir Length = 0x%04X"),nIfdDirLen); - m_pLog->AddLine(strTmp); - - // =========== EXIF IFD Header (End) =========== - - - // Start of IFD processing - // Step through each IFD entry and determine the type and - // decode accordingly. - for (unsigned nIfdEntryInd=0;nIfdEntryInd 4000) { - // Warn user that we have clippped the component list. - // Note that this condition is only relevant when we are - // processing the general array fields. Fields such as MakerNote - // will also enter this condition so we shouldn't warn in those cases. - // - // TODO: Defer this warning message until after we are sure that we - // didn't handle the large dataset elsewhere. - // For now, only report this warning if we are not processing MakerNote - if (strIfdTag.Compare(_T("MakerNote"))!=0) { - strTmp.Format(_T(" Excessive # components (%u). Limiting to first 4000."),nIfdNumComps); - m_pLog->AddLineWarn(strTmp); - } - nIfdNumComps = 4000; - } - - // Read Component Value / Offset - // We first treat it as a string and then re-interpret it as an integer - - // ... first as a string (just in case length <=4) - for (unsigned i=0;i<4;i++) { - acIfdValOffsetStr[i] = Buf(m_nPos+i); - } - acIfdValOffsetStr[4] = '\0'; - - // ... now as an unsigned value - // This assignment is general-purpose, typically used when - // we know that the IFD Value/Offset is just an offset - nIfdOffset = ReadSwap4(m_nPos); - strTmp.Format(_T(" # Val/Offset = 0x%08X"),nIfdOffset); - DbgAddLine(strTmp); - - // =========== EXIF IFD Interoperability entry (End) =========== - - - // ========================================================================== - // Extract the IFD component entries - // ========================================================================== - - // The EXIF IFD entries can appear in a wide range of - // formats / data types. The formats that have been - // publicly documented include: - // EXIF_FORMAT_BYTE = 1, - // EXIF_FORMAT_ASCII = 2, - // EXIF_FORMAT_SHORT = 3, - // EXIF_FORMAT_LONG = 4, - // EXIF_FORMAT_RATIONAL = 5, - // EXIF_FORMAT_SBYTE = 6, - // EXIF_FORMAT_UNDEFINED = 7, - // EXIF_FORMAT_SSHORT = 8, - // EXIF_FORMAT_SLONG = 9, - // EXIF_FORMAT_SRATIONAL = 10, - // EXIF_FORMAT_FLOAT = 11, - // EXIF_FORMAT_DOUBLE = 12 - - // The IFD variable formatter logic operates in two stages: - // In the first stage, the format type is decoded, which results - // in a generic decode for the IFD entry. Then, we start a second - // stage which re-interprets the values for a number of known - // special types. - - switch(nIfdFormat) - { - - // ---------------------------------------- - // --- IFD Entry Type: Unsigned Byte - // ---------------------------------------- - case 1: - strFull = _T(" Unsigned Byte=["); - strValOut = _T(""); - - // Limit display output - nCompsToDisplay = min(MAX_anValues,nIfdNumComps); - - // If only a single value, use decimal, else use hex - if (nIfdNumComps == 1) { - anValues[0] = Buf(m_nPos+0); - strTmp.Format(_T("%u"),anValues[0]); - strValOut += strTmp; - } else { - for (unsigned nInd=0;nInd MAX_IFD_COMPS) { - strValTmp.Format(_T(" Unsigned Short=[Too many entries (%u) to display]"),nIfdNumComps); - DbgAddLine(strValTmp); - strValOut.Format(_T("[Too many entries (%u) to display]"),nIfdNumComps); - } else { - // Try to handle multiple entries... note that this - // is used by the Maker notes IFD decode - - strValOut = _T(""); - strFull = _T(" Unsigned Short=["); - for (unsigned nInd=0;nInd MAX_IFD_COMPS) { - // Only print it out if it has less than MAX_IFD_COMPS entries - strValTmp.Format(_T(" Signed Short=[Too many entries (%u) to display]"),nIfdNumComps); - DbgAddLine(strValTmp); - strValOut.Format(_T("[Too many entries (%u) to display]"),nIfdNumComps); - } else { - // Try to handle multiple entries... note that this - // is used by the Maker notes IFD decode - - // Note that we don't call LookupMakerCanonTag() here - // as that is only needed for the "unsigned short", not - // "signed short". - strValOut = _T(""); - strFull = _T(" Signed Short=["); - for (unsigned nInd=0;nIndEnable(); - return 2; - break; - } // switch nIfdTagVal - - - - // ========================================================================== - // Custom Value String decodes - // ========================================================================== - - // At this point we might re-format the values, thereby - // overriding the default strValOut. We have access to the - // anValues[] (array of unsigned int) - // anValuesS[] (array of signed int) - // afValues[] (array of float) - - // Re-format special output items - // This will override "strValOut" that may have previously been defined - - if ((strIfdTag == _T("GPSLatitude")) || - (strIfdTag == _T("GPSLongitude"))) { - bRet = PrintValGPS(nIfdNumComps,afValues[0],afValues[1],afValues[2],strValOut); - } else if (strIfdTag == _T("GPSVersionID")) { - strValOut.Format(_T("%u.%u.%u.%u"),anValues[0],anValues[1],anValues[2],anValues[3]); - } else if (strIfdTag == _T("GPSAltitudeRef")) { - switch (anValues[0]) { - case 0 : strValOut = _T("Above Sea Level"); break; - case 1 : strValOut = _T("Below Sea Level"); break; - } - } else if (strIfdTag == _T("GPSStatus")) { - switch (acIfdValOffsetStr[0]) { - case 'A' : strValOut = _T("Measurement in progress"); break; - case 'V' : strValOut = _T("Measurement Interoperability"); break; - } - } else if (strIfdTag == _T("GPSMeasureMode")) { - switch (acIfdValOffsetStr[0]) { - case '2' : strValOut = _T("2-dimensional"); break; - case '3' : strValOut = _T("3-dimensional"); break; - } - } else if ((strIfdTag == _T("GPSSpeedRef")) || - (strIfdTag == _T("GPSDestDistanceRef"))) { - switch (acIfdValOffsetStr[0]) { - case 'K' : strValOut = _T("km/h"); break; - case 'M' : strValOut = _T("mph"); break; - case 'N' : strValOut = _T("knots"); break; - } - } else if ((strIfdTag == _T("GPSTrackRef")) || - (strIfdTag == _T("GPSImgDirectionRef")) || - (strIfdTag == _T("GPSDestBearingRef"))) { - switch (acIfdValOffsetStr[0]) { - case 'T' : strValOut = _T("True direction"); break; - case 'M' : strValOut = _T("Magnetic direction"); break; - } - } else if (strIfdTag == _T("GPSDifferential")) { - switch (anValues[0]) { - case 0 : strValOut = _T("Measurement without differential correction"); break; - case 1 : strValOut = _T("Differential correction applied"); break; - } - } else if (strIfdTag == _T("GPSAltitude")) { - strValOut.Format(_T("%.3f m"),afValues[0]); - } else if (strIfdTag == _T("GPSSpeed")) { - strValOut.Format(_T("%.3f"),afValues[0]); - } else if (strIfdTag == _T("GPSTimeStamp")) { - strValOut.Format(_T("%.0f:%.0f:%.2f"),afValues[0],afValues[1],afValues[2]); - } else if (strIfdTag == _T("GPSTrack")) { - strValOut.Format(_T("%.2f"),afValues[0]); - } else if (strIfdTag == _T("GPSDOP")) { - strValOut.Format(_T("%.4f"),afValues[0]); - } - - - if (strIfdTag == _T("Compression")) { - switch (anValues[0]) { - case 1 : strValOut = _T("None"); break; - case 6 : strValOut = _T("JPEG"); break; - } - } else if (strIfdTag == _T("ExposureTime")) { - // Assume only one - strValTmp = strValOut; - strValOut.Format(_T("%s s"),(LPCTSTR)strValTmp); - } else if (strIfdTag == _T("FNumber")) { - // Assume only one - strValOut.Format(_T("F%.1f"),afValues[0]); - } else if (strIfdTag == _T("FocalLength")) { - // Assume only one - strValOut.Format(_T("%.0f mm"),afValues[0]); - } else if (strIfdTag == _T("ExposureBiasValue")) { - // Assume only one - // TODO: Need to test negative numbers - strValOut.Format(_T("%0.2f eV"),afValues[0]); - } else if (strIfdTag == _T("ExifVersion")) { - // Assume only one - strValOut.Format(_T("%c%c.%c%c"),anValues[0],anValues[1],anValues[2],anValues[3]); - } else if (strIfdTag == _T("FlashPixVersion")) { - // Assume only one - strValOut.Format(_T("%c%c.%c%c"),anValues[0],anValues[1],anValues[2],anValues[3]); - } else if (strIfdTag == _T("PhotometricInterpretation")) { - switch (anValues[0]) { - case 1 : strValOut = _T("Monochrome"); break; - case 2 : strValOut = _T("RGB"); break; - case 6 : strValOut = _T("YCbCr"); break; - } - } else if (strIfdTag == _T("Orientation")) { - switch (anValues[0]) { - case 1 : strValOut = _T("1 = Row 0: top, Col 0: left"); break; - case 2 : strValOut = _T("2 = Row 0: top, Col 0: right"); break; - case 3 : strValOut = _T("3 = Row 0: bottom, Col 0: right"); break; - case 4 : strValOut = _T("4 = Row 0: bottom, Col 0: left"); break; - case 5 : strValOut = _T("5 = Row 0: left, Col 0: top"); break; - case 6 : strValOut = _T("6 = Row 0: right, Col 0: top"); break; - case 7 : strValOut = _T("7 = Row 0: right, Col 0: bottom"); break; - case 8 : strValOut = _T("8 = Row 0: left, Col 0: bottom"); break; - } - } else if (strIfdTag == _T("PlanarConfiguration")) { - switch (anValues[0]) { - case 1 : strValOut = _T("Chunky format"); break; - case 2 : strValOut = _T("Planar format"); break; - } - } else if (strIfdTag == _T("YCbCrSubSampling")) { - switch (anValues[0]*65536 + anValues[1]) { - case 0x00020001 : strValOut = _T("4:2:2"); break; - case 0x00020002 : strValOut = _T("4:2:0"); break; - } - } else if (strIfdTag == _T("YCbCrPositioning")) { - switch (anValues[0]) { - case 1 : strValOut = _T("Centered"); break; - case 2 : strValOut = _T("Co-sited"); break; - } - } else if (strIfdTag == _T("ResolutionUnit")) { - switch (anValues[0]) { - case 1 : strValOut = _T("None"); break; - case 2 : strValOut = _T("Inch"); break; - case 3 : strValOut = _T("Centimeter"); break; - } - } else if (strIfdTag == _T("FocalPlaneResolutionUnit")) { - switch (anValues[0]) { - case 1 : strValOut = _T("None"); break; - case 2 : strValOut = _T("Inch"); break; - case 3 : strValOut = _T("Centimeter"); break; - } - } else if (strIfdTag == _T("ColorSpace")) { - switch (anValues[0]) { - case 1 : strValOut = _T("sRGB"); break; - case 0xFFFF : strValOut = _T("Uncalibrated"); break; - } - } else if (strIfdTag == _T("ComponentsConfiguration")) { - // Undefined type, assume 4 bytes - strValOut = _T("["); - for (unsigned vind=0;vind<4;vind++) { - if (vind != 0) { strValOut += _T(" "); } - switch (anValues[vind]) { - case 0 : strValOut += _T("."); break; - case 1 : strValOut += _T("Y"); break; - case 2 : strValOut += _T("Cb"); break; - case 3 : strValOut += _T("Cr"); break; - case 4 : strValOut += _T("R"); break; - case 5 : strValOut += _T("G"); break; - case 6 : strValOut += _T("B"); break; - default : strValOut += _T("?"); break; - } - } - strValOut += _T("]"); - - } else if ( (strIfdTag == _T("XPTitle")) || - (strIfdTag == _T("XPComment")) || - (strIfdTag == _T("XPAuthor")) || - (strIfdTag == _T("XPKeywords")) || - (strIfdTag == _T("XPSubject")) ) { - strValOut = _T("\""); - CString strVal; - strVal = m_pWBuf->BufReadUniStr2(nPosExifStart+nIfdOffset,nIfdNumComps); - strValOut += strVal; - strValOut += _T("\""); - - } else if (strIfdTag == _T("UserComment")) { - // Character code - unsigned anCharCode[8]; - for (unsigned vInd=0;vInd<8;vInd++) { - anCharCode[vInd] = Buf(nPosExifStart+nIfdOffset+0+vInd); - } - // Actual string - strValOut = _T("\""); - bool bDone = false; - unsigned char cTmp; - - for (unsigned vInd=0;(vIndAddLine(strLine); - } - } - - } - - - if ((strIfd == _T("InteropIFD")) && (strIfdTag == _T("InteroperabilityVersion"))) { - // Assume only one - strValOut.Format(_T("%c%c.%c%c"),anValues[0],anValues[1],anValues[2],anValues[3]); - } - - - // ========================================================================== - - // ---------------------------------------- - // Handle certain MakerNotes - // For Canon, we have a special parser routine to handle these - // ---------------------------------------- - if (strIfd == _T("MakerIFD")) { - - if ((m_strImgExifMake == _T("Canon")) && (nIfdFormat == 3) && (nIfdNumComps > 4)) { - // Print summary line now, before sub details - // Disable later summary line - bExtraDecode = TRUE; - if ((!m_pAppConfig->bExifHideUnknown) || (!nIfdTagUnknown)) { - strTmp.Format(_T(" [%-36s]"),(LPCTSTR)strIfdTag); - m_pLog->AddLine(strTmp); - - // Assume it is a maker field with subentries! - - for (unsigned ind=0;indbExifHideUnknown) || (!strRetVal.bUnknown)) { - m_pLog->AddLine(strValTmp); - } - } else if (ind == MAX_anValues) { - m_pLog->AddLine(_T(" [... etc ...]")); - } else { - // Don't print! - } - } - } - - - strValOut = _T("..."); - } - - // For Nikon & Sigma, we simply support the quality field - if ( (strIfdTag=="Nikon1.Quality") || - (strIfdTag=="Nikon2.Quality") || - (strIfdTag=="Nikon3.Quality") || - (strIfdTag=="Sigma.Quality") ) - { - m_strImgQualExif = strValOut; - - // Collect extra details (for later DB submission) - strTmp = _T(""); - strTmp.Format(_T("[%s]:[%s],"),(LPCTSTR)strIfdTag,(LPCTSTR)strValOut); - m_strImgExtras += strTmp; - } - - // Collect extra details (for later DB submission) - if (strIfdTag==_T("Canon.ImageType")) { - strTmp = _T(""); - strTmp.Format(_T("[%s]:[%s],"),(LPCTSTR)strIfdTag,(LPCTSTR)strValOut); - m_strImgExtras += strTmp; - } - } - - // ---------------------------------------- - - // Now extract some of the important offsets / pointers - if ((strIfd == _T("IFD0")) && (strIfdTag == _T("ExifOffset"))) { - // EXIF SubIFD - Pointer - m_nImgExifSubIfdPtr = nIfdOffset; - strValOut.Format(_T("@ 0x%04X"),nIfdOffset); - } - - if ((strIfd == _T("IFD0")) && (strIfdTag == _T("GPSOffset"))) { - // GPS SubIFD - Pointer - m_nImgExifGpsIfdPtr = nIfdOffset; - strValOut.Format(_T("@ 0x%04X"),nIfdOffset); - } - - // TODO: Add Interoperability IFD (0xA005)? - if ((strIfd == _T("SubIFD")) && (strIfdTag == _T("ExifInteroperabilityOffset"))) { - m_nImgExifInteropIfdPtr = nIfdOffset; - strValOut.Format(_T("@ 0x%04X"),nIfdOffset); - } - - // Extract software field - if ((strIfd == _T("IFD0")) && (strIfdTag == _T("Software"))) { - m_strSoftware = strValOut; - } - - // ------------------------- - // IFD0 - ExifMake - // ------------------------- - if ((strIfd == _T("IFD0")) && (strIfdTag == _T("Make"))) { - m_strImgExifMake = strValOut; - m_strImgExifMake.Trim(); // Trim whitespace (e.g. Pentax) - - } - - // ------------------------- - // IFD0 - ExifModel - // ------------------------- - if ((strIfd == _T("IFD0")) && (strIfdTag == _T("Model"))) { - m_strImgExifModel= strValOut; - m_strImgExifModel.Trim(); - } - - - if ((strIfd == _T("SubIFD")) && (strIfdTag == _T("MakerNote"))) { - // Maker IFD - Pointer - m_nImgExifMakerPtr = nIfdOffset; - strValOut.Format(_T("@ 0x%04X"),nIfdOffset); - } - - - // ------------------------- - // IFD1 - Embedded Thumbnail - // ------------------------- - if ((strIfd == _T("IFD1")) && (strIfdTag == _T("Compression"))) { - // Embedded thumbnail, compression format - m_nImgExifThumbComp = ReadSwap4(m_nPos); - } - if ((strIfd == _T("IFD1")) && (strIfdTag == _T("JpegIFOffset"))) { - // Embedded thumbnail, offset - m_nImgExifThumbOffset = nIfdOffset + nPosExifStart; - strValOut.Format(_T("@ +0x%04X = @ 0x%04X"),nIfdOffset,m_nImgExifThumbOffset); - } - if ((strIfd == _T("IFD1")) && (strIfdTag == _T("JpegIFByteCount"))) { - // Embedded thumbnail, length - m_nImgExifThumbLen = ReadSwap4(m_nPos); - } - - - // ========================================================================== - // Determine MakerNote support - // ========================================================================== - - if (m_strImgExifMake != _T("")) { - // 1) Identify the supported MakerNotes - // 2) Remap variations of the Maker field (e.g. Nikon) - // as some manufacturers have been inconsistent in their - // use of the Make field - - m_bImgExifMakeSupported = FALSE; - if (m_strImgExifMake == _T("Canon")) { - m_bImgExifMakeSupported = TRUE; - } - else if (m_strImgExifMake == _T("PENTAX Corporation")) { - m_strImgExifMake = _T("PENTAX"); - } - else if (m_strImgExifMake == _T("NIKON CORPORATION")) { - m_strImgExifMake = _T("NIKON"); - m_bImgExifMakeSupported = TRUE; - } - else if (m_strImgExifMake == _T("NIKON")) { - m_strImgExifMake = _T("NIKON"); - m_bImgExifMakeSupported = TRUE; - } - else if (m_strImgExifMake == _T("SIGMA")) { - m_bImgExifMakeSupported = TRUE; - } - else if (m_strImgExifMake == _T("SONY")) { - m_bImgExifMakeSupported = TRUE; - } - else if (m_strImgExifMake == _T("FUJIFILM")) { - // TODO: - // FUJIFILM Maker notes apparently use - // big endian format even though main section uses little. - // Need to switch if in maker section for FUJI - // For now, disable support - m_bImgExifMakeSupported = FALSE; - } - } - - // Now advance the m_nPos ptr as we have finished with valoffset - m_nPos+=4; - - - // ========================================================================== - // SUMMARY REPORT - // ========================================================================== - - // If we haven't already output a detailed decode of this field - // then we can output the generic representation here - if (!bExtraDecode) - { - // Provide option to skip unknown fields - if ((!m_pAppConfig->bExifHideUnknown) || (!nIfdTagUnknown)) { - - // If the tag is an ASCII string, we want to wrap with quote marks - if (nIfdFormat == 2) { - strTmp.Format(_T(" [%-36s] = \"%s\""),(LPCTSTR)strIfdTag,(LPCTSTR)strValOut); - } else { - strTmp.Format(_T(" [%-36s] = %s"),(LPCTSTR)strIfdTag,(LPCTSTR)strValOut); - } - m_pLog->AddLine(strTmp); - - } - } - - DbgAddLine(_T("")); - - } // for nIfdEntryInd - - - // =========== EXIF IFD (End) =========== - // - Defined in Exif 2.2 Standard (JEITA CP-3451) section 4.6.2 - // - Is completed by 4-byte offset to next IFD, which is - // read in next iteration. - - m_pLog->Enable(); - return 0; -} - - -// Handle APP13 marker -// This includes: -// - Photoshop "Save As" and "Save for Web" quality settings -// - IPTC entries -// PRE: -// - m_nPos -// POST: -// - m_nImgQualPhotoshopSa -unsigned CjfifDecode::DecodeApp13Ps() -{ - // Photoshop APP13 marker definition doesn't appear to have a - // well-defined length, so I will read until I encounter a - // non-"8BIM" entry, then we reset the position counter - // and move on to the next marker. - // FIXME: This does not appear to be very robust - - CString strTmp; - CString strBimName; - bool bDone = false; - - //unsigned nVal = 0x8000; - - CString strVal; - CString strByte; - - CString strBimSig; - - // Reset PsDec decoder state - m_pPsDec->Reset(); - - while (!bDone) - { - // FIXME: Need to check for actual marker section extent, not - // just the lack of an 8BIM signature as the terminator! - - // Check the signature but don't advance the file pointer - strBimSig = m_pWBuf->BufReadStrn(m_nPos,4); - // Check for signature "8BIM" - if (strBimSig == _T("8BIM")) { - m_pPsDec->PhotoshopParseImageResourceBlock(m_nPos,3); - } else { - // Not 8BIM? - bDone = true; - } - } - - // Now that we've finished with the PsDec decoder we can fetch - // some of the parser state - // TODO: Migrate into accessor - m_nImgQualPhotoshopSa = m_pPsDec->m_nQualitySaveAs; - m_nImgQualPhotoshopSfw = m_pPsDec->m_nQualitySaveForWeb; - m_bPsd = m_pPsDec->m_bPsd; - - return 0; -} - - -// Start decoding a single ICC header segment @ nPos -unsigned CjfifDecode::DecodeIccHeader(unsigned nPos) -{ - CString strTmp,strTmp1; - - // Profile header - unsigned nProfSz; - unsigned nPrefCmmType; - unsigned nProfVer; - unsigned nProfDevClass; - unsigned nDataColorSpace; - unsigned nPcs; - unsigned anDateTimeCreated[3]; - unsigned nProfFileSig; - unsigned nPrimPlatSig; - unsigned nProfFlags; - unsigned nDevManuf; - unsigned nDevModel; - unsigned anDevAttrib[2]; - unsigned nRenderIntent; - unsigned anIllumPcsXyz[3]; - unsigned nProfCreatorSig; - unsigned anProfId[4]; - unsigned anRsvd[7]; - - // Read in all of the ICC header bytes - nProfSz = ReadBe4(nPos);nPos+=4; - nPrefCmmType = ReadBe4(nPos);nPos+=4; - nProfVer = ReadBe4(nPos);nPos+=4; - nProfDevClass = ReadBe4(nPos);nPos+=4; - nDataColorSpace = ReadBe4(nPos);nPos+=4; - nPcs = ReadBe4(nPos);nPos+=4; - anDateTimeCreated[2] = ReadBe4(nPos);nPos+=4; - anDateTimeCreated[1] = ReadBe4(nPos);nPos+=4; - anDateTimeCreated[0] = ReadBe4(nPos);nPos+=4; - nProfFileSig = ReadBe4(nPos);nPos+=4; - nPrimPlatSig = ReadBe4(nPos);nPos+=4; - nProfFlags = ReadBe4(nPos);nPos+=4; - nDevManuf = ReadBe4(nPos);nPos+=4; - nDevModel = ReadBe4(nPos);nPos+=4; - anDevAttrib[1] = ReadBe4(nPos);nPos+=4; - anDevAttrib[0] = ReadBe4(nPos);nPos+=4; - nRenderIntent = ReadBe4(nPos);nPos+=4; - anIllumPcsXyz[2] = ReadBe4(nPos);nPos+=4; - anIllumPcsXyz[1] = ReadBe4(nPos);nPos+=4; - anIllumPcsXyz[0] = ReadBe4(nPos);nPos+=4; - nProfCreatorSig = ReadBe4(nPos);nPos+=4; - anProfId[3] = ReadBe4(nPos);nPos+=4; - anProfId[2] = ReadBe4(nPos);nPos+=4; - anProfId[1] = ReadBe4(nPos);nPos+=4; - anProfId[0] = ReadBe4(nPos);nPos+=4; - anRsvd[6] = ReadBe4(nPos);nPos+=4; - anRsvd[5] = ReadBe4(nPos);nPos+=4; - anRsvd[4] = ReadBe4(nPos);nPos+=4; - anRsvd[3] = ReadBe4(nPos);nPos+=4; - anRsvd[2] = ReadBe4(nPos);nPos+=4; - anRsvd[1] = ReadBe4(nPos);nPos+=4; - anRsvd[0] = ReadBe4(nPos);nPos+=4; - - // Now output the formatted version of the above data structures - strTmp.Format(_T(" %-33s : %u bytes"),_T("Profile Size"),nProfSz); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" %-33s : %s"),_T("Preferred CMM Type"),(LPCTSTR)Uint2Chars(nPrefCmmType)); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" %-33s : %u.%u.%u.%u (0x%08X)"),_T("Profile Version"), - ((nProfVer & 0xF0000000)>>28), - ((nProfVer & 0x0F000000)>>24), - ((nProfVer & 0x00F00000)>>20), - ((nProfVer & 0x000F0000)>>16), - nProfVer); - m_pLog->AddLine(strTmp); - - switch (nProfDevClass) { - case 'scnr': - strTmp1.Format(_T("Input Device profile"));break; - case 'mntr': - strTmp1.Format(_T("Display Device profile"));break; - case 'prtr': - strTmp1.Format(_T("Output Device profile"));break; - case 'link': - strTmp1.Format(_T("DeviceLink Device profile"));break; - case 'spac': - strTmp1.Format(_T("ColorSpace Conversion profile"));break; - case 'abst': - strTmp1.Format(_T("Abstract profile"));break; - case 'nmcl': - strTmp1.Format(_T("Named colour profile"));break; - default: - strTmp1.Format(_T("? (0x%08X)"),nProfDevClass); - break; - } - strTmp.Format(_T(" %-33s : %s (%s)"),_T("Profile Device/Class"),(LPCTSTR)strTmp1,(LPCTSTR)Uint2Chars(nProfDevClass)); - m_pLog->AddLine(strTmp); - - switch (nDataColorSpace) { - case 'XYZ ': - strTmp1.Format(_T("XYZData"));break; - case 'Lab ': - strTmp1.Format(_T("labData"));break; - case 'Luv ': - strTmp1.Format(_T("lubData"));break; - case 'YCbr': - strTmp1.Format(_T("YCbCrData"));break; - case 'Yxy ': - strTmp1.Format(_T("YxyData"));break; - case 'RGB ': - strTmp1.Format(_T("rgbData"));break; - case 'GRAY': - strTmp1.Format(_T("grayData"));break; - case 'HSV ': - strTmp1.Format(_T("hsvData"));break; - case 'HLS ': - strTmp1.Format(_T("hlsData"));break; - case 'CMYK': - strTmp1.Format(_T("cmykData"));break; - case 'CMY ': - strTmp1.Format(_T("cmyData"));break; - case '2CLR': - strTmp1.Format(_T("2colourData"));break; - case '3CLR': - strTmp1.Format(_T("3colourData"));break; - case '4CLR': - strTmp1.Format(_T("4colourData"));break; - case '5CLR': - strTmp1.Format(_T("5colourData"));break; - case '6CLR': - strTmp1.Format(_T("6colourData"));break; - case '7CLR': - strTmp1.Format(_T("7colourData"));break; - case '8CLR': - strTmp1.Format(_T("8colourData"));break; - case '9CLR': - strTmp1.Format(_T("9colourData"));break; - case 'ACLR': - strTmp1.Format(_T("10colourData"));break; - case 'BCLR': - strTmp1.Format(_T("11colourData"));break; - case 'CCLR': - strTmp1.Format(_T("12colourData"));break; - case 'DCLR': - strTmp1.Format(_T("13colourData"));break; - case 'ECLR': - strTmp1.Format(_T("14colourData"));break; - case 'FCLR': - strTmp1.Format(_T("15colourData"));break; - default: - strTmp1.Format(_T("? (0x%08X)"),nDataColorSpace); - break; - } - strTmp.Format(_T(" %-33s : %s (%s)"),_T("Data Colour Space"),(LPCTSTR)strTmp1,(LPCTSTR)Uint2Chars(nDataColorSpace)); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" %-33s : %s"),_T("Profile connection space (PCS)"),(LPCTSTR)Uint2Chars(nPcs)); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" %-33s : %s"),_T("Profile creation date"),(LPCTSTR)DecodeIccDateTime(anDateTimeCreated)); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" %-33s : %s"),_T("Profile file signature"),(LPCTSTR)Uint2Chars(nProfFileSig)); - m_pLog->AddLine(strTmp); - - switch (nPrimPlatSig) { - case 'APPL': - strTmp1.Format(_T("Apple Computer, Inc."));break; - case 'MSFT': - strTmp1.Format(_T("Microsoft Corporation"));break; - case 'SGI ': - strTmp1.Format(_T("Silicon Graphics, Inc."));break; - case 'SUNW': - strTmp1.Format(_T("Sun Microsystems, Inc."));break; - default: - strTmp1.Format(_T("? (0x%08X)"),nPrimPlatSig); - break; - } - strTmp.Format(_T(" %-33s : %s (%s)"),_T("Primary platform"),(LPCTSTR)strTmp1,(LPCTSTR)Uint2Chars(nPrimPlatSig)); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" %-33s : 0x%08X"),_T("Profile flags"),nProfFlags); - m_pLog->AddLine(strTmp); - strTmp1 = (TestBit(nProfFlags,0))?"Embedded profile":"Profile not embedded"; - strTmp.Format(_T(" %-35s > %s"),_T("Profile flags"),(LPCTSTR)strTmp1); - m_pLog->AddLine(strTmp); - strTmp1 = (TestBit(nProfFlags,1))?"Profile can be used independently of embedded":"Profile can't be used independently of embedded"; - strTmp.Format(_T(" %-35s > %s"),_T("Profile flags"),(LPCTSTR)strTmp1); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" %-33s : %s"),_T("Device Manufacturer"),(LPCTSTR)Uint2Chars(nDevManuf)); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" %-33s : %s"),_T("Device Model"),(LPCTSTR)Uint2Chars(nDevModel)); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" %-33s : 0x%08X_%08X"),_T("Device attributes"),anDevAttrib[1],anDevAttrib[0]); - m_pLog->AddLine(strTmp); - strTmp1 = (TestBit(anDevAttrib[0],0))?"Transparency":"Reflective"; - strTmp.Format(_T(" %-35s > %s"),_T("Device attributes"),(LPCTSTR)strTmp1); - m_pLog->AddLine(strTmp); - strTmp1 = (TestBit(anDevAttrib[0],1))?"Matte":"Glossy"; - strTmp.Format(_T(" %-35s > %s"),_T("Device attributes"),(LPCTSTR)strTmp1); - m_pLog->AddLine(strTmp); - strTmp1 = (TestBit(anDevAttrib[0],2))?"Media polarity = positive":"Media polarity = negative"; - strTmp.Format(_T(" %-35s > %s"),_T("Device attributes"),(LPCTSTR)strTmp1); - m_pLog->AddLine(strTmp); - strTmp1 = (TestBit(anDevAttrib[0],3))?"Colour media":"Black & white media"; - strTmp.Format(_T(" %-35s > %s"),_T("Device attributes"),(LPCTSTR)strTmp1); - m_pLog->AddLine(strTmp); - - switch(nRenderIntent) { - case 0x00000000: strTmp1.Format(_T("Perceptual"));break; - case 0x00000001: strTmp1.Format(_T("Media-Relative Colorimetric"));break; - case 0x00000002: strTmp1.Format(_T("Saturation"));break; - case 0x00000003: strTmp1.Format(_T("ICC-Absolute Colorimetric"));break; - default: - strTmp1.Format(_T("0x%08X"),nRenderIntent); - break; - } - strTmp.Format(_T(" %-33s : %s"),_T("Rendering intent"),(LPCTSTR)strTmp1); - m_pLog->AddLine(strTmp); - - // PCS illuminant - - strTmp.Format(_T(" %-33s : %s"),_T("Profile creator"),(LPCTSTR)Uint2Chars(nProfCreatorSig)); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" %-33s : 0x%08X_%08X_%08X_%08X"),_T("Profile ID"), - anProfId[3],anProfId[2],anProfId[1],anProfId[0]); - m_pLog->AddLine(strTmp); - - return 0; -} - -// Provide special output formatter for ICC Date/Time -// NOTE: It appears that the nParts had to be decoded in the -// reverse order from what I had expected, so one should -// confirm that the byte order / endianness is appropriate. -CString CjfifDecode::DecodeIccDateTime(unsigned anVal[3]) -{ - CString strDate; - unsigned short anParts[6]; - anParts[0] = (anVal[2] & 0xFFFF0000) >> 16; // Year - anParts[1] = (anVal[2] & 0x0000FFFF); // Mon - anParts[2] = (anVal[1] & 0xFFFF0000) >> 16; // Day - anParts[3] = (anVal[1] & 0x0000FFFF); // Hour - anParts[4] = (anVal[0] & 0xFFFF0000) >> 16; // Min - anParts[5] = (anVal[0] & 0x0000FFFF); // Sec - strDate.Format(_T("%04u-%02u-%02u %02u:%02u:%02u"), - anParts[0],anParts[1],anParts[2],anParts[3],anParts[4],anParts[5]); - return strDate; -} - - -// Parser for APP2 ICC profile marker -unsigned CjfifDecode::DecodeApp2IccProfile(unsigned nLen) -{ - CString strTmp; - unsigned nMarkerSeqNum; // Byte - unsigned nNumMarkers; // Byte - unsigned nPayloadLen; // Len of this ICC marker payload - - unsigned nMarkerPosStart; - - nMarkerSeqNum = Buf(m_nPos++); - nNumMarkers = Buf(m_nPos++); - nPayloadLen = nLen - 2 - 12 - 2; // TODO: check? - - strTmp.Format(_T(" Marker Number = %u of %u"),nMarkerSeqNum,nNumMarkers); - m_pLog->AddLine(strTmp); - - if (nMarkerSeqNum == 1) { - nMarkerPosStart = m_nPos; - DecodeIccHeader(nMarkerPosStart); - } else { - m_pLog->AddLineWarn(_T(" Only support decode of 1st ICC Marker")); - } - - return 0; -} - -// Parser for APP2 FlashPix marker -unsigned CjfifDecode::DecodeApp2Flashpix() -{ - - CString strTmp; - - unsigned nFpxVer; - unsigned nFpxSegType; - unsigned nFpxInteropCnt; - unsigned nFpxEntitySz; - unsigned nFpxDefault; - - bool bFpxStorage; - CString strFpxStorageClsStr; - unsigned nFpxStIndexCont; - unsigned nFpxStOffset; - - unsigned nFpxStWByteOrder; - unsigned nFpxStWFormat; - CString strFpxStClsidStr; - unsigned nFpxStDwOsVer; - unsigned nFpxStRsvd; - - CString streamStr; - - nFpxVer = Buf(m_nPos++); - nFpxSegType = Buf(m_nPos++); - - // FlashPix segments: Contents List or Stream Data - - if (nFpxSegType == 1) { - // Contents List - strTmp.Format(_T(" Segment: CONTENTS LIST")); - m_pLog->AddLine(strTmp); - - nFpxInteropCnt = (Buf(m_nPos++)<<8) + Buf(m_nPos++); - strTmp.Format(_T(" Interoperability Count = %u"),nFpxInteropCnt); - m_pLog->AddLine(strTmp); - - for (unsigned ind=0;indAddLine(strTmp); - nFpxEntitySz = (Buf(m_nPos++)<<24) + (Buf(m_nPos++)<<16) + (Buf(m_nPos++)<<8) + Buf(m_nPos++); - - // If the "entity size" field is 0xFFFFFFFF, then it should be treated as - // a "storage". It looks like we should probably be using this to determine - // that we have a "storage" - bFpxStorage = false; - if (nFpxEntitySz == 0xFFFFFFFF) { - bFpxStorage = true; - } - - if (!bFpxStorage) { - strTmp.Format(_T(" Entity Size = %u"),nFpxEntitySz); - m_pLog->AddLine(strTmp); - } else { - strTmp.Format(_T(" Entity is Storage")); - m_pLog->AddLine(strTmp); - } - - nFpxDefault = Buf(m_nPos++); - - - // BUG: #1112 - //streamStr = m_pWBuf->BufReadUniStr(m_nPos); - streamStr = m_pWBuf->BufReadUniStr2(m_nPos,MAX_BUF_READ_STR); - m_nPos += 2*((unsigned)_tcslen(streamStr)+1); // 2x because unicode - - strTmp.Format(_T(" Stream Name = [%s]"),(LPCTSTR)streamStr); - m_pLog->AddLine(strTmp); - - - // In the case of "storage", we decode the next 16 bytes as the class - if (bFpxStorage) { - - // FIXME: - // NOTE: Very strange reordering required here. Doesn't seem consistent - // This means that other fields are probably wrong as well (endian) - strFpxStorageClsStr.Format(_T("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X"), - Buf(m_nPos+3),Buf(m_nPos+2),Buf(m_nPos+1),Buf(m_nPos+0), - Buf(m_nPos+5),Buf(m_nPos+4), - Buf(m_nPos+7),Buf(m_nPos+6), - Buf(m_nPos+8),Buf(m_nPos+9), - Buf(m_nPos+10),Buf(m_nPos+11),Buf(m_nPos+12),Buf(m_nPos+13),Buf(m_nPos+14),Buf(m_nPos+15) ); - m_nPos+= 16; - strTmp.Format(_T(" Storage Class = [%s]"),(LPCTSTR)strFpxStorageClsStr); - m_pLog->AddLine(strTmp); - - - } - - } - - return 0; - - } else if (nFpxSegType == 2) { - // Stream Data - strTmp.Format(_T(" Segment: STREAM DATA")); - m_pLog->AddLine(strTmp); - - nFpxStIndexCont = (Buf(m_nPos++)<<8) + Buf(m_nPos++); - strTmp.Format(_T(" Index in Contents List = %u"),nFpxStIndexCont); - m_pLog->AddLine(strTmp); - - nFpxStOffset = (Buf(m_nPos++)<<24) + (Buf(m_nPos++)<<16) + (Buf(m_nPos++)<<8) + Buf(m_nPos++); - strTmp.Format(_T(" Offset in stream = %u (0x%08X)"),nFpxStOffset,nFpxStOffset); - m_pLog->AddLine(strTmp); - - // Now decode the Property Set Header - - // NOTE: Should only decode this if we are doing first part of stream - // TODO: How do we know this? First reference to index #? - - nFpxStWByteOrder = (Buf(m_nPos++)<<8) + Buf(m_nPos++); - nFpxStWFormat = (Buf(m_nPos++)<<8) + Buf(m_nPos++); - nFpxStDwOsVer = (Buf(m_nPos++)<<24) + (Buf(m_nPos++)<<16) + (Buf(m_nPos++)<<8) + Buf(m_nPos++); - - // FIXME: - // NOTE: Very strange reordering required here. Doesn't seem consistent! - // This means that other fields are probably wrong as well (endian) - strFpxStClsidStr.Format(_T("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X"), - Buf(m_nPos+3),Buf(m_nPos+2),Buf(m_nPos+1),Buf(m_nPos+0), - Buf(m_nPos+5),Buf(m_nPos+4), - Buf(m_nPos+7),Buf(m_nPos+6), - Buf(m_nPos+8),Buf(m_nPos+9), - Buf(m_nPos+10),Buf(m_nPos+11),Buf(m_nPos+12),Buf(m_nPos+13),Buf(m_nPos+14),Buf(m_nPos+15) ); - m_nPos+= 16; - nFpxStRsvd = (Buf(m_nPos++)<<8) + Buf(m_nPos++); - - strTmp.Format(_T(" ByteOrder = 0x%04X"),nFpxStWByteOrder); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" Format = 0x%04X"),nFpxStWFormat); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" OSVer = 0x%08X"),nFpxStDwOsVer); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" clsid = %s"),(LPCTSTR)strFpxStClsidStr); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" reserved = 0x%08X"),nFpxStRsvd); - m_pLog->AddLine(strTmp); - - // .... - - return 2; - - } else { - strTmp.Format(_T(" Reserved Segment. Stopping.")); - m_pLog->AddLineErr(strTmp); - return 1; - } - -} - - -// Decode the DHT marker segment (Huffman Tables) -// In some cases (such as for MotionJPEG), we fake out -// the DHT tables (when bInject=true) with a standard table -// as each JPEG frame in the MJPG does not include the DHT. -// In all other cases (bInject=false), we simply read the -// DHT table from the file buffer via Buf() -// -// ITU-T standard indicates that we can expect up to a -// maximum of 16-bit huffman code bitstrings. -void CjfifDecode::DecodeDHT(bool bInject) -{ - unsigned nLength; - unsigned nTmpVal; - CString strTmp,strFull; - unsigned nPosEnd; - unsigned nPosSaved = 0; - - bool bRet; - - - if (bInject) { - // Redirect Buf() to DHT table in MJPGDHTSeg[] - // ... so change mode that Buf() call uses - m_bBufFakeDHT = true; - - // Preserve the "m_nPos" pointer, at end we undo it - // And we also start at 2 which is just after FFC4 in array - nPosSaved = m_nPos; - m_nPos = 2; - } - - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - nPosEnd = m_nPos+nLength; - m_nPos+=2; - strTmp.Format(_T(" Huffman table length = %u"),nLength); - m_pLog->AddLine(strTmp); - - unsigned nDhtClass_Tc; // Range 0..1 - unsigned nDhtHuffTblId_Th; // Range 0..3 - - // In various places, added m_bStateAbort check to allow us - // to escape in case we get in excessive number of DHT entries - // See BUG FIX #1003 - - while ((!m_bStateAbort)&&(nPosEnd > m_nPos)) - { - m_pLog->AddLine(_T(" ----")); - - nTmpVal = Buf(m_nPos++); - nDhtClass_Tc = (nTmpVal & 0xF0) >> 4; // Tc, range 0..1 - nDhtHuffTblId_Th = nTmpVal & 0x0F; // Th, range 0..3 - strTmp.Format(_T(" Destination ID = %u"),nDhtHuffTblId_Th); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Class = %u (%s)"),nDhtClass_Tc,(nDhtClass_Tc?_T("AC Table"):_T("DC / Lossless Table"))); - m_pLog->AddLine(strTmp); - - // Add in some error checking to prevent - if (nDhtClass_Tc >= MAX_DHT_CLASS) { - strTmp.Format(_T("ERROR: Invalid DHT Class (%u). Aborting DHT Load."),nDhtClass_Tc); - m_pLog->AddLineErr(strTmp); - m_nPos = nPosEnd; - //m_bStateAbort = true; // Stop decoding - break; - } - if (nDhtHuffTblId_Th >= MAX_DHT_DEST_ID) { - strTmp.Format(_T("ERROR: Invalid DHT Dest ID (%u). Aborting DHT Load."),nDhtHuffTblId_Th); - m_pLog->AddLineErr(strTmp); - m_nPos = nPosEnd; - //m_bStateAbort = true; // Stop decoding - break; - } - - // Read in the array of DHT code lengths - for (unsigned int i=1;i<=MAX_DHT_CODELEN;i++) - { - m_anDhtNumCodesLen_Li[i] = Buf(m_nPos++); // Li, range 0..255 - } - - #define DECODE_DHT_MAX_DHT 256 - - unsigned int anDhtCodeVal[DECODE_DHT_MAX_DHT+1]; // Should only need max 162 codes - unsigned int nDhtInd; - unsigned int nDhtCodesTotal; - - // Clear out the code list - for (nDhtInd = 0;nDhtInd AddLine(strFull); - strFull = _T(""); - } - - // Save the huffman code - // Just in case we have more DHT codes than we expect, trap - // the range check here, otherwise we'll have buffer overrun! - if (nDhtInd < DECODE_DHT_MAX_DHT) { - anDhtCodeVal[nDhtInd++] = nTmpVal; // Vij, range 0..255 - } else { - nDhtInd++; - strTmp.Format(_T("Excessive DHT entries (%u)... skipping"),nDhtInd); - m_pLog->AddLineErr(strTmp); - if (!m_bStateAbort) { DecodeErrCheck(true); } - } - - } - m_pLog->AddLine(strFull); - } - strTmp.Format(_T(" Total number of codes: %03u"),nDhtCodesTotal); - m_pLog->AddLine(strTmp); - - unsigned int nDhtLookupInd = 0; - - // Now print out the actual binary strings! - unsigned int nCodeVal = 0; - nDhtInd = 0; - if (m_pAppConfig->bOutputDHTexpand) { - m_pLog->AddLine(_T("")); - m_pLog->AddLine(_T(" Expanded Form of Codes:")); - } - for (unsigned int nBitLen=1;((!m_bStateAbort)&&(nBitLen<=16));nBitLen++) - { - if (m_anDhtNumCodesLen_Li[nBitLen] > 0) - { - if (m_pAppConfig->bOutputDHTexpand) { - strTmp.Format(_T(" Codes of length %02u bits:"),nBitLen); - m_pLog->AddLine(strTmp); - } - // Codes exist for this bit-length - // Walk through and generate the bitvalues - for (unsigned int bit_ind=1;((!m_bStateAbort)&&(bit_ind<=m_anDhtNumCodesLen_Li[nBitLen]));bit_ind++) - { - unsigned int nDecVal = nCodeVal; - unsigned int nBinBit; - TCHAR acBinStr[17] = _T(""); - unsigned int nBinStrLen = 0; - - // If the user has enabled output of DHT expanded tables, - // report the bit-string sequences. - if (m_pAppConfig->bOutputDHTexpand) { - for (unsigned int nBinInd=nBitLen;nBinInd>=1;nBinInd--) - { - nBinBit = (nDecVal >> (nBinInd-1)) & 1; - acBinStr[nBinStrLen++] = (nBinBit)?'1':'0'; - } - acBinStr[nBinStrLen] = '\0'; - strFull.Format(_T(" %s = %02X"),acBinStr,anDhtCodeVal[nDhtInd]); - - // The following are only valid for AC components - // Bug [3442132] - if (nDhtClass_Tc == DHT_CLASS_AC) { - if (anDhtCodeVal[nDhtInd] == 0x00) { strFull += _T(" (EOB)"); } - if (anDhtCodeVal[nDhtInd] == 0xF0) { strFull += _T(" (ZRL)"); } - } - - strTmp.Format(_T("%-40s (Total Len = %2u)"),(LPCTSTR)strFull,nBitLen + (anDhtCodeVal[nDhtInd] & 0xF)); - - m_pLog->AddLine(strTmp); - } - - // Store the lookup value - // Shift left to MSB of 32-bit - unsigned nTmpMask = m_anMaskLookup[nBitLen]; - - unsigned nTmpBits = nDecVal << (32-nBitLen); - unsigned nTmpCode = anDhtCodeVal[nDhtInd]; - bRet = m_pImgDec->SetDhtEntry(nDhtHuffTblId_Th,nDhtClass_Tc,nDhtLookupInd,nBitLen, - nTmpBits,nTmpMask,nTmpCode); - - DecodeErrCheck(bRet); - - nDhtLookupInd++; - - // Move to the next code - nCodeVal++; - nDhtInd++; - } - } - // For each loop iteration (on bit length), we shift the code value - nCodeVal <<= 1; - } - - - // Now store the dht_lookup_size - unsigned nTmpSize = nDhtLookupInd; - bRet = m_pImgDec->SetDhtSize(nDhtHuffTblId_Th,nDhtClass_Tc,nTmpSize); - if (!m_bStateAbort) { DecodeErrCheck(bRet); } - - m_pLog->AddLine(_T("")); - - } - - if (bInject) { - // Restore position (as if we didn't move) - m_nPos = nPosSaved; - m_bBufFakeDHT = false; - } -} - - -// Check return value of previous call. If failed, then ask -// user if they wish to continue decoding. If no, then flag to -// the decoder that we're done (avoids continuous failures) -void CjfifDecode::DecodeErrCheck(bool bRet) -{ - if (!bRet) { - if (m_pAppConfig->bInteractive) { - if (AfxMessageBox(_T("Do you want to continue decoding?"),MB_YESNO|MB_ICONQUESTION)== IDNO) { - m_bStateAbort = true; - } - } - } -} - -// This routine is called after the expected fields of the marker segment -// have been processed. The file position should line up with the offset -// dictated by the marker length. If a mismatch is detected, report an -// error. -// -// RETURN: -// - True if decode error is fatal (configurable) -// -bool CjfifDecode::ExpectMarkerEnd(unsigned long nMarkerStart,unsigned nMarkerLen) -{ - CString strTmp; - unsigned long nMarkerEnd = nMarkerStart + nMarkerLen; - unsigned long nMarkerExtra = nMarkerEnd - m_nPos; - if (m_nPos < nMarkerEnd) { - // The length indicates that there is more data than we processed - strTmp.Format(_T(" WARNING: Marker length longer than expected")); - m_pLog->AddLineWarn(strTmp); - if (!m_pAppConfig->bRelaxedParsing) { - // Abort - m_pLog->AddLineErr(_T(" Stopping decode")); - m_pLog->AddLineErr(_T(" Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs")); - return false; - } else { - // Warn and skip - strTmp.Format(_T(" Skipping remainder [%u bytes]"),nMarkerExtra); - m_pLog->AddLineWarn(strTmp); - m_nPos += nMarkerExtra; - } - } else if (m_nPos > nMarkerEnd) { - // The length indicates that there is less data than we processed - strTmp.Format(_T(" WARNING: Marker length shorter than expected")); - m_pLog->AddLineWarn(strTmp); - if (!m_pAppConfig->bRelaxedParsing) { - // Abort - m_pLog->AddLineErr(_T(" Stopping decode")); - m_pLog->AddLineErr(_T(" Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs")); - return false; - } else { - // Warn but no skip - // Note that we can't skip as the length would imply a rollback - // Most resilient solution is probably to assume length was - // wrong and continue from where the marker should have ended. - // For resiliency, attempt two methods to find point to resume: - // 1) Current position - // 2) Actual length defined in marker - if (Buf(m_nPos) == 0xFF) { - // Using actual data expected seems more promising - m_pLog->AddLineWarn(_T(" Resuming decode")); - } else if (Buf(nMarkerEnd) == 0xFF) { - // Using actual length seems more promising - m_nPos = nMarkerEnd; - m_pLog->AddLineWarn(_T(" Rolling back pointer to end indicated by length")); - m_pLog->AddLineWarn(_T(" Resuming decode")); - } else { - // No luck. Expect marker failure now - m_pLog->AddLineWarn(_T(" Resuming decode")); - } - } - } - - // If we get here, then we haven't seen a fatal issue - return true; -} - -// Validate an unsigned value to ensure it is in allowable range -// - If the value is outside the range, an error is shown and -// the parsing stops if relaxed parsing is not enabled -// - An optional override value is provided for the resume case -// -// INPUT: -// - nVal Input value (unsigned 32-bit) -// - nMin Minimum allowed value -// - nMax Maximum allowed value -// - strName Name of the field -// - bOverride Should we override the value upon out-of-range? -// - nOverrideVal Value to override if bOverride and out-of-range -// -// PRE: -// - m_pAppConfig -// -// OUTPUT: -// - nVal Output value (including any override) -// -bool CjfifDecode::ValidateValue(unsigned &nVal,unsigned nMin,unsigned nMax,CString strName,bool bOverride,unsigned nOverrideVal) -{ - CString strErr; - if ((nVal >= nMin) && (nVal <= nMax)) { - // Value is within range - return true; - } else { - if (nVal < nMin) { - strErr.Format(_T(" ERROR: %s value too small (Actual = %u, Expected >= %u)"), - (LPCTSTR)strName,nVal,nMin); - m_pLog->AddLineErr(strErr); - } else if (nVal > nMax) { - strErr.Format(_T(" ERROR: %s value too large (Actual = %u, Expected <= %u)"), - (LPCTSTR)strName,nVal,nMax); - m_pLog->AddLineErr(strErr); - } - if (!m_pAppConfig->bRelaxedParsing) { - // Defined as fatal error - // TODO: Replace with glb_strMsgStopDecode? - m_pLog->AddLineErr(_T(" Stopping decode")); - m_pLog->AddLineErr(_T(" Use [Relaxed Parsing] to continue")); - return false; - } else { - // Non-fatal - if (bOverride) { - // Update value with override - nVal = nOverrideVal; - strErr.Format(_T(" WARNING: Forcing value to [%u]"),nOverrideVal); - m_pLog->AddLineWarn(strErr); - m_pLog->AddLineWarn(_T(" Resuming decode")); - } else { - // No override - strErr.Format(_T(" Resuming decode")); - m_pLog->AddLineWarn(strErr); - } - return true; - } - } - -} - -// This is the primary JFIF marker parser. It reads the -// marker value at the current file position and launches the -// specific parser routine. This routine exits when -#define DECMARK_OK 0 -#define DECMARK_ERR 1 -#define DECMARK_EOI 2 -unsigned CjfifDecode::DecodeMarker() -{ - TCHAR acIdentifier[MAX_IDENTIFIER]; - CString strTmp; - CString strFull; // Used for concatenation - unsigned nLength; // General purpose - unsigned nTmpVal; - BYTE nTmpVal1; - unsigned short nTmpVal2; - unsigned nCode; - unsigned long nPosEnd; - unsigned long nPosSaved; // General-purpose saved position in file - unsigned long nPosExifStart; - unsigned nRet; // General purpose return value - bool bRet; - unsigned long nPosMarkerStart; // Offset for current marker - - unsigned nColTransform = 0; // Color Transform from APP14 marker - - // For DQT - CString strDqtPrecision = _T(""); - CString strDqtZigZagOrder = _T(""); - - - if (Buf(m_nPos) != 0xFF) { - if (m_nPos == 0) { - // Don't give error message if we've already alerted them of AVI / PSD - if ((!m_bAvi) && (!m_bPsd)) { - strTmp.Format(_T("NOTE: File did not start with JPEG marker. Consider using [Tools->Img Search Fwd] to locate embedded JPEG.")); - m_pLog->AddLineErr(strTmp); - } - } else { - strTmp.Format(_T("ERROR: Expected marker 0xFF, got 0x%02X @ offset 0x%08X. Consider using [Tools->Img Search Fwd/Rev]."),Buf(m_nPos),m_nPos); - m_pLog->AddLineErr(strTmp); - } - m_nPos++; - return DECMARK_ERR; - } - m_nPos++; - - - // Read the current marker code - nCode = Buf(m_nPos++); - - // Handle Marker Padding - // - // According to Section B.1.1.2: - // "Any marker may optionally be preceded by any number of fill bytes, which are bytes assigned code X’FF’." - // - unsigned nSkipMarkerPad = 0; - while (nCode == 0xFF) { - // Count the pad - nSkipMarkerPad++; - // Read another byte - nCode = Buf(m_nPos++); - } - - // Report out any padding - if (nSkipMarkerPad>0) { - strTmp.Format(_T("*** Skipped %u marker pad bytes ***"),nSkipMarkerPad); - m_pLog->AddLineHdr(strTmp); - } - - - // Save the current marker offset - nPosMarkerStart = m_nPos; - - AddHeader(nCode); - - switch (nCode) - { - case JFIF_SOI: // SOI - m_bStateSoi = true; - break; - - - case JFIF_APP12: - // Photoshop DUCKY (Save For Web) - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); - strTmp.Format(_T(" Length = %u"),nLength); - m_pLog->AddLine(strTmp); - - nPosSaved = m_nPos; - - m_nPos += 2; // Move past length now that we've used it - - _tcscpy_s(acIdentifier,MAX_IDENTIFIER,m_pWBuf->BufReadStrn(m_nPos,MAX_IDENTIFIER-1)); - acIdentifier[MAX_IDENTIFIER-1] = 0; // Null terminate just in case - strTmp.Format(_T(" Identifier = [%s]"),acIdentifier); - m_pLog->AddLine(strTmp); - m_nPos += (unsigned)_tcslen(acIdentifier)+1; - if (_tcscmp(acIdentifier,_T("Ducky")) != 0) - { - m_pLog->AddLine(_T(" Not Photoshop DUCKY. Skipping remainder.")); - } - else // Photoshop - { - // Please see reference on http://cpan.uwinnipeg.ca/htdocs/Image-ExifTool/Image/ExifTool/APP12.pm.html - // A direct indexed approach should be safe - m_nImgQualPhotoshopSfw = Buf(m_nPos+6); - strTmp.Format(_T(" Photoshop Save For Web Quality = [%d]"),m_nImgQualPhotoshopSfw); - m_pLog->AddLine(strTmp); - } - // Restore original position in file to a point - // after the section - m_nPos = nPosSaved+nLength; - break; - - case JFIF_APP14: - // JPEG Adobe tag - - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - strTmp.Format(_T(" Length = %u"),nLength); - m_pLog->AddLine(strTmp); - - nPosSaved = m_nPos; - // Some files had very short segment (eg. nLength=2) - if (nLength < 2+12) { - m_pLog->AddLine(_T(" Segment too short for Identifier. Skipping remainder.")); - m_nPos = nPosSaved+nLength; - break; - } - m_nPos += 2; // Move past length now that we've used it - - // TODO: Confirm Adobe flag - m_nPos += 5; - - nTmpVal = Buf(m_nPos+0)*256 + Buf(m_nPos+1); - strTmp.Format(_T(" DCTEncodeVersion = %u"),nTmpVal); - m_pLog->AddLine(strTmp); - - nTmpVal = Buf(m_nPos+2)*256 + Buf(m_nPos+3); - strTmp.Format(_T(" APP14Flags0 = %u"),nTmpVal); - m_pLog->AddLine(strTmp); - - nTmpVal = Buf(m_nPos+4)*256 + Buf(m_nPos+5); - strTmp.Format(_T(" APP14Flags1 = %u"),nTmpVal); - m_pLog->AddLine(strTmp); - - nColTransform = Buf(m_nPos+6); - switch (nColTransform) { - case APP14_COLXFM_UNK_RGB: - strTmp.Format(_T(" ColorTransform = %u [Unknown (RGB or CMYK)]"),nColTransform); - break; - case APP14_COLXFM_YCC: - strTmp.Format(_T(" ColorTransform = %u [YCbCr]"),nColTransform); - break; - case APP14_COLXFM_YCCK: - strTmp.Format(_T(" ColorTransform = %u [YCCK]"),nColTransform); - break; - default: - strTmp.Format(_T(" ColorTransform = %u [???]"),nColTransform); - break; - - } - m_pLog->AddLine(strTmp); - m_nApp14ColTransform = (nColTransform & 0xFF); - - // Restore original position in file to a point - // after the section - m_nPos = nPosSaved+nLength; - - break; - - case JFIF_APP13: - // Photoshop (Save As) - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); - strTmp.Format(_T(" Length = %u"),nLength); - m_pLog->AddLine(strTmp); - - nPosSaved = m_nPos; - - // Some files had very short segment (eg. nLength=2) - if (nLength < 2+20) { - m_pLog->AddLine(_T(" Segment too short for Identifier. Skipping remainder.")); - m_nPos = nPosSaved+nLength; - break; - } - m_nPos += 2; // Move past length now that we've used it - - _tcscpy_s(acIdentifier,MAX_IDENTIFIER,m_pWBuf->BufReadStrn(m_nPos,MAX_IDENTIFIER-1)); - acIdentifier[MAX_IDENTIFIER-1] = 0; // Null terminate just in case - strTmp.Format(_T(" Identifier = [%s]"),acIdentifier); - m_pLog->AddLine(strTmp); - m_nPos += (unsigned)_tcslen(acIdentifier)+1; - if (_tcscmp(acIdentifier,_T("Photoshop 3.0")) != 0) - { - m_pLog->AddLine(_T(" Not Photoshop. Skipping remainder.")); - } - else // Photoshop - { - DecodeApp13Ps(); - } - // Restore original position in file to a point - // after the section - m_nPos = nPosSaved+nLength; - break; - - case JFIF_APP1: - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); - strTmp.Format(_T(" Length = %u"),nLength); - m_pLog->AddLine(strTmp); - - nPosSaved = m_nPos; - - m_nPos += 2; // Move past length now that we've used it - - _tcscpy_s(acIdentifier,MAX_IDENTIFIER,m_pWBuf->BufReadStrn(m_nPos,MAX_IDENTIFIER-1)); - acIdentifier[MAX_IDENTIFIER-1] = 0; // Null terminate just in case - strTmp.Format(_T(" Identifier = [%s]"),acIdentifier); - m_pLog->AddLine(strTmp); - m_nPos += (unsigned)_tcslen(acIdentifier); - - - if (!_tcsnccmp(acIdentifier,_T("http://ns.adobe.com/xap/1.0/\x00"),29) != 0) { - // XMP - - m_pLog->AddLine(_T(" XMP = ")); - - m_nPos++; - - // NOTE: This code currently treats the strings from the XMP section - // as single byte characters. In reality, it should probably be - // updated to support unicode properly. - - unsigned nPosMarkerEnd = nPosSaved+nLength-1; - unsigned sXmpLen = nPosMarkerEnd-m_nPos; - unsigned char cXmpChar; - bool bNonSpace; - CString strLine; - - // Reset state - strLine = _T(" |"); - bNonSpace = false; - - for (unsigned nInd=0;nIndBuf(m_nPos+nInd); - - // Detect a non-space in line - if ((cXmpChar != 0x20) && (cXmpChar != 0x0A)) { - bNonSpace = true; - } - - // Detect Linefeed, print out line - if (cXmpChar == 0x0A) { - // Only print line if some non-space elements! - if (bNonSpace) { - m_pLog->AddLine(strLine); - } - // Reset state - strLine = _T(" |"); - bNonSpace = false; - } else { - // Add the char - strLine.AppendChar(cXmpChar); - } - } - } - else if (!_tcscmp(acIdentifier,_T("Exif")) != 0) - { - // Only decode it further if it is EXIF format - - m_nPos += 2; // Skip two 00 bytes - - - nPosExifStart = m_nPos; // Save m_nPos @ start of EXIF used for all IFD offsets - - // =========== EXIF TIFF Header (Start) =========== - // - Defined in Exif 2.2 Standard (JEITA CP-3451) section 4.5.2 - // - Contents (8 bytes total) - // - Byte order (2 bytes) - // - 0x002A (2 bytes) - // - Offset of 0th IFD (4 bytes) - - unsigned char acIdentifierTiff[9]; - strFull = _T(""); - strTmp = _T(""); - - strFull = _T(" Identifier TIFF = "); - for (unsigned int i=0;i<8;i++) { - acIdentifierTiff[i] = (unsigned char)Buf(m_nPos++); - } - strTmp = PrintAsHexUC(acIdentifierTiff,8); - strFull += strTmp; - m_pLog->AddLine(strFull); - - - switch (acIdentifierTiff[0]*256+acIdentifierTiff[1]) - { - case 0x4949: // "II" - // Intel alignment - m_nImgExifEndian = 0; - m_pLog->AddLine(_T(" Endian = Intel (little)")); - break; - case 0x4D4D: // "MM" - // Motorola alignment - m_nImgExifEndian = 1; - m_pLog->AddLine(_T(" Endian = Motorola (big)")); - break; - } - - // We expect the TAG mark of 0x002A (depending on endian mode) - unsigned test_002a; - test_002a = ByteSwap2(acIdentifierTiff[2],acIdentifierTiff[3]); - strTmp.Format(_T(" TAG Mark x002A = 0x%04X"),test_002a); - m_pLog->AddLine(strTmp); - - unsigned nIfdCount; // Current IFD # - unsigned nOffsetIfd1; - - // Mark pointer to EXIF Sub IFD as 0 so that we can - // detect if the tag never showed up. - m_nImgExifSubIfdPtr = 0; - m_nImgExifMakerPtr = 0; - m_nImgExifGpsIfdPtr = 0; - m_nImgExifInteropIfdPtr = 0; - - bool exif_done = FALSE; - - nOffsetIfd1 = ByteSwap4(acIdentifierTiff[4],acIdentifierTiff[5], - acIdentifierTiff[6],acIdentifierTiff[7]); - - // =========== EXIF TIFF Header (End) =========== - - // =========== EXIF IFD 0 =========== - // Do we start the 0th IFD for the "Primary Image Data"? - // Even though the nOffsetIfd1 pointer should indicate to - // us where the IFD should start (0x0008 if immediately after - // EXIF TIFF Header), I have observed JPEG files that - // do not contain the IFD. Therefore, we must check for this - // condition by comparing against the APP marker length. - // Example file: http://img9.imageshack.us/img9/194/90114543.jpg - - if ((nPosSaved + nLength) <= (nPosExifStart+nOffsetIfd1)) { - // We've run out of space for any IFD, so cancel now - exif_done = true; - m_pLog->AddLine(_T(" NOTE: No IFD entries")); - } - - - nIfdCount = 0; - while (!exif_done) { - - m_pLog->AddLine(_T("")); - - strTmp.Format(_T("IFD%u"),nIfdCount); - - // Process the IFD - nRet = DecodeExifIfd(strTmp,nPosExifStart,nOffsetIfd1); - - // Now that we have gone through all entries in the IFD directory, - // we read the offset to the next IFD - nOffsetIfd1 = ByteSwap4(Buf(m_nPos+0),Buf(m_nPos+1),Buf(m_nPos+2),Buf(m_nPos+3)); - m_nPos += 4; - - - strTmp.Format(_T(" Offset to Next IFD = 0x%08X"),nOffsetIfd1); - m_pLog->AddLine(strTmp); - - - if (nRet != 0) { - // Error condition (DecodeExifIfd returned error) - nOffsetIfd1 = 0x00000000; - } - - - if (nOffsetIfd1 == 0x00000000) { - // Either error condition or truly end of IFDs - exif_done = TRUE; - } else { - nIfdCount++; - } - - } // while ! exif_done - - // If EXIF SubIFD was defined, then handle it now - if (m_nImgExifSubIfdPtr != 0) - { - m_pLog->AddLine(_T("")); - DecodeExifIfd(_T("SubIFD"),nPosExifStart,m_nImgExifSubIfdPtr); - } - if (m_nImgExifMakerPtr != 0) - { - m_pLog->AddLine(_T("")); - DecodeExifIfd(_T("MakerIFD"),nPosExifStart,m_nImgExifMakerPtr); - } - if (m_nImgExifGpsIfdPtr != 0) - { - m_pLog->AddLine(_T("")); - DecodeExifIfd(_T("GPSIFD"),nPosExifStart,m_nImgExifGpsIfdPtr); - } - if (m_nImgExifInteropIfdPtr != 0) - { - m_pLog->AddLine(_T("")); - DecodeExifIfd(_T("InteropIFD"),nPosExifStart,m_nImgExifInteropIfdPtr); - } - - } else { - strTmp.Format(_T("Identifier [%s] not supported. Skipping remainder."),(LPCTSTR)acIdentifier); - m_pLog->AddLine(strTmp); - } - - ////////// - - - // Dump out Makernote area - - // TODO: Disabled for now -#if 0 - unsigned ptr_base; - - if (m_bVerbose) - { - if (m_nImgExifMakerPtr != 0) - { - // FIXME: Seems that nPosExifStart is not initialized in VERBOSE mode - ptr_base = nPosExifStart+m_nImgExifMakerPtr; - - m_pLog->AddLine(_T("Exif Maker IFD DUMP")); - strFull.Format(_T(" MarkerOffset @ 0x%08X"),ptr_base); - m_pLog->AddLine(strFull); - } - } -#endif - - // End of dump out makernote area - - - - // Restore file position - m_nPos = nPosSaved; - - - // Restore original position in file to a point - // after the section - m_nPos = nPosSaved+nLength; - - break; - - case JFIF_APP2: - // Typically used for Flashpix and possibly ICC profiles - // Photoshop (Save As) - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); - strTmp.Format(_T(" Length = %u"),nLength); - m_pLog->AddLine(strTmp); - - nPosSaved = m_nPos; - - m_nPos += 2; // Move past length now that we've used it - - - _tcscpy_s(acIdentifier,MAX_IDENTIFIER,m_pWBuf->BufReadStrn(m_nPos,MAX_IDENTIFIER-1)); - acIdentifier[MAX_IDENTIFIER-1] = 0; // Null terminate just in case - strTmp.Format(_T(" Identifier = [%s]"),acIdentifier); - m_pLog->AddLine(strTmp); - m_nPos += (unsigned)_tcslen(acIdentifier)+1; - if (_tcscmp(acIdentifier,_T("FPXR")) == 0) { - // Photoshop - m_pLog->AddLine(_T(" FlashPix:")); - DecodeApp2Flashpix(); - } else if (_tcscmp(acIdentifier,_T("ICC_PROFILE")) == 0) { - // ICC Profile - m_pLog->AddLine(_T(" ICC Profile:")); - DecodeApp2IccProfile(nLength); - } else { - m_pLog->AddLine(_T(" Not supported. Skipping remainder.")); - } - // Restore original position in file to a point - // after the section - m_nPos = nPosSaved+nLength; - break; - - - case JFIF_APP3: - case JFIF_APP4: - case JFIF_APP5: - case JFIF_APP6: - case JFIF_APP7: - case JFIF_APP8: - case JFIF_APP9: - case JFIF_APP10: - case JFIF_APP11: - //case JFIF_APP12: // Handled separately - //case JFIF_APP13: // Handled separately - //case JFIF_APP14: // Handled separately - case JFIF_APP15: - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); - strTmp.Format(_T(" Length = %u"),nLength); - m_pLog->AddLine(strTmp); - - if (m_bVerbose) - { - - strFull = _T(""); - for (unsigned int i=0;iAddLine(strFull); - strFull = _T(""); - } - } - m_pLog->AddLine(strFull); - - strFull = _T(""); - for (unsigned int i=0;iAddLine(strFull); - } - } - m_pLog->AddLine(strFull); - - } // nVerbose - - m_nPos += nLength; - break; - - case JFIF_APP0: // APP0 - - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); - m_nPos+=2; - strTmp.Format(_T(" Length = %u"),nLength); - m_pLog->AddLine(strTmp); - - _tcscpy_s(m_acApp0Identifier,MAX_IDENTIFIER,m_pWBuf->BufReadStrn(m_nPos,MAX_IDENTIFIER-1)); - m_acApp0Identifier[MAX_IDENTIFIER-1] = 0; // Null terminate just in case - strTmp.Format(_T(" Identifier = [%s]"),m_acApp0Identifier); - m_pLog->AddLine(strTmp); - - if (!_tcscmp(m_acApp0Identifier,_T("JFIF"))) - { - // Only process remainder if it is JFIF. This marker - // is also used for application-specific functions. - - m_nPos += (unsigned)(_tcslen(m_acApp0Identifier)+1); - - m_nImgVersionMajor = Buf(m_nPos++); - m_nImgVersionMinor = Buf(m_nPos++); - strTmp.Format(_T(" version = [%u.%u]"),m_nImgVersionMajor,m_nImgVersionMinor); - m_pLog->AddLine(strTmp); - - m_nImgUnits = Buf(m_nPos++); - - m_nImgDensityX = Buf(m_nPos)*256 + Buf(m_nPos+1); - //m_nImgDensityX = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); - m_nPos+=2; - m_nImgDensityY = Buf(m_nPos)*256 + Buf(m_nPos+1); - //m_nImgDensityY = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); - m_nPos+=2; - strTmp.Format(_T(" density = %u x %u "),m_nImgDensityX,m_nImgDensityY); - strFull = strTmp; - - switch (m_nImgUnits) - { - case 0: - strFull += _T("(aspect ratio)"); - m_pLog->AddLine(strFull); - break; - case 1: - strFull += _T("DPI (dots per inch)"); - m_pLog->AddLine(strFull); - break; - case 2: - strFull += _T("DPcm (dots per cm)"); - m_pLog->AddLine(strFull); - break; - default: - strTmp.Format(_T("ERROR: Unknown ImgUnits parameter [%u]"),m_nImgUnits); - strFull += strTmp; - m_pLog->AddLineWarn(strFull); - //return DECMARK_ERR; - break; - } - - - m_nImgThumbSizeX = Buf(m_nPos++); - m_nImgThumbSizeY = Buf(m_nPos++); - strTmp.Format(_T(" thumbnail = %u x %u"),m_nImgThumbSizeX,m_nImgThumbSizeY); - m_pLog->AddLine(strTmp); - - // Unpack the thumbnail: - unsigned thumbnail_r,thumbnail_g,thumbnail_b; - if (m_nImgThumbSizeX && m_nImgThumbSizeY) { - for (unsigned y=0;yAddLine(strFull); - } - } - } - - // TODO: - // - In JPEG-B mode (GeoRaster), we will need to fake out - // the DHT & DQT tables here. Unfortunately, we'll have to - // rely on the user to put us into this mode as there is nothing - // in the file that specifies this mode. - - /* - // TODO: Need to ensure that Faked DHT is correct table - - AddHeader(JFIF_DHT_FAKE); - DecodeDHT(true); - // Need to mark DHT tables as OK - m_bStateDht = true; - m_bStateDhtFake = true; - m_bStateDhtOk = true; - - // ... same for DQT - */ - - - - } else if (!_tcsnccmp(m_acApp0Identifier,_T("AVI1"),4)) - { - // AVI MJPEG type - - // Need to fill in predefined DHT table from spec: - // OpenDML file format for AVI, section "Proposed Data Chunk Format" - // Described in MMREG.H - m_pLog->AddLine(_T(" Detected MotionJPEG")); - m_pLog->AddLine(_T(" Importing standard Huffman table...")); - m_pLog->AddLine(_T("")); - - AddHeader(JFIF_DHT_FAKE); - - DecodeDHT(true); - // Need to mark DHT tables as OK - m_bStateDht = true; - m_bStateDhtFake = true; - m_bStateDhtOk = true; - - m_nPos += nLength-2; // Skip over, and undo length short read - - - } else { - // Not JFIF or AVI1 - m_pLog->AddLine(_T(" Not known APP0 type. Skipping remainder.")); - m_nPos += nLength-2; - } - - if (!ExpectMarkerEnd(nPosMarkerStart,nLength)) - return DECMARK_ERR; - - break; - - case JFIF_DQT: // Define quantization tables - m_bStateDqt = true; - unsigned nDqtPrecision_Pq; - unsigned nDqtQuantDestId_Tq; - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); // Lq - nPosEnd = m_nPos+nLength; - m_nPos+=2; -//XXX strTmp.Format(_T(" Table length = %u"),nLength); - strTmp.Format(_T(" Table length = %u"),nLength); - m_pLog->AddLine(strTmp); - - while (nPosEnd > m_nPos) - { - strTmp.Format(_T(" ----")); - m_pLog->AddLine(strTmp); - - nTmpVal = Buf(m_nPos++); // Pq | Tq - nDqtPrecision_Pq = (nTmpVal & 0xF0) >> 4; // Pq, range 0-1 - nDqtQuantDestId_Tq = nTmpVal & 0x0F; // Tq, range 0-3 - - // Decode per ITU-T.81 standard -#if 1 - - if (nDqtPrecision_Pq == 0) { - strDqtPrecision = _T("8 bits"); - } else if (nDqtPrecision_Pq == 1) { - strDqtPrecision = _T("16 bits"); - } else { - strTmp.Format(_T(" Unsupported precision value [%u]"),nDqtPrecision_Pq); - m_pLog->AddLineWarn(strTmp); - strDqtPrecision = _T("???"); - // FIXME: Consider terminating marker parsing early - } - - if (!ValidateValue(nDqtPrecision_Pq,0,1,_T("DQT Precision "),true,0)) return DECMARK_ERR; - if (!ValidateValue(nDqtQuantDestId_Tq,0,3,_T("DQT Destination ID "),true,0)) return DECMARK_ERR; - - strTmp.Format(_T(" Precision=%s"),(LPCTSTR)strDqtPrecision); - m_pLog->AddLine(strTmp); - -#else - // Decode with additional DQT extension (ITU-T-JPEG-Plus-Proposal_R3.doc) - - if ((nDqtPrecision_Pq & 0xE) == 0) { - // Per ITU-T.81 Standard - if (nDqtPrecision_Pq == 0) { - strDqtPrecision = _T("8 bits"); - } else if (nDqtPrecision_Pq == 1) { - strDqtPrecision = _T("16 bits"); - } - strTmp.Format(_T(" Precision=%s"),strDqtPrecision); - m_pLog->AddLine(strTmp); - } else { - // Non-standard - // JPEG-Plus-Proposal-R3: - // - Alternative sub-block-wise sequence - strTmp.Format(_T(" Non-Standard DQT Extension detected")); - m_pLog->AddLineWarn(strTmp); - - // FIXME: Should prevent attempt to decode until this is implemented - - if (nDqtPrecision_Pq == 0) { - strDqtPrecision = _T("8 bits"); - } else if (nDqtPrecision_Pq == 1) { - strDqtPrecision = _T("16 bits"); - } - strTmp.Format(_T(" Precision=%s"),strDqtPrecision); - m_pLog->AddLine(strTmp); - - if ((nDqtPrecision_Pq & 0x2) == 0) { - strDqtZigZagOrder = _T("Diagonal zig-zag coeff scan seqeunce"); - } else if ((nDqtPrecision_Pq & 0x2) == 1) { - strDqtZigZagOrder = _T("Alternate coeff scan seqeunce"); - } - strTmp.Format(_T(" Coeff Scan Sequence=%s"),strDqtZigZagOrder); - m_pLog->AddLine(strTmp); - - if ((nDqtPrecision_Pq & 0x4) == 1) { - strTmp.Format(_T(" Custom coeff scan sequence")); - m_pLog->AddLine(strTmp); - // Now expect sequence of 64 coefficient entries - CString strSequence = _T(""); - for (unsigned nInd=0;nInd<64;nInd++) { - nTmpVal = Buf(m_nPos++); - strTmp.Format(_T("%u"),nTmpVal); - strSequence += strTmp; - if (nInd!=63) { - strSequence += _T(", "); - } - } - strTmp.Format(_T(" Custom sequence = [ %s ]"),strSequence); - m_pLog->AddLine(strTmp); - } - } -#endif - - strTmp.Format(_T(" Destination ID=%u"),nDqtQuantDestId_Tq); - if (nDqtQuantDestId_Tq == 0) { - strTmp += _T(" (Luminance)"); - } - else if (nDqtQuantDestId_Tq == 1) { - strTmp += _T(" (Chrominance)"); - } - else if (nDqtQuantDestId_Tq == 2) { - strTmp += _T(" (Chrominance)"); - } - else { - strTmp += _T(" (???)"); - } - m_pLog->AddLine(strTmp); - - - // FIXME: The following is somewhat superseded by ValidateValue() above - // with the exception of skipping remainder - if (nDqtQuantDestId_Tq >= MAX_DQT_DEST_ID) { - strTmp.Format(_T("ERROR: Destination ID = %u, >= %u"),nDqtQuantDestId_Tq,MAX_DQT_DEST_ID); - m_pLog->AddLineErr(strTmp); - if (!m_pAppConfig->bRelaxedParsing) { - m_pLog->AddLineErr(_T(" Stopping decode")); - return DECMARK_ERR; - } else { - // Now skip remainder of DQT - // FIXME - strTmp.Format(_T(" Skipping remainder of marker [%u bytes]"),nPosMarkerStart + nLength - m_nPos); - m_pLog->AddLineWarn(strTmp); - m_pLog->AddLine(_T("")); - m_nPos = nPosMarkerStart + nLength; - return DECMARK_OK; - } - } - - bool bQuantAllOnes = true; - double dComparePercent; - double dSumPercent=0; - double dSumPercentSqr=0; - - - for (unsigned nCoeffInd=0;nCoeffInd low freq - // To X,Y, left-to-right, top-to-bottom - - // Flag this DQT table as being set! - m_abImgDqtSet[nDqtQuantDestId_Tq] = true; - - unsigned nCoeffInd; - - // Now display the table - for (unsigned nDqtY=0;nDqtY<8;nDqtY++) { - strFull.Format(_T(" DQT, Row #%u: "),nDqtY); - for (unsigned nDqtX=0;nDqtX<8;nDqtX++) { - nCoeffInd = nDqtY*8+nDqtX; - strTmp.Format(_T("%3u "),m_anImgDqtTbl[nDqtQuantDestId_Tq][nCoeffInd]); - strFull += strTmp; - - // Store the DQT entry into the Image Decoder - bRet = m_pImgDec->SetDqtEntry(nDqtQuantDestId_Tq,nCoeffInd,glb_anUnZigZag[nCoeffInd], - m_anImgDqtTbl[nDqtQuantDestId_Tq][nCoeffInd]); - DecodeErrCheck(bRet); - } - - // Now add the compare with Annex K - // Decided to disable this as it was confusing users - /* - strFull += _T(" AnnexRatio: <"); - for (unsigned nDqtX=0;nDqtX<8;nDqtX++) { - nCoeffInd = nDqtY*8+nDqtX; - if (nDqtQuantDestId_Tq == 0) { - strTmp.Format(_T("%5.1f "),m_afStdQuantLumCompare[nCoeffInd]); - } else { - strTmp.Format(_T("%5.1f "),m_afStdQuantChrCompare[nCoeffInd]); - } - strFull += strTmp; - } - strFull += _T(">"); - */ - - m_pLog->AddLine(strFull); - - } - - - - // Perform some statistical analysis of the quality factor - // to determine the likelihood of the current quantization - // table being a scaled version of the "standard" tables. - // If the variance is high, it is unlikely to be the case. - double dQuality; - double dVariance; - dSumPercent /= 64.0; /* mean scale factor */ - dSumPercentSqr /= 64.0; - dVariance = dSumPercentSqr - (dSumPercent * dSumPercent); /* variance */ - - // Generate the equivalent IJQ "quality" factor - if (bQuantAllOnes) /* special case for all-ones table */ - dQuality = 100.0; - else if (dSumPercent <= 100.0) - dQuality = (200.0 - dSumPercent) / 2.0; - else - dQuality = 5000.0 / dSumPercent; - - // Save the quality rating for later - m_adImgDqtQual[nDqtQuantDestId_Tq] = dQuality; - - strTmp.Format(_T(" Approx quality factor = %.2f (scaling=%.2f variance=%.2f)"), - dQuality,dSumPercent,dVariance); - m_pLog->AddLine(strTmp); - - - } - m_bStateDqtOk = true; - - if (!ExpectMarkerEnd(nPosMarkerStart,nLength)) - return DECMARK_ERR; - - break; - - case JFIF_DAC: // DAC (Arithmetic Coding) - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); // La - m_nPos+=2; -//XXX strTmp.Format(_T(" Arithmetic coding header length = %u"),nLength); - strTmp.Format(_T(" Arithmetic coding header length = %u"),nLength); - m_pLog->AddLine(strTmp); - unsigned nDAC_n; - unsigned nDAC_Tc,nDAC_Tb; - unsigned nDAC_Cs; - nDAC_n = (nLength>2)?(nLength-2)/2:0; - for (unsigned nInd=0;nInd> 4; - nDAC_Tb = (nTmpVal & 0x0F); -//XXX strTmp.Format(_T(" #%02u: Table class = %u"),nInd+1,nDAC_Tc); - strTmp.Format(_T(" #%02u: Table class = %u"),nInd+1,nDAC_Tc); - m_pLog->AddLine(strTmp); -//XXX strTmp.Format(_T(" #%02u: Table destination identifier = %u"),nInd+1,nDAC_Tb); - strTmp.Format(_T(" #%02u: Table destination identifier = %u"),nInd+1,nDAC_Tb); - m_pLog->AddLine(strTmp); - - nDAC_Cs = Buf(m_nPos++); // Cs -//XXX strTmp.Format(_T(" #%02u: Conditioning table value = %u"),nInd+1,nDAC_Cs); - strTmp.Format(_T(" #%02u: Conditioning table value = %u"),nInd+1,nDAC_Cs); - m_pLog->AddLine(strTmp); - - if (!ValidateValue(nDAC_Tc,0,1,_T("Table class "),true,0)) return DECMARK_ERR; - if (!ValidateValue(nDAC_Tb,0,3,_T("Table destination ID "),true,0)) return DECMARK_ERR; - - // Parameter range constraints per Table B.6: - // ------------|-------------------------|-------------------|------------ - // | Sequential DCT | Progressive DCT | Lossless - // Parameter | Baseline Extended | | - // ------------|-----------|-------------|-------------------|------------ - // Cs | Undef | Tc=0: 0-255 | Tc=0: 0-255 | 0-255 - // | | Tc=1: 1-63 | Tc=1: 1-63 | - // ------------|-----------|-------------|-------------------|------------ - - // However, to keep it simple (and not depend on lossless mode), - // we will only check the maximal range - if (!ValidateValue(nDAC_Cs,0,255,_T("Conditioning table value "),true,0)) return DECMARK_ERR; - } - if (!ExpectMarkerEnd(nPosMarkerStart,nLength)) - return DECMARK_ERR; - - break; - - case JFIF_DNL: // DNL (Define number of lines) - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); // Ld - m_nPos+=2; -//XXX strTmp.Format(_T(" Header length = %u"),nLength); - strTmp.Format(_T(" Header length = %u"),nLength); - m_pLog->AddLine(strTmp); - - nTmpVal = Buf(m_nPos)*256 + Buf(m_nPos+1); // NL - m_nPos+=2; -//XXX strTmp.Format(_T(" Number of lines = %u"),nTmpVal); - strTmp.Format(_T(" Number of lines = %u"),nTmpVal); - m_pLog->AddLine(strTmp); - - if (!ValidateValue(nTmpVal,1,65535,_T("Number of lines "),true,1)) return DECMARK_ERR; - - if (!ExpectMarkerEnd(nPosMarkerStart,nLength)) - return DECMARK_ERR; - break; - - case JFIF_EXP: - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); // Le - m_nPos+=2; -//XXX strTmp.Format(_T(" Header length = %u"),nLength); - strTmp.Format(_T(" Header length = %u"),nLength); - m_pLog->AddLine(strTmp); - - unsigned nEXP_Eh,nEXP_Ev; - nTmpVal = Buf(m_nPos)*256 + Buf(m_nPos+1); // Eh,Ev - nEXP_Eh = (nTmpVal & 0xF0) >> 4; - nEXP_Ev = (nTmpVal & 0x0F); - m_nPos+=2; -//XXX strTmp.Format(_T(" Expand horizontally = %u"),nEXP_Eh); - strTmp.Format(_T(" Expand horizontally = %u"),nEXP_Eh); - m_pLog->AddLine(strTmp); -//XXX strTmp.Format(_T(" Expand vertically = %u"),nEXP_Ev); - strTmp.Format(_T(" Expand vertically = %u"),nEXP_Ev); - m_pLog->AddLine(strTmp); - - if (!ValidateValue(nEXP_Eh,0,1,_T("Expand horizontally "),true,0)) return DECMARK_ERR; - if (!ValidateValue(nEXP_Ev,0,1,_T("Expand vertically "),true,0)) return DECMARK_ERR; - - if (!ExpectMarkerEnd(nPosMarkerStart,nLength)) - return DECMARK_ERR; - break; - - - case JFIF_SOF0: // SOF0 (Baseline DCT) - case JFIF_SOF1: // SOF1 (Extended sequential) - case JFIF_SOF2: // SOF2 (Progressive) - case JFIF_SOF3: - case JFIF_SOF5: - case JFIF_SOF6: - case JFIF_SOF7: - case JFIF_SOF9: - case JFIF_SOF10: - case JFIF_SOF11: - case JFIF_SOF13: - case JFIF_SOF14: - case JFIF_SOF15: - - // TODO: - // - JFIF_DHP should be able to reuse the JFIF_SOF marker parsing - // however as we don't support hierarchical image decode, we - // would want to skip the update of class members. - - m_bStateSof = true; - - // Determine if this is a SOF mode that we support - // At this time, we only support Baseline DCT & Extended Sequential Baseline DCT - // (non-differential) with Huffman coding. Progressive, Lossless, - // Differential and Arithmetic coded modes are not supported. - m_bImgSofUnsupported = true; - if (nCode == JFIF_SOF0) { m_bImgSofUnsupported = false; } - if (nCode == JFIF_SOF1) { m_bImgSofUnsupported = false; } - - // For reference, note progressive scan files even though - // we don't currently support their decode - if (nCode == JFIF_SOF2) { m_bImgProgressive = true; } - - - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); // Lf - m_nPos+=2; -//XXX strTmp.Format(_T(" Frame header length = %u"),nLength); - strTmp.Format(_T(" Frame header length = %u"),nLength); - m_pLog->AddLine(strTmp); - - m_nSofPrecision_P = Buf(m_nPos++); // P -//XXX strTmp.Format(_T(" Precision

= %u"),m_nSofPrecision_P); - strTmp.Format(_T(" Precision = %u"),m_nSofPrecision_P); - m_pLog->AddLine(strTmp); - if (!ValidateValue(m_nSofPrecision_P,2,16,_T("Precision

"),true,8)) return DECMARK_ERR; - - m_nSofNumLines_Y = Buf(m_nPos)*256 + Buf(m_nPos+1); // Y - m_nPos += 2; -//XXX strTmp.Format(_T(" Number of Lines = %u"),m_nSofNumLines_Y); - strTmp.Format(_T(" Number of Lines = %u"),m_nSofNumLines_Y); - m_pLog->AddLine(strTmp); - if (!ValidateValue(m_nSofNumLines_Y,0,65535,_T("Number of Lines "),true,0)) return DECMARK_ERR; - - m_nSofSampsPerLine_X = Buf(m_nPos)*256 + Buf(m_nPos+1); // X - m_nPos += 2; -//XXX strTmp.Format(_T(" Samples per Line = %u"),m_nSofSampsPerLine_X); - strTmp.Format(_T(" Samples per Line = %u"),m_nSofSampsPerLine_X); - m_pLog->AddLine(strTmp); - if (!ValidateValue(m_nSofSampsPerLine_X,1,65535,_T("Samples per Line "),true,1)) return DECMARK_ERR; - - strTmp.Format(_T(" Image Size = %u x %u"),m_nSofSampsPerLine_X,m_nSofNumLines_Y); - m_pLog->AddLine(strTmp); - - // Determine orientation - // m_nSofSampsPerLine_X = X - // m_nSofNumLines_Y = Y - m_eImgLandscape = ENUM_LANDSCAPE_YES; - if (m_nSofNumLines_Y > m_nSofSampsPerLine_X) - m_eImgLandscape = ENUM_LANDSCAPE_NO; - strTmp.Format(_T(" Raw Image Orientation = %s"),(m_eImgLandscape==ENUM_LANDSCAPE_YES)?_T("Landscape"):_T("Portrait")); - m_pLog->AddLine(strTmp); - - m_nSofNumComps_Nf = Buf(m_nPos++); // Nf, range 1..255 -//XXX strTmp.Format(_T(" Number of Img components = %u"),m_nSofNumComps_Nf); - strTmp.Format(_T(" Number of Img components = %u"),m_nSofNumComps_Nf); - m_pLog->AddLine(strTmp); - if (!ValidateValue(m_nSofNumComps_Nf,1,255,_T("Number of Img components "),true,1)) return DECMARK_ERR; - - unsigned nCompIdent; - unsigned anSofSampFact[MAX_SOF_COMP_NF]; - - m_nSofHorzSampFactMax_Hmax = 0; - m_nSofVertSampFactMax_Vmax = 0; - - // Now clear the output image content (all components) - // TODO: Migrate some of the bitmap allocation / clearing from - // DecodeScanImg() into ResetImageContent() and call here - //m_pImgDec->ResetImageContent(); - - // Per JFIF v1.02: - // - Nf = 1 or 3 - // - C1 = Y - // - C2 = Cb - // - C3 = Cr - - for (unsigned nCompInd=1;((!m_bStateAbort)&&(nCompInd<=m_nSofNumComps_Nf));nCompInd++) - { - nCompIdent = Buf(m_nPos++); // Ci, range 0..255 - m_anSofQuantCompId[nCompInd] = nCompIdent; - //if (!ValidateValue(m_anSofQuantCompId[nCompInd],0,255,_T("Component ID "),true,0)) return DECMARK_ERR; - - anSofSampFact[nCompIdent] = Buf(m_nPos++); - m_anSofQuantTblSel_Tqi[nCompIdent] = Buf(m_nPos++); // Tqi, range 0..3 - //if (!ValidateValue(m_anSofQuantTblSel_Tqi[nCompIdent],0,3,_T("Table Destination ID "),true,0)) return DECMARK_ERR; - - // NOTE: We protect against bad input here as replication ratios are - // determined later that depend on dividing by sampling factor (hence - // possibility of div by 0). - m_anSofHorzSampFact_Hi[nCompIdent] = (anSofSampFact[nCompIdent] & 0xF0) >> 4; // Hi, range 1..4 - m_anSofVertSampFact_Vi[nCompIdent] = (anSofSampFact[nCompIdent] & 0x0F); // Vi, range 1..4 - if (!ValidateValue(m_anSofHorzSampFact_Hi[nCompIdent],1,4,_T("Horizontal Sampling Factor "),true,1)) return DECMARK_ERR; - if (!ValidateValue(m_anSofVertSampFact_Vi[nCompIdent],1,4,_T("Vertical Sampling Factor "),true,1)) return DECMARK_ERR; - - } - - // Calculate max sampling factors - for (unsigned nCompInd=1;((!m_bStateAbort)&&(nCompInd<=m_nSofNumComps_Nf));nCompInd++) - { - nCompIdent = m_anSofQuantCompId[nCompInd]; - // Calculate maximum sampling factor for the SOF. This is only - // used for later generation of m_strImgQuantCss an the SOF - // reporting below. The CimgDecode block is responsible for - // calculating the maximum sampling factor on a per-scan basis. - m_nSofHorzSampFactMax_Hmax = max(m_nSofHorzSampFactMax_Hmax,m_anSofHorzSampFact_Hi[nCompIdent]); - m_nSofVertSampFactMax_Vmax = max(m_nSofVertSampFactMax_Vmax,m_anSofVertSampFact_Vi[nCompIdent]); - } - - // Report per-component sampling factors and quantization table selectors - for (unsigned nCompInd=1;((!m_bStateAbort)&&(nCompInd<=m_nSofNumComps_Nf));nCompInd++) - { - nCompIdent = m_anSofQuantCompId[nCompInd]; - - // Create subsampling ratio - // - Protect against division-by-zero - CString strSubsampH = _T("?"); - CString strSubsampV = _T("?"); - if (m_anSofHorzSampFact_Hi[nCompIdent] > 0) { - strSubsampH.Format(_T("%u"),m_nSofHorzSampFactMax_Hmax/m_anSofHorzSampFact_Hi[nCompIdent]); - } - if (m_anSofVertSampFact_Vi[nCompIdent] > 0) { - strSubsampV.Format(_T("%u"),m_nSofVertSampFactMax_Vmax/m_anSofVertSampFact_Vi[nCompIdent]); - } - - strFull.Format(_T(" Component[%u]: "),nCompInd); // Note i in Ci is 1-based -//XXX strTmp.Format(_T("ID=0x%02X, Samp Fac =0x%02X (Subsamp %u x %u), Quant Tbl Sel =0x%02X"), - strTmp.Format(_T("ID=0x%02X, Samp Fac=0x%02X (Subsamp %s x %s), Quant Tbl Sel=0x%02X"), - nCompIdent,anSofSampFact[nCompIdent], - (LPCTSTR)strSubsampH,(LPCTSTR)strSubsampV, - m_anSofQuantTblSel_Tqi[nCompIdent]); - strFull += strTmp; - - // Mapping from component index (not ID) to colour channel per JFIF - if (m_nSofNumComps_Nf == 1) { - // Assume grayscale - strFull += _T(" (Lum: Y)"); - } else if (m_nSofNumComps_Nf == 3) { - // Assume YCC - if (nCompInd == SCAN_COMP_Y) { - strFull += _T(" (Lum: Y)"); - } - else if (nCompInd == SCAN_COMP_CB) { - strFull += _T(" (Chrom: Cb)"); - } - else if (nCompInd == SCAN_COMP_CR) { - strFull += _T(" (Chrom: Cr)"); - } - } else if (m_nSofNumComps_Nf == 4) { - // Assume YCCK - if (nCompInd == 1) { - strFull += _T(" (Y)"); - } - else if (nCompInd == 2) { - strFull += _T(" (Cb)"); - } - else if (nCompInd == 3) { - strFull += _T(" (Cr)"); - } - else if (nCompInd == 4) { - strFull += _T(" (K)"); - } - } else { - strFull += _T(" (???)"); // Unknown - } - m_pLog->AddLine(strFull); - - } - - // Test for bad input, clean up if bad - for (unsigned nCompInd=1;((!m_bStateAbort)&&(nCompInd<=m_nSofNumComps_Nf));nCompInd++) - { - nCompIdent = m_anSofQuantCompId[nCompInd]; - if (!ValidateValue(m_anSofQuantCompId[nCompInd],0,255,_T("Component ID "),true,0)) return DECMARK_ERR; - if (!ValidateValue(m_anSofQuantTblSel_Tqi[nCompIdent],0,3,_T("Table Destination ID "),true,0)) return DECMARK_ERR; - if (!ValidateValue(m_anSofHorzSampFact_Hi[nCompIdent],1,4,_T("Horizontal Sampling Factor "),true,1)) return DECMARK_ERR; - if (!ValidateValue(m_anSofVertSampFact_Vi[nCompIdent],1,4,_T("Vertical Sampling Factor "),true,1)) return DECMARK_ERR; - } - - - // Finally, assign the cleaned values to the decoder - for (unsigned nCompInd=1;((!m_bStateAbort)&&(nCompInd<=m_nSofNumComps_Nf));nCompInd++) - { - nCompIdent = m_anSofQuantCompId[nCompInd]; - // Store the DQT Table selection for the Image Decoder - // Param values: Nf,Tqi - // Param ranges: 1..255,0..3 - // Note that the Image Decoder doesn't need to see the Component Identifiers - bRet = m_pImgDec->SetDqtTables(nCompInd,m_anSofQuantTblSel_Tqi[nCompIdent]); - DecodeErrCheck(bRet); - - // Store the Precision (to handle 12-bit decode) - m_pImgDec->SetPrecision(m_nSofPrecision_P); - - } - - if (!m_bStateAbort) { - - // Set the component sampling factors (chroma subsampling) - // FIXME: check ranging - for (unsigned nCompInd=1;nCompInd<=m_nSofNumComps_Nf;nCompInd++) { - // nCompInd is component index (1...Nf) - // nCompIdent is Component Identifier (Ci) - // Note that the Image Decoder doesn't need to see the Component Identifiers - nCompIdent = m_anSofQuantCompId[nCompInd]; - m_pImgDec->SetSofSampFactors(nCompInd,m_anSofHorzSampFact_Hi[nCompIdent],m_anSofVertSampFact_Vi[nCompIdent]); - } - - // Now mark the image as been somewhat OK (ie. should - // also be suitable for EmbeddedThumb() and PrepareSignature() - m_bImgOK = true; - - m_bStateSofOk = true; - - } - - if (!ExpectMarkerEnd(nPosMarkerStart,nLength)) - return DECMARK_ERR; - - break; - - - case JFIF_COM: // COM - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - m_nPos+=2; - strTmp.Format(_T(" Comment length = %u"),nLength); - m_pLog->AddLine(strTmp); - - // Check for JPEG COM vulnerability - // http://marc.info/?l=bugtraq&m=109524346729948 - // Note that the recovery is not very graceful. It will assume that the - // field is actually zero-length, which will make the next byte trigger the - // "Expected marker 0xFF" error message and probably abort. There is no - // obvious way to - - if ( (nLength == 0) || (nLength == 1) ) { - strTmp.Format(_T(" JPEG Comment Field Vulnerability detected!")); - m_pLog->AddLineErr(strTmp); - strTmp.Format(_T(" Skipping data until next marker...")); - m_pLog->AddLineErr(strTmp); - nLength = 2; - - bool bDoneSearch = false; - unsigned nSkipStart = m_nPos; - while (!bDoneSearch) { - if (Buf(m_nPos) != 0xFF) { - m_nPos++; - } else { - bDoneSearch = true; - } - if (m_nPos >= m_pWBuf->GetPosEof()) { - bDoneSearch = true; - } - } - strTmp.Format(_T(" Skipped %u bytes"),m_nPos - nSkipStart); - m_pLog->AddLineErr(strTmp); - - // Break out of case statement - break; - } - - // Assume COM field valid length (ie. >= 2) - strFull = _T(" Comment="); - m_strComment = _T(""); - for (unsigned ind=0;indAddLine(strFull); - - break; - - case JFIF_DHT: // DHT - m_bStateDht = true; - DecodeDHT(false); - m_bStateDhtOk = true; - break; - - case JFIF_SOS: // SOS - unsigned long nPosScanStart; // Byte count at start of scan data segment - - m_bStateSos = true; - - // NOTE: Only want to capture position of first SOS - // This should make other function such as AVI frame extract - // more robust in case we get multiple SOS segments. - // We assume that this value is reset when we start a new decode - if (m_nPosSos == 0) { - m_nPosSos = m_nPos-2; // Used for Extract. Want to include actual marker - } - - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - m_nPos+=2; - - // Ensure that we have seen proper markers before we try this one! - if (!m_bStateSofOk) { - strTmp.Format(_T(" ERROR: SOS before valid SOF defined")); - m_pLog->AddLineErr(strTmp); - return DECMARK_ERR; - } - - strTmp.Format(_T(" Scan header length = %u"),nLength); - m_pLog->AddLine(strTmp); - - m_nSosNumCompScan_Ns = Buf(m_nPos++); // Ns, range 1..4 -//XXX strTmp.Format(_T(" Number of image components = %u"),m_nSosNumCompScan_Ns); - strTmp.Format(_T(" Number of img components = %u"),m_nSosNumCompScan_Ns); - m_pLog->AddLine(strTmp); - - // Just in case something got corrupted, don't want to get out - // of range here. Note that this will be a hard abort, and - // will not resume decoding. - if (m_nSosNumCompScan_Ns > MAX_SOS_COMP_NS) { - strTmp.Format(_T(" ERROR: Scan decode does not support > %u components"),MAX_SOS_COMP_NS); - m_pLog->AddLineErr(strTmp); - return DECMARK_ERR; - } - - unsigned nSosCompSel_Cs; - unsigned nSosHuffTblSel; - unsigned nSosHuffTblSelDc_Td; - unsigned nSosHuffTblSelAc_Ta; - // Max range of components indices is between 1..4 - for (unsigned int nScanCompInd=1;((nScanCompInd<=m_nSosNumCompScan_Ns) && (!m_bStateAbort));nScanCompInd++) - { - strFull.Format(_T(" Component[%u]: "),nScanCompInd); - nSosCompSel_Cs = Buf(m_nPos++); // Cs, range 0..255 - nSosHuffTblSel = Buf(m_nPos++); - nSosHuffTblSelDc_Td = (nSosHuffTblSel & 0xf0)>>4; // Td, range 0..3 - nSosHuffTblSelAc_Ta = (nSosHuffTblSel & 0x0f); // Ta, range 0..3 - strTmp.Format(_T("selector=0x%02X, table=%u(DC),%u(AC)"),nSosCompSel_Cs,nSosHuffTblSelDc_Td,nSosHuffTblSelAc_Ta); - strFull += strTmp; - m_pLog->AddLine(strFull); - - bRet = m_pImgDec->SetDhtTables(nScanCompInd,nSosHuffTblSelDc_Td,nSosHuffTblSelAc_Ta); - - DecodeErrCheck(bRet); - } - - - m_nSosSpectralStart_Ss = Buf(m_nPos++); - m_nSosSpectralEnd_Se = Buf(m_nPos++); - m_nSosSuccApprox_A = Buf(m_nPos++); - - strTmp.Format(_T(" Spectral selection = %u .. %u"),m_nSosSpectralStart_Ss,m_nSosSpectralEnd_Se); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Successive approximation = 0x%02X"),m_nSosSuccApprox_A); - m_pLog->AddLine(strTmp); - - if (m_pAppConfig->bOutputScanDump) { - m_pLog->AddLine(_T("")); - m_pLog->AddLine(_T(" Scan Data: (after bitstuff removed)")); - } - - // Save the scan data segment position - nPosScanStart = m_nPos; - - // Skip over the Scan Data segment - // Pass 1) Quick, allowing for bOutputScanDump to dump first 640B. - // Pass 2) If bDecodeScanImg, we redo the process but in detail decoding. - - // FIXME: Not sure why, but if I skip over Pass 1 (eg if I leave in the - // following line uncommented), then I get an error at the end of the - // pass 2 decode (indicating that EOI marker not seen, and expecting - // marker). -// if (m_pAppConfig->bOutputScanDump) { - - // --- PASS 1 --- - bool bSkipDone; - unsigned nSkipCount; - unsigned nSkipData; - unsigned nSkipPos; - bool bScanDumpTrunc; - - bSkipDone = false; - nSkipCount = 0; - nSkipPos = 0; - bScanDumpTrunc = FALSE; - - strFull = _T(""); - while (!bSkipDone) - { - nSkipCount++; - nSkipPos++; - nSkipData = Buf(m_nPos++); - - if (nSkipData == 0xFF) { - // this could either be a marker or a byte stuff - nSkipData = Buf(m_nPos++); - nSkipCount++; - if (nSkipData == 0x00) { - // Byte stuff - nSkipData = 0xFF; - } else if ((nSkipData >= JFIF_RST0) && (nSkipData <= JFIF_RST7)) { - // Skip over - } else { - // Marker - bSkipDone = true; - m_nPos -= 2; - } - } - - if (m_pAppConfig->bOutputScanDump && (!bSkipDone) ) { - // Only display 20 lines of scan data - if (nSkipPos > 640) { - if (!bScanDumpTrunc) { - m_pLog->AddLineWarn(_T(" WARNING: Dump truncated.")); - bScanDumpTrunc = TRUE; - } - } else { - if ( ((nSkipPos-1) == 0) || (((nSkipPos-1) % 32) == 0) ) { - strFull = _T(" "); - } - - strTmp.Format(_T("%02x "),nSkipData); - strFull += strTmp; - - if (((nSkipPos-1) % 32) == 31) { - m_pLog->AddLine(strFull); - strFull = _T(""); - } - } - } - - // Did we run out of bytes? - - // FIXME: - // NOTE: This line here doesn't allow us to attempt to - // decode images that are missing EOI. Maybe this is - // not the best solution here? Instead, we should be - // checking m_nPos against file length? .. and not - // return but "break". - if (!m_pWBuf->GetBufOk()) { - strTmp.Format(_T("ERROR: Ran out of buffer before EOI during phase 1 of Scan decode @ 0x%08X"),m_nPos); - m_pLog->AddLineErr(strTmp); - break; - } - - } - m_pLog->AddLine(strFull); - -// } - - // --- PASS 2 --- - // If the option is set, start parsing! - if (m_pAppConfig->bDecodeScanImg && m_bImgSofUnsupported) { - // SOF marker was of type we don't support, so skip decoding - m_pLog->AddLineWarn(_T(" NOTE: Scan parsing doesn't support this SOF mode.")); -#ifndef DEBUG_YCCK - } else if (m_pAppConfig->bDecodeScanImg && (m_nSofNumComps_Nf == 4)) { - m_pLog->AddLineWarn(_T(" NOTE: Scan parsing doesn't support CMYK files yet.")); -#endif - } else if (m_pAppConfig->bDecodeScanImg && !m_bImgSofUnsupported) { - if (!m_bStateSofOk) { - m_pLog->AddLineWarn(_T(" NOTE: Scan decode disabled as SOF not decoded.")); - } else if (!m_bStateDqtOk) { - m_pLog->AddLineWarn(_T(" NOTE: Scan decode disabled as DQT not decoded.")); - } else if (!m_bStateDhtOk) { - m_pLog->AddLineWarn(_T(" NOTE: Scan decode disabled as DHT not decoded.")); - - } else { - m_pLog->AddLine(_T("")); - - // Set the primary image details - m_pImgDec->SetImageDetails(m_nSofSampsPerLine_X,m_nSofNumLines_Y, - m_nSofNumComps_Nf,m_nSosNumCompScan_Ns,m_nImgRstEn,m_nImgRstInterval); - - // Only recalculate the scan decoding if we need to (i.e. file - // changed, offset changed, scan option changed) - // TODO: In order to decode multiple scans, we will need to alter the - // way that m_pImgSrcDirty is set - if (m_pImgSrcDirty) { - m_pImgDec->DecodeScanImg(nPosScanStart,true,false); - m_pImgSrcDirty = false; - } - } - - } - - m_bStateSosOk = true; - - break; - - case JFIF_DRI: - unsigned nVal; - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - strTmp.Format(_T(" Length = %u"),nLength); - m_pLog->AddLine(strTmp); - nVal = Buf(m_nPos+2)*256 + Buf(m_nPos+3); - - // According to ITU-T spec B.2.4.4, we only expect - // restart markers if DRI value is non-zero! - m_nImgRstInterval = nVal; - if (nVal != 0) { - m_nImgRstEn = true; - } else { - m_nImgRstEn = false; - } - strTmp.Format(_T(" interval = %u"),m_nImgRstInterval); - m_pLog->AddLine(strTmp); - m_nPos += 4; - if (!ExpectMarkerEnd(nPosMarkerStart,nLength)) - return DECMARK_ERR; - break; - - case JFIF_EOI: // EOI - m_pLog->AddLine(_T("")); - - // Save the EOI file position - // NOTE: If the file is missing the EOI, then this variable will be - // set to mark the end of file. - m_nPosEmbedEnd = m_nPos; - m_nPosEoi = m_nPos; - m_bStateEoi = true; - - return DECMARK_EOI; - - break; - - // Markers that are not yet supported in JPEGsnoop - case JFIF_DHP: - // Markers defined for future use / extensions - case JFIF_JPG: - case JFIF_JPG0: - case JFIF_JPG1: - case JFIF_JPG2: - case JFIF_JPG3: - case JFIF_JPG4: - case JFIF_JPG5: - case JFIF_JPG6: - case JFIF_JPG7: - case JFIF_JPG8: - case JFIF_JPG9: - case JFIF_JPG10: - case JFIF_JPG11: - case JFIF_JPG12: - case JFIF_JPG13: - case JFIF_TEM: - // Unsupported marker - // - Provide generic decode based on length - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); // Length - strTmp.Format(_T(" Header length = %u"),nLength); - m_pLog->AddLine(strTmp); - m_pLog->AddLineWarn(_T(" Skipping unsupported marker")); - m_nPos += nLength; - break; - - case JFIF_RST0: - case JFIF_RST1: - case JFIF_RST2: - case JFIF_RST3: - case JFIF_RST4: - case JFIF_RST5: - case JFIF_RST6: - case JFIF_RST7: - // We don't expect to see restart markers outside the entropy coded segment. - // NOTE: RST# are standalone markers, so no length indicator exists - // But for the sake of robustness, we can check here to see if treating - // as a standalone marker will arrive at another marker (ie. OK). If not, - // proceed to assume there is a length indicator. - strTmp.Format(_T(" WARNING: Restart marker [0xFF%02X] detected outside scan"),nCode); - m_pLog->AddLineWarn(strTmp); - if (!m_pAppConfig->bRelaxedParsing) { - // Abort - m_pLog->AddLineErr(_T(" Stopping decode")); - m_pLog->AddLine(_T(" Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs")); - return DECMARK_ERR; - } else { - // Ignore - // Check to see if standalone marker treatment looks OK - if (Buf(m_nPos+2) == 0xFF) { - // Looks like standalone - m_pLog->AddLineWarn(_T(" Ignoring standalone marker. Proceeding with decode.")); - m_nPos += 2; - } else { - // Looks like marker with length - - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - strTmp.Format(_T(" Header length = %u"),nLength); - m_pLog->AddLine(strTmp); - m_pLog->AddLineWarn(_T(" Skipping marker")); - m_nPos += nLength; - } - } - break; - - default: - strTmp.Format(_T(" WARNING: Unknown marker [0xFF%02X]"),nCode); - m_pLog->AddLineWarn(strTmp); - if (!m_pAppConfig->bRelaxedParsing) { - // Abort - m_pLog->AddLineErr(_T(" Stopping decode")); - m_pLog->AddLine(_T(" Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs")); - return DECMARK_ERR; - } else { - // Skip - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - strTmp.Format(_T(" Header length = %u"),nLength); - m_pLog->AddLine(strTmp); - m_pLog->AddLineWarn(_T(" Skipping marker")); - m_nPos += nLength; - } - } - - // Add white-space between each marker - m_pLog->AddLine(_T(" ")); - - // If we decided to abort for any reason, make sure we trap it now. - // This will stop the ProcessFile() while loop. We can set m_bStateAbort - // if user says that they want to stop. - if (m_bStateAbort) { - return DECMARK_ERR; - } - - return DECMARK_OK; -} - - -// Print out a header for the current JFIF marker code -void CjfifDecode::AddHeader(unsigned nCode) -{ - CString strTmp; - - switch(nCode) - { - case JFIF_SOI: m_pLog->AddLineHdr(_T("*** Marker: SOI (xFFD8) ***")); break; - - case JFIF_APP0: m_pLog->AddLineHdr(_T("*** Marker: APP0 (xFFE0) ***")); break; - case JFIF_APP1: m_pLog->AddLineHdr(_T("*** Marker: APP1 (xFFE1) ***")); break; - case JFIF_APP2: m_pLog->AddLineHdr(_T("*** Marker: APP2 (xFFE2) ***")); break; - case JFIF_APP3: m_pLog->AddLineHdr(_T("*** Marker: APP3 (xFFE3) ***")); break; - case JFIF_APP4: m_pLog->AddLineHdr(_T("*** Marker: APP4 (xFFE4) ***")); break; - case JFIF_APP5: m_pLog->AddLineHdr(_T("*** Marker: APP5 (xFFE5) ***")); break; - case JFIF_APP6: m_pLog->AddLineHdr(_T("*** Marker: APP6 (xFFE6) ***")); break; - case JFIF_APP7: m_pLog->AddLineHdr(_T("*** Marker: APP7 (xFFE7) ***")); break; - case JFIF_APP8: m_pLog->AddLineHdr(_T("*** Marker: APP8 (xFFE8) ***")); break; - case JFIF_APP9: m_pLog->AddLineHdr(_T("*** Marker: APP9 (xFFE9) ***")); break; - case JFIF_APP10: m_pLog->AddLineHdr(_T("*** Marker: APP10 (xFFEA) ***")); break; - case JFIF_APP11: m_pLog->AddLineHdr(_T("*** Marker: APP11 (xFFEB) ***")); break; - case JFIF_APP12: m_pLog->AddLineHdr(_T("*** Marker: APP12 (xFFEC) ***")); break; - case JFIF_APP13: m_pLog->AddLineHdr(_T("*** Marker: APP13 (xFFED) ***")); break; - case JFIF_APP14: m_pLog->AddLineHdr(_T("*** Marker: APP14 (xFFEE) ***")); break; - case JFIF_APP15: m_pLog->AddLineHdr(_T("*** Marker: APP15 (xFFEF) ***")); break; - - case JFIF_SOF0: m_pLog->AddLineHdr(_T("*** Marker: SOF0 (Baseline DCT) (xFFC0) ***")); break; - case JFIF_SOF1: m_pLog->AddLineHdr(_T("*** Marker: SOF1 (Extended Sequential DCT, Huffman) (xFFC1) ***")); break; - case JFIF_SOF2: m_pLog->AddLineHdr(_T("*** Marker: SOF2 (Progressive DCT, Huffman) (xFFC2) ***")); break; - case JFIF_SOF3: m_pLog->AddLineHdr(_T("*** Marker: SOF3 (Lossless Process, Huffman) (xFFC3) ***")); break; - case JFIF_SOF5: m_pLog->AddLineHdr(_T("*** Marker: SOF5 (Differential Sequential DCT, Huffman) (xFFC4) ***")); break; - case JFIF_SOF6: m_pLog->AddLineHdr(_T("*** Marker: SOF6 (Differential Progressive DCT, Huffman) (xFFC5) ***")); break; - case JFIF_SOF7: m_pLog->AddLineHdr(_T("*** Marker: SOF7 (Differential Lossless Process, Huffman) (xFFC6) ***")); break; - case JFIF_SOF9: m_pLog->AddLineHdr(_T("*** Marker: SOF9 (Sequential DCT, Arithmetic) (xFFC9) ***")); break; - case JFIF_SOF10: m_pLog->AddLineHdr(_T("*** Marker: SOF10 (Progressive DCT, Arithmetic) (xFFCA) ***")); break; - case JFIF_SOF11: m_pLog->AddLineHdr(_T("*** Marker: SOF11 (Lossless Process, Arithmetic) (xFFCB) ***")); break; - case JFIF_SOF13: m_pLog->AddLineHdr(_T("*** Marker: SOF13 (Differential Sequential, Arithmetic) (xFFCD) ***")); break; - case JFIF_SOF14: m_pLog->AddLineHdr(_T("*** Marker: SOF14 (Differential Progressive DCT, Arithmetic) (xFFCE) ***")); break; - case JFIF_SOF15: m_pLog->AddLineHdr(_T("*** Marker: SOF15 (Differential Lossless Process, Arithmetic) (xFFCF) ***")); break; - - case JFIF_JPG: m_pLog->AddLineHdr(_T("*** Marker: JPG (xFFC8) ***")); break; - case JFIF_DAC: m_pLog->AddLineHdr(_T("*** Marker: DAC (xFFCC) ***")); break; - - case JFIF_RST0: - case JFIF_RST1: - case JFIF_RST2: - case JFIF_RST3: - case JFIF_RST4: - case JFIF_RST5: - case JFIF_RST6: - case JFIF_RST7: - m_pLog->AddLineHdr(_T("*** Marker: RST# ***")); - break; - - case JFIF_DQT: // Define quantization tables - m_pLog->AddLineHdr(_T("*** Marker: DQT (xFFDB) ***")); - m_pLog->AddLineHdrDesc(_T(" Define a Quantization Table.")); - break; - - - case JFIF_COM: // COM - m_pLog->AddLineHdr(_T("*** Marker: COM (Comment) (xFFFE) ***")); - break; - - case JFIF_DHT: // DHT - m_pLog->AddLineHdr(_T("*** Marker: DHT (Define Huffman Table) (xFFC4) ***")); - break; - case JFIF_DHT_FAKE: // DHT from standard table (MotionJPEG) - m_pLog->AddLineHdr(_T("*** Marker: DHT from MotionJPEG standard (Define Huffman Table) ***")); - break; - - case JFIF_SOS: // SOS - m_pLog->AddLineHdr(_T("*** Marker: SOS (Start of Scan) (xFFDA) ***")); - break; - - case JFIF_DRI: // DRI - m_pLog->AddLineHdr(_T("*** Marker: DRI (Restart Interval) (xFFDD) ***")); - break; - - case JFIF_EOI: // EOI - m_pLog->AddLineHdr(_T("*** Marker: EOI (End of Image) (xFFD9) ***")); - break; - - case JFIF_DNL: m_pLog->AddLineHdr(_T("*** Marker: DNL (Define Number of Lines) (xFFDC) ***")); break; - case JFIF_DHP: m_pLog->AddLineHdr(_T("*** Marker: DHP (Define Hierarchical Progression) (xFFDE) ***")); break; - case JFIF_EXP: m_pLog->AddLineHdr(_T("*** Marker: EXP (Expand Reference Components) (xFFDF) ***")); break; - case JFIF_JPG0: m_pLog->AddLineHdr(_T("*** Marker: JPG0 (JPEG Extension) (xFFF0) ***")); break; - case JFIF_JPG1: m_pLog->AddLineHdr(_T("*** Marker: JPG1 (JPEG Extension) (xFFF1) ***")); break; - case JFIF_JPG2: m_pLog->AddLineHdr(_T("*** Marker: JPG2 (JPEG Extension) (xFFF2) ***")); break; - case JFIF_JPG3: m_pLog->AddLineHdr(_T("*** Marker: JPG3 (JPEG Extension) (xFFF3) ***")); break; - case JFIF_JPG4: m_pLog->AddLineHdr(_T("*** Marker: JPG4 (JPEG Extension) (xFFF4) ***")); break; - case JFIF_JPG5: m_pLog->AddLineHdr(_T("*** Marker: JPG5 (JPEG Extension) (xFFF5) ***")); break; - case JFIF_JPG6: m_pLog->AddLineHdr(_T("*** Marker: JPG6 (JPEG Extension) (xFFF6) ***")); break; - case JFIF_JPG7: m_pLog->AddLineHdr(_T("*** Marker: JPG7 (JPEG Extension) (xFFF7) ***")); break; - case JFIF_JPG8: m_pLog->AddLineHdr(_T("*** Marker: JPG8 (JPEG Extension) (xFFF8) ***")); break; - case JFIF_JPG9: m_pLog->AddLineHdr(_T("*** Marker: JPG9 (JPEG Extension) (xFFF9) ***")); break; - case JFIF_JPG10: m_pLog->AddLineHdr(_T("*** Marker: JPG10 (JPEG Extension) (xFFFA) ***")); break; - case JFIF_JPG11: m_pLog->AddLineHdr(_T("*** Marker: JPG11 (JPEG Extension) (xFFFB) ***")); break; - case JFIF_JPG12: m_pLog->AddLineHdr(_T("*** Marker: JPG12 (JPEG Extension) (xFFFC) ***")); break; - case JFIF_JPG13: m_pLog->AddLineHdr(_T("*** Marker: JPG13 (JPEG Extension) (xFFFD) ***")); break; - case JFIF_TEM: m_pLog->AddLineHdr(_T("*** Marker: TEM (Temporary) (xFF01) ***")); break; - - - - default: - strTmp.Format(_T("*** Marker: ??? (Unknown) (xFF%02X) ***"),nCode); - m_pLog->AddLineHdr(strTmp); - break; - } - // Adjust position to account for the word used in decoding the marker! - strTmp.Format(_T(" OFFSET: 0x%08X"),m_nPos-2); - m_pLog->AddLine(strTmp); -} - - -// Update the status bar with a message -void CjfifDecode::SetStatusText(CString strText) -{ - // Make sure that we have been connected to the status - // bar of the main window first! Note that it is jpegsnoopDoc - // that sets this variable. - if (m_pStatBar) { - m_pStatBar->SetPaneText(0,strText); - } -} - -// Generate a special output form of the current image's -// compression signature and other characteristics. This is only -// used during development and batch import to build the MySQL repository. -void CjfifDecode::OutputSpecial() -{ - CString strTmp; - CString strFull; - - ASSERT(m_eImgLandscape!=ENUM_LANDSCAPE_UNSET); - - // This mode of operation is currently only used - // to import the local signature database into a MySQL database - // backend. It simply reports the MySQL commands which can be input - // into a MySQL client application. - if (m_bOutputDB) - { - m_pLog->AddLine(_T("*** DB OUTPUT START ***")); - m_pLog->AddLine(_T("INSERT INTO `quant` (`key`, `make`, `model`, ")); - m_pLog->AddLine(_T("`qual`, `subsamp`, `lum_00`, `lum_01`, `lum_02`, `lum_03`, `lum_04`, ")); - m_pLog->AddLine(_T("`lum_05`, `lum_06`, `lum_07`, `chr_00`, `chr_01`, `chr_02`, ")); - m_pLog->AddLine(_T("`chr_03`, `chr_04`, `chr_05`, `chr_06`, `chr_07`, `qual_lum`, `qual_chr`) VALUES (")); - - strFull = _T("'*KEY*', "); // key -- need to override - - // Might need to change m_strImgExifMake to be lowercase - strTmp.Format(_T("'%s', "),(LPCTSTR)m_strImgExifMake); - strFull += strTmp; // make - - strTmp.Format(_T("'%s', "),(LPCTSTR)m_strImgExifModel); - strFull += strTmp; // model - - strTmp.Format(_T("'%s', "),(LPCTSTR)m_strImgQualExif); - strFull += strTmp; // quality - - strTmp.Format(_T("'%s', "),(LPCTSTR)m_strImgQuantCss); - strFull += strTmp; // subsampling - - m_pLog->AddLine(strFull); - - // Step through both quantization tables (0=lum,1=chr) - unsigned nMatrixInd; - - for (unsigned nDqtInd=0;nDqtInd<2;nDqtInd++) { - - strFull = _T(""); - for (unsigned nY=0;nY<8;nY++) { - strFull += _T("'"); - for (unsigned nX=0;nX<8;nX++) { - // Rotate the matrix if necessary! - nMatrixInd = (m_eImgLandscape!=ENUM_LANDSCAPE_NO)?(nY*8+nX):(nX*8+nY); - strTmp.Format(_T("%u"),m_anImgDqtTbl[nDqtInd][nMatrixInd]); - strFull += strTmp; - if (nX!=7) { strFull += _T(","); } - } - strFull += _T("', "); - if (nY==3) { - m_pLog->AddLine(strFull); - strFull = _T(""); - } - } - m_pLog->AddLine(strFull); - - } - - strFull = _T(""); - // Output quality ratings - strTmp.Format(_T("'%f', "),m_adImgDqtQual[0]); - strFull += strTmp; - // Don't put out comma separator on last line! - strTmp.Format(_T("'%f'"),m_adImgDqtQual[1]); - strFull += strTmp; - strFull += _T(");"); - m_pLog->AddLine(strFull); - - m_pLog->AddLine(_T("*** DB OUTPUT END ***")); - } - -} - -// Generate the compression signatures (both unrotated and -// rotated) in advance of submitting to the database. -void CjfifDecode::PrepareSignature() -{ - // Set m_strHash - PrepareSignatureSingle(false); - // Set m_strHashRot - PrepareSignatureSingle(true); -} - -// Prepare the image signature for later submission -// NOTE: ASCII vars are used (instead of unicode) to support usage of MD5 library -void CjfifDecode::PrepareSignatureSingle(bool bRotate) -{ - CStringA strTmp; - CStringA strSet; - - CStringA strHashIn; - unsigned char pHashIn[2000]; - CStringA strDqt; - MD5_CTX sMd5; - unsigned nLenHashIn; - unsigned nInd; - - ASSERT(m_eImgLandscape!=ENUM_LANDSCAPE_UNSET); - - // ----------------------------------------------------------- - // Calculate the MD5 hash for online/internal database! - // signature "00" : DQT0,DQT1,CSS - // signature "01" : salt,DQT0,DQT1,..DQTx(if defined) - - - // Build the source string - // NOTE: For the purposes of the hash, we need to rotate the DQT tables - // if we detect that the photo is in portrait orientation! This keeps everything - // consistent. - - - // If no DQT tables have been defined (e.g. could have loaded text file!) - // then override the sig generation! - bool bDqtDefined = false; - for (unsigned nSet=0;nSet<4;nSet++) { - if (m_abImgDqtSet[nSet]) { - bDqtDefined = true; - } - } - if (!bDqtDefined) { - m_strHash = _T("NONE"); - m_strHashRot = _T("NONE"); - return; - } - - // NOTE: - // The following MD5 code depends on an ASCII string for input - // We are therefore using CStringA for the hash input instead - // of the generic text functions. No special (non-ASCII) - // characters are expected in this string. - - if (DB_SIG_VER == 0x00) { - strHashIn = ""; - } else { - strHashIn = "JPEGsnoop"; - } - - // Need to duplicate DQT0 if we only have one DQT table - for (unsigned nSet=0;nSet<4;nSet++) { - if (m_abImgDqtSet[nSet]) { - strSet = ""; - strSet.Format("*DQT%u,",nSet); - strHashIn += strSet; - for (unsigned i=0;i<64;i++) { - nInd = (!bRotate)?i:glb_anQuantRotate[i]; - strTmp.Format("%03u,",m_anImgDqtTbl[nSet][nInd]); - strHashIn += strTmp; - } - } // if DQTx defined - } // loop through sets (DQT0..DQT3) - - // Removed CSS from signature after version 0x00 - if (DB_SIG_VER == 0x00) { - strHashIn += "*CSS,"; - strHashIn += m_strImgQuantCss; - strHashIn += ","; - } - strHashIn += "*END"; - nLenHashIn = strlen(strHashIn); - - // Display hash input - for (unsigned i=0;iAddLine(strTmp); -#endif - } - - // Copy into buffer - ASSERT(nLenHashIn < 2000); - for (unsigned i=0;iAddLine(strTmp); -#endif - } - - // Copy into buffer - ASSERT(nLenHashIn < 2000); - for (unsigned i=0;iDisable(); } - - - m_pLog->AddLine(_T("")); - m_pLog->AddLineHdr(_T("*** Searching Compression Signatures ***")); - m_pLog->AddLine(_T("")); - - // Output the hash - strHashOut = _T(" Signature: "); - strHashOut += m_strHash; - m_pLog->AddLine(strHashOut); - strHashOut = _T(" Signature (Rotated): "); - strHashOut += m_strHashRot; - m_pLog->AddLine(strHashOut); - - strTmp.Format(_T(" File Offset: %lu bytes"),m_pAppConfig->nPosStart); - m_pLog->AddLine(strTmp); - - // Output the CSS - strTmp.Format(_T(" Chroma subsampling: %s"),(LPCTSTR)m_strImgQuantCss); - m_pLog->AddLine(strTmp); - - - // Calculate the final fields - // Add Photoshop IRB entries - // Note that we always add an entry to the m_strImgExtras even if - // there are no photoshop tags detected. It will appear as "[PS]:[0/0]" - strTmp = _T(""); - strTmp.Format(_T("[PS]:[%u/%u],"),m_nImgQualPhotoshopSa,m_nImgQualPhotoshopSfw); - m_strImgExtras += strTmp; - - - // -------------------------------------- - // Determine current entry fields - - // Note that some cameras/phones have an empty Make, but use the Model! (eg. Palm Treo) - if ((m_strImgExifMake == _T("???")) && (m_strImgExifModel == _T("???"))) { - m_pLog->AddLine(_T(" EXIF Make/Model: NONE")); - bCurXmm = false; - } else { - strTmp.Format(_T(" EXIF Make/Model: OK [%s] [%s]"),(LPCTSTR)m_strImgExifMake,(LPCTSTR)m_strImgExifModel); - m_pLog->AddLine(strTmp); - bCurXmm = true; - } - - if (m_bImgExifMakernotes) { - m_pLog->AddLine(_T(" EXIF Makernotes: OK ")); - bCurXmkr = true; - } else { - m_pLog->AddLine(_T(" EXIF Makernotes: NONE")); - bCurXmkr = false; - } - - if (_tcslen(m_strSoftware) == 0) { - m_pLog->AddLine(_T(" EXIF Software: NONE")); - bCurXsw = false; - } else { - strTmp.Format(_T(" EXIF Software: OK [%s]"),(LPCTSTR)m_strSoftware); - m_pLog->AddLine(strTmp); - - // EXIF software field is non-empty - bCurXsw = true; - } - - m_pLog->AddLine(_T("")); - - // -------------------------------------- - // Determine search results - - - // All of the rest of the search results require searching - // through the database entries - - bSrchXswUsig = false; - bSrchXmmUsig = false; - bSrchUsig = false; - bMatchIjg = false; - sMatchIjgQual = _T(""); - - unsigned nSigsInternal = theApp.m_pDbSigs->GetNumSigsInternal(); - unsigned nSigsExtra = theApp.m_pDbSigs->GetNumSigsExtra(); - - strTmp.Format(_T(" Searching Compression Signatures: (%u built-in, %u user(*) )"),nSigsInternal,nSigsExtra); - m_pLog->AddLine(strTmp); - - - // Now in SIG version 0x01 and later, we are not including - // the CSS in the signature. Therefore, we need to compare it - // manually. - - bool curMatchMm; - bool curMatchSw; - bool curMatchSig; - bool curMatchSigCss; - - - // Check on Extras field - // Noted that Canon EOS Viewer Utility (EVU) seems to convert RAWs with - // the only identifying information being this: - // e.g. "[Canon.ImageType]:[CRW:EOS 300D DIGITAL CMOS RAW],_T(" - if (m_strImgExtras.Find(_T(")[Canon.ImageType]:[CRW:")) != -1) { - bCurXextrasw = true; - } - if (m_strImgExtras.Find(_T("[Nikon1.Quality]:[RAW")) != -1) { - bCurXextrasw = true; - } - if (m_strImgExtras.Find(_T("[Nikon2.Quality]:[RAW")) != -1) { - bCurXextrasw = true; - } - if (m_strImgExtras.Find(_T("[Nikon3.Quality]:[RAW")) != -1) { - bCurXextrasw = true; - } - if ((m_nImgQualPhotoshopSa != 0) || (m_nImgQualPhotoshopSfw != 0)) { - bCurXps = true; - } - - // Search for known COMment field indicators - if (theApp.m_pDbSigs->SearchCom(m_strComment)) { - bCurXcomsw = true; - } - - m_pLog->AddLine(_T("")); - m_pLog->AddLine(_T(" EXIF.Make / Software EXIF.Model Quality Subsamp Match?")); - m_pLog->AddLine(_T(" ------------------------- ----------------------------------- ---------------- --------------")); - - CompSig pEntry; - unsigned ind_max = theApp.m_pDbSigs->GetDBNumEntries(); - for (ind=0;indGetDBEntry(ind,&pEntry); - - // Reset current entry state - curMatchMm = false; - curMatchSw = false; - curMatchSig = false; - curMatchSigCss = false; - - // Compare make/model (only for digicams) - if ((pEntry.eEditor == ENUM_EDITOR_CAM) && - (bCurXmm == true) && - (pEntry.strXMake == m_strImgExifMake) && - (pEntry.strXModel == m_strImgExifModel) ) - { - curMatchMm = true; - } - - // For software entries, do a loose search - if ((pEntry.eEditor == ENUM_EDITOR_SW) && - (bCurXsw == true) && - (pEntry.strMSwTrim != _T("")) && - (m_strSoftware.Find(pEntry.strMSwTrim) != -1) ) - { - // Software field matches known software string - bSrchXsw = true; - curMatchSw = true; - } - - - // Compare signature (and CSS for digicams) - if ( (pEntry.strCSig == m_strHash) || (pEntry.strCSigRot == m_strHash) || - (pEntry.strCSig == m_strHashRot) || (pEntry.strCSigRot == m_strHashRot) ) - { - curMatchSig = true; - - // If Database entry is for an editor, sig matches irrespective of CSS - if (pEntry.eEditor == ENUM_EDITOR_SW) { - bSrchUsig = true; - curMatchSigCss = true; // FIXME: do I need this? - - // For special case of IJG - if (pEntry.strMSwDisp == _T("IJG Library")) { - bMatchIjg = true; - sMatchIjgQual = pEntry.strUmQual; - } - - } else { - // Database entry is for a digicam, sig match only if CSS matches too - if (pEntry.strXSubsamp == m_strImgQuantCss) { - bSrchUsig = true; - curMatchSigCss = true; - } else { - curMatchSigCss = false; - } - - } // editor - - } else { - // sig doesn't match - curMatchSig = false; - curMatchSigCss = false; - } - - - // For digicams: - if (curMatchMm && curMatchSigCss) { - bSrchXmmUsig = true; - } - // For software: - if (curMatchSw && curMatchSig) { - bSrchXswUsig = true; - } - - if (theApp.m_pDbSigs->IsDBEntryUser(ind)) { - locationStr = _T("*"); - } else { - locationStr = _T(" "); - } - - // Display entry if it is a good match - if (curMatchSig) { - if (pEntry.eEditor==ENUM_EDITOR_CAM) { - strTmp.Format(_T(" %s%4s[%-25s] [%-35s] [%-16s] %-5s %-5s %-5s"),(LPCTSTR)locationStr,_T("CAM:"), - (LPCTSTR)pEntry.strXMake.Left(25),(LPCTSTR)pEntry.strXModel.Left(35),(LPCTSTR)pEntry.strUmQual.Left(16), - (curMatchSigCss?_T("Yes"):_T("No")),_T(""),_T("")); - } else if (pEntry.eEditor==ENUM_EDITOR_SW) { - strTmp.Format(_T(" %s%4s[%-25s] %-35s [%-16s] %-5s %-5s %-5s"),(LPCTSTR)locationStr,_T("SW :"), - (LPCTSTR)pEntry.strMSwDisp.Left(25),_T(""),(LPCTSTR)pEntry.strUmQual.Left(16), - _T(""),_T(""),_T("")); - } else { - strTmp.Format(_T(" %s%4s[%-25s] [%-35s] [%-16s] %-5s %-5s %-5s"),(LPCTSTR)locationStr,_T("?? :"), - (LPCTSTR)pEntry.strXMake.Left(25),(LPCTSTR)pEntry.strXModel.Left(35),(LPCTSTR)pEntry.strUmQual.Left(16), - _T(""),_T(""),_T("")); - } - if (curMatchMm || curMatchSw) { - m_pLog->AddLineGood(strTmp); - } else { - m_pLog->AddLine(strTmp); - } - - } - - - } // loop through DB - - CString strSw; - // If it matches an IJG signature, report other possible sources: - if (bMatchIjg) { - m_pLog->AddLine(_T("")); - m_pLog->AddLine(_T(" The following IJG-based editors also match this signature:")); - unsigned nIjgNum; - CString strIjgSw; - nIjgNum = theApp.m_pDbSigs->GetIjgNum(); - for (ind=0;indGetIjgEntry(ind); - strTmp.Format(_T(" %4s[%-25s] %-35s [%-16s] %-5s %-5s %-5s"),_T("SW :"), - (LPCTSTR)strIjgSw.Left(25),_T(""),(LPCTSTR)sMatchIjgQual.Left(16), - _T(""),_T(""),_T("")); - m_pLog->AddLine(strTmp); - } - } - - //m_pLog->AddLine(_T(" -------------------- ----------------------------------- ---------------- --------------")); - m_pLog->AddLine(_T("")); - - if (bCurXps) { - m_pLog->AddLine(_T(" NOTE: Photoshop IRB detected")); - } - if (bCurXextrasw) { - m_pLog->AddLine(_T(" NOTE: Additional EXIF fields indicate software processing")); - } - if (bSrchXsw) { - m_pLog->AddLine(_T(" NOTE: EXIF Software field recognized as from editor")); - } - if (bCurXcomsw) { - m_pLog->AddLine(_T(" NOTE: JFIF COMMENT field is known software")); - } - - - - // ============================================ - // Image Assessment Algorithm - // ============================================ - - bool bEditDefinite = false; - bool bEditLikely = false; - bool bEditNot = false; - bool bEditNotUnknownSw = false; - - if (bCurXps) { - bEditDefinite = true; - } - if (!bCurXmm) { - bEditDefinite = true; - } - if (bCurXextrasw) { - bEditDefinite = true; - } - if (bCurXcomsw) { - bEditDefinite = true; - } - if (bSrchXsw) { - // Software field matches known software string - bEditDefinite = true; - } - if (theApp.m_pDbSigs->LookupExcMmIsEdit(m_strImgExifMake,m_strImgExifModel)) { - // Make/Model is in exception list of ones that mark known software - bEditDefinite = true; - } - - if (!bCurXmkr) { - // If we are missing maker notes, we are almost always dealing with - // edited images. There are some known exceptions, so far: - // - Very old digicams - // - Certain camera phones - // - Blackberry - // Perhaps we can make an exception for particular digicams (based on - // make/model) that this determination will not apply. This means that - // we open up the doors for these files being edited and not caught. - - if (theApp.m_pDbSigs->LookupExcMmNoMkr(m_strImgExifMake,m_strImgExifModel)) { - // This is a known exception! - } else { - bEditLikely = true; - } - } - - - // Filter down remaining scenarios - if (!bEditDefinite && !bEditLikely) { - - if (bSrchXmmUsig) { - // DB cam signature matches DQT & make/model - if (!bCurXsw) { - // EXIF software field is empty - // - // We can now be pretty confident that this file has not - // been edited by all the means that we are checking - bEditNot = true; - } else { - // EXIF software field is set - // - // This field is often used by: - // - Software editors (edited) - // - RAW converter software (edited) - // - Digicams to indicate firmware (original) - // - Phones to indicate firmware (original) - // - // However, in generating bEditDefinite, we have already - // checked for bSrchXsw which looked for known software - // strings. Therefore, we will primarily be left with - // firmware strings, etc. - // - // We will mark this as NOT EDITED but with caution of unknown SW field - bEditNot = true; - bEditNotUnknownSw = true; - } - } else { - // No DB cam signature matches DQT & make/model - // According to EXIF data, this file does not appear to be edited, - // but no compression signatures in the database match this - // particular make/model. Therefore, result is UNSURE. - } - - } - - - // Now make final assessment call - - - - // Determine if image has been processed/edited - m_eImgEdited = EDITED_UNSET; - if (bEditDefinite) { - m_eImgEdited = EDITED_YES; - } else if (bEditLikely) { - m_eImgEdited = EDITED_YESPROB; - } else if (bEditNot) { - // Images that fall into this category will have: - // - No Photoshop tags - // - Make/Model is present - // - Makernotes present - // - No extra software tags (eg. IFD) - // - No comment field with known software - // - No software field or it does not match known software - // - Signature matches DB for this make/model - m_eImgEdited = EDITED_NO; - } else { - // Images that fall into this category will have: - // - Same as EDITED_NO but: - // - Signature does not match DB for this make/model - // In all likelihood, this image will in fact be original - m_eImgEdited = EDITED_UNSURE; - } - - - - - // If the file offset is non-zero, then don't ask for submit or show assessment - if (m_pAppConfig->nPosStart != 0) { - m_pLog->AddLine(_T(" ASSESSMENT not done as file offset non-zero")); - if (bQuiet) { m_pLog->Enable(); } - return false; - } - - // ============================================ - // Display final assessment - // ============================================ - - m_pLog->AddLine(_T(" Based on the analysis of compression characteristics and EXIF metadata:")); - m_pLog->AddLine(_T("")); - if (m_eImgEdited == EDITED_YES) { - m_pLog->AddLine(_T(" ASSESSMENT: Class 1 - Image is processed/edited")); - } else if (m_eImgEdited == EDITED_YESPROB) { - m_pLog->AddLine(_T(" ASSESSMENT: Class 2 - Image has high probability of being processed/edited")); - } else if (m_eImgEdited == EDITED_NO) { - m_pLog->AddLine(_T(" ASSESSMENT: Class 3 - Image has high probability of being original")); - // In case the EXIF Software field was detected, - if (bEditNotUnknownSw) { - m_pLog->AddLine(_T(" Note that EXIF Software field is set (typically contains Firmware version)")); - } - } else if (m_eImgEdited == EDITED_UNSURE) { - m_pLog->AddLine(_T(" ASSESSMENT: Class 4 - Uncertain if processed or original")); - m_pLog->AddLine(_T(" While the EXIF fields indicate original, no compression signatures ")); - m_pLog->AddLine(_T(" in the current database were found matching this make/model")); - } else { - m_pLog->AddLineErr(_T(" ASSESSMENT: *** Failed to complete ***")); - } - m_pLog->AddLine(_T("")); - - - - // Determine if user should add entry to DB - bool bDbReqAdd = false; // Ask user to add - bool bDbReqAddAuto = false; // Automatically add (in batch operation) - - - // TODO: This section should be rewritten to reduce complexity - - m_eDbReqSuggest = DB_ADD_SUGGEST_UNSET; - if (m_eImgEdited == EDITED_NO) { - bDbReqAdd = false; - m_eDbReqSuggest = DB_ADD_SUGGEST_CAM; - } else if (m_eImgEdited == EDITED_UNSURE) { - bDbReqAdd = true; - bDbReqAddAuto = true; - m_eDbReqSuggest = DB_ADD_SUGGEST_CAM; - m_pLog->AddLine(_T(" Appears to be new signature for known camera.")); - m_pLog->AddLine(_T(" If the camera/software doesn't appear in list above,")); - m_pLog->AddLineWarn(_T(" PLEASE ADD TO DATABASE with [Tools->Add Camera to DB]")); - } else if (bCurXps && bSrchUsig) { - // Photoshop and we already have sig - bDbReqAdd = false; - m_eDbReqSuggest = DB_ADD_SUGGEST_SW; - } else if (bCurXps && !bSrchUsig) { - // Photoshop and we don't already have sig - bDbReqAdd = true; - bDbReqAddAuto = true; - m_eDbReqSuggest = DB_ADD_SUGGEST_SW; - m_pLog->AddLine(_T(" Appears to be new signature for Photoshop.")); - m_pLog->AddLine(_T(" If it doesn't appear in list above,")); - m_pLog->AddLineWarn(_T(" PLEASE ADD TO DATABASE with [Tools->Add Camera to DB]")); - } else if (bCurXsw && bSrchXsw && bSrchXswUsig) { - bDbReqAdd = false; - m_eDbReqSuggest = DB_ADD_SUGGEST_SW; - } else if (bCurXextrasw) { - bDbReqAdd = false; - m_eDbReqSuggest = DB_ADD_SUGGEST_SW; - } else if (bCurXsw && bSrchXsw && !bSrchXswUsig) { - bDbReqAdd = true; - //bDbReqAddAuto = true; - m_eDbReqSuggest = DB_ADD_SUGGEST_SW; - m_pLog->AddLine(_T(" Appears to be new signature for known software.")); - m_pLog->AddLine(_T(" If the camera/software doesn't appear in list above,")); - m_pLog->AddLineWarn(_T(" PLEASE ADD TO DATABASE with [Tools->Add Camera to DB]")); - } else if (bCurXmm && bCurXmkr && !bSrchXsw && !bSrchXmmUsig) { - // unsure if cam, so ask user - bDbReqAdd = true; - bDbReqAddAuto = true; - m_eDbReqSuggest = DB_ADD_SUGGEST_CAM; - m_pLog->AddLine(_T(" This may be a new camera for the database.")); - m_pLog->AddLine(_T(" If this file is original, and camera doesn't appear in list above,")); - m_pLog->AddLineWarn(_T(" PLEASE ADD TO DATABASE with [Tools->Add Camera to DB]")); - } else if (!bCurXmm && !bCurXmkr && !bSrchXsw) { - // unsure if SW, so ask user - bDbReqAdd = true; - m_eDbReqSuggest = DB_ADD_SUGGEST_SW; - m_pLog->AddLine(_T(" This may be a new software editor for the database.")); - m_pLog->AddLine(_T(" If this file is processed, and editor doesn't appear in list above,")); - m_pLog->AddLineWarn(_T(" PLEASE ADD TO DATABASE with [Tools->Add Camera to DB]")); - } - - - m_pLog->AddLine(_T("")); - - // ----------------------------------------------------------- - - if (bQuiet) { m_pLog->Enable(); } - -#ifdef BATCH_DO_DBSUBMIT_ALL - bDbReqAddAuto = true; -#endif - - // Return a value that indicates whether or not we should add this - // entry to the database - return bDbReqAddAuto; - -} - - -// Build the image data string that will be sent to the database repository -// This data string contains the compression siganture and a few special -// fields such as image dimensions, etc. -// -// If Portrait, Rotates DQT table, Width/Height. -// m_strImgQuantCss is already rotated by ProcessFile() -// PRE: m_strHash already defined -void CjfifDecode::PrepareSendSubmit(CString strQual,teSource eUserSource,CString strUserSoftware,CString strUserNotes) -{ - // Generate the DQT arrays suitable for posting - CString strTmp1; - CString asDqt[4]; - unsigned nMatrixInd; - - ASSERT(m_strHash != _T("NONE")); - ASSERT(m_eImgLandscape!=ENUM_LANDSCAPE_UNSET); - - for (unsigned nSet=0;nSet<4;nSet++) { - asDqt[nSet] = _T(""); - - if (m_abImgDqtSet[nSet]) { - for (unsigned nInd=0;nInd<64;nInd++) { - // FIXME: Still consider rotating DQT table even though we - // don't know for sure if m_eImgLandscape is accurate - // Not a big deal if we get it wrong as we still add - // both pre- and post-rotated sigs. - nMatrixInd = (m_eImgLandscape!=ENUM_LANDSCAPE_NO)?nInd:glb_anQuantRotate[nInd]; - if ((nInd%8 == 0) && (nInd != 0)) { - asDqt[nSet].Append(_T("!")); - } - - asDqt[nSet].AppendFormat(_T("%u"),m_anImgDqtTbl[nSet][nMatrixInd]); - if (nInd%8 != 7) { - asDqt[nSet].Append(_T(",")); - } - } - } // set defined? - } // up to 4 sets - - unsigned nOrigW,nOrigH; - nOrigW = (m_eImgLandscape!=ENUM_LANDSCAPE_NO)?m_nSofSampsPerLine_X:m_nSofNumLines_Y; - nOrigH = (m_eImgLandscape!=ENUM_LANDSCAPE_NO)?m_nSofNumLines_Y:m_nSofSampsPerLine_X; - - unsigned nOrigThumbW,nOrigThumbH; - nOrigThumbW = (m_eImgLandscape!=ENUM_LANDSCAPE_NO)?m_nImgThumbSampsPerLine:m_nImgThumbNumLines; - nOrigThumbH = (m_eImgLandscape!=ENUM_LANDSCAPE_NO)?m_nImgThumbNumLines:m_nImgThumbSampsPerLine; - - teMaker eMaker; - eMaker = (m_bImgExifMakernotes)?ENUM_MAKER_PRESENT:ENUM_MAKER_NONE; - - // Sort sig additions - // To create some determinism in the database, arrange the sigs - // to be in numerical order - CString strSig0,strSig1,strSigThm0,strSigThm1; - if (m_strHash <= m_strHashRot) { - strSig0 = m_strHash; - strSig1 = m_strHashRot; - } else { - strSig0 = m_strHashRot; - strSig1 = m_strHash; - } - if (m_strHashThumb <= m_strHashThumbRot) { - strSigThm0 = m_strHashThumb; - strSigThm1 = m_strHashThumbRot; - } else { - strSigThm0 = m_strHashThumbRot; - strSigThm1 = m_strHashThumb; - } - - SendSubmit(m_strImgExifMake,m_strImgExifModel,strQual,asDqt[0],asDqt[1],asDqt[2],asDqt[3],m_strImgQuantCss, - strSig0,strSig1,strSigThm0,strSigThm1,(float)m_adImgDqtQual[0],(float)m_adImgDqtQual[1],nOrigW,nOrigH, - m_strSoftware,m_strComment,eMaker,eUserSource,strUserSoftware,m_strImgExtras, - strUserNotes,m_eImgLandscape,nOrigThumbW,nOrigThumbH); - -} - - -// Send the compression signature string to the local database file -// in addition to the web repository if the user has enabled it. -void CjfifDecode::SendSubmit(CString strExifMake, CString strExifModel, CString strQual, - CString strDqt0, CString strDqt1, CString strDqt2, CString strDqt3, - CString strCss, - CString strSig, CString strSigRot, CString strSigThumb, - CString strSigThumbRot, float fQFact0, float fQFact1, unsigned nImgW, unsigned nImgH, - CString strExifSoftware, CString strComment, teMaker eMaker, - teSource eUserSource, CString strUserSoftware, CString strExtra, - CString strUserNotes, unsigned nExifLandscape, - unsigned nThumbX,unsigned nThumbY) -{ - // NOTE: This assumes that we've already run PrepareSignature() - // which usually happens when we process a file. - ASSERT(strSig != _T("")); - ASSERT(strSigRot != _T("")); - - CUrlString curls; - - // Version "03": (v1.8.0+) - // - Adds JPEGsnoop version (js_ver) to enable signature source correction - CString DB_SUBMIT_WWW_VER = _T("03"); - -#ifndef BATCH_DO - if (m_bSigExactInDB) { - if (m_pAppConfig->bInteractive) - AfxMessageBox(_T("Compression signature already in database")); - } else { - - // Now append it to the local database and resave - theApp.m_pDbSigs->DatabaseExtraAdd(strExifMake,strExifModel, - strQual,strSig,strSigRot,strCss,eUserSource,strUserSoftware); - - if (m_pAppConfig->bInteractive) - AfxMessageBox(_T("Added Compression signature to database")); - } -#endif - - - // Is automatic internet update enabled? - if (!theApp.m_pAppConfig->bDbSubmitNet) { - return; - } - - CString strTmp; - - CString strFormat; - CString strFormDataPre; - CString strFormData; - unsigned nFormDataLen; - - unsigned nChecksum=32; - CString strSubmitHost; - CString strSubmitPage; - strSubmitHost = IA_HOST; - strSubmitPage = IA_DB_SUBMIT_PAGE; - for (unsigned i=0;i<_tcslen(IA_HOST);i++) { - nChecksum += strSubmitHost.GetAt(i); - nChecksum += 3*strSubmitPage.GetAt(i); - } - - //if ( (m_pAppConfig->bIsWindowsNTorLater) && (nChecksum == 9678) ) { - if (nChecksum == 9678) { - - // Submit to online database - // - Mark the encoding as UTF-8 - CString strHeaders = - _T("Content-Type: application/x-www-form-urlencoded; charset=utf-8"); - - // URL-encoded form variables - - strFormat = _T("ver=%s&js_ver=%s&x_make=%s&x_model=%s&um_qual=%s&x_dqt0=%s&x_dqt1=%s&x_dqt2=%s&x_dqt3=%s"); - strFormat += _T("&x_subsamp=%s&c_sig=%s&c_sigrot=%s&c_qfact0=%f&c_qfact1=%f&x_img_w=%u&x_img_h=%u"); - strFormat += _T("&x_sw=%s&x_com=%s&x_maker=%u&u_source=%d&u_sw=%s"); - strFormat += _T("&x_extra=%s&u_notes=%s&c_sigthumb=%s&c_sigthumbrot=%s&x_landscape=%u"); - strFormat += _T("&x_thumbx=%u&x_thumby=%u"); - - - strFormDataPre.Format(strFormat, - (LPCTSTR)DB_SUBMIT_WWW_VER,(LPCTSTR)VERSION_STR,(LPCTSTR)strExifMake,(LPCTSTR)strExifModel, - (LPCTSTR)strQual,(LPCTSTR)strDqt0,(LPCTSTR)strDqt1,(LPCTSTR)strDqt2,(LPCTSTR)strDqt3, - (LPCTSTR)strCss,(LPCTSTR)strSig,(LPCTSTR)strSigRot,fQFact0,fQFact1,nImgW,nImgH, - (LPCTSTR)strExifSoftware,(LPCTSTR)strComment, - eMaker,eUserSource,(LPCTSTR)strUserSoftware, - (LPCTSTR)strExtra,(LPCTSTR)strUserNotes, - (LPCTSTR)strSigThumb, (LPCTSTR)strSigThumbRot,nExifLandscape,nThumbX,nThumbY); - - //*** Need to sanitize data for URL submission! - // Search for "&", "?", "=" - strFormData.Format(strFormat, - (LPCTSTR)DB_SUBMIT_WWW_VER,(LPCTSTR)VERSION_STR,(LPCTSTR)curls.Encode(strExifMake),(LPCTSTR)curls.Encode(strExifModel), - (LPCTSTR)strQual,(LPCTSTR)strDqt0,(LPCTSTR)strDqt1,(LPCTSTR)strDqt2,(LPCTSTR)strDqt3, - (LPCTSTR)strCss,(LPCTSTR)strSig,(LPCTSTR)strSigRot,fQFact0,fQFact1,nImgW,nImgH, - (LPCTSTR)curls.Encode(strExifSoftware),(LPCTSTR)curls.Encode(strComment), - eMaker,eUserSource,(LPCTSTR)curls.Encode(strUserSoftware), - (LPCTSTR)curls.Encode(strExtra),(LPCTSTR)curls.Encode(strUserNotes), - (LPCTSTR)strSigThumb,(LPCTSTR)strSigThumbRot,nExifLandscape,nThumbX,nThumbY); - - nFormDataLen = strFormData.GetLength(); - - -#ifdef DEBUG_SIG - if (m_pAppConfig->bInteractive) { - AfxMessageBox(strFormDataPre); - AfxMessageBox(strFormData); - } -#endif - -#ifdef WWW_WININET - //static LPSTR astrAcceptTypes[2]={"*/*", NULL}; - HINTERNET hINet = NULL; - HINTERNET hConnection = NULL; - HINTERNET hData = NULL; - - hINet = InternetOpen(_T("JPEGsnoop/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ); - if ( !hINet ) - { - if (m_pAppConfig->bInteractive) - AfxMessageBox(_T("InternetOpen Failed")); - return; - } - try - { - hConnection = InternetConnect( hINet, (LPCTSTR)strSubmitHost, 80, NULL,NULL, INTERNET_SERVICE_HTTP, 0, 1 ); - if ( !hConnection ) - { - InternetCloseHandle(hINet); - return; - } - hData = HttpOpenRequest( hConnection, _T("POST"), (LPCTSTR)strSubmitPage, NULL, NULL, NULL, 0, 1 ); - if ( !hData ) - { - InternetCloseHandle(hConnection); - InternetCloseHandle(hINet); - return; - } - // GET HttpSendRequest( hData, NULL, 0, NULL, 0); - - // POST requests from HttpSendRequest() don't work well with - // unicode, so convert from unicode to ANSI - CStringA strHeadersA = CW2A(strHeaders,CP_UTF8); - CStringA strFormDataA = CW2A(strFormData,CP_UTF8); - HttpSendRequestA( hData, strHeadersA, strHeadersA.GetLength(), strFormDataA.GetBuffer(), strFormDataA.GetLength()); - - } - catch( CInternetException* e) - { - e->ReportError(); - e->Delete(); - //AfxMessageBox(_T("EXCEPTION!")); - } - InternetCloseHandle(hConnection); - InternetCloseHandle(hINet); - InternetCloseHandle(hData); -#endif - -#ifdef WWW_WINHTTP - - CInternetSession sSession; - CHttpConnection* pConnection; - CHttpFile* pFile; - BOOL bResult; - DWORD dwRet; - - // *** NOTE: Will not work on Windows 95/98! - // This section is avoided in early OSes otherwise we get an Illegal Op - try { - pConnection = sSession.GetHttpConnection(submit_host); - ASSERT (pConnection); - pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,_T(submit_page)); - ASSERT (pFile); - bResult = pFile->SendRequest( - strHeaders,(LPVOID)(LPCTSTR)strFormData, strFormData.GetLength()); - ASSERT (bResult != 0); - pFile->QueryInfoStatusCode(dwRet); - ASSERT (dwRet == HTTP_STATUS_OK); - - // Clean up! - if (pFile) { - pFile->Close(); - delete pFile; - pFile = NULL; - } - if (pConnection) { - pConnection->Close(); - delete pConnection; - pConnection = NULL; - } - sSession.Close(); - - } - - catch (CInternetException* pEx) - { - // catch any exceptions from WinINet - TCHAR szErr[MAX_BUF_EX_ERR_MSG]; - szErr[0] = '\0'; - if(!pEx->GetErrorMessage(szErr, MAX_BUF_EX_ERR_MSG)) - _tcscpy(szErr,_T("Unknown error")); - TRACE("Submit Failed! - %s",szErr); - if (m_pAppConfig->bInteractive) - AfxMessageBox(szErr); - pEx->Delete(); - if(pFile) - delete pFile; - if(pConnection) - delete pConnection; - session.Close(); - return; - } -#endif - - - - } - -} - - -// Parse the embedded JPEG thumbnail. This routine is a much-reduced -// version of the main JFIF parser, in that it focuses primarily on the -// DQT tables. -void CjfifDecode::DecodeEmbeddedThumb() -{ - CString strTmp; - CString strMarker; - unsigned nPosSaved; - unsigned nPosSaved_sof; - unsigned nPosEnd; - bool bDone; - unsigned nCode; - bool bRet; - - CString strFull; - unsigned nDqtPrecision_Pq; - unsigned nDqtQuantDestId_Tq; - unsigned nImgPrecision; - unsigned nLength; - unsigned nTmpVal; - bool bScanSkipDone; - bool bErrorAny = false; - bool bErrorThumbLenZero = false; - unsigned nSkipCount; - - nPosSaved = m_nPos; - - // Examine the EXIF embedded thumbnail (if it exists) - if (m_nImgExifThumbComp == 6) { - m_pLog->AddLine(_T("")); - m_pLog->AddLineHdr(_T("*** Embedded JPEG Thumbnail ***")); - strTmp.Format(_T(" Offset: 0x%08X"),m_nImgExifThumbOffset); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Length: 0x%08X (%u)"),m_nImgExifThumbLen,m_nImgExifThumbLen); - m_pLog->AddLine(strTmp); - - // Quick scan for DQT tables - m_nPos = m_nImgExifThumbOffset; - bDone = false; - while (!bDone) { - - // For some reason, I have found files that have a nLength of 0 - if (m_nImgExifThumbLen != 0) { - if ((m_nPos-m_nImgExifThumbOffset) > m_nImgExifThumbLen) { - strTmp.Format(_T("ERROR: Read more than specified EXIF thumb nLength (%u bytes) before EOI"),m_nImgExifThumbLen); - m_pLog->AddLineErr(strTmp); - bErrorAny = true; - bDone = true; - } - } else { - // Don't try to process if nLength is 0! - // Seen this in a Canon 1ds file (processed by photoshop) - bDone = true; - bErrorAny = true; - bErrorThumbLenZero = true; - } - if ((!bDone) && (Buf(m_nPos++) != 0xFF)) { - strTmp.Format(_T("ERROR: Expected marker 0xFF, got 0x%02X @ offset 0x%08X"),Buf(m_nPos-1),(m_nPos-1)); - m_pLog->AddLineErr(strTmp); - bErrorAny = true; - bDone = true; - - } - - - - if (!bDone) { - nCode = Buf(m_nPos++); - - m_pLog->AddLine(_T("")); - switch (nCode) { - case JFIF_SOI: // SOI - m_pLog->AddLine(_T(" * Embedded Thumb Marker: SOI")); - break; - - case JFIF_DQT: // Define quantization tables - m_pLog->AddLine(_T(" * Embedded Thumb Marker: DQT")); - - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - nPosEnd = m_nPos+nLength; - m_nPos+=2; - strTmp.Format(_T(" Length = %u"),nLength); - m_pLog->AddLine(strTmp); - - while (nPosEnd > m_nPos) - { - strTmp.Format(_T(" ----")); - m_pLog->AddLine(strTmp); - - nTmpVal = Buf(m_nPos++); - nDqtPrecision_Pq = (nTmpVal & 0xF0) >> 4; - nDqtQuantDestId_Tq = nTmpVal & 0x0F; - CString strPrecision = _T(""); - if (nDqtPrecision_Pq == 0) { - strPrecision = _T("8 bits"); - } else if (nDqtPrecision_Pq == 1) { - strPrecision = _T("16 bits"); - } else { - strPrecision.Format(_T("??? unknown [value=%u]"),nDqtPrecision_Pq); - } - - strTmp.Format(_T(" Precision=%s"),(LPCTSTR)strPrecision); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Destination ID=%u"),nDqtQuantDestId_Tq); - // NOTE: The mapping between destination IDs and the actual - // usage is defined in the SOF marker which is often later. - // In nearly all images, the following is true. However, I have - // seen some test images that set Tbl 3 = Lum, Tbl 0=Chr, - // Tbl1=Chr, and Tbl2 undefined - if (nDqtQuantDestId_Tq == 0) { - strTmp += _T(" (Luminance, typically)"); - } - else if (nDqtQuantDestId_Tq == 1) { - strTmp += _T(" (Chrominance, typically)"); - } - else if (nDqtQuantDestId_Tq == 2) { - strTmp += _T(" (Chrominance, typically)"); - } - else { - strTmp += _T(" (???)"); - } - m_pLog->AddLine(strTmp); - - - if (nDqtQuantDestId_Tq >= 4) { - strTmp.Format(_T("ERROR: nDqtQuantDestId_Tq = %u, >= 4"),nDqtQuantDestId_Tq); - m_pLog->AddLineErr(strTmp); - bDone = true; - bErrorAny = true; - break; - } - - for (unsigned nInd=0;nInd<=63;nInd++) - { - nTmpVal = Buf(m_nPos++); - m_anImgThumbDqt[nDqtQuantDestId_Tq][glb_anZigZag[nInd]] = nTmpVal; - } - m_abImgDqtThumbSet[nDqtQuantDestId_Tq] = true; - - // Now display the table - for (unsigned nY=0;nY<8;nY++) { - strFull.Format(_T(" DQT, Row #%u: "),nY); - for (unsigned nX=0;nX<8;nX++) { - strTmp.Format(_T("%3u "),m_anImgThumbDqt[nDqtQuantDestId_Tq][nY*8+nX]); - strFull += strTmp; - - // Store the DQT entry into the Image DenCoder - bRet = m_pImgDec->SetDqtEntry(nDqtQuantDestId_Tq,nY*8+nX, - glb_anUnZigZag[nY*8+nX],m_anImgDqtTbl[nDqtQuantDestId_Tq][nY*8+nX]); - DecodeErrCheck(bRet); - - } - - m_pLog->AddLine(strFull); - - } - - } - - break; - - case JFIF_SOF0: - m_pLog->AddLine(_T(" * Embedded Thumb Marker: SOF")); - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - nPosSaved_sof = m_nPos; - m_nPos+=2; - strTmp.Format(_T(" Frame header length = %u"),nLength); - m_pLog->AddLine(strTmp); - - - nImgPrecision = Buf(m_nPos++); - strTmp.Format(_T(" Precision = %u"),nImgPrecision); - m_pLog->AddLine(strTmp); - - m_nImgThumbNumLines = Buf(m_nPos)*256 + Buf(m_nPos+1); - m_nPos += 2; - strTmp.Format(_T(" Number of Lines = %u"),m_nImgThumbNumLines); - m_pLog->AddLine(strTmp); - - m_nImgThumbSampsPerLine = Buf(m_nPos)*256 + Buf(m_nPos+1); - m_nPos += 2; - strTmp.Format(_T(" Samples per Line = %u"),m_nImgThumbSampsPerLine); - m_pLog->AddLine(strTmp); - strTmp.Format(_T(" Image Size = %u x %u"),m_nImgThumbSampsPerLine,m_nImgThumbNumLines); - m_pLog->AddLine(strTmp); - - m_nPos = nPosSaved_sof+nLength; - - break; - - case JFIF_SOS: // SOS - m_pLog->AddLine(_T(" * Embedded Thumb Marker: SOS")); - m_pLog->AddLine(_T(" Skipping scan data")); - bScanSkipDone = false; - nSkipCount = 0; - while (!bScanSkipDone) { - if ((Buf(m_nPos) == 0xFF) && (Buf(m_nPos+1) != 0x00)) { - // Was it a restart marker? - if ((Buf(m_nPos+1) >= JFIF_RST0) && (Buf(m_nPos+1) <= JFIF_RST7)) { - m_nPos++; - } else { - // No... it's a real marker - bScanSkipDone = true; - } - } else { - m_nPos++; - nSkipCount++; - } - } - strTmp.Format(_T(" Skipped %u bytes"),nSkipCount); - m_pLog->AddLine(strTmp); - break; - - case JFIF_EOI: - m_pLog->AddLine(_T(" * Embedded Thumb Marker: EOI")); - bDone = true; - break; - - case JFIF_RST0: - case JFIF_RST1: - case JFIF_RST2: - case JFIF_RST3: - case JFIF_RST4: - case JFIF_RST5: - case JFIF_RST6: - case JFIF_RST7: - break; - - default: - GetMarkerName(nCode,strMarker); - strTmp.Format(_T(" * Embedded Thumb Marker: %s"),(LPCTSTR)strMarker); - m_pLog->AddLine(strTmp); - nLength = Buf(m_nPos)*256 + Buf(m_nPos+1); - strTmp.Format(_T(" Length = %u"),nLength); - m_pLog->AddLine(strTmp); - m_nPos += nLength; - break; - - } - } // if !bDone - } // while !bDone - - // Now calculate the signature - if (!bErrorAny) { - PrepareSignatureThumb(); - m_pLog->AddLine(_T("")); - strTmp.Format(_T(" * Embedded Thumb Signature: %s"),(LPCTSTR)m_strHashThumb); - m_pLog->AddLine(strTmp); - } - - if (bErrorThumbLenZero) { - m_strHashThumb = _T("ERR: Len=0"); - m_strHashThumbRot = _T("ERR: Len=0"); - } - - } // if JPEG compressed - - m_nPos = nPosSaved; -} - - -// Lookup the EXIF marker name from the code value -bool CjfifDecode::GetMarkerName(unsigned nCode,CString &markerStr) -{ - bool bDone = false; - bool bFound = false; - unsigned nInd=0; - - while (!bDone) - { - if (m_pMarkerNames[nInd].nCode==0) { - bDone = true; - } else if (m_pMarkerNames[nInd].nCode==nCode) { - bDone = true; - bFound = true; - markerStr = m_pMarkerNames[nInd].strName; - return true; - } else { - nInd++; - } - } - if (!bFound) { - markerStr = _T(""); - markerStr.Format(_T("(0xFF%02X)"),nCode); - return false; - } - return true; - -} - - -// Determine if the file is an AVI MJPEG. -// If so, parse the headers. -// TODO: Expand this function to use sub-functions for each block type -bool CjfifDecode::DecodeAvi() -{ - CString strTmp; - unsigned nPosSaved; - - m_bAvi = false; - m_bAviMjpeg = false; - - // Perhaps start from file position 0? - nPosSaved = m_nPos; - - // Start from file position 0 - m_nPos = 0; - - bool bSwap = true; - - CString strRiff; - unsigned nRiffLen; - CString strForm; - - strRiff = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - nRiffLen = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - strForm = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - if ((strRiff == _T("RIFF")) && (strForm == _T("AVI "))) { - m_bAvi = true; - m_pLog->AddLine(_T("")); - m_pLog->AddLineHdr(_T("*** AVI File Decoding ***")); - m_pLog->AddLine(_T("Decoding RIFF AVI format...")); - m_pLog->AddLine(_T("")); - } else { - // Reset file position - m_nPos = nPosSaved; - return false; - } - - CString strHeader; - unsigned nChunkSize; - unsigned nChunkDataStart; - - bool done = false; - while (!done) { - if (m_nPos >= m_pWBuf->GetPosEof()) { - done = true; - break; - } - - strHeader = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - strTmp.Format(_T(" %s"),(LPCTSTR)strHeader); - m_pLog->AddLine(strTmp); - - nChunkSize = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - nChunkDataStart = m_nPos; - - - if (strHeader == _T("LIST")) { - - // --- LIST --- - - CString strListType; - strListType = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - - strTmp.Format(_T(" %s"),(LPCTSTR)strListType); - m_pLog->AddLine(strTmp); - - if (strListType == _T("hdrl")) { - - // --- hdrl --- - - unsigned nPosHdrlStart; - CString strHdrlId; - strHdrlId = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - unsigned nHdrlLen; - nHdrlLen = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - nPosHdrlStart = m_nPos; - - // nHdrlLen should be 14*4 bytes - - m_nPos = nPosHdrlStart + nHdrlLen; - - } else if (strListType == _T("strl")) { - - // --- strl --- - - // strhHEADER - unsigned nPosStrlStart; - CString strStrlId; - strStrlId = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - unsigned nStrhLen; - nStrhLen = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - nPosStrlStart = m_nPos; - - CString fccType; - CString fccHandler; - unsigned dwFlags,dwReserved1,dwInitialFrames,dwScale,dwRate; - unsigned dwStart,dwLength,dwSuggestedBufferSize,dwQuality; - unsigned dwSampleSize,xdwQuality,xdwSampleSize; - fccType = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - fccHandler = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - dwFlags = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - dwReserved1 = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - dwInitialFrames = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - dwScale = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - dwRate = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - dwStart = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - dwLength = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - dwSuggestedBufferSize = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - dwQuality = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - dwSampleSize = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - xdwQuality = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - xdwSampleSize = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - - CString fccTypeDecode = _T(""); - if (fccType == _T("vids")) { fccTypeDecode = _T("[vids] Video"); } - else if (fccType == _T("auds")) { fccTypeDecode = _T("[auds] Audio"); } - else if (fccType == _T("txts")) { fccTypeDecode = _T("[txts] Subtitle"); } - else { fccTypeDecode.Format(_T("[%s]"),(LPCTSTR)fccType); } - strTmp.Format(_T(" -[FourCC Type] = %s"),(LPCTSTR)fccTypeDecode); - m_pLog->AddLine(strTmp); - - strTmp.Format(_T(" -[FourCC Codec] = [%s]"),(LPCTSTR)fccHandler); - m_pLog->AddLine(strTmp); - - float fSampleRate = 0; - if (dwScale != 0) { - fSampleRate = (float)dwRate / (float)dwScale; - } - strTmp.Format(_T(" -[Sample Rate] = [%.2f]"),fSampleRate); - if (fccType == _T("vids")) { strTmp.Append(_T(" frames/sec")); } - else if (fccType == _T("auds")) { strTmp.Append(_T(" samples/sec")); } - m_pLog->AddLine(strTmp); - - m_nPos = nPosStrlStart + nStrhLen; // Skip - - strTmp.Format(_T(" %s"),(LPCTSTR)fccType); - m_pLog->AddLine(strTmp); - - if (fccType == _T("vids")) { - // --- vids --- - - // Is it MJPEG? - //strTmp.Format(_T(" -[Video Stream FourCC]=[%s]"),fccHandler); - //m_pLog->AddLine(strTmp); - if (fccHandler == _T("mjpg")) { - m_bAviMjpeg = true; - } - if (fccHandler == _T("MJPG")) { - m_bAviMjpeg = true; - } - - // strfHEADER_BIH - CString strSkipId; - unsigned nSkipLen; - unsigned nSkipStart; - strSkipId = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - nSkipLen = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - nSkipStart = m_nPos; - - m_nPos = nSkipStart + nSkipLen; // Skip - - } else if (fccType == _T("auds")) { - // --- auds --- - - // strfHEADER_WAVE - - CString strSkipId; - unsigned nSkipLen; - unsigned nSkipStart; - strSkipId = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - nSkipLen = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - nSkipStart = m_nPos; - - m_nPos = nSkipStart + nSkipLen; // Skip - } else { - // strfHEADER - - CString strSkipId; - unsigned nSkipLen; - unsigned nSkipStart; - strSkipId = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - nSkipLen = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - nSkipStart = m_nPos; - - m_nPos = nSkipStart + nSkipLen; // Skip - } - - // strnHEADER - unsigned nPosStrnStart; - CString strStrnId; - strStrnId = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - unsigned nStrnLen; - nStrnLen = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - nPosStrnStart = m_nPos; - - // FIXME: Can we rewrite in terms of ChunkSize and ChunkDataStart? - //ASSERT ((nPosStrnStart + nStrnLen + (nStrnLen%2)) == (nChunkDataStart + nChunkSize + (nChunkSize%2))); - //m_nPos = nChunkDataStart + nChunkSize + (nChunkSize%2); - m_nPos = nPosStrnStart + nStrnLen + (nStrnLen%2); // Skip - - } else if (strListType == _T("movi")) { - // movi - - m_nPos = nChunkDataStart + nChunkSize + (nChunkSize%2); - } else if (strListType == _T("INFO")) { - // INFO - unsigned nInfoStart; - nInfoStart = m_nPos; - - CString strInfoId; - unsigned nInfoLen; - strInfoId = m_pWBuf->BufReadStrn(m_nPos,4); m_nPos+=4; - nInfoLen = m_pWBuf->BufX(m_nPos,4,bSwap); m_nPos+=4; - - if (strInfoId == _T("ISFT")) { - CString strIsft=_T(""); - strIsft = m_pWBuf->BufReadStrn(m_nPos,nChunkSize); - strIsft.TrimRight(); - strTmp.Format(_T(" -[Software] = [%s]"),(LPCTSTR)strIsft); - m_pLog->AddLine(strTmp); - } - - m_nPos = nChunkDataStart + nChunkSize + (nChunkSize%2); - } else { - // ? - m_nPos = nChunkDataStart + nChunkSize + (nChunkSize%2); - } - - } else if (strHeader == _T("JUNK")) { - // Junk - - m_nPos = nChunkDataStart + nChunkSize + (nChunkSize%2); - } else if (strHeader == _T("IDIT")) { - // Timestamp info (Canon, etc.) - - CString strIditTimestamp=_T(""); - strIditTimestamp = m_pWBuf->BufReadStrn(m_nPos,nChunkSize); - strIditTimestamp.TrimRight(); - strTmp.Format(_T(" -[Timestamp] = [%s]"),(LPCTSTR)strIditTimestamp); - m_pLog->AddLine(strTmp); - - m_nPos = nChunkDataStart + nChunkSize + (nChunkSize%2); - - } else if (strHeader == _T("indx")) { - // Index - - m_nPos = nChunkDataStart + nChunkSize + (nChunkSize%2); - } else if (strHeader == _T("idx1")) { - // Index - //unsigned nIdx1Entries = nChunkSize / (4*4); - - m_nPos = nChunkDataStart + nChunkSize + (nChunkSize%2); - - } else { - // Unsupported - m_nPos = nChunkDataStart + nChunkSize + (nChunkSize%2); - - } - - } - - m_pLog->AddLine(_T("")); - if (m_bAviMjpeg) { - m_strImgExtras += _T("[AVI]:[mjpg],"); - m_pLog->AddLineGood(_T(" AVI is MotionJPEG")); - m_pLog->AddLineWarn(_T(" Use [Tools->Img Search Fwd] to locate next frame")); - } else { - m_strImgExtras += _T("[AVI]:[????],"); - m_pLog->AddLineWarn(_T(" AVI is not MotionJPEG. [Img Search Fwd/Rev] unlikely to find frames.")); - } - m_pLog->AddLine(_T("")); - - // Reset file position - m_nPos = nPosSaved; - - return m_bAviMjpeg; -} - - - -// This is the primary JFIF parsing routine. -// The main loop steps through all of the JFIF markers and calls -// DecodeMarker() each time until we reach the end of file or an error. -// Finally, we invoke the compression signature search function. -// -// Processing starts at the file offset m_pAppConfig->nPosStart -// -// INPUT: -// - inFile = Input file pointer -// -// PRE: -// - m_pAppConfig->nPosStart = Starting file offset for decode -// -void CjfifDecode::ProcessFile(CFile* inFile) -{ - - CString strTmp; - - // Reset the JFIF decoder state as we may be redoing another file - Reset(); - - // Reset the IMG Decoder state - if (m_pImgSrcDirty) { - m_pImgDec->ResetState(); - } - - // Set the statusbar text to Processing... - - // Ensure the status bar has been allocated - // NOTE: The stat bar is NULL if we drag & drop a file onto - // the JPEGsnoop app icon. - if (m_pStatBar) { - m_pStatBar->SetPaneText(0,_T("Processing...")); - } - - - // Note that we don't clear out the logger (with m_pLog->Reset()) - // as we want top-level caller to do this. This way we can - // still insert extra lines from top level. - - // GetLength returns ULONGLONG. Abort on large files (>=4GB) - ULONGLONG nPosFileEnd; - nPosFileEnd = inFile->GetLength(); - if (nPosFileEnd > 0xFFFFFFFFUL) { - strTmp = _T("File too large. Skipping."); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return; - } - m_nPosFileEnd = static_cast(nPosFileEnd); - - - unsigned nStartPos; - nStartPos = m_pAppConfig->nPosStart; - m_nPos = nStartPos; - m_nPosEmbedStart = nStartPos; // Save the embedded file start position - - strTmp.Format(_T("Start Offset: 0x%08X"),nStartPos); - m_pLog->AddLine(strTmp); - - - // ---------------------------------------------------------------- - - // Test for AVI file - // - Detect header - // - start from beginning of file - DecodeAvi(); - // TODO: Should we skip decode of file if not MJPEG? - - - // ---------------------------------------------------------------- - - // Test for PSD file - // - Detect header - // - FIXME: start from current offset? - unsigned nWidth=0; - unsigned nHeight=0; - -#ifdef PS_IMG_DEC_EN - // If PSD image decoding is enabled, associate the PSD parsing with - // the current DIB. After decoding, flag the DIB as ready for display. - - // Attempt decode as PSD - bool bDecPsdOk; - bDecPsdOk = m_pPsDec->DecodePsd(nStartPos,&m_pImgDec->m_pDibTemp,nWidth,nHeight); - if (bDecPsdOk) { - // FIXME: The following is a bit of a hack - m_pImgDec->m_bDibTempReady = true; - m_pImgDec->m_bPreviewIsJpeg = false; // MCU/Block info not available - m_pImgDec->SetImageDimensions(nWidth,nHeight); - - // Clear the image information - // The primary reason for this is to ensure we don't have stale information from a previous - // JPEG image (eg. real image border inside MCU border which would be overlayed during draw). - m_pImgDec->SetImageDetails(0,0,0,0,false,0); - - // No more processing of file - // - Otherwise we'd continue to attempt to decode as JPEG - return; - } -#else - // Don't attempt to display Photoshop image data - if (m_pPsDec->DecodePsd(nStartPos,NULL,nWidth,nHeight)) { - return; - } -#endif - - - // ---------------------------------------------------------------- - -// Disable DICOM for now until fully tested -#ifdef SUPPORT_DICOM - // Test for DICOM - // - Detect header - // - start from beginning of file - bool bDicom = false; - unsigned long nPosJpeg = 0; // File offset to embedded JPEG in DICOM - bDicom = m_pDecDicom->DecodeDicom(0,m_nPosFileEnd,nPosJpeg); - if (bDicom) { - // Adjust start of JPEG decoding if we are currently without an offset - if (nStartPos == 0) { - m_pAppConfig->nPosStart = nPosJpeg; - - nStartPos = m_pAppConfig->nPosStart; - m_nPos = nStartPos; - m_nPosEmbedStart = nStartPos; // Save the embedded file start position - - strTmp.Format(_T("Adjusting Start Offset to: 0x%08X"),nStartPos); - m_pLog->AddLine(strTmp); - m_pLog->AddLine(_T("")); - } - } -#endif - - - // ---------------------------------------------------------------- - - // Decode as JPEG JFIF file - - // If we are in a non-zero offset, add this to extras - if (m_pAppConfig->nPosStart!=0) { - strTmp.Format(_T("[Offset]=[%lu],"),m_pAppConfig->nPosStart); - m_strImgExtras += strTmp; - } - - unsigned nDataAfterEof = 0; - - BOOL bDone = FALSE; - while (!bDone) - { - // Allow some other threads to jump in - - // Return value 0 - OK - // 1 - Error - // 2 - EOI - if (DecodeMarker() != DECMARK_OK) { - bDone = TRUE; - if (m_nPosFileEnd >= m_nPosEoi) { - nDataAfterEof = m_nPosFileEnd - m_nPosEoi; - } - } else { - if (m_nPos > m_pWBuf->GetPosEof()) { - m_pLog->AddLineErr(_T("ERROR: Early EOF - file may be missing EOI")); - bDone = TRUE; - } - } - } - - // ----------------------------------------------------------- - // Perform any other informational calculations that require all tables - // to be present. - - // Determine the CSS Ratio - // Save the subsampling string. Assume component 2 is representative of the overall chrominance. - - // NOTE: Ensure that we don't execute the following code if we haven't - // completed our read (ie. get bad marker earlier in processing). - // TODO: What is the best way to determine all is OK? - - m_strImgQuantCss = _T("?x?"); - m_strHash = _T("NONE"); - m_strHashRot = _T("NONE"); - - if (m_bImgOK) { - ASSERT(m_eImgLandscape!=ENUM_LANDSCAPE_UNSET); - - if (m_nSofNumComps_Nf == NUM_CHAN_YCC) { - // We only try to determine the chroma subsampling ratio if we have 3 components (assume YCC) - // In general, we should be able to use the 2nd or 3rd component - - // NOTE: The following assumes m_anSofHorzSampFact_Hi and m_anSofVertSampFact_Vi - // are non-zero as otherwise we'll have a divide-by-0 exception. - unsigned nCompIdent = m_anSofQuantCompId[SCAN_COMP_CB]; - unsigned nCssFactH = m_nSofHorzSampFactMax_Hmax/m_anSofHorzSampFact_Hi[nCompIdent]; - unsigned nCssFactV = m_nSofVertSampFactMax_Vmax/m_anSofVertSampFact_Vi[nCompIdent]; - if (m_eImgLandscape!=ENUM_LANDSCAPE_NO) { - // Landscape orientation - m_strImgQuantCss.Format(_T("%ux%u"),nCssFactH,nCssFactV); - } - else { - // Portrait orientation (flip subsampling ratio) - m_strImgQuantCss.Format(_T("%ux%u"),nCssFactV,nCssFactH); - } - } else if (m_nSofNumComps_Nf == NUM_CHAN_GRAYSCALE) { - m_strImgQuantCss = _T("Gray"); - } - - DecodeEmbeddedThumb(); - - // Generate the signature - PrepareSignature(); - - // Compare compression signature - if (m_pAppConfig->bSigSearch) { - // In the case of lossless files, there won't be any DQT and - // hence no compression signatures to compare. Therefore, skip this process. - if (m_strHash == _T("NONE")) { - m_pLog->AddLineWarn(_T("Skipping compression signature search as no DQT")); - } else { - CompareSignature(); - } - } - - if (nDataAfterEof > 0) { - m_pLog->AddLine(_T("")); - m_pLog->AddLineHdr(_T("*** Additional Info ***")); - strTmp.Format(_T("NOTE: Data exists after EOF, range: 0x%08X-0x%08X (%u bytes)"), - m_nPosEoi,m_nPosFileEnd,nDataAfterEof); - m_pLog->AddLine(strTmp); - } - - // Print out the special-purpose outputs - OutputSpecial(); - } - - - // Reset the status bar text - if (m_pStatBar) { - m_pStatBar->SetPaneText(0,_T("Done")); - } - - // Mark the file as closed - //m_pWBuf->BufFileUnset(); - -} - - -// Determine if the analyzed file is in a state ready for image -// extraction. Confirms that the important JFIF markers have been -// detected in the previous analysis. -// -// PRE: -// - m_nPosEmbedStart -// - m_nPosEmbedEnd -// - m_nPosFileEnd -// -// RETURN: -// - True if image is ready for extraction -// -bool CjfifDecode::ExportJpegPrepare(CString strFileIn,bool bForceSoi,bool bForceEoi,bool bIgnoreEoi) -{ - // Extract from current file - // [m_nPosEmbedStart ... m_nPosEmbedEnd] - // If state is valid (i.e. file opened) - - CString strTmp = _T(""); - - m_pLog->AddLine(_T("")); - m_pLog->AddLineHdr(_T("*** Exporting JPEG ***")); - - strTmp.Format(_T(" Exporting from: [%s]"),(LPCTSTR)strFileIn); - m_pLog->AddLine(strTmp); - - // Only bother to extract if all main sections are present - bool bExtractWarn = false; - CString strMissing = _T(""); - - if (!m_bStateEoi) { - if (!bForceEoi && !bIgnoreEoi) { - strTmp.Format(_T(" ERROR: Missing marker: %s"),_T("EOI")); - m_pLog->AddLineErr(strTmp); - m_pLog->AddLineErr(_T(" Aborting export. Consider enabling [Force EOI] or [Ignore Missing EOI] option")); - return false; - } else if (bIgnoreEoi) { - // Ignore the EOI, so mark the end of file, but don't - // set the flag where we force one. - m_nPosEmbedEnd = m_nPosFileEnd; - } else { - // We're missing the EOI but the user has requested - // that we force an EOI, so let's fix things up - m_nPosEmbedEnd = m_nPosFileEnd; - } - } - - - if ((m_nPosEmbedStart == 0) && (m_nPosEmbedEnd == 0)) { - strTmp.Format(_T(" No frame found at this position in file. Consider using [Img Search]")); - m_pLog->AddLineErr(strTmp); - return false; - } - - if (!m_bStateSoi) { - if (!bForceSoi) { - strTmp.Format(_T(" ERROR: Missing marker: %s"),_T("SOI")); - m_pLog->AddLineErr(strTmp); - m_pLog->AddLineErr(_T(" Aborting export. Consider enabling [Force SOI] option")); - return false; - } else { - // We're missing the SOI but the user has requested - // that we force an SOI, so let's fix things up - } - - } - if (!m_bStateSos) { - strTmp.Format(_T(" ERROR: Missing marker: %s"),_T("SOS")); - m_pLog->AddLineErr(strTmp); - m_pLog->AddLineErr(_T(" Aborting export")); - return false; - } - - if (!m_bStateDqt) { bExtractWarn = true; strMissing += _T("DQT "); } - if (!m_bStateDht) { bExtractWarn = true; strMissing += _T("DHT "); } - if (!m_bStateSof) { bExtractWarn = true; strMissing += _T("SOF "); } - - if (bExtractWarn) { - strTmp.Format(_T(" NOTE: Missing marker: %s"),(LPCTSTR)strMissing); - m_pLog->AddLineWarn(strTmp); - m_pLog->AddLineWarn(_T(" Exported JPEG may not be valid")); - } - - if (m_nPosEmbedEnd < m_nPosEmbedStart) { - strTmp.Format(_T("ERROR: Invalid SOI-EOI order. Export aborted.")); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - return false; - } - - return true; -} - - - -#define EXPORT_BUF_SIZE 131072 - -// Export the embedded JPEG image at the current position in the file (with overlays) -// (may be the primary image or even an embedded thumbnail). -bool CjfifDecode::ExportJpegDo(CString strFileIn, CString strFileOut, - unsigned long nFileLen, bool bOverlayEn,bool bDhtAviInsert,bool bForceSoi,bool bForceEoi) -{ - CFile* pFileOutput; - CString strTmp = _T(""); - - strTmp.Format(_T(" Exporting to: [%s]"),(LPCTSTR)strFileOut); - m_pLog->AddLine(strTmp); - - if (strFileIn == strFileOut) { - strTmp.Format(_T("ERROR: Can't overwrite source file. Aborting export.")); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - - return false; - } - - ASSERT(strFileIn != _T("")); - if (strFileIn == _T("")) { - strTmp.Format(_T("ERROR: Export but source filename empty")); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - - return false; - } - - - - try - { - // Open specified file - // Added in shareDenyNone as this apparently helps resolve some people's troubles - // with an error showing: Couldn't open file "Sharing Violation" - pFileOutput = new CFile(strFileOut, CFile::modeCreate| CFile::modeWrite | CFile::typeBinary | CFile::shareDenyNone); - } - catch (CFileException* e) - { - TCHAR msg[MAX_BUF_EX_ERR_MSG]; - CString strError; - e->GetErrorMessage(msg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - strError.Format(_T("ERROR: Couldn't open file for write [%s]: [%s]"), - (LPCTSTR)strFileOut, (LPCTSTR)msg); - m_pLog->AddLineErr(strError); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strError); - pFileOutput = NULL; - - return false; - - } - - // Don't attempt to load buffer with zero length file! - if (nFileLen==0) { - strTmp.Format(_T("ERROR: Source file length error. Please Reprocess first.")); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - - if (pFileOutput) { delete pFileOutput; pFileOutput = NULL; } - return false; - } - - - // Need to insert fake DHT. Assume we have enough buffer allocated. - // - // Step 1: Copy from SOI -> SOS (not incl) - // Step 2: Insert Fake DHT - // Step 3: Copy from SOS -> EOI - unsigned nCopyStart; - unsigned nCopyEnd; - unsigned nCopyLeft; - unsigned ind; - - BYTE* pBuf; - - pBuf = new BYTE[EXPORT_BUF_SIZE+10]; - if (!pBuf) { - if (pFileOutput) { delete pFileOutput; pFileOutput = NULL; } - return false; - } - - - - // Step 1 - - // If we need to force an SOI, do it now - if (!m_bStateSoi && bForceSoi) { - m_pLog->AddLine(_T(" Forcing SOI Marker")); - BYTE anBufSoi[2] = {0xFF,JFIF_SOI}; - pFileOutput->Write(&anBufSoi,2); - } - - nCopyStart = m_nPosEmbedStart; - nCopyEnd = (m_nPosSos-1); - ind = nCopyStart; - while (indEXPORT_BUF_SIZE) { nCopyLeft = EXPORT_BUF_SIZE; } - for (unsigned ind1=0;ind1Write(pBuf,nCopyLeft); - ind += nCopyLeft; - // NOTE: We ensure nFileLen != 0 earlier - ASSERT(nFileLen>0); - strTmp.Format(_T("Exporting %3u%%..."),ind*100/nFileLen); - SetStatusText(strTmp); - } - - - - if (bDhtAviInsert) { - // Step 2. The following struct includes the JFIF marker too - strTmp.Format(_T(" Inserting standard AVI DHT huffman table")); - m_pLog->AddLine(strTmp); - pFileOutput->Write(m_abMJPGDHTSeg,JFIF_DHT_FAKE_SZ); - } - - // Step 3 - nCopyStart = m_nPosSos; - nCopyEnd = m_nPosEmbedEnd-1; - ind = nCopyStart; - while (indEXPORT_BUF_SIZE) { nCopyLeft = EXPORT_BUF_SIZE; } - for (unsigned ind1=0;ind1Write(pBuf,nCopyLeft); - ind += nCopyLeft; - // NOTE: We ensure nFileLen != 0 earlier - ASSERT(nFileLen>0); - strTmp.Format(_T("Exporting %3u%%..."),ind*100/nFileLen); - SetStatusText(strTmp); - } - - // Now optionally insert the EOI Marker - if (bForceEoi) { - m_pLog->AddLine(_T(" Forcing EOI Marker")); - BYTE anBufEoi[2] = {0xFF,JFIF_EOI}; - pFileOutput->Write(&anBufEoi,2); - } - - - // Free up space - pFileOutput->Close(); - - if (pBuf) { - delete [] pBuf; - pBuf = NULL; - } - - if (pFileOutput) { - delete pFileOutput; - pFileOutput = NULL; - } - - SetStatusText(_T("")); - strTmp.Format(_T(" Export done")); - m_pLog->AddLine(strTmp); - - return true; -} - - -// Export a subset of the file with no overlays or mods -bool CjfifDecode::ExportJpegDoRange(CString strFileIn, CString strFileOut, - unsigned long nStart, unsigned long nEnd) -{ - CFile* pFileOutput; - CString strTmp = _T(""); - - strTmp.Format(_T(" Exporting range to: [%s]"),(LPCTSTR)strFileOut); - m_pLog->AddLine(strTmp); - - if (strFileIn == strFileOut) { - strTmp.Format(_T("ERROR: Can't overwrite source file. Aborting export.")); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - - return false; - } - - ASSERT(strFileIn != _T("")); - if (strFileIn == _T("")) { - strTmp.Format(_T("ERROR: Export but source filename empty")); - m_pLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - - return false; - } - - - - try - { - // Open specified file - // Added in shareDenyNone as this apparently helps resolve some people's troubles - // with an error showing: Couldn't open file "Sharing Violation" - pFileOutput = new CFile(strFileOut, CFile::modeCreate| CFile::modeWrite | CFile::typeBinary | CFile::shareDenyNone); - } - catch (CFileException* e) - { - TCHAR msg[MAX_BUF_EX_ERR_MSG]; - CString strError; - e->GetErrorMessage(msg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - strError.Format(_T("ERROR: Couldn't open file for write [%s]: [%s]"), - (LPCTSTR)strFileOut, (LPCTSTR)msg); - m_pLog->AddLineErr(strError); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strError); - pFileOutput = NULL; - - return false; - - } - - - unsigned nCopyStart; - unsigned nCopyEnd; - unsigned nCopyLeft; - unsigned ind; - - BYTE* pBuf; - - pBuf = new BYTE[EXPORT_BUF_SIZE+10]; - if (!pBuf) { - if (pFileOutput) { delete pFileOutput; pFileOutput = NULL; } - return false; - } - - - - // Step 1 - nCopyStart = nStart; - nCopyEnd = nEnd; - ind = nCopyStart; - while (indEXPORT_BUF_SIZE) { nCopyLeft = EXPORT_BUF_SIZE; } - for (unsigned ind1=0;ind1Write(pBuf,nCopyLeft); - ind += nCopyLeft; - strTmp.Format(_T("Exporting %3u%%..."),ind*100/(nCopyEnd-nCopyStart)); - SetStatusText(strTmp); - } - - - // Free up space - pFileOutput->Close(); - - if (pBuf) { - delete [] pBuf; - pBuf = NULL; - } - - if (pFileOutput) { - delete pFileOutput; - pFileOutput = NULL; - } - - SetStatusText(_T("")); - strTmp.Format(_T(" Export range done")); - m_pLog->AddLine(strTmp); - - return true; -} - - -// ==================================================================================== -// JFIF Decoder Constants -// ==================================================================================== - -// List of the JFIF markers -const MarkerNameTable CjfifDecode::m_pMarkerNames[] = { - {JFIF_SOF0,_T("SOF0")}, - {JFIF_SOF1,_T("SOF1")}, - {JFIF_SOF2,_T("SOF2")}, - {JFIF_SOF3,_T("SOF3")}, - {JFIF_SOF5,_T("SOF5")}, - {JFIF_SOF6,_T("SOF6")}, - {JFIF_SOF7,_T("SOF7")}, - {JFIF_JPG,_T("JPG")}, - {JFIF_SOF9,_T("SOF9")}, - {JFIF_SOF10,_T("SOF10")}, - {JFIF_SOF11,_T("SOF11")}, - {JFIF_SOF13,_T("SOF13")}, - {JFIF_SOF14,_T("SOF14")}, - {JFIF_SOF15,_T("SOF15")}, - {JFIF_DHT,_T("DHT")}, - {JFIF_DAC,_T("DAC")}, - {JFIF_RST0,_T("RST0")}, - {JFIF_RST1,_T("RST1")}, - {JFIF_RST2,_T("RST2")}, - {JFIF_RST3,_T("RST3")}, - {JFIF_RST4,_T("RST4")}, - {JFIF_RST5,_T("RST5")}, - {JFIF_RST6,_T("RST6")}, - {JFIF_RST7,_T("RST7")}, - {JFIF_SOI,_T("SOI")}, - {JFIF_EOI,_T("EOI")}, - {JFIF_SOS,_T("SOS")}, - {JFIF_DQT,_T("DQT")}, - {JFIF_DNL,_T("DNL")}, - {JFIF_DRI,_T("DRI")}, - {JFIF_DHP,_T("DHP")}, - {JFIF_EXP,_T("EXP")}, - {JFIF_APP0,_T("APP0")}, - {JFIF_APP1,_T("APP1")}, - {JFIF_APP2,_T("APP2")}, - {JFIF_APP3,_T("APP3")}, - {JFIF_APP4,_T("APP4")}, - {JFIF_APP5,_T("APP5")}, - {JFIF_APP6,_T("APP6")}, - {JFIF_APP7,_T("APP7")}, - {JFIF_APP8,_T("APP8")}, - {JFIF_APP9,_T("APP9")}, - {JFIF_APP10,_T("APP10")}, - {JFIF_APP11,_T("APP11")}, - {JFIF_APP12,_T("APP12")}, - {JFIF_APP13,_T("APP13")}, - {JFIF_APP14,_T("APP14")}, - {JFIF_APP15,_T("APP15")}, - {JFIF_JPG0,_T("JPG0")}, - {JFIF_JPG1,_T("JPG1")}, - {JFIF_JPG2,_T("JPG2")}, - {JFIF_JPG3,_T("JPG3")}, - {JFIF_JPG4,_T("JPG4")}, - {JFIF_JPG5,_T("JPG5")}, - {JFIF_JPG6,_T("JPG6")}, - {JFIF_JPG7,_T("JPG7")}, - {JFIF_JPG8,_T("JPG8")}, - {JFIF_JPG9,_T("JPG9")}, - {JFIF_JPG10,_T("JPG10")}, - {JFIF_JPG11,_T("JPG11")}, - {JFIF_JPG12,_T("JPG12")}, - {JFIF_JPG13,_T("JPG13")}, - {JFIF_COM,_T("COM")}, - {JFIF_TEM,_T("TEM")}, - //{JFIF_RES*,_T("RES")}, - {0x00,_T("*")}, -}; - - -// For Motion JPEG, define the DHT tables that we use since they won't exist -// in each frame within the AVI. This table will be read in during -// DecodeDHT()'s call to Buf(). -const BYTE CjfifDecode::m_abMJPGDHTSeg[JFIF_DHT_FAKE_SZ] = { - /* JPEG DHT Segment for YCrCb omitted from MJPG data */ - 0xFF,0xC4,0x01,0xA2, - 0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x01,0x00,0x03,0x01,0x01,0x01,0x01, - 0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0A,0x0B,0x10,0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00, - 0x00,0x01,0x7D,0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61, - 0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24, - 0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x34, - 0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56, - 0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78, - 0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99, - 0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9, - 0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9, - 0xDA,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7, - 0xF8,0xF9,0xFA,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01, - 0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71, - 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,0x15,0x62, - 0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,0x27,0x28,0x29,0x2A, - 0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56, - 0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78, - 0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98, - 0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8, - 0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8, - 0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8, - 0xF9,0xFA -}; - - - -// TODO: Add ITU-T Example DQT & DHT -// These will be useful for GeoRaster decode (ie. JPEG-B) - -CString glb_strMsgStopDecode = _T(" Stopping decode. Use [Relaxed Parsing] to continue."); \ No newline at end of file +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include + +#include +#include +#include +#include +#include +#include + +#include "JfifDecode.h" +#include "snoop.h" +#include "JPEGsnoop.h" // for m_pAppConfig get + +#include "WindowBuf.h" + +#include "Md5.h" + +#include "UrlString.h" +#include "DbSigs.h" + +#include "General.h" + +// Maximum number of component values to extract into array for display +static const quint32 MAX_anValues = 64; + +// Clear out internal members +void CjfifDecode::Reset() +{ + // File handling + m_nPos = 0; + m_nPosSos = 0; + m_nPosEoi = 0; + m_nPosEmbedStart = 0; + m_nPosEmbedEnd = 0; + m_nPosFileEnd = 0; + + // SOS / SOF handling + m_nSofNumLines_Y = 0; + m_nSofSampsPerLine_X = 0; + m_nSofNumComps_Nf = 0; + + // Quantization tables + ClearDQT(); + + // Photoshop + m_nImgQualPhotoshopSfw = 0; + m_nImgQualPhotoshopSa = 0; + + m_nApp14ColTransform = -1; + + // Restart marker + m_nImgRstEn = false; + m_nImgRstInterval = 0; + + // Basic metadata + m_strImgExifMake = "???"; + m_nImgExifMakeSubtype = 0; + m_strImgExifModel = "???"; + m_bImgExifMakernotes = false; + m_strImgExtras = ""; + m_strComment = ""; + m_strSoftware = ""; + m_bImgProgressive = false; + m_bImgSofUnsupported = false; + strcpy(m_acApp0Identifier, ""); + + // Derived metadata + m_strHash = "NONE"; + m_strHashRot = "NONE"; + m_eImgLandscape = ENUM_LANDSCAPE_UNSET; + m_strImgQualExif = ""; + m_bAvi = false; + m_bAviMjpeg = false; + m_bPsd = false; + + // Misc + m_bImgOK = false; // Set during SOF to indicate further proc OK + m_bBufFakeDHT = false; // Start in normal Buf mode + m_eImgEdited = EDITED_UNSET; + m_eDbReqSuggest = DB_ADD_SUGGEST_UNSET; + m_bSigExactInDB = false; + + // Embedded thumbnail + m_nImgExifThumbComp = 0; + m_nImgExifThumbOffset = 0; + m_nImgExifThumbLen = 0; + m_strHashThumb = "NONE"; // Will go into DB to say NONE! + m_strHashThumbRot = "NONE"; // Will go into DB to say NONE! + m_nImgThumbNumLines = 0; + m_nImgThumbSampsPerLine = 0; + + // Now clear out any previously generated bitmaps + // or image decoding parameters + if(m_pImgDec) + { + if(m_pImgSrcDirty) + { + m_pImgDec->Reset(); + } + } + + // Reset the decoding state checks + // These are to help ensure we don't start decoding SOS + // if we haven't seen other valid markers yet! Otherwise + // we could run into very bad loops (e.g. .PSD files) + // just because we saw FFD8FF first then JFIF_SOS + m_bStateAbort = false; + m_bStateSoi = false; + m_bStateDht = false; + m_bStateDhtOk = false; + m_bStateDhtFake = false; + m_bStateDqt = false; + m_bStateDqtOk = false; + m_bStateSof = false; + m_bStateSofOk = false; + m_bStateSos = false; + m_bStateSosOk = false; + m_bStateEoi = false; + +} + +// Initialize the JFIF decoder. Several class pointers are provided +// as parameters, so that we can directly access the output log, the +// file buffer and the image scan decoder. +// Loads up the signature database. +// +// INPUT: +// - pLog Ptr to log file class +// - pWBuf Ptr to Window Buf class +// - pImgDec Ptr to Image Decoder class +// +// PRE: +// - Requires that CDocLog, CwindowBuf and CimgDecode classes +// are already initialized +// +CjfifDecode::CjfifDecode(CDocLog *pLog, CwindowBuf *pWBuf, CimgDecode *pImgDec) +{ + // Ideally this would be passed by constructor, but simply access + // directly for now. + +// m_pAppConfig = pAppConfig; + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CjfifDecode::CjfifDecode() Begin"); + +// Q_ASSERT(m_pAppConfig); + Q_ASSERT(pLog); + Q_ASSERT(pWBuf); + Q_ASSERT(pImgDec); + + // Need to zero out the private members + m_bOutputDB = false; // mySQL output for web + + // Enable verbose reporting + m_bVerbose = false; + + m_pImgSrcDirty = true; + + // Generate lookup tables for Huffman codes + GenLookupHuffMask(); + + // Window status bar is not ready yet, wait for call to SetStatusBar() + m_pStatBar = NULL; + + // Save copies of other class pointers + m_pLog = pLog; + m_pWBuf = pWBuf; + m_pImgDec = pImgDec; + + // Reset decoding state + Reset(); + + // Load the local database (if it exists) +//@@ m_pDbSigs->DatabaseExtraLoad(); + + // Allocate the Photoshop decoder + m_pPsDec = new CDecodePs(pWBuf, pLog); + + if(!m_pPsDec) + { + Q_ASSERT(false); + return; + } + +#ifdef SUPPORT_DICOM + // Allocate the DICOM decoder + m_pDecDicom = new CDecodeDicom(pWBuf, pLog); + + if(!m_pDecDicom) + { + Q_ASSERT(false); + return; + } + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CjfifDecode::CjfifDecode() Checkpoint 5"); +#endif +} + +// Destructor +CjfifDecode::~CjfifDecode() +{ + // Free the Photoshop decoder + if(m_pPsDec) + { + delete m_pPsDec; + + m_pPsDec = NULL; + } + +#ifdef SUPPORT_DICOM + // Free the DICOM decoder + if(m_pDecDicom) + { + delete m_pDecDicom; + + m_pDecDicom = NULL; + } +#endif + +} + +// Asynchronously update a local pointer to the status bar once +// it becomes available. Note that the status bar is not ready by +// the time of the CjfifDecode class constructor call. +// +// INPUT: +// - pStatBar Ptr to status bar +// +// POST: +// - m_pStatBar +// +void CjfifDecode::SetStatusBar(QStatusBar * pStatBar) +{ + m_pStatBar = pStatBar; +} + +// Indicate that the source of the image scan data +// has been dirtied. Either the source has changed +// or some of the View2 options have changed. +// +// POST: +// - m_pImgSrcDirty +// +void CjfifDecode::ImgSrcChanged() +{ + m_pImgSrcDirty = true; +} + +// Set the AVI mode flag for this file +// +// POST: +// - m_bAvi +// - m_bAviMjpeg +// +void CjfifDecode::SetAviMode(bool bIsAvi, bool bIsMjpeg) +{ + m_bAvi = bIsAvi; + m_bAviMjpeg = bIsMjpeg; +} + +// Fetch the AVI mode flag for this file +// +// PRE: +// - m_bAvi +// - m_bAviMjpeg +// +// OUTPUT: +// - bIsAvi +// - bIsMjpeg +// +void CjfifDecode::GetAviMode(bool & bIsAvi, bool & bIsMjpeg) +{ + bIsAvi = m_bAvi; + bIsMjpeg = m_bAviMjpeg; +} + +// Fetch the starting file position of the embedded thumbnail +// +// PRE: +// - m_nPosEmbedStart +// +// RETURN: +// - File position +// +uint32_t CjfifDecode::GetPosEmbedStart() +{ + return m_nPosEmbedStart; +} + +// Fetch the ending file position of the embedded thumbnail +// +// PRE: +// - m_nPosEmbedEnd +// +// RETURN: +// - File position +// +uint32_t CjfifDecode::GetPosEmbedEnd() +{ + return m_nPosEmbedEnd; +} + +// Determine if the last analysis revealed a JFIF with known markers +// +// RETURN: +// - true if file (at position during analysis) appeared to decode OK +// +bool CjfifDecode::GetDecodeStatus() +{ + return m_bImgOK; +} + +// Fetch a summary of the JFIF decoder results +// These details are used in preparation of signature submission to the DB +// +// PRE: +// - m_strHash +// - m_strHashRot +// - m_strImgExifMake +// - m_strImgExifModel +// - m_strImgQualExif +// - m_strSoftware +// - m_eDbReqSuggest +// +// OUTPUT: +// - strHash +// - strHashRot +// - strImgExifMake +// - strImgExifModel +// - strImgQualExif +// - strSoftware +// - nDbReqSuggest +// +void CjfifDecode::GetDecodeSummary(QString & strHash, QString & strHashRot, QString & strImgExifMake, QString & strImgExifModel, + QString & strImgQualExif, QString & strSoftware, teDbAdd & eDbReqSuggest) +{ + strHash = m_strHash; + strHashRot = m_strHashRot; + strImgExifMake = m_strImgExifMake; + strImgExifModel = m_strImgExifModel; + strImgQualExif = m_strImgQualExif; + strSoftware = m_strSoftware; + eDbReqSuggest = m_eDbReqSuggest; +} + +// Fetch an element from the "standard" luminance quantization table +// +// PRE: +// - glb_anStdQuantLum[] +// +// RETURN: +// - DQT matrix element +// +uint32_t CjfifDecode::GetDqtQuantStd(uint32_t nInd) +{ + if(nInd < MAX_DQT_COEFF) + { + return glb_anStdQuantLum[nInd]; + } + else + { +#ifdef DEBUG_LOG + QString strTmp; + + QString strDebug; + + strTmp = QString("GetDqtQuantStd() with nInd out of range. nInd=[%1]").arg(nInd); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]").arg(m_pAppConfig->strCurFname, -100).arg("JfifDecode", -10).arg(strTmp); + qDebug() << strDebug; +#else + Q_ASSERT(false); +#endif + return 0; + } +} + +// Fetch the DQT ordering index (with optional zigzag sequence) +// +// INPUT: +// - nInd Coefficient index +// - bZigZag Use zig-zag ordering +// +// RETURN: +// - Sequence index +// +uint32_t CjfifDecode::GetDqtZigZagIndex(uint32_t nInd, bool bZigZag) +{ + if(nInd < MAX_DQT_COEFF) + { + if(bZigZag) + { + return nInd; + } + else + { + return glb_anZigZag[nInd]; + } + } + else + { +#ifdef DEBUG_LOG + QString strTmp; + QString strDebug; + + strTmp = QString("GetDqtZigZagIndex() with nInd out of range. nInd=[%1]").arg(nInd); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]").arg(m_pAppConfig->strCurFname, -100).arg("JfifDecode", -10).arg(strTmp); + qDebug() << strDebug; +#else + Q_ASSERT(false); +#endif + return 0; + } +} + +// Reset the DQT tables +// +// POST: +// - m_anImgDqtTbl[][] +// - m_anImgThumbDqt[][] +// - m_adImgDqtQual[] +// - m_abImgDqtSet[] +// - m_abImgDqtThumbSet[] +// +void CjfifDecode::ClearDQT() +{ + for(uint32_t nTblInd = 0; nTblInd < MAX_DQT_DEST_ID; nTblInd++) + { + for(uint32_t nCoeffInd = 0; nCoeffInd < MAX_DQT_COEFF; nCoeffInd++) + { + m_anImgDqtTbl[nTblInd][nCoeffInd] = 0; + m_anImgThumbDqt[nTblInd][nCoeffInd] = 0; + } + + m_adImgDqtQual[nTblInd] = 0; + m_abImgDqtSet[nTblInd] = false; + m_abImgDqtThumbSet[nTblInd] = false; + } +} + +// Set the DQT matrix element +// +// INPUT: +// - dqt0[] Matrix array for table 0 +// - dqt1[] Matrix array for table 1 +// +// POST: +// - m_anImgDqtTbl[][] +// - m_eImgLandscape +// - m_abImgDqtSet[] +// - m_strImgQuantCss +// +void CjfifDecode::SetDQTQuick(uint16_t anDqt0[64], uint16_t anDqt1[64]) +{ + m_eImgLandscape = ENUM_LANDSCAPE_YES; + + for(uint32_t ind = 0; ind < MAX_DQT_COEFF; ind++) + { + m_anImgDqtTbl[0][ind] = anDqt0[ind]; + m_anImgDqtTbl[1][ind] = anDqt1[ind]; + } + + m_abImgDqtSet[0] = true; + m_abImgDqtSet[1] = true; + m_strImgQuantCss = "NA"; +} + +// Construct a lookup table for the Huffman code masks +// The result is a simple bit sequence of zeros followed by +// an increasing number of 1 bits. +// 00000000...00000001 +// 00000000...00000011 +// 00000000...00000111 +// ... +// 01111111...11111111 +// 11111111...11111111 +// +// POST: +// - m_anMaskLookup[] +// +void CjfifDecode::GenLookupHuffMask() +{ + uint32_t mask; + + for(uint32_t len = 0; len < 32; len++) + { + mask = (1 << (len)) - 1; + mask <<= 32 - len; + m_anMaskLookup[len] = mask; + } +} + +// Provide a short-hand alias for the m_pWBuf buffer +// Also support redirection to a local table in case we are +// faking out the DHT (eg. for MotionJPEG files). +// +// PRE: +// - m_bBufFakeDHT Flag to include Fake DHT table +// - m_abMJPGDHTSeg[] DHT table used if m_bBufFakeDHT=true +// +// INPUT: +// - nOffset File offset to read from +// - bClean Forcibly disables any redirection to Fake DHT table +// +// POST: +// - m_pLog +// +// RETURN: +// - Byte from file (or local table) +// +uint8_t CjfifDecode::Buf(uint32_t nOffset, bool bClean = false) +{ + // Buffer can be redirected to internal array for AVI DHT + // tables, so check for it here. + if(m_bBufFakeDHT) + { + return m_abMJPGDHTSeg[nOffset]; + } + else + { + return m_pWBuf->Buf(nOffset, bClean); + } +} + +// Write out a line to the log buffer if we are in verbose mode +// +// PRE: +// - m_bVerbose Verbose mode +// +// INPUT: +// - strLine String to output +// +// OUTPUT: +// - none +// +// POST: +// - m_pLog +// +// RETURN: +// - none +// +void CjfifDecode::DbgAddLine(QString strLine) +{ + if(m_bVerbose) + { + m_pLog->AddLine(strLine); + } +} + +// Convert a UINT32 and decompose into 4 bytes, but support +// either endian byte-swap mode +// +// PRE: +// - m_nImgExifEndian Byte swap mode (0=little, 1=big) +// +// INPUT: +// - nVal Input UINT32 +// +// OUTPUT: +// - nByte0 Byte #1 +// - nByte1 Byte #2 +// - nByte2 Byte #3 +// - nByte3 Byte #4 +// +// RETURN: +// - none +// +void CjfifDecode::UnByteSwap4(uint32_t nVal, uint32_t &nByte0, uint32_t &nByte1, uint32_t &nByte2, uint32_t &nByte3) +{ + if(m_nImgExifEndian == 0) + { + // Little Endian + nByte3 = (nVal & 0xFF000000) >> 24; + nByte2 = (nVal & 0x00FF0000) >> 16; + nByte1 = (nVal & 0x0000FF00) >> 8; + nByte0 = (nVal & 0x000000FF); + } + else + { + // Big Endian + nByte0 = (nVal & 0xFF000000) >> 24; + nByte1 = (nVal & 0x00FF0000) >> 16; + nByte2 = (nVal & 0x0000FF00) >> 8; + nByte3 = (nVal & 0x000000FF); + } +} + +// Perform conversion from 4 bytes into UINT32 with +// endian byte-swapping support +// +// PRE: +// - m_nImgExifEndian Byte swap mode (0=little, 1=big) +// +// INPUT: +// - nByte0 Byte #1 +// - nByte1 Byte #2 +// - nByte2 Byte #3 +// - nByte3 Byte #4 +// +// RETURN: +// - UINT32 +// +uint32_t CjfifDecode::ByteSwap4(uint32_t nByte0, uint32_t nByte1, uint32_t nByte2, uint32_t nByte3) +{ + uint32_t nVal; + + if(m_nImgExifEndian == 0) + { + // Little endian, byte swap required + nVal = (nByte3 << 24) + (nByte2 << 16) + (nByte1 << 8) + nByte0; + } + else + { + // Big endian, no swap required + nVal = (nByte0 << 24) + (nByte1 << 16) + (nByte2 << 8) + nByte3; + } + + return nVal; +} + +// Perform conversion from 2 bytes into half-word with +// endian byte-swapping support +// +// PRE: +// - m_nImgExifEndian Byte swap mode (0=little, 1=big) +// +// INPUT: +// - nByte0 Byte #1 +// - nByte1 Byte #2 +// +// RETURN: +// - UINT16 +// +uint32_t CjfifDecode::ByteSwap2(uint32_t nByte0, uint32_t nByte1) +{ + uint32_t nVal; + + if(m_nImgExifEndian == 0) + { + // Little endian, byte swap required + nVal = (nByte1 << 8) + nByte0; + } + else + { + // Big endian, no swap required + nVal = (nByte0 << 8) + nByte1; + } + + return nVal; +} + +// Decode Canon Makernotes +// Only the most common makernotes are supported; there are a large +// number of makernotes that have not been documented anywhere. +CStr2 CjfifDecode::LookupMakerCanonTag(uint32_t nMainTag, uint32_t nSubTag, uint32_t nVal) +{ + QString strTmp; + + CStr2 sRetVal; + + sRetVal.strTag = "???"; + sRetVal.bUnknown = false; // Set to true in default clauses + sRetVal.strVal = QString("%1").arg(nVal); // Provide default value + + uint32_t nValHi, nValLo; + + nValHi = (nVal & 0xff00) >> 8; + nValLo = (nVal & 0x00ff); + + switch (nMainTag) + { + case 0x0001: + switch (nSubTag) + { + case 0x0001: + sRetVal.strTag = "Canon.Cs1.Macro"; + break; // Short Macro mode + + case 0x0002: + sRetVal.strTag = "Canon.Cs1.Selftimer"; + break; // Short Self timer + + case 0x0003: + sRetVal.strTag = "Canon.Cs1.Quality"; + + if(nVal == 2) + { + sRetVal.strVal = "norm"; + } + else if(nVal == 3) + { + sRetVal.strVal = "fine"; + } + else if(nVal == 5) + { + sRetVal.strVal = "superfine"; + } + else + { + sRetVal.strVal = "?"; + } + + // Save the quality string for later + m_strImgQualExif = sRetVal.strVal; + break; // Short Quality + + case 0x0004: + sRetVal.strTag = "Canon.Cs1.FlashMode"; + break; // Short Flash mode setting + + case 0x0005: + sRetVal.strTag = "Canon.Cs1.DriveMode"; + break; // Short Drive mode setting + + case 0x0007: + sRetVal.strTag = "Canon.Cs1.FocusMode"; // Short Focus mode setting + + switch (nVal) + { + case 0: + sRetVal.strVal = "One-shot"; + break; + + case 1: + sRetVal.strVal = "AI Servo"; + break; + + case 2: + sRetVal.strVal = "AI Focus"; + break; + + case 3: + sRetVal.strVal = "Manual Focus"; + break; + + case 4: + sRetVal.strVal = "Single"; + break; + + case 5: + sRetVal.strVal = "Continuous"; + break; + + case 6: + sRetVal.strVal = "Manual Focus"; + break; + + default: + sRetVal.strVal = "?"; + break; + } + + break; + + case 0x000a: + sRetVal.strTag = "Canon.Cs1.ImageSize"; // Short Image size + + if(nVal == 0) + { + sRetVal.strVal = "Large"; + } + else if(nVal == 1) + { + sRetVal.strVal = "Medium"; + } + else if(nVal == 2) + { + sRetVal.strVal = "Small"; + } + else + { + sRetVal.strVal = "?"; + } + + break; + + case 0x000b: + sRetVal.strTag = "Canon.Cs1.EasyMode"; + break; // Short Easy shooting mode + + case 0x000c: + sRetVal.strTag = "Canon.Cs1.DigitalZoom"; + break; // Short Digital zoom + + case 0x000d: + sRetVal.strTag = "Canon.Cs1.Contrast"; + break; // Short Contrast setting + + case 0x000e: + sRetVal.strTag = "Canon.Cs1.Saturation"; + break; // Short Saturation setting + + case 0x000f: + sRetVal.strTag = "Canon.Cs1.Sharpness"; + break; // Short Sharpness setting + + case 0x0010: + sRetVal.strTag = "Canon.Cs1.ISOSpeed"; + break; // Short ISO speed setting + + case 0x0011: + sRetVal.strTag = "Canon.Cs1.MeteringMode"; + break; // Short Metering mode setting + + case 0x0012: + sRetVal.strTag = "Canon.Cs1.FocusType"; + break; // Short Focus type setting + + case 0x0013: + sRetVal.strTag = "Canon.Cs1.AFPoint"; + break; // Short AF point selected + + case 0x0014: + sRetVal.strTag = "Canon.Cs1.ExposureProgram"; + break; // Short Exposure mode setting + + case 0x0016: + sRetVal.strTag = "Canon.Cs1.LensType"; + break; // + + case 0x0017: + sRetVal.strTag = "Canon.Cs1.Lens"; + break; // Short 'long' and 'short' focal length of lens (in 'focal m_nImgUnits' and 'focal m_nImgUnits' per mm + + case 0x001a: + sRetVal.strTag = "Canon.Cs1.MaxAperture"; + break; // + + case 0x001b: + sRetVal.strTag = "Canon.Cs1.MinAperture"; + break; // + + case 0x001c: + sRetVal.strTag = "Canon.Cs1.FlashActivity"; + break; // Short Flash activity + + case 0x001d: + sRetVal.strTag = "Canon.Cs1.FlashDetails"; + break; // Short Flash details + + case 0x0020: + sRetVal.strTag = "Canon.Cs1.FocusMode"; + break; // Short Focus mode setting + + default: + sRetVal.strTag = QString("Canon.Cs1.x%1").arg(nSubTag, 4, 16, QChar('0')); + sRetVal.bUnknown = true; + break; + } // switch nSubTag + + break; + + case 0x0004: + switch (nSubTag) + { + case 0x0002: + sRetVal.strTag = "Canon.Cs2.ISOSpeed"; + break; // Short ISO speed used + case 0x0004: + sRetVal.strTag = "Canon.Cs2.TargetAperture"; + break; // Short Target Aperture + case 0x0005: + sRetVal.strTag = "Canon.Cs2.TargetShutterSpeed"; + break; // Short Target shutter speed + case 0x0007: + sRetVal.strTag = "Canon.Cs2.WhiteBalance"; + break; // Short White balance setting + case 0x0009: + sRetVal.strTag = "Canon.Cs2.Sequence"; + break; // Short Sequence number (if in a continuous burst + case 0x000e: + sRetVal.strTag = "Canon.Cs2.AFPointUsed"; + break; // Short AF point used + case 0x000f: + sRetVal.strTag = "Canon.Cs2.FlashBias"; + break; // Short Flash bias + case 0x0013: + sRetVal.strTag = "Canon.Cs2.SubjectDistance"; + break; // Short Subject distance (m_nImgUnits are not clear + case 0x0015: + sRetVal.strTag = "Canon.Cs2.ApertureValue"; + break; // Short Aperture + case 0x0016: + sRetVal.strTag = "Canon.Cs2.ShutterSpeedValue"; + break; // Short Shutter speed + default: + sRetVal.strTag = QString("Canon.Cs2.x%1").arg(nSubTag, 4, 16, QChar('0')); + sRetVal.bUnknown = true; + break; + } // switch nSubTag + break; + + case 0x000F: + // CustomFunctions are different! Tag given by high byte, value by low + // Index order (usually the nSubTag) is not used. + sRetVal.strVal = QString("%1").arg(nValLo); // Provide default value + + switch (nValHi) + { + case 0x0001: + sRetVal.strTag = "Canon.Cf.NoiseReduction"; + break; // Short Long exposure noise reduction + case 0x0002: + sRetVal.strTag = "Canon.Cf.ShutterAeLock"; + break; // Short Shutter/AE lock buttons + case 0x0003: + sRetVal.strTag = "Canon.Cf.MirrorLockup"; + break; // Short Mirror lockup + case 0x0004: + sRetVal.strTag = "Canon.Cf.ExposureLevelIncrements"; + break; // Short Tv/Av and exposure level + case 0x0005: + sRetVal.strTag = "Canon.Cf.AFAssist"; + break; // Short AF assist light + case 0x0006: + sRetVal.strTag = "Canon.Cf.FlashSyncSpeedAv"; + break; // Short Shutter speed in Av mode + case 0x0007: + sRetVal.strTag = "Canon.Cf.AEBSequence"; + break; // Short AEB sequence/auto cancellation + case 0x0008: + sRetVal.strTag = "Canon.Cf.ShutterCurtainSync"; + break; // Short Shutter curtain sync + case 0x0009: + sRetVal.strTag = "Canon.Cf.LensAFStopButton"; + break; // Short Lens AF stop button Fn. Switch + case 0x000a: + sRetVal.strTag = "Canon.Cf.FillFlashAutoReduction"; + break; // Short Auto reduction of fill flash + case 0x000b: + sRetVal.strTag = "Canon.Cf.MenuButtonReturn"; + break; // Short Menu button return position + case 0x000c: + sRetVal.strTag = "Canon.Cf.SetButtonFunction"; + break; // Short SET button func. when shooting + case 0x000d: + sRetVal.strTag = "Canon.Cf.SensorCleaning"; + break; // Short Sensor cleaning + case 0x000e: + sRetVal.strTag = "Canon.Cf.SuperimposedDisplay"; + break; // Short Superimposed display + case 0x000f: + sRetVal.strTag = "Canon.Cf.ShutterReleaseNoCFCard"; + break; // Short Shutter Release W/O CF Card + default: + sRetVal.strTag = QString("Canon.Cf.x%1").arg(nValHi, 4, 16, QChar('0')); + sRetVal.bUnknown = true; + break; + } + // switch nSubTag + break; + +/* + // Other ones assumed to use high-byte/low-byte method: + case 0x00C0: + sRetVal.strVal = QString("%u"),nValLo; // Provide default value + switch(nValHi) + { + //case 0x0001: sRetVal.strTag = "Canon.x00C0.???";break; // + default: + sRetVal.strTag = QString("Canon.x00C0.x%04X"),nValHi; + break; + } + break; + + case 0x00C1: + sRetVal.strVal = QString("%u"),nValLo; // Provide default value + switch(nValHi) + { + //case 0x0001: sRetVal.strTag = "Canon.x00C1.???";break; // + default: + sRetVal.strTag = QString("Canon.x00C1.x%04X"),nValHi; + break; + } + break; +*/ + + case 0x0012: + switch (nSubTag) + { + case 0x0002: + sRetVal.strTag = "Canon.Pi.ImageWidth"; + break; // + case 0x0003: + sRetVal.strTag = "Canon.Pi.ImageHeight"; + break; // + case 0x0004: + sRetVal.strTag = "Canon.Pi.ImageWidthAsShot"; + break; // + case 0x0005: + sRetVal.strTag = "Canon.Pi.ImageHeightAsShot"; + break; // + case 0x0016: + sRetVal.strTag = "Canon.Pi.AFPointsUsed"; + break; // + case 0x001a: + sRetVal.strTag = "Canon.Pi.AFPointsUsed20D"; + break; // + default: + sRetVal.strTag = QString("Canon.Pi.x%1").arg(nSubTag, 4, 16, QChar('0')); + sRetVal.bUnknown = true; + break; + } // switch nSubTag + + break; + + default: + sRetVal.strTag = QString("Canon.x%1.x%1") + .arg(nMainTag, 4, 16, QChar('0')) + .arg(nSubTag, 4, 16, QChar('0')); + sRetVal.bUnknown = true; + break; + + } // switch mainTag + + return sRetVal; +} + +// Perform decode of EXIF IFD tags including MakerNote tags +// +// PRE: +// - m_strImgExifMake Used for MakerNote decode +// +// INPUT: +// - strSect IFD section +// - nTag Tag code value +// +// OUTPUT: +// - bUnknown Was the tag unknown? +// +// RETURN: +// - Formatted string +// +QString CjfifDecode::LookupExifTag(QString strSect, uint32_t nTag, bool & bUnknown) +{ + QString strTmp; + + bUnknown = false; + + if(strSect == "IFD0") + { + switch (nTag) + { + case 0x010E: + return QString("ImageDescription"); + break; // ascii string Describes image + case 0x010F: + return QString("Make"); + break; // ascii string Shows manufacturer of digicam + case 0x0110: + return QString("Model"); + break; // ascii string Shows model number of digicam + case 0x0112: + return QString("Orientation"); + break; // unsigned short 1 The orientation of the camera relative to the scene, when the image was captured. The start point of stored data is, '1' means upper left, '3' lower right, '6' upper right, '8' lower left, '9' undefined. + case 0x011A: + return QString("XResolution"); + break; // unsigned rational 1 Display/Print resolution of image. Large number of digicam uses 1/72inch, but it has no mean because personal computer doesn't use this value to display/print out. + case 0x011B: + return QString("YResolution"); + break; // unsigned rational 1 + case 0x0128: + return QString("ResolutionUnit"); + break; // unsigned short 1 Unit of XResolution(0x011a)/YResolution(0x011b. '1' means no-unit, '2' means inch, '3' means centimeter. + case 0x0131: + return QString("Software"); + break; // ascii string Shows firmware(internal software of digicam version number. + case 0x0132: + return QString("DateTime"); + break; // ascii string 20 Date/Time of image was last modified. Data format is "YYYY:MM:DD HH:MM:SS"+0x00, total 20bytes. In usual, it has the same value of DateTimeOriginal(0x9003 + case 0x013B: + return QString("Artist"); + break; // Seems to be here and not only in SubIFD (maybe instead of SubIFD + case 0x013E: + return QString("WhitePoint"); + break; // unsigned rational 2 Defines chromaticity of white point of the image. If the image uses CIE Standard Illumination D65(known as international standard of 'daylight', the values are '3127/10000,3290/10000'. + case 0x013F: + return QString("PrimChromaticities"); + break; // unsigned rational 6 Defines chromaticity of the primaries of the image. If the image uses CCIR Recommendation 709 primearies, values are '640/1000,330/1000,300/1000,600/1000,150/1000,0/1000'. + case 0x0211: + return QString("YCbCrCoefficients"); + break; // unsigned rational 3 When image format is YCbCr, this value shows a constant to translate it to RGB format. In usual, values are '0.299/0.587/0.114'. + case 0x0213: + return QString("YCbCrPositioning"); + break; // unsigned short 1 When image format is YCbCr and uses 'Subsampling'(cropping of chroma data, all the digicam do that, defines the chroma sample point of subsampling pixel array. '1' means the center of pixel array, '2' means the datum point. + case 0x0214: + return QString("ReferenceBlackWhite"); + break; // unsigned rational 6 Shows reference value of black point/white point. In case of YCbCr format, first 2 show black/white of Y, next 2 are Cb, last 2 are Cr. In case of RGB format, first 2 show black/white of R, next 2 are G, last 2 are B. + case 0x8298: + return QString("Copyright"); + break; // ascii string Shows copyright information + case 0x8769: + return QString("ExifOffset"); + break; //unsigned long 1 Offset to Exif Sub IFD + case 0x8825: + return QString("GPSOffset"); + break; //unsigned long 1 Offset to Exif GPS IFD +//NEW: + case 0x9C9B: + return QString("XPTitle"); + break; + case 0x9C9C: + return QString("XPComment"); + break; + case 0x9C9D: + return QString("XPAuthor"); + break; + case 0x9C9e: + return QString("XPKeywords"); + break; + case 0x9C9f: + return QString("XPSubject"); + break; +//NEW: The following were found in IFD0 even though they should just be SubIFD? + case 0xA401: + return QString("CustomRendered"); + break; + case 0xA402: + return QString("ExposureMode"); + break; + case 0xA403: + return QString("WhiteBalance"); + break; + case 0xA406: + return QString("SceneCaptureType"); + break; + + default: + strTmp = QString("IFD0.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } + else if(strSect == "SubIFD") + { + switch (nTag) + { + case 0x00fe: + return QString("NewSubfileType"); + break; // unsigned long 1 + case 0x00ff: + return QString("SubfileType"); + break; // unsigned short 1 + case 0x012d: + return QString("TransferFunction"); + break; // unsigned short 3 + case 0x013b: + return QString("Artist"); + break; // ascii string + case 0x013d: + return QString("Predictor"); + break; // unsigned short 1 + case 0x0142: + return QString("TileWidth"); + break; // unsigned short 1 + case 0x0143: + return QString("TileLength"); + break; // unsigned short 1 + case 0x0144: + return QString("TileOffsets"); + break; // unsigned long + case 0x0145: + return QString("TileByteCounts"); + break; // unsigned short + case 0x014a: + return QString("SubIFDs"); + break; // unsigned long + case 0x015b: + return QString("JPEGTables"); + break; // undefined + case 0x828d: + return QString("CFARepeatPatternDim"); + break; // unsigned short 2 + case 0x828e: + return QString("CFAPattern"); + break; // unsigned byte + case 0x828f: + return QString("BatteryLevel"); + break; // unsigned rational 1 + case 0x829A: + return QString("ExposureTime"); + break; + case 0x829D: + return QString("FNumber"); + break; + case 0x83bb: + return QString("IPTC/NAA"); + break; // unsigned long + case 0x8773: + return QString("InterColorProfile"); + break; // undefined + case 0x8822: + return QString("ExposureProgram"); + break; + case 0x8824: + return QString("SpectralSensitivity"); + break; // ascii string + case 0x8825: + return QString("GPSInfo"); + break; // unsigned long 1 + case 0x8827: + return QString("ISOSpeedRatings"); + break; + case 0x8828: + return QString("OECF"); + break; // undefined + case 0x8829: + return QString("Interlace"); + break; // unsigned short 1 + case 0x882a: + return QString("TimeZoneOffset"); + break; // signed short 1 + case 0x882b: + return QString("SelfTimerMode"); + break; // unsigned short 1 + case 0x9000: + return QString("ExifVersion"); + break; + case 0x9003: + return QString("DateTimeOriginal"); + break; + case 0x9004: + return QString("DateTimeDigitized"); + break; + case 0x9101: + return QString("ComponentsConfiguration"); + break; + case 0x9102: + return QString("CompressedBitsPerPixel"); + break; + case 0x9201: + return QString("ShutterSpeedValue"); + break; + case 0x9202: + return QString("ApertureValue"); + break; + case 0x9203: + return QString("BrightnessValue"); + break; + case 0x9204: + return QString("ExposureBiasValue"); + break; + case 0x9205: + return QString("MaxApertureValue"); + break; + case 0x9206: + return QString("SubjectDistance"); + break; + case 0x9207: + return QString("MeteringMode"); + break; + case 0x9208: + return QString("LightSource"); + break; + case 0x9209: + return QString("Flash"); + break; + case 0x920A: + return QString("FocalLength"); + break; + case 0x920b: + return QString("FlashEnergy"); + break; // unsigned rational 1 + case 0x920c: + return QString("SpatialFrequencyResponse"); + break; // undefined + case 0x920d: + return QString("Noise"); + break; // undefined + case 0x9211: + return QString("ImageNumber"); + break; // unsigned long 1 + case 0x9212: + return QString("SecurityClassification"); + break; // ascii string 1 + case 0x9213: + return QString("ImageHistory"); + break; // ascii string + case 0x9214: + return QString("SubjectLocation"); + break; // unsigned short 4 + case 0x9215: + return QString("ExposureIndex"); + break; // unsigned rational 1 + case 0x9216: + return QString("TIFF/EPStandardID"); + break; // unsigned byte 4 + case 0x927C: + return QString("MakerNote"); + break; + case 0x9286: + return QString("UserComment"); + break; + case 0x9290: + return QString("SubSecTime"); + break; // ascii string + case 0x9291: + return QString("SubSecTimeOriginal"); + break; // ascii string + case 0x9292: + return QString("SubSecTimeDigitized"); + break; // ascii string + case 0xA000: + return QString("FlashPixVersion"); + break; + case 0xA001: + return QString("ColorSpace"); + break; + case 0xA002: + return QString("ExifImageWidth"); + break; + case 0xA003: + return QString("ExifImageHeight"); + break; + case 0xA004: + return QString("RelatedSoundFile"); + break; + case 0xA005: + return QString("ExifInteroperabilityOffset"); + break; + case 0xa20b: + return QString("FlashEnergy unsigned"); + break; // rational 1 + case 0xa20c: + return QString("SpatialFrequencyResponse"); + break; // unsigned short 1 + case 0xA20E: + return QString("FocalPlaneXResolution"); + break; + case 0xA20F: + return QString("FocalPlaneYResolution"); + break; + case 0xA210: + return QString("FocalPlaneResolutionUnit"); + break; + case 0xa214: + return QString("SubjectLocation"); + break; // unsigned short 1 + case 0xa215: + return QString("ExposureIndex"); + break; // unsigned rational 1 + case 0xA217: + return QString("SensingMethod"); + break; + case 0xA300: + return QString("FileSource"); + break; + case 0xA301: + return QString("SceneType"); + break; + case 0xa302: + return QString("CFAPattern"); + break; // undefined 1 + case 0xa401: + return QString("CustomRendered"); + break; // Short Custom image processing + case 0xa402: + return QString("ExposureMode"); + break; // Short Exposure mode + case 0xa403: + return QString("WhiteBalance"); + break; // Short White balance + case 0xa404: + return QString("DigitalZoomRatio"); + break; // Rational Digital zoom ratio + case 0xa405: + return QString("FocalLengthIn35mmFilm"); + break; // Short Focal length in 35 mm film + case 0xa406: + return QString("SceneCaptureType"); + break; // Short Scene capture type + case 0xa407: + return QString("GainControl"); + break; // Rational Gain control + case 0xa408: + return QString("Contrast"); + break; // Short Contrast + case 0xa409: + return QString("Saturation"); + break; // Short Saturation + case 0xa40a: + return QString("Sharpness"); + break; // Short Sharpness + case 0xa40b: + return QString("DeviceSettingDescription"); + break; // Undefined Device settings description + case 0xa40c: + return QString("SubjectDistanceRange"); + break; // Short Subject distance range + case 0xa420: + return QString("ImageUniqueID"); + break; // Ascii Unique image ID + + default: + strTmp = QString("SubIFD.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } + else if(strSect == "IFD1") + { + switch (nTag) + { + case 0x0100: + return QString("ImageWidth"); + break; // unsigned short/long 1 Shows size of thumbnail image. + case 0x0101: + return QString("ImageLength"); + break; // unsigned short/long 1 + case 0x0102: + return QString("BitsPerSample"); + break; // unsigned short 3 When image format is no compression, this value shows the number of bits per component for each pixel. Usually this value is '8,8,8' + case 0x0103: + return QString("Compression"); + break; // unsigned short 1 Shows compression method. '1' means no compression, '6' means JPEG compression. + case 0x0106: + return QString("PhotometricInterpretation"); + break; // unsigned short 1 Shows the color space of the image data components. '1' means monochrome, '2' means RGB, '6' means YCbCr. + case 0x0111: + return QString("StripOffsets"); + break; // unsigned short/long When image format is no compression, this value shows offset to image data. In some case image data is striped and this value is plural. + case 0x0115: + return QString("SamplesPerPixel"); + break; // unsigned short 1 When image format is no compression, this value shows the number of components stored for each pixel. At color image, this value is '3'. + case 0x0116: + return QString("RowsPerStrip"); + break; // unsigned short/long 1 When image format is no compression and image has stored as strip, this value shows how many rows stored to each strip. If image has not striped, this value is the same as ImageLength(0x0101. + case 0x0117: + return QString("StripByteConunts"); + break; // unsigned short/long When image format is no compression and stored as strip, this value shows how many bytes used for each strip and this value is plural. If image has not stripped, this value is single and means whole data size of image. + case 0x011a: + return QString("XResolution"); + break; // unsigned rational 1 Display/Print resolution of image. Large number of digicam uses 1/72inch, but it has no mean because personal computer doesn't use this value to display/print out. + case 0x011b: + return QString("YResolution"); + break; // unsigned rational 1 + case 0x011c: + return QString("PlanarConfiguration"); + break; // unsigned short 1 When image format is no compression YCbCr, this value shows byte aligns of YCbCr data. If value is '1', Y/Cb/Cr value is chunky format, contiguous for each subsampling pixel. If value is '2', Y/Cb/Cr value is separated and stored to Y plane/Cb plane/Cr plane format. + case 0x0128: + return QString("ResolutionUnit"); + break; // unsigned short 1 Unit of XResolution(0x011a)/YResolution(0x011b. '1' means inch, '2' means centimeter. + case 0x0201: + return QString("JpegIFOffset"); + break; // unsigned long 1 When image format is JPEG, this value show offset to JPEG data stored. + case 0x0202: + return QString("JpegIFByteCount"); + break; // unsigned long 1 When image format is JPEG, this value shows data size of JPEG image. + case 0x0211: + return QString("YCbCrCoefficients"); + break; // unsigned rational 3 When image format is YCbCr, this value shows constants to translate it to RGB format. In usual, '0.299/0.587/0.114' are used. + case 0x0212: + return QString("YCbCrSubSampling"); + break; // unsigned short 2 When image format is YCbCr and uses subsampling(cropping of chroma data, all the digicam do that, this value shows how many chroma data subsampled. First value shows horizontal, next value shows vertical subsample rate. + case 0x0213: + return QString("YCbCrPositioning"); + break; // unsigned short 1 When image format is YCbCr and uses 'Subsampling'(cropping of chroma data, all the digicam do that), this value defines the chroma sample point of subsampled pixel array. '1' means the center of pixel array, '2' means the datum point(0,0. + case 0x0214: + return QString("ReferenceBlackWhite"); + break; // unsigned rational 6 Shows reference value of black point/white point. In case of YCbCr format, first 2 show black/white of Y, next 2 are Cb, last 2 are Cr. In case of RGB format, first 2 show black/white of R, next 2 are G, last 2 are B. + + default: + strTmp = QString("IFD1.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + + } + + } + else if(strSect == "InteropIFD") + { + switch (nTag) + { + case 0x0001: + return QString("InteroperabilityIndex"); + break; + case 0x0002: + return QString("InteroperabilityVersion"); + break; + case 0x1000: + return QString("RelatedImageFileFormat"); + break; + case 0x1001: + return QString("RelatedImageWidth"); + break; + case 0x1002: + return QString("RelatedImageLength"); + break; + + default: + strTmp = QString("Interop.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } + else if(strSect == "GPSIFD") + { + switch (nTag) + { + case 0x0000: + return QString("GPSVersionID"); + break; + case 0x0001: + return QString("GPSLatitudeRef"); + break; + case 0x0002: + return QString("GPSLatitude"); + break; + case 0x0003: + return QString("GPSLongitudeRef"); + break; + case 0x0004: + return QString("GPSLongitude"); + break; + case 0x0005: + return QString("GPSAltitudeRef"); + break; + case 0x0006: + return QString("GPSAltitude"); + break; + case 0x0007: + return QString("GPSTimeStamp"); + break; + case 0x0008: + return QString("GPSSatellites"); + break; + case 0x0009: + return QString("GPSStatus"); + break; + case 0x000A: + return QString("GPSMeasureMode"); + break; + case 0x000B: + return QString("GPSDOP"); + break; + case 0x000C: + return QString("GPSSpeedRef"); + break; + case 0x000D: + return QString("GPSSpeed"); + break; + case 0x000E: + return QString("GPSTrackRef"); + break; + case 0x000F: + return QString("GPSTrack"); + break; + case 0x0010: + return QString("GPSImgDirectionRef"); + break; + case 0x0011: + return QString("GPSImgDirection"); + break; + case 0x0012: + return QString("GPSMapDatum"); + break; + case 0x0013: + return QString("GPSDestLatitudeRef"); + break; + case 0x0014: + return QString("GPSDestLatitude"); + break; + case 0x0015: + return QString("GPSDestLongitudeRef"); + break; + case 0x0016: + return QString("GPSDestLongitude"); + break; + case 0x0017: + return QString("GPSDestBearingRef"); + break; + case 0x0018: + return QString("GPSDestBearing"); + break; + case 0x0019: + return QString("GPSDestDistanceRef"); + break; + case 0x001A: + return QString("GPSDestDistance"); + break; + case 0x001B: + return QString("GPSProcessingMethod"); + break; + case 0x001C: + return QString("GPSAreaInformation"); + break; + case 0x001D: + return QString("GPSDateStamp"); + break; + case 0x001E: + return QString("GPSDifferential"); + break; + + default: + strTmp = QString("GPS.0x%").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } + else if(strSect == "MakerIFD") + { + + // Makernotes need special handling + // We only support a few different manufacturers for makernotes. + + // A few Canon tags are supported in this routine, the rest are + // handled by the LookupMakerCanonTag() call. + if(m_strImgExifMake == "Canon") + { + + switch (nTag) + { + case 0x0001: + return QString("Canon.CameraSettings1"); + break; + case 0x0004: + return QString("Canon.CameraSettings2"); + break; + case 0x0006: + return QString("Canon.ImageType"); + break; + case 0x0007: + return QString("Canon.FirmwareVersion"); + break; + case 0x0008: + return QString("Canon.ImageNumber"); + break; + case 0x0009: + return QString("Canon.OwnerName"); + break; + case 0x000C: + return QString("Canon.SerialNumber"); + break; + case 0x000F: + return QString("Canon.CustomFunctions"); + break; + case 0x0012: + return QString("Canon.PictureInfo"); + break; + case 0x00A9: + return QString("Canon.WhiteBalanceTable"); + break; + + default: + strTmp = QString("Canon.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } // Canon + else if(m_strImgExifMake == "SIGMA") + { + switch (nTag) + { + case 0x0002: + return QString("Sigma.SerialNumber"); + break; // Ascii Camera serial number + case 0x0003: + return QString("Sigma.DriveMode"); + break; // Ascii Drive Mode + case 0x0004: + return QString("Sigma.ResolutionMode"); + break; // Ascii Resolution Mode + case 0x0005: + return QString("Sigma.AutofocusMode"); + break; // Ascii Autofocus mode + case 0x0006: + return QString("Sigma.FocusSetting"); + break; // Ascii Focus setting + case 0x0007: + return QString("Sigma.WhiteBalance"); + break; // Ascii White balance + case 0x0008: + return QString("Sigma.ExposureMode"); + break; // Ascii Exposure mode + case 0x0009: + return QString("Sigma.MeteringMode"); + break; // Ascii Metering mode + case 0x000a: + return QString("Sigma.LensRange"); + break; // Ascii Lens focal length range + case 0x000b: + return QString("Sigma.ColorSpace"); + break; // Ascii Color space + case 0x000c: + return QString("Sigma.Exposure"); + break; // Ascii Exposure + case 0x000d: + return QString("Sigma.Contrast"); + break; // Ascii Contrast + case 0x000e: + return QString("Sigma.Shadow"); + break; // Ascii Shadow + case 0x000f: + return QString("Sigma.Highlight"); + break; // Ascii Highlight + case 0x0010: + return QString("Sigma.Saturation"); + break; // Ascii Saturation + case 0x0011: + return QString("Sigma.Sharpness"); + break; // Ascii Sharpness + case 0x0012: + return QString("Sigma.FillLight"); + break; // Ascii X3 Fill light + case 0x0014: + return QString("Sigma.ColorAdjustment"); + break; // Ascii Color adjustment + case 0x0015: + return QString("Sigma.AdjustmentMode"); + break; // Ascii Adjustment mode + case 0x0016: + return QString("Sigma.Quality"); + break; // Ascii Quality + case 0x0017: + return QString("Sigma.Firmware"); + break; // Ascii Firmware + case 0x0018: + return QString("Sigma.Software"); + break; // Ascii Software + case 0x0019: + return QString("Sigma.AutoBracket"); + break; // Ascii Auto bracket + default: + strTmp = QString("Sigma.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } // SIGMA + else if(m_strImgExifMake == "SONY") + { + switch (nTag) + { + case 0xb021: + return QString("Sony.ColorTemperature"); + break; + case 0xb023: + return QString("Sony.SceneMode"); + break; + case 0xb024: + return QString("Sony.ZoneMatching"); + break; + case 0xb025: + return QString("Sony.DynamicRangeOptimizer"); + break; + case 0xb026: + return QString("Sony.ImageStabilization"); + break; + case 0xb027: + return QString("Sony.LensID"); + break; + case 0xb029: + return QString("Sony.ColorMode"); + break; + case 0xb040: + return QString("Sony.Macro"); + break; + case 0xb041: + return QString("Sony.ExposureMode"); + break; + case 0xb047: + return QString("Sony.Quality"); + break; + case 0xb04e: + return QString("Sony.LongExposureNoiseReduction"); + break; + default: + // No real info is known + strTmp = QString("Sony.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } // SONY + else if(m_strImgExifMake == "FUJIFILM") + { + switch (nTag) + { + case 0x0000: + return QString("Fujifilm.Version"); + break; // Undefined Fujifilm Makernote version + case 0x1000: + return QString("Fujifilm.Quality"); + break; // Ascii Image quality setting + case 0x1001: + return QString("Fujifilm.Sharpness"); + break; // Short Sharpness setting + case 0x1002: + return QString("Fujifilm.WhiteBalance"); + break; // Short White balance setting + case 0x1003: + return QString("Fujifilm.Color"); + break; // Short Chroma saturation setting + case 0x1004: + return QString("Fujifilm.Tone"); + break; // Short Contrast setting + case 0x1010: + return QString("Fujifilm.FlashMode"); + break; // Short Flash firing mode setting + case 0x1011: + return QString("Fujifilm.FlashStrength"); + break; // SRational Flash firing strength compensation setting + case 0x1020: + return QString("Fujifilm.Macro"); + break; // Short Macro mode setting + case 0x1021: + return QString("Fujifilm.FocusMode"); + break; // Short Focusing mode setting + case 0x1030: + return QString("Fujifilm.SlowSync"); + break; // Short Slow synchro mode setting + case 0x1031: + return QString("Fujifilm.PictureMode"); + break; // Short Picture mode setting + case 0x1100: + return QString("Fujifilm.Continuous"); + break; // Short Continuous shooting or auto bracketing setting + case 0x1210: + return QString("Fujifilm.FinePixColor"); + break; // Short Fuji FinePix Color setting + case 0x1300: + return QString("Fujifilm.BlurWarning"); + break; // Short Blur warning status + case 0x1301: + return QString("Fujifilm.FocusWarning"); + break; // Short Auto Focus warning status + case 0x1302: + return QString("Fujifilm.AeWarning"); + break; // Short Auto Exposure warning status + default: + strTmp = QString("Fujifilm.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } // FUJIFILM + else if(m_strImgExifMake == "NIKON") + { + if(m_nImgExifMakeSubtype == 1) + { + // Type 1 + switch (nTag) + { + case 0x0001: + return QString("Nikon1.Version"); + break; // Undefined Nikon Makernote version + case 0x0002: + return QString("Nikon1.ISOSpeed"); + break; // Short ISO speed setting + case 0x0003: + return QString("Nikon1.ColorMode"); + break; // Ascii Color mode + case 0x0004: + return QString("Nikon1.Quality"); + break; // Ascii Image quality setting + case 0x0005: + return QString("Nikon1.WhiteBalance"); + break; // Ascii White balance + case 0x0006: + return QString("Nikon1.Sharpening"); + break; // Ascii Image sharpening setting + case 0x0007: + return QString("Nikon1.Focus"); + break; // Ascii Focus mode + case 0x0008: + return QString("Nikon1.Flash"); + break; // Ascii Flash mode + case 0x000f: + return QString("Nikon1.ISOSelection"); + break; // Ascii ISO selection + case 0x0010: + return QString("Nikon1.DataDump"); + break; // Undefined Data dump + case 0x0080: + return QString("Nikon1.ImageAdjustment"); + break; // Ascii Image adjustment setting + case 0x0082: + return QString("Nikon1.Adapter"); + break; // Ascii Adapter used + case 0x0085: + return QString("Nikon1.FocusDistance"); + break; // Rational Manual focus distance + case 0x0086: + return QString("Nikon1.DigitalZoom"); + break; // Rational Digital zoom setting + case 0x0088: + return QString("Nikon1.AFFocusPos"); + break; // Undefined AF focus position + default: + strTmp = QString("Nikon1.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } + else if(m_nImgExifMakeSubtype == 2) + { + // Type 2 + switch (nTag) + { + case 0x0003: + return QString("Nikon2.Quality"); + break; // Short Image quality setting + case 0x0004: + return QString("Nikon2.ColorMode"); + break; // Short Color mode + case 0x0005: + return QString("Nikon2.ImageAdjustment"); + break; // Short Image adjustment setting + case 0x0006: + return QString("Nikon2.ISOSpeed"); + break; // Short ISO speed setting + case 0x0007: + return QString("Nikon2.WhiteBalance"); + break; // Short White balance + case 0x0008: + return QString("Nikon2.Focus"); + break; // Rational Focus mode + case 0x000a: + return QString("Nikon2.DigitalZoom"); + break; // Rational Digital zoom setting + case 0x000b: + return QString("Nikon2.Adapter"); + break; // Short Adapter used + default: + strTmp = QString("Nikon2.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } + else if(m_nImgExifMakeSubtype == 3) + { + // Type 3 + switch (nTag) + { + case 0x0001: + return QString("Nikon3.Version"); + break; // Undefined Nikon Makernote version + case 0x0002: + return QString("Nikon3.ISOSpeed"); + break; // Short ISO speed used + case 0x0003: + return QString("Nikon3.ColorMode"); + break; // Ascii Color mode + case 0x0004: + return QString("Nikon3.Quality"); + break; // Ascii Image quality setting + case 0x0005: + return QString("Nikon3.WhiteBalance"); + break; // Ascii White balance + case 0x0006: + return QString("Nikon3.Sharpening"); + break; // Ascii Image sharpening setting + case 0x0007: + return QString("Nikon3.Focus"); + break; // Ascii Focus mode + case 0x0008: + return QString("Nikon3.FlashSetting"); + break; // Ascii Flash setting + case 0x0009: + return QString("Nikon3.FlashMode"); + break; // Ascii Flash mode + case 0x000b: + return QString("Nikon3.WhiteBalanceBias"); + break; // SShort White balance bias + case 0x000e: + return QString("Nikon3.ExposureDiff"); + break; // Undefined Exposure difference + case 0x000f: + return QString("Nikon3.ISOSelection"); + break; // Ascii ISO selection + case 0x0010: + return QString("Nikon3.DataDump"); + break; // Undefined Data dump + case 0x0011: + return QString("Nikon3.ThumbOffset"); + break; // Long Thumbnail IFD offset + case 0x0012: + return QString("Nikon3.FlashComp"); + break; // Undefined Flash compensation setting + case 0x0013: + return QString("Nikon3.ISOSetting"); + break; // Short ISO speed setting + case 0x0016: + return QString("Nikon3.ImageBoundary"); + break; // Short Image boundry + case 0x0018: + return QString("Nikon3.FlashBracketComp"); + break; // Undefined Flash bracket compensation applied + case 0x0019: + return QString("Nikon3.ExposureBracketComp"); + break; // SRational AE bracket compensation applied + case 0x0080: + return QString("Nikon3.ImageAdjustment"); + break; // Ascii Image adjustment setting + case 0x0081: + return QString("Nikon3.ToneComp"); + break; // Ascii Tone compensation setting (contrast + case 0x0082: + return QString("Nikon3.AuxiliaryLens"); + break; // Ascii Auxiliary lens (adapter + case 0x0083: + return QString("Nikon3.LensType"); + break; // Byte Lens type + case 0x0084: + return QString("Nikon3.Lens"); + break; // Rational Lens + case 0x0085: + return QString("Nikon3.FocusDistance"); + break; // Rational Manual focus distance + case 0x0086: + return QString("Nikon3.DigitalZoom"); + break; // Rational Digital zoom setting + case 0x0087: + return QString("Nikon3.FlashType"); + break; // Byte Type of flash used + case 0x0088: + return QString("Nikon3.AFFocusPos"); + break; // Undefined AF focus position + case 0x0089: + return QString("Nikon3.Bracketing"); + break; // Short Bracketing + case 0x008b: + return QString("Nikon3.LensFStops"); + break; // Undefined Number of lens stops + case 0x008c: + return QString("Nikon3.ToneCurve"); + break; // Undefined Tone curve + case 0x008d: + return QString("Nikon3.ColorMode"); + break; // Ascii Color mode + case 0x008f: + return QString("Nikon3.SceneMode"); + break; // Ascii Scene mode + case 0x0090: + return QString("Nikon3.LightingType"); + break; // Ascii Lighting type + case 0x0092: + return QString("Nikon3.HueAdjustment"); + break; // SShort Hue adjustment + case 0x0094: + return QString("Nikon3.Saturation"); + break; // SShort Saturation adjustment + case 0x0095: + return QString("Nikon3.NoiseReduction"); + break; // Ascii Noise reduction + case 0x0096: + return QString("Nikon3.CompressionCurve"); + break; // Undefined Compression curve + case 0x0097: + return QString("Nikon3.ColorBalance2"); + break; // Undefined Color balance 2 + case 0x0098: + return QString("Nikon3.LensData"); + break; // Undefined Lens data + case 0x0099: + return QString("Nikon3.NEFThumbnailSize"); + break; // Short NEF thumbnail size + case 0x009a: + return QString("Nikon3.SensorPixelSize"); + break; // Rational Sensor pixel size + case 0x00a0: + return QString("Nikon3.SerialNumber"); + break; // Ascii Camera serial number + case 0x00a7: + return QString("Nikon3.ShutterCount"); + break; // Long Number of shots taken by camera + case 0x00a9: + return QString("Nikon3.ImageOptimization"); + break; // Ascii Image optimization + case 0x00aa: + return QString("Nikon3.Saturation"); + break; // Ascii Saturation + case 0x00ab: + return QString("Nikon3.VariProgram"); + break; // Ascii Vari program + + default: + strTmp = QString("Nikon3.0x%1").arg(nTag, 4, 16, QChar('0')); + bUnknown = true; + return strTmp; + break; + } + } + } // NIKON + } // if strSect + + bUnknown = true; + return QString("???"); +} + +// Interpret the MakerNote header to determine any applicable MakerNote subtype. +// +// PRE: +// - m_strImgExifMake +// - buffer +// +// INPUT: +// - none +// +// RETURN: +// - Decode success +// +// POST: +// - m_nImgExifMakeSubtype +// +bool CjfifDecode::DecodeMakerSubType() +{ + QString strTmp; + + m_nImgExifMakeSubtype = 0; + + if(m_strImgExifMake == "NIKON") + { + strTmp = ""; + for(uint32_t nInd = 0; nInd < 5; nInd++) + { + strTmp += Buf(m_nPos + nInd); + } + + if(strTmp == "Nikon") + { + if(Buf(m_nPos + 6) == 1) + { + // Type 1 + m_pLog->AddLine(" Nikon Makernote Type 1 detected"); + m_nImgExifMakeSubtype = 1; + m_nPos += 8; + } + else if(Buf(m_nPos + 6) == 2) + { + // Type 3 + m_pLog->AddLine(" Nikon Makernote Type 3 detected"); + m_nImgExifMakeSubtype = 3; + m_nPos += 18; + } + else + { + strTmp = "ERROR: Unknown Nikon Makernote Type"; + m_pLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return false; + } + } + else + { + // Type 2 + m_pLog->AddLine(" Nikon Makernote Type 2 detected"); + //m_nImgExifMakeSubtype = 2; + // tests on D1 seem to indicate that it uses Type 1 headers + m_nImgExifMakeSubtype = 1; + m_nPos += 0; + } + + } + else if(m_strImgExifMake == "SIGMA") + { + strTmp = ""; + for(uint32_t ind = 0; ind < 8; ind++) + { + if(Buf(m_nPos + ind) != 0) + strTmp += Buf(m_nPos + ind); + } + if((strTmp == "SIGMA") || (strTmp == "FOVEON")) + { + // Valid marker + // Now skip over the 8-chars and 2 unknown chars + m_nPos += 10; + } + else + { + strTmp = "ERROR: Unknown SIGMA Makernote identifier"; + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return false; + } + + } // SIGMA + else if(m_strImgExifMake == "FUJIFILM") + { + strTmp = ""; + for(uint32_t ind = 0; ind < 8; ind++) + { + if(Buf(m_nPos + ind) != 0) + strTmp += Buf(m_nPos + ind); + } + if(strTmp == "FUJIFILM") + { + // Valid marker + // Now skip over the 8-chars and 4 Pointer chars + // FIXME: Do I need to dereference this pointer? + m_nPos += 12; + } + else + { + strTmp = "ERROR: Unknown FUJIFILM Makernote identifier"; + m_pLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return false; + } + + } // FUJIFILM + else if(m_strImgExifMake == "SONY") + { + strTmp = ""; + for(uint32_t ind = 0; ind < 12; ind++) + { + if(Buf(m_nPos + ind) != 0) + strTmp += Buf(m_nPos + ind); + } + if(strTmp == "SONY DSC ") + { + // Valid marker + // Now skip over the 9-chars and 3 null chars + m_nPos += 12; + } + else + { + strTmp = "ERROR: Unknown SONY Makernote identifier"; + m_pLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strTmp); + msgBox.exec(); + } + + return false; + } + + } // SONY + + return true; + +} + +// Read two UINT32 from the buffer (8B) and interpret +// as a rational entry. Convert to floating point. +// Byte swap as required +// +// INPUT: +// - pos Buffer position +// - val Floating point value +// +// RETURN: +// - Was the conversion successful? +// +bool CjfifDecode::DecodeValRational(uint32_t nPos, float &nVal) +{ + int nValNumer; + + int nValDenom; + + nVal = 0; + + nValNumer = ByteSwap4(Buf(nPos + 0), Buf(nPos + 1), Buf(nPos + 2), Buf(nPos + 3)); + nValDenom = ByteSwap4(Buf(nPos + 4), Buf(nPos + 5), Buf(nPos + 6), Buf(nPos + 7)); + + if(nValDenom == 0) + { + // Divide by zero! + return false; + } + else + { + nVal = (float) nValNumer / (float) nValDenom; + return true; + } +} + +// Read two UINT32 from the buffer (8B) to create a formatted +// fraction string. Byte swap as required +// +// INPUT: +// - pos Buffer position +// +// RETURN: +// - Formatted string +// +QString CjfifDecode::DecodeValFraction(uint32_t nPos) +{ + QString strTmp; + + int nValNumer = ReadSwap4(nPos + 0); + + int nValDenom = ReadSwap4(nPos + 4); + + strTmp = QString("%1/%2").arg(nValNumer).arg(nValDenom); + return strTmp; +} + +// Convert multiple coordinates into a formatted GPS string +// +// INPUT: +// - nCount Number of coordinates (1,2,3) +// - fCoord1 Coordinate #1 +// - fCoord2 Coordinate #2 +// - fCoord3 Coordinate #3 +// +// OUTPUT: +// - strCoord The formatted GPS string +// +// RETURN: +// - Was the conversion successful? +// +bool CjfifDecode::PrintValGPS(uint32_t nCount, float fCoord1, float fCoord2, float fCoord3, QString & strCoord) +{ + float fTemp; + + uint32_t nCoordDeg; + + uint32_t nCoordMin; + + float fCoordSec; + + // TODO: Extend to support 1 & 2 coordinate GPS entries + if(nCount == 3) + { + nCoordDeg = uint32_t (fCoord1); + + nCoordMin = uint32_t (fCoord2); + + if(fCoord3 == 0) + { + fTemp = fCoord2 - (float) nCoordMin; + fCoordSec = fTemp * (float) 60.0; + } + else + { + fCoordSec = fCoord3; + } + + strCoord = QString("%1 deg %2' %.3f\"").arg(nCoordDeg).arg(nCoordMin).arg(fCoordSec); + return true; + } + else + { + strCoord = QString("ERROR: Can't handle %1-comonent GPS coords").arg(nCount); + return false; + } + +} + +// Read in 3 rational values from the buffer and output as a formatted GPS string +// +// INPUT: +// - pos Buffer position +// +// OUTPUT: +// - strCoord The formatted GPS string +// +// RETURN: +// - Was the conversion successful? +// +bool CjfifDecode::DecodeValGPS(uint32_t nPos, QString & strCoord) +{ + float fCoord1 = 0; + + float fCoord2 = 0; + + float fCoord3 = 0; + + bool bRet; + + bRet = true; + if(bRet) + { + bRet = DecodeValRational(nPos, fCoord1); + nPos += 8; + } + if(bRet) + { + bRet = DecodeValRational(nPos, fCoord2); + nPos += 8; + } + if(bRet) + { + bRet = DecodeValRational(nPos, fCoord3); + nPos += 8; + } + + if(!bRet) + { + strCoord = QString("???"); + return false; + } + else + { + return PrintValGPS(3, fCoord1, fCoord2, fCoord3, strCoord); + } +} + +// Read a UINT16 from the buffer, byte swap as required +// +// INPUT: +// - nPos Buffer position +// +// RETURN: +// - UINT16 from buffer +// +uint32_t CjfifDecode::ReadSwap2(uint32_t nPos) +{ + return ByteSwap2(Buf(nPos + 0), Buf(nPos + 1)); +} + +// Read a UINT32 from the buffer, byte swap as required +// +// INPUT: +// - nPos Buffer position +// +// RETURN: +// - UINT32 from buffer +// +uint32_t CjfifDecode::ReadSwap4(uint32_t nPos) +{ + return ByteSwap4(Buf(nPos), Buf(nPos + 1), Buf(nPos + 2), Buf(nPos + 3)); +} + +// Read a UINT32 from the buffer, force as big endian +// +// INPUT: +// - nPos Buffer position +// +// RETURN: +// - UINT32 from buffer +// +uint32_t CjfifDecode::ReadBe4(uint32_t nPos) +{ + // Big endian, no swap required + return (Buf(nPos) << 24) + (Buf(nPos + 1) << 16) + (Buf(nPos + 2) << 8) + Buf(nPos + 3); +} + +// Print hex from array of unsigned char +// +// INPUT: +// - anBytes Array of unsigned chars +// - nCount Indicates the number of array entries originally specified +// but the printing routine limits it to the maximum array depth +// allocated (MAX_anValues) and add an ellipsis "..." +// RETURN: +// - A formatted string +// +QString CjfifDecode::PrintAsHexUC(uint8_t *anBytes, uint32_t nCount) +{ + QString strVal; + + QString strFull; + + strFull = "0x["; + uint32_t nMaxDisplay = MAX_anValues; + + bool bExceedMaxDisplay; + + bExceedMaxDisplay = (nCount > nMaxDisplay); + for(uint32_t nInd = 0; nInd < nCount; nInd++) + { + if(nInd < nMaxDisplay) + { + if((nInd % 4) == 0) + { + if(nInd == 0) + { + // Don't do anything for first value! + } + else + { + // Every 16 add big spacer / break + strFull += " "; + } + } + else + { + //strFull += " "; + } + + strVal = QString("%1").arg(anBytes[nInd], 2, 16, QChar('0')); + strFull += strVal; + } + + if((nInd == nMaxDisplay) && (bExceedMaxDisplay)) + { + strFull += "..."; + } + + } + strFull += "]"; + return strFull; +} + +// Print hex from array of unsigned bytes +// +// INPUT: +// - anBytes Array is passed as UINT32* even though it only +// represents a byte per entry +// - nCount Indicates the number of array entries originally specified +// but the printing routine limits it to the maximum array depth +// allocated (MAX_anValues) and add an ellipsis "..." +// +// RETURN: +// - A formatted string +// +QString CjfifDecode::PrintAsHex8(uint32_t *anBytes, uint32_t nCount) +{ + QString strVal; + + QString strFull; + + uint32_t nMaxDisplay = MAX_anValues; + + bool bExceedMaxDisplay; + + strFull = "0x["; + bExceedMaxDisplay = (nCount > nMaxDisplay); + for(uint32_t nInd = 0; nInd < nCount; nInd++) + { + if(nInd < nMaxDisplay) + { + if((nInd % 4) == 0) + { + if(nInd == 0) + { + // Don't do anything for first value! + } + else + { + // Every 16 add big spacer / break + strFull += " "; + } + } + + strVal = QString("%1").arg(anBytes[nInd], 2, 16, QChar('0')); + strFull += strVal; + } + + if((nInd == nMaxDisplay) && (bExceedMaxDisplay)) + { + strFull += "..."; + } + + } + strFull += "]"; + return strFull; +} + +// Print hex from array of unsigned words +// +// INPUT: +// - anWords Array of UINT32 is passed +// - nCount Indicates the number of array entries originally specified +// but the printing routine limits it to the maximum array depth +// allocated (MAX_anValues) and add an ellipsis "..." +// +// RETURN: +// - A formatted string +// +QString CjfifDecode::PrintAsHex32(uint32_t *anWords, uint32_t nCount) +{ + QString strVal; + + QString strFull; + + strFull = "0x["; + uint32_t nMaxDisplay = MAX_anValues / 4; // Reduce number of words to display since each is 32b not 8b + + bool bExceedMaxDisplay; + + bExceedMaxDisplay = (nCount > nMaxDisplay); + for(uint32_t nInd = 0; nInd < nCount; nInd++) + { + if(nInd < nMaxDisplay) + { + if(nInd == 0) + { + // Don't do anything for first value! + } + else + { + // Every word add a spacer + strFull += " "; + } + + strVal = QString("%1").arg(anWords[nInd], 8, 16, QChar('0')); // 32-bit words + strFull += strVal; + } + + if((nInd == nMaxDisplay) && (bExceedMaxDisplay)) + { + strFull += "..."; + } + + } + strFull += "]"; + return strFull; +} + +// Process all of the entries within an EXIF IFD directory +// This is used for the main EXIF IFDs as well as MakerNotes +// +// INPUT: +// - ifdStr The IFD section that we are processing +// - pos_exif_start +// - start_ifd_ptr +// +// PRE: +// - m_strImgExifMake +// - m_bImgExifMakeSupported +// - m_nImgExifMakeSubtype +// - m_nImgExifMakerPtr +// +// RETURN: +// - 0 Decoding OK +// - 2 Decoding failure +// +// POST: +// - m_nPos +// - m_strImgExifMake +// - m_strImgExifModel +// - m_strImgQualExif +// - m_strImgExtras +// - m_strImgExifMake +// - m_nImgExifSubIfdPtr +// - m_nImgExifGpsIfdPtr +// - m_nImgExifInteropIfdPtr +// - m_bImgExifMakeSupported +// - m_bImgExifMakernotes +// - m_nImgExifMakerPtr +// - m_nImgExifThumbComp +// - m_nImgExifThumbOffset +// - m_nImgExifThumbLen +// - m_strSoftware +// +// NOTE: +// - IFD1 typically contains the thumbnail +// +uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint32_t nStartIfdPtr) +{ + // Temp variables + bool bRet; + + QString strTmp; + + CStr2 strRetVal; + + QString strValTmp; + + float fValReal; + + QString strMaker; + + // Display output variables + QString strFull; + + QString strValOut; + + bool bExtraDecode; + + // Primary IFD variables + uint8_t acIfdValOffsetStr[5]; + + uint32_t nIfdDirLen; + + uint32_t nIfdTagVal; + + uint32_t nIfdFormat; + + uint32_t nIfdNumComps; + + bool nIfdTagUnknown; + + uint32_t nCompsToDisplay; // Maximum number of values to capture for display + + uint32_t anValues[MAX_anValues]; // Array of decoded values (Uint32) + + signed anValuesS[MAX_anValues]; // Array of decoded values (Int32) + + float afValues[MAX_anValues]; // Array of decoded values (float) + + uint32_t nIfdOffset; // First DWORD decode, usually offset + + // Clear values array + for(uint32_t ind = 0; ind < MAX_anValues; ind++) + { + anValues[ind] = 0; + anValuesS[ind] = 0; + afValues[ind] = 0; + } + + // ========================================================================== + // Process IFD directory header + // ========================================================================== + + // Move the file pointer to the start of the IFD + m_nPos = nPosExifStart + nStartIfdPtr; + + strTmp = QString(" EXIF %1 @ Absolute 0x%2").arg(strIfd).arg(m_nPos, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + //////////// + + // NOTE: Nikon type 3 starts out with the ASCII string "Nikon\0" + // before the rest of the items. + // TODO: need to process type1,type2,type3 + // see: http://www.gvsoft.homedns.org/exif/makernote-nikon.html + + strTmp = QString("strIfd=[%1] m_strImgExifMake=[%2]").arg(strIfd).arg(m_strImgExifMake); + DbgAddLine(strTmp); + + // If this is the MakerNotes section, then we may want to skip + // altogether. Check to see if we are configured to process this + // section or if it is a supported manufacturer. + + if(strIfd == "MakerIFD") + { + // Mark the image as containing Makernotes + m_bImgExifMakernotes = true; + + if(!m_pAppConfig->bDecodeMaker) + { + strTmp = QString(" Makernote decode option not enabled."); + m_pLog->AddLine(strTmp); + + // If user didn't enable makernote decode, don't exit, just + // hide output. We still want to get at some info (such as Quality setting). + // At end, we'll need to re-enable it again. + m_pLog->Disable(); + } + + // If this Make is not supported, we'll need to exit + if(!m_bImgExifMakeSupported) + { + strTmp = QString(" Makernotes not yet supported for [%1]").arg(m_strImgExifMake); + m_pLog->AddLine(strTmp); + + m_pLog->Enable(); + return 2; + } + + // Determine the sub-type of the Maker field (if applicable) + // and advance the m_nPos pointer past the custom header. + // This call uses the class members: Buf(),m_nPos + if(!DecodeMakerSubType()) + { + // If the subtype decode failed, skip the processing + m_pLog->Enable(); + return 2; + } + + } + + // ========================================================================== + // Process IFD directory entries + // ========================================================================== + + QString strIfdTag; + + // =========== EXIF IFD Header (Start) =========== + // - Defined in Exif 2.2 Standard (JEITA CP-3451) section 4.6.2 + // - Contents (2 bytes total) + // - Number of fields (2 bytes) + + nIfdDirLen = ReadSwap2(m_nPos); + m_nPos += 2; + strTmp = QString(" Dir Length = 0x%1").arg(nIfdDirLen, 4, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + // =========== EXIF IFD Header (End) =========== + + // Start of IFD processing + // Step through each IFD entry and determine the type and + // decode accordingly. + for(uint32_t nIfdEntryInd = 0; nIfdEntryInd < nIfdDirLen; nIfdEntryInd++) + { + + // By default, show single-line value summary + // bExtraDecode is used to indicate that additional special + // parsing output is available for this entry + bExtraDecode = false; + + strTmp = QString(" Entry #%1:").arg(nIfdEntryInd, 2, 10, QChar('0')); + DbgAddLine(strTmp); + + // =========== EXIF IFD Interoperability entry (Start) =========== + // - Defined in Exif 2.2 Standard (JEITA CP-3451) section 4.6.2 + // - Contents (12 bytes total) + // - Tag (2 bytes) + // - Type (2 bytes) + // - Count (4 bytes) + // - Value Offset (4 bytes) + + // Read Tag # + nIfdTagVal = ReadSwap2(m_nPos); + m_nPos += 2; + nIfdTagUnknown = false; + strIfdTag = LookupExifTag(strIfd, nIfdTagVal, nIfdTagUnknown); + strTmp = QString(" Tag # = 0x%1 = [%2]").arg(nIfdTagVal, 4, 16, QChar('0')).arg(strIfdTag); + DbgAddLine(strTmp); + + // Read Format (or Type) + nIfdFormat = ReadSwap2(m_nPos); + m_nPos += 2; + strTmp = QString(" Format # = 0x%1").arg(nIfdFormat, 4, 16, QChar('0')); + DbgAddLine(strTmp); + + // Read number of Components + nIfdNumComps = ReadSwap4(m_nPos); + m_nPos += 4; + strTmp = QString(" # Comps = 0x%1").arg(nIfdNumComps, 4, 16, QChar('0')); + DbgAddLine(strTmp); + + // Check to see how many components have been listed. + // This helps trap errors in corrupted IFD segments, otherwise + // we will hang trying to decode millions of entries! + // See issue & testcase #1148 + if(nIfdNumComps > 4000) + { + // Warn user that we have clippped the component list. + // Note that this condition is only relevant when we are + // processing the general array fields. Fields such as MakerNote + // will also enter this condition so we shouldn't warn in those cases. + // + // TODO: Defer this warning message until after we are sure that we + // didn't handle the large dataset elsewhere. + // For now, only report this warning if we are not processing MakerNote + if(strIfdTag != "MakerNote") + { + strTmp = QString(" Excessive # components (%1). Limiting to first 4000.").arg(nIfdNumComps); + m_pLog->AddLineWarn(strTmp); + } + nIfdNumComps = 4000; + } + + // Read Component Value / Offset + // We first treat it as a string and then re-interpret it as an integer + + // ... first as a string (just in case length <=4) + for(uint32_t i = 0; i < 4; i++) + { + acIfdValOffsetStr[i] = Buf(m_nPos + i); + } + acIfdValOffsetStr[4] = '\0'; + + // ... now as an unsigned value + // This assignment is general-purpose, typically used when + // we know that the IFD Value/Offset is just an offset + nIfdOffset = ReadSwap4(m_nPos); + strTmp = QString(" # Val/Offset = 0x%1").arg(nIfdOffset, 8, 16, QChar('0')); + DbgAddLine(strTmp); + + // =========== EXIF IFD Interoperability entry (End) =========== + + // ========================================================================== + // Extract the IFD component entries + // ========================================================================== + + // The EXIF IFD entries can appear in a wide range of + // formats / data types. The formats that have been + // publicly documented include: + // EXIF_FORMAT_quint8 = 1, + // EXIF_FORMAT_ASCII = 2, + // EXIF_FORMAT_SHORT = 3, + // EXIF_FORMAT_LONG = 4, + // EXIF_FORMAT_RATIONAL = 5, + // EXIF_FORMAT_Squint8 = 6, + // EXIF_FORMAT_UNDEFINED = 7, + // EXIF_FORMAT_SSHORT = 8, + // EXIF_FORMAT_SLONG = 9, + // EXIF_FORMAT_SRATIONAL = 10, + // EXIF_FORMAT_FLOAT = 11, + // EXIF_FORMAT_DOUBLE = 12 + + // The IFD variable formatter logic operates in two stages: + // In the first stage, the format type is decoded, which results + // in a generic decode for the IFD entry. Then, we start a second + // stage which re-interprets the values for a number of known + // special types. + + switch (nIfdFormat) + { + + // ---------------------------------------- + // --- IFD Entry Type: Unsigned Byte + // ---------------------------------------- + case 1: + strFull = " Unsigned Byte=["; + strValOut = ""; + + // Limit display output + nCompsToDisplay = qMin(uint32_t (MAX_anValues), nIfdNumComps); + + // If only a single value, use decimal, else use hex + if(nIfdNumComps == 1) + { + anValues[0] = Buf(m_nPos + 0); + strTmp = QString("%1").arg(anValues[0]); + strValOut += strTmp; + } + else + { + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) + { + if(nIfdNumComps <= 4) + { + // Components fit inside 4B inline region + anValues[nInd] = Buf(m_nPos + nInd); + } + else + { + // Since the components don't fit inside 4B inline region + // we need to dereference + anValues[nInd] = Buf(nPosExifStart + nIfdOffset + nInd); + } + } + strValOut = PrintAsHex8(anValues, nIfdNumComps); + } + strFull += strValOut; + strFull += "]"; + DbgAddLine(strFull); + break; + + // ---------------------------------------- + // --- IFD Entry Type: ASCII string + // ---------------------------------------- + case 2: + strFull = " String="; + strValOut = ""; + char cVal; + + quint8 nVal; + + // Limit display output + // TODO: Decide what an appropriate string limit would be + nCompsToDisplay = qMin(uint(250), nIfdNumComps); + + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) + { + if(nIfdNumComps <= 4) + { + nVal = acIfdValOffsetStr[nInd]; + } + else + { + // TODO: See if this can be migrated to the "custom decode" + // section later in the code. Decoding makernotes here is + // less desirable but unfortunately some Nikon makernotes use + // a non-standard offset value. + if((strIfd == "MakerIFD") && (m_strImgExifMake == "NIKON") && (m_nImgExifMakeSubtype == 3)) + { + // It seems that pointers in the Nikon Makernotes are + // done relative to the start of Maker IFD + // But why 10? Is this 10 = 18-8? + nVal = Buf(nPosExifStart + m_nImgExifMakerPtr + nIfdOffset + 10 + nInd); + } + else if((strIfd == "MakerIFD") && (m_strImgExifMake == "NIKON")) + { + // It seems that pointers in the Nikon Makernotes are + // done relative to the start of Maker IFD + nVal = Buf(nPosExifStart + nIfdOffset + 0 + nInd); + } + else + { + // Canon Makernotes seem to be relative to the start + // of the EXIF IFD + nVal = Buf(nPosExifStart + nIfdOffset + nInd); + } + } + + // Just in case the string has been null-terminated early + // or we have garbage, replace with '.' + // TODO: Clean this up + if(nVal != 0) + { + cVal = (char) nVal; + if(!isprint(nVal)) + { + cVal = '.'; + } + strValOut += cVal; + } + + } + strFull += strValOut; + DbgAddLine(strFull); + + // TODO: Ideally, we would use a different string for display + // purposes that is wrapped in quotes. Currently "strValOut" is used + // in other sections of code (eg. in assignment to EXIF Make/Model/Software, etc.) + // so we don't want to affect that. + + break; + + // ---------------------------------------- + // --- IFD Entry Type: Unsigned Short (2 bytes) + // ---------------------------------------- + case 3: + // Limit display output + nCompsToDisplay = qMin(MAX_anValues, nIfdNumComps); + + // Unsigned Short (2 bytes) + if(nIfdNumComps == 1) + { + strFull = " Unsigned Short=["; + // TODO: Confirm endianness is correct here + // Refer to Exif2-2 spec, page 14. + // Currently selecting 2 byte conversion from [1:0] out of [3:0] + anValues[0] = ReadSwap2(m_nPos); + strValOut = QString("%1").arg(anValues[0]); + strFull += strValOut; + strFull += "]"; + DbgAddLine(strFull); + } + else if(nIfdNumComps == 2) + { + strFull = " Unsigned Short=["; + // 2 unsigned shorts in 1 word + anValues[0] = ReadSwap2(m_nPos + 0); + anValues[1] = ReadSwap2(m_nPos + 2); + strValOut = QString("%1, %1").arg(anValues[0]).arg(anValues[1]); + strFull += strValOut; + strFull += "]"; + DbgAddLine(strFull); + } + else if(nIfdNumComps > MAX_IFD_COMPS) + { + strValTmp = QString(" Unsigned Short=[Too many entries (%1) to display]").arg(nIfdNumComps); + DbgAddLine(strValTmp); + strValOut = QString("[Too many entries (%1) to display]").arg(nIfdNumComps); + } + else + { + // Try to handle multiple entries... note that this + // is used by the Maker notes IFD decode + + strValOut = ""; + strFull = " Unsigned Short=["; + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) + { + if(nInd != 0) + { + strValOut += ", "; + } + anValues[nInd] = ReadSwap2(nPosExifStart + nIfdOffset + (2 * nInd)); + strValTmp = QString("%1").arg(anValues[nInd]); + strValOut += strValTmp; + } + strFull += strValOut; + strFull += "]"; + DbgAddLine(strFull); + + } + break; + + // ---------------------------------------- + // --- IFD Entry Type: Unsigned Long (4 bytes) + // ---------------------------------------- + case 4: + strFull = " Unsigned Long=["; + strValOut = ""; + + // Limit display output + nCompsToDisplay = qMin(MAX_anValues, nIfdNumComps); + + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) + { + if(nIfdNumComps == 1) + { + // Components fit inside 4B inline region + anValues[nInd] = ReadSwap4(m_nPos + (nInd * 4)); + } + else + { + // Since the components don't fit inside 4B inline region + // we need to dereference + anValues[nInd] = ReadSwap4(nPosExifStart + nIfdOffset + (nInd * 4)); + } + } + strValOut = PrintAsHex32(anValues, nIfdNumComps); + // If we only have a single component, then display both the hex and decimal + if(nCompsToDisplay == 1) + { + strTmp = QString("%1 / %2").arg(strValOut).arg(anValues[0]); + strValOut = strTmp; + } + break; + + // ---------------------------------------- + // --- IFD Entry Type: Unsigned Rational (8 bytes) + // ---------------------------------------- + case 5: + // Unsigned Rational + strFull = " Unsigned Rational=["; + strValOut = ""; + + // Limit display output + nCompsToDisplay = qMin(MAX_anValues, nIfdNumComps); + + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) + { + if(nInd != 0) + { + strValOut += ", "; + } + strValTmp = DecodeValFraction(nPosExifStart + nIfdOffset + (nInd * 8)); + bRet = DecodeValRational(nPosExifStart + nIfdOffset + (nInd * 8), fValReal); + afValues[nInd] = fValReal; + strValOut += strValTmp; + } + strFull += strValOut; + strFull += "]"; + DbgAddLine(strFull); + break; + + // ---------------------------------------- + // --- IFD Entry Type: Undefined (?) + // ---------------------------------------- + case 7: + // Undefined -- assume 1 word long + // This is supposed to be a series of 8-bit bytes + // It is usually used for 32-bit pointers (in case of offsets), but could + // also represent ExifVersion, etc. + strFull = " Undefined=["; + strValOut = ""; + + // Limit display output + nCompsToDisplay = qMin(MAX_anValues, nIfdNumComps); + + if(nIfdNumComps <= 4) + { + // This format is not defined, so output as hex for now + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) + { + anValues[nInd] = Buf(m_nPos + nInd); + } + strValOut = PrintAsHex8(anValues, nIfdNumComps); + strFull += strValOut; + + } + else + { + + // Dereference pointer + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) + { + anValues[nInd] = Buf(nPosExifStart + nIfdOffset + nInd); + } + strValOut = PrintAsHex8(anValues, nIfdNumComps); + strFull += strValOut; + } + strFull += "]"; + DbgAddLine(strFull); + + break; + + // ---------------------------------------- + // --- IFD Entry Type: Signed Short (2 bytes) + // ---------------------------------------- + case 8: + // Limit display output + nCompsToDisplay = qMin(MAX_anValues, nIfdNumComps); + + // Signed Short (2 bytes) + if(nIfdNumComps == 1) + { + strFull = " Signed Short=["; + // TODO: Confirm endianness is correct here + // Refer to Exif2-2 spec, page 14. + // Currently selecting 2 byte conversion from [1:0] out of [3:0] + + // TODO: Ensure that ReadSwap2 handles signed notation properly + anValuesS[0] = ReadSwap2(m_nPos); + strValOut = QString("%1").arg(anValuesS[0]); + strFull += strValOut; + strFull += "]"; + DbgAddLine(strFull); + } + else if(nIfdNumComps == 2) + { + strFull = " Signed Short=["; + // 2 signed shorts in 1 word + + // TODO: Ensure that ReadSwap2 handles signed notation properly + anValuesS[0] = ReadSwap2(m_nPos + 0); + anValuesS[1] = ReadSwap2(m_nPos + 2); + strValOut = QString("%1, %1").arg(anValuesS[0]).arg(anValuesS[0]); + strFull += strValOut; + strFull += "]"; + DbgAddLine(strFull); + } + else if(nIfdNumComps > MAX_IFD_COMPS) + { + // Only print it out if it has less than MAX_IFD_COMPS entries + strValTmp = QString(" Signed Short=[Too many entries (%1) to display]").arg(nIfdNumComps); + DbgAddLine(strValTmp); + strValOut = QString("[Too many entries (%1) to display]").arg(nIfdNumComps); + } + else + { + // Try to handle multiple entries... note that this + // is used by the Maker notes IFD decode + + // Note that we don't call LookupMakerCanonTag() here + // as that is only needed for the "unsigned short", not + // "signed short". + strValOut = ""; + strFull = " Signed Short=["; + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) + { + if(nInd != 0) + { + strValOut += ", "; + } + anValuesS[nInd] = ReadSwap2(nPosExifStart + nIfdOffset + (2 * nInd)); + strValTmp = QString("%1").arg(anValuesS[nInd]); + strValOut += strValTmp; + } + strFull += strValOut; + strFull += "]"; + DbgAddLine(strFull); + + } + break; + + // ---------------------------------------- + // --- IFD Entry Type: Signed Rational (8 bytes) + // ---------------------------------------- + case 10: + // Signed Rational + strFull = " Signed Rational=["; + strValOut = ""; + + // Limit display output + nCompsToDisplay = qMin(MAX_anValues, nIfdNumComps); + + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) + { + if(nInd != 0) + { + strValOut += ", "; + } + strValTmp = DecodeValFraction(nPosExifStart + nIfdOffset + (nInd * 8)); + bRet = DecodeValRational(nPosExifStart + nIfdOffset + (nInd * 8), fValReal); + afValues[nInd] = fValReal; + strValOut += strValTmp; + } + strFull += strValOut; + strFull += "]"; + DbgAddLine(strFull); + break; + + default: + strTmp = QString("ERROR: Unsupported format [%1]").arg(nIfdFormat); + anValues[0] = ReadSwap4(m_nPos); + strValOut = QString("0x%1???").arg(anValues[0], 4, 16, QChar('0')); + m_pLog->Enable(); + return 2; + break; + } // switch nIfdTagVal + + // ========================================================================== + // Custom Value String decodes + // ========================================================================== + + // At this point we might re-format the values, thereby + // overriding the default strValOut. We have access to the + // anValues[] (array of unsigned int) + // anValuesS[] (array of signed int) + // afValues[] (array of float) + + // Re-format special output items + // This will override "strValOut" that may have previously been defined + + if((strIfdTag == "GPSLatitude") || (strIfdTag == "GPSLongitude")) + { + bRet = PrintValGPS(nIfdNumComps, afValues[0], afValues[1], afValues[2], strValOut); + } + else if(strIfdTag == "GPSVersionID") + { + strValOut = QString("%1.%2.%3.%4").arg(anValues[0]).arg(anValues[1]).arg(anValues[2]).arg(anValues[3]); + } + else if(strIfdTag == "GPSAltitudeRef") + { + switch (anValues[0]) + { + case 0: + strValOut = "Above Sea Level"; + break; + case 1: + strValOut = "Below Sea Level"; + break; + } + } + else if(strIfdTag == "GPSStatus") + { + switch (acIfdValOffsetStr[0]) + { + case 'A': + strValOut = "Measurement in progress"; + break; + case 'V': + strValOut = "Measurement Interoperability"; + break; + } + } + else if(strIfdTag == "GPSMeasureMode") + { + switch (acIfdValOffsetStr[0]) + { + case '2': + strValOut = "2-dimensional"; + break; + case '3': + strValOut = "3-dimensional"; + break; + } + } + else if((strIfdTag == "GPSSpeedRef") || (strIfdTag == "GPSDestDistanceRef")) + { + switch (acIfdValOffsetStr[0]) + { + case 'K': + strValOut = "km/h"; + break; + case 'M': + strValOut = "mph"; + break; + case 'N': + strValOut = "knots"; + break; + } + } + else if((strIfdTag == "GPSTrackRef") || (strIfdTag == "GPSImgDirectionRef") || (strIfdTag == "GPSDestBearingRef")) + { + switch (acIfdValOffsetStr[0]) + { + case 'T': + strValOut = "True direction"; + break; + case 'M': + strValOut = "Magnetic direction"; + break; + } + } + else if(strIfdTag == "GPSDifferential") + { + switch (anValues[0]) + { + case 0: + strValOut = "Measurement without differential correction"; + break; + case 1: + strValOut = "Differential correction applied"; + break; + } + } + else if(strIfdTag == "GPSAltitude") + { + strValOut = QString("%.3f m").arg(afValues[0]); + } + else if(strIfdTag == "GPSSpeed") + { + strValOut = QString("%.3f").arg(afValues[0]); + } + else if(strIfdTag == "GPSTimeStamp") + { + strValOut = QString("%.0f:%.0f:%.2f").arg(afValues[0]).arg(afValues[1]).arg(afValues[2]); + } + else if(strIfdTag == "GPSTrack") + { + strValOut = QString("%1").arg(afValues[0], 0, 'f', 2); + } + else if(strIfdTag == "GPSDOP") + { + strValOut = QString("%1").arg(afValues[0], 0, 'f', 4); + } + + if(strIfdTag == "Compression") + { + switch (anValues[0]) + { + case 1: + strValOut = "None"; + break; + case 6: + strValOut = "JPEG"; + break; + } + } + else if(strIfdTag == "ExposureTime") + { + // Assume only one + strValTmp = strValOut; + strValOut = QString("%1 s").arg(strValTmp); + } + else if(strIfdTag == "FNumber") + { + // Assume only one + strValOut = QString("F%1").arg(afValues[0], 0, 'f', 1); + } + else if(strIfdTag == "FocalLength") + { + // Assume only one + strValOut = QString("%1 mm").arg(afValues[0], 0, 'f', 0); + } + else if(strIfdTag == "ExposureBiasValue") + { + // Assume only one + // TODO: Need to test negative numbers + strValOut = QString("%1 eV").arg(afValues[0], 0, 'f', 2); + } + else if(strIfdTag == "ExifVersion") + { + // Assume only one + strValOut = QString("%1%2.%3%4") + .arg(static_cast(anValues[0])) + .arg(static_cast(anValues[1])) + .arg(static_cast(anValues[2])) + .arg(static_cast(anValues[3])); + } + else if(strIfdTag == "FlashPixVersion") + { + // Assume only one + strValOut = QString("%1%2.%3%4") + .arg(static_cast(anValues[0])) + .arg(static_cast(anValues[1])) + .arg(static_cast(anValues[2])) + .arg(static_cast(anValues[3])); + } + else if(strIfdTag == "PhotometricInterpretation") + { + switch (anValues[0]) + { + case 1: + strValOut = "Monochrome"; + break; + case 2: + strValOut = "RGB"; + break; + case 6: + strValOut = "YCbCr"; + break; + } + } + else if(strIfdTag == "Orientation") + { + switch (anValues[0]) + { + case 1: + strValOut = "1 = Row 0: top, Col 0: left"; + break; + case 2: + strValOut = "2 = Row 0: top, Col 0: right"; + break; + case 3: + strValOut = "3 = Row 0: bottom, Col 0: right"; + break; + case 4: + strValOut = "4 = Row 0: bottom, Col 0: left"; + break; + case 5: + strValOut = "5 = Row 0: left, Col 0: top"; + break; + case 6: + strValOut = "6 = Row 0: right, Col 0: top"; + break; + case 7: + strValOut = "7 = Row 0: right, Col 0: bottom"; + break; + case 8: + strValOut = "8 = Row 0: left, Col 0: bottom"; + break; + } + } + else if(strIfdTag == "PlanarConfiguration") + { + switch (anValues[0]) + { + case 1: + strValOut = "Chunky format"; + break; + case 2: + strValOut = "Planar format"; + break; + } + } + else if(strIfdTag == "YCbCrSubSampling") + { + switch (anValues[0] * 65536 + anValues[1]) + { + case 0x00020001: + strValOut = "4:2:2"; + break; + case 0x00020002: + strValOut = "4:2:0"; + break; + } + } + else if(strIfdTag == "YCbCrPositioning") + { + switch (anValues[0]) + { + case 1: + strValOut = "Centered"; + break; + case 2: + strValOut = "Co-sited"; + break; + } + } + else if(strIfdTag == "ResolutionUnit") + { + switch (anValues[0]) + { + case 1: + strValOut = "None"; + break; + case 2: + strValOut = "Inch"; + break; + case 3: + strValOut = "Centimeter"; + break; + } + } + else if(strIfdTag == "FocalPlaneResolutionUnit") + { + switch (anValues[0]) + { + case 1: + strValOut = "None"; + break; + case 2: + strValOut = "Inch"; + break; + case 3: + strValOut = "Centimeter"; + break; + } + } + else if(strIfdTag == "ColorSpace") + { + switch (anValues[0]) + { + case 1: + strValOut = "sRGB"; + break; + case 0xFFFF: + strValOut = "Uncalibrated"; + break; + } + } + else if(strIfdTag == "ComponentsConfiguration") + { + // Undefined type, assume 4 bytes + strValOut = "["; + for(uint32_t vind = 0; vind < 4; vind++) + { + if(vind != 0) + { + strValOut += " "; + } + switch (anValues[vind]) + { + case 0: + strValOut += "."; + break; + case 1: + strValOut += "Y"; + break; + case 2: + strValOut += "Cb"; + break; + case 3: + strValOut += "Cr"; + break; + case 4: + strValOut += "R"; + break; + case 5: + strValOut += "G"; + break; + case 6: + strValOut += "B"; + break; + default: + strValOut += "?"; + break; + } + } + strValOut += "]"; + + } + else if((strIfdTag == "XPTitle") || + (strIfdTag == "XPComment") || (strIfdTag == "XPAuthor") || (strIfdTag == "XPKeywords") || (strIfdTag == "XPSubject")) + { + strValOut = "\""; + QString strVal; + + strVal = m_pWBuf->BufReadUniStr2(nPosExifStart + nIfdOffset, nIfdNumComps); + strValOut += strVal; + strValOut += "\""; + + } + else if(strIfdTag == "UserComment") + { + // Character code + uint32_t anCharCode[8]; + + for(uint32_t vInd = 0; vInd < 8; vInd++) + { + anCharCode[vInd] = Buf(nPosExifStart + nIfdOffset + 0 + vInd); + } + // Actual string + strValOut = "\""; + bool bDone = false; + + uint8_t cTmp; + + for(uint32_t vInd = 0; (vInd < nIfdNumComps - 8) && (!bDone); vInd++) + { + cTmp = Buf(nPosExifStart + nIfdOffset + 8 + vInd); + if(cTmp == 0) + { + bDone = true; + } + else + { + strValOut += cTmp; + } + } + strValOut += "\""; + } + else if(strIfdTag == "MeteringMode") + { + switch (anValues[0]) + { + case 0: + strValOut = "Unknown"; + break; + case 1: + strValOut = "Average"; + break; + case 2: + strValOut = "CenterWeightedAverage"; + break; + case 3: + strValOut = "Spot"; + break; + case 4: + strValOut = "MultiSpot"; + break; + case 5: + strValOut = "Pattern"; + break; + case 6: + strValOut = "Partial"; + break; + case 255: + strValOut = "Other"; + break; + } + } + else if(strIfdTag == "ExposureProgram") + { + switch (anValues[0]) + { + case 0: + strValOut = "Not defined"; + break; + case 1: + strValOut = "Manual"; + break; + case 2: + strValOut = "Normal program"; + break; + case 3: + strValOut = "Aperture priority"; + break; + case 4: + strValOut = "Shutter priority"; + break; + case 5: + strValOut = "Creative program (depth of field)"; + break; + case 6: + strValOut = "Action program (fast shutter speed)"; + break; + case 7: + strValOut = "Portrait mode"; + break; + case 8: + strValOut = "Landscape mode"; + break; + } + } + else if(strIfdTag == "Flash") + { + switch (anValues[0] & 1) + { + case 0: + strValOut = "Flash did not fire"; + break; + case 1: + strValOut = "Flash fired"; + break; + } + // TODO: Add other bitfields? + } + else if(strIfdTag == "SensingMethod") + { + switch (anValues[0]) + { + case 1: + strValOut = "Not defined"; + break; + case 2: + strValOut = "One-chip color area sensor"; + break; + case 3: + strValOut = "Two-chip color area sensor"; + break; + case 4: + strValOut = "Three-chip color area sensor"; + break; + case 5: + strValOut = "Color sequential area sensor"; + break; + case 7: + strValOut = "Trilinear sensor"; + break; + case 8: + strValOut = "Color sequential linear sensor"; + break; + } + } + else if(strIfdTag == "FileSource") + { + switch (anValues[0]) + { + case 3: + strValOut = "DSC"; + break; + } + } + else if(strIfdTag == "CustomRendered") + { + switch (anValues[0]) + { + case 0: + strValOut = "Normal process"; + break; + case 1: + strValOut = "Custom process"; + break; + } + } + else if(strIfdTag == "ExposureMode") + { + switch (anValues[0]) + { + case 0: + strValOut = "Auto exposure"; + break; + case 1: + strValOut = "Manual exposure"; + break; + case 2: + strValOut = "Auto bracket"; + break; + } + } + else if(strIfdTag == "WhiteBalance") + { + switch (anValues[0]) + { + case 0: + strValOut = "Auto white balance"; + break; + case 1: + strValOut = "Manual white balance"; + break; + } + } + else if(strIfdTag == "SceneCaptureType") + { + switch (anValues[0]) + { + case 0: + strValOut = "Standard"; + break; + case 1: + strValOut = "Landscape"; + break; + case 2: + strValOut = "Portrait"; + break; + case 3: + strValOut = "Night scene"; + break; + } + } + else if(strIfdTag == "SceneType") + { + switch (anValues[0]) + { + case 1: + strValOut = "A directly photographed image"; + break; + } + } + else if(strIfdTag == "LightSource") + { + switch (anValues[0]) + { + case 0: + strValOut = "unknown"; + break; + case 1: + strValOut = "Daylight"; + break; + case 2: + strValOut = "Fluorescent"; + break; + case 3: + strValOut = "Tungsten (incandescent light)"; + break; + case 4: + strValOut = "Flash"; + break; + case 9: + strValOut = "Fine weather"; + break; + case 10: + strValOut = "Cloudy weather"; + break; + case 11: + strValOut = "Shade"; + break; + case 12: + strValOut = "Daylight fluorescent (D 5700 � 7100K)"; + break; + case 13: + strValOut = "Day white fluorescent (N 4600 � 5400K)"; + break; + case 14: + strValOut = "Cool white fluorescent (W 3900 � 4500K)"; + break; + case 15: + strValOut = "White fluorescent (WW 3200 � 3700K)"; + break; + case 17: + strValOut = "Standard light A"; + break; + case 18: + strValOut = "Standard light B"; + break; + case 19: + strValOut = "Standard light C"; + break; + case 20: + strValOut = "D55"; + break; + case 21: + strValOut = "D65"; + break; + case 22: + strValOut = "D75"; + break; + case 23: + strValOut = "D50"; + break; + case 24: + strValOut = "ISO studio tungsten"; + break; + case 255: + strValOut = "other light source"; + break; + } + } + else if(strIfdTag == "SubjectArea") + { + switch (nIfdNumComps) + { + case 2: + // coords + strValOut = QString("Coords: Center=[%1,%2]").arg(anValues[0]).arg(anValues[1]); + break; + case 3: + // circle + strValOut = QString("Coords (Circle): Center=[%1,%2] Diameter=%3").arg(anValues[0]).arg(anValues[1]).arg(anValues[2]); + break; + case 4: + // rectangle + strValOut = + QString("Coords (Rect): Center=[%1,%2] Width=%3 Height=%4").arg(anValues[0]).arg(anValues[1]).arg(anValues[2]). + arg(anValues[3]); + break; + default: + // Leave default decode, unexpected value + break; + } + } + + if(strIfdTag == "CFAPattern") + { + uint32_t nHorzRepeat, nVertRepeat; + + uint32_t anCfaVal[16][16]; + + uint32_t nInd = 0; + + uint32_t nVal; + + QString strLine, strCol; + + nHorzRepeat = anValues[nInd + 0] * 256 + anValues[nInd + 1]; + nVertRepeat = anValues[nInd + 2] * 256 + anValues[nInd + 3]; + nInd += 4; + if((nHorzRepeat < 16) && (nVertRepeat < 16)) + { + bExtraDecode = true; + strTmp = QString(" [%1] =").arg(strIfdTag, -36); + m_pLog->AddLine(strTmp); + for(uint32_t nY = 0; nY < nVertRepeat; nY++) + { + strLine = QString(" %1 = [ ").arg("", -36); + for(uint32_t nX = 0; nX < nHorzRepeat; nX++) + { + if(nInd < MAX_anValues) + { + nVal = anValues[nInd++]; + anCfaVal[nY][nX] = nVal; + switch (nVal) + { + case 0: + strCol = "Red"; + break; + case 1: + strCol = "Grn"; + break; + case 2: + strCol = "Blu"; + break; + case 3: + strCol = "Cya"; + break; + case 4: + strCol = "Mgn"; + break; + case 5: + strCol = "Yel"; + break; + case 6: + strCol = "Wht"; + break; + default: + strCol = QString("x%1").arg(nVal, 2, 16, QChar('0')); + break; + } + + strLine.append(QString("%1 ").arg(strCol)); + } + } + + strLine.append("]"); + m_pLog->AddLine(strLine); + } + } + + } + + if((strIfd == "InteropIFD") && (strIfdTag == "InteroperabilityVersion")) + { + // Assume only one + strValOut = QString("%1%2.%3%4") + .arg(static_cast(anValues[0])) + .arg(static_cast(anValues[1])) + .arg(static_cast(anValues[2])) + .arg(static_cast(anValues[3])); + } + + // ========================================================================== + + // ---------------------------------------- + // Handle certain MakerNotes + // For Canon, we have a special parser routine to handle these + // ---------------------------------------- + if(strIfd == "MakerIFD") + { + + if((m_strImgExifMake == "Canon") && (nIfdFormat == 3) && (nIfdNumComps > 4)) + { + // Print summary line now, before sub details + // Disable later summary line + bExtraDecode = true; + if((!m_pAppConfig->bExifHideUnknown) || (!nIfdTagUnknown)) + { + strTmp = QString(" [%1]").arg(strIfdTag, -36); + m_pLog->AddLine(strTmp); + + // Assume it is a maker field with subentries! + + for(uint32_t ind = 0; ind < nIfdNumComps; ind++) + { + // Limit the number of entries (in case there was a decode error + // or simply too many to report) + if(ind < MAX_anValues) + { + strValOut = QString("#%1=%2 ").arg(ind).arg(anValues[ind]); + strRetVal = LookupMakerCanonTag(nIfdTagVal, ind, anValues[ind]); + strMaker = strRetVal.strTag; + strValTmp = QString(" [%1] = %2").arg(strMaker, -34).arg(strRetVal.strVal); + if((!m_pAppConfig->bExifHideUnknown) || (!strRetVal.bUnknown)) + { + m_pLog->AddLine(strValTmp); + } + } + else if(ind == MAX_anValues) + { + m_pLog->AddLine(" [... etc ...]"); + } + else + { + // Don't print! + } + } + } + + strValOut = "..."; + } + + // For Nikon & Sigma, we simply support the quality field + if((strIfdTag == "Nikon1.Quality") || + (strIfdTag == "Nikon2.Quality") || (strIfdTag == "Nikon3.Quality") || (strIfdTag == "Sigma.Quality")) + { + m_strImgQualExif = strValOut; + + // Collect extra details (for later DB submission) + strTmp = ""; + strTmp = QString("[%1]:[%1],").arg(strIfdTag).arg(strValOut); + m_strImgExtras += strTmp; + } + + // Collect extra details (for later DB submission) + if(strIfdTag == "Canon.ImageType") + { + strTmp = ""; + strTmp = QString("[%1]:[%1],").arg(strIfdTag).arg(strValOut); + m_strImgExtras += strTmp; + } + } + + // ---------------------------------------- + + // Now extract some of the important offsets / pointers + if((strIfd == "IFD0") && (strIfdTag == "ExifOffset")) + { + // EXIF SubIFD - Pointer + m_nImgExifSubIfdPtr = nIfdOffset; + strValOut = QString("@ 0x%1").arg(nIfdOffset, 4, 16, QChar('0')); + } + + if((strIfd == "IFD0") && (strIfdTag == "GPSOffset")) + { + // GPS SubIFD - Pointer + m_nImgExifGpsIfdPtr = nIfdOffset; + strValOut = QString("@ 0x%1").arg(nIfdOffset, 4, 16, QChar('0')); + } + + // TODO: Add Interoperability IFD (0xA005)? + if((strIfd == "SubIFD") && (strIfdTag == "ExifInteroperabilityOffset")) + { + m_nImgExifInteropIfdPtr = nIfdOffset; + strValOut = QString("@ 0x%1").arg(nIfdOffset, 4, 16, QChar('0')); + } + + // Extract software field + if((strIfd == "IFD0") && (strIfdTag == "Software")) + { + m_strSoftware = strValOut; + } + + // ------------------------- + // IFD0 - ExifMake + // ------------------------- + if((strIfd == "IFD0") && (strIfdTag == "Make")) + { + m_strImgExifMake = strValOut.trimmed(); + + } + + // ------------------------- + // IFD0 - ExifModel + // ------------------------- + if((strIfd == "IFD0") && (strIfdTag == "Model")) + { + m_strImgExifModel = strValOut.trimmed(); + } + + if((strIfd == "SubIFD") && (strIfdTag == "MakerNote")) + { + // Maker IFD - Pointer + m_nImgExifMakerPtr = nIfdOffset; + strValOut = QString("@ 0x%1").arg(nIfdOffset, 4, 16, QChar('0')); + } + + // ------------------------- + // IFD1 - Embedded Thumbnail + // ------------------------- + if((strIfd == "IFD1") && (strIfdTag == "Compression")) + { + // Embedded thumbnail, compression format + m_nImgExifThumbComp = ReadSwap4(m_nPos); + } + if((strIfd == "IFD1") && (strIfdTag == "JpegIFOffset")) + { + // Embedded thumbnail, offset + m_nImgExifThumbOffset = nIfdOffset + nPosExifStart; + strValOut = QString("@ +0x%1 = @ 0x%2") + .arg(nIfdOffset, 4, 16, QChar('0')) + .arg(m_nImgExifThumbOffset, 4, 16, QChar('0')); + } + if((strIfd == "IFD1") && (strIfdTag == "JpegIFByteCount")) + { + // Embedded thumbnail, length + m_nImgExifThumbLen = ReadSwap4(m_nPos); + } + + // ========================================================================== + // Determine MakerNote support + // ========================================================================== + + if(m_strImgExifMake != "") + { + // 1) Identify the supported MakerNotes + // 2) Remap variations of the Maker field (e.g. Nikon) + // as some manufacturers have been inconsistent in their + // use of the Make field + + m_bImgExifMakeSupported = false; + if(m_strImgExifMake == "Canon") + { + m_bImgExifMakeSupported = true; + } + else if(m_strImgExifMake == "PENTAX Corporation") + { + m_strImgExifMake = "PENTAX"; + } + else if(m_strImgExifMake == "NIKON CORPORATION") + { + m_strImgExifMake = "NIKON"; + m_bImgExifMakeSupported = true; + } + else if(m_strImgExifMake == "NIKON") + { + m_strImgExifMake = "NIKON"; + m_bImgExifMakeSupported = true; + } + else if(m_strImgExifMake == "SIGMA") + { + m_bImgExifMakeSupported = true; + } + else if(m_strImgExifMake == "SONY") + { + m_bImgExifMakeSupported = true; + } + else if(m_strImgExifMake == "FUJIFILM") + { + // TODO: + // FUJIFILM Maker notes apparently use + // big endian format even though main section uses little. + // Need to switch if in maker section for FUJI + // For now, disable support + m_bImgExifMakeSupported = false; + } + } + + // Now advance the m_nPos ptr as we have finished with valoffset + m_nPos += 4; + + // ========================================================================== + // SUMMARY REPORT + // ========================================================================== + + // If we haven't already output a detailed decode of this field + // then we can output the generic representation here + if(!bExtraDecode) + { + // Provide option to skip unknown fields + if((!m_pAppConfig->bExifHideUnknown) || (!nIfdTagUnknown)) + { + + // If the tag is an ASCII string, we want to wrap with quote marks + if(nIfdFormat == 2) + { + strTmp = QString(" [%1] = \"%2\"").arg(strIfdTag, -36).arg(strValOut); + } + else + { + strTmp = QString(" [%1] = %2").arg(strIfdTag, -36).arg(strValOut); + } + m_pLog->AddLine(strTmp); + + } + } + + DbgAddLine(""); + + } // for nIfdEntryInd + + // =========== EXIF IFD (End) =========== + // - Defined in Exif 2.2 Standard (JEITA CP-3451) section 4.6.2 + // - Is completed by 4-byte offset to next IFD, which is + // read in next iteration. + + m_pLog->Enable(); + return 0; +} + +// Handle APP13 marker +// This includes: +// - Photoshop "Save As" and "Save for Web" quality settings +// - IPTC entries +// PRE: +// - m_nPos +// POST: +// - m_nImgQualPhotoshopSa +uint32_t CjfifDecode::DecodeApp13Ps() +{ + // Photoshop APP13 marker definition doesn't appear to have a + // well-defined length, so I will read until I encounter a + // non-"8BIM" entry, then we reset the position counter + // and move on to the next marker. + // FIXME: This does not appear to be very robust + + QString strTmp; + QString strBimName; + + bool bDone = false; + + //uint32_t nVal = 0x8000; + + QString strVal; + QString strByte; + QString strBimSig; + + // Reset PsDec decoder state + m_pPsDec->Reset(); + + while(!bDone) + { + // FIXME: Need to check for actual marker section extent, not + // just the lack of an 8BIM signature as the terminator! + + // Check the signature but don't advance the file pointer + strBimSig = m_pWBuf->BufReadStrn(m_nPos, 4); + + // Check for signature "8BIM" + if(strBimSig == "8BIM") + { + m_pPsDec->PhotoshopParseImageResourceBlock(m_nPos, 3); + } + else + { + // Not 8BIM? + bDone = true; + } + } + + // Now that we've finished with the PsDec decoder we can fetch + // some of the parser state + // TODO: Migrate into accessor + m_nImgQualPhotoshopSa = m_pPsDec->m_nQualitySaveAs; + m_nImgQualPhotoshopSfw = m_pPsDec->m_nQualitySaveForWeb; + m_bPsd = m_pPsDec->m_bPsd; + + return 0; +} + +// Start decoding a single ICC header segment @ nPos +uint32_t CjfifDecode::DecodeIccHeader(uint32_t nPos) +{ + QString strTmp, strTmp1; + + // Profile header + uint32_t nProfSz; + uint32_t nPrefCmmType; + uint32_t nProfVer; + uint32_t nProfDevClass; + uint32_t nDataColorSpace; + uint32_t nPcs; + uint32_t anDateTimeCreated[3]; + uint32_t nProfFileSig; + uint32_t nPrimPlatSig; + uint32_t nProfFlags; + uint32_t nDevManuf; + uint32_t nDevModel; + uint32_t anDevAttrib[2]; + uint32_t nRenderIntent; + uint32_t anIllumPcsXyz[3]; + uint32_t nProfCreatorSig; + uint32_t anProfId[4]; + uint32_t anRsvd[7]; + + // Read in all of the ICC header bytes + nProfSz = ReadBe4(nPos); + nPos += 4; + nPrefCmmType = ReadBe4(nPos); + nPos += 4; + nProfVer = ReadBe4(nPos); + nPos += 4; + nProfDevClass = ReadBe4(nPos); + nPos += 4; + nDataColorSpace = ReadBe4(nPos); + nPos += 4; + nPcs = ReadBe4(nPos); + nPos += 4; + anDateTimeCreated[2] = ReadBe4(nPos); + nPos += 4; + anDateTimeCreated[1] = ReadBe4(nPos); + nPos += 4; + anDateTimeCreated[0] = ReadBe4(nPos); + nPos += 4; + nProfFileSig = ReadBe4(nPos); + nPos += 4; + nPrimPlatSig = ReadBe4(nPos); + nPos += 4; + nProfFlags = ReadBe4(nPos); + nPos += 4; + nDevManuf = ReadBe4(nPos); + nPos += 4; + nDevModel = ReadBe4(nPos); + nPos += 4; + anDevAttrib[1] = ReadBe4(nPos); + nPos += 4; + anDevAttrib[0] = ReadBe4(nPos); + nPos += 4; + nRenderIntent = ReadBe4(nPos); + nPos += 4; + anIllumPcsXyz[2] = ReadBe4(nPos); + nPos += 4; + anIllumPcsXyz[1] = ReadBe4(nPos); + nPos += 4; + anIllumPcsXyz[0] = ReadBe4(nPos); + nPos += 4; + nProfCreatorSig = ReadBe4(nPos); + nPos += 4; + anProfId[3] = ReadBe4(nPos); + nPos += 4; + anProfId[2] = ReadBe4(nPos); + nPos += 4; + anProfId[1] = ReadBe4(nPos); + nPos += 4; + anProfId[0] = ReadBe4(nPos); + nPos += 4; + anRsvd[6] = ReadBe4(nPos); + nPos += 4; + anRsvd[5] = ReadBe4(nPos); + nPos += 4; + anRsvd[4] = ReadBe4(nPos); + nPos += 4; + anRsvd[3] = ReadBe4(nPos); + nPos += 4; + anRsvd[2] = ReadBe4(nPos); + nPos += 4; + anRsvd[1] = ReadBe4(nPos); + nPos += 4; + anRsvd[0] = ReadBe4(nPos); + nPos += 4; + + // Now output the formatted version of the above data structures + strTmp = QString(" %1 : %2 bytes").arg("Profile Size", -33).arg(nProfSz); + m_pLog->AddLine(strTmp); + + strTmp = QString(" %1 : %2").arg("Preferred CMM Type", -33).arg(Uint2Chars(nPrefCmmType)); + m_pLog->AddLine(strTmp); + + strTmp = + QString(" %1 : %2.%3.%4.%5 (0x%6)") + .arg("Profile Version",-33) + .arg((nProfVer & 0xF0000000) >> 28) + .arg((nProfVer & 0x0F000000) >> 24) + .arg((nProfVer & 0x00F00000) >> 20) + .arg((nProfVer & 0x000F0000) >> 16) + .arg(nProfVer, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + switch (nProfDevClass) + { + case 'scnr': + strTmp1 = "Input Device profile"; + break; + case 'mntr': + strTmp1 = "Display Device profile"; + break; + case 'prtr': + strTmp1 = "Output Device profile"; + break; + case 'link': + strTmp1 = "DeviceLink Device profile"; + break; + case 'spac': + strTmp1 = "ColorSpace Conversion profile"; + break; + case 'abst': + strTmp1 = "Abstract profile"; + break; + case 'nmcl': + strTmp1 = "Named colour profile"; + break; + default: + strTmp1 = QString("? (0x%1)").arg(nProfDevClass, 8, 16, QChar('0')); + break; + } + strTmp = QString(" %1 : %2 (%3)").arg("Profile Device/Class", -33).arg(strTmp1).arg(Uint2Chars(nProfDevClass)); + m_pLog->AddLine(strTmp); + + switch (nDataColorSpace) + { + case 'XYZ ': + strTmp1 = "XYZData"; + break; + case 'Lab ': + strTmp1 = "labData"; + break; + case 'Luv ': + strTmp1 = "lubData"; + break; + case 'YCbr': + strTmp1 = "YCbCrData"; + break; + case 'Yxy ': + strTmp1 = "YxyData"; + break; + case 'RGB ': + strTmp1 = "rgbData"; + break; + case 'GRAY': + strTmp1 = "grayData"; + break; + case 'HSV ': + strTmp1 = "hsvData"; + break; + case 'HLS ': + strTmp1 = "hlsData"; + break; + case 'CMYK': + strTmp1 = "cmykData"; + break; + case 'CMY ': + strTmp1 = "cmyData"; + break; + case '2CLR': + strTmp1 = "2colourData"; + break; + case '3CLR': + strTmp1 = "3colourData"; + break; + case '4CLR': + strTmp1 = "4colourData"; + break; + case '5CLR': + strTmp1 = "5colourData"; + break; + case '6CLR': + strTmp1 = "6colourData"; + break; + case '7CLR': + strTmp1 = "7colourData"; + break; + case '8CLR': + strTmp1 = "8colourData"; + break; + case '9CLR': + strTmp1 = "9colourData"; + break; + case 'ACLR': + strTmp1 = "10colourData"; + break; + case 'BCLR': + strTmp1 = "11colourData"; + break; + case 'CCLR': + strTmp1 = "12colourData"; + break; + case 'DCLR': + strTmp1 = "13colourData"; + break; + case 'ECLR': + strTmp1 = "14colourData"; + break; + case 'FCLR': + strTmp1 = "15colourData"; + break; + default: + strTmp1 = QString("? (0x%1)").arg(nDataColorSpace, 8, 16, QChar('0')); + break; + } + strTmp = QString(" %1 : %2 (%3)").arg("Data Colour Space", -33).arg(strTmp1).arg(Uint2Chars(nDataColorSpace)); + m_pLog->AddLine(strTmp); + + strTmp = QString(" %1 : %2").arg("Profile connection space (PCS)", -33).arg(Uint2Chars(nPcs)); + m_pLog->AddLine(strTmp); + + strTmp = QString(" %1 : %2").arg("Profile creation date", -33).arg(DecodeIccDateTime(anDateTimeCreated)); + m_pLog->AddLine(strTmp); + + strTmp = QString(" %1 : %2").arg("Profile file signature", -33).arg(Uint2Chars(nProfFileSig)); + m_pLog->AddLine(strTmp); + + switch (nPrimPlatSig) + { + case 'APPL': + strTmp1 = "Apple Computer, Inc."; + break; + case 'MSFT': + strTmp1 = "Microsoft Corporation"; + break; + case 'SGI ': + strTmp1 = "Silicon Graphics, Inc."; + break; + case 'SUNW': + strTmp1 = "Sun Microsystems, Inc."; + break; + default: + strTmp1 = QString("? (0x%1)").arg(nPrimPlatSig, 8, 16, QChar('0')); + break; + } + strTmp = QString(" %1 : %2 (%3)").arg("Primary platform", -33).arg(strTmp1).arg(Uint2Chars(nPrimPlatSig)); + m_pLog->AddLine(strTmp); + + strTmp = QString(" %1 : 0x%2").arg("Profile flags", -33).arg(nProfFlags, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + strTmp1 = (TestBit(nProfFlags, 0)) ? "Embedded profile" : "Profile not embedded"; + strTmp = QString(" %1 > %2").arg("Profile flags", -35).arg(strTmp1); + m_pLog->AddLine(strTmp); + strTmp1 = + (TestBit(nProfFlags, 1)) ? "Profile can be used independently of embedded" : + "Profile can't be used independently of embedded"; + strTmp = QString(" %1 > %2").arg("Profile flags", -35).arg(strTmp1); + m_pLog->AddLine(strTmp); + + strTmp = QString(" %1 : %2").arg("Device Manufacturer", -33).arg(Uint2Chars(nDevManuf)); + m_pLog->AddLine(strTmp); + + strTmp = QString(" %1 : %2").arg("Device Model", -33).arg(Uint2Chars(nDevModel)); + m_pLog->AddLine(strTmp); + + strTmp = QString(" %1 : 0x%2_%3") + .arg("Device attributes", -33) + .arg(anDevAttrib[1], 8, 16, QChar('0')) + .arg(anDevAttrib[0], 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + strTmp1 = (TestBit(anDevAttrib[0], 0)) ? "Transparency" : "Reflective"; + strTmp = QString(" %1 > %2") + .arg("Device attributes", -35) + .arg(strTmp1); + m_pLog->AddLine(strTmp); + strTmp1 = (TestBit(anDevAttrib[0], 1)) ? "Matte" : "Glossy"; + strTmp = QString(" %1 > %2") + .arg("Device attributes", -35) + .arg(strTmp1); + m_pLog->AddLine(strTmp); + strTmp1 = (TestBit(anDevAttrib[0], 2)) ? "Media polarity = positive" : "Media polarity = negative"; + strTmp = QString(" %1 > %2") + .arg("Device attributes", -35) + .arg(strTmp1); + m_pLog->AddLine(strTmp); + strTmp1 = (TestBit(anDevAttrib[0], 3)) ? "Colour media" : "Black & white media"; + strTmp = QString(" %1 > %2") + .arg("Device attributes", -35) + .arg(strTmp1); + m_pLog->AddLine(strTmp); + + switch (nRenderIntent) + { + case 0x00000000: + strTmp1 = "Perceptual"; + break; + case 0x00000001: + strTmp1 = "Media-Relative Colorimetric"; + break; + case 0x00000002: + strTmp1 = "Saturation"; + break; + case 0x00000003: + strTmp1 = "ICC-Absolute Colorimetric"; + break; + default: + strTmp1 = QString("0x%1").arg(nRenderIntent, 8, 16, QChar('0')); + break; + } + strTmp = QString(" %1 : %2").arg("Rendering intent", -33).arg(strTmp1); + m_pLog->AddLine(strTmp); + + // PCS illuminant + + strTmp = QString(" %1 : %2").arg("Profile creator", -33).arg(Uint2Chars(nProfCreatorSig)); + m_pLog->AddLine(strTmp); + + strTmp = + QString(" %1 : 0x%2_%3_%4_%5") + .arg("Profile ID", -33) + .arg(anProfId[3], 8, 16, QChar('0')) + .arg(anProfId[2], 8, 16, QChar('0')) + .arg(anProfId[1], 8, 16, QChar('0')) + .arg(anProfId[0], 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + return 0; +} + +// Provide special output formatter for ICC Date/Time +// NOTE: It appears that the nParts had to be decoded in the +// reverse order from what I had expected, so one should +// confirm that the byte order / endianness is appropriate. +QString CjfifDecode::DecodeIccDateTime(uint32_t anVal[]) +{ + QString strDate; + + uint16_t anParts[6]; + + anParts[0] = (anVal[2] & 0xFFFF0000) >> 16; // Year + anParts[1] = (anVal[2] & 0x0000FFFF); // Mon + anParts[2] = (anVal[1] & 0xFFFF0000) >> 16; // Day + anParts[3] = (anVal[1] & 0x0000FFFF); // Hour + anParts[4] = (anVal[0] & 0xFFFF0000) >> 16; // Min + anParts[5] = (anVal[0] & 0x0000FFFF); // Sec + strDate = + QString("%1-%2-%3 %4:%5:%6") + .arg(anParts[0], 4, 10, QChar('0')) + .arg(anParts[1], 2, 10, QChar('0')) + .arg(anParts[2], 2, 10, QChar('0')) + .arg(anParts[3], 2, 10, QChar('0')) + .arg(anParts[4], 2, 10, QChar('0')) + .arg(anParts[5], 2, 10, QChar('0')); + return strDate; +} + +// Parser for APP2 ICC profile marker +uint32_t CjfifDecode::DecodeApp2IccProfile(uint32_t nLen) +{ + QString strTmp; + + uint32_t nMarkerSeqNum; // Byte + + uint32_t nNumMarkers; // Byte + + uint32_t nPayloadLen; // Len of this ICC marker payload + + uint32_t nMarkerPosStart; + + nMarkerSeqNum = Buf(m_nPos++); + nNumMarkers = Buf(m_nPos++); + nPayloadLen = nLen - 2 - 12 - 2; // TODO: check? + + strTmp = QString(" Marker Number = %1 of %2").arg(nMarkerSeqNum).arg(nNumMarkers); + m_pLog->AddLine(strTmp); + + if(nMarkerSeqNum == 1) + { + nMarkerPosStart = m_nPos; + DecodeIccHeader(nMarkerPosStart); + } + else + { + m_pLog->AddLineWarn(" Only support decode of 1st ICC Marker"); + } + + return 0; +} + +// Parser for APP2 FlashPix marker +uint32_t CjfifDecode::DecodeApp2Flashpix() +{ + + QString strTmp; + + uint32_t nFpxVer; + + uint32_t nFpxSegType; + + uint32_t nFpxInteropCnt; + + uint32_t nFpxEntitySz; + + uint32_t nFpxDefault; + + bool bFpxStorage; + + QString strFpxStorageClsStr; + + uint32_t nFpxStIndexCont; + + uint32_t nFpxStOffset; + + uint32_t nFpxStWByteOrder; + + uint32_t nFpxStWFormat; + + QString strFpxStClsidStr; + + uint32_t nFpxStDwOsVer; + + uint32_t nFpxStRsvd; + + QString streamStr; + + nFpxVer = Buf(m_nPos++); + nFpxSegType = Buf(m_nPos++); + + // FlashPix segments: Contents List or Stream Data + + if(nFpxSegType == 1) + { + // Contents List + strTmp = QString(" Segment: CONTENTS LIST"); + m_pLog->AddLine(strTmp); + + nFpxInteropCnt = (Buf(m_nPos++) << 8) + Buf(m_nPos++); + strTmp = QString(" Interoperability Count = %1").arg(nFpxInteropCnt); + m_pLog->AddLine(strTmp); + + for(uint32_t ind = 0; ind < nFpxInteropCnt; ind++) + { + strTmp = QString(" Entity Index #%1").arg(ind); + m_pLog->AddLine(strTmp); + nFpxEntitySz = (Buf(m_nPos++) << 24) + (Buf(m_nPos++) << 16) + (Buf(m_nPos++) << 8) + Buf(m_nPos++); + + // If the "entity size" field is 0xFFFFFFFF, then it should be treated as + // a "storage". It looks like we should probably be using this to determine + // that we have a "storage" + bFpxStorage = false; + if(nFpxEntitySz == 0xFFFFFFFF) + { + bFpxStorage = true; + } + + if(!bFpxStorage) + { + strTmp = QString(" Entity Size = %1").arg(nFpxEntitySz); + m_pLog->AddLine(strTmp); + } + else + { + strTmp = " Entity is Storage"; + m_pLog->AddLine(strTmp); + } + + nFpxDefault = Buf(m_nPos++); + + // BUG: #1112 + //streamStr = m_pWBuf->BufReadUniStr(m_nPos); + streamStr = m_pWBuf->BufReadUniStr2(m_nPos, MAX_BUF_READ_STR); + m_nPos += 2 * ((uint32_t) streamStr.length() + 1); // 2x because unicode + + strTmp = QString(" Stream Name = [%1]").arg(streamStr); + m_pLog->AddLine(strTmp); + + // In the case of "storage", we decode the next 16 bytes as the class + if(bFpxStorage) + { + + // FIXME: + // NOTE: Very strange reordering required here. Doesn't seem consistent + // This means that other fields are probably wrong as well (endian) + strFpxStorageClsStr = + QString("%1%2%3%4-%5%6-%7%8-%9%10-%11%12%13%14%15%16").arg(Buf(m_nPos + 3), 2, 16, QChar('0')).arg(Buf(m_nPos + 2), 2, + 16, + QChar('0')). + arg(Buf(m_nPos + 1), 2, 16, QChar('0')).arg(Buf(m_nPos + 0), 2, 16, QChar('0')).arg(Buf(m_nPos + 5), 2, 16, + QChar('0')).arg(Buf(m_nPos + 4), 2, + 16, + QChar('0')). + arg(Buf(m_nPos + 7), 2, 16, QChar('0')).arg(Buf(m_nPos + 6), 2, 16, QChar('0')).arg(Buf(m_nPos + 8), 2, 16, + QChar('0')).arg(Buf(m_nPos + 9), 2, + 16, + QChar('0')). + arg(Buf(m_nPos + 10), 2, 16, QChar('0')).arg(Buf(m_nPos + 11), 2, 16, QChar('0')).arg(Buf(m_nPos + 12), 2, 16, + QChar('0')).arg(Buf(m_nPos + 13), + 2, 16, + QChar('0')). + arg(Buf(m_nPos + 14), 2, 16, QChar('0')).arg(Buf(m_nPos + 15), 2, 16, QChar('0')); + m_nPos += 16; + strTmp = QString(" Storage Class = [%1]").arg(strFpxStorageClsStr); + m_pLog->AddLine(strTmp); + } + } + + return 0; + + } + else if(nFpxSegType == 2) + { + // Stream Data + strTmp = " Segment: STREAM DATA"; + m_pLog->AddLine(strTmp); + + nFpxStIndexCont = (Buf(m_nPos++) << 8) + Buf(m_nPos++); + strTmp = QString(" Index in Contents List = %1").arg(nFpxStIndexCont); + m_pLog->AddLine(strTmp); + + nFpxStOffset = (Buf(m_nPos++) << 24) + (Buf(m_nPos++) << 16) + (Buf(m_nPos++) << 8) + Buf(m_nPos++); + strTmp = QString(" Offset in stream = %1 (0x%2)").arg(nFpxStOffset).arg(nFpxStOffset, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + // Now decode the Property Set Header + + // NOTE: Should only decode this if we are doing first part of stream + // TODO: How do we know this? First reference to index #? + + nFpxStWByteOrder = (Buf(m_nPos++) << 8) + Buf(m_nPos++); + nFpxStWFormat = (Buf(m_nPos++) << 8) + Buf(m_nPos++); + nFpxStDwOsVer = (Buf(m_nPos++) << 24) + (Buf(m_nPos++) << 16) + (Buf(m_nPos++) << 8) + Buf(m_nPos++); + + // FIXME: + // NOTE: Very strange reordering required here. Doesn't seem consistent! + // This means that other fields are probably wrong as well (endian) + strFpxStClsidStr = + QString("%1%2%3%4-%5%6-%7%8-%9%10-%11%12%13%14%15%16").arg(Buf(m_nPos + 3), 2, 16, QChar('0')).arg(Buf(m_nPos + 2), 2, 16, + QChar('0')). + arg(Buf(m_nPos + 1), 2, 16, QChar('0')).arg(Buf(m_nPos + 0), 2, 16, QChar('0')).arg(Buf(m_nPos + 5), 2, 16, + QChar('0')).arg(Buf(m_nPos + 4), 2, 16, + QChar('0')). + arg(Buf(m_nPos + 7), 2, 16, QChar('0')).arg(Buf(m_nPos + 6), 2, 16, QChar('0')).arg(Buf(m_nPos + 8), 2, 16, + QChar('0')).arg(Buf(m_nPos + 9), 2, 16, + QChar('0')). + arg(Buf(m_nPos + 10), 2, 16, QChar('0')).arg(Buf(m_nPos + 11), 2, 16, QChar('0')).arg(Buf(m_nPos + 12), 2, 16, + QChar('0')).arg(Buf(m_nPos + 13), 2, + 16, + QChar('0')). + arg(Buf(m_nPos + 14), 2, 16, QChar('0')).arg(Buf(m_nPos + 15), 2, 16, QChar('0')); + m_nPos += 16; + nFpxStRsvd = (Buf(m_nPos++) << 8) + Buf(m_nPos++); + + strTmp = QString(" ByteOrder = 0x%1").arg(nFpxStWByteOrder, 4, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + strTmp = QString(" Format = 0x%1").arg(nFpxStWFormat, 4, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + strTmp = QString(" OSVer = 0x%1").arg(nFpxStDwOsVer, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + strTmp = QString(" clsid = %1").arg(strFpxStClsidStr); + m_pLog->AddLine(strTmp); + + strTmp = QString(" reserved = 0x%1").arg(nFpxStRsvd, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + // .... + + return 2; + + } + else + { + m_pLog->AddLineErr(" Reserved Segment. Stopping."); + return 1; + } +} + +// Decode the DHT marker segment (Huffman Tables) +// In some cases (such as for MotionJPEG), we fake out +// the DHT tables (when bInject=true) with a standard table +// as each JPEG frame in the MJPG does not include the DHT. +// In all other cases (bInject=false), we simply read the +// DHT table from the file buffer via Buf() +// +// ITU-T standard indicates that we can expect up to a +// maximum of 16-bit huffman code bitstrings. +void CjfifDecode::DecodeDHT(bool bInject) +{ + uint32_t nLength; + uint32_t nTmpVal; + + QString strTmp, strFull; + + uint32_t nPosEnd; + uint32_t nPosSaved = 0; + + bool bRet; + + if(bInject) + { + // Redirect Buf() to DHT table in MJPGDHTSeg[] + // ... so change mode that Buf() call uses + m_bBufFakeDHT = true; + + // Preserve the "m_nPos" pointer, at end we undo it + // And we also start at 2 which is just after FFC4 in array + nPosSaved = m_nPos; + m_nPos = 2; + } + + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + nPosEnd = m_nPos + nLength; + m_nPos += 2; + strTmp = QString(" Huffman table length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + uint32_t nDhtClass_Tc; // Range 0..1 + + uint32_t nDhtHuffTblId_Th; // Range 0..3 + + // In various places, added m_bStateAbort check to allow us + // to escape in case we get in excessive number of DHT entries + // See BUG FIX #1003 + + while((!m_bStateAbort) && (nPosEnd > m_nPos)) + { + m_pLog->AddLine(" ----"); + + nTmpVal = Buf(m_nPos++); + nDhtClass_Tc = (nTmpVal & 0xF0) >> 4; // Tc, range 0..1 + nDhtHuffTblId_Th = nTmpVal & 0x0F; // Th, range 0..3 + strTmp = QString(" Destination ID = %1").arg(nDhtHuffTblId_Th); + m_pLog->AddLine(strTmp); + strTmp = QString(" Class = %1 (%2)").arg(nDhtClass_Tc).arg(nDhtClass_Tc ? "AC Table" : "DC / Lossless Table"); + m_pLog->AddLine(strTmp); + + // Add in some error checking to prevent + if(nDhtClass_Tc >= MAX_DHT_CLASS) + { + strTmp = QString("ERROR: Invalid DHT Class (%1). Aborting DHT Load.").arg(nDhtClass_Tc); + m_pLog->AddLineErr(strTmp); + m_nPos = nPosEnd; + //m_bStateAbort = true; // Stop decoding + break; + } + if(nDhtHuffTblId_Th >= MAX_DHT_DEST_ID) + { + strTmp = QString("ERROR: Invalid DHT Dest ID (%1). Aborting DHT Load.").arg(nDhtHuffTblId_Th); + m_pLog->AddLineErr(strTmp); + m_nPos = nPosEnd; + //m_bStateAbort = true; // Stop decoding + break; + } + + // Read in the array of DHT code lengths + for(uint32_t i = 1; i <= MAX_DHT_CODELEN; i++) + { + m_anDhtNumCodesLen_Li[i] = Buf(m_nPos++); // Li, range 0..255 + } + +#define DECODE_DHT_MAX_DHT 256 + + uint32_t anDhtCodeVal[DECODE_DHT_MAX_DHT + 1]; // Should only need max 162 codes + + uint32_t nDhtInd; + + uint32_t nDhtCodesTotal; + + // Clear out the code list + for(nDhtInd = 0; nDhtInd < DECODE_DHT_MAX_DHT; nDhtInd++) + { + anDhtCodeVal[nDhtInd] = 0xFFFF; // Dummy value + } + + // Now read in all of the DHT codes according to the lengths + // read in earlier + nDhtCodesTotal = 0; + nDhtInd = 0; + for(uint32_t nIndLen = 1; ((!m_bStateAbort) && (nIndLen <= MAX_DHT_CODELEN)); nIndLen++) + { + // Keep a total count of the number of DHT codes read + nDhtCodesTotal += m_anDhtNumCodesLen_Li[nIndLen]; + + strFull = QString(" Codes of length %1 bits (%2 total): ") + .arg(nIndLen, 2, 10, QChar('0')) + .arg(m_anDhtNumCodesLen_Li[nIndLen], 3, 10, QChar('0')); + + for(uint32_t nIndCode = 0; ((!m_bStateAbort) && (nIndCode < m_anDhtNumCodesLen_Li[nIndLen])); nIndCode++) + { + // Start a new line for every 16 codes + if((nIndCode != 0) && ((nIndCode % 16) == 0)) + { + strFull = " "; + } + nTmpVal = Buf(m_nPos++); + strTmp = QString("%1 ").arg(nTmpVal, 2, 16, QChar('0')); + strFull += strTmp; + + // Only write 16 codes per line + if((nIndCode % 16) == 15) + { + m_pLog->AddLine(strFull); + strFull = ""; + } + + // Save the huffman code + // Just in case we have more DHT codes than we expect, trap + // the range check here, otherwise we'll have buffer overrun! + if(nDhtInd < DECODE_DHT_MAX_DHT) + { + anDhtCodeVal[nDhtInd++] = nTmpVal; // Vij, range 0..255 + } + else + { + nDhtInd++; + strTmp = QString("Excessive DHT entries (%1)... skipping").arg(nDhtInd); + m_pLog->AddLineErr(strTmp); + if(!m_bStateAbort) + { + DecodeErrCheck(true); + } + } + + } + m_pLog->AddLine(strFull); + } + strTmp = QString(" Total number of codes: %1").arg(nDhtCodesTotal, 3, 10, QChar('0')); + m_pLog->AddLine(strTmp); + + uint32_t nDhtLookupInd = 0; + + // Now print out the actual binary strings! + uint32_t nCodeVal = 0; + + nDhtInd = 0; + if(m_pAppConfig->bOutputDHTexpand) + { + m_pLog->AddLine(""); + m_pLog->AddLine(" Expanded Form of Codes:"); + } + for(uint32_t nBitLen = 1; ((!m_bStateAbort) && (nBitLen <= 16)); nBitLen++) + { + if(m_anDhtNumCodesLen_Li[nBitLen] > 0) + { + if(m_pAppConfig->bOutputDHTexpand) + { + strTmp = QString(" Codes of length %1 bits:").arg(nBitLen, 2, 10, QChar('0')); + m_pLog->AddLine(strTmp); + } + // Codes exist for this bit-length + // Walk through and generate the bitvalues + for(uint32_t bit_ind = 1; ((!m_bStateAbort) && (bit_ind <= m_anDhtNumCodesLen_Li[nBitLen])); bit_ind++) + { + uint32_t nDecVal = nCodeVal; + + uint32_t nBinBit; + + char acBinStr[17] = ""; + + uint32_t nBinStrLen = 0; + + // If the user has enabled output of DHT expanded tables, + // report the bit-string sequences. + if(m_pAppConfig->bOutputDHTexpand) + { + for(uint32_t nBinInd = nBitLen; nBinInd >= 1; nBinInd--) + { + nBinBit = (nDecVal >> (nBinInd - 1)) & 1; + acBinStr[nBinStrLen++] = (nBinBit) ? '1' : '0'; + } + acBinStr[nBinStrLen] = '\0'; + strFull = QString(" %1 = %2").arg(acBinStr).arg(anDhtCodeVal[nDhtInd], 2, 16, QChar('0')); + + // The following are only valid for AC components + // Bug [3442132] + if(nDhtClass_Tc == DHT_CLASS_AC) + { + if(anDhtCodeVal[nDhtInd] == 0x00) + { + strFull += " (EOB)"; + } + if(anDhtCodeVal[nDhtInd] == 0xF0) + { + strFull += " (ZRL)"; + } + } + + strTmp = QString("%1 (Total Len = %2)").arg(strFull, -40).arg(nBitLen + (anDhtCodeVal[nDhtInd] & 0xF), 2); + + m_pLog->AddLine(strTmp); + } + + // Store the lookup value + // Shift left to MSB of 32-bit + uint32_t nTmpMask = m_anMaskLookup[nBitLen]; + + uint32_t nTmpBits = nDecVal << (32 - nBitLen); + + uint32_t nTmpCode = anDhtCodeVal[nDhtInd]; + + bRet = m_pImgDec->SetDhtEntry(nDhtHuffTblId_Th, nDhtClass_Tc, nDhtLookupInd, nBitLen, nTmpBits, nTmpMask, nTmpCode); + + DecodeErrCheck(bRet); + + nDhtLookupInd++; + + // Move to the next code + nCodeVal++; + nDhtInd++; + } + } + // For each loop iteration (on bit length), we shift the code value + nCodeVal <<= 1; + } + + // Now store the dht_lookup_size + uint32_t nTmpSize = nDhtLookupInd; + + bRet = m_pImgDec->SetDhtSize(nDhtHuffTblId_Th, nDhtClass_Tc, nTmpSize); + if(!m_bStateAbort) + { + DecodeErrCheck(bRet); + } + + m_pLog->AddLine(""); + + } + + if(bInject) + { + // Restore position (as if we didn't move) + m_nPos = nPosSaved; + m_bBufFakeDHT = false; + } +} + +// Check return value of previous call. If failed, then ask +// user if they wish to continue decoding. If no, then flag to +// the decoder that we're done (avoids continuous failures) +void CjfifDecode::DecodeErrCheck(bool bRet) +{ + if(!bRet) + { + if(m_pAppConfig->bInteractive) + { + msgBox.setText("Do you want to continue decoding?"); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + + if(msgBox.exec() == QMessageBox::No) + { + m_bStateAbort = true; + } + } + } +} + +// This routine is called after the expected fields of the marker segment +// have been processed. The file position should line up with the offset +// dictated by the marker length. If a mismatch is detected, report an +// error. +// +// RETURN: +// - True if decode error is fatal (configurable) +// +bool CjfifDecode::ExpectMarkerEnd(uint32_t nMarkerStart, uint32_t nMarkerLen) +{ + QString strTmp; + + uint32_t nMarkerEnd = nMarkerStart + nMarkerLen; + + uint32_t nMarkerExtra = nMarkerEnd - m_nPos; + + if(m_nPos < nMarkerEnd) + { + // The length indicates that there is more data than we processed + strTmp = QString(" WARNING: Marker length longer than expected"); + m_pLog->AddLineWarn(strTmp); + if(!m_pAppConfig->bRelaxedParsing) + { + // Abort + m_pLog->AddLineErr(" Stopping decode"); + m_pLog->AddLineErr(" Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs"); + return false; + } + else + { + // Warn and skip + strTmp = QString(" Skipping remainder [%1 bytes]").arg(nMarkerExtra); + m_pLog->AddLineWarn(strTmp); + m_nPos += nMarkerExtra; + } + } + else if(m_nPos > nMarkerEnd) + { + // The length indicates that there is less data than we processed + strTmp = QString(" WARNING: Marker length shorter than expected"); + m_pLog->AddLineWarn(strTmp); + if(!m_pAppConfig->bRelaxedParsing) + { + // Abort + m_pLog->AddLineErr(" Stopping decode"); + m_pLog->AddLineErr(" Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs"); + return false; + } + else + { + // Warn but no skip + // Note that we can't skip as the length would imply a rollback + // Most resilient solution is probably to assume length was + // wrong and continue from where the marker should have ended. + // For resiliency, attempt two methods to find point to resume: + // 1) Current position + // 2) Actual length defined in marker + if(Buf(m_nPos) == 0xFF) + { + // Using actual data expected seems more promising + m_pLog->AddLineWarn(" Resuming decode"); + } + else if(Buf(nMarkerEnd) == 0xFF) + { + // Using actual length seems more promising + m_nPos = nMarkerEnd; + m_pLog->AddLineWarn(" Rolling back pointer to end indicated by length"); + m_pLog->AddLineWarn(" Resuming decode"); + } + else + { + // No luck. Expect marker failure now + m_pLog->AddLineWarn(" Resuming decode"); + } + } + } + + // If we get here, then we haven't seen a fatal issue + return true; +} + +// Validate an unsigned value to ensure it is in allowable range +// - If the value is outside the range, an error is shown and +// the parsing stops if relaxed parsing is not enabled +// - An optional override value is provided for the resume case +// +// INPUT: +// - nVal Input value (unsigned 32-bit) +// - nMin Minimum allowed value +// - nMax Maximum allowed value +// - strName Name of the field +// - bOverride Should we override the value upon out-of-range? +// - nOverrideVal Value to override if bOverride and out-of-range +// +// PRE: +// - m_pAppConfig +// +// OUTPUT: +// - nVal Output value (including any override) +// +bool CjfifDecode::ValidateValue(uint32_t &nVal, uint32_t nMin, uint32_t nMax, QString strName, bool bOverride, + uint32_t nOverrideVal) +{ + QString strErr; + + if((nVal >= nMin) && (nVal <= nMax)) + { + // Value is within range + return true; + } + else + { + if(nVal < nMin) + { + strErr = QString(" ERROR: %1 value too small (Actual = %2, Expected >= %3)").arg(strName).arg(nVal).arg(nMin); + m_pLog->AddLineErr(strErr); + } + else if(nVal > nMax) + { + strErr = QString(" ERROR: %1 value too large (Actual = %2, Expected <= %3)").arg(strName).arg(nVal).arg(nMax); + m_pLog->AddLineErr(strErr); + } + if(!m_pAppConfig->bRelaxedParsing) + { + // Defined as fatal error + // TODO: Replace with glb_strMsgStopDecode? + m_pLog->AddLineErr(" Stopping decode"); + m_pLog->AddLineErr(" Use [Relaxed Parsing] to continue"); + return false; + } + else + { + // Non-fatal + if(bOverride) + { + // Update value with override + nVal = nOverrideVal; + strErr = QString(" WARNING: Forcing value to [%1]").arg(nOverrideVal); + m_pLog->AddLineWarn(strErr); + m_pLog->AddLineWarn(" Resuming decode"); + } + else + { + // No override + strErr = QString(" Resuming decode"); + m_pLog->AddLineWarn(strErr); + } + return true; + } + } + +} + +// This is the primary JFIF marker parser. It reads the +// marker value at the current file position and launches the +// specific parser routine. This routine exits when +#define DECMARK_OK 0 +#define DECMARK_ERR 1 +#define DECMARK_EOI 2 +uint32_t CjfifDecode::DecodeMarker() +{ + char acIdentifier[MAX_IDENTIFIER]; + + QString strTmp; + + QString strFull; // Used for concatenation + + uint32_t nLength; // General purpose + + uint32_t nTmpVal; + + quint8 nTmpVal1; + + uint16_t nTmpVal2; + + uint32_t nCode; + + uint32_t nPosEnd; + + uint32_t nPosSaved; // General-purpose saved position in file + + uint32_t nPosExifStart; + + uint32_t nRet; // General purpose return value + + bool bRet; + + uint32_t nPosMarkerStart; // Offset for current marker + + uint32_t nColTransform = 0; // Color Transform from APP14 marker + + // For DQT + QString strDqtPrecision = ""; + + QString strDqtZigZagOrder = ""; + + if(Buf(m_nPos) != 0xFF) + { + if(m_nPos == 0) + { + // Don't give error message if we've already alerted them of AVI / PSD + if((!m_bAvi) && (!m_bPsd)) + { + strTmp = "NOTE: File did not start with JPEG marker. Consider using [Tools->Img Search Fwd] to locate embedded JPEG."; + m_pLog->AddLineErr(strTmp); + } + } + else + { + strTmp = + QString("ERROR: Expected marker 0xFF, got 0x%1 @ offset 0x%2. Consider using [Tools->Img Search Fwd/Rev].") + .arg(Buf(m_nPos), 2, 16, QChar('0')) + .arg(m_nPos, 8, 16, QChar('0')); + m_pLog->AddLineErr(strTmp); + } + m_nPos++; + return DECMARK_ERR; + } + m_nPos++; + + // Read the current marker code + nCode = Buf(m_nPos++); + + // Handle Marker Padding + // + // According to Section B.1.1.2: + // "Any marker may optionally be preceded by any number of fill bytes, which are bytes assigned code X�FF�." + // + uint32_t nSkipMarkerPad = 0; + + while(nCode == 0xFF) + { + // Count the pad + nSkipMarkerPad++; + // Read another byte + nCode = Buf(m_nPos++); + } + + // Report out any padding + if(nSkipMarkerPad > 0) + { + strTmp = QString("*** Skipped %1 marker pad bytes ***").arg(nSkipMarkerPad); + m_pLog->AddLineHdr(strTmp); + } + + // Save the current marker offset + nPosMarkerStart = m_nPos; + + AddHeader(nCode); + + switch (nCode) + { + case JFIF_SOI: // SOI + m_bStateSoi = true; + break; + + case JFIF_APP12: + // Photoshop DUCKY (Save For Web) + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); + strTmp = QString(" Length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + nPosSaved = m_nPos; + + m_nPos += 2; // Move past length now that we've used it + + strcpy(acIdentifier, m_pWBuf->BufReadStrn(m_nPos, MAX_IDENTIFIER - 1).toLatin1().data()); + acIdentifier[MAX_IDENTIFIER - 1] = 0; // Null terminate just in case + strTmp = QString(" Identifier = [%1]").arg(acIdentifier); + m_pLog->AddLine(strTmp); + m_nPos += (uint32_t) strlen(acIdentifier) + 1; + + if(strcmp(acIdentifier, "Ducky") != 0) + { + m_pLog->AddLine(" Not Photoshop DUCKY. Skipping remainder."); + } + else // Photoshop + { + // Please see reference on http://cpan.uwinnipeg.ca/htdocs/Image-ExifTool/Image/ExifTool/APP12.pm.html + // A direct indexed approach should be safe + m_nImgQualPhotoshopSfw = Buf(m_nPos + 6); + strTmp = QString(" Photoshop Save For Web Quality = [%1]").arg(m_nImgQualPhotoshopSfw); + m_pLog->AddLine(strTmp); + } + // Restore original position in file to a point + // after the section + m_nPos = nPosSaved + nLength; + break; + + case JFIF_APP14: + // JPEG Adobe tag + + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + strTmp = QString(" Length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + nPosSaved = m_nPos; + + // Some files had very short segment (eg. nLength=2) + if(nLength < 2 + 12) + { + m_pLog->AddLine(" Segment too short for Identifier. Skipping remainder."); + m_nPos = nPosSaved + nLength; + break; + } + + m_nPos += 2; // Move past length now that we've used it + + // TODO: Confirm Adobe flag + m_nPos += 5; + + nTmpVal = Buf(m_nPos + 0) * 256 + Buf(m_nPos + 1); + strTmp = QString(" DCTEncodeVersion = %1").arg(nTmpVal); + m_pLog->AddLine(strTmp); + + nTmpVal = Buf(m_nPos + 2) * 256 + Buf(m_nPos + 3); + strTmp = QString(" APP14Flags0 = %1").arg(nTmpVal); + m_pLog->AddLine(strTmp); + + nTmpVal = Buf(m_nPos + 4) * 256 + Buf(m_nPos + 5); + strTmp = QString(" APP14Flags1 = %1").arg(nTmpVal); + m_pLog->AddLine(strTmp); + + nColTransform = Buf(m_nPos + 6); + + switch (nColTransform) + { + case APP14_COLXFM_UNK_RGB: + strTmp = QString(" ColorTransform = %1 [Unknown (RGB or CMYK)]").arg(nColTransform); + break; + case APP14_COLXFM_YCC: + strTmp = QString(" ColorTransform = %1 [YCbCr]").arg(nColTransform); + break; + case APP14_COLXFM_YCCK: + strTmp = QString(" ColorTransform = %1 [YCCK]").arg(nColTransform); + break; + default: + strTmp = QString(" ColorTransform = %1 [???]").arg(nColTransform); + break; + + } + + m_pLog->AddLine(strTmp); + m_nApp14ColTransform = (nColTransform & 0xFF); + + // Restore original position in file to a point + // after the section + m_nPos = nPosSaved + nLength; + + break; + + case JFIF_APP13: + // Photoshop (Save As) + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); + strTmp = QString(" Length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + nPosSaved = m_nPos; + + // Some files had very short segment (eg. nLength=2) + if(nLength < 2 + 20) + { + m_pLog->AddLine(" Segment too short for Identifier. Skipping remainder."); + m_nPos = nPosSaved + nLength; + break; + } + + m_nPos += 2; // Move past length now that we've used it + + strcpy(acIdentifier, m_pWBuf->BufReadStrn(m_nPos, MAX_IDENTIFIER - 1).toLatin1().data()); + acIdentifier[MAX_IDENTIFIER - 1] = 0; // Null terminate just in case + strTmp = QString(" Identifier = [%1]").arg(acIdentifier); + m_pLog->AddLine(strTmp); + m_nPos += (uint32_t) strlen(acIdentifier) + 1; + + if(strcmp(acIdentifier, "Photoshop 3.0") != 0) + { + m_pLog->AddLine(" Not Photoshop. Skipping remainder."); + } + else // Photoshop + { + DecodeApp13Ps(); + } + + // Restore original position in file to a point + // after the section + m_nPos = nPosSaved + nLength; + break; + + case JFIF_APP1: + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); + strTmp = QString(" Length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + nPosSaved = m_nPos; + + m_nPos += 2; // Move past length now that we've used it + + strcpy(acIdentifier, m_pWBuf->BufReadStrn(m_nPos, MAX_IDENTIFIER - 1).toLatin1().data()); + acIdentifier[MAX_IDENTIFIER - 1] = 0; // Null terminate just in case + strTmp = QString(" Identifier = [%1]").arg(acIdentifier); + m_pLog->AddLine(strTmp); + m_nPos += (uint32_t) strlen(acIdentifier); + + if(strncmp(acIdentifier, "http://ns.adobe.com/xap/1.0/\x00", 29) == 0) + { //@@ + // XMP + + m_pLog->AddLine(" XMP = "); + + m_nPos++; + + // NOTE: This code currently treats the strings from the XMP section + // as single byte characters. In reality, it should probably be + // updated to support unicode properly. + + uint32_t nPosMarkerEnd = nPosSaved + nLength - 1; + + uint32_t sXmpLen = nPosMarkerEnd - m_nPos; + + uint8_t cXmpChar; + + bool bNonSpace; + + QString strLine; + + // Reset state + strLine = " |"; + bNonSpace = false; + + for(uint32_t nInd = 0; nInd < sXmpLen; nInd++) + { + // Get the next char (8-bit byte) + cXmpChar = m_pWBuf->Buf(m_nPos + nInd); + + // Detect a non-space in line + if((cXmpChar != 0x20) && (cXmpChar != 0x0A)) + { + bNonSpace = true; + } + + // Detect Linefeed, print out line + if(cXmpChar == 0x0A) + { + // Only print line if some non-space elements! + if(bNonSpace) + { + m_pLog->AddLine(strLine); + } + // Reset state + strLine = " |"; + bNonSpace = false; + } + else + { + // Add the char + strLine += cXmpChar; + } + } + } + else if(strcmp(acIdentifier, "Exif") == 0) //@@ + { + // Only decode it further if it is EXIF format + + m_nPos += 2; // Skip two 00 bytes + + nPosExifStart = m_nPos; // Save m_nPos @ start of EXIF used for all IFD offsets + + // =========== EXIF TIFF Header (Start) =========== + // - Defined in Exif 2.2 Standard (JEITA CP-3451) section 4.5.2 + // - Contents (8 bytes total) + // - Byte order (2 bytes) + // - 0x002A (2 bytes) + // - Offset of 0th IFD (4 bytes) + + uint8_t acIdentifierTiff[9]; + + strFull = ""; + strTmp = ""; + + strFull = " Identifier TIFF = "; + for(uint32_t i = 0; i < 8; i++) + { + acIdentifierTiff[i] = (uint8_t) Buf(m_nPos++); + } + strTmp = PrintAsHexUC(acIdentifierTiff, 8); + strFull += strTmp; + m_pLog->AddLine(strFull); + + switch (acIdentifierTiff[0] * 256 + acIdentifierTiff[1]) + { + case 0x4949: // "II" + // Intel alignment + m_nImgExifEndian = 0; + m_pLog->AddLine(" Endian = Intel (little)"); + break; + case 0x4D4D: // "MM" + // Motorola alignment + m_nImgExifEndian = 1; + m_pLog->AddLine(" Endian = Motorola (big)"); + break; + } + + // We expect the TAG mark of 0x002A (depending on endian mode) + uint32_t test_002a; + + test_002a = ByteSwap2(acIdentifierTiff[2], acIdentifierTiff[3]); + strTmp = QString(" TAG Mark x002A = 0x%1").arg(test_002a, 4, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + uint32_t nIfdCount; // Current IFD # + + uint32_t nOffsetIfd1; + + // Mark pointer to EXIF Sub IFD as 0 so that we can + // detect if the tag never showed up. + m_nImgExifSubIfdPtr = 0; + m_nImgExifMakerPtr = 0; + m_nImgExifGpsIfdPtr = 0; + m_nImgExifInteropIfdPtr = 0; + + bool exif_done = false; + + nOffsetIfd1 = ByteSwap4(acIdentifierTiff[4], acIdentifierTiff[5], acIdentifierTiff[6], acIdentifierTiff[7]); + + // =========== EXIF TIFF Header (End) =========== + + // =========== EXIF IFD 0 =========== + // Do we start the 0th IFD for the "Primary Image Data"? + // Even though the nOffsetIfd1 pointer should indicate to + // us where the IFD should start (0x0008 if immediately after + // EXIF TIFF Header), I have observed JPEG files that + // do not contain the IFD. Therefore, we must check for this + // condition by comparing against the APP marker length. + // Example file: http://img9.imageshack.us/img9/194/90114543.jpg + + if((nPosSaved + nLength) <= (nPosExifStart + nOffsetIfd1)) + { + // We've run out of space for any IFD, so cancel now + exif_done = true; + m_pLog->AddLine(" NOTE: No IFD entries"); + } + + nIfdCount = 0; + while(!exif_done) + { + + m_pLog->AddLine(""); + + strTmp = QString("IFD%1").arg(nIfdCount); + + // Process the IFD + nRet = DecodeExifIfd(strTmp, nPosExifStart, nOffsetIfd1); + + // Now that we have gone through all entries in the IFD directory, + // we read the offset to the next IFD + nOffsetIfd1 = ByteSwap4(Buf(m_nPos + 0), Buf(m_nPos + 1), Buf(m_nPos + 2), Buf(m_nPos + 3)); + m_nPos += 4; + + strTmp = QString(" Offset to Next IFD = 0x%1").arg(nOffsetIfd1, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + if(nRet != 0) + { + // Error condition (DecodeExifIfd returned error) + nOffsetIfd1 = 0x00000000; + } + + if(nOffsetIfd1 == 0x00000000) + { + // Either error condition or truly end of IFDs + exif_done = true; + } + else + { + nIfdCount++; + } + + } // while ! exif_done + + // If EXIF SubIFD was defined, then handle it now + if(m_nImgExifSubIfdPtr != 0) + { + m_pLog->AddLine(""); + DecodeExifIfd("SubIFD", nPosExifStart, m_nImgExifSubIfdPtr); + } + if(m_nImgExifMakerPtr != 0) + { + m_pLog->AddLine(""); + DecodeExifIfd("MakerIFD", nPosExifStart, m_nImgExifMakerPtr); + } + if(m_nImgExifGpsIfdPtr != 0) + { + m_pLog->AddLine(""); + DecodeExifIfd("GPSIFD", nPosExifStart, m_nImgExifGpsIfdPtr); + } + if(m_nImgExifInteropIfdPtr != 0) + { + m_pLog->AddLine(""); + DecodeExifIfd("InteropIFD", nPosExifStart, m_nImgExifInteropIfdPtr); + } + + } + else + { + strTmp = QString("Identifier [%1] not supported. Skipping remainder.").arg(acIdentifier); + m_pLog->AddLine(strTmp); + } + + ////////// + + // Dump out Makernote area + + // TODO: Disabled for now +#if 0 + uint32_t ptr_base; + + if(m_bVerbose) + { + if(m_nImgExifMakerPtr != 0) + { + // FIXME: Seems that nPosExifStart is not initialized in VERBOSE mode + ptr_base = nPosExifStart + m_nImgExifMakerPtr; + + m_pLog->AddLine("Exif Maker IFD DUMP"); + strFull = QString(" MarkerOffset @ 0x%08X"), ptr_base; + m_pLog->AddLine(strFull); + } + } +#endif + + // End of dump out makernote area + + // Restore file position + m_nPos = nPosSaved; + + // Restore original position in file to a point + // after the section + m_nPos = nPosSaved + nLength; + + break; + + case JFIF_APP2: + // Typically used for Flashpix and possibly ICC profiles + // Photoshop (Save As) + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); + strTmp = QString(" Length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + nPosSaved = m_nPos; + + m_nPos += 2; // Move past length now that we've used it + + strcpy(acIdentifier, m_pWBuf->BufReadStrn(m_nPos, MAX_IDENTIFIER - 1).toLatin1().data()); + acIdentifier[MAX_IDENTIFIER - 1] = 0; // Null terminate just in case + strTmp = QString(" Identifier = [%1]").arg(acIdentifier); + m_pLog->AddLine(strTmp); + m_nPos += (uint32_t) strlen(acIdentifier) + 1; + + if(strcmp(acIdentifier, "FPXR") == 0) + { + // Photoshop + m_pLog->AddLine(" FlashPix:"); + DecodeApp2Flashpix(); + } + else if(strcmp(acIdentifier, "ICC_PROFILE") == 0) + { + // ICC Profile + m_pLog->AddLine(" ICC Profile:"); + DecodeApp2IccProfile(nLength); + } + else + { + m_pLog->AddLine(" Not supported. Skipping remainder."); + } + + // Restore original position in file to a point + // after the section + m_nPos = nPosSaved + nLength; + break; + + case JFIF_APP3: + case JFIF_APP4: + case JFIF_APP5: + case JFIF_APP6: + case JFIF_APP7: + case JFIF_APP8: + case JFIF_APP9: + case JFIF_APP10: + case JFIF_APP11: + //case JFIF_APP12: // Handled separately + //case JFIF_APP13: // Handled separately + //case JFIF_APP14: // Handled separately + case JFIF_APP15: + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); + m_pLog->AddLine(QString(" Length = %1").arg(nLength)); + + if(m_bVerbose) + { + strFull = ""; + + for(uint32_t i = 0; i < nLength; i++) + { + // Start a new line for every 16 codes + if((i % 16) == 0) + { + strFull = QString(" MarkerOffset [%1]: ").arg(i, 4, 16, QChar('0')); + } + else if((i % 8) == 0) + { + strFull += " "; + } + + nTmpVal = Buf(m_nPos + i); + strFull += QString("%1 ").arg(nTmpVal, 2, 16, QChar('0')); + + if((i % 16) == 15) + { + m_pLog->AddLine(strFull); + strFull = ""; + } + } + + m_pLog->AddLine(strFull); + + strFull = ""; + + for(uint32_t i = 0; i < nLength; i++) + { + // Start a new line for every 16 codes + if((i % 32) == 0) + { + strFull = QString(" MarkerOffset [%1]: ").arg(i, 4, 16, QChar('0')); + } + else if((i % 8) == 0) + { + strFull += " "; + } + + nTmpVal1 = Buf(m_nPos + i); + + if(isprint(nTmpVal1)) + { + strFull += QString("%1").arg(nTmpVal1); + } + else + { + strFull += "."; + } + if((i % 32) == 31) + { + m_pLog->AddLine(strFull); + } + } + + m_pLog->AddLine(strFull); + } // nVerbose + + m_nPos += nLength; + break; + + case JFIF_APP0: // APP0 + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + //nLength = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); + m_nPos += 2; + strTmp = QString(" Length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + strcpy(m_acApp0Identifier, m_pWBuf->BufReadStrn(m_nPos, MAX_IDENTIFIER - 1).toLatin1().data()); + m_acApp0Identifier[MAX_IDENTIFIER - 1] = 0; // Null terminate just in case + strTmp = QString(" Identifier = [%1]").arg(m_acApp0Identifier); + m_pLog->AddLine(strTmp); + + if(strcmp(m_acApp0Identifier, "JFIF")) + { + // Only process remainder if it is JFIF. This marker + // is also used for application-specific functions. + + m_nPos += (uint32_t) (strlen(m_acApp0Identifier) + 1); + + m_nImgVersionMajor = Buf(m_nPos++); + m_nImgVersionMinor = Buf(m_nPos++); + strTmp = QString(" version = [%1.%2]").arg(m_nImgVersionMajor).arg(m_nImgVersionMinor); + m_pLog->AddLine(strTmp); + + m_nImgUnits = Buf(m_nPos++); + + m_nImgDensityX = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + //m_nImgDensityX = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); + m_nPos += 2; + m_nImgDensityY = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + //m_nImgDensityY = m_pWBuf->BufX(m_nPos,2,!m_nImgExifEndian); + m_nPos += 2; + strTmp = QString(" density = %1 x %2 ").arg(m_nImgDensityX).arg(m_nImgDensityY); + strFull = strTmp; + + switch (m_nImgUnits) + { + case 0: + strFull += "(aspect ratio)"; + m_pLog->AddLine(strFull); + break; + + case 1: + strFull += "DPI (dots per inch)"; + m_pLog->AddLine(strFull); + break; + + case 2: + strFull += "DPcm (dots per cm)"; + m_pLog->AddLine(strFull); + break; + + default: + strTmp = QString("ERROR: Unknown ImgUnits parameter [%1]").arg(m_nImgUnits); + strFull += strTmp; + m_pLog->AddLineWarn(strFull); + //return DECMARK_ERR; + break; + } + + m_nImgThumbSizeX = Buf(m_nPos++); + m_nImgThumbSizeY = Buf(m_nPos++); + strTmp = QString(" thumbnail = %1 x %2").arg(m_nImgThumbSizeX).arg(m_nImgThumbSizeY); + m_pLog->AddLine(strTmp); + + // Unpack the thumbnail: + uint32_t thumbnail_r, thumbnail_g, thumbnail_b; + + if(m_nImgThumbSizeX && m_nImgThumbSizeY) + { + for(uint32_t y = 0; y < m_nImgThumbSizeY; y++) + { + strFull = QString(" Thumb[%1] = ").arg(y, 3, 10, QChar('0')); + + for(uint32_t x = 0; x < m_nImgThumbSizeX; x++) + { + thumbnail_r = Buf(m_nPos++); + thumbnail_g = Buf(m_nPos++); + thumbnail_b = Buf(m_nPos++); + strTmp = QString("(0x%1,0x%2,0x%3) ") + .arg(thumbnail_r, 2, 16, QChar('0')) + .arg(thumbnail_g, 2, 16, QChar('0')) + .arg(thumbnail_b, 2, 16, QChar('0')); + strFull += strTmp; + m_pLog->AddLine(strFull); + } + } + } + + // TODO: + // - In JPEG-B mode (GeoRaster), we will need to fake out + // the DHT & DQT tables here. Unfortunately, we'll have to + // rely on the user to put us into this mode as there is nothing + // in the file that specifies this mode. + + /* + // TODO: Need to ensure that Faked DHT is correct table + + AddHeader(JFIF_DHT_FAKE); + DecodeDHT(true); + // Need to mark DHT tables as OK + m_bStateDht = true; + m_bStateDhtFake = true; + m_bStateDhtOk = true; + + // ... same for DQT + */ + + } + else if(strncmp(m_acApp0Identifier, "AVI1", 4)) //@@ + { + // AVI MJPEG type + + // Need to fill in predefined DHT table from spec: + // OpenDML file format for AVI, section "Proposed Data Chunk Format" + // Described in MMREG.H + m_pLog->AddLine(" Detected MotionJPEG"); + m_pLog->AddLine(" Importing standard Huffman table..."); + m_pLog->AddLine(""); + + AddHeader(JFIF_DHT_FAKE); + + DecodeDHT(true); + // Need to mark DHT tables as OK + m_bStateDht = true; + m_bStateDhtFake = true; + m_bStateDhtOk = true; + + m_nPos += nLength - 2; // Skip over, and undo length short read + + } + else + { + // Not JFIF or AVI1 + m_pLog->AddLine(" Not known APP0 type. Skipping remainder."); + m_nPos += nLength - 2; + } + + if(!ExpectMarkerEnd(nPosMarkerStart, nLength)) + return DECMARK_ERR; + + break; + + case JFIF_DQT: // Define quantization tables + m_bStateDqt = true; + + uint32_t nDqtPrecision_Pq; + uint32_t nDqtQuantDestId_Tq; + + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); // Lq + nPosEnd = m_nPos + nLength; + m_nPos += 2; + strTmp = QString(" Table length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + while(nPosEnd > m_nPos) + { + m_pLog->AddLine(" ----"); + + nTmpVal = Buf(m_nPos++); // Pq | Tq + nDqtPrecision_Pq = (nTmpVal & 0xF0) >> 4; // Pq, range 0-1 + nDqtQuantDestId_Tq = nTmpVal & 0x0F; // Tq, range 0-3 + + // Decode per ITU-T.81 standard +#if 1 + if(nDqtPrecision_Pq == 0) + { + strDqtPrecision = "8 bits"; + } + else if(nDqtPrecision_Pq == 1) + { + strDqtPrecision = "16 bits"; + } + else + { + m_pLog->AddLineWarn(QString(" Unsupported precision value [%1]").arg(nDqtPrecision_Pq)); + strDqtPrecision = "???"; + // FIXME: Consider terminating marker parsing early + } + + if(!ValidateValue(nDqtPrecision_Pq, 0, 1, "DQT Precision ", true, 0)) + return DECMARK_ERR; + + if(!ValidateValue(nDqtQuantDestId_Tq, 0, 3, "DQT Destination ID ", true, 0)) + return DECMARK_ERR; + + strTmp = QString(" Precision=%1").arg(strDqtPrecision); + m_pLog->AddLine(strTmp); +#else + // Decode with additional DQT extension (ITU-T-JPEG-Plus-Proposal_R3.doc) + + if((nDqtPrecision_Pq & 0xE) == 0) + { + // Per ITU-T.81 Standard + if(nDqtPrecision_Pq == 0) + { + strDqtPrecision = "8 bits"; + } + else if(nDqtPrecision_Pq == 1) + { + strDqtPrecision = "16 bits"; + } + strTmp = QString(" Precision=%1"), strDqtPrecision; + m_pLog->AddLine(strTmp); + } + else + { + // Non-standard + // JPEG-Plus-Proposal-R3: + // - Alternative sub-block-wise sequence + strTmp = QString(" Non-Standard DQT Extension detected"); + m_pLog->AddLineWarn(strTmp); + + // FIXME: Should prevent attempt to decode until this is implemented + + if(nDqtPrecision_Pq == 0) + { + strDqtPrecision = "8 bits"; + } + else if(nDqtPrecision_Pq == 1) + { + strDqtPrecision = "16 bits"; + } + strTmp = QString(" Precision=%1"), strDqtPrecision; + m_pLog->AddLine(strTmp); + + if((nDqtPrecision_Pq & 0x2) == 0) + { + strDqtZigZagOrder = "Diagonal zig-zag coeff scan seqeunce"; + } + else if((nDqtPrecision_Pq & 0x2) == 1) + { + strDqtZigZagOrder = "Alternate coeff scan seqeunce"; + } + strTmp = QString(" Coeff Scan Sequence=%s"), strDqtZigZagOrder; + m_pLog->AddLine(strTmp); + + if((nDqtPrecision_Pq & 0x4) == 1) + { + strTmp = QString(" Custom coeff scan sequence"); + m_pLog->AddLine(strTmp); + // Now expect sequence of 64 coefficient entries + QString strSequence = ""; + + for(uint32_t nInd = 0; nInd < 64; nInd++) + { + nTmpVal = Buf(m_nPos++); + strTmp = QString("%u"), nTmpVal; + strSequence += strTmp; + if(nInd != 63) + { + strSequence += ", "; + } + } + strTmp = QString(" Custom sequence = [ %s ]"), strSequence; + m_pLog->AddLine(strTmp); + } + } +#endif + strTmp = QString(" Destination ID=%1").arg(nDqtQuantDestId_Tq); + + if(nDqtQuantDestId_Tq == 0) + { + strTmp += " (Luminance)"; + } + else if(nDqtQuantDestId_Tq == 1) + { + strTmp += " (Chrominance)"; + } + else if(nDqtQuantDestId_Tq == 2) + { + strTmp += " (Chrominance)"; + } + else + { + strTmp += " (???)"; + } + + m_pLog->AddLine(strTmp); + + // FIXME: The following is somewhat superseded by ValidateValue() above with the exception of skipping remainder + if(nDqtQuantDestId_Tq >= MAX_DQT_DEST_ID) + { + m_pLog->AddLineErr(QString("ERROR: Destination ID = %1, >= %2").arg(nDqtQuantDestId_Tq).arg(MAX_DQT_DEST_ID)); + + if(!m_pAppConfig->bRelaxedParsing) + { + m_pLog->AddLineErr(" Stopping decode"); + return DECMARK_ERR; + } + else + { + // Now skip remainder of DQT + // FIXME + m_pLog->AddLineWarn(QString(" Skipping remainder of marker [%1 bytes]").arg(nPosMarkerStart + nLength - m_nPos)); + m_pLog->AddLine(""); + m_nPos = nPosMarkerStart + nLength; + return DECMARK_OK; + } + } + + bool bQuantAllOnes = true; + + double dComparePercent; + double dSumPercent = 0; + double dSumPercentSqr = 0; + + for(uint32_t nCoeffInd = 0; nCoeffInd < MAX_DQT_COEFF; nCoeffInd++) + { + nTmpVal2 = Buf(m_nPos++); + + if(nDqtPrecision_Pq == 1) + { + // 16-bit DQT entries! + nTmpVal2 <<= 8; + nTmpVal2 += Buf(m_nPos++); + } + + m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]] = nTmpVal2; + + /* scaling factor in percent */ + + // Now calculate the comparison with the Annex sample + + // FIXME: Should probably use check for landscape orientation and + // rotate comparison matrix accordingly + + if(nDqtQuantDestId_Tq == 0) + { + if(m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]] != 0) + { + m_afStdQuantLumCompare[glb_anZigZag[nCoeffInd]] = + (float) (glb_anStdQuantLum[glb_anZigZag[nCoeffInd]]) / + (float) (m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]]); + dComparePercent = 100.0 * + (double) (m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]]) / + (double) (glb_anStdQuantLum[glb_anZigZag[nCoeffInd]]); + } + else + { + m_afStdQuantLumCompare[glb_anZigZag[nCoeffInd]] = (float) 999.99; + dComparePercent = 999.99; + } + } + else + { + if(m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]] != 0) + { + m_afStdQuantChrCompare[glb_anZigZag[nCoeffInd]] = + (float) (glb_anStdQuantChr[glb_anZigZag[nCoeffInd]]) / + (float) (m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]]); + dComparePercent = 100.0 * + (double) (m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]]) / + (double) (glb_anStdQuantChr[glb_anZigZag[nCoeffInd]]); + } + else + { + m_afStdQuantChrCompare[glb_anZigZag[nCoeffInd]] = (float) 999.99; + } + } + + dSumPercent += dComparePercent; + dSumPercentSqr += dComparePercent * dComparePercent; + + // Check just in case entire table are ones (Quality 100) + if(m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]] != 1) + bQuantAllOnes = 0; + + } // 0..63 + + // Note that the DQT table that we are saving is already + // after doing zigzag reordering: + // From high freq -> low freq + // To X,Y, left-to-right, top-to-bottom + + // Flag this DQT table as being set! + m_abImgDqtSet[nDqtQuantDestId_Tq] = true; + + uint32_t nCoeffInd; + + // Now display the table + for(uint32_t nDqtY = 0; nDqtY < 8; nDqtY++) + { + strFull = QString(" DQT, Row #%1: ").arg(nDqtY); + + for(uint32_t nDqtX = 0; nDqtX < 8; nDqtX++) + { + nCoeffInd = nDqtY * 8 + nDqtX; + strFull += QString("%1 ").arg(m_anImgDqtTbl[nDqtQuantDestId_Tq][nCoeffInd], 3); + + // Store the DQT entry into the Image Decoder + bRet = m_pImgDec->SetDqtEntry(nDqtQuantDestId_Tq, nCoeffInd, glb_anUnZigZag[nCoeffInd], + m_anImgDqtTbl[nDqtQuantDestId_Tq][nCoeffInd]); + DecodeErrCheck(bRet); + } + + // Now add the compare with Annex K + // Decided to disable this as it was confusing users + /* + strFull += " AnnexRatio: <"; + for (uint32_t nDqtX=0;nDqtX<8;nDqtX++) { + nCoeffInd = nDqtY*8+nDqtX; + if (nDqtQuantDestId_Tq == 0) { + strTmp = QString("%5.1f "),m_afStdQuantLumCompare[nCoeffInd]; + } else { + strTmp = QString("%5.1f "),m_afStdQuantChrCompare[nCoeffInd]; + } + strFull += strTmp; + } + strFull += ">"; + */ + + m_pLog->AddLine(strFull); + + } + + // Perform some statistical analysis of the quality factor + // to determine the likelihood of the current quantization + // table being a scaled version of the "standard" tables. + // If the variance is high, it is unlikely to be the case. + double dQuality; + double dVariance; + + dSumPercent /= 64.0; /* mean scale factor */ + dSumPercentSqr /= 64.0; + dVariance = dSumPercentSqr - (dSumPercent * dSumPercent); /* variance */ + + // Generate the equivalent IJQ "quality" factor + if(bQuantAllOnes) /* special case for all-ones table */ + dQuality = 100.0; + else if(dSumPercent <= 100.0) + dQuality = (200.0 - dSumPercent) / 2.0; + else + dQuality = 5000.0 / dSumPercent; + + // Save the quality rating for later + m_adImgDqtQual[nDqtQuantDestId_Tq] = dQuality; + m_pLog->AddLine(QString(" Approx quality factor = %1 (scaling=%2 variance=%3)") + .arg(dQuality, 0, 'f', 2) + .arg(dSumPercent, 0, 'f', 2) + .arg(dVariance, 0, 'f', 2)); + } + + m_bStateDqtOk = true; + + if(!ExpectMarkerEnd(nPosMarkerStart, nLength)) + return DECMARK_ERR; + + break; + + case JFIF_DAC: // DAC (Arithmetic Coding) + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); // La + m_nPos += 2; + strTmp = QString(" Arithmetic coding header length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + uint32_t nDAC_n; + uint32_t nDAC_Tc, nDAC_Tb; + uint32_t nDAC_Cs; + + nDAC_n = (nLength > 2) ? (nLength - 2) / 2 : 0; + + for(uint32_t nInd = 0; nInd < nDAC_n; nInd++) + { + nTmpVal = Buf(m_nPos++); // Tc,Tb + nDAC_Tc = (nTmpVal & 0xF0) >> 4; + nDAC_Tb = (nTmpVal & 0x0F); + strTmp = QString(" #%1: Table class = %2") + .arg(nInd + 1, 2, 10, QChar('0')) + .arg(nDAC_Tc); + m_pLog->AddLine(strTmp); + strTmp = QString(" #%1: Table destination identifier = %2") + .arg(nInd, 2, 10, QChar('0')) + .arg(nDAC_Tb); + m_pLog->AddLine(strTmp); + + nDAC_Cs = Buf(m_nPos++); // Cs + strTmp = QString(" #%1: Conditioning table value = %2") + .arg(nInd + 1, 2, 10, QChar('0')) + .arg(nDAC_Cs); + m_pLog->AddLine(strTmp); + + if(!ValidateValue(nDAC_Tc, 0, 1, "Table class ", true, 0)) + return DECMARK_ERR; + if(!ValidateValue(nDAC_Tb, 0, 3, "Table destination ID ", true, 0)) + return DECMARK_ERR; + + // Parameter range constraints per Table B.6: + // ------------|-------------------------|-------------------|------------ + // | Sequential DCT | Progressive DCT | Lossless + // Parameter | Baseline Extended | | + // ------------|-----------|-------------|-------------------|------------ + // Cs | Undef | Tc=0: 0-255 | Tc=0: 0-255 | 0-255 + // | | Tc=1: 1-63 | Tc=1: 1-63 | + // ------------|-----------|-------------|-------------------|------------ + + // However, to keep it simple (and not depend on lossless mode), + // we will only check the maximal range + if(!ValidateValue(nDAC_Cs, 0, 255, "Conditioning table value ", true, 0)) + return DECMARK_ERR; + } + if(!ExpectMarkerEnd(nPosMarkerStart, nLength)) + return DECMARK_ERR; + + break; + + case JFIF_DNL: // DNL (Define number of lines) + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); // Ld + m_nPos += 2; + strTmp = QString(" Header length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + nTmpVal = Buf(m_nPos) * 256 + Buf(m_nPos + 1); // NL + m_nPos += 2; + strTmp = QString(" Number of lines = %1").arg(nTmpVal); + m_pLog->AddLine(strTmp); + + if(!ValidateValue(nTmpVal, 1, 65535, "Number of lines ", true, 1)) + return DECMARK_ERR; + + if(!ExpectMarkerEnd(nPosMarkerStart, nLength)) + return DECMARK_ERR; + break; + + case JFIF_EXP: + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); // Le + m_nPos += 2; + strTmp = QString(" Header length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + uint32_t nEXP_Eh, nEXP_Ev; + + nTmpVal = Buf(m_nPos) * 256 + Buf(m_nPos + 1); // Eh,Ev + nEXP_Eh = (nTmpVal & 0xF0) >> 4; + nEXP_Ev = (nTmpVal & 0x0F); + m_nPos += 2; + strTmp = QString(" Expand horizontally = %1").arg(nEXP_Eh); + m_pLog->AddLine(strTmp); + strTmp = QString(" Expand vertically = %1").arg(nEXP_Ev); + m_pLog->AddLine(strTmp); + + if(!ValidateValue(nEXP_Eh, 0, 1, "Expand horizontally ", true, 0)) + return DECMARK_ERR; + + if(!ValidateValue(nEXP_Ev, 0, 1, "Expand vertically ", true, 0)) + return DECMARK_ERR; + + if(!ExpectMarkerEnd(nPosMarkerStart, nLength)) + return DECMARK_ERR; + break; + + case JFIF_SOF0: // SOF0 (Baseline DCT) + case JFIF_SOF1: // SOF1 (Extended sequential) + case JFIF_SOF2: // SOF2 (Progressive) + case JFIF_SOF3: + case JFIF_SOF5: + case JFIF_SOF6: + case JFIF_SOF7: + case JFIF_SOF9: + case JFIF_SOF10: + case JFIF_SOF11: + case JFIF_SOF13: + case JFIF_SOF14: + case JFIF_SOF15: + + // TODO: + // - JFIF_DHP should be able to reuse the JFIF_SOF marker parsing + // however as we don't support hierarchical image decode, we + // would want to skip the update of class members. + + m_bStateSof = true; + + // Determine if this is a SOF mode that we support + // At this time, we only support Baseline DCT & Extended Sequential Baseline DCT + // (non-differential) with Huffman coding. Progressive, Lossless, + // Differential and Arithmetic coded modes are not supported. + m_bImgSofUnsupported = true; + if(nCode == JFIF_SOF0) + { + m_bImgSofUnsupported = false; + } + if(nCode == JFIF_SOF1) + { + m_bImgSofUnsupported = false; + } + + // For reference, note progressive scan files even though + // we don't currently support their decode + if(nCode == JFIF_SOF2) + { + m_bImgProgressive = true; + } + + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); // Lf + m_nPos += 2; + strTmp = QString(" Frame header length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + m_nSofPrecision_P = Buf(m_nPos++); // P + strTmp = QString(" Precision = %1").arg(m_nSofPrecision_P); + m_pLog->AddLine(strTmp); + if(!ValidateValue(m_nSofPrecision_P, 2, 16, "Precision

", true, 8)) + return DECMARK_ERR; + + m_nSofNumLines_Y = Buf(m_nPos) * 256 + Buf(m_nPos + 1); // Y + m_nPos += 2; + strTmp = QString(" Number of Lines = %1").arg(m_nSofNumLines_Y); + m_pLog->AddLine(strTmp); + + if(!ValidateValue(m_nSofNumLines_Y, 0, 65535, "Number of Lines ", true, 0)) + return DECMARK_ERR; + + m_nSofSampsPerLine_X = Buf(m_nPos) * 256 + Buf(m_nPos + 1); // X + m_nPos += 2; + strTmp = QString(" Samples per Line = %1").arg(m_nSofSampsPerLine_X); + m_pLog->AddLine(strTmp); + + if(!ValidateValue(m_nSofSampsPerLine_X, 1, 65535, "Samples per Line ", true, 1)) + return DECMARK_ERR; + + strTmp = QString(" Image Size = %1 x %2").arg(m_nSofSampsPerLine_X).arg(m_nSofNumLines_Y); + m_pLog->AddLine(strTmp); + + // Determine orientation + // m_nSofSampsPerLine_X = X + // m_nSofNumLines_Y = Y + m_eImgLandscape = ENUM_LANDSCAPE_YES; + if(m_nSofNumLines_Y > m_nSofSampsPerLine_X) + m_eImgLandscape = ENUM_LANDSCAPE_NO; + strTmp = QString(" Raw Image Orientation = %1").arg(m_eImgLandscape == ENUM_LANDSCAPE_YES ? "Landscape" : "Portrait"); + m_pLog->AddLine(strTmp); + + m_nSofNumComps_Nf = Buf(m_nPos++); // Nf, range 1..255 + strTmp = QString(" Number of Img components = %1").arg(m_nSofNumComps_Nf); + m_pLog->AddLine(strTmp); + if(!ValidateValue(m_nSofNumComps_Nf, 1, 255, "Number of Img components ", true, 1)) + return DECMARK_ERR; + + uint32_t nCompIdent; + + uint32_t anSofSampFact[MAX_SOF_COMP_NF]; + + m_nSofHorzSampFactMax_Hmax = 0; + m_nSofVertSampFactMax_Vmax = 0; + + // Now clear the output image content (all components) + // TODO: Migrate some of the bitmap allocation / clearing from + // DecodeScanImg() into ResetImageContent() and call here + //m_pImgDec->ResetImageContent(); + + // Per JFIF v1.02: + // - Nf = 1 or 3 + // - C1 = Y + // - C2 = Cb + // - C3 = Cr + + for(uint32_t nCompInd = 1; ((!m_bStateAbort) && (nCompInd <= m_nSofNumComps_Nf)); nCompInd++) + { + nCompIdent = Buf(m_nPos++); // Ci, range 0..255 + m_anSofQuantCompId[nCompInd] = nCompIdent; + + //if (!ValidateValue(m_anSofQuantCompId[nCompInd],0,255,"Component ID "),true,0) return DECMARK_ERR; + + anSofSampFact[nCompIdent] = Buf(m_nPos++); + m_anSofQuantTblSel_Tqi[nCompIdent] = Buf(m_nPos++); // Tqi, range 0..3 + + //if (!ValidateValue(m_anSofQuantTblSel_Tqi[nCompIdent],0,3,"Table Destination ID "),true,0) return DECMARK_ERR; + + // NOTE: We protect against bad input here as replication ratios are + // determined later that depend on dividing by sampling factor (hence + // possibility of div by 0). + m_anSofHorzSampFact_Hi[nCompIdent] = (anSofSampFact[nCompIdent] & 0xF0) >> 4; // Hi, range 1..4 + m_anSofVertSampFact_Vi[nCompIdent] = (anSofSampFact[nCompIdent] & 0x0F); // Vi, range 1..4 + + if(!ValidateValue(m_anSofHorzSampFact_Hi[nCompIdent], 1, 4, "Horizontal Sampling Factor ", true, 1)) + return DECMARK_ERR; + + if(!ValidateValue(m_anSofVertSampFact_Vi[nCompIdent], 1, 4, "Vertical Sampling Factor ", true, 1)) + return DECMARK_ERR; + } + + // Calculate max sampling factors + for(uint32_t nCompInd = 1; ((!m_bStateAbort) && (nCompInd <= m_nSofNumComps_Nf)); nCompInd++) + { + nCompIdent = m_anSofQuantCompId[nCompInd]; + // Calculate maximum sampling factor for the SOF. This is only + // used for later generation of m_strImgQuantCss an the SOF + // reporting below. The CimgDecode block is responsible for + // calculating the maximum sampling factor on a per-scan basis. + m_nSofHorzSampFactMax_Hmax = qMax(m_nSofHorzSampFactMax_Hmax, m_anSofHorzSampFact_Hi[nCompIdent]); + m_nSofVertSampFactMax_Vmax = qMax(m_nSofVertSampFactMax_Vmax, m_anSofVertSampFact_Vi[nCompIdent]); + } + + // Report per-component sampling factors and quantization table selectors + for(uint32_t nCompInd = 1; ((!m_bStateAbort) && (nCompInd <= m_nSofNumComps_Nf)); nCompInd++) + { + nCompIdent = m_anSofQuantCompId[nCompInd]; + + // Create subsampling ratio + // - Protect against division-by-zero + QString strSubsampH = "?"; + + QString strSubsampV = "?"; + + if(m_anSofHorzSampFact_Hi[nCompIdent] > 0) + { + strSubsampH = QString("%1").arg(m_nSofHorzSampFactMax_Hmax / m_anSofHorzSampFact_Hi[nCompIdent]); + } + if(m_anSofVertSampFact_Vi[nCompIdent] > 0) + { + strSubsampV = QString("%1").arg(m_nSofVertSampFactMax_Vmax / m_anSofVertSampFact_Vi[nCompIdent]); + } + + strFull = QString(" Component[%1]: ").arg(nCompInd); // Note i in Ci is 1-based + strTmp = QString("ID=0x%1, Samp Fac=0x%2 (Subsamp %3 x %4), Quant Tbl Sel=0x%5") + .arg(nCompIdent, 2, 16, QChar('0')) + .arg(anSofSampFact[nCompIdent], 2, 16, QChar('0')) + .arg(strSubsampH) + .arg(strSubsampV) + .arg(m_anSofQuantTblSel_Tqi[nCompIdent], 2, 16, QChar('0')); + strFull += strTmp; + + // Mapping from component index (not ID) to colour channel per JFIF + if(m_nSofNumComps_Nf == 1) + { + // Assume grayscale + strFull += " (Lum: Y)"; + } + else if(m_nSofNumComps_Nf == 3) + { + // Assume YCC + if(nCompInd == SCAN_COMP_Y) + { + strFull += " (Lum: Y)"; + } + else if(nCompInd == SCAN_COMP_CB) + { + strFull += " (Chrom: Cb)"; + } + else if(nCompInd == SCAN_COMP_CR) + { + strFull += " (Chrom: Cr)"; + } + } + else if(m_nSofNumComps_Nf == 4) + { + // Assume YCCK + if(nCompInd == 1) + { + strFull += " (Y)"; + } + else if(nCompInd == 2) + { + strFull += " (Cb)"; + } + else if(nCompInd == 3) + { + strFull += " (Cr)"; + } + else if(nCompInd == 4) + { + strFull += " (K)"; + } + } + else + { + strFull += " (???)"; // Unknown + } + m_pLog->AddLine(strFull); + + } + + // Test for bad input, clean up if bad + for(uint32_t nCompInd = 1; ((!m_bStateAbort) && (nCompInd <= m_nSofNumComps_Nf)); nCompInd++) + { + nCompIdent = m_anSofQuantCompId[nCompInd]; + + if(!ValidateValue(m_anSofQuantCompId[nCompInd], 0, 255, "Component ID ", true, 0)) + return DECMARK_ERR; + + if(!ValidateValue(m_anSofQuantTblSel_Tqi[nCompIdent], 0, 3, "Table Destination ID ", true, 0)) + return DECMARK_ERR; + + if(!ValidateValue(m_anSofHorzSampFact_Hi[nCompIdent], 1, 4, "Horizontal Sampling Factor ", true, 1)) + return DECMARK_ERR; + + if(!ValidateValue(m_anSofVertSampFact_Vi[nCompIdent], 1, 4, "Vertical Sampling Factor ", true, 1)) + return DECMARK_ERR; + } + + // Finally, assign the cleaned values to the decoder + for(uint32_t nCompInd = 1; ((!m_bStateAbort) && (nCompInd <= m_nSofNumComps_Nf)); nCompInd++) + { + nCompIdent = m_anSofQuantCompId[nCompInd]; + // Store the DQT Table selection for the Image Decoder + // Param values: Nf,Tqi + // Param ranges: 1..255,0..3 + // Note that the Image Decoder doesn't need to see the Component Identifiers + bRet = m_pImgDec->SetDqtTables(nCompInd, m_anSofQuantTblSel_Tqi[nCompIdent]); + DecodeErrCheck(bRet); + + // Store the Precision (to handle 12-bit decode) + m_pImgDec->SetPrecision(m_nSofPrecision_P); + + } + + if(!m_bStateAbort) + { + + // Set the component sampling factors (chroma subsampling) + // FIXME: check ranging + for(uint32_t nCompInd = 1; nCompInd <= m_nSofNumComps_Nf; nCompInd++) + { + // nCompInd is component index (1...Nf) + // nCompIdent is Component Identifier (Ci) + // Note that the Image Decoder doesn't need to see the Component Identifiers + nCompIdent = m_anSofQuantCompId[nCompInd]; + m_pImgDec->SetSofSampFactors(nCompInd, m_anSofHorzSampFact_Hi[nCompIdent], m_anSofVertSampFact_Vi[nCompIdent]); + } + + // Now mark the image as been somewhat OK (ie. should + // also be suitable for EmbeddedThumb() and PrepareSignature() + m_bImgOK = true; + + m_bStateSofOk = true; + + } + + if(!ExpectMarkerEnd(nPosMarkerStart, nLength)) + return DECMARK_ERR; + + break; + + case JFIF_COM: // COM + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + m_nPos += 2; + strTmp = QString(" Comment length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + // Check for JPEG COM vulnerability + // http://marc.info/?l=bugtraq&m=109524346729948 + // Note that the recovery is not very graceful. It will assume that the + // field is actually zero-length, which will make the next byte trigger the + // "Expected marker 0xFF" error message and probably abort. There is no + // obvious way to + + if((nLength == 0) || (nLength == 1)) + { + strTmp = QString(" JPEG Comment Field Vulnerability detected!"); + m_pLog->AddLineErr(strTmp); + strTmp = QString(" Skipping data until next marker..."); + m_pLog->AddLineErr(strTmp); + nLength = 2; + + bool bDoneSearch = false; + + uint32_t nSkipStart = m_nPos; + + while(!bDoneSearch) + { + if(Buf(m_nPos) != 0xFF) + { + m_nPos++; + } + else + { + bDoneSearch = true; + } + if(m_nPos >= m_pWBuf->GetPosEof()) + { + bDoneSearch = true; + } + } + strTmp = QString(" Skipped %1 bytes").arg(m_nPos - nSkipStart); + m_pLog->AddLineErr(strTmp); + + // Break out of case statement + break; + } + + // Assume COM field valid length (ie. >= 2) + strFull = " Comment="; + m_strComment = ""; + for(uint32_t ind = 0; ind < nLength - 2; ind++) + { + nTmpVal1 = Buf(m_nPos++); + if(isprint(nTmpVal1)) + { + strTmp = QString("%1").arg(nTmpVal1); + m_strComment += strTmp; + } + else + { + m_strComment += "."; + } + } + strFull += m_strComment; + m_pLog->AddLine(strFull); + + break; + + case JFIF_DHT: // DHT + m_bStateDht = true; + DecodeDHT(false); + m_bStateDhtOk = true; + break; + + case JFIF_SOS: // SOS + uint32_t nPosScanStart; // Byte count at start of scan data segment + + m_bStateSos = true; + + // NOTE: Only want to capture position of first SOS + // This should make other function such as AVI frame extract + // more robust in case we get multiple SOS segments. + // We assume that this value is reset when we start a new decode + if(m_nPosSos == 0) + { + m_nPosSos = m_nPos - 2; // Used for Extract. Want to include actual marker + } + + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + m_nPos += 2; + + // Ensure that we have seen proper markers before we try this one! + if(!m_bStateSofOk) + { + strTmp = QString(" ERROR: SOS before valid SOF defined"); + m_pLog->AddLineErr(strTmp); + return DECMARK_ERR; + } + + strTmp = QString(" Scan header length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + m_nSosNumCompScan_Ns = Buf(m_nPos++); // Ns, range 1..4 + strTmp = QString(" Number of img components = %1").arg(m_nSosNumCompScan_Ns); + m_pLog->AddLine(strTmp); + + // Just in case something got corrupted, don't want to get out + // of range here. Note that this will be a hard abort, and + // will not resume decoding. + if(m_nSosNumCompScan_Ns > MAX_SOS_COMP_NS) + { + strTmp = QString(" ERROR: Scan decode does not support > %1 components").arg(MAX_SOS_COMP_NS); + m_pLog->AddLineErr(strTmp); + return DECMARK_ERR; + } + + uint32_t nSosCompSel_Cs; + uint32_t nSosHuffTblSel; + uint32_t nSosHuffTblSelDc_Td; + uint32_t nSosHuffTblSelAc_Ta; + + // Max range of components indices is between 1..4 + for(uint32_t nScanCompInd = 1; ((nScanCompInd <= m_nSosNumCompScan_Ns) && (!m_bStateAbort)); nScanCompInd++) + { + strFull = QString(" Component[%1]: ").arg(nScanCompInd); + nSosCompSel_Cs = Buf(m_nPos++); // Cs, range 0..255 + nSosHuffTblSel = Buf(m_nPos++); + nSosHuffTblSelDc_Td = (nSosHuffTblSel & 0xf0) >> 4; // Td, range 0..3 + nSosHuffTblSelAc_Ta = (nSosHuffTblSel & 0x0f); // Ta, range 0..3 + strTmp = QString("selector=0x%1, table=%2(DC),%3(AC)") + .arg(nSosCompSel_Cs, 2, 16, QChar('0')) + .arg(nSosHuffTblSelDc_Td) + .arg(nSosHuffTblSelAc_Ta); + strFull += strTmp; + m_pLog->AddLine(strFull); + + bRet = m_pImgDec->SetDhtTables(nScanCompInd, nSosHuffTblSelDc_Td, nSosHuffTblSelAc_Ta); + + DecodeErrCheck(bRet); + } + + m_nSosSpectralStart_Ss = Buf(m_nPos++); + m_nSosSpectralEnd_Se = Buf(m_nPos++); + m_nSosSuccApprox_A = Buf(m_nPos++); + + strTmp = QString(" Spectral selection = %1 .. %2") + .arg(m_nSosSpectralStart_Ss) + .arg(m_nSosSpectralEnd_Se); + m_pLog->AddLine(strTmp); + strTmp = QString(" Successive approximation = 0x%1").arg(m_nSosSuccApprox_A, 2, 16, QChar('0')); + m_pLog->AddLine(strTmp); + + if(m_pAppConfig->bOutputScanDump) + { + m_pLog->AddLine(""); + m_pLog->AddLine(" Scan Data: (after bitstuff removed)"); + } + + // Save the scan data segment position + nPosScanStart = m_nPos; + + // Skip over the Scan Data segment + // Pass 1) Quick, allowing for bOutputScanDump to dump first 640B. + // Pass 2) If bDecodeScanImg, we redo the process but in detail decoding. + + // FIXME: Not sure why, but if I skip over Pass 1 (eg if I leave in the + // following line uncommented), then I get an error at the end of the + // pass 2 decode (indicating that EOI marker not seen, and expecting + // marker). +// if (m_pAppConfig->bOutputScanDump) { + + // --- PASS 1 --- + bool bSkipDone; + + uint32_t nSkipCount; + uint32_t nSkipData; + uint32_t nSkipPos; + + bool bScanDumpTrunc; + + bSkipDone = false; + nSkipCount = 0; + nSkipPos = 0; + bScanDumpTrunc = false; + + strFull = ""; + + while(!bSkipDone) + { + nSkipCount++; + nSkipPos++; + nSkipData = Buf(m_nPos++); + + if(nSkipData == 0xFF) + { + // this could either be a marker or a byte stuff + nSkipData = Buf(m_nPos++); + nSkipCount++; + + if(nSkipData == 0x00) + { + // Byte stuff + nSkipData = 0xFF; + } + else if((nSkipData >= JFIF_RST0) && (nSkipData <= JFIF_RST7)) + { + // Skip over + } + else + { + // Marker + bSkipDone = true; + m_nPos -= 2; + } + } + + if(m_pAppConfig->bOutputScanDump && (!bSkipDone)) + { + // Only display 20 lines of scan data + if(nSkipPos > 640) + { + if(!bScanDumpTrunc) + { + m_pLog->AddLineWarn(" WARNING: Dump truncated."); + bScanDumpTrunc = true; + } + } + else + { + if(((nSkipPos - 1) == 0) || (((nSkipPos - 1) % 32) == 0)) + { + strFull = " "; + } + + strTmp = QString("%1 ").arg(nSkipData, 2, 16, QChar('0')); + strFull += strTmp; + + if(((nSkipPos - 1) % 32) == 31) + { + m_pLog->AddLine(strFull); + strFull = ""; + } + } + } + + // Did we run out of bytes? + + // FIXME: + // NOTE: This line here doesn't allow us to attempt to + // decode images that are missing EOI. Maybe this is + // not the best solution here? Instead, we should be + // checking m_nPos against file length? .. and not + // return but "break". + if(!m_pWBuf->GetBufOk()) + { + strTmp = QString("ERROR: Ran out of buffer before EOI during phase 1 of Scan decode @ 0x%1").arg(m_nPos, 8, 16, QChar('0')); + m_pLog->AddLineErr(strTmp); + break; + } + + } + m_pLog->AddLine(strFull); + +// } + + // --- PASS 2 --- + // If the option is set, start parsing! + if(m_pAppConfig->bDecodeScanImg && m_bImgSofUnsupported) + { + // SOF marker was of type we don't support, so skip decoding + m_pLog->AddLineWarn(" NOTE: Scan parsing doesn't support this SOF mode."); +#ifndef DEBUG_YCCK + } + else if(m_pAppConfig->bDecodeScanImg && (m_nSofNumComps_Nf == 4)) + { + m_pLog->AddLineWarn(" NOTE: Scan parsing doesn't support CMYK files yet."); +#endif + } + else if(m_pAppConfig->bDecodeScanImg && !m_bImgSofUnsupported) + { + if(!m_bStateSofOk) + { + m_pLog->AddLineWarn(" NOTE: Scan decode disabled as SOF not decoded."); + } + else if(!m_bStateDqtOk) + { + m_pLog->AddLineWarn(" NOTE: Scan decode disabled as DQT not decoded."); + } + else if(!m_bStateDhtOk) + { + m_pLog->AddLineWarn(" NOTE: Scan decode disabled as DHT not decoded."); + + } + else + { + m_pLog->AddLine(""); + + // Set the primary image details + m_pImgDec->SetImageDetails(m_nSofSampsPerLine_X, m_nSofNumLines_Y, + m_nSofNumComps_Nf, m_nSosNumCompScan_Ns, m_nImgRstEn, m_nImgRstInterval); + + // Only recalculate the scan decoding if we need to (i.e. file + // changed, offset changed, scan option changed) + // TODO: In order to decode multiple scans, we will need to alter the + // way that m_pImgSrcDirty is set + if(m_pImgSrcDirty) + { + m_pImgDec->DecodeScanImg(nPosScanStart, true, false); + m_pImgSrcDirty = false; + } + } + + } + + m_bStateSosOk = true; + + break; + + case JFIF_DRI: + uint32_t nVal; + + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + strTmp = QString(" Length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + nVal = Buf(m_nPos + 2) * 256 + Buf(m_nPos + 3); + + // According to ITU-T spec B.2.4.4, we only expect + // restart markers if DRI value is non-zero! + m_nImgRstInterval = nVal; + if(nVal != 0) + { + m_nImgRstEn = true; + } + else + { + m_nImgRstEn = false; + } + strTmp = QString(" interval = %1").arg(m_nImgRstInterval); + m_pLog->AddLine(strTmp); + m_nPos += 4; + + if(!ExpectMarkerEnd(nPosMarkerStart, nLength)) + return DECMARK_ERR; + + break; + + case JFIF_EOI: // EOI + m_pLog->AddLine(""); + + // Save the EOI file position + // NOTE: If the file is missing the EOI, then this variable will be + // set to mark the end of file. + m_nPosEmbedEnd = m_nPos; + m_nPosEoi = m_nPos; + m_bStateEoi = true; + + return DECMARK_EOI; + + break; + + // Markers that are not yet supported in JPEGsnoop + case JFIF_DHP: + // Markers defined for future use / extensions + case JFIF_JPG: + case JFIF_JPG0: + case JFIF_JPG1: + case JFIF_JPG2: + case JFIF_JPG3: + case JFIF_JPG4: + case JFIF_JPG5: + case JFIF_JPG6: + case JFIF_JPG7: + case JFIF_JPG8: + case JFIF_JPG9: + case JFIF_JPG10: + case JFIF_JPG11: + case JFIF_JPG12: + case JFIF_JPG13: + case JFIF_TEM: + // Unsupported marker + // - Provide generic decode based on length + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); // Length + strTmp = QString(" Header length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + m_pLog->AddLineWarn(" Skipping unsupported marker"); + m_nPos += nLength; + break; + + case JFIF_RST0: + case JFIF_RST1: + case JFIF_RST2: + case JFIF_RST3: + case JFIF_RST4: + case JFIF_RST5: + case JFIF_RST6: + case JFIF_RST7: + // We don't expect to see restart markers outside the entropy coded segment. + // NOTE: RST# are standalone markers, so no length indicator exists + // But for the sake of robustness, we can check here to see if treating + // as a standalone marker will arrive at another marker (ie. OK). If not, + // proceed to assume there is a length indicator. + strTmp = QString(" WARNING: Restart marker [0xFF%1] detected outside scan").arg(nCode, 2, 16, QChar('0')); + m_pLog->AddLineWarn(strTmp); + + if(!m_pAppConfig->bRelaxedParsing) + { + // Abort + m_pLog->AddLineErr(" Stopping decode"); + m_pLog->AddLine(" Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs"); + return DECMARK_ERR; + } + else + { + // Ignore + // Check to see if standalone marker treatment looks OK + if(Buf(m_nPos + 2) == 0xFF) + { + // Looks like standalone + m_pLog->AddLineWarn(" Ignoring standalone marker. Proceeding with decode."); + m_nPos += 2; + } + else + { + // Looks like marker with length + + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + strTmp = QString(" Header length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + m_pLog->AddLineWarn(" Skipping marker"); + m_nPos += nLength; + } + } + break; + + default: + strTmp = QString(" WARNING: Unknown marker [0xFF%1]").arg(nCode, 2, 16, QChar('0')); + m_pLog->AddLineWarn(strTmp); + + if(!m_pAppConfig->bRelaxedParsing) + { + // Abort + m_pLog->AddLineErr(" Stopping decode"); + m_pLog->AddLine(" Use [Img Search Fwd/Rev] to locate other valid embedded JPEGs"); + return DECMARK_ERR; + } + else + { + // Skip + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + strTmp = QString(" Header length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + m_pLog->AddLineWarn(" Skipping marker"); + m_nPos += nLength; + } + } + + // Add white-space between each marker + m_pLog->AddLine(" "); + + // If we decided to abort for any reason, make sure we trap it now. + // This will stop the ProcessFile() while loop. We can set m_bStateAbort + // if user says that they want to stop. + if(m_bStateAbort) + { + return DECMARK_ERR; + } + + return DECMARK_OK; +} + +// Print out a header for the current JFIF marker code +void CjfifDecode::AddHeader(uint32_t nCode) +{ + QString strTmp; + + switch (nCode) + { + case JFIF_SOI: + m_pLog->AddLineHdr("*** Marker: SOI (xFFD8) ***"); + break; + + case JFIF_APP0: + m_pLog->AddLineHdr("*** Marker: APP0 (xFFE0) ***"); + break; + + case JFIF_APP1: + m_pLog->AddLineHdr("*** Marker: APP1 (xFFE1) ***"); + break; + + case JFIF_APP2: + m_pLog->AddLineHdr("*** Marker: APP2 (xFFE2) ***"); + break; + + case JFIF_APP3: + m_pLog->AddLineHdr("*** Marker: APP3 (xFFE3) ***"); + break; + + case JFIF_APP4: + m_pLog->AddLineHdr("*** Marker: APP4 (xFFE4) ***"); + break; + + case JFIF_APP5: + m_pLog->AddLineHdr("*** Marker: APP5 (xFFE5) ***"); + break; + + case JFIF_APP6: + m_pLog->AddLineHdr("*** Marker: APP6 (xFFE6) ***"); + break; + + case JFIF_APP7: + m_pLog->AddLineHdr("*** Marker: APP7 (xFFE7) ***"); + break; + + case JFIF_APP8: + m_pLog->AddLineHdr("*** Marker: APP8 (xFFE8) ***"); + break; + + case JFIF_APP9: + m_pLog->AddLineHdr("*** Marker: APP9 (xFFE9) ***"); + break; + + case JFIF_APP10: + m_pLog->AddLineHdr("*** Marker: APP10 (xFFEA) ***"); + break; + + case JFIF_APP11: + m_pLog->AddLineHdr("*** Marker: APP11 (xFFEB) ***"); + break; + + case JFIF_APP12: + m_pLog->AddLineHdr("*** Marker: APP12 (xFFEC) ***"); + break; + + case JFIF_APP13: + m_pLog->AddLineHdr("*** Marker: APP13 (xFFED) ***"); + break; + + case JFIF_APP14: + m_pLog->AddLineHdr("*** Marker: APP14 (xFFEE) ***"); + break; + + case JFIF_APP15: + m_pLog->AddLineHdr("*** Marker: APP15 (xFFEF) ***"); + break; + + case JFIF_SOF0: + m_pLog->AddLineHdr("*** Marker: SOF0 (Baseline DCT) (xFFC0) ***"); + break; + + case JFIF_SOF1: + m_pLog->AddLineHdr("*** Marker: SOF1 (Extended Sequential DCT, Huffman) (xFFC1) ***"); + break; + + case JFIF_SOF2: + m_pLog->AddLineHdr("*** Marker: SOF2 (Progressive DCT, Huffman) (xFFC2) ***"); + break; + + case JFIF_SOF3: + m_pLog->AddLineHdr("*** Marker: SOF3 (Lossless Process, Huffman) (xFFC3) ***"); + break; + + case JFIF_SOF5: + m_pLog->AddLineHdr("*** Marker: SOF5 (Differential Sequential DCT, Huffman) (xFFC4) ***"); + break; + + case JFIF_SOF6: + m_pLog->AddLineHdr("*** Marker: SOF6 (Differential Progressive DCT, Huffman) (xFFC5) ***"); + break; + + case JFIF_SOF7: + m_pLog->AddLineHdr("*** Marker: SOF7 (Differential Lossless Process, Huffman) (xFFC6) ***"); + break; + + case JFIF_SOF9: + m_pLog->AddLineHdr("*** Marker: SOF9 (Sequential DCT, Arithmetic) (xFFC9) ***"); + break; + + case JFIF_SOF10: + m_pLog->AddLineHdr("*** Marker: SOF10 (Progressive DCT, Arithmetic) (xFFCA) ***"); + break; + + case JFIF_SOF11: + m_pLog->AddLineHdr("*** Marker: SOF11 (Lossless Process, Arithmetic) (xFFCB) ***"); + break; + + case JFIF_SOF13: + m_pLog->AddLineHdr("*** Marker: SOF13 (Differential Sequential, Arithmetic) (xFFCD) ***"); + break; + + case JFIF_SOF14: + m_pLog->AddLineHdr("*** Marker: SOF14 (Differential Progressive DCT, Arithmetic) (xFFCE) ***"); + break; + + case JFIF_SOF15: + m_pLog->AddLineHdr("*** Marker: SOF15 (Differential Lossless Process, Arithmetic) (xFFCF) ***"); + break; + + case JFIF_JPG: + m_pLog->AddLineHdr("*** Marker: JPG (xFFC8) ***"); + break; + + case JFIF_DAC: + m_pLog->AddLineHdr("*** Marker: DAC (xFFCC) ***"); + break; + + case JFIF_RST0: + case JFIF_RST1: + case JFIF_RST2: + case JFIF_RST3: + case JFIF_RST4: + case JFIF_RST5: + case JFIF_RST6: + case JFIF_RST7: + m_pLog->AddLineHdr("*** Marker: RST# ***"); + break; + + case JFIF_DQT: // Define quantization tables + m_pLog->AddLineHdr("*** Marker: DQT (xFFDB) ***"); + m_pLog->AddLineHdrDesc(" Define a Quantization Table."); + break; + + case JFIF_COM: // COM + m_pLog->AddLineHdr("*** Marker: COM (Comment) (xFFFE) ***"); + break; + + case JFIF_DHT: // DHT + m_pLog->AddLineHdr("*** Marker: DHT (Define Huffman Table) (xFFC4) ***"); + break; + + case JFIF_DHT_FAKE: // DHT from standard table (MotionJPEG) + m_pLog->AddLineHdr("*** Marker: DHT from MotionJPEG standard (Define Huffman Table) ***"); + break; + + case JFIF_SOS: // SOS + m_pLog->AddLineHdr("*** Marker: SOS (Start of Scan) (xFFDA) ***"); + break; + + case JFIF_DRI: // DRI + m_pLog->AddLineHdr("*** Marker: DRI (Restart Interval) (xFFDD) ***"); + break; + + case JFIF_EOI: // EOI + m_pLog->AddLineHdr("*** Marker: EOI (End of Image) (xFFD9) ***"); + break; + + case JFIF_DNL: + m_pLog->AddLineHdr("*** Marker: DNL (Define Number of Lines) (xFFDC) ***"); + break; + case JFIF_DHP: + m_pLog->AddLineHdr("*** Marker: DHP (Define Hierarchical Progression) (xFFDE) ***"); + break; + case JFIF_EXP: + m_pLog->AddLineHdr("*** Marker: EXP (Expand Reference Components) (xFFDF) ***"); + break; + case JFIF_JPG0: + m_pLog->AddLineHdr("*** Marker: JPG0 (JPEG Extension) (xFFF0) ***"); + break; + case JFIF_JPG1: + m_pLog->AddLineHdr("*** Marker: JPG1 (JPEG Extension) (xFFF1) ***"); + break; + case JFIF_JPG2: + m_pLog->AddLineHdr("*** Marker: JPG2 (JPEG Extension) (xFFF2) ***"); + break; + case JFIF_JPG3: + m_pLog->AddLineHdr("*** Marker: JPG3 (JPEG Extension) (xFFF3) ***"); + break; + case JFIF_JPG4: + m_pLog->AddLineHdr("*** Marker: JPG4 (JPEG Extension) (xFFF4) ***"); + break; + case JFIF_JPG5: + m_pLog->AddLineHdr("*** Marker: JPG5 (JPEG Extension) (xFFF5) ***"); + break; + case JFIF_JPG6: + m_pLog->AddLineHdr("*** Marker: JPG6 (JPEG Extension) (xFFF6) ***"); + break; + case JFIF_JPG7: + m_pLog->AddLineHdr("*** Marker: JPG7 (JPEG Extension) (xFFF7) ***"); + break; + case JFIF_JPG8: + m_pLog->AddLineHdr("*** Marker: JPG8 (JPEG Extension) (xFFF8) ***"); + break; + case JFIF_JPG9: + m_pLog->AddLineHdr("*** Marker: JPG9 (JPEG Extension) (xFFF9) ***"); + break; + case JFIF_JPG10: + m_pLog->AddLineHdr("*** Marker: JPG10 (JPEG Extension) (xFFFA) ***"); + break; + case JFIF_JPG11: + m_pLog->AddLineHdr("*** Marker: JPG11 (JPEG Extension) (xFFFB) ***"); + break; + case JFIF_JPG12: + m_pLog->AddLineHdr("*** Marker: JPG12 (JPEG Extension) (xFFFC) ***"); + break; + case JFIF_JPG13: + m_pLog->AddLineHdr("*** Marker: JPG13 (JPEG Extension) (xFFFD) ***"); + break; + case JFIF_TEM: + m_pLog->AddLineHdr("*** Marker: TEM (Temporary) (xFF01) ***"); + break; + + default: + strTmp = QString("*** Marker: ??? (Unknown) (xFF%1) ***").arg(nCode, 2, 16, QChar('0')); + m_pLog->AddLineHdr(strTmp); + break; + } + + // Adjust position to account for the word used in decoding the marker! + strTmp = QString(" OFFSET: 0x%1").arg(m_nPos - 2, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); +} + +// Update the status bar with a message +void CjfifDecode::SetStatusText(QString strText) +{ + // Make sure that we have been connected to the status + // bar of the main window first! Note that it is jpegsnoopDoc + // that sets this variable. +// if(m_pStatBar) +// { +// m_pStatBar->showMessage(strText); +// } + + emit(strText, 0); + QCoreApplication::processEvents(); + qDebug() << strText; +} + +// Generate a special output form of the current image's +// compression signature and other characteristics. This is only +// used during development and batch import to build the MySQL repository. +void CjfifDecode::OutputSpecial() +{ + QString strTmp; + QString strFull; + + Q_ASSERT(m_eImgLandscape != ENUM_LANDSCAPE_UNSET); + + // This mode of operation is currently only used + // to import the local signature database into a MySQL database + // backend. It simply reports the MySQL commands which can be input + // into a MySQL client application. + if(m_bOutputDB) + { + m_pLog->AddLine("*** DB OUTPUT START ***"); + m_pLog->AddLine("INSERT INTO `quant` (`key`, `make`, `model`, "); + m_pLog->AddLine("`qual`, `subsamp`, `lum_00`, `lum_01`, `lum_02`, `lum_03`, `lum_04`, "); + m_pLog->AddLine("`lum_05`, `lum_06`, `lum_07`, `chr_00`, `chr_01`, `chr_02`, "); + m_pLog->AddLine("`chr_03`, `chr_04`, `chr_05`, `chr_06`, `chr_07`, `qual_lum`, `qual_chr`) VALUES ("); + + strFull = "'*KEY*', "; // key -- need to override + + // Might need to change m_strImgExifMake to be lowercase + strTmp = QString("'%1', ").arg(m_strImgExifMake); + strFull += strTmp; // make + + strTmp = QString("'%1', ").arg(m_strImgExifModel); + strFull += strTmp; // model + + strTmp = QString("'%1', ").arg(m_strImgQualExif); + strFull += strTmp; // quality + + strTmp = QString("'%1', ").arg(m_strImgQuantCss); + strFull += strTmp; // subsampling + + m_pLog->AddLine(strFull); + + // Step through both quantization tables (0=lum,1=chr) + uint32_t nMatrixInd; + + for(uint32_t nDqtInd = 0; nDqtInd < 2; nDqtInd++) + { + + strFull = ""; + for(uint32_t nY = 0; nY < 8; nY++) + { + strFull += "'"; + for(uint32_t nX = 0; nX < 8; nX++) + { + // Rotate the matrix if necessary! + nMatrixInd = (m_eImgLandscape != ENUM_LANDSCAPE_NO) ? (nY * 8 + nX) : (nX * 8 + nY); + strTmp = QString("%1").arg(m_anImgDqtTbl[nDqtInd][nMatrixInd]); + strFull += strTmp; + if(nX != 7) + { + strFull += ","; + } + } + strFull += "', "; + if(nY == 3) + { + m_pLog->AddLine(strFull); + strFull = ""; + } + } + m_pLog->AddLine(strFull); + + } + + strFull = ""; + // Output quality ratings + strTmp = QString("'%1', ").arg(m_adImgDqtQual[0]); + strFull += strTmp; + // Don't put out comma separator on last line! + strTmp = QString("'%1'").arg(m_adImgDqtQual[1]); + strFull += strTmp; + strFull += ");"; + m_pLog->AddLine(strFull); + + m_pLog->AddLine("*** DB OUTPUT END ***"); + } + +} + +// Generate the compression signatures (both unrotated and +// rotated) in advance of submitting to the database. +void CjfifDecode::PrepareSignature() +{ + // Set m_strHash + PrepareSignatureSingle(false); + // Set m_strHashRot + PrepareSignatureSingle(true); +} + +// Prepare the image signature for later submission +// NOTE: ASCII vars are used (instead of unicode) to support usage of MD5 library +void CjfifDecode::PrepareSignatureSingle(bool bRotate) +{ + QString strTmp; + QString strSet; + QString strHashIn; + +// unsigned char pHashIn[2000]; + unsigned char *pHashIn; + + QString strDqt; + + MD5_CTX sMd5; + + int32_t nLenHashIn; + uint32_t nInd; + + Q_ASSERT(m_eImgLandscape != ENUM_LANDSCAPE_UNSET); + + pHashIn = new unsigned char[2000]; + // ----------------------------------------------------------- + // Calculate the MD5 hash for online/internal database! + // signature "00" : DQT0,DQT1,CSS + // signature "01" : salt,DQT0,DQT1,..DQTx(if defined) + + // Build the source string + // NOTE: For the purposes of the hash, we need to rotate the DQT tables + // if we detect that the photo is in portrait orientation! This keeps everything consistent. + + // If no DQT tables have been defined (e.g. could have loaded text file!) then override the sig generation! + bool bDqtDefined = false; + + for(uint32_t nSet = 0; nSet < 4; nSet++) + { + if(m_abImgDqtSet[nSet]) + { + bDqtDefined = true; + } + } + + if(!bDqtDefined) + { + m_strHash = "NONE"; + m_strHashRot = "NONE"; + return; + } + + // NOTE: + // The following MD5 code depends on an ASCII string for input + // We are therefore using QStringA for the hash input instead + // of the generic text functions. No special (non-ASCII) + // characters are expected in this string. + + if(DB_SIG_VER == 0x00) + { + strHashIn = ""; + } + else + { + strHashIn = "JPEGsnoop"; + } + + // Need to duplicate DQT0 if we only have one DQT table + for(uint32_t nSet = 0; nSet < 4; nSet++) + { + if(m_abImgDqtSet[nSet]) + { + strSet = ""; + strSet = QString("*DQT%1,").arg(nSet); + strHashIn += strSet; + + for(uint32_t i = 0; i < 64; i++) + { + nInd = (!bRotate) ? i : glb_anQuantRotate[i]; + strTmp = QString("%1,").arg(m_anImgDqtTbl[nSet][nInd], 3, 10, QChar('0')); + strHashIn += strTmp; + } + } // if DQTx defined + } // loop through sets (DQT0..DQT3) + + // Removed CSS from signature after version 0x00 + if(DB_SIG_VER == 0x00) + { + strHashIn += "*CSS,"; + strHashIn += m_strImgQuantCss; + strHashIn += ","; + } + + strHashIn += "*END"; + nLenHashIn = strHashIn.length(); + + // Display hash input + for(int32_t i = 0; i < nLenHashIn; i += 80) + { + strTmp = ""; + strTmp = QString("In%1: [").arg(i / 80); + strTmp += strHashIn.mid(i, 80); + strTmp += "]"; +#ifdef DEBUG_SIG + m_pLog->AddLine(strTmp); +#endif + } + + // Copy into buffer + Q_ASSERT(nLenHashIn < 2000); + + for(int32_t i = 0; i < nLenHashIn; i++) + { + pHashIn[i] = strHashIn[i].toLatin1(); + } + + // Calculate the hash + MD5Init(&sMd5, 0); + MD5Update(&sMd5, pHashIn, nLenHashIn); + MD5Final(&sMd5); + + // Overwrite top 8 bits for signature version number + sMd5.digest32[0] = (sMd5.digest32[0] & 0x00FFFFFF) + (DB_SIG_VER << 24); + + // Convert hash to string format + // The hexadecimal string is converted to Unicode (if that is build directive) + if(!bRotate) + { + m_strHash = QString("%1%2%3%4") + .arg(sMd5.digest32[0], 8, 16, QChar('0')) + .arg(sMd5.digest32[1], 8, 16, QChar('0')) + .arg(sMd5.digest32[2], 8, 16, QChar('0')) + .arg(sMd5.digest32[3], 8, 16, QChar('0')); + m_strHash = m_strHash.toUpper(); + } + else + { + m_strHashRot = QString("%1%2%3%4") + .arg(sMd5.digest32[0], 8, 16, QChar('0')) + .arg(sMd5.digest32[1], 8, 16, QChar('0')) + .arg(sMd5.digest32[2], 8, 16, QChar('0')) + .arg(sMd5.digest32[3], 8, 16, QChar('0')); + m_strHashRot = m_strHashRot.toUpper(); + } + +// QByteArray in(reinterpret_cast(pHashIn), nLenHashIn); +// m_strHash = QCryptographicHash::hash(reinterpret_cast(pHashIn), QCryptographicHash::Md5).toHex(); +} + + +// Generate the compression signatures for the thumbnails +void CjfifDecode::PrepareSignatureThumb() +{ + // Generate m_strHashThumb + PrepareSignatureThumbSingle(false); + // Generate m_strHashThumbRot + PrepareSignatureThumbSingle(true); +} + +// Prepare the image signature for later submission +// NOTE: ASCII vars are used (instead of unicode) to support usage of MD5 library +void CjfifDecode::PrepareSignatureThumbSingle(bool bRotate) +{ + QString strTmp; + QString strSet; + QString strHashIn; + + unsigned char pHashIn[2000]; + + QString strDqt; + + MD5_CTX sMd5; + + int32_t nLenHashIn; + uint32_t nInd; + + // ----------------------------------------------------------- + // Calculate the MD5 hash for online/internal database! + // signature "00" : DQT0,DQT1,CSS + // signature "01" : salt,DQT0,DQT1 + + // Build the source string + // NOTE: For the purposes of the hash, we need to rotate the DQT tables + // if we detect that the photo is in portrait orientation! This keeps everything + // consistent. + + // If no DQT tables have been defined (e.g. could have loaded text file!) + // then override the sig generation! + bool bDqtDefined = false; + + for(uint32_t nSet = 0; nSet < 4; nSet++) + { + if(m_abImgDqtThumbSet[nSet]) + { + bDqtDefined = true; + } + } + if(!bDqtDefined) + { + m_strHashThumb = "NONE"; + m_strHashThumbRot = "NONE"; + return; + } + + if(DB_SIG_VER == 0x00) + { + strHashIn = ""; + } + else + { + strHashIn = "JPEGsnoop"; + } + + //tblSelY = m_anSofQuantTblSel_Tqi[0]; // Y + //tblSelC = m_anSofQuantTblSel_Tqi[1]; // Cb (should be same as for Cr) + + // Need to duplicate DQT0 if we only have one DQT table + + for(uint32_t nSet = 0; nSet < 4; nSet++) + { + if(m_abImgDqtThumbSet[nSet]) + { + strSet = ""; + strSet = QString("*DQT%1,").arg(nSet); + strHashIn += strSet; + + for(uint32_t i = 0; i < 64; i++) + { + nInd = (!bRotate) ? i : glb_anQuantRotate[i]; + strTmp = QString("%1,").arg(m_anImgThumbDqt[nSet][nInd], 3, 10, QChar('0')); + strHashIn += strTmp; + } + } // if DQTx defined + } // loop through sets (DQT0..DQT3) + + // Removed CSS from signature after version 0x00 + if(DB_SIG_VER == 0x00) + { + strHashIn += "*CSS,"; + strHashIn += m_strImgQuantCss; + strHashIn += ","; + } + + strHashIn += "*END"; + nLenHashIn = strHashIn.length(); + +// qDebug() << "Hash" << strHashIn << strHashIn.length() << strHashIn.toLatin1(); +// QByteArray s; +// s = QCryptographicHash::hash(strHashIn.toLatin1(), QCryptographicHash::Md5); +// qDebug() << s; + + // Display hash input + for(int32_t i = 0; i < nLenHashIn; i += 80) + { + strTmp = ""; + strTmp = QString("In%1: [").arg(i / 80); + strTmp += strHashIn.mid(i, 80); + strTmp += "]"; +#ifdef DEBUG_SIG + //m_pLog->AddLine(strTmp); +#endif + } + + // Copy into buffer + Q_ASSERT(nLenHashIn < 2000); + + for(int32_t i = 0; i < nLenHashIn; i++) + { + pHashIn[i] = strHashIn[i].toLatin1(); + } + + // Calculate the hash + MD5Init(&sMd5, 0); + MD5Update(&sMd5, pHashIn, nLenHashIn); + MD5Final(&sMd5); + + // Overwrite top 8 bits for signature version number + sMd5.digest32[0] = (sMd5.digest32[0] & 0x00FFFFFF) + (DB_SIG_VER << 24); + + // Convert hash to string format + if(!bRotate) + { + m_strHashThumb = + QString("%1%2%3%4") + .arg(sMd5.digest32[0], 8, 16, QChar('0')) + .arg(sMd5.digest32[1], 8, 16, QChar('0')) + .arg(sMd5.digest32[2], 8, 16, QChar('0')) + .arg(sMd5.digest32[3], 8, 16, QChar('0')); + } + else + { + m_strHashThumbRot = + QString("%1%2%3%4") + .arg(sMd5.digest32[0], 8, 16, QChar('0')) + .arg(sMd5.digest32[1], 8, 16, QChar('0')) + .arg(sMd5.digest32[2], 8, 16, QChar('0')) + .arg(sMd5.digest32[3], 8, 16, QChar('0')); + } + +} + +// Compare the image compression signature & metadata against the database. +// This is the routine that is also responsible for creating an +// "Image Assessment" -- ie. whether the image may have been edited or not. +// +// PRE: m_strHash signature has already been calculated by PrepareSignature() +bool CjfifDecode::CompareSignature(bool bQuiet = false) +{ + QString strTmp; + QString strHashOut; + QString locationStr; + + uint32_t ind; + + bool bCurXsw = false; + bool bCurXmm = false; + bool bCurXmkr = false; + bool bCurXextrasw = false; // EXIF Extra fields match software indicator + bool bCurXcomsw = false; // EXIF COM field match software indicator + bool bCurXps = false; // EXIF photoshop IRB present + bool bSrchXsw = false; + bool bSrchXswUsig = false; + bool bSrchXmmUsig = false; + bool bSrchUsig = false; + bool bMatchIjg = false; + + QString sMatchIjgQual = ""; + + Q_ASSERT(m_strHash != "NONE"); + Q_ASSERT(m_strHashRot != "NONE"); + + if(bQuiet) + { + m_pLog->Disable(); + } + + m_pLog->AddLine(""); + m_pLog->AddLineHdr("*** Searching Compression Signatures ***"); + m_pLog->AddLine(""); + + // Output the hash + strHashOut = " Signature: "; + strHashOut += m_strHash; + m_pLog->AddLine(strHashOut); + strHashOut = " Signature (Rotated): "; + strHashOut += m_strHashRot; + m_pLog->AddLine(strHashOut); + + strTmp = QString(" File Offset: %1 bytes").arg(m_pAppConfig->nPosStart, 1); + m_pLog->AddLine(strTmp); + + // Output the CSS + strTmp = QString(" Chroma subsampling: %1").arg(m_strImgQuantCss); + m_pLog->AddLine(strTmp); + + // Calculate the final fields + // Add Photoshop IRB entries + // Note that we always add an entry to the m_strImgExtras even if + // there are no photoshop tags detected. It will appear as "[PS]:[0/0]" + strTmp = ""; + strTmp = QString("[PS]:[%1/%2],").arg(m_nImgQualPhotoshopSa).arg(m_nImgQualPhotoshopSfw); + m_strImgExtras += strTmp; + + // -------------------------------------- + // Determine current entry fields + + // Note that some cameras/phones have an empty Make, but use the Model! (eg. Palm Treo) + if((m_strImgExifMake == "???") && (m_strImgExifModel == "???")) + { + m_pLog->AddLine(" EXIF Make/Model: NONE"); + bCurXmm = false; + } + else + { + strTmp = QString(" EXIF Make/Model: OK [%1] [%2]").arg(m_strImgExifMake).arg(m_strImgExifModel); + m_pLog->AddLine(strTmp); + bCurXmm = true; + } + + if(m_bImgExifMakernotes) + { + m_pLog->AddLine(" EXIF Makernotes: OK "); + bCurXmkr = true; + } + else + { + m_pLog->AddLine(" EXIF Makernotes: NONE"); + bCurXmkr = false; + } + + if(m_strSoftware.length() == 0) + { + m_pLog->AddLine(" EXIF Software: NONE"); + bCurXsw = false; + } + else + { + strTmp = QString(" EXIF Software: OK [%1]").arg(m_strSoftware); + m_pLog->AddLine(strTmp); + + // EXIF software field is non-empty + bCurXsw = true; + } + + m_pLog->AddLine(""); + + // -------------------------------------- + // Determine search results + + // All of the rest of the search results require searching + // through the database entries + + bSrchXswUsig = false; + bSrchXmmUsig = false; + bSrchUsig = false; + bMatchIjg = false; + sMatchIjgQual = ""; + + uint32_t nSigsInternal = m_pDbSigs->GetNumSigsInternal(); + + uint32_t nSigsExtra = m_pDbSigs->GetNumSigsExtra(); + + strTmp = QString(" Searching Compression Signatures: (%1 built-in, %2 user(*) )").arg(nSigsInternal).arg(nSigsExtra); + m_pLog->AddLine(strTmp); + + // Now in SIG version 0x01 and later, we are not including + // the CSS in the signature. Therefore, we need to compare it + // manually. + + bool curMatchMm; + bool curMatchSw; + bool curMatchSig; + bool curMatchSigCss; + + // Check on Extras field + // Noted that Canon EOS Viewer Utility (EVU) seems to convert RAWs with + // the only identifying information being this: + // e.g. "[Canon.ImageType]:[CRW:EOS 300D DIGITAL CMOS RAW],_T(" + if(m_strImgExtras.contains("[Canon.ImageType]:[CRW:")) + { + bCurXextrasw = true; + } + + if(m_strImgExtras.contains("[Nikon1.Quality]:[RAW")) + { + bCurXextrasw = true; + } + + if(m_strImgExtras.contains("[Nikon2.Quality]:[RAW")) + { + bCurXextrasw = true; + } + + if(m_strImgExtras.contains("[Nikon3.Quality]:[RAW")) + { + bCurXextrasw = true; + } + + if((m_nImgQualPhotoshopSa != 0) || (m_nImgQualPhotoshopSfw != 0)) + { + bCurXps = true; + } + + // Search for known COMment field indicators + if(m_pDbSigs->SearchCom(m_strComment)) + { + bCurXcomsw = true; + } + + m_pLog->AddLine(""); + m_pLog->AddLine(" EXIF.Make / Software EXIF.Model Quality Subsamp Match?"); + m_pLog->AddLine(" ------------------------- ----------------------------------- ---------------- --------------"); + + CompSig pEntry; + + uint32_t ind_max = m_pDbSigs->GetDBNumEntries(); + + for(ind = 0; ind < ind_max; ind++) + { + m_pDbSigs->GetDBEntry(ind, &pEntry); + + // Reset current entry state + curMatchMm = false; + curMatchSw = false; + curMatchSig = false; + curMatchSigCss = false; + + // Compare make/model (only for digicams) + if((pEntry.eEditor == ENUM_EDITOR_CAM) && + (bCurXmm == true) && (pEntry.strXMake == m_strImgExifMake) && (pEntry.strXModel == m_strImgExifModel)) + { + curMatchMm = true; + } + + // For software entries, do a loose search + if((pEntry.eEditor == ENUM_EDITOR_SW) && + (bCurXsw == true) && (pEntry.strMSwTrim != "") && (m_strSoftware.indexOf(pEntry.strMSwTrim) != -1)) + { + // Software field matches known software string + bSrchXsw = true; + curMatchSw = true; + } + + // Compare signature (and CSS for digicams) + if((pEntry.strCSig == m_strHash) || (pEntry.strCSigRot == m_strHash) || + (pEntry.strCSig == m_strHashRot) || (pEntry.strCSigRot == m_strHashRot)) + { + curMatchSig = true; + + // If Database entry is for an editor, sig matches irrespective of CSS + if(pEntry.eEditor == ENUM_EDITOR_SW) + { + bSrchUsig = true; + curMatchSigCss = true; // FIXME: do I need this? + + // For special case of IJG + if(pEntry.strMSwDisp == "IJG Library") + { + bMatchIjg = true; + sMatchIjgQual = pEntry.strUmQual; + } + } + else + { + // Database entry is for a digicam, sig match only if CSS matches too + if(pEntry.strXSubsamp == m_strImgQuantCss) + { + bSrchUsig = true; + curMatchSigCss = true; + } + else + { + curMatchSigCss = false; + } + } // editor + } + else + { + // sig doesn't match + curMatchSig = false; + curMatchSigCss = false; + } + + // For digicams: + if(curMatchMm && curMatchSigCss) + { + bSrchXmmUsig = true; + } + + // For software: + if(curMatchSw && curMatchSig) + { + bSrchXswUsig = true; + } + + if(m_pDbSigs->IsDBEntryUser(ind)) + { + locationStr = "*"; + } + else + { + locationStr = " "; + } + + // Display entry if it is a good match + if(curMatchSig) + { + if(pEntry.eEditor == ENUM_EDITOR_CAM) + { + strTmp = + QString(" %1%2[%3] [%4] [%5] %6 %7 %8") + .arg(locationStr) + .arg("CAM:", 4) + .arg(pEntry.strXMake.left(25), -25) + .arg(pEntry.strXModel.left(35), -35) + .arg(pEntry.strUmQual.left(16), -16) + .arg(curMatchSigCss ? "Yes" : "No", -5) + .arg("", -5) + .arg("", -5); + } + else if(pEntry.eEditor == ENUM_EDITOR_SW) + { + strTmp = + QString(" %1%2[%3] [%4] [%5] %6 %7 %8") + .arg(locationStr) + .arg("SW :", 4) + .arg(pEntry.strMSwDisp.left(25), -25) + .arg("", -35) + .arg(pEntry.strUmQual.left(16), -16) + .arg("", -5) + .arg("", -5) + .arg("", -5); + } + else + { + strTmp = + QString(" %1%2[%3] [%4] [%5] %6 %7 %8") + .arg(locationStr) + .arg("?? :", 4) + .arg(pEntry.strXMake.left(25), -25) + .arg(pEntry.strXModel.left(35), -35) + .arg(pEntry.strUmQual.left(16), -16) + .arg("", -5) + .arg("", -5) + .arg("", -5); + } + + if(curMatchMm || curMatchSw) + { + m_pLog->AddLineGood(strTmp); + } + else + { + m_pLog->AddLine(strTmp); + } + } + } // loop through DB + + QString strSw; + + // If it matches an IJG signature, report other possible sources: + if(bMatchIjg) + { + m_pLog->AddLine(""); + m_pLog->AddLine(" The following IJG-based editors also match this signature:"); + uint32_t nIjgNum; + + QString strIjgSw; + + nIjgNum = m_pDbSigs->GetIjgNum(); + for(ind = 0; ind < nIjgNum; ind++) + { + strIjgSw = m_pDbSigs->GetIjgEntry(ind); + strTmp = + QString(" %1[%2] %3 [%4] %5 %6 %7") + .arg("SW :", 4) + .arg(strIjgSw.left(25), -25) + .arg("", -35) + .arg(sMatchIjgQual.left(16), -16) + .arg("", -5) + .arg("", -5) + .arg("", -5); + m_pLog->AddLine(strTmp); + } + } + + //m_pLog->AddLine(" -------------------- ----------------------------------- ---------------- --------------"); + m_pLog->AddLine(""); + + if(bCurXps) + { + m_pLog->AddLine(" NOTE: Photoshop IRB detected"); + } + if(bCurXextrasw) + { + m_pLog->AddLine(" NOTE: Additional EXIF fields indicate software processing"); + } + if(bSrchXsw) + { + m_pLog->AddLine(" NOTE: EXIF Software field recognized as from editor"); + } + if(bCurXcomsw) + { + m_pLog->AddLine(" NOTE: JFIF COMMENT field is known software"); + } + + // ============================================ + // Image Assessment Algorithm + // ============================================ + + bool bEditDefinite = false; + + bool bEditLikely = false; + + bool bEditNot = false; + + bool bEditNotUnknownSw = false; + + if(bCurXps) + { + bEditDefinite = true; + } + if(!bCurXmm) + { + bEditDefinite = true; + } + if(bCurXextrasw) + { + bEditDefinite = true; + } + if(bCurXcomsw) + { + bEditDefinite = true; + } + if(bSrchXsw) + { + // Software field matches known software string + bEditDefinite = true; + } + if(m_pDbSigs->LookupExcMmIsEdit(m_strImgExifMake, m_strImgExifModel)) + { + // Make/Model is in exception list of ones that mark known software + bEditDefinite = true; + } + + if(!bCurXmkr) + { + // If we are missing maker notes, we are almost always dealing with + // edited images. There are some known exceptions, so far: + // - Very old digicams + // - Certain camera phones + // - Blackberry + // Perhaps we can make an exception for particular digicams (based on + // make/model) that this determination will not apply. This means that + // we open up the doors for these files being edited and not caught. + + if(m_pDbSigs->LookupExcMmNoMkr(m_strImgExifMake, m_strImgExifModel)) + { + // This is a known exception! + } + else + { + bEditLikely = true; + } + } + + // Filter down remaining scenarios + if(!bEditDefinite && !bEditLikely) + { + + if(bSrchXmmUsig) + { + // DB cam signature matches DQT & make/model + if(!bCurXsw) + { + // EXIF software field is empty + // + // We can now be pretty confident that this file has not + // been edited by all the means that we are checking + bEditNot = true; + } + else + { + // EXIF software field is set + // + // This field is often used by: + // - Software editors (edited) + // - RAW converter software (edited) + // - Digicams to indicate firmware (original) + // - Phones to indicate firmware (original) + // + // However, in generating bEditDefinite, we have already + // checked for bSrchXsw which looked for known software + // strings. Therefore, we will primarily be left with + // firmware strings, etc. + // + // We will mark this as NOT EDITED but with caution of unknown SW field + bEditNot = true; + bEditNotUnknownSw = true; + } + } + else + { + // No DB cam signature matches DQT & make/model + // According to EXIF data, this file does not appear to be edited, + // but no compression signatures in the database match this + // particular make/model. Therefore, result is UNSURE. + } + + } + + // Now make final assessment call + + // Determine if image has been processed/edited + m_eImgEdited = EDITED_UNSET; + if(bEditDefinite) + { + m_eImgEdited = EDITED_YES; + } + else if(bEditLikely) + { + m_eImgEdited = EDITED_YESPROB; + } + else if(bEditNot) + { + // Images that fall into this category will have: + // - No Photoshop tags + // - Make/Model is present + // - Makernotes present + // - No extra software tags (eg. IFD) + // - No comment field with known software + // - No software field or it does not match known software + // - Signature matches DB for this make/model + m_eImgEdited = EDITED_NO; + } + else + { + // Images that fall into this category will have: + // - Same as EDITED_NO but: + // - Signature does not match DB for this make/model + // In all likelihood, this image will in fact be original + m_eImgEdited = EDITED_UNSURE; + } + + // If the file offset is non-zero, then don't ask for submit or show assessment + if(m_pAppConfig->nPosStart != 0) + { + m_pLog->AddLine(" ASSESSMENT not done as file offset non-zero"); + if(bQuiet) + { + m_pLog->Enable(); + } + return false; + } + + // ============================================ + // Display final assessment + // ============================================ + + m_pLog->AddLine(" Based on the analysis of compression characteristics and EXIF metadata:"); + m_pLog->AddLine(""); + if(m_eImgEdited == EDITED_YES) + { + m_pLog->AddLine(" ASSESSMENT: Class 1 - Image is processed/edited"); + } + else if(m_eImgEdited == EDITED_YESPROB) + { + m_pLog->AddLine(" ASSESSMENT: Class 2 - Image has high probability of being processed/edited"); + } + else if(m_eImgEdited == EDITED_NO) + { + m_pLog->AddLine(" ASSESSMENT: Class 3 - Image has high probability of being original"); + // In case the EXIF Software field was detected, + if(bEditNotUnknownSw) + { + m_pLog->AddLine(" Note that EXIF Software field is set (typically contains Firmware version)"); + } + } + else if(m_eImgEdited == EDITED_UNSURE) + { + m_pLog->AddLine(" ASSESSMENT: Class 4 - Uncertain if processed or original"); + m_pLog->AddLine(" While the EXIF fields indicate original, no compression signatures "); + m_pLog->AddLine(" in the current database were found matching this make/model"); + } + else + { + m_pLog->AddLineErr(" ASSESSMENT: *** Failed to complete ***"); + } + m_pLog->AddLine(""); + + // Determine if user should add entry to DB + bool bDbReqAdd = false; // Ask user to add + + bool bDbReqAddAuto = false; // Automatically add (in batch operation) + + // TODO: This section should be rewritten to reduce complexity + + m_eDbReqSuggest = DB_ADD_SUGGEST_UNSET; + if(m_eImgEdited == EDITED_NO) + { + bDbReqAdd = false; + m_eDbReqSuggest = DB_ADD_SUGGEST_CAM; + } + else if(m_eImgEdited == EDITED_UNSURE) + { + bDbReqAdd = true; + bDbReqAddAuto = true; + m_eDbReqSuggest = DB_ADD_SUGGEST_CAM; + m_pLog->AddLine(" Appears to be new signature for known camera."); + m_pLog->AddLine(" If the camera/software doesn't appear in list above,"); + m_pLog->AddLineWarn(" PLEASE ADD TO DATABASE with [Tools->Add Camera to DB]"); + } + else if(bCurXps && bSrchUsig) + { + // Photoshop and we already have sig + bDbReqAdd = false; + m_eDbReqSuggest = DB_ADD_SUGGEST_SW; + } + else if(bCurXps && !bSrchUsig) + { + // Photoshop and we don't already have sig + bDbReqAdd = true; + bDbReqAddAuto = true; + m_eDbReqSuggest = DB_ADD_SUGGEST_SW; + m_pLog->AddLine(" Appears to be new signature for Photoshop."); + m_pLog->AddLine(" If it doesn't appear in list above,"); + m_pLog->AddLineWarn(" PLEASE ADD TO DATABASE with [Tools->Add Camera to DB]"); + } + else if(bCurXsw && bSrchXsw && bSrchXswUsig) + { + bDbReqAdd = false; + m_eDbReqSuggest = DB_ADD_SUGGEST_SW; + } + else if(bCurXextrasw) + { + bDbReqAdd = false; + m_eDbReqSuggest = DB_ADD_SUGGEST_SW; + } + else if(bCurXsw && bSrchXsw && !bSrchXswUsig) + { + bDbReqAdd = true; + //bDbReqAddAuto = true; + m_eDbReqSuggest = DB_ADD_SUGGEST_SW; + m_pLog->AddLine(" Appears to be new signature for known software."); + m_pLog->AddLine(" If the camera/software doesn't appear in list above,"); + m_pLog->AddLineWarn(" PLEASE ADD TO DATABASE with [Tools->Add Camera to DB]"); + } + else if(bCurXmm && bCurXmkr && !bSrchXsw && !bSrchXmmUsig) + { + // unsure if cam, so ask user + bDbReqAdd = true; + bDbReqAddAuto = true; + m_eDbReqSuggest = DB_ADD_SUGGEST_CAM; + m_pLog->AddLine(" This may be a new camera for the database."); + m_pLog->AddLine(" If this file is original, and camera doesn't appear in list above,"); + m_pLog->AddLineWarn(" PLEASE ADD TO DATABASE with [Tools->Add Camera to DB]"); + } + else if(!bCurXmm && !bCurXmkr && !bSrchXsw) + { + // unsure if SW, so ask user + bDbReqAdd = true; + m_eDbReqSuggest = DB_ADD_SUGGEST_SW; + m_pLog->AddLine(" This may be a new software editor for the database."); + m_pLog->AddLine(" If this file is processed, and editor doesn't appear in list above,"); + m_pLog->AddLineWarn(" PLEASE ADD TO DATABASE with [Tools->Add Camera to DB]"); + } + + m_pLog->AddLine(""); + + // ----------------------------------------------------------- + + if(bQuiet) + { + m_pLog->Enable(); + } + +#ifdef BATCH_DO_DBSUBMIT_ALL + bDbReqAddAuto = true; +#endif + + // Return a value that indicates whether or not we should add this + // entry to the database + return bDbReqAddAuto; + +} + +// Build the image data string that will be sent to the database repository +// This data string contains the compression siganture and a few special +// fields such as image dimensions, etc. +// +// If Portrait, Rotates DQT table, Width/Height. +// m_strImgQuantCss is already rotated by ProcessFile() +// PRE: m_strHash already defined +void CjfifDecode::PrepareSendSubmit(QString strQual, teSource eUserSource, QString strUserSoftware, QString strUserNotes) +{ + // Generate the DQT arrays suitable for posting + QString strTmp1; + + QString asDqt[4]; + + uint32_t nMatrixInd; + + Q_ASSERT(m_strHash != "NONE"); + Q_ASSERT(m_eImgLandscape != ENUM_LANDSCAPE_UNSET); + + for(uint32_t nSet = 0; nSet < 4; nSet++) + { + asDqt[nSet] = ""; + + if(m_abImgDqtSet[nSet]) + { + for(uint32_t nInd = 0; nInd < 64; nInd++) + { + // FIXME: Still consider rotating DQT table even though we + // don't know for sure if m_eImgLandscape is accurate + // Not a big deal if we get it wrong as we still add + // both pre- and post-rotated sigs. + nMatrixInd = (m_eImgLandscape != ENUM_LANDSCAPE_NO) ? nInd : glb_anQuantRotate[nInd]; + if((nInd % 8 == 0) && (nInd != 0)) + { + asDqt[nSet].append("!"); + } + + asDqt[nSet].append(QString("%1").arg(m_anImgDqtTbl[nSet][nMatrixInd])); + if(nInd % 8 != 7) + { + asDqt[nSet].append(","); + } + } + } // set defined? + } // up to 4 sets + + uint32_t nOrigW, nOrigH; + + nOrigW = (m_eImgLandscape != ENUM_LANDSCAPE_NO) ? m_nSofSampsPerLine_X : m_nSofNumLines_Y; + nOrigH = (m_eImgLandscape != ENUM_LANDSCAPE_NO) ? m_nSofNumLines_Y : m_nSofSampsPerLine_X; + + uint32_t nOrigThumbW, nOrigThumbH; + + nOrigThumbW = (m_eImgLandscape != ENUM_LANDSCAPE_NO) ? m_nImgThumbSampsPerLine : m_nImgThumbNumLines; + nOrigThumbH = (m_eImgLandscape != ENUM_LANDSCAPE_NO) ? m_nImgThumbNumLines : m_nImgThumbSampsPerLine; + + teMaker eMaker; + + eMaker = (m_bImgExifMakernotes) ? ENUM_MAKER_PRESENT : ENUM_MAKER_NONE; + + // Sort sig additions + // To create some determinism in the database, arrange the sigs + // to be in numerical order + QString strSig0, strSig1, strSigThm0, strSigThm1; + + if(m_strHash <= m_strHashRot) + { + strSig0 = m_strHash; + strSig1 = m_strHashRot; + } + else + { + strSig0 = m_strHashRot; + strSig1 = m_strHash; + } + if(m_strHashThumb <= m_strHashThumbRot) + { + strSigThm0 = m_strHashThumb; + strSigThm1 = m_strHashThumbRot; + } + else + { + strSigThm0 = m_strHashThumbRot; + strSigThm1 = m_strHashThumb; + } + + SendSubmit(m_strImgExifMake, m_strImgExifModel, strQual, asDqt[0], asDqt[1], asDqt[2], asDqt[3], m_strImgQuantCss, + strSig0, strSig1, strSigThm0, strSigThm1, (float) m_adImgDqtQual[0], (float) m_adImgDqtQual[1], nOrigW, nOrigH, + m_strSoftware, m_strComment, eMaker, eUserSource, strUserSoftware, m_strImgExtras, + strUserNotes, m_eImgLandscape, nOrigThumbW, nOrigThumbH); + +} + +// Send the compression signature string to the local database file +// in addition to the web repository if the user has enabled it. +void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString strQual, + QString strDqt0, QString strDqt1, QString strDqt2, QString strDqt3, + QString strCss, + QString strSig, QString strSigRot, QString strSigThumb, + QString strSigThumbRot, float fQFact0, float fQFact1, uint32_t nImgW, uint32_t nImgH, + QString strExifSoftware, QString strComment, teMaker eMaker, + teSource eUserSource, QString strUserSoftware, QString strExtra, + QString strUserNotes, uint32_t nExifLandscape, uint32_t nThumbX, uint32_t nThumbY) +{ + // NOTE: This assumes that we've already run PrepareSignature() which usually happens when we process a file. + Q_ASSERT(strSig != ""); + Q_ASSERT(strSigRot != ""); + +// CUrlString curls; + + // Version "03": (v1.8.0+) + // - Adds JPEGsnoop version (js_ver) to enable signature source correction + QString DB_SUBMIT_WWW_VER = "03"; + +#ifndef BATCH_DO + if(m_bSigExactInDB) + { + if(m_pAppConfig->bInteractive) + msgBox.setText("Compression signature already in database"); + } + else + { + // Now append it to the local database and resave +//@@ m_pDbSigs->DatabaseExtraAdd(strExifMake, strExifModel, strQual, strSig, strSigRot, strCss, eUserSource, strUserSoftware); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText("Added Compression signature to database"); + } + } +#endif + + // Is automatic internet update enabled? +//@@ if(!m_pAppConfig->bDbSubmitNet) + if(!m_pAppConfig->bDbSubmitNet) + { + return; + } + + QString strTmp; + QString strFormat; + QString strFormDataPre; + QString strFormData; + + uint32_t nFormDataLen; + uint32_t nChecksum = 32; + + QString strSubmitHost; + QString strSubmitPage; + + strSubmitHost = IA_HOST; + strSubmitPage = IA_DB_SUBMIT_PAGE; + + for(uint32_t i = 0; i < strlen(IA_HOST); i++) + { + nChecksum += strSubmitHost[i].toLatin1(); + nChecksum += 3 * strSubmitPage[i].toLatin1(); + } + + //if ( (m_pAppConfig->bIsWindowsNTorLater) && (nChecksum == 9678) ) { + if(nChecksum == 9678) + { + // Submit to online database + // - Mark the encoding as UTF-8 + QString strHeaders = "Content-Type: application/x-www-form-urlencoded; charset=utf-8"; + + // URL-encoded form variables - + strFormat = "ver=%1&js_ver=%2&x_make=%3&x_model=%4&um_qual=%5&x_dqt0=%6&x_dqt1=%7&x_dqt2=%8&x_dqt3=%9"; + strFormat += "&x_subsamp=%10&c_sig=%11&c_sigrot=%12&c_qfact0=%13&c_qfact1=%14&x_img_w=%15&x_img_h=%16"; + strFormat += "&x_sw=%17&x_com=%18&x_maker=%19&u_source=%20&u_sw=%21"; + strFormat += "&x_extra=%22&u_notes=%23&c_sigthumb=%24&c_sigthumbrot=%25&x_landscape=%26"; + strFormat += "&x_thumbx=%27&x_thumby=%28"; + + strFormDataPre = QString(strFormat) + .arg(DB_SUBMIT_WWW_VER) + .arg(VERSION_STR) + .arg(strExifMake) + .arg(strExifModel) + .arg(strQual) + .arg(strDqt0) + .arg(strDqt1) + .arg(strDqt2) + .arg(strDqt3) + .arg(strCss) + .arg(strSig) + .arg(strSigRot) + .arg(fQFact0) + .arg(fQFact1) + .arg(nImgW) + .arg(nImgH) + .arg(strExifSoftware) + .arg(strComment) + .arg(eMaker) + .arg(eUserSource) + .arg(strUserSoftware) + .arg(strExtra) + .arg(strUserNotes) + .arg(strSigThumb) + .arg( strSigThumbRot) + .arg(nExifLandscape) + .arg(nThumbX) + .arg(nThumbY); + + //*** Need to sanitize data for URL submission! + // Search for "&", "?", "=" +//@@ strFormData = QString(strFormat) +// .arg(DB_SUBMIT_WWW_VER) +// .arg(VERSION_STR) +// .arg(curls.Encode(strExifMake)) +// .arg(curls.Encode(strExifModel)) +// .arg(strQual) +// .arg(strDqt0) +// .arg(strDqt1) +// .arg(strDqt2) +// .arg(strDqt3) +// .arg(strCss) +// .arg(strSig) +// .arg(strSigRot) +// .arg(fQFact0) +// .arg(fQFact1) +// .arg(nImgW) +// .arg(nImgH) +// .arg(curls.Encode(strExifSoftware)) +// .arg(curls.Encode(strComment)) +// .arg(eMaker) +// .arg(eUserSource) +// .arg(curls.Encode(strUserSoftware)) +// .arg(curls.Encode(strExtra)) +// .arg(curls.Encode(strUserNotes)) +// .arg(strSigThumb) +// .arg(strSigThumbRot) +// .arg(nExifLandscape) +// .arg(nThumbX) +// .arg(nThumbY); + + nFormDataLen = strFormData.length(); + +#ifdef DEBUG_SIG + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strFormDataPre); + msgBox.setText(strFormData); + } +#endif + +#ifdef WWW_WININET + //static LPSTR astrAcceptTypes[2]={"*/*", NULL}; + +/* HINTERNET hINet = NULL; + HINTERNET hConnection = NULL; + HINTERNET hData = NULL; + + hINet = InternetOpen("JPEGsnoop/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ; + if ( !hINet ) + { + if (m_pAppConfig->bInteractive) + msgBox.setText("InternetOpen Failed"); + return; + } + try + { + hConnection = InternetConnect( hINet, strSubmitHost, 80, NULL,NULL, INTERNET_SERVICE_HTTP, 0, 1 ); + if ( !hConnection ) + { + InternetCloseHandle(hINet); + return; + } + hData = HttpOpenRequest( hConnection, "POST"), strSubmitPage, NULL, NULL, NULL, 0, 1 ; + if ( !hData ) + { + InternetCloseHandle(hConnection); + InternetCloseHandle(hINet); + return; + } + // GET HttpSendRequest( hData, NULL, 0, NULL, 0); + + // POST requests from HttpSendRequest() don't work well with + // unicode, so convert from unicode to ANSI +//@@ QString strHeadersA = CW2A(strHeaders,CP_UTF8); +//@@ QString strFormDataA = CW2A(strFormData,CP_UTF8); + HttpSendRequestA( hData, strHeadersA, strHeadersA.GetLength(), strFormDataA.GetBuffer(), strFormDataA.GetLength()); + + } + catch( CInternetException* e) + { + e->ReportError(); + e->Delete(); + //msgBox.setText("EXCEPTION!"); + } + InternetCloseHandle(hConnection); + InternetCloseHandle(hINet); + InternetCloseHandle(hData); */ +#endif + +#ifdef WWW_WINHTTP + CInternetSession sSession; + CHttpConnection *pConnection; + CHttpFile *pFile; + + bool bResult; + + DWORD dwRet; + + // *** NOTE: Will not work on Windows 95/98! + // This section is avoided in early OSes otherwise we get an Illegal Op + try + { + pConnection = sSession.GetHttpConnection(submit_host); + Q_ASSERT(pConnection); + pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST, submit_page); + Q_ASSERT(pFile); + bResult = pFile->SendRequest(strHeaders, (LPVOID) strFormData, strFormData.GetLength()); + Q_ASSERT(bResult != 0); + pFile->QueryInfoStatusCode(dwRet); + Q_ASSERT(dwRet == HTTP_STATUS_OK); + + // Clean up! + if(pFile) + { + pFile->Close(); + delete pFile; + + pFile = NULL; + } + if(pConnection) + { + pConnection->Close(); + delete pConnection; + + pConnection = NULL; + } + sSession.Close(); + + } + + catch(CInternetException * pEx) + { + // catch any exceptions from WinINet + TCHAR szErr[MAX_BUF_EX_ERR_MSG]; + + szErr[0] = '\0'; + + if(!pEx->GetErrorMessage(szErr, MAX_BUF_EX_ERR_MSG)) + _tcscpy(szErr, "Unknown error"); + + TRACE("Submit Failed! - %s", szErr); + + if(m_pAppConfig->bInteractive) + msgBox.setText(szErr); + + pEx->Delete(); + + if(pFile) + delete pFile; + + if(pConnection) + delete pConnection; + + session.Close(); + return; + } +#endif + + } +} + +// Parse the embedded JPEG thumbnail. This routine is a much-reduced +// version of the main JFIF parser, in that it focuses primarily on the +// DQT tables. +void CjfifDecode::DecodeEmbeddedThumb() +{ + QString strTmp; + QString strMarker; + + uint32_t nPosSaved; + uint32_t nPosSaved_sof; + uint32_t nPosEnd; + + bool bDone; + + uint32_t nCode; + + bool bRet; + + QString strFull; + + uint32_t nDqtPrecision_Pq; + uint32_t nDqtQuantDestId_Tq; + uint32_t nImgPrecision; + uint32_t nLength; + uint32_t nTmpVal; + + bool bScanSkipDone; + bool bErrorAny = false; + bool bErrorThumbLenZero = false; + + uint32_t nSkipCount; + + nPosSaved = m_nPos; + + // Examine the EXIF embedded thumbnail (if it exists) + if(m_nImgExifThumbComp == 6) + { + m_pLog->AddLine(""); + m_pLog->AddLineHdr("*** Embedded JPEG Thumbnail ***"); + strTmp = QString(" Offset: 0x%1").arg(m_nImgExifThumbOffset, 8, 16, QChar('0')); + m_pLog->AddLine(strTmp); + strTmp = QString(" Length: 0x%1 (%2)").arg(m_nImgExifThumbLen, 8, 16, QChar('0')).arg(m_nImgExifThumbLen); + m_pLog->AddLine(strTmp); + + // Quick scan for DQT tables + m_nPos = m_nImgExifThumbOffset; + bDone = false; + + while(!bDone) + { + // For some reason, I have found files that have a nLength of 0 + if(m_nImgExifThumbLen != 0) + { + if((m_nPos - m_nImgExifThumbOffset) > m_nImgExifThumbLen) + { + strTmp = QString("ERROR: Read more than specified EXIF thumb nLength (%1 bytes) before EOI").arg(m_nImgExifThumbLen); + m_pLog->AddLineErr(strTmp); + bErrorAny = true; + bDone = true; + } + } + else + { + // Don't try to process if nLength is 0! + // Seen this in a Canon 1ds file (processed by photoshop) + bDone = true; + bErrorAny = true; + bErrorThumbLenZero = true; + } + + if((!bDone) && (Buf(m_nPos++) != 0xFF)) + { + strTmp = + QString("ERROR: Expected marker 0xFF, got 0x%1 @ offset 0x%2") + .arg(Buf(m_nPos - 1), 2, 16, QChar('0')) + .arg(m_nPos - 1, 8, 16, QChar('0')); + m_pLog->AddLineErr(strTmp); + bErrorAny = true; + bDone = true; + } + + if(!bDone) + { + nCode = Buf(m_nPos++); + + m_pLog->AddLine(""); + + switch (nCode) + { + case JFIF_SOI: // SOI + m_pLog->AddLine(" * Embedded Thumb Marker: SOI"); + break; + + case JFIF_DQT: // Define quantization tables + m_pLog->AddLine(" * Embedded Thumb Marker: DQT"); + + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + nPosEnd = m_nPos + nLength; + m_nPos += 2; + strTmp = QString(" Length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + while(nPosEnd > m_nPos) + { + strTmp = QString(" ----"); + m_pLog->AddLine(strTmp); + + nTmpVal = Buf(m_nPos++); + nDqtPrecision_Pq = (nTmpVal & 0xF0) >> 4; + nDqtQuantDestId_Tq = nTmpVal & 0x0F; + QString strPrecision = ""; + + if(nDqtPrecision_Pq == 0) + { + strPrecision = "8 bits"; + } + else if(nDqtPrecision_Pq == 1) + { + strPrecision = "16 bits"; + } + else + { + strPrecision = QString("??? unknown [value=%1]").arg(nDqtPrecision_Pq); + } + + strTmp = QString(" Precision=%1").arg(strPrecision); + m_pLog->AddLine(strTmp); + strTmp = QString(" Destination ID=%1").arg(nDqtQuantDestId_Tq); + // NOTE: The mapping between destination IDs and the actual + // usage is defined in the SOF marker which is often later. + // In nearly all images, the following is true. However, I have + // seen some test images that set Tbl 3 = Lum, Tbl 0=Chr, + // Tbl1=Chr, and Tbl2 undefined + if(nDqtQuantDestId_Tq == 0) + { + strTmp += " (Luminance, typically)"; + } + else if(nDqtQuantDestId_Tq == 1) + { + strTmp += " (Chrominance, typically)"; + } + else if(nDqtQuantDestId_Tq == 2) + { + strTmp += " (Chrominance, typically)"; + } + else + { + strTmp += " (???)"; + } + + m_pLog->AddLine(strTmp); + + if(nDqtQuantDestId_Tq >= 4) + { + strTmp = QString("ERROR: nDqtQuantDestId_Tq = %1, >= 4").arg(nDqtQuantDestId_Tq); + m_pLog->AddLineErr(strTmp); + bDone = true; + bErrorAny = true; + break; + } + + for(uint32_t nInd = 0; nInd <= 63; nInd++) + { + nTmpVal = Buf(m_nPos++); + m_anImgThumbDqt[nDqtQuantDestId_Tq][glb_anZigZag[nInd]] = nTmpVal; + } + + m_abImgDqtThumbSet[nDqtQuantDestId_Tq] = true; + + // Now display the table + for(uint32_t nY = 0; nY < 8; nY++) + { + strFull = QString(" DQT, Row #%1: ").arg(nY); + + for(uint32_t nX = 0; nX < 8; nX++) + { + strTmp = QString("%1 ").arg(m_anImgThumbDqt[nDqtQuantDestId_Tq][nY * 8 + nX], 3); + strFull += strTmp; + + // Store the DQT entry into the Image DenCoder + bRet = m_pImgDec->SetDqtEntry(nDqtQuantDestId_Tq, nY * 8 + nX, + glb_anUnZigZag[nY * 8 + nX], m_anImgDqtTbl[nDqtQuantDestId_Tq][nY * 8 + nX]); + DecodeErrCheck(bRet); + + } + + m_pLog->AddLine(strFull); + + } + } + + break; + + case JFIF_SOF0: + m_pLog->AddLine(" * Embedded Thumb Marker: SOF"); + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + nPosSaved_sof = m_nPos; + m_nPos += 2; + strTmp = QString(" Frame header length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + + nImgPrecision = Buf(m_nPos++); + strTmp = QString(" Precision = %1").arg(nImgPrecision); + m_pLog->AddLine(strTmp); + + m_nImgThumbNumLines = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + m_nPos += 2; + strTmp = QString(" Number of Lines = %1").arg(m_nImgThumbNumLines); + m_pLog->AddLine(strTmp); + + m_nImgThumbSampsPerLine = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + m_nPos += 2; + strTmp = QString(" Samples per Line = %1").arg(m_nImgThumbSampsPerLine); + m_pLog->AddLine(strTmp); + strTmp = QString(" Image Size = %1 x %2").arg(m_nImgThumbSampsPerLine).arg(m_nImgThumbNumLines); + m_pLog->AddLine(strTmp); + + m_nPos = nPosSaved_sof + nLength; + + break; + + case JFIF_SOS: // SOS + m_pLog->AddLine(" * Embedded Thumb Marker: SOS"); + m_pLog->AddLine(" Skipping scan data"); + bScanSkipDone = false; + nSkipCount = 0; + + while(!bScanSkipDone) + { + if((Buf(m_nPos) == 0xFF) && (Buf(m_nPos + 1) != 0x00)) + { + // Was it a restart marker? + if((Buf(m_nPos + 1) >= JFIF_RST0) && (Buf(m_nPos + 1) <= JFIF_RST7)) + { + m_nPos++; + } + else + { + // No... it's a real marker + bScanSkipDone = true; + } + } + else + { + m_nPos++; + nSkipCount++; + } + } + + strTmp = QString(" Skipped %1 bytes").arg(nSkipCount); + m_pLog->AddLine(strTmp); + break; + + case JFIF_EOI: + m_pLog->AddLine(" * Embedded Thumb Marker: EOI"); + bDone = true; + break; + + case JFIF_RST0: + case JFIF_RST1: + case JFIF_RST2: + case JFIF_RST3: + case JFIF_RST4: + case JFIF_RST5: + case JFIF_RST6: + case JFIF_RST7: + break; + + default: + GetMarkerName(nCode, strMarker); + strTmp = QString(" * Embedded Thumb Marker: %1").arg(strMarker); + m_pLog->AddLine(strTmp); + nLength = Buf(m_nPos) * 256 + Buf(m_nPos + 1); + strTmp = QString(" Length = %1").arg(nLength); + m_pLog->AddLine(strTmp); + m_nPos += nLength; + break; + } + } // if !bDone + } // while !bDone + + // Now calculate the signature + if(!bErrorAny) + { + PrepareSignatureThumb(); + m_pLog->AddLine(""); + strTmp = QString(" * Embedded Thumb Signature: %1").arg(m_strHashThumb); + m_pLog->AddLine(strTmp); + } + + if(bErrorThumbLenZero) + { + m_strHashThumb = "ERR: Len=0"; + m_strHashThumbRot = "ERR: Len=0"; + } + + } // if JPEG compressed + + m_nPos = nPosSaved; +} + +// Lookup the EXIF marker name from the code value +bool CjfifDecode::GetMarkerName(uint32_t nCode, QString & markerStr) +{ + bool bDone = false; + bool bFound = false; + + uint32_t nInd = 0; + + while(!bDone) + { + if(m_pMarkerNames[nInd].nCode == 0) + { + bDone = true; + } + else if(m_pMarkerNames[nInd].nCode == nCode) + { + bDone = true; + bFound = true; + markerStr = m_pMarkerNames[nInd].strName; + return true; + } + else + { + nInd++; + } + } + + if(!bFound) + { + markerStr = ""; + markerStr = QString("(0xFF%1)").arg(nCode, 2, 16, QChar('0')); + return false; + } + + return true; +} + +// Determine if the file is an AVI MJPEG. +// If so, parse the headers. +// TODO: Expand this function to use sub-functions for each block type +bool CjfifDecode::DecodeAvi() +{ + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CfifDecode::DecodeAvi() Begin"); + + QString strTmp; + + uint32_t nPosSaved; + + m_bAvi = false; + m_bAviMjpeg = false; + + // Perhaps start from file position 0? + nPosSaved = m_nPos; + + // Start from file position 0 + m_nPos = 0; + + bool bSwap = true; + + QString strRiff; + + uint32_t nRiffLen; + + QString strForm; + + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CfifDecode::DecodeAvi() Checkpoint 1"); + + strRiff = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + nRiffLen = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + strForm = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CfifDecode::DecodeAvi() Checkpoint 2"); + + if((strRiff == "RIFF") && (strForm == "AVI ")) + { + m_bAvi = true; + m_pLog->AddLine(""); + m_pLog->AddLineHdr("*** AVI File Decoding ***"); + m_pLog->AddLine("Decoding RIFF AVI format..."); + m_pLog->AddLine(""); + } + else + { + // Reset file position + m_nPos = nPosSaved; + return false; + } + + QString strHeader; + + uint32_t nChunkSize; + uint32_t nChunkDataStart; + + bool done = false; + + while(!done) + { + if(m_nPos >= m_pWBuf->GetPosEof()) + { + done = true; + break; + } + + strHeader = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + strTmp = QString(" %1").arg(strHeader); + m_pLog->AddLine(strTmp); + + nChunkSize = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + nChunkDataStart = m_nPos; + + if(strHeader == "LIST") + { + // --- LIST --- + QString strListType; + + strListType = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + + strTmp = QString(" %1").arg(strListType); + m_pLog->AddLine(strTmp); + + if(strListType == "hdrl") + { + // --- hdrl --- + + uint32_t nPosHdrlStart; + + QString strHdrlId; + + strHdrlId = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + uint32_t nHdrlLen; + + nHdrlLen = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + nPosHdrlStart = m_nPos; + + // nHdrlLen should be 14*4 bytes + + m_nPos = nPosHdrlStart + nHdrlLen; + + } + else if(strListType == "strl") + { + // --- strl --- + + // strhHEADER + uint32_t nPosStrlStart; + + QString strStrlId; + + strStrlId = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + uint32_t nStrhLen; + + nStrhLen = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + nPosStrlStart = m_nPos; + + QString fccType; + + QString fccHandler; + + uint32_t dwFlags, dwReserved1, dwInitialFrames, dwScale, dwRate; + + uint32_t dwStart, dwLength, dwSuggestedBufferSize, dwQuality; + + uint32_t dwSampleSize, xdwQuality, xdwSampleSize; + + fccType = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + fccHandler = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + dwFlags = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + dwReserved1 = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + dwInitialFrames = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + dwScale = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + dwRate = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + dwStart = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + dwLength = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + dwSuggestedBufferSize = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + dwQuality = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + dwSampleSize = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + xdwQuality = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + xdwSampleSize = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + + QString fccTypeDecode = ""; + + if(fccType == "vids") + { + fccTypeDecode = "[vids] Video"; + } + else if(fccType == "auds") + { + fccTypeDecode = "[auds] Audio"; + } + else if(fccType == "txts") + { + fccTypeDecode = "[txts] Subtitle"; + } + else + { + fccTypeDecode = QString("[%1]").arg(fccType); + } + + strTmp = QString(" -[FourCC Type] = %1").arg(fccTypeDecode); + m_pLog->AddLine(strTmp); + + strTmp = QString(" -[FourCC Codec] = [%1]").arg(fccHandler); + m_pLog->AddLine(strTmp); + + float fSampleRate = 0; + + if(dwScale != 0) + { + fSampleRate = (float) dwRate / (float) dwScale; + } + + strTmp = QString(" -[Sample Rate] = [%.2f]").arg(fSampleRate); + + if(fccType == "vids") + { + strTmp.append(" frames/sec"); + } + else if(fccType == "auds") + { + strTmp.append(" samples/sec"); + } + + m_pLog->AddLine(strTmp); + + m_nPos = nPosStrlStart + nStrhLen; // Skip + + strTmp = QString(" %1").arg(fccType); + m_pLog->AddLine(strTmp); + + if(fccType == "vids") + { + // --- vids --- + + // Is it MJPEG? + //strTmp = QString(" -[Video Stream FourCC]=[%s]"),fccHandler; + //m_pLog->AddLine(strTmp); + if(fccHandler == "mjpg") + { + m_bAviMjpeg = true; + } + + if(fccHandler == "MJPG") + { + m_bAviMjpeg = true; + } + + // strfHEADER_BIH + QString strSkipId; + + uint32_t nSkipLen; + uint32_t nSkipStart; + + strSkipId = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + nSkipLen = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + nSkipStart = m_nPos; + + m_nPos = nSkipStart + nSkipLen; // Skip + } + else if(fccType == "auds") + { + // --- auds --- + + // strfHEADER_WAVE + + QString strSkipId; + + uint32_t nSkipLen; + uint32_t nSkipStart; + + strSkipId = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + nSkipLen = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + nSkipStart = m_nPos; + + m_nPos = nSkipStart + nSkipLen; // Skip + } + else + { + // strfHEADER + + QString strSkipId; + + uint32_t nSkipLen; + + uint32_t nSkipStart; + + strSkipId = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + nSkipLen = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + nSkipStart = m_nPos; + + m_nPos = nSkipStart + nSkipLen; // Skip + } + + // strnHEADER + uint32_t nPosStrnStart; + + QString strStrnId; + + strStrnId = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + uint32_t nStrnLen; + + nStrnLen = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + nPosStrnStart = m_nPos; + + // FIXME: Can we rewrite in terms of ChunkSize and ChunkDataStart? + //Q_ASSERT ((nPosStrnStart + nStrnLen + (nStrnLen%2)) == (nChunkDataStart + nChunkSize + (nChunkSize%2))); + //m_nPos = nChunkDataStart + nChunkSize + (nChunkSize%2); + m_nPos = nPosStrnStart + nStrnLen + (nStrnLen % 2); // Skip + } + else if(strListType == "movi") + { + // movi + + m_nPos = nChunkDataStart + nChunkSize + (nChunkSize % 2); + } + else if(strListType == "INFO") + { + // INFO + uint32_t nInfoStart; + + nInfoStart = m_nPos; + + QString strInfoId; + + uint32_t nInfoLen; + + strInfoId = m_pWBuf->BufReadStrn(m_nPos, 4); + m_nPos += 4; + nInfoLen = m_pWBuf->BufX(m_nPos, 4, bSwap); + m_nPos += 4; + + if(strInfoId == "ISFT") + { + QString strIsft = ""; + + strIsft = m_pWBuf->BufReadStrn(m_nPos, nChunkSize); + strIsft = strIsft.trimmed(); //!! trim right + strTmp = QString(" -[Software] = [%1]").arg(strIsft); + m_pLog->AddLine(strTmp); + } + + m_nPos = nChunkDataStart + nChunkSize + (nChunkSize % 2); + } + else + { + // ? + m_nPos = nChunkDataStart + nChunkSize + (nChunkSize % 2); + } + } + else if(strHeader == "JUNK") + { + // Junk + + m_nPos = nChunkDataStart + nChunkSize + (nChunkSize % 2); + } + else if(strHeader == "IDIT") + { + // Timestamp info (Canon, etc.) + + QString strIditTimestamp = ""; + + strIditTimestamp = m_pWBuf->BufReadStrn(m_nPos, nChunkSize); + strIditTimestamp = strIditTimestamp.trimmed(); //!! + strTmp = QString(" -[Timestamp] = [1s]").arg(strIditTimestamp); + m_pLog->AddLine(strTmp); + + m_nPos = nChunkDataStart + nChunkSize + (nChunkSize % 2); + + } + else if(strHeader == "indx") + { + // Index + + m_nPos = nChunkDataStart + nChunkSize + (nChunkSize % 2); + } + else if(strHeader == "idx1") + { + // Index + //uint32_t nIdx1Entries = nChunkSize / (4*4); + + m_nPos = nChunkDataStart + nChunkSize + (nChunkSize % 2); + } + else + { + // Unsupported + m_nPos = nChunkDataStart + nChunkSize + (nChunkSize % 2); + } + } + + m_pLog->AddLine(""); + + if(m_bAviMjpeg) + { + m_strImgExtras += "[AVI]:[mjpg],"; + m_pLog->AddLineGood(" AVI is MotionJPEG"); + m_pLog->AddLineWarn(" Use [Tools->Img Search Fwd] to locate next frame"); + } + else + { + m_strImgExtras += "[AVI]:[????],"; + m_pLog->AddLineWarn(" AVI is not MotionJPEG. [Img Search Fwd/Rev] unlikely to find frames."); + } + + m_pLog->AddLine(""); + + // Reset file position + m_nPos = nPosSaved; + + return m_bAviMjpeg; +} + +// This is the primary JFIF parsing routine. +// The main loop steps through all of the JFIF markers and calls +// DecodeMarker() each time until we reach the end of file or an error. +// Finally, we invoke the compression signature search function. +// +// Processing starts at the file offset m_pAppConfig->nPosStart +// +// INPUT: +// - inFile = Input file pointer +// +// PRE: +// - m_pAppConfig->nPosStart = Starting file offset for decode +// +void CjfifDecode::ProcessFile(QFile * inFile) +{ + QString strTmp; + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CfifDecode::ProcessFile() Checkpoint 1"); + + // Reset the JFIF decoder state as we may be redoing another file + Reset(); + + // Reset the IMG Decoder state + if(m_pImgSrcDirty) + { + m_pImgDec->ResetState(); + } + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CfifDecode::ProcessFile() Checkpoint 2"); + + // Set the statusbar text to Processing... + + // Ensure the status bar has been allocated + // NOTE: The stat bar is NULL if we drag & drop a file onto + // the JPEGsnoop app icon. + if(m_pStatBar) + { + m_pStatBar->showMessage("Processing..."); + } + + // Note that we don't clear out the logger (with m_pLog->Reset()) + // as we want top-level caller to do this. This way we can + // still insert extra lines from top level. + + // GetLength returns ULONGLONG. Abort on large files (>=4GB) + qint64 nPosFileEnd; + + nPosFileEnd = inFile->size(); + + if(nPosFileEnd > 0xFFFFFFFF) + { + strTmp = "File too large. Skipping."; + m_pLog->AddLineErr(strTmp); + + if(m_pAppConfig->bInteractive) + msgBox.setText(strTmp); + + return; + } + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CfifDecode::ProcessFile() Checkpoint 3"); + + qDebug() << m_pAppConfig; + + m_nPosFileEnd = static_cast < uint32_t >(nPosFileEnd); + + uint32_t nStartPos; + + nStartPos = m_pAppConfig->nPosStart; + m_nPos = nStartPos; + m_nPosEmbedStart = nStartPos; // Save the embedded file start position + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CfifDecode::ProcessFile() Checkpoint 4"); + + m_pLog->AddLine(QString("Start Offset: 0x%1").arg(nStartPos, 8, 16, QChar('0'))); + + // ---------------------------------------------------------------- + + // Test for AVI file + // - Detect header + // - start from beginning of file + DecodeAvi(); + // TODO: Should we skip decode of file if not MJPEG? + + // ---------------------------------------------------------------- + + // Test for PSD file + // - Detect header + // - FIXME: start from current offset? + uint32_t nWidth = 0; + + uint32_t nHeight = 0; + +#ifdef PS_IMG_DEC_EN + // If PSD image decoding is enabled, associate the PSD parsing with + // the current DIB. After decoding, flag the DIB as ready for display. + + // Attempt decode as PSD + bool bDecPsdOk = false; + +//@@ bDecPsdOk = m_pPsDec->DecodePsd(nStartPos, &m_pImgDec->m_pDibTemp, nWidth, nHeight); + + if(bDecPsdOk) + { + // FIXME: The following is a bit of a hack + m_pImgDec->m_bDibTempReady = true; + m_pImgDec->m_bPreviewIsJpeg = false; // MCU/Block info not available + m_pImgDec->SetImageDimensions(nWidth, nHeight); + + // Clear the image information + // The primary reason for this is to ensure we don't have stale information from a previous + // JPEG image (eg. real image border inside MCU border which would be overlayed during draw). + m_pImgDec->SetImageDetails(0, 0, 0, 0, false, 0); + + // No more processing of file + // - Otherwise we'd continue to attempt to decode as JPEG + return; + } +#else + // Don't attempt to display Photoshop image data + if(m_pPsDec->DecodePsd(nStartPos, NULL, nWidth, nHeight)) + { + return; + } +#endif + + // ---------------------------------------------------------------- + +// Disable DICOM for now until fully tested +#ifdef SUPPORT_DICOM + // Test for DICOM + // - Detect header + // - start from beginning of file + bool bDicom = false; + + uint32_t nPosJpeg = 0; // File offset to embedded JPEG in DICOM + + bDicom = m_pDecDicom->DecodeDicom(0, m_nPosFileEnd, nPosJpeg); + + if(bDicom) + { + // Adjust start of JPEG decoding if we are currently without an offset + if(nStartPos == 0) + { + m_pAppConfig->nPosStart = nPosJpeg; + + nStartPos = m_pAppConfig->nPosStart; + m_nPos = nStartPos; + m_nPosEmbedStart = nStartPos; // Save the embedded file start position + + strTmp = QString("Adjusting Start Offset to: 0x%08X"), nStartPos; + m_pLog->AddLine(strTmp); + m_pLog->AddLine(""); + } + } +#endif + + // ---------------------------------------------------------------- + + // Decode as JPEG JFIF file + + // If we are in a non-zero offset, add this to extras + if(m_pAppConfig->nPosStart != 0) + { + strTmp = QString("[Offset]=[%1],").arg(m_pAppConfig->nPosStart); + m_strImgExtras += strTmp; + } + + uint32_t nDataAfterEof = 0; + + bool bDone = false; + + while(!bDone) + { + // Allow some other threads to jump in + + // Return value 0 - OK + // 1 - Error + // 2 - EOI + if(DecodeMarker() != DECMARK_OK) + { + bDone = true; + + if(m_nPosFileEnd >= m_nPosEoi) + { + nDataAfterEof = m_nPosFileEnd - m_nPosEoi; + } + } + else + { + if(m_nPos > m_pWBuf->GetPosEof()) + { + m_pLog->AddLineErr("ERROR: Early EOF - file may be missing EOI"); + bDone = true; + } + } + } + + // ----------------------------------------------------------- + // Perform any other informational calculations that require all tables + // to be present. + + // Determine the CSS Ratio + // Save the subsampling string. Assume component 2 is representative of the overall chrominance. + + // NOTE: Ensure that we don't execute the following code if we haven't + // completed our read (ie. get bad marker earlier in processing). + // TODO: What is the best way to determine all is OK? + + m_strImgQuantCss = "?x?"; + m_strHash = "NONE"; + m_strHashRot = "NONE"; + + if(m_bImgOK) + { + Q_ASSERT(m_eImgLandscape != ENUM_LANDSCAPE_UNSET); + + if(m_nSofNumComps_Nf == NUM_CHAN_YCC) + { + // We only try to determine the chroma subsampling ratio if we have 3 components (assume YCC) + // In general, we should be able to use the 2nd or 3rd component + + // NOTE: The following assumes m_anSofHorzSampFact_Hi and m_anSofVertSampFact_Vi + // are non-zero as otherwise we'll have a divide-by-0 exception. + uint32_t nCompIdent = m_anSofQuantCompId[SCAN_COMP_CB]; + + uint32_t nCssFactH = m_nSofHorzSampFactMax_Hmax / m_anSofHorzSampFact_Hi[nCompIdent]; + + uint32_t nCssFactV = m_nSofVertSampFactMax_Vmax / m_anSofVertSampFact_Vi[nCompIdent]; + + if(m_eImgLandscape != ENUM_LANDSCAPE_NO) + { + // Landscape orientation + m_strImgQuantCss = QString("%1x%2").arg(nCssFactH).arg(nCssFactV); + } + else + { + // Portrait orientation (flip subsampling ratio) + m_strImgQuantCss = QString("%1x%1").arg(nCssFactV).arg(nCssFactH); + } + } + else if(m_nSofNumComps_Nf == NUM_CHAN_GRAYSCALE) + { + m_strImgQuantCss = "Gray"; + } + + DecodeEmbeddedThumb(); + + // Generate the signature + PrepareSignature(); + + // Compare compression signature + if(m_pAppConfig->bSigSearch) + { + // In the case of lossless files, there won't be any DQT and + // hence no compression signatures to compare. Therefore, skip this process. + if(m_strHash == "NONE") + { + m_pLog->AddLineWarn("Skipping compression signature search as no DQT"); + } + else + { + CompareSignature(); + } + } + + if(nDataAfterEof > 0) + { + m_pLog->AddLine(""); + m_pLog->AddLineHdr("*** Additional Info ***"); + strTmp = + QString("NOTE: Data exists after EOF, range: 0x%1-0x%2 (%3 bytes)") + .arg(m_nPosEoi, 8, 16, QChar('0')) + .arg(m_nPosFileEnd, 8, 16, QChar('0')) + .arg(nDataAfterEof); + m_pLog->AddLine(strTmp); + } + + // Print out the special-purpose outputs + OutputSpecial(); + } + + // Reset the status bar text + if(m_pStatBar) + { + m_pStatBar->showMessage("Done"); + } + + // Mark the file as closed + //m_pWBuf->BufFileUnset(); + +} + +// Determine if the analyzed file is in a state ready for image +// extraction. Confirms that the important JFIF markers have been +// detected in the previous analysis. +// +// PRE: +// - m_nPosEmbedStart +// - m_nPosEmbedEnd +// - m_nPosFileEnd +// +// RETURN: +// - True if image is ready for extraction +// +bool CjfifDecode::ExportJpegPrepare(QString strFileIn, bool bForceSoi, bool bForceEoi, bool bIgnoreEoi) +{ + // Extract from current file + // [m_nPosEmbedStart ... m_nPosEmbedEnd] + // If state is valid (i.e. file opened) + + QString strTmp = ""; + + m_pLog->AddLine(""); + m_pLog->AddLineHdr("*** Exporting JPEG ***"); + + strTmp = QString(" Exporting from: [%1]").arg(strFileIn); + m_pLog->AddLine(strTmp); + + // Only bother to extract if all main sections are present + bool bExtractWarn = false; + + QString strMissing = ""; + + if(!m_bStateEoi) + { + if(!bForceEoi && !bIgnoreEoi) + { + strTmp = QString(" ERROR: Missing marker: %1").arg("EOI"); + m_pLog->AddLineErr(strTmp); + m_pLog->AddLineErr(" Aborting export. Consider enabling [Force EOI] or [Ignore Missing EOI] option"); + return false; + } + else if(bIgnoreEoi) + { + // Ignore the EOI, so mark the end of file, but don't + // set the flag where we force one. + m_nPosEmbedEnd = m_nPosFileEnd; + } + else + { + // We're missing the EOI but the user has requested + // that we force an EOI, so let's fix things up + m_nPosEmbedEnd = m_nPosFileEnd; + } + } + + if((m_nPosEmbedStart == 0) && (m_nPosEmbedEnd == 0)) + { + strTmp = QString(" No frame found at this position in file. Consider using [Img Search]"); + m_pLog->AddLineErr(strTmp); + return false; + } + + if(!m_bStateSoi) + { + if(!bForceSoi) + { + strTmp = QString(" ERROR: Missing marker: %1").arg("SOI"); + m_pLog->AddLineErr(strTmp); + m_pLog->AddLineErr(" Aborting export. Consider enabling [Force SOI] option"); + return false; + } + else + { + // We're missing the SOI but the user has requested + // that we force an SOI, so let's fix things up + } + + } + if(!m_bStateSos) + { + strTmp = QString(" ERROR: Missing marker: %1").arg("SOS"); + m_pLog->AddLineErr(strTmp); + m_pLog->AddLineErr(" Aborting export"); + return false; + } + + if(!m_bStateDqt) + { + bExtractWarn = true; + strMissing += "DQT "; + } + if(!m_bStateDht) + { + bExtractWarn = true; + strMissing += "DHT "; + } + if(!m_bStateSof) + { + bExtractWarn = true; + strMissing += "SOF "; + } + + if(bExtractWarn) + { + strTmp = QString(" NOTE: Missing marker: %1").arg(strMissing); + m_pLog->AddLineWarn(strTmp); + m_pLog->AddLineWarn(" Exported JPEG may not be valid"); + } + + if(m_nPosEmbedEnd < m_nPosEmbedStart) + { + strTmp = QString("ERROR: Invalid SOI-EOI order. Export aborted."); + m_pLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + msgBox.setText(strTmp); + return false; + } + + return true; +} + +#define EXPORT_BUF_SIZE 131072 + +// Export the embedded JPEG image at the current position in the file (with overlays) +// (may be the primary image or even an embedded thumbnail). +bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, + uint32_t nFileLen, bool bOverlayEn, bool bDhtAviInsert, bool bForceSoi, bool bForceEoi) +{ + QFile *pFileOutput; + + QString strTmp = ""; + + strTmp = QString(" Exporting to: [%1]").arg(strFileOut); + m_pLog->AddLine(strTmp); + + if(strFileIn == strFileOut) + { + strTmp = QString("ERROR: Can't overwrite source file. Aborting export."); + m_pLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + msgBox.setText(strTmp); + + return false; + } + + Q_ASSERT(strFileIn != ""); + if(strFileIn == "") + { + strTmp = QString("ERROR: Export but source filename empty"); + m_pLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + msgBox.setText(strTmp); + + return false; + } + + // Open specified file + // Added in shareDenyNone as this apparently helps resolve some people's troubles + // with an error showing: Couldn't open file "Sharing Violation" +// pFileOutput = new CFile(strFileOut, CFile::modeCreate| CFile::modeWrite | CFile::typeBinary | CFile::shareDenyNone); + pFileOutput = new QFile(strFileOut); + + if((pFileOutput->open(QIODevice::WriteOnly)) == false) + { + QString strError; + + strError = QString("ERROR: Couldn't open file for write [%1]: [%2]").arg(strFileOut).arg(pFileOutput->errorString()); + m_pLog->AddLineErr(strError); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strError); + msgBox.exec(); + } + + pFileOutput = NULL; + + return false; + } + + // Don't attempt to load buffer with zero length file! + if(nFileLen == 0) + { + strTmp = QString("ERROR: Source file length error. Please Reprocess first."); + m_pLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + msgBox.setText(strTmp); + + if(pFileOutput) + { + delete pFileOutput; + + pFileOutput = NULL; + } + return false; + } + + // Need to insert fake DHT. Assume we have enough buffer allocated. + // + // Step 1: Copy from SOI -> SOS (not incl) + // Step 2: Insert Fake DHT + // Step 3: Copy from SOS -> EOI + uint32_t nCopyStart; + uint32_t nCopyEnd; + uint32_t nCopyLeft; + uint32_t ind; + uint8_t *pBuf; + + pBuf = new uint8_t[EXPORT_BUF_SIZE + 10]; + + if(!pBuf) + { + if(pFileOutput) + { + delete pFileOutput; + + pFileOutput = NULL; + } + + return false; + } + + // Step 1 + + // If we need to force an SOI, do it now + if(!m_bStateSoi && bForceSoi) + { + m_pLog->AddLine(" Forcing SOI Marker"); + uint8_t anBufSoi[2] = { 0xFF, JFIF_SOI }; + pFileOutput->write(reinterpret_cast(&anBufSoi), 2); + } + + nCopyStart = m_nPosEmbedStart; + nCopyEnd = (m_nPosSos - 1); + ind = nCopyStart; + + while(ind < nCopyEnd) + { + nCopyLeft = nCopyEnd - ind + 1; + + if(nCopyLeft > EXPORT_BUF_SIZE) + { + nCopyLeft = EXPORT_BUF_SIZE; + } + + for(uint32_t ind1 = 0; ind1 < nCopyLeft; ind1++) + { + pBuf[ind1] = Buf(ind + ind1, !bOverlayEn); + } + + pFileOutput->write(reinterpret_cast(pBuf), nCopyLeft); + ind += nCopyLeft; + // NOTE: We ensure nFileLen != 0 earlier + Q_ASSERT(nFileLen > 0); + strTmp = QString("Exporting %1%...").arg(ind * 100 / nFileLen, 3); + SetStatusText(strTmp); + } + + if(bDhtAviInsert) + { + // Step 2. The following struct includes the JFIF marker too + strTmp = " Inserting standard AVI DHT huffman table"; + m_pLog->AddLine(strTmp); +//!! pFileOutput->write(reinterpret_cast(&m_abMJPGDHTSeg), JFIF_DHT_FAKE_SZ); + } + + // Step 3 + nCopyStart = m_nPosSos; + nCopyEnd = m_nPosEmbedEnd - 1; + ind = nCopyStart; + + while(ind < nCopyEnd) + { + nCopyLeft = nCopyEnd - ind + 1; + + if(nCopyLeft > EXPORT_BUF_SIZE) + { + nCopyLeft = EXPORT_BUF_SIZE; + } + for(uint32_t ind1 = 0; ind1 < nCopyLeft; ind1++) + { + pBuf[ind1] = Buf(ind + ind1, !bOverlayEn); + } + + pFileOutput->write(reinterpret_cast(pBuf), nCopyLeft); + ind += nCopyLeft; + // NOTE: We ensure nFileLen != 0 earlier + Q_ASSERT(nFileLen > 0); + strTmp = QString("Exporting %1%%...").arg(ind * 100 / nFileLen, 3); + SetStatusText(strTmp); + } + + // Now optionally insert the EOI Marker + if(bForceEoi) + { + m_pLog->AddLine(" Forcing EOI Marker"); + uint8_t anBufEoi[2] = { 0xFF, JFIF_EOI }; + pFileOutput->write(reinterpret_cast(&anBufEoi), 2); + } + + // Free up space + pFileOutput->close(); + + if(pBuf) + { + delete[]pBuf; + pBuf = NULL; + } + + if(pFileOutput) + { + delete pFileOutput; + + pFileOutput = NULL; + } + + SetStatusText(""); + strTmp = QString(" Export done"); + m_pLog->AddLine(strTmp); + + return true; +} + +// Export a subset of the file with no overlays or mods +bool CjfifDecode::ExportJpegDoRange(QString strFileIn, QString strFileOut, uint32_t nStart, uint32_t nEnd) +{ + QFile *pFileOutput; + + QString strTmp = ""; + + strTmp = QString(" Exporting range to: [%1]").arg(strFileOut); + m_pLog->AddLine(strTmp); + + if(strFileIn == strFileOut) + { + strTmp = "ERROR: Can't overwrite source file. Aborting export."; + m_pLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + msgBox.setText(strTmp); + + return false; + } + + Q_ASSERT(strFileIn != ""); + + if(strFileIn == "") + { + strTmp = QString("ERROR: Export but source filename empty"); + m_pLog->AddLineErr(strTmp); + if(m_pAppConfig->bInteractive) + msgBox.setText(strTmp); + + return false; + } + + pFileOutput = new QFile(strFileOut); + + if((pFileOutput->open(QIODevice::WriteOnly)) == false) + { + QString strError; + + strError = QString("ERROR: Couldn't open file for write [%1]: [%2]").arg(strFileOut).arg(pFileOutput->errorString()); + m_pLog->AddLineErr(strError); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strError); + msgBox.exec(); + } + + pFileOutput = NULL; + + return false; + } + + uint32_t nCopyStart; + uint32_t nCopyEnd; + uint32_t nCopyLeft; + uint32_t ind; + + uint8_t *pBuf; + + pBuf = new uint8_t [EXPORT_BUF_SIZE + 10]; + + if(!pBuf) + { + if(pFileOutput) + { + delete pFileOutput; + + pFileOutput = NULL; + } + return false; + } + + // Step 1 + nCopyStart = nStart; + nCopyEnd = nEnd; + ind = nCopyStart; + + while(ind < nCopyEnd) + { + nCopyLeft = nCopyEnd - ind + 1; + + if(nCopyLeft > EXPORT_BUF_SIZE) + { + nCopyLeft = EXPORT_BUF_SIZE; + } + + for(uint32_t ind1 = 0; ind1 < nCopyLeft; ind1++) + { + pBuf[ind1] = Buf(ind + ind1, false); + } + + pFileOutput->write(reinterpret_cast(pBuf), nCopyLeft); + ind += nCopyLeft; + strTmp = QString("Exporting %1%%...").arg(ind * 100 / (nCopyEnd - nCopyStart), 3); + SetStatusText(strTmp); + } + + // Free up space + pFileOutput->close(); + + if(pBuf) + { + delete[]pBuf; + pBuf = NULL; + } + + if(pFileOutput) + { + delete pFileOutput; + + pFileOutput = NULL; + } + + SetStatusText(""); + strTmp = " Export range done"; + m_pLog->AddLine(strTmp); + + return true; +} + +// ==================================================================================== +// JFIF Decoder Constants +// ==================================================================================== + +// List of the JFIF markers +const MarkerNameTable CjfifDecode::m_pMarkerNames[] = { + {JFIF_SOF0, "SOF0"}, + {JFIF_SOF1, "SOF1"}, + {JFIF_SOF2, "SOF2"}, + {JFIF_SOF3, "SOF3"}, + {JFIF_SOF5, "SOF5"}, + {JFIF_SOF6, "SOF6"}, + {JFIF_SOF7, "SOF7"}, + {JFIF_JPG, "JPG"}, + {JFIF_SOF9, "SOF9"}, + {JFIF_SOF10, "SOF10"}, + {JFIF_SOF11, "SOF11"}, + {JFIF_SOF13, "SOF13"}, + {JFIF_SOF14, "SOF14"}, + {JFIF_SOF15, "SOF15"}, + {JFIF_DHT, "DHT"}, + {JFIF_DAC, "DAC"}, + {JFIF_RST0, "RST0"}, + {JFIF_RST1, "RST1"}, + {JFIF_RST2, "RST2"}, + {JFIF_RST3, "RST3"}, + {JFIF_RST4, "RST4"}, + {JFIF_RST5, "RST5"}, + {JFIF_RST6, "RST6"}, + {JFIF_RST7, "RST7"}, + {JFIF_SOI, "SOI"}, + {JFIF_EOI, "EOI"}, + {JFIF_SOS, "SOS"}, + {JFIF_DQT, "DQT"}, + {JFIF_DNL, "DNL"}, + {JFIF_DRI, "DRI"}, + {JFIF_DHP, "DHP"}, + {JFIF_EXP, "EXP"}, + {JFIF_APP0, "APP0"}, + {JFIF_APP1, "APP1"}, + {JFIF_APP2, "APP2"}, + {JFIF_APP3, "APP3"}, + {JFIF_APP4, "APP4"}, + {JFIF_APP5, "APP5"}, + {JFIF_APP6, "APP6"}, + {JFIF_APP7, "APP7"}, + {JFIF_APP8, "APP8"}, + {JFIF_APP9, "APP9"}, + {JFIF_APP10, "APP10"}, + {JFIF_APP11, "APP11"}, + {JFIF_APP12, "APP12"}, + {JFIF_APP13, "APP13"}, + {JFIF_APP14, "APP14"}, + {JFIF_APP15, "APP15"}, + {JFIF_JPG0, "JPG0"}, + {JFIF_JPG1, "JPG1"}, + {JFIF_JPG2, "JPG2"}, + {JFIF_JPG3, "JPG3"}, + {JFIF_JPG4, "JPG4"}, + {JFIF_JPG5, "JPG5"}, + {JFIF_JPG6, "JPG6"}, + {JFIF_JPG7, "JPG7"}, + {JFIF_JPG8, "JPG8"}, + {JFIF_JPG9, "JPG9"}, + {JFIF_JPG10, "JPG10"}, + {JFIF_JPG11, "JPG11"}, + {JFIF_JPG12, "JPG12"}, + {JFIF_JPG13, "JPG13"}, + {JFIF_COM, "COM"}, + {JFIF_TEM, "TEM"}, + //{JFIF_RES*,"RES"}, + {0x00, "*"}, +}; + +// For Motion JPEG, define the DHT tables that we use since they won't exist +// in each frame within the AVI. This table will be read in during +// DecodeDHT()'s call to Buf(). +const quint8 CjfifDecode::m_abMJPGDHTSeg[JFIF_DHT_FAKE_SZ] = { + /* JPEG DHT Segment for YCrCb omitted from MJPG data */ + 0xFF, 0xC4, 0x01, 0xA2, + 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, + 0x00, 0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, + 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, + 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, + 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, + 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, + 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, + 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, + 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, + 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, + 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, + 0xF9, 0xFA +}; + +// TODO: Add ITU-T Example DQT & DHT +// These will be useful for GeoRaster decode (ie. JPEG-B) + +QString glb_strMsgStopDecode = " Stopping decode. Use [Relaxed Parsing] to continue."; diff --git a/source/JfifDecode.h b/source/JfifDecode.h index 5365cea..8fdb71b 100644 --- a/source/JfifDecode.h +++ b/source/JfifDecode.h @@ -1,413 +1,402 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - This module decodes the JPEG JFIF marker segments -// - Decoding the scan segment (SOS) is not handled here as that is -// done in the CimgDecode class. -// -// ========================================================================== - -#pragma once - -#include "DocLog.h" -#include "ImgDecode.h" -#include "DecodePs.h" -#include "DecodeDicom.h" -#include "WindowBuf.h" -#include "snoop.h" -#include "SnoopConfig.h" - -#include "DbSigs.h" - - -// Disable DICOM support until fully tested -//#define SUPPORT_DICOM - -#define MAX_IFD_COMPS 150 // Maximum number of IFD entry components to display - -#define JFIF_SOF0 0xC0 -#define JFIF_SOF1 0xC1 -#define JFIF_SOF2 0xC2 -#define JFIF_SOF3 0xC3 -#define JFIF_SOF5 0xC5 -#define JFIF_SOF6 0xC6 -#define JFIF_SOF7 0xC7 -#define JFIF_JPG 0xC8 -#define JFIF_SOF9 0xC9 -#define JFIF_SOF10 0xCA -#define JFIF_SOF11 0xCB -#define JFIF_SOF13 0xCD -#define JFIF_SOF14 0xCE -#define JFIF_SOF15 0xCF -#define JFIF_DHT 0xC4 -#define JFIF_DAC 0xCC -#define JFIF_RST0 0xD0 -#define JFIF_RST1 0xD1 -#define JFIF_RST2 0xD2 -#define JFIF_RST3 0xD3 -#define JFIF_RST4 0xD4 -#define JFIF_RST5 0xD5 -#define JFIF_RST6 0xD6 -#define JFIF_RST7 0xD7 -#define JFIF_SOI 0xD8 -#define JFIF_EOI 0xD9 -#define JFIF_SOS 0xDA -#define JFIF_DQT 0xDB -#define JFIF_DNL 0xDC -#define JFIF_DRI 0xDD -#define JFIF_DHP 0xDE -#define JFIF_EXP 0xDF -#define JFIF_APP0 0xE0 -#define JFIF_APP1 0xE1 -#define JFIF_APP2 0xE2 -#define JFIF_APP3 0xE3 -#define JFIF_APP4 0xE4 -#define JFIF_APP5 0xE5 -#define JFIF_APP6 0xE6 -#define JFIF_APP7 0xE7 -#define JFIF_APP8 0xE8 -#define JFIF_APP9 0xE9 -#define JFIF_APP10 0xEA -#define JFIF_APP11 0xEB -#define JFIF_APP12 0xEC -#define JFIF_APP13 0xED -#define JFIF_APP14 0xEE -#define JFIF_APP15 0xEF -#define JFIF_JPG0 0xF0 -#define JFIF_JPG1 0xF1 -#define JFIF_JPG2 0xF2 -#define JFIF_JPG3 0xF3 -#define JFIF_JPG4 0xF4 -#define JFIF_JPG5 0xF5 -#define JFIF_JPG6 0xF6 -#define JFIF_JPG7 0xF7 -#define JFIF_JPG8 0xF8 -#define JFIF_JPG9 0xF9 -#define JFIF_JPG10 0xFA -#define JFIF_JPG11 0xFB -#define JFIF_JPG12 0xFC -#define JFIF_JPG13 0xFD -#define JFIF_COM 0xFE -#define JFIF_TEM 0x01 - -#define JFIF_DHT_FAKE 0x999999C4 -#define JFIF_DHT_FAKE_SZ 0x1A4 - -#define APP14_COLXFM_UNSET -1 -#define APP14_COLXFM_UNK_RGB 0 -#define APP14_COLXFM_YCC 1 -#define APP14_COLXFM_YCCK 2 - -#define MAX_IDENTIFIER 256 // Max length for identifier strings (include terminator) - -struct CStr2 { - CString strTag; - CString strVal; - bool bUnknown; // Tag is not known -}; - - -struct MarkerNameTable { - unsigned nCode; - LPTSTR strName; -}; - - -class CjfifDecode -{ - // Constructor & Initialization - public: - CjfifDecode(CDocLog* pLog,CwindowBuf* pWBuf,CimgDecode* pImgDec); - ~CjfifDecode(); - -public: - void Reset(); - - // -------------------------------------- - // Class Methods - // -------------------------------------- - - // Public accesssor & mutator functions -public: - void GetAviMode(bool &bIsAvi,bool &bIsMjpeg); - void SetAviMode(bool bIsAvi,bool bIsMjpeg); - void ImgSrcChanged(); - unsigned long GetPosEmbedStart(); - unsigned long GetPosEmbedEnd(); - void GetDecodeSummary(CString &strHash,CString &strHashRot,CString &strImgExifMake,CString &strImgExifModel, - CString &strImgQualExif,CString &strSoftware,teDbAdd &eDbReqSuggest); - unsigned GetDqtZigZagIndex(unsigned nInd,bool bZigZag); - unsigned GetDqtQuantStd(unsigned nInd); - - bool GetDecodeStatus(); - -private: - - - // Export Operations -public: -// void ExportRangeSet(unsigned nStart, unsigned nEnd); - bool ExportJpegPrepare(CString strFileIn,bool bForceSoi,bool bForceEoi,bool bIgnoreEoi); - bool ExportJpegDo(CString strFileIn, CString strFileOut, unsigned long nFileLen, - bool bOverlayEn, bool bDhtAviInsert,bool bForceSoi,bool bForceEoi); -private: - bool ExportJpegDoRange(CString strFileIn, CString strFileOut, - unsigned long nStart, unsigned long nEnd); - - - // General parsing -public: - void ProcessFile(CFile* inFile); -private: - unsigned DecodeMarker(); - bool ExpectMarkerEnd(unsigned long nMarkerStart,unsigned nMarkerLen); - void DecodeEmbeddedThumb(); - bool DecodeAvi(); - - bool ValidateValue(unsigned &nVal,unsigned nMin,unsigned nMax,CString strName,bool bOverride,unsigned nOverrideVal); - - // Marker specific parsing - bool GetMarkerName(unsigned nCode,CString &markerStr); - unsigned DecodeExifIfd(CString strIfd,unsigned nPosExifStart,unsigned nStartIfdPtr); -// unsigned DecodeMakerIfd(unsigned ifd_tag,unsigned ptr,unsigned len); - bool DecodeMakerSubType(); - void DecodeDHT(bool bInject); - unsigned DecodeApp13Ps(); - unsigned DecodeApp2Flashpix(); - unsigned DecodeApp2IccProfile(unsigned nLen); - unsigned DecodeIccHeader(unsigned nPos); - - // DQT / DHT - void ClearDQT(); - void SetDQTQuick(unsigned short anDqt0[64],unsigned short anDqt1[64]); - void GenLookupHuffMask(); - - // Field parsing - bool DecodeValRational(unsigned nPos,float &nVal); - CString DecodeValFraction(unsigned nPos); - bool DecodeValGPS(unsigned nPos,CString &strCoord); - bool PrintValGPS(unsigned nCount, float fCoord1, float fCoord2, float fCoord3,CString &strCoord); - CString DecodeIccDateTime(unsigned anVal[3]); - CString LookupExifTag(CString strSect, unsigned nTag, bool &bUnknown); - CStr2 LookupMakerCanonTag(unsigned nMainTag,unsigned nSubTag,unsigned nVal); - - - // Signature database -public: - void PrepareSendSubmit(CString strQual,teSource eUserSource,CString strUserSoftware,CString strUserNotes); -private: - void PrepareSignature(); - void PrepareSignatureSingle(bool bRotate); - void PrepareSignatureThumb(); - void PrepareSignatureThumbSingle(bool bRotate); - bool CompareSignature(bool bQuiet); - void SendSubmit(CString strExifMake, CString strExifModel, CString strQual, - CString strDqt0, CString strDqt1, CString strDqt2, CString strDqt3, - CString strCss, - CString strSig, CString strSigRot, CString strSigThumb, - CString strSigThumbRot, float fQFact0, float fQFact1, unsigned nImgW, unsigned nImgH, - CString strExifSoftware, CString strComment, teMaker eMaker, - teSource eUserSource, CString strUserSoftware, CString strExtra, - CString strUserNotes, unsigned nExifLandscape, - unsigned nThumbX,unsigned nThumbY); - void OutputSpecial(); - - - // Display routines - void DbgAddLine(LPCTSTR strLine); - void AddHeader(unsigned nCode); - CString PrintAsHexUC(unsigned char* anBytes,unsigned nCount); - CString PrintAsHex8(unsigned* anBytes,unsigned nCount); - CString PrintAsHex32(unsigned* anWords,unsigned nCount); - - // Buffer access - BYTE Buf(unsigned long nOffset,bool bClean); - void UnByteSwap4(unsigned nVal,unsigned &nByte0,unsigned &nByte1,unsigned &nByte2,unsigned &nByte3); - unsigned ByteSwap4(unsigned nByte0,unsigned nByte1, unsigned nByte2, unsigned nByte3); - unsigned ByteSwap2(unsigned nByte0,unsigned nByte1); - unsigned ReadSwap2(unsigned nPos); - unsigned ReadSwap4(unsigned nPos); - unsigned ReadBe4(unsigned nPos); - - // UI elements -public: - void SetStatusBar(CStatusBar* pStatBar); -private: - void SetStatusText(CString strText); - void DecodeErrCheck(bool bRet); - - - // -------------------------------------- - // Class variables - // -------------------------------------- - -private: - // Configuration - CSnoopConfig* m_pAppConfig; - bool m_bVerbose; - bool m_bOutputDB; - bool m_bBufFakeDHT; // Flag to redirect DHT read to AVI DHT over Buffer content - - // General classes required for decoding - CwindowBuf* m_pWBuf; - CimgDecode* m_pImgDec; - CDecodePs* m_pPsDec; - CDecodeDicom* m_pDecDicom; - - // UI elements & log - CDocLog* m_pLog; - CStatusBar* m_pStatBar; // Link to status bar - - // Constants - static const BYTE m_abMJPGDHTSeg[JFIF_DHT_FAKE_SZ]; // Motion JPEG DHT - static const MarkerNameTable m_pMarkerNames[]; - - - - // Status - bool m_bImgOK; // Img decode encounter SOF - bool m_bAvi; // Is it an AVI file? - bool m_bAviMjpeg; // Is it a MotionJPEG AVI file? - bool m_bPsd; // Is it a Photoshop file? - - bool m_pImgSrcDirty; // Do we need to recalculate the scan decode? - - - // File position records - unsigned long m_nPos; // Current file/buffer position - unsigned long m_nPosEoi; // Position of EOI (0xFFD9) marker - unsigned m_nPosSos; - unsigned long m_nPosEmbedStart; // Embedded/offset start - unsigned long m_nPosEmbedEnd; // Embedded/offset end - unsigned long m_nPosFileEnd; // End of file position - - - // Decoder state - TCHAR m_acApp0Identifier[MAX_IDENTIFIER]; // APP0 type: JFIF, AVI1, etc. - - float m_afStdQuantLumCompare[64]; - float m_afStdQuantChrCompare[64]; - - unsigned m_anMaskLookup[32]; - - unsigned m_nImgVersionMajor; - unsigned m_nImgVersionMinor; - unsigned m_nImgUnits; - unsigned m_nImgDensityX; - unsigned m_nImgDensityY; - unsigned m_nImgThumbSizeX; - unsigned m_nImgThumbSizeY; - - bool m_bImgProgressive; // Progressive scan? - bool m_bImgSofUnsupported; // SOF mode unsupported - skip SOI content - - CString m_strComment; // Comment string - - unsigned m_nSosNumCompScan_Ns; - unsigned m_nSosSpectralStart_Ss; - unsigned m_nSosSpectralEnd_Se; - unsigned m_nSosSuccApprox_A; - - bool m_nImgRstEn; // DRI seen - unsigned m_nImgRstInterval; - - unsigned short m_anImgDqtTbl[MAX_DQT_DEST_ID][MAX_DQT_COEFF]; - double m_adImgDqtQual[MAX_DQT_DEST_ID]; - bool m_abImgDqtSet[MAX_DQT_DEST_ID]; // Has this table been configured? - unsigned m_anDhtNumCodesLen_Li[17]; - - unsigned m_nSofPrecision_P; - unsigned m_nSofNumLines_Y; - unsigned m_nSofSampsPerLine_X; - unsigned m_nSofNumComps_Nf; // Number of components in frame (might not equal m_nSosNumCompScan_Ns) - - // Define Quantization table details for the indexed Component Identifier - // - Component identifier (SOF:Ci) has a range of 0..255 - unsigned m_anSofQuantCompId[MAX_SOF_COMP_NF]; // SOF:Ci, index is i-1 - unsigned m_anSofQuantTblSel_Tqi[MAX_SOF_COMP_NF]; - unsigned m_anSofHorzSampFact_Hi[MAX_SOF_COMP_NF]; - unsigned m_anSofVertSampFact_Vi[MAX_SOF_COMP_NF]; - unsigned m_nSofHorzSampFactMax_Hmax; - unsigned m_nSofVertSampFactMax_Vmax; - - // FIXME: Move to CDecodePs - unsigned m_nImgQualPhotoshopSa; - unsigned m_nImgQualPhotoshopSfw; - - int m_nApp14ColTransform; // Color transform from JFIF APP14 Adobe marker (-1 if not set) - - teLandscape m_eImgLandscape; // Landscape vs Portrait - CString m_strImgQuantCss; // Chroma subsampling (e.g. "2x1") - - unsigned m_nImgExifEndian; // 0=Intel 1=Motorola - unsigned m_nImgExifSubIfdPtr; - unsigned m_nImgExifGpsIfdPtr; - unsigned m_nImgExifInteropIfdPtr; - unsigned m_nImgExifMakerPtr; - - bool m_bImgExifMakeSupported; // Mark makes that we support decode for - unsigned m_nImgExifMakeSubtype; // Used for Nikon (e.g. type3) - - CString m_strImgExtras; // Extra strings used for DB submission - - // Embedded EXIF Thumbnail - unsigned m_nImgExifThumbComp; - unsigned m_nImgExifThumbOffset; - unsigned m_nImgExifThumbLen; - unsigned m_anImgThumbDqt[4][64]; - bool m_abImgDqtThumbSet[4]; - CString m_strHashThumb; - CString m_strHashThumbRot; - unsigned m_nImgThumbNumLines; - unsigned m_nImgThumbSampsPerLine; - - // Signature handling - bool m_bSigExactInDB; // Is current entry already in local DB? - - // State of decoder -- have we seen each marker? - bool m_bStateAbort; // Do we abort decoding? (eg. user hits cancel after errs) - - bool m_bStateSoi; - bool m_bStateDht; - bool m_bStateDhtOk; - bool m_bStateDhtFake; // Fake DHT required for AVI - bool m_bStateDqt; - bool m_bStateDqtOk; - bool m_bStateSof; - bool m_bStateSofOk; - bool m_bStateSos; - bool m_bStateSosOk; - bool m_bStateEoi; - - - teDbAdd m_eDbReqSuggest; - CString m_strHash; - CString m_strHashRot; - CString m_strImgExifMake; - CString m_strImgExifModel; - CString m_strImgQualExif; // Quality (e.g. "fine") from makernotes - CString m_strSoftware; // EXIF Software field - bool m_bImgExifMakernotes; // Are any Makernotes present? - - teEdited m_eImgEdited; // Image edited? 0 = unset, 1 = yes, etc. - - -}; - +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - This module decodes the JPEG JFIF marker segments +// - Decoding the scan segment (SOS) is not handled here as that is +// done in the CimgDecode class. +// +// ========================================================================== + +#ifndef JFIFDECODE_H +#define JFIFDECODE_H + +#include +#include +#include + +#include "DocLog.h" +#include "ImgDecode.h" +#include "DecodePs.h" +#include "DecodeDicom.h" +#include "WindowBuf.h" +#include "snoop.h" +#include "SnoopConfig.h" + +#include "DbSigs.h" + +// Disable DICOM support until fully tested +//#define SUPPORT_DICOM + +static const int32_t MAX_IFD_COMPS = 150; // Maximum number of IFD entry components to display + +static const uint32_t JFIF_SOF0 = 0xC0; +static const uint32_t JFIF_SOF1 = 0xC1; +static const uint32_t JFIF_SOF2 = 0xC2; +static const uint32_t JFIF_SOF3 = 0xC3; +static const uint32_t JFIF_SOF5 = 0xC5; +static const uint32_t JFIF_SOF6 = 0xC6; +static const uint32_t JFIF_SOF7 = 0xC7; +static const uint32_t JFIF_JPG = 0xC8; +static const uint32_t JFIF_SOF9 = 0xC9; +static const uint32_t JFIF_SOF10 = 0xCA; +static const uint32_t JFIF_SOF11 = 0xCB; +static const uint32_t JFIF_SOF13 = 0xCD; +static const uint32_t JFIF_SOF14 = 0xCE; +static const uint32_t JFIF_SOF15 = 0xCF; +static const uint32_t JFIF_DHT = 0xC4; +static const uint32_t JFIF_DAC = 0xCC; +//static const uint32_t JFIF_RST0 = 0xD0; +//static const uint32_t JFIF_RST1 = 0xD1; +//static const uint32_t JFIF_RST2 = 0xD2; +//static const uint32_t JFIF_RST3 = 0xD3; +//static const uint32_t JFIF_RST4 = 0xD4; +//static const uint32_t JFIF_RST5 = 0xD5; +//static const uint32_t JFIF_RST6 = 0xD6; +//static const uint32_t JFIF_RST7 = 0xD7; +static const uint32_t JFIF_SOI = 0xD8; +//static const uint32_t JFIF_EOI = 0xD9; +static const uint32_t JFIF_SOS = 0xDA; +static const uint32_t JFIF_DQT = 0xDB; +static const uint32_t JFIF_DNL = 0xDC; +static const uint32_t JFIF_DRI = 0xDD; +static const uint32_t JFIF_DHP = 0xDE; +static const uint32_t JFIF_EXP = 0xDF; +static const uint32_t JFIF_APP0 = 0xE0; +static const uint32_t JFIF_APP1 = 0xE1; +static const uint32_t JFIF_APP2 = 0xE2; +static const uint32_t JFIF_APP3 = 0xE3; +static const uint32_t JFIF_APP4 = 0xE4; +static const uint32_t JFIF_APP5 = 0xE5; +static const uint32_t JFIF_APP6 = 0xE6; +static const uint32_t JFIF_APP7 = 0xE7; +static const uint32_t JFIF_APP8 = 0xE8; +static const uint32_t JFIF_APP9 = 0xE9; +static const uint32_t JFIF_APP10 = 0xEA; +static const uint32_t JFIF_APP11 = 0xEB; +static const uint32_t JFIF_APP12 = 0xEC; +static const uint32_t JFIF_APP13 = 0xED; +static const uint32_t JFIF_APP14 = 0xEE; +static const uint32_t JFIF_APP15 = 0xEF; +static const uint32_t JFIF_JPG0 = 0xF0; +static const uint32_t JFIF_JPG1 = 0xF1; +static const uint32_t JFIF_JPG2 = 0xF2; +static const uint32_t JFIF_JPG3 = 0xF3; +static const uint32_t JFIF_JPG4 = 0xF4; +static const uint32_t JFIF_JPG5 = 0xF5; +static const uint32_t JFIF_JPG6 = 0xF6; +static const uint32_t JFIF_JPG7 = 0xF7; +static const uint32_t JFIF_JPG8 = 0xF8; +static const uint32_t JFIF_JPG9 = 0xF9; +static const uint32_t JFIF_JPG10 = 0xFA; +static const uint32_t JFIF_JPG11 = 0xFB; +static const uint32_t JFIF_JPG12 = 0xFC; +static const uint32_t JFIF_JPG13 = 0xFD; +static const uint32_t JFIF_COM = 0xFE; +static const uint32_t JFIF_TEM = 0x01; +static const uint32_t JFIF_DHT_FAKE = 0x999999C4; +static const uint32_t JFIF_DHT_FAKE_SZ = 0x1A4; + +#define APP14_COLXFM_UNSET -1 +#define APP14_COLXFM_UNK_RGB 0 +#define APP14_COLXFM_YCC 1 +#define APP14_COLXFM_YCCK 2 + +static const int32_t MAX_IDENTIFIER = 256; // Max length for identifier strings (include terminator) + +struct CStr2 +{ + QString strTag; + QString strVal; + bool bUnknown; // Tag is not known +}; + +struct MarkerNameTable +{ + uint32_t nCode; + QString strName; +}; + +class CjfifDecode : public QObject +{ + Q_OBJECT + + // Constructor & Initialization +public: + CjfifDecode(CDocLog * pLog, CwindowBuf * pWBuf, CimgDecode * pImgDec); + ~CjfifDecode(); + + void Reset(); + + // -------------------------------------- + // Class Methods + // -------------------------------------- + + // Public accesssor & mutator functions + void GetAviMode(bool & bIsAvi, bool & bIsMjpeg); + void SetAviMode(bool bIsAvi, bool bIsMjpeg); + void ImgSrcChanged(); + uint32_t GetPosEmbedStart(); + uint32_t GetPosEmbedEnd(); + void GetDecodeSummary(QString & strHash, QString & strHashRot, QString & strImgExifMake, QString & strImgExifModel, + QString & strImgQualExif, QString & strSoftware, teDbAdd & eDbReqSuggest); + uint32_t GetDqtZigZagIndex(uint32_t nInd, bool bZigZag); + uint32_t GetDqtQuantStd(uint32_t nInd); + + bool GetDecodeStatus(); + + // void ExportRangeSet(uint32_t nStart, uint32_t nEnd); + bool ExportJpegPrepare(QString strFileIn, bool bForceSoi, bool bForceEoi, bool bIgnoreEoi); + bool ExportJpegDo(QString strFileIn, QString strFileOut, uint32_t nFileLen, + bool bOverlayEn, bool bDhtAviInsert, bool bForceSoi, bool bForceEoi); + + void ProcessFile(QFile * inFile); + + // UI elements + void SetStatusBar(QStatusBar * pStatBar); + + // Signature database: + void PrepareSendSubmit(QString strQual, teSource eUserSource, QString strUserSoftware, QString strUserNotes); + +signals: + void updateStatus(QString statusMsg, int); + +private: + CjfifDecode &operator = (const CjfifDecode&); + CjfifDecode(CjfifDecode&); + + void PrepareSignature(); + void PrepareSignatureSingle(bool bRotate); + void PrepareSignatureThumb(); + void PrepareSignatureThumbSingle(bool bRotate); + bool CompareSignature(bool bQuiet); + void SendSubmit(QString strExifMake, QString strExifModel, QString strQual, + QString strDqt0, QString strDqt1, QString strDqt2, QString strDqt3, + QString strCss, + QString strSig, QString strSigRot, QString strSigThumb, + QString strSigThumbRot, float fQFact0, float fQFact1, uint32_t nImgW, uint32_t nImgH, + QString strExifSoftware, QString strComment, teMaker eMaker, + teSource eUserSource, QString strUserSoftware, QString strExtra, + QString strUserNotes, uint32_t nExifLandscape, uint32_t nThumbX, uint32_t nThumbY); + void OutputSpecial(); + + // Display routines + void DbgAddLine(QString strLine); + void AddHeader(uint32_t nCode); + QString PrintAsHexUC(uint8_t *anBytes, uint32_t nCount); + QString PrintAsHex8(uint32_t *anBytes, uint32_t nCount); + QString PrintAsHex32(uint32_t *anWords, uint32_t nCount); + + // Buffer access + quint8 Buf(uint32_t nOffset, bool bClean); + void UnByteSwap4(uint32_t nVal, uint32_t &nByte0, uint32_t &nByte1, uint32_t &nByte2, uint32_t &nByte3); + uint32_t ByteSwap4(uint32_t nByte0, uint32_t nByte1, uint32_t nByte2, uint32_t nByte3); + uint32_t ByteSwap2(uint32_t nByte0, uint32_t nByte1); + uint32_t ReadSwap2(uint32_t nPos); + uint32_t ReadSwap4(uint32_t nPos); + uint32_t ReadBe4(uint32_t nPos); + + bool ExportJpegDoRange(QString strFileIn, QString strFileOut, uint32_t nStart, uint32_t nEnd); + + uint32_t DecodeMarker(); + bool ExpectMarkerEnd(uint32_t nMarkerStart, uint32_t nMarkerLen); + void DecodeEmbeddedThumb(); + bool DecodeAvi(); + + bool ValidateValue(uint32_t &nVal, uint32_t nMin, uint32_t nMax, QString strName, bool bOverride, uint32_t nOverrideVal); + + // Marker specific parsing + bool GetMarkerName(uint32_t nCode, QString & markerStr); + uint32_t DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint32_t nStartIfdPtr); +// uint32_t DecodeMakerIfd(uint32_t ifd_tag,uint32_t ptr,uint32_t len); + bool DecodeMakerSubType(); + void DecodeDHT(bool bInject); + uint32_t DecodeApp13Ps(); + uint32_t DecodeApp2Flashpix(); + uint32_t DecodeApp2IccProfile(uint32_t nLen); + uint32_t DecodeIccHeader(uint32_t nPos); + + // DQT / DHT + void ClearDQT(); + void SetDQTQuick(uint16_t anDqt0[], uint16_t anDqt1[]); + void GenLookupHuffMask(); + + // Field parsing + bool DecodeValRational(uint32_t nPos, float &nVal); + QString DecodeValFraction(uint32_t nPos); + bool DecodeValGPS(uint32_t nPos, QString & strCoord); + bool PrintValGPS(uint32_t nCount, float fCoord1, float fCoord2, float fCoord3, QString & strCoord); + QString DecodeIccDateTime(uint32_t anVal[3]); + QString LookupExifTag(QString strSect, uint32_t nTag, bool & bUnknown); + CStr2 LookupMakerCanonTag(uint32_t nMainTag, uint32_t nSubTag, uint32_t nVal); + + void SetStatusText(QString strText); + void DecodeErrCheck(bool bRet); + + // -------------------------------------- + // Class variables + // -------------------------------------- + + // Configuration + // CSnoopConfig * m_pAppConfig; + bool m_bVerbose; + bool m_bOutputDB; + bool m_bBufFakeDHT; // Flag to redirect DHT read to AVI DHT over Buffer content + + // General classes required for decoding + CwindowBuf *m_pWBuf; + CimgDecode *m_pImgDec; + CDecodePs *m_pPsDec; + CDecodeDicom *m_pDecDicom; + + // UI elements & log + QMessageBox msgBox; + CDocLog *m_pLog; + QStatusBar *m_pStatBar; // Link to status bar + + // Constants + static const uint8_t m_abMJPGDHTSeg[JFIF_DHT_FAKE_SZ]; // Motion JPEG DHT + static const MarkerNameTable m_pMarkerNames[]; + + // Status + bool m_bImgOK; // Img decode encounter SOF + bool m_bAvi; // Is it an AVI file? + bool m_bAviMjpeg; // Is it a MotionJPEG AVI file? + bool m_bPsd; // Is it a Photoshop file? + + bool m_pImgSrcDirty; // Do we need to recalculate the scan decode? + + // File position records + uint32_t m_nPos; // Current file/buffer position + uint32_t m_nPosEoi; // Position of EOI (0xFFD9) marker + uint32_t m_nPosSos; + uint32_t m_nPosEmbedStart; // Embedded/offset start + uint32_t m_nPosEmbedEnd; // Embedded/offset end + uint32_t m_nPosFileEnd; // End of file position + + // Decoder state + char m_acApp0Identifier[MAX_IDENTIFIER]; // APP0 type: JFIF, AVI1, etc. + + float m_afStdQuantLumCompare[64]; + float m_afStdQuantChrCompare[64]; + + uint32_t m_anMaskLookup[32]; + + uint32_t m_nImgVersionMajor; + uint32_t m_nImgVersionMinor; + uint32_t m_nImgUnits; + uint32_t m_nImgDensityX; + uint32_t m_nImgDensityY; + uint32_t m_nImgThumbSizeX; + uint32_t m_nImgThumbSizeY; + + bool m_bImgProgressive; // Progressive scan? + bool m_bImgSofUnsupported; // SOF mode unsupported - skip SOI content + + QString m_strComment; // Comment string + + uint32_t m_nSosNumCompScan_Ns; + uint32_t m_nSosSpectralStart_Ss; + uint32_t m_nSosSpectralEnd_Se; + uint32_t m_nSosSuccApprox_A; + + bool m_nImgRstEn; // DRI seen + uint32_t m_nImgRstInterval; + + uint16_t m_anImgDqtTbl[MAX_DQT_DEST_ID][MAX_DQT_COEFF]; + double m_adImgDqtQual[MAX_DQT_DEST_ID]; + bool m_abImgDqtSet[MAX_DQT_DEST_ID]; // Has this table been configured? + uint32_t m_anDhtNumCodesLen_Li[17]; + + uint32_t m_nSofPrecision_P; + uint32_t m_nSofNumLines_Y; + uint32_t m_nSofSampsPerLine_X; + uint32_t m_nSofNumComps_Nf; // Number of components in frame (might not equal m_nSosNumCompScan_Ns) + + // Define Quantization table details for the indexed Component Identifier + // - Component identifier (SOF:Ci) has a range of 0..255 + uint32_t m_anSofQuantCompId[MAX_SOF_COMP_NF]; // SOF:Ci, index is i-1 + uint32_t m_anSofQuantTblSel_Tqi[MAX_SOF_COMP_NF]; + uint32_t m_anSofHorzSampFact_Hi[MAX_SOF_COMP_NF]; + uint32_t m_anSofVertSampFact_Vi[MAX_SOF_COMP_NF]; + uint32_t m_nSofHorzSampFactMax_Hmax; + uint32_t m_nSofVertSampFactMax_Vmax; + + // FIXME: Move to CDecodePs + uint32_t m_nImgQualPhotoshopSa; + uint32_t m_nImgQualPhotoshopSfw; + + int m_nApp14ColTransform; // Color transform from JFIF APP14 Adobe marker (-1 if not set) + + teLandscape m_eImgLandscape; // Landscape vs Portrait + QString m_strImgQuantCss; // Chroma subsampling (e.g. "2x1") + + uint32_t m_nImgExifEndian; // 0=Intel 1=Motorola + uint32_t m_nImgExifSubIfdPtr; + uint32_t m_nImgExifGpsIfdPtr; + uint32_t m_nImgExifInteropIfdPtr; + uint32_t m_nImgExifMakerPtr; + + bool m_bImgExifMakeSupported; // Mark makes that we support decode for + uint32_t m_nImgExifMakeSubtype; // Used for Nikon (e.g. type3) + + QString m_strImgExtras; // Extra strings used for DB submission + + // Embedded EXIF Thumbnail + uint32_t m_nImgExifThumbComp; + uint32_t m_nImgExifThumbOffset; + uint32_t m_nImgExifThumbLen; + uint32_t m_anImgThumbDqt[4][64]; + bool m_abImgDqtThumbSet[4]; + QString m_strHashThumb; + QString m_strHashThumbRot; + uint32_t m_nImgThumbNumLines; + uint32_t m_nImgThumbSampsPerLine; + + // Signature handling + bool m_bSigExactInDB; // Is current entry already in local DB? + + // State of decoder -- have we seen each marker? + bool m_bStateAbort; // Do we abort decoding? (eg. user hits cancel after errs) + + bool m_bStateSoi; + bool m_bStateDht; + bool m_bStateDhtOk; + bool m_bStateDhtFake; // Fake DHT required for AVI + bool m_bStateDqt; + bool m_bStateDqtOk; + bool m_bStateSof; + bool m_bStateSofOk; + bool m_bStateSos; + bool m_bStateSosOk; + bool m_bStateEoi; + + teDbAdd m_eDbReqSuggest; + QString m_strHash; + QString m_strHashRot; + QString m_strImgExifMake; + QString m_strImgExifModel; + QString m_strImgQualExif; // Quality (e.g. "fine") from makernotes + QString m_strSoftware; // EXIF Software field + bool m_bImgExifMakernotes; // Are any Makernotes present? + + teEdited m_eImgEdited; // Image edited? 0 = unset, 1 = yes, etc. +}; + +#endif diff --git a/source/Md5.cpp b/source/Md5.cpp index f073318..91d07ba 100644 --- a/source/Md5.cpp +++ b/source/Md5.cpp @@ -1,312 +1,311 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code is derived from the following project on CodeProject: -// -// Title: ReHash - A console-based hash calculator -// Author: Dominik Reichl -// URL: http://www.codeproject.com/Articles/3945/ReHash-A-console-based-hash-calculator -// Date: Apr 11, 2003 -// -// ==================================================================================================== - - -// Free for all implementation of the MD5 hash algorithm - -/* - ********************************************************************** - ** MD5.cpp ** - ** ** - ** - Style modified by Tony Ray, January 2001 ** - ** Added support for randomizing initialization constants ** - ** - Style modified by Dominik Reichl, April 2003 ** - ** Optimized code ** - ** ** - ********************************************************************** - */ - -/* - ********************************************************************** - ** MD5.c ** - ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** - ** Created: 2/17/90 RLR ** - ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** - ********************************************************************** - */ - -/* - ********************************************************************** - ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** - ** ** - ** License to copy and use this software is granted provided that ** - ** it is identified as the "RSA Data Security, Inc. MD5 Message ** - ** Digest Algorithm" in all material mentioning or referencing this ** - ** software or this function. ** - ** ** - ** License is also granted to make and use derivative works ** - ** provided that such works are identified as "derived from the RSA ** - ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** - ** material mentioning or referencing the derived work. ** - ** ** - ** RSA Data Security, Inc. makes no representations concerning ** - ** either the merchantability of this software or the suitability ** - ** of this software for any particular purpose. It is provided "as ** - ** is" without express or implied warranty of any kind. ** - ** ** - ** These notices must be retained in any copies of any part of this ** - ** documentation and/or software. ** - ********************************************************************** - */ - -#include -#include - -#include "stdafx.h" //CAL! Added to avoid compile error C1010 - -#include "MD5.h" - -/* Padding */ -static unsigned char MD5_PADDING[64] = { - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -/* MD5_F, MD5_G and MD5_H are basic MD5 functions: selection, majority, parity */ -#define MD5_F(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define MD5_H(x, y, z) ((x) ^ (y) ^ (z)) -#define MD5_I(x, y, z) ((y) ^ ((x) | (~z))) - -/* ROTATE_LEFT rotates x left n bits */ -#ifndef ROTATE_LEFT -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) -#endif - -/* MD5_FF, MD5_GG, MD5_HH, and MD5_II transformations for rounds 1, 2, 3, and 4 */ -/* Rotation is separate from addition to prevent recomputation */ -#define MD5_FF(a, b, c, d, x, s, ac) {(a) += MD5_F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define MD5_GG(a, b, c, d, x, s, ac) {(a) += MD5_G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define MD5_HH(a, b, c, d, x, s, ac) {(a) += MD5_H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } -#define MD5_II(a, b, c, d, x, s, ac) {(a) += MD5_I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } - -/* Constants for transformation */ -#define MD5_S11 7 /* Round 1 */ -#define MD5_S12 12 -#define MD5_S13 17 -#define MD5_S14 22 -#define MD5_S21 5 /* Round 2 */ -#define MD5_S22 9 -#define MD5_S23 14 -#define MD5_S24 20 -#define MD5_S31 4 /* Round 3 */ -#define MD5_S32 11 -#define MD5_S33 16 -#define MD5_S34 23 -#define MD5_S41 6 /* Round 4 */ -#define MD5_S42 10 -#define MD5_S43 15 -#define MD5_S44 21 - -/* Basic MD5 step. MD5_Transform buf based on in */ -static void MD5_Transform (UINT4 *buf, UINT4 *in) -{ - UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; - - /* Round 1 */ - MD5_FF ( a, b, c, d, in[ 0], MD5_S11, (UINT4) 3614090360u); /* 1 */ - MD5_FF ( d, a, b, c, in[ 1], MD5_S12, (UINT4) 3905402710u); /* 2 */ - MD5_FF ( c, d, a, b, in[ 2], MD5_S13, (UINT4) 606105819u); /* 3 */ - MD5_FF ( b, c, d, a, in[ 3], MD5_S14, (UINT4) 3250441966u); /* 4 */ - MD5_FF ( a, b, c, d, in[ 4], MD5_S11, (UINT4) 4118548399u); /* 5 */ - MD5_FF ( d, a, b, c, in[ 5], MD5_S12, (UINT4) 1200080426u); /* 6 */ - MD5_FF ( c, d, a, b, in[ 6], MD5_S13, (UINT4) 2821735955u); /* 7 */ - MD5_FF ( b, c, d, a, in[ 7], MD5_S14, (UINT4) 4249261313u); /* 8 */ - MD5_FF ( a, b, c, d, in[ 8], MD5_S11, (UINT4) 1770035416u); /* 9 */ - MD5_FF ( d, a, b, c, in[ 9], MD5_S12, (UINT4) 2336552879u); /* 10 */ - MD5_FF ( c, d, a, b, in[10], MD5_S13, (UINT4) 4294925233u); /* 11 */ - MD5_FF ( b, c, d, a, in[11], MD5_S14, (UINT4) 2304563134u); /* 12 */ - MD5_FF ( a, b, c, d, in[12], MD5_S11, (UINT4) 1804603682u); /* 13 */ - MD5_FF ( d, a, b, c, in[13], MD5_S12, (UINT4) 4254626195u); /* 14 */ - MD5_FF ( c, d, a, b, in[14], MD5_S13, (UINT4) 2792965006u); /* 15 */ - MD5_FF ( b, c, d, a, in[15], MD5_S14, (UINT4) 1236535329u); /* 16 */ - - /* Round 2 */ - MD5_GG ( a, b, c, d, in[ 1], MD5_S21, (UINT4) 4129170786u); /* 17 */ - MD5_GG ( d, a, b, c, in[ 6], MD5_S22, (UINT4) 3225465664u); /* 18 */ - MD5_GG ( c, d, a, b, in[11], MD5_S23, (UINT4) 643717713u); /* 19 */ - MD5_GG ( b, c, d, a, in[ 0], MD5_S24, (UINT4) 3921069994u); /* 20 */ - MD5_GG ( a, b, c, d, in[ 5], MD5_S21, (UINT4) 3593408605u); /* 21 */ - MD5_GG ( d, a, b, c, in[10], MD5_S22, (UINT4) 38016083u); /* 22 */ - MD5_GG ( c, d, a, b, in[15], MD5_S23, (UINT4) 3634488961u); /* 23 */ - MD5_GG ( b, c, d, a, in[ 4], MD5_S24, (UINT4) 3889429448u); /* 24 */ - MD5_GG ( a, b, c, d, in[ 9], MD5_S21, (UINT4) 568446438u); /* 25 */ - MD5_GG ( d, a, b, c, in[14], MD5_S22, (UINT4) 3275163606u); /* 26 */ - MD5_GG ( c, d, a, b, in[ 3], MD5_S23, (UINT4) 4107603335u); /* 27 */ - MD5_GG ( b, c, d, a, in[ 8], MD5_S24, (UINT4) 1163531501u); /* 28 */ - MD5_GG ( a, b, c, d, in[13], MD5_S21, (UINT4) 2850285829u); /* 29 */ - MD5_GG ( d, a, b, c, in[ 2], MD5_S22, (UINT4) 4243563512u); /* 30 */ - MD5_GG ( c, d, a, b, in[ 7], MD5_S23, (UINT4) 1735328473u); /* 31 */ - MD5_GG ( b, c, d, a, in[12], MD5_S24, (UINT4) 2368359562u); /* 32 */ - - /* Round 3 */ - MD5_HH ( a, b, c, d, in[ 5], MD5_S31, (UINT4) 4294588738u); /* 33 */ - MD5_HH ( d, a, b, c, in[ 8], MD5_S32, (UINT4) 2272392833u); /* 34 */ - MD5_HH ( c, d, a, b, in[11], MD5_S33, (UINT4) 1839030562u); /* 35 */ - MD5_HH ( b, c, d, a, in[14], MD5_S34, (UINT4) 4259657740u); /* 36 */ - MD5_HH ( a, b, c, d, in[ 1], MD5_S31, (UINT4) 2763975236u); /* 37 */ - MD5_HH ( d, a, b, c, in[ 4], MD5_S32, (UINT4) 1272893353u); /* 38 */ - MD5_HH ( c, d, a, b, in[ 7], MD5_S33, (UINT4) 4139469664u); /* 39 */ - MD5_HH ( b, c, d, a, in[10], MD5_S34, (UINT4) 3200236656u); /* 40 */ - MD5_HH ( a, b, c, d, in[13], MD5_S31, (UINT4) 681279174u); /* 41 */ - MD5_HH ( d, a, b, c, in[ 0], MD5_S32, (UINT4) 3936430074u); /* 42 */ - MD5_HH ( c, d, a, b, in[ 3], MD5_S33, (UINT4) 3572445317u); /* 43 */ - MD5_HH ( b, c, d, a, in[ 6], MD5_S34, (UINT4) 76029189u); /* 44 */ - MD5_HH ( a, b, c, d, in[ 9], MD5_S31, (UINT4) 3654602809u); /* 45 */ - MD5_HH ( d, a, b, c, in[12], MD5_S32, (UINT4) 3873151461u); /* 46 */ - MD5_HH ( c, d, a, b, in[15], MD5_S33, (UINT4) 530742520u); /* 47 */ - MD5_HH ( b, c, d, a, in[ 2], MD5_S34, (UINT4) 3299628645u); /* 48 */ - - /* Round 4 */ - MD5_II ( a, b, c, d, in[ 0], MD5_S41, (UINT4) 4096336452u); /* 49 */ - MD5_II ( d, a, b, c, in[ 7], MD5_S42, (UINT4) 1126891415u); /* 50 */ - MD5_II ( c, d, a, b, in[14], MD5_S43, (UINT4) 2878612391u); /* 51 */ - MD5_II ( b, c, d, a, in[ 5], MD5_S44, (UINT4) 4237533241u); /* 52 */ - MD5_II ( a, b, c, d, in[12], MD5_S41, (UINT4) 1700485571u); /* 53 */ - MD5_II ( d, a, b, c, in[ 3], MD5_S42, (UINT4) 2399980690u); /* 54 */ - MD5_II ( c, d, a, b, in[10], MD5_S43, (UINT4) 4293915773u); /* 55 */ - MD5_II ( b, c, d, a, in[ 1], MD5_S44, (UINT4) 2240044497u); /* 56 */ - MD5_II ( a, b, c, d, in[ 8], MD5_S41, (UINT4) 1873313359u); /* 57 */ - MD5_II ( d, a, b, c, in[15], MD5_S42, (UINT4) 4264355552u); /* 58 */ - MD5_II ( c, d, a, b, in[ 6], MD5_S43, (UINT4) 2734768916u); /* 59 */ - MD5_II ( b, c, d, a, in[13], MD5_S44, (UINT4) 1309151649u); /* 60 */ - MD5_II ( a, b, c, d, in[ 4], MD5_S41, (UINT4) 4149444226u); /* 61 */ - MD5_II ( d, a, b, c, in[11], MD5_S42, (UINT4) 3174756917u); /* 62 */ - MD5_II ( c, d, a, b, in[ 2], MD5_S43, (UINT4) 718787259u); /* 63 */ - MD5_II ( b, c, d, a, in[ 9], MD5_S44, (UINT4) 3951481745u); /* 64 */ - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -// Set pseudoRandomNumber to zero for RFC MD5 implementation -void MD5Init (MD5_CTX *mdContext, unsigned long pseudoRandomNumber) -{ - mdContext->i[0] = mdContext->i[1] = (UINT4)0; - - /* Load magic initialization constants */ - mdContext->buf[0] = (UINT4)0x67452301 + (pseudoRandomNumber * 11); - mdContext->buf[1] = (UINT4)0xefcdab89 + (pseudoRandomNumber * 71); - mdContext->buf[2] = (UINT4)0x98badcfe + (pseudoRandomNumber * 37); - mdContext->buf[3] = (UINT4)0x10325476 + (pseudoRandomNumber * 97); - - //CAL! Added - mdContext->digest32[0] = 0; - mdContext->digest32[1] = 0; - mdContext->digest32[2] = 0; - mdContext->digest32[3] = 0; -} - -void MD5Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) -{ - UINT4 in[16]; - int mdi = 0; - unsigned int i = 0, ii = 0; - - /* Compute number of bytes mod 64 */ - mdi = (int)((mdContext->i[0] >> 3) & 0x3F); - - /* Update number of bits */ - if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) - mdContext->i[1]++; - mdContext->i[0] += ((UINT4)inLen << 3); - mdContext->i[1] += ((UINT4)inLen >> 29); - - while (inLen--) - { - /* Add new character to buffer, increment mdi */ - mdContext->in[mdi++] = *inBuf++; - - /* Transform if necessary */ - if (mdi == 0x40) - { - for (i = 0, ii = 0; i < 16; i++, ii += 4) - in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | - (((UINT4)mdContext->in[ii+2]) << 16) | - (((UINT4)mdContext->in[ii+1]) << 8) | - ((UINT4)mdContext->in[ii]); - - MD5_Transform (mdContext->buf, in); - mdi = 0; - } - } -} - -void MD5Final (MD5_CTX *mdContext) -{ - UINT4 in[16]; - int mdi = 0; - unsigned int i = 0, ii = 0, padLen = 0; - - /* Save number of bits */ - in[14] = mdContext->i[0]; - in[15] = mdContext->i[1]; - - /* Compute number of bytes mod 64 */ - mdi = (int)((mdContext->i[0] >> 3) & 0x3F); - - /* Pad out to 56 mod 64 */ - padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); - MD5Update (mdContext, MD5_PADDING, padLen); - - /* Append length in bits and transform */ - for (i = 0, ii = 0; i < 14; i++, ii += 4) - in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | - (((UINT4)mdContext->in[ii+2]) << 16) | - (((UINT4)mdContext->in[ii+1]) << 8) | - ((UINT4)mdContext->in[ii]); - MD5_Transform (mdContext->buf, in); - - /* Store buffer in digest */ - for (i = 0, ii = 0; i < 4; i++, ii += 4) - { - mdContext->digest[ii] = (unsigned char)( mdContext->buf[i] & 0xFF); - mdContext->digest[ii+1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); - mdContext->digest[ii+2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); - mdContext->digest[ii+3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); - - //CAL! Added - // Make my own 32-bit digest, but use big endian. - mdContext->digest32[i] = (((mdContext->buf[i] ) & 0xFF) << 24) + - (((mdContext->buf[i] >> 8) & 0xFF) << 16) + - (((mdContext->buf[i] >> 16) & 0xFF) << 8) + - ((mdContext->buf[i] >> 24) & 0xFF); - } - - -} +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ==================================================================================================== +// SOURCE CODE ACKNOWLEDGEMENT +// ==================================================================================================== +// The following code is derived from the following project on CodeProject: +// +// Title: ReHash - A console-based hash calculator +// Author: Dominik Reichl +// URL: http://www.codeproject.com/Articles/3945/ReHash-A-console-based-hash-calculator +// Date: Apr 11, 2003 +// +// ==================================================================================================== + + +// Free for all implementation of the MD5 hash algorithm + +/* + ********************************************************************** + ** MD5.cpp ** + ** ** + ** - Style modified by Tony Ray, January 2001 ** + ** Added support for randomizing initialization constants ** + ** - Style modified by Dominik Reichl, April 2003 ** + ** Optimized code ** + ** ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** MD5.c ** + ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** + */ + +#include +#include + +//#include "stdafx.h" //CAL! Added to avoid compile error C1010 + +#include "Md5.h" + +/* Padding */ +static unsigned char MD5_PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* MD5_F, MD5_G and MD5_H are basic MD5 functions: selection, majority, parity */ +#define MD5_F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define MD5_H(x, y, z) ((x) ^ (y) ^ (z)) +#define MD5_I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#ifndef ROTATE_LEFT +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +#endif + +/* MD5_FF, MD5_GG, MD5_HH, and MD5_II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define MD5_FF(a, b, c, d, x, s, ac) {(a) += MD5_F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define MD5_GG(a, b, c, d, x, s, ac) {(a) += MD5_G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define MD5_HH(a, b, c, d, x, s, ac) {(a) += MD5_H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define MD5_II(a, b, c, d, x, s, ac) {(a) += MD5_I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } + +/* Constants for transformation */ +#define MD5_S11 7 /* Round 1 */ +#define MD5_S12 12 +#define MD5_S13 17 +#define MD5_S14 22 +#define MD5_S21 5 /* Round 2 */ +#define MD5_S22 9 +#define MD5_S23 14 +#define MD5_S24 20 +#define MD5_S31 4 /* Round 3 */ +#define MD5_S32 11 +#define MD5_S33 16 +#define MD5_S34 23 +#define MD5_S41 6 /* Round 4 */ +#define MD5_S42 10 +#define MD5_S43 15 +#define MD5_S44 21 + +/* Basic MD5 step. MD5_Transform buf based on in */ +static void MD5_Transform (UINT4 *buf, UINT4 *in) +{ + UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + /* Round 1 */ + MD5_FF ( a, b, c, d, in[ 0], MD5_S11, (UINT4) 3614090360u); /* 1 */ + MD5_FF ( d, a, b, c, in[ 1], MD5_S12, (UINT4) 3905402710u); /* 2 */ + MD5_FF ( c, d, a, b, in[ 2], MD5_S13, (UINT4) 606105819u); /* 3 */ + MD5_FF ( b, c, d, a, in[ 3], MD5_S14, (UINT4) 3250441966u); /* 4 */ + MD5_FF ( a, b, c, d, in[ 4], MD5_S11, (UINT4) 4118548399u); /* 5 */ + MD5_FF ( d, a, b, c, in[ 5], MD5_S12, (UINT4) 1200080426u); /* 6 */ + MD5_FF ( c, d, a, b, in[ 6], MD5_S13, (UINT4) 2821735955u); /* 7 */ + MD5_FF ( b, c, d, a, in[ 7], MD5_S14, (UINT4) 4249261313u); /* 8 */ + MD5_FF ( a, b, c, d, in[ 8], MD5_S11, (UINT4) 1770035416u); /* 9 */ + MD5_FF ( d, a, b, c, in[ 9], MD5_S12, (UINT4) 2336552879u); /* 10 */ + MD5_FF ( c, d, a, b, in[10], MD5_S13, (UINT4) 4294925233u); /* 11 */ + MD5_FF ( b, c, d, a, in[11], MD5_S14, (UINT4) 2304563134u); /* 12 */ + MD5_FF ( a, b, c, d, in[12], MD5_S11, (UINT4) 1804603682u); /* 13 */ + MD5_FF ( d, a, b, c, in[13], MD5_S12, (UINT4) 4254626195u); /* 14 */ + MD5_FF ( c, d, a, b, in[14], MD5_S13, (UINT4) 2792965006u); /* 15 */ + MD5_FF ( b, c, d, a, in[15], MD5_S14, (UINT4) 1236535329u); /* 16 */ + + /* Round 2 */ + MD5_GG ( a, b, c, d, in[ 1], MD5_S21, (UINT4) 4129170786u); /* 17 */ + MD5_GG ( d, a, b, c, in[ 6], MD5_S22, (UINT4) 3225465664u); /* 18 */ + MD5_GG ( c, d, a, b, in[11], MD5_S23, (UINT4) 643717713u); /* 19 */ + MD5_GG ( b, c, d, a, in[ 0], MD5_S24, (UINT4) 3921069994u); /* 20 */ + MD5_GG ( a, b, c, d, in[ 5], MD5_S21, (UINT4) 3593408605u); /* 21 */ + MD5_GG ( d, a, b, c, in[10], MD5_S22, (UINT4) 38016083u); /* 22 */ + MD5_GG ( c, d, a, b, in[15], MD5_S23, (UINT4) 3634488961u); /* 23 */ + MD5_GG ( b, c, d, a, in[ 4], MD5_S24, (UINT4) 3889429448u); /* 24 */ + MD5_GG ( a, b, c, d, in[ 9], MD5_S21, (UINT4) 568446438u); /* 25 */ + MD5_GG ( d, a, b, c, in[14], MD5_S22, (UINT4) 3275163606u); /* 26 */ + MD5_GG ( c, d, a, b, in[ 3], MD5_S23, (UINT4) 4107603335u); /* 27 */ + MD5_GG ( b, c, d, a, in[ 8], MD5_S24, (UINT4) 1163531501u); /* 28 */ + MD5_GG ( a, b, c, d, in[13], MD5_S21, (UINT4) 2850285829u); /* 29 */ + MD5_GG ( d, a, b, c, in[ 2], MD5_S22, (UINT4) 4243563512u); /* 30 */ + MD5_GG ( c, d, a, b, in[ 7], MD5_S23, (UINT4) 1735328473u); /* 31 */ + MD5_GG ( b, c, d, a, in[12], MD5_S24, (UINT4) 2368359562u); /* 32 */ + + /* Round 3 */ + MD5_HH ( a, b, c, d, in[ 5], MD5_S31, (UINT4) 4294588738u); /* 33 */ + MD5_HH ( d, a, b, c, in[ 8], MD5_S32, (UINT4) 2272392833u); /* 34 */ + MD5_HH ( c, d, a, b, in[11], MD5_S33, (UINT4) 1839030562u); /* 35 */ + MD5_HH ( b, c, d, a, in[14], MD5_S34, (UINT4) 4259657740u); /* 36 */ + MD5_HH ( a, b, c, d, in[ 1], MD5_S31, (UINT4) 2763975236u); /* 37 */ + MD5_HH ( d, a, b, c, in[ 4], MD5_S32, (UINT4) 1272893353u); /* 38 */ + MD5_HH ( c, d, a, b, in[ 7], MD5_S33, (UINT4) 4139469664u); /* 39 */ + MD5_HH ( b, c, d, a, in[10], MD5_S34, (UINT4) 3200236656u); /* 40 */ + MD5_HH ( a, b, c, d, in[13], MD5_S31, (UINT4) 681279174u); /* 41 */ + MD5_HH ( d, a, b, c, in[ 0], MD5_S32, (UINT4) 3936430074u); /* 42 */ + MD5_HH ( c, d, a, b, in[ 3], MD5_S33, (UINT4) 3572445317u); /* 43 */ + MD5_HH ( b, c, d, a, in[ 6], MD5_S34, (UINT4) 76029189u); /* 44 */ + MD5_HH ( a, b, c, d, in[ 9], MD5_S31, (UINT4) 3654602809u); /* 45 */ + MD5_HH ( d, a, b, c, in[12], MD5_S32, (UINT4) 3873151461u); /* 46 */ + MD5_HH ( c, d, a, b, in[15], MD5_S33, (UINT4) 530742520u); /* 47 */ + MD5_HH ( b, c, d, a, in[ 2], MD5_S34, (UINT4) 3299628645u); /* 48 */ + + /* Round 4 */ + MD5_II ( a, b, c, d, in[ 0], MD5_S41, (UINT4) 4096336452u); /* 49 */ + MD5_II ( d, a, b, c, in[ 7], MD5_S42, (UINT4) 1126891415u); /* 50 */ + MD5_II ( c, d, a, b, in[14], MD5_S43, (UINT4) 2878612391u); /* 51 */ + MD5_II ( b, c, d, a, in[ 5], MD5_S44, (UINT4) 4237533241u); /* 52 */ + MD5_II ( a, b, c, d, in[12], MD5_S41, (UINT4) 1700485571u); /* 53 */ + MD5_II ( d, a, b, c, in[ 3], MD5_S42, (UINT4) 2399980690u); /* 54 */ + MD5_II ( c, d, a, b, in[10], MD5_S43, (UINT4) 4293915773u); /* 55 */ + MD5_II ( b, c, d, a, in[ 1], MD5_S44, (UINT4) 2240044497u); /* 56 */ + MD5_II ( a, b, c, d, in[ 8], MD5_S41, (UINT4) 1873313359u); /* 57 */ + MD5_II ( d, a, b, c, in[15], MD5_S42, (UINT4) 4264355552u); /* 58 */ + MD5_II ( c, d, a, b, in[ 6], MD5_S43, (UINT4) 2734768916u); /* 59 */ + MD5_II ( b, c, d, a, in[13], MD5_S44, (UINT4) 1309151649u); /* 60 */ + MD5_II ( a, b, c, d, in[ 4], MD5_S41, (UINT4) 4149444226u); /* 61 */ + MD5_II ( d, a, b, c, in[11], MD5_S42, (UINT4) 3174756917u); /* 62 */ + MD5_II ( c, d, a, b, in[ 2], MD5_S43, (UINT4) 718787259u); /* 63 */ + MD5_II ( b, c, d, a, in[ 9], MD5_S44, (UINT4) 3951481745u); /* 64 */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +// Set pseudoRandomNumber to zero for RFC MD5 implementation +void MD5Init (MD5_CTX *mdContext, unsigned long pseudoRandomNumber) +{ + mdContext->i[0] = mdContext->i[1] = (UINT4)0; + + /* Load magic initialization constants */ + mdContext->buf[0] = (UINT4)0x67452301 + (pseudoRandomNumber * 11); + mdContext->buf[1] = (UINT4)0xefcdab89 + (pseudoRandomNumber * 71); + mdContext->buf[2] = (UINT4)0x98badcfe + (pseudoRandomNumber * 37); + mdContext->buf[3] = (UINT4)0x10325476 + (pseudoRandomNumber * 97); + + //CAL! Added + mdContext->digest32[0] = 0; + mdContext->digest32[1] = 0; + mdContext->digest32[2] = 0; + mdContext->digest32[3] = 0; +} + +void MD5Update (MD5_CTX *mdContext, unsigned char *inBuf, int32_t inLen) +{ + UINT4 in[16]; + int32_t mdi = 0; + uint32_t i = 0, ii = 0; + + /* Compute number of bytes mod 64 */ + mdi = static_cast((mdContext->i[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + + mdContext->i[0] += ((UINT4)inLen << 3); + mdContext->i[1] += ((UINT4)inLen >> 29); + + while (inLen--) + { + /* Add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* Transform if necessary */ + if (mdi == 0x40) + { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + + MD5_Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +void MD5Final (MD5_CTX *mdContext) +{ + UINT4 in[16]; + int32_t mdi = 0; + uint32_t i = 0, ii = 0, padLen = 0; + + /* Save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* Compute number of bytes mod 64 */ + mdi = static_cast((mdContext->i[0] >> 3) & 0x3F); + + /* Pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + MD5Update (mdContext, MD5_PADDING, padLen); + + /* Append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | + (((UINT4)mdContext->in[ii+2]) << 16) | + (((UINT4)mdContext->in[ii+1]) << 8) | + ((UINT4)mdContext->in[ii]); + MD5_Transform (mdContext->buf, in); + + /* Store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) + { + mdContext->digest[ii] = (unsigned char)( mdContext->buf[i] & 0xFF); + mdContext->digest[ii+1] = (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); + mdContext->digest[ii+2] = (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); + mdContext->digest[ii+3] = (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); + + //CAL! Added + // Make my own 32-bit digest, but use big endian. + mdContext->digest32[i] = (((mdContext->buf[i] ) & 0xFF) << 24) + + (((mdContext->buf[i] >> 8) & 0xFF) << 16) + + (((mdContext->buf[i] >> 16) & 0xFF) << 8) + + ((mdContext->buf[i] >> 24) & 0xFF); + } +} diff --git a/source/Md5.h b/source/Md5.h index ab090f6..c92abfa 100644 --- a/source/Md5.h +++ b/source/Md5.h @@ -1,106 +1,108 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code is derived from the following project on CodeProject: -// -// Title: ReHash - A console-based hash calculator -// Author: Dominik Reichl -// URL: http://www.codeproject.com/Articles/3945/ReHash-A-console-based-hash-calculator -// Date: Apr 11, 2003 -// -// ==================================================================================================== - -/* - ********************************************************************** - ** MD5.h ** - ** ** - ** - Style modified by Tony Ray, January 2001 ** - ** Added support for randomizing initialization constants ** - ** - Style modified by Dominik Reichl, September 2002 ** - ** Optimized code ** - ** ** - ********************************************************************** - */ - -/* - ********************************************************************** - ** MD5.h -- Header file for implementation of MD5 ** - ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** - ** Created: 2/17/90 RLR ** - ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** - ** Revised (for MD5): RLR 4/27/91 ** - ** -- G modified to have y&~z instead of y&z ** - ** -- FF, GG, HH modified to add in last register done ** - ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** - ** -- distinct additive constant for each step ** - ** -- round 4 added, working mod 7 ** - ********************************************************************** - */ - -/* - ********************************************************************** - ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** - ** ** - ** License to copy and use this software is granted provided that ** - ** it is identified as the "RSA Data Security, Inc. MD5 Message ** - ** Digest Algorithm" in all material mentioning or referencing this ** - ** software or this function. ** - ** ** - ** License is also granted to make and use derivative works ** - ** provided that such works are identified as "derived from the RSA ** - ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** - ** material mentioning or referencing the derived work. ** - ** ** - ** RSA Data Security, Inc. makes no representations concerning ** - ** either the merchantability of this software or the suitability ** - ** of this software for any particular purpose. It is provided "as ** - ** is" without express or implied warranty of any kind. ** - ** ** - ** These notices must be retained in any copies of any part of this ** - ** documentation and/or software. ** - ********************************************************************** - */ - -#ifndef ___MD5_H___ -#define ___MD5_H___ - -/* Typedef a 32 bit type */ -#ifndef UINT4 -typedef unsigned long int UINT4; -#endif - -/* Data structure for MD5 (Message Digest) computation */ -typedef struct { - UINT4 i[2]; /* Number of _bits_ handled mod 2^64 */ - UINT4 buf[4]; /* Scratch buffer */ - unsigned char in[64]; /* Input buffer */ - unsigned char digest[16]; /* Actual digest after MD5Final call */ - - unsigned int digest32[4]; //CAL! Added -} MD5_CTX; - -static void MD5_Transform (UINT4 *buf, UINT4 *in); - -void MD5Init(MD5_CTX *mdContext, unsigned long pseudoRandomNumber = 0); -void MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen); -void MD5Final(MD5_CTX *mdContext); - -#endif /* ___MD5_H___ included */ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ==================================================================================================== +// SOURCE CODE ACKNOWLEDGEMENT +// ==================================================================================================== +// The following code is derived from the following project on CodeProject: +// +// Title: ReHash - A console-based hash calculator +// Author: Dominik Reichl +// URL: http://www.codeproject.com/Articles/3945/ReHash-A-console-based-hash-calculator +// Date: Apr 11, 2003 +// +// ==================================================================================================== + +/* + ********************************************************************** + ** MD5.h ** + ** ** + ** - Style modified by Tony Ray, January 2001 ** + ** Added support for randomizing initialization constants ** + ** - Style modified by Dominik Reichl, September 2002 ** + ** Optimized code ** + ** ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** MD5.h -- Header file for implementation of MD5 ** + ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** + ** Created: 2/17/90 RLR ** + ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** + ** Revised (for MD5): RLR 4/27/91 ** + ** -- G modified to have y&~z instead of y&z ** + ** -- FF, GG, HH modified to add in last register done ** + ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** + ** -- distinct additive constant for each step ** + ** -- round 4 added, working mod 7 ** + ********************************************************************** + */ + +/* + ********************************************************************** + ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** + ** ** + ** License to copy and use this software is granted provided that ** + ** it is identified as the "RSA Data Security, Inc. MD5 Message ** + ** Digest Algorithm" in all material mentioning or referencing this ** + ** software or this function. ** + ** ** + ** License is also granted to make and use derivative works ** + ** provided that such works are identified as "derived from the RSA ** + ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** + ** material mentioning or referencing the derived work. ** + ** ** + ** RSA Data Security, Inc. makes no representations concerning ** + ** either the merchantability of this software or the suitability ** + ** of this software for any particular purpose. It is provided "as ** + ** is" without express or implied warranty of any kind. ** + ** ** + ** These notices must be retained in any copies of any part of this ** + ** documentation and/or software. ** + ********************************************************************** + */ + +#ifndef ___MD5_H___ +#define ___MD5_H___ + +#include + +/* Typedef a 32 bit type */ +#ifndef UINT4 +typedef uint32_t UINT4; +#endif + +/* Data structure for MD5 (Message Digest) computation */ +typedef struct { + UINT4 i[2]; /* Number of _bits_ handled mod 2^64 */ + UINT4 buf[4]; /* Scratch buffer */ + unsigned char in[64]; /* Input buffer */ + unsigned char digest[16]; /* Actual digest after MD5Final call */ + + uint32_t digest32[4]; //CAL! Added +} MD5_CTX; + +static void MD5_Transform (UINT4 *buf, UINT4 *in); + +void MD5Init(MD5_CTX *mdContext, unsigned long pseudoRandomNumber = 0); +void MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, int32_t inLen); +void MD5Final(MD5_CTX *mdContext); + +#endif /* ___MD5_H___ included */ diff --git a/source/Signatures.inl b/source/Signatures.inl index 78f04d8..8c902ce 100644 --- a/source/Signatures.inl +++ b/source/Signatures.inl @@ -16,3369 +16,3368 @@ // along with this program. If not, see . // -#include "stdafx.h" #include "DbSigs.h" // Signature List const CompSigConst CDbSigs::m_sSigList[] = { -{ ENUM_EDITOR_CAM,_T("10.0M 3X digital camera"),_T("DigitalCam"),_T(""),_T("01ABDC51F42E1B9894AD6BA6180AEC08"),_T("01D0F3FAE71E7CE4E25ED195F2599491"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("???"),_T("Treo 680"),_T(""),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Apple"),_T("iPhone"),_T(""),_T("01114839EC1207E51E21B08385DF6974"),_T("01234D2E8848CB268F789EBB63EE1B8D"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Asahi Optical Co.,Ltd"),_T("PENTAX Optio 330"),_T(""),_T("0152B022B4F4AC1741AF3BA5F0B4C3C6"),_T("01AF9C2CD0D6D3B4EA273D052679C144"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Asahi Optical Co.,Ltd"),_T("PENTAX Optio 330"),_T(""),_T("01012CAE6B2A83F4ECFDC9516C93825E"),_T("01E53DA9892B36ADAAEAC58897E28B7B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Asahi Optical Co.,Ltd"),_T("PENTAX Optio 330"),_T(""),_T("015CEBBBDF89445196B16C9736466726"),_T("01EC96C762F7941278E3F5584E9B100C"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Asahi Optical Co.,Ltd"),_T("PENTAX Optio 330"),_T(""),_T("013489D0392A3692A8D7389782C0A6EB"),_T("0166B131CC98588533F1D93ACE79AA1A"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Asahi Optical Co.,Ltd"),_T("PENTAX Optio 330"),_T(""),_T("0123D54F3D383A3E64A10DE0D5A97816"),_T("016EE147C94FA14FFEB80BC6FA4614C8"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Asahi Optical Co.,Ltd"),_T("PENTAX Optio 430"),_T(""),_T("0152B022B4F4AC1741AF3BA5F0B4C3C6"),_T("01AF9C2CD0D6D3B4EA273D052679C144"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 300"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 330"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 330"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 40"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 40"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 400"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 400"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 50"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 50"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 55"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 70"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 700"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 700"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 750"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 800 IS"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 850 IS"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 850 IS"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 860 IS"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 900Ti"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS 900Ti"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon DIGITAL IXUS II"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 10D"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 10D"),_T("norm"),_T("017C9D4907C58FFF90C29510E8DD23EB"),_T("01C8A7D568C582C8D42E10882ECA7701"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 20D"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 300D DIGITAL"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 30D"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 350D DIGITAL"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 400D DIGITAL"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 40D"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 40D"),_T("norm"),_T("017C9D4907C58FFF90C29510E8DD23EB"),_T("01C8A7D568C582C8D42E10882ECA7701"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 450D"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 500D"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 500D"),_T("norm"),_T("017C9D4907C58FFF90C29510E8DD23EB"),_T("01C8A7D568C582C8D42E10882ECA7701"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 50D"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 550D"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 5D"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 5D Mark II"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 5D Mark III"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 600D"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 60D"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS 7D"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS D30"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS D60"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS DIGITAL REBEL"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS DIGITAL REBEL XS"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS DIGITAL REBEL XSi"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS DIGITAL REBEL XT"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS DIGITAL REBEL XTi"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS DIGITAL REBEL XTi"),_T("fine"),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS REBEL T1i"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS REBEL T2i"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS REBEL T3i"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS-1D"),_T("fine"),_T("017211BC8C6161BCE36DB4E91A7A575F"),_T("018C775AA14027570ED51F477477AA84"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS-1D Mark II"),_T("fine"),_T("01693B4A9D484C7DF321A6051F241493"),_T("01F308C26BBCCE3A8D1E869927236116"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS-1D Mark II"),_T("fine"),_T("014E3B2CA236245A8E6AC25D4C0547B5"),_T("016FF2A5B4DCC046A3499C4E12912CBE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS-1D Mark III"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS-1DS"),_T("fine"),_T("017211BC8C6161BCE36DB4E91A7A575F"),_T("018C775AA14027570ED51F477477AA84"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS-1Ds Mark II"),_T("fine"),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon EOS-1Ds Mark III"),_T("fine"),_T("018F98F7BF412181D34F86F1A3BCD26F"),_T("01A5A96C366F3E76B00DA5ED55BB3238"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A20"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A20"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A40"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A430"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A460"),_T("superfine"),_T("0197DCCA5A22C4279E039DC052C60443"),_T("01F240E7FA65AB2E40EFA1C2CCEE3726"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A510"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A520"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A520"),_T("norm"),_T("01536581ECEFBFB9C18C278E79905118"),_T("01D91E583DD0037108266E42ED3A262C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A520"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A60"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A620"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A620"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A630"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A640"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A640"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A650 IS"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A70"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A700"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A710 IS"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A710 IS"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A720 IS"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A75"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A95"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot A95"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G1"),_T("fine"),_T("0166C6447A130A0EB12268E3E74C2545"),_T("01FEF02BAC5C13D1C39BCA4E342A8434"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G1"),_T("superfine"),_T("01D98D90B542316CF007C19CB4C99545"),_T("01D98D90B542316CF007C19CB4C99545"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G10"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G11"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G12"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G2"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G2"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G3"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G5"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G6"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G6"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G7"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G7"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G7"),_T("superfine"),_T("0197DCCA5A22C4279E039DC052C60443"),_T("01F240E7FA65AB2E40EFA1C2CCEE3726"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot G9"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot Pro1"),_T("fine"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot Pro1"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S1 IS"),_T("fine"),_T("018567C5DEAAD7EF4120A002519DC287"),_T("01BD35C96FB5A5B7BBD37BEAE0E8938C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S1 IS"),_T("superfine"),_T("012292153D6B64A48C045C10DA4FC0F9"),_T("01C11E397A687C7513E1034BC24F4710"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S2 IS"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S2 IS"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S20"),_T("fine"),_T("0166C6447A130A0EB12268E3E74C2545"),_T("01FEF02BAC5C13D1C39BCA4E342A8434"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S20"),_T("superfine"),_T("01254D92D792D2CB6523C82CF3641DB5"),_T("01AF89B1822B526790CC093D6D374A09"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S200"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S3 IS"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S3 IS"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S30"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S40"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S45"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S45"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S5 IS"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S50"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S60"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S70"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S80"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot S80"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot SD1000"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot SD20"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot SD300"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot SD40"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot SD400"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot SD600"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot SD800 IS"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot SD800 IS"),_T("norm"),_T("01A9490A915CC37ECB6E1256F8E6644B"),_T("01B61A33CB5EFDF80F505C0224D3B563"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot SD800 IS"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot SD950 IS"),_T("fine"),_T("01A84EC0DDFAE937A0336DB825C85028"),_T("01A9B171AA8560DD8EA55A93D29361E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Canon"),_T("Canon PowerShot TX1"),_T("superfine"),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("0114ACEDA8F9481F39E84EFF05320A75"),_T("012FCA6D6632CA1A4A7BDD6231B32535"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("010901E28B712B0A893D88C64200A77C"),_T("01A458CA927F61177265F104EFC3B6DB"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("0154891CBD5437A548A3C052C118AA0B"),_T("01B36319ECD00B49D67C9A766B774E2C"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("0106EE66B9A3CCA78E456DBD4F70C75A"),_T("0109875B03DEB01C981AD4D394F5366C"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("0101D11D279551CC7C4CA86A8F39A41A"),_T("0161415C082A4312146D7F5C39BA5ED1"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("0186E4B502CA67A194BF25F837844D8D"),_T("01A32782FC02530A42591F1F4F464F3F"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("01284370CBB386736D9945F4CC9B67D2"),_T("01CCC7E166F2A263B79D58383140B8A1"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("01072BA17E81B063A400664BBDF89044"),_T("01C4A90CB8D7B176C23A657F10AF4F62"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("01642B5F591CE08B51B5D0D2493A956D"),_T("01A431C10DF789D73EDA19939C228D84"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("01C839B17EE76D0157A2AAE990D683B4"),_T("01FE40687C4282564075351F339BDCAD"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("0186895D7C5F2BBA6028D98DBA7CEA73"),_T("01CD2D081D75FDCD853C8C66B5A9E79B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("01878DA912905F4FB26A085F27638E14"),_T("01B6670DB7E3D9B5378D0B4D54F84632"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("014D370BE2BDBDBCB33569C338FECF5C"),_T("01FEDC6036672378F31AAE0AE2E28E0E"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("016BB57ACC9696E011186EC286CFC185"),_T("01ADDA416DCF3BBC8649DC7495FF09F8"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("0191369E9D5A81193E62D58452CC5DDB"),_T("01AE39A80FB5251F44103926ED2EC3E2"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("01D8752CBB2AE66D6F4CFB775D59A7A5"),_T("01F6B4F4795B85ADB326FD80B4993D68"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("012DE9EF5B39566F08E4864A0E6734F1"),_T("01508825BF8EACB426BE13B9F647B278"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("01646DA44D608C8154DCF8F04E540FC1"),_T("01D5F912A2CAC1141FEDFAD87B2A66D1"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("013C143987565282044C2DAC1A068436"),_T("01879A52F82348EFAC4D95E0C53D88D7"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-3000EX"),_T(""),_T("011A671A74533E934228664BC17AB47F"),_T("01B002679AE502C39E114EF2B5FC0306"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("011B35D8688C01551FDE78BFFB8F1C57"),_T("014E650C236D4FC2D83EF2A6226A8A9B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("01081B465B20737AFAD71D785AC239B0"),_T("016A90369C5FDF1067FE96D982AD2119"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("01BAAEE4D1A66BBB7F4F0E88411017E5"),_T("01CC1C78C52A9250EC2589572EEE1985"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("012C5B50BF9AE8AAB4A56B596E435A92"),_T("017ACD82E5B0B9829E9213B645C356D6"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("01CC03D9AD8BD65C811C26485454F57F"),_T("01CF95ACB5EC9CE5A1DECCE25E5353D8"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("015A33449827A6024F4F2088B40487FF"),_T("01FC69409FCF1FF801C9ECE870FF52F2"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("0104176A29E2524FBA25A9905E4F23B8"),_T("01F2D9EBEA054E050687EF4CD4A3BC43"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("01AD43A6537A8BFA5B99A6DD691C86CA"),_T("01AF1667B04F8576816B0BDCD7C2DE43"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("0158C4F5686476668DB83B0E530AD342"),_T("01F04E7D6E8E71B08B3426073D69212E"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("0188DCDAB979EC7D09A12202F2B774AF"),_T("01CC33C98E3EA1AF8D6BA30C49E3F2DD"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO"),_T("QV-4000"),_T(""),_T("011AE1522C59D1CDBABB1F8AE9C18859"),_T("0129A2541B4DC116666C667A9E7798C3"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-P700"),_T(""),_T("01158B0D515E752B1B0716889F2B3371"),_T("017BBA44ECD57A9B2E59D0D6967F1623"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-P700"),_T(""),_T("018A97EF0C8856D9155F90A770C73067"),_T("01F68622EE6EF782C32ACC2CCF6A9907"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-P700"),_T(""),_T("0102294DDB25E3C1C60F5C5DC104F7B5"),_T("016B3CB8CC79372F62EC1BF4D84C018E"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("01307DB502FD0796E12F5BBEB51B4AB2"),_T("01663330C80C57C3B23D93665BCA78AD"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("013E4F4032D7BBB022EA8A4DD2A79AA1"),_T("015DD46C027E5E984C8305753B29931D"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("01D0473D74948D7D40D56AE4618F18FA"),_T("01E2C847E07C54190944A74B136E452B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("016457926DC23B96DCB1158EC97FA41F"),_T("01CF9466A7F18116407263F3C571385B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("013EB813C8BBDFFF0B4E8A901F467A53"),_T("016E3BEA7C7F7A2699A831BD7D810755"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("01541589583CE2044639D04AFA5D92EC"),_T("01C87F3D55EDD94FF768CD3D6C4C5EB9"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("01538B160141A7D4D5EC996041B13927"),_T("01CD00B4F906A2D48B87B432BD90C47F"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("01E4024724CFD9D59967431BE3D4B5F7"),_T("01FC172DB6898BD03C724F65B292E2DB"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("0189899374B6A91C23CE16E82E10860A"),_T("01A03ED33AF152520F69668A6384F1CD"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("01762465923F7F2BDED202DCC9EC1C61"),_T("019BA0F4F58AB3E2D5503B48FBE64BCD"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("0125B10AC281E131BEEF59122D2A50D9"),_T("018613B9EDD3B80CD5532CEDB56E179A"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("012004B942B765F1D36C13D9037D6FBC"),_T("01DB30EDD5E692FCF2A005916617DEAD"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("0105A3A5351DF1752ED496F68DAA2FBB"),_T("01732657CD1F44D5B7321E556A8612DA"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("012345305944D817D0C161C7B54BAF5C"),_T("017DDCB884AFEF1F6DD72AEA5D125933"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z3"),_T(""),_T("012EE70617EAFF0FC7A699EDF281D96C"),_T("0140748F1853345BF32A08347F94C9A4"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("0114F4E9F4E455967FE80C4ED10EBDAD"),_T("01680D1FE97C0D264CA8043A194C8133"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("01158B0D515E752B1B0716889F2B3371"),_T("017BBA44ECD57A9B2E59D0D6967F1623"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("0151361D87566A29C7953F5D17496970"),_T("01C9FD0688443EC6A4EA219C6875EF80"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("013B1FC692BCCE8DBBAEA5BD4DC13F87"),_T("01DB220936AEBE1D36FDF3382FD48D2E"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("018A97EF0C8856D9155F90A770C73067"),_T("01F68622EE6EF782C32ACC2CCF6A9907"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("0102E487A27A09D7582FA1E0001EDDA8"),_T("011B1F3139A11C00C8AF37C1E3BC177F"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("01282B7C952CA521A46610097AF44D85"),_T("01D66E67E2B232758F87834EF50590B5"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("01133005CDA1908ED26E50DDB781DF3D"),_T("0160796D6F8855EA95ECF106A9654836"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("01898FC95FA9A32B051449450C4D2A12"),_T("01C2E8DD6BF896D8E02C99FF30979C44"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("0153055EA4D756EC9F6475B3C09E7C01"),_T("01FD90D92E90DBA384669EADB3F577C6"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("01353F8208A74D70DE394C36EF9E1930"),_T("0187F5E28A0687D5CCFCFC88CAE032D6"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("01E58965F8067668C66AFED5D75C697A"),_T("01E9F3EA3C7492A27953F6010EEC4018"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("012EB4552CC504B451C1DB9919AF87B4"),_T("01E45CAEA1F7F87027D080E583B4E4B2"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("0181E59CD24EF8789C041D42B8AD1D5A"),_T("01E463C57C904FE7ACC294AD6019A96D"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("0141C8BCEE79DCFDA074E3C07736416A"),_T("01DE5CEEED245872C6FCA585F661116B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("01140A9EB6A29B75A94DAA83062EDF86"),_T("015EF8EB6F5D14FB23AB7ABDC958138A"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("01573FFE0766609566191C1833D6F679"),_T("0183874EA1080211719853DD0F1BCF07"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD"),_T("EX-Z750"),_T(""),_T("01A06F04F4B4D355BA155DEF93666C41"),_T("01B46D5D99ED73CD4F3240EC47C43EFA"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-S1"),_T(""),_T("0101A7F739C69F00359D8B85CC34F0FB"),_T("01367C97B8AC950F6F131433253F02B6"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-V7"),_T(""),_T("010A617846E6CF420B022872292301CF"),_T("01DB0DF2EAE120F08CE3C4D7878A4E22"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("0114F4E9F4E455967FE80C4ED10EBDAD"),_T("01680D1FE97C0D264CA8043A194C8133"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("015810C34129CDE961B762FC29DAD759"),_T("01A966EEF909399816B26D62AA2361A1"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("01158B0D515E752B1B0716889F2B3371"),_T("017BBA44ECD57A9B2E59D0D6967F1623"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("0151361D87566A29C7953F5D17496970"),_T("01C9FD0688443EC6A4EA219C6875EF80"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("0174AE9734728759DD35CDC2E31AA7A1"),_T("018F56C5185CA8141F9A004ABF9D73D8"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("012FF3521C45C6DAEEA460C7BDD6DCCC"),_T("0187425514C2B6F84D4F22EF7A9D9C40"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("0142650EF71E4211C4C81828541A77F8"),_T("0194F0978127E72F4314C73250B9E6B4"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("017968F1F9AEE81D13441ECE60DA6BEA"),_T("01A370D713D9ABF8C828A06FCBB25860"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("011BFA3463AE7DAC4A6D3902FB1C0108"),_T("01739F243032DF6F0262F85D7A36CFE5"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("011A3E23EC6F242909B20639EB7205D8"),_T("01823F6AF5D968093CE92BB16C4A4988"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("0129FE5A01A618B61ABCC5F50F960D20"),_T("01F091FFC7E5B8779C78222894121BDF"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("01898FC95FA9A32B051449450C4D2A12"),_T("01C2E8DD6BF896D8E02C99FF30979C44"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("011D3D09F48DCC50F94890D1C9A69C5B"),_T("01E26E34B5F5E005BA9F75037796E619"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("0133226BF13534FDE68EFC2D88AE82CE"),_T("01B9E5BE874A359DE08D0316A0177506"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("014AAC72448AB92C4302572620B7F4AC"),_T("014DCA2B0866A92BD9B6839AFC50A1D6"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("0185FECE30CB0A7EB5E37B6A11BD6836"),_T("01B3720783EA3E69C14BBFBF06757E64"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("0142BB80C46874F3726D3A8EEED24A3F"),_T("014789A946A1654649745D9ABDEAAE79"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("013041C49E6936277A0AB6A1E36A2E56"),_T("01C7A2FB7E82A978A31032E710B85EEE"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("015A69E9850D5D1EEAC2BA4108D0314C"),_T("01FAA2C9873B4E3B098860660F4C910D"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z1000"),_T(""),_T("01AE4DFAA5863EF3F54DA3BB2BF35E66"),_T("01B67A85A646A481EF7378F757E236D1"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("EX-Z60"),_T(""),_T("0149FA5635438A0954FA8059E2793FB3"),_T("01F127B5443FBD96B3025F295D69BE9F"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("CASIO COMPUTER CO.,LTD."),_T("QV-R3"),_T(""),_T("0123352933C37236F67F03EB6B0E3A91"),_T("0153CE6A2850A881FA5219B4669EE67C"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK C875 ZOOM DIGITAL CAMERA"),_T(""),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Eastman Kodak Company"),_T("KODAK DC265 ZOOM DIGITAL CAMERA (V01.00)"),_T(""),_T("0108DD2F610E7A2995F0205A2B110768"),_T("0108DD2F610E7A2995F0205A2B110768"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Eastman Kodak Company"),_T("KODAK DC265 ZOOM DIGITAL CAMERA (V01.00)"),_T(""),_T("01641718AE2C9861D8B6FA297AFF7345"),_T("01641718AE2C9861D8B6FA297AFF7345"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK DC280 ZOOM DIGITAL CAMERA"),_T(""),_T("0108DD2F610E7A2995F0205A2B110768"),_T("0108DD2F610E7A2995F0205A2B110768"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK DC280 ZOOM DIGITAL CAMERA"),_T(""),_T("01641718AE2C9861D8B6FA297AFF7345"),_T("01641718AE2C9861D8B6FA297AFF7345"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Eastman Kodak Company"),_T("KODAK DC290 Zoom Digital Camera (V01.00)"),_T(""),_T("0108DD2F610E7A2995F0205A2B110768"),_T("0108DD2F610E7A2995F0205A2B110768"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK DC4800 ZOOM DIGITAL CAMERA"),_T(""),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK DX4900 ZOOM DIGITAL CAMERA"),_T(""),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK DX7590 ZOOM DIGITAL CAMERA"),_T(""),_T("01761CEA379B4F7A4F77D06279E8050F"),_T("01761CEA379B4F7A4F77D06279E8050F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK DX7590 ZOOM DIGITAL CAMERA"),_T(""),_T("01761CEA379B4F7A4F77D06279E8050F"),_T("01761CEA379B4F7A4F77D06279E8050F"),_T("1x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK LS753 ZOOM DIGITAL CAMERA"),_T("Best"),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P712 ZOOM DIGITAL CAMERA"),_T("Basic"),_T("01625155BE84D00125E6E169DF4A2F65"),_T("01C54F8112BAF719522090C85C5E23F1"),_T("1x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P712 ZOOM DIGITAL CAMERA"),_T("Fine"),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("1x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P712 ZOOM DIGITAL CAMERA"),_T("Standard"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("1x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P850 ZOOM DIGITAL CAMERA"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P850 ZOOM DIGITAL CAMERA"),_T(""),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P850 ZOOM DIGITAL CAMERA"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P850 ZOOM DIGITAL CAMERA"),_T(""),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P850 ZOOM DIGITAL CAMERA"),_T(""),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P850 ZOOM DIGITAL CAMERA"),_T(""),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P850 ZOOM DIGITAL CAMERA"),_T(""),_T("0134F2041810CE97DAAB408D5E71163C"),_T("01D831EF97768EF36E607FD5D85426FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P850 ZOOM DIGITAL CAMERA"),_T(""),_T("01BD24596581D7A1535AFC805B0D60A2"),_T("01D47AD28A985151B705F90864369E2C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P850 ZOOM DIGITAL CAMERA"),_T(""),_T("0184C9EBAD799D9C4AFE7B97932F42C5"),_T("01F0A787A4F48EE0145B0243DD91F234"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("0124AC8790656DF23F8070E2A880B501"),_T("016CC716D191DBD0BB21F1090184405D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("1x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("1x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("1x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("1x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("0134F2041810CE97DAAB408D5E71163C"),_T("01D831EF97768EF36E607FD5D85426FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK P880 ZOOM DIGITAL CAMERA"),_T(""),_T("0178BAF59FA3A93E45912D1A3AB3DFA4"),_T("0183C6D8ADA5B5856CB6C4CEAFA87628"),_T("1x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK V610 DUAL LENS DIGITAL CAMERA"),_T(""),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK V705 DUAL LENS DIGITAL CAMERA"),_T(""),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK Z612 ZOOM DIGITAL CAMERA"),_T(""),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK Z650 ZOOM DIGITAL CAMERA"),_T(""),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("EASTMAN KODAK COMPANY"),_T("KODAK Z740 ZOOM DIGITAL CAMERA"),_T(""),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("01BBFCF1173FB5AFEACBC1D065B6DC5B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix A330"),_T("high"),_T("016177AB8D6680CE1D5BD42F16970EBB"),_T("01CF7260141AA84FBDC5E47A35118EBF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix A700"),_T(""),_T("01144982047160D8F5F6F1353EF1713C"),_T("01EE606D916D8DBD24D301A85169CE58"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0107970B1B893B56DEC2A2B1B0B797B1"),_T("0115AB45CC9CD386DAC1E6E7DAB33CD6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("01DE1EEA3B2C88A57A1D3894C9F4CA25"),_T("01EEFBA4B1584A8B8B670D9EAB8D0C9D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0143A9114D57AEC803D47AB9AA1DAC8E"),_T("01E0F7F87C972B220E1203E00D78FF1E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0136AAFA05459AEFAABBB57620F4604F"),_T("01B995B722D53ADDC6AA4D06115AFE4F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0167ADE27CBB81EED41B08E8DD91919C"),_T("017FA6A0E82890CD1734E1435D5EED33"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("01144982047160D8F5F6F1353EF1713C"),_T("01EE606D916D8DBD24D301A85169CE58"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("016FA4721E4BDCA33AB0243056ED052F"),_T("01B0ACBB0E5167B3D432056CDFF87C98"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0194A30D59C5D4F233C204CCCD9383E0"),_T("01D69C67E78A7244D23671EB2DEDF6C1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("018DDDBEBFE9897574F2601B234742B0"),_T("01EDD07571B6983644D2B38B88D520A6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("010D98BF96F187A0C2C69857A2532D3A"),_T("01A30B61A5E49BF4ED08B00CFE7916BE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("01300CF6E26C44CA6E1F7E002E90E29B"),_T("01C97D0146AF14BC73CBB75FBC2DEA7D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("01209694C019817E5160C77ECB0E6E73"),_T("01A6E0CFCF95398C049C8A6A8CB5662F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("01322A55C3F539232F9F48AC5DCA0072"),_T("01448D46E463836F6191E0916423365A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0145F26B95FF8AF15D1A7DC64355F872"),_T("016D15F943FA53E2F9E93A89A926B850"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("011F72189F16FB63160539354A378C18"),_T("01B57B0DB97AF420331DCB82522A4FC0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0105CCB4C4B348AE594D640D47A029B7"),_T("014CE1370398E06CCA7E7635DA264D67"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0114487FCFC83B9264E0E8E7CEB018C1"),_T("01775E6DC2982017FD3CADA42C020735"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0175096CD9CB339136584317671A190F"),_T("01FFAD541AE2A57B779D1092D1D36CC6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("010B56EF40829B8C4322CA40EC09F38E"),_T("01EDC31567D017E237CD52453C45DD19"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0143F7DAE2EA08DE30DA14FE894C3D07"),_T("017C6D26409ACAF1615DE04A6B9C9C7C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("01A88E1F6EE058E7ED3461A41319E940"),_T("01F2199FD2DDA564B7B2C2B509C9B867"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("012C11691B3D750330F68718791E6D82"),_T("016F2A0902423BB51F4C00CB28EC2AC2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T(""),_T("0158A6F94ACA7479ADC3CE97BCCF6067"),_T("01966CF476E457732318E23BED0FACFB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T("fine"),_T("0115FB8DBBBF91B4B9D9F034824CB8DE"),_T("013855ED9741DF50B314E3AC7E2F6A3F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E550"),_T("normal"),_T("01131D987286C9F06E27B89F8CB39055"),_T("01E3FB9A93F491AF8D8D25B6C85C60AF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix E900"),_T(""),_T("016FA4721E4BDCA33AB0243056ED052F"),_T("01B0ACBB0E5167B3D432056CDFF87C98"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("018E2B0BAB1091B759DA4A36C1498434"),_T("01B3E93337A2DC7DB01EFC7F0B9260BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("01511F2752713A5E416E7F52CAACC00F"),_T("01652DC355F8FE9317D1ACD1B61F3BFD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("0142BD6537DD267D5315D93E3199D296"),_T("019F6B8CF9E4A7B141FF8C23430ABB79"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("0126DF310012A2906C931B68FFE4A4FF"),_T("01EDEA44DA225D6BAAA693F15D5D9FA4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("01CF6837934F5586370A3208A5964B35"),_T("01CFFF16E1C60E2DBE37A43C7DC375A6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("01F66DD3883F0537836AF63904F782EA"),_T("01F683F377BF9221D4B797F47699DB46"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("01DE1EEA3B2C88A57A1D3894C9F4CA25"),_T("01EEFBA4B1584A8B8B670D9EAB8D0C9D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("0103AF85E3D5BCF4E131B579BE784A54"),_T("011FB35319800515F3B1AF9C01B98F5C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("015263B1DEF7F49143B25A7399503908"),_T("01D9E2046C67FBA14257D043ABD80227"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("01DC8EA12E8F9DE73C730CE2710B6CB1"),_T("01FCD32DF9F3AF71786DD78DC0800136"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("0143172307C00E1BF25477E64B4D871E"),_T("0149D17CAB38C9B9FEBDBA1E18354E75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("0103D886A565CB92A2C07B1E83283938"),_T("01B0DFFF3B86F30AB053C9E4D90E2857"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("01775803404B1F6E51DA270D875AE21C"),_T("018DE101321099CA44B3BBB7A971FC1D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("0135B9D3FA43F42B228C8D68559183A1"),_T("01E9A7153A4282CFAFCB55AE330A529D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("0136AAFA05459AEFAABBB57620F4604F"),_T("01B995B722D53ADDC6AA4D06115AFE4F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("0167ADE27CBB81EED41B08E8DD91919C"),_T("017FA6A0E82890CD1734E1435D5EED33"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("01E63EEB1C76EA886EB86D05A4BF6453"),_T("01EE5B1290C0B04E02A7A5909D728E53"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("01AB6FC5F47A256B85A06A20DF7A2E73"),_T("01D33FAE924EC067B2FA25060B9DBDDE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("01322A55C3F539232F9F48AC5DCA0072"),_T("01448D46E463836F6191E0916423365A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("014D07412D807AFD47466BC3B2DCFD20"),_T("018571F62223F9611C5C82E33361D715"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("01269559519B7DD8BEF85FD3A3D36098"),_T("01699EC66C077829BFC5A565F2406A2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("0106D2E82ED326912ACBE67C2156F424"),_T("01389549659E667495B6C42EE144CB04"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("016177AB8D6680CE1D5BD42F16970EBB"),_T("01CF7260141AA84FBDC5E47A35118EBF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F10"),_T(""),_T("0187E258D1C4458BF14E95702CCA2CF9"),_T("01E68E3620535112F02B2D1133033A90"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("012DA6A8179D685C316E3561ECFDFBBD"),_T("012DA6A8179D685C316E3561ECFDFBBD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("013659FB683254FC54DDE61474AF809C"),_T("0174AB5078929D8E287FECAA4B30532E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0177F18C71320F7FF7F3B037DD101223"),_T("01D9F611647071948F3807C5C4C97964"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("01159F4F09FFCFDABE48FC7C23DCF0CA"),_T("018E6E27D7203B16A8C808E94F67089F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("018C380E60DF1314784C827EFEC4087F"),_T("01C4776D91252150EA3E030855ED4E70"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0107970B1B893B56DEC2A2B1B0B797B1"),_T("0115AB45CC9CD386DAC1E6E7DAB33CD6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0142BD6537DD267D5315D93E3199D296"),_T("019F6B8CF9E4A7B141FF8C23430ABB79"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0125360719B8F561A961A8205CA300A6"),_T("01A12CBCB3929F4F50A2361636A2C17F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0133353D7ACF8F6FFD9C833C91C2DE82"),_T("01DCD75B2D981DCBA8F67F138F5A4689"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("01CF6837934F5586370A3208A5964B35"),_T("01CFFF16E1C60E2DBE37A43C7DC375A6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("01DE1EEA3B2C88A57A1D3894C9F4CA25"),_T("01EEFBA4B1584A8B8B670D9EAB8D0C9D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0103AF85E3D5BCF4E131B579BE784A54"),_T("011FB35319800515F3B1AF9C01B98F5C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("015263B1DEF7F49143B25A7399503908"),_T("01D9E2046C67FBA14257D043ABD80227"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("01DC8EA12E8F9DE73C730CE2710B6CB1"),_T("01FCD32DF9F3AF71786DD78DC0800136"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0103D886A565CB92A2C07B1E83283938"),_T("01B0DFFF3B86F30AB053C9E4D90E2857"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0143A9114D57AEC803D47AB9AA1DAC8E"),_T("01E0F7F87C972B220E1203E00D78FF1E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0113F8BF2685232C081221544B886BE3"),_T("014A4D2D56D0003594C4ECB8139B08D4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0135B9D3FA43F42B228C8D68559183A1"),_T("01E9A7153A4282CFAFCB55AE330A529D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("01340755C56A1C1E8A7E59A1B3BA24D8"),_T("0159C96D7604CE74484E5E1BFDECC62E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("01E63EEB1C76EA886EB86D05A4BF6453"),_T("01EE5B1290C0B04E02A7A5909D728E53"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("019CAE8BAA4E0901A8132DB0460252E6"),_T("01D6C978E3AABF216D5CAACF54F63412"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0132B6121FABF922EC108ED2299A4DF8"),_T("01B1D99243F7145290F94B0DDB143DF1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("013848370A40F0D07134E5F819A35BAA"),_T("01AA5DCFB1E3186C06CED70E710F15C0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F30"),_T(""),_T("0173377CDE7592A2713170C463771BCF"),_T("01D784735642AA8E091C60FEE5FD1DBD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("0109D9B765ADC9B8A749C830F9A87C0C"),_T("01F47FF18B844BA5E3163DC1BB954612"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("0103E19EF10910FD9D0710852668A178"),_T("01D5BC8CE7BC209B25A8C8648FB61439"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("013AB20A7D024D1D24EE5CA8A01B8A2E"),_T("015620909103A039B8D64818100C3538"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("012FCE7A1A81837C7F3783AA9F2CB0CF"),_T("01BDD87262EF899D2EA565BAEBFF8285"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("012BFCCAF570BA39D7758A93212F4FE6"),_T("01383B54C4063EEBA23F13AB1415BB64"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("01EF23B16E6DF6EFE5F4E183E476188A"),_T("01F57F9E26A77E824BF4EA1D93EBFEB6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("0137DD0B0E26F694CBB317E21B4AE230"),_T("01DEB47B3440B79A7568ADAAC0B5D4E1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("0124A6EC131285715A0E4C5C37AACFE8"),_T("01381ECEF3CA87CC5B27C32FC8FCADD0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("01229C5AA062D88A9449065018371866"),_T("015A18E7902796EB4DBDE8A5AC7CDC91"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("018EDB93CFE7F86ECE0E37F92C374F62"),_T("0191E43084B599DC909907C4BA82070A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("01537B41C7887A54ABAAB2B14836B7F6"),_T("01CA67189FF26224721E329BB73A2CF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("0127BA5075AD35F0F85D15DE0568818E"),_T("012A90C987751ECEF261E62CC88755B5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("013CD57992DEE9AF4FF18916A1BAF695"),_T("018849D06D074410D0C51A22F8DECE87"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("014B5F0D2E14DA1836880E0B71113A23"),_T("0178844318AA60BEBB0F3D39BFA7C282"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("014F28993E97414C40DFD0B6C3F53AEA"),_T("01581A04F9ABEEDFFCF3917BB2C925A7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F700"),_T(""),_T("0105B30BB6043B3CC5A9518A60947F04"),_T("011D5E41D0A9E07F8DC8ECBC923E1A50"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("0102FD60B1BEE5C1D4E09C430F3BAF8E"),_T("016A742831A8B18944908F8FE6667FF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("01CF6837934F5586370A3208A5964B35"),_T("01CFFF16E1C60E2DBE37A43C7DC375A6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("0103AF85E3D5BCF4E131B579BE784A54"),_T("011FB35319800515F3B1AF9C01B98F5C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("0136909CD8B831B7F2A1A40DDFE711FA"),_T("013DD960D0C3B58269535DF656FA87AE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("016FA4721E4BDCA33AB0243056ED052F"),_T("01B0ACBB0E5167B3D432056CDFF87C98"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("01E63EEB1C76EA886EB86D05A4BF6453"),_T("01EE5B1290C0B04E02A7A5909D728E53"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("010591CD94BABC13B571DEDB9A76B196"),_T("01F0E53A1233A692F0D17371293F5342"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("013848370A40F0D07134E5F819A35BAA"),_T("01AA5DCFB1E3186C06CED70E710F15C0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("011F13E54D8728C8486C2D0547B93C00"),_T("01E981EDB38DC8239E54BA4805C26B74"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("012840C2B1FCCDE2221D57CD894F5898"),_T("015F4AA8F8D3132E1FAF5DB940997359"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("014953E487E86BCA6BB01842D37A3979"),_T("01CBF30DCDFF5964440C0DD7A1DC9DDD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("0125B5D4DAD31F73197E943B1FA80710"),_T("012B5C9C9DE2B306557D7F6F0ABBC33F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("0195EEA7C7FFC31874CB47F55A731440"),_T("01EA701641AE57738E101037BBDFBAC4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("0177F851C3B1746C6F3ED95C768B72AF"),_T("01A2D84750639B253394A2BC702BBA64"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("011C906212D8A2C45BA66ED96B57DD16"),_T("018F1C3E1FDB4A1785F9BF63ACC5DD1B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("012F2EE5B50FBD87AF3DD370C98D4E3A"),_T("01CF07DB139C22B4C3B7B59640D0EE06"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("010E3334FC94179364A056207AE42ACB"),_T("01BBD1C9C6E595E3D97E4CC4D24E0066"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("015D43A40A0602CAFB865C7620995223"),_T("018D283C92404C7F768254885EFD5DA2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("015BDA2DD1B591063B1D47998A5BF147"),_T("018E9408F19306B79381D994B812C431"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("0124A6EC131285715A0E4C5C37AACFE8"),_T("01381ECEF3CA87CC5B27C32FC8FCADD0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("01450C56AA66881CD17F96A041FC17F7"),_T("01BD74F16BA271F7A0438D79AFC746C5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("01A88E1F6EE058E7ED3461A41319E940"),_T("01F2199FD2DDA564B7B2C2B509C9B867"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix F810"),_T(""),_T("0155A48050753EA001FBAF229F98C84B"),_T("01E7CEA6D4523C9769B9D7E3C0D1CA78"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S20Pro"),_T(""),_T("01AC5C1171760A3C309B7156A91E7E65"),_T("01CA4C33113E1681E0196932FB6D9D81"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("01089D27A104A81CE3A986763DEF98B8"),_T("016783137CC0098188020126C5327C0D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("018E2B0BAB1091B759DA4A36C1498434"),_T("01B3E93337A2DC7DB01EFC7F0B9260BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("01511F2752713A5E416E7F52CAACC00F"),_T("01652DC355F8FE9317D1ACD1B61F3BFD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("0107970B1B893B56DEC2A2B1B0B797B1"),_T("0115AB45CC9CD386DAC1E6E7DAB33CD6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("0126DF310012A2906C931B68FFE4A4FF"),_T("01EDEA44DA225D6BAAA693F15D5D9FA4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("0133353D7ACF8F6FFD9C833C91C2DE82"),_T("01DCD75B2D981DCBA8F67F138F5A4689"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("0103AF85E3D5BCF4E131B579BE784A54"),_T("011FB35319800515F3B1AF9C01B98F5C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("01338863A9E9D87C756424FEB020BD98"),_T("01D90BFC434FAD5B68EA3351CF827D30"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("0143172307C00E1BF25477E64B4D871E"),_T("0149D17CAB38C9B9FEBDBA1E18354E75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("0103D886A565CB92A2C07B1E83283938"),_T("01B0DFFF3B86F30AB053C9E4D90E2857"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("01775803404B1F6E51DA270D875AE21C"),_T("018DE101321099CA44B3BBB7A971FC1D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("0143A9114D57AEC803D47AB9AA1DAC8E"),_T("01E0F7F87C972B220E1203E00D78FF1E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("0126DAA916EC369FF8B1797B107C375F"),_T("01BAC7FF877B99FA2EFE0B0BC9A51F70"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("01A1E20150A519300E142C5DFF57F49D"),_T("01A9F212229355222B1DF6D1C6BA36CE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("0135B9D3FA43F42B228C8D68559183A1"),_T("01E9A7153A4282CFAFCB55AE330A529D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("0147C9CEBD36DF9A8FC10C197C655B9A"),_T("01CBF7CACE5354346E834F315D68854C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("01340755C56A1C1E8A7E59A1B3BA24D8"),_T("0159C96D7604CE74484E5E1BFDECC62E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("016FA4721E4BDCA33AB0243056ED052F"),_T("01B0ACBB0E5167B3D432056CDFF87C98"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("014D07412D807AFD47466BC3B2DCFD20"),_T("018571F62223F9611C5C82E33361D715"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("017548B546BB0963B26B44611755A70D"),_T("01C985AE33A5F28E8BAB1D3ED75ED2A1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S3Pro"),_T(""),_T("014899659B5DFB996E7E35C3DA1F6211"),_T("017230BF5CE1D091A27340E31A89BF61"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("0154B9751596FC0D25ADC6F9D2B6B274"),_T("01D07180C64D9BDF825A5304B71E751F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("019F5DB74FAF31A9F4895A9A007E0A01"),_T("01ADB3065BA5B24F87745074E70B7C54"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("011C1CA26C33CE3E87B733EC41F1E233"),_T("019938269F4D594DE389F9C1DE231D9A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("010E3334FC94179364A056207AE42ACB"),_T("01BBD1C9C6E595E3D97E4CC4D24E0066"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("01991A5434F416A7CCBDACDB066BDFA5"),_T("01E1BB8350885874B0A7C8C9750985BB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("016C0C68D03E7317DDED0A07B2492CA2"),_T("019C0C77CBCDFB463BAA8F0543FA3BC4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("0124A6EC131285715A0E4C5C37AACFE8"),_T("01381ECEF3CA87CC5B27C32FC8FCADD0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("01A88E1F6EE058E7ED3461A41319E940"),_T("01F2199FD2DDA564B7B2C2B509C9B867"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("01062F81528A1594FFBFF7BEED6584DA"),_T("01DE2EFED0143FDF402CD486CF4B67F4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("01A30316FC14ABE0576A6D39338B489F"),_T("01AE9F3C5615392B7144D385A82925AD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("0155A48050753EA001FBAF229F98C84B"),_T("01E7CEA6D4523C9769B9D7E3C0D1CA78"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("014F28993E97414C40DFD0B6C3F53AEA"),_T("01581A04F9ABEEDFFCF3917BB2C925A7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("01172B3480B05799AA98FAB9BBACA31C"),_T("017E24A44A691C3AAC93AA741E7BA8BE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("013C282F2F9C1270D6FC8DD4E334CBE9"),_T("017D5A53E3ABF75F2FBAA66DE6804CA6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("0120638613ED08DC3B923EC45E3F2BDB"),_T("01F85A256DFDBBC84214D566AB8AACFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5000"),_T(""),_T("0123530416265D640E4E07C606357E5A"),_T("012978B985997C7A0597D7CAC69525DA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("01089D27A104A81CE3A986763DEF98B8"),_T("016783137CC0098188020126C5327C0D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("018E2B0BAB1091B759DA4A36C1498434"),_T("01B3E93337A2DC7DB01EFC7F0B9260BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("0126DF310012A2906C931B68FFE4A4FF"),_T("01EDEA44DA225D6BAAA693F15D5D9FA4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("01F66DD3883F0537836AF63904F782EA"),_T("01F683F377BF9221D4B797F47699DB46"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("01DE1EEA3B2C88A57A1D3894C9F4CA25"),_T("01EEFBA4B1584A8B8B670D9EAB8D0C9D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("0103AF85E3D5BCF4E131B579BE784A54"),_T("011FB35319800515F3B1AF9C01B98F5C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("015263B1DEF7F49143B25A7399503908"),_T("01D9E2046C67FBA14257D043ABD80227"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("01338863A9E9D87C756424FEB020BD98"),_T("01D90BFC434FAD5B68EA3351CF827D30"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("01DC8EA12E8F9DE73C730CE2710B6CB1"),_T("01FCD32DF9F3AF71786DD78DC0800136"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("014D9616BBF7E071E910B93ABFB21C27"),_T("018734006FEA2D30B1C0A8F47A50FF74"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("0136AAFA05459AEFAABBB57620F4604F"),_T("01B995B722D53ADDC6AA4D06115AFE4F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("0147C9CEBD36DF9A8FC10C197C655B9A"),_T("01CBF7CACE5354346E834F315D68854C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("013FA8B0D97468662280A7C33A960DD7"),_T("014B6B976D0DF6E350AD535F4BEA101F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("0115FB8DBBBF91B4B9D9F034824CB8DE"),_T("013855ED9741DF50B314E3AC7E2F6A3F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("01BD62DE4967E5CD3906D337D28B5905"),_T("01C9C71A684334A614FC1F7BE6A00D15"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("01AB6FC5F47A256B85A06A20DF7A2E73"),_T("01D33FAE924EC067B2FA25060B9DBDDE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("011A4E131AE6141F56175D11C0FF08F3"),_T("019C6D82AB51688BCFEF61E51C4C4B89"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("01209694C019817E5160C77ECB0E6E73"),_T("01A6E0CFCF95398C049C8A6A8CB5662F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("016ADD09C60862FD6F0B9452EC614AD8"),_T("017B24E070670F38FE2761B505BF97C4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("01322A55C3F539232F9F48AC5DCA0072"),_T("01448D46E463836F6191E0916423365A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("014F18BED4590DE7A0360B979D6C1EC0"),_T("016FC2A0F1990575069647DB51BF5D98"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("011F72189F16FB63160539354A378C18"),_T("01B57B0DB97AF420331DCB82522A4FC0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("011A0B6A5E2CD8D701387C1B92673C51"),_T("01424F959EF392EE7D3A4B878C98E2B2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5500"),_T(""),_T("011A80B1C9B879845EFE6653EA3D3C98"),_T("01423B8723E1E7758F00E44D42A3A2CB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("012DA6A8179D685C316E3561ECFDFBBD"),_T("012DA6A8179D685C316E3561ECFDFBBD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("0129F7BBA55E2EAEB8C9E3BDDBA7B64A"),_T("014363233109D50BE8328B6044FE1D58"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("019EF19678BB82F6281BF75BEE17635A"),_T("01B721616C882F82F632C9C9A02029A3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("013659FB683254FC54DDE61474AF809C"),_T("0174AB5078929D8E287FECAA4B30532E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("0177F18C71320F7FF7F3B037DD101223"),_T("01D9F611647071948F3807C5C4C97964"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("01089D27A104A81CE3A986763DEF98B8"),_T("016783137CC0098188020126C5327C0D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("018C380E60DF1314784C827EFEC4087F"),_T("01C4776D91252150EA3E030855ED4E70"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("01511F2752713A5E416E7F52CAACC00F"),_T("01652DC355F8FE9317D1ACD1B61F3BFD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("0107970B1B893B56DEC2A2B1B0B797B1"),_T("0115AB45CC9CD386DAC1E6E7DAB33CD6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("0126DF310012A2906C931B68FFE4A4FF"),_T("01EDEA44DA225D6BAAA693F15D5D9FA4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("0133353D7ACF8F6FFD9C833C91C2DE82"),_T("01DCD75B2D981DCBA8F67F138F5A4689"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("01CF6837934F5586370A3208A5964B35"),_T("01CFFF16E1C60E2DBE37A43C7DC375A6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("01DE1EEA3B2C88A57A1D3894C9F4CA25"),_T("01EEFBA4B1584A8B8B670D9EAB8D0C9D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("01DC8EA12E8F9DE73C730CE2710B6CB1"),_T("01FCD32DF9F3AF71786DD78DC0800136"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("013FA8B0D97468662280A7C33A960DD7"),_T("014B6B976D0DF6E350AD535F4BEA101F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S5Pro"),_T(""),_T("0115FB8DBBBF91B4B9D9F034824CB8DE"),_T("013855ED9741DF50B314E3AC7E2F6A3F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6000fd"),_T("normal"),_T("0121D8EB73BAC21E4308A56F22BCB342"),_T("01AA1D853FAC38D9FC8DC1E65CED1574"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6000fd"),_T("normal"),_T("01BEB83A517518E7E38D6457D7B098DE"),_T("01EF98C649CA056505C41E28C21A354E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S602 ZOOM"),_T(""),_T("01C6EB2D5C761F5B0F41195E09A7C5E1"),_T("01EDB7106ED8CE9E8F7BD7F14EC44611"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S602 ZOOM"),_T(""),_T("012840C2B1FCCDE2221D57CD894F5898"),_T("015F4AA8F8D3132E1FAF5DB940997359"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S602 ZOOM"),_T(""),_T("0153F536ECB43EAF05B3724640284BC1"),_T("01E70A0FD3DB0A5288CF9E983B6F9531"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S602 ZOOM"),_T(""),_T("01315E29DF55971D2E1D34104AC3E495"),_T("01928C9C997CDBA38DA512091CF1A7F1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("012DA6A8179D685C316E3561ECFDFBBD"),_T("012DA6A8179D685C316E3561ECFDFBBD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("0129F7BBA55E2EAEB8C9E3BDDBA7B64A"),_T("014363233109D50BE8328B6044FE1D58"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("019EF19678BB82F6281BF75BEE17635A"),_T("01B721616C882F82F632C9C9A02029A3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("018C380E60DF1314784C827EFEC4087F"),_T("01C4776D91252150EA3E030855ED4E70"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("018E2B0BAB1091B759DA4A36C1498434"),_T("01B3E93337A2DC7DB01EFC7F0B9260BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("01511F2752713A5E416E7F52CAACC00F"),_T("01652DC355F8FE9317D1ACD1B61F3BFD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("0125360719B8F561A961A8205CA300A6"),_T("01A12CBCB3929F4F50A2361636A2C17F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("0102FD60B1BEE5C1D4E09C430F3BAF8E"),_T("016A742831A8B18944908F8FE6667FF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("0133353D7ACF8F6FFD9C833C91C2DE82"),_T("01DCD75B2D981DCBA8F67F138F5A4689"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("01DE1EEA3B2C88A57A1D3894C9F4CA25"),_T("01EEFBA4B1584A8B8B670D9EAB8D0C9D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("0103AF85E3D5BCF4E131B579BE784A54"),_T("011FB35319800515F3B1AF9C01B98F5C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("01338863A9E9D87C756424FEB020BD98"),_T("01D90BFC434FAD5B68EA3351CF827D30"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("01DC8EA12E8F9DE73C730CE2710B6CB1"),_T("01FCD32DF9F3AF71786DD78DC0800136"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("0143172307C00E1BF25477E64B4D871E"),_T("0149D17CAB38C9B9FEBDBA1E18354E75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("0103D886A565CB92A2C07B1E83283938"),_T("01B0DFFF3B86F30AB053C9E4D90E2857"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("01775803404B1F6E51DA270D875AE21C"),_T("018DE101321099CA44B3BBB7A971FC1D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("01A1E20150A519300E142C5DFF57F49D"),_T("01A9F212229355222B1DF6D1C6BA36CE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("0135B9D3FA43F42B228C8D68559183A1"),_T("01E9A7153A4282CFAFCB55AE330A529D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("015533F5B111AD9E51590E42BF1CF318"),_T("018AE8620E8E1B95D1C8FD0338613321"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("01986403D0DB39CED56956CC83185747"),_T("01D8F9653754860125F8983DB814867D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("01BD62DE4967E5CD3906D337D28B5905"),_T("01C9C71A684334A614FC1F7BE6A00D15"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("01AB6FC5F47A256B85A06A20DF7A2E73"),_T("01D33FAE924EC067B2FA25060B9DBDDE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("01300CF6E26C44CA6E1F7E002E90E29B"),_T("01C97D0146AF14BC73CBB75FBC2DEA7D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("016ADD09C60862FD6F0B9452EC614AD8"),_T("017B24E070670F38FE2761B505BF97C4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S6500fd"),_T(""),_T("0173E1FDEFE1767FC62734B7FD5B4FE6"),_T("017EFC8A48D105AD27C16C3EC1B7A211"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("01986403D0DB39CED56956CC83185747"),_T("01D8F9653754860125F8983DB814867D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("0139C3609C7439A2677D0591BAA17CA0"),_T("017CE35D279F1A8B21080E0AE6C53CAD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("01870F12535AD117686AA38D87F4F230"),_T("01F1932E46B612094A22F38BD5FF970E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("011A0B6A5E2CD8D701387C1B92673C51"),_T("01424F959EF392EE7D3A4B878C98E2B2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("0153F536ECB43EAF05B3724640284BC1"),_T("01E70A0FD3DB0A5288CF9E983B6F9531"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("01B87A9323B8323DBBF8D268C8DA5CCB"),_T("01FA3743550ECF2375FD313472BC7415"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("01269559519B7DD8BEF85FD3A3D36098"),_T("01699EC66C077829BFC5A565F2406A2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("0195EEA7C7FFC31874CB47F55A731440"),_T("01EA701641AE57738E101037BBDFBAC4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("012ACF619E4947C6342F0DFA82B454F4"),_T("017696925674863D4E93611CF53FE982"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("0158F705D871236CACBC097D8FF7E553"),_T("01C46C517D157C7456DAB45044446CB2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("01D44FF54148D7672B0F9F149588C216"),_T("01FCF038CB0AFCB826D6834D3B9BB7FF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("01B6370B0E1246DC33A50DE4AFAE3064"),_T("01C32DF8021355EF8B5777806A810BFE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("01932B6BF7C7C4EA0676C13FE773E9F0"),_T("01B0A192C8D2D9B359A6A71DBFC65DE7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("01C1350830CDC224402C69FBBA4B4D32"),_T("01C40C78BB04798DE6386B16D6CA2F48"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("0160C13457E7492844700B1E2765A7C2"),_T("017374AB9A06F5B7D9C547A5D586B0BE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("011593FAC397BE3E35F132DA00BB55C1"),_T("014D9687F924E7724F494F7538C9C7EF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S7000"),_T(""),_T("014412B6367A91A2120C56FE9DEDCF7A"),_T("0199DFAF205A8F5ED6131F8C9D4E7C4C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("012DA6A8179D685C316E3561ECFDFBBD"),_T("012DA6A8179D685C316E3561ECFDFBBD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("0129F7BBA55E2EAEB8C9E3BDDBA7B64A"),_T("014363233109D50BE8328B6044FE1D58"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("013659FB683254FC54DDE61474AF809C"),_T("0174AB5078929D8E287FECAA4B30532E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("0177F18C71320F7FF7F3B037DD101223"),_T("01D9F611647071948F3807C5C4C97964"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("01089D27A104A81CE3A986763DEF98B8"),_T("016783137CC0098188020126C5327C0D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("01159F4F09FFCFDABE48FC7C23DCF0CA"),_T("018E6E27D7203B16A8C808E94F67089F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("018E2B0BAB1091B759DA4A36C1498434"),_T("01B3E93337A2DC7DB01EFC7F0B9260BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("0142BD6537DD267D5315D93E3199D296"),_T("019F6B8CF9E4A7B141FF8C23430ABB79"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("0168B62B2672A1EA16B5EEFCE01A5D3D"),_T("01DA3B84475F74FFA005D8B903F9305C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("01004744D797C2E65F6E10A01801F988"),_T("0126C34F057B641EA35917CAE5BABD04"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("0125360719B8F561A961A8205CA300A6"),_T("01A12CBCB3929F4F50A2361636A2C17F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("01CF6837934F5586370A3208A5964B35"),_T("01CFFF16E1C60E2DBE37A43C7DC375A6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("01DE1EEA3B2C88A57A1D3894C9F4CA25"),_T("01EEFBA4B1584A8B8B670D9EAB8D0C9D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("01338863A9E9D87C756424FEB020BD98"),_T("01D90BFC434FAD5B68EA3351CF827D30"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("01775803404B1F6E51DA270D875AE21C"),_T("018DE101321099CA44B3BBB7A971FC1D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("0126DAA916EC369FF8B1797B107C375F"),_T("01BAC7FF877B99FA2EFE0B0BC9A51F70"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("0147C9CEBD36DF9A8FC10C197C655B9A"),_T("01CBF7CACE5354346E834F315D68854C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("0115FB8DBBBF91B4B9D9F034824CB8DE"),_T("013855ED9741DF50B314E3AC7E2F6A3F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("01DF82190E252AC7A11162C378E74D8F"),_T("01F6A274D8F0CBC5C82B7B67941C1C8E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("014899659B5DFB996E7E35C3DA1F6211"),_T("017230BF5CE1D091A27340E31A89BF61"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("015BFED124534D3E92BBF2906045F273"),_T("0190E3CE4CB1DEB9C26685C28EE19669"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix S9500"),_T(""),_T("01B6890F97E3942CF6210514EAD0B4DF"),_T("01F14DAD8C7B9AAAC1F8DB9C88E21E3F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix V10"),_T("fine"),_T("01DC8EA12E8F9DE73C730CE2710B6CB1"),_T("01FCD32DF9F3AF71786DD78DC0800136"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix2650"),_T(""),_T("0173E1FDEFE1767FC62734B7FD5B4FE6"),_T("017EFC8A48D105AD27C16C3EC1B7A211"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix2650"),_T(""),_T("0103BCA9D0FF326CE25144CF5AE1D884"),_T("019F7525A3CBF83459E6870C7D506833"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("0139C3609C7439A2677D0591BAA17CA0"),_T("017CE35D279F1A8B21080E0AE6C53CAD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("019CAE8BAA4E0901A8132DB0460252E6"),_T("01D6C978E3AABF216D5CAACF54F63412"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("01300CF6E26C44CA6E1F7E002E90E29B"),_T("01C97D0146AF14BC73CBB75FBC2DEA7D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("0131856988BD7B6B71E3C17784F3B1DF"),_T("0164A6B8BA79A38657D4129B88C1E935"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("012EFDA0756DC8F02E1314E0A85E38DA"),_T("0150B33D240B71C570632E01FEB03F89"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("0117AFF0AC55A9FA9B557341ED28AA4F"),_T("019FC66891E7C2CB433015662520C0B7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("0102C9551E830545C18B70A571480094"),_T("01F15F441249A8D22F60EE46C1A5E212"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("0178484D9EC1A5ECCEAE50569236B015"),_T("01A26D8FAC66BE2064402779D63E7401"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("014B61CBCC7D97DD7DB61C0EFD0AB9D3"),_T("0171C28AC02233CEF51F1715DD281396"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("019A4D45AE6936BB8BEC4EDE730117CD"),_T("01A11FE6F7D27DC64C8B2B33D2897452"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("017058A60BB7E5ABA088618FFB832B0A"),_T("01EE2DF6C151E5ACD0A3486FBF4E13BE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("0120638613ED08DC3B923EC45E3F2BDB"),_T("01F85A256DFDBBC84214D566AB8AACFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("01162961AA289CC2513853FB31F0ACDB"),_T("0120F0B88A52100F82FEABC058B05CBF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("015474DAE40565467683F60E7D6B6F73"),_T("01B3F14AE750544D9C9AD20F6B823CEC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("015CE917BCF8AC73508BA0C75E562B75"),_T("01F42AADEAF7C0257B27DCBE24A2EAC0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("01957F28DB8A7D2E18F08AEA246A4DE3"),_T("01E323A0DF8F66AE1E221AE79A931716"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("01406565599DBF14F8047FC359DD66A6"),_T("017D5401D16B226E8EC07EDDA05439CD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("0189E78B2B76067BD8FD61F468E67EB1"),_T("01F59D383C499039CF4F238405E5F9C3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix40i"),_T(""),_T("013F606C45AD191612B28EEF1CF6D7F9"),_T("0170C371C8D24158A7740555A3D0254E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix4700 ZOOM"),_T(""),_T("01B9EBFD77569CE29D8C032DA51DAD85"),_T("01BAD4B2C44FC0802AD488E3B5325405"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix4700 ZOOM"),_T(""),_T("01BF1089DB13798CF30FA0B6E186875D"),_T("01F21F74C1D6A089ACB1C6E39E624E84"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("01400713A3B10D105792E66D14AE5117"),_T("019624AE422BF7F88A92118F611DD996"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("016ADD09C60862FD6F0B9452EC614AD8"),_T("017B24E070670F38FE2761B505BF97C4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("01322A55C3F539232F9F48AC5DCA0072"),_T("01448D46E463836F6191E0916423365A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("014D07412D807AFD47466BC3B2DCFD20"),_T("018571F62223F9611C5C82E33361D715"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("011F72189F16FB63160539354A378C18"),_T("01B57B0DB97AF420331DCB82522A4FC0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("018A502DE0262FC6DC8403269363DDAA"),_T("01931CC3681EB77CAE72911CE36B4E45"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("012840C2B1FCCDE2221D57CD894F5898"),_T("015F4AA8F8D3132E1FAF5DB940997359"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("017AAFD0B2845F41BAEC5521AF7E60BE"),_T("017CFBCEBE300D30A2D3DEAD73C002D0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("011BC0CF1B8F6C86A969EDB72AF27E24"),_T("01C994AFEBE3496186FC47707252ED30"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("0107F7F326C0D058D0FC463309D21C61"),_T("01FADF48C0D5EFBD05CA31667FBD79DE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("01314A8C33DC01682816CD4AFE0E7B96"),_T("01FF7EAC06B780BA2C3FC2E5C66BFF3C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("0108B1AD56CEBAD5367B758EE1A63F18"),_T("017AC2BA97E4EDA4876AD2D0189C8F06"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("01927DE8CDA4A34FD981CA1E4BA453B3"),_T("01DC11991BE26BEBDC12355CA2257CB1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("013FB5BDF7687EB994ECEB079C294E87"),_T("01D99CAE0607C1F221C77094F1740AFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("01F555C022AB19D485F62E5008BC0722"),_T("01FD0F0A93A98D049E8365862CBC20EB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("01957F28DB8A7D2E18F08AEA246A4DE3"),_T("01E323A0DF8F66AE1E221AE79A931716"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6800 ZOOM"),_T(""),_T("016DFAF277299189E9A1092D09A50FFE"),_T("01E0D78873374FD205A32162BC32DC8E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("0126DAA916EC369FF8B1797B107C375F"),_T("01BAC7FF877B99FA2EFE0B0BC9A51F70"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("015533F5B111AD9E51590E42BF1CF318"),_T("018AE8620E8E1B95D1C8FD0338613321"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("0139C3609C7439A2677D0591BAA17CA0"),_T("017CE35D279F1A8B21080E0AE6C53CAD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("0161149FCDDF874DEC4C938ED855AACC"),_T("01D3BAD36E511A7EAC1E7792840C74B5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("019CAE8BAA4E0901A8132DB0460252E6"),_T("01D6C978E3AABF216D5CAACF54F63412"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("011A4E131AE6141F56175D11C0FF08F3"),_T("019C6D82AB51688BCFEF61E51C4C4B89"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("016ADD09C60862FD6F0B9452EC614AD8"),_T("017B24E070670F38FE2761B505BF97C4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("0132B6121FABF922EC108ED2299A4DF8"),_T("01B1D99243F7145290F94B0DDB143DF1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("010591CD94BABC13B571DEDB9A76B196"),_T("01F0E53A1233A692F0D17371293F5342"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("013220D5B0D1F5FE11D1EF6E38C75F28"),_T("01FF04703C85EEC5589CB5AFC641A3B8"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("0145F26B95FF8AF15D1A7DC64355F872"),_T("016D15F943FA53E2F9E93A89A926B850"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("014F18BED4590DE7A0360B979D6C1EC0"),_T("016FC2A0F1990575069647DB51BF5D98"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("011A0B6A5E2CD8D701387C1B92673C51"),_T("01424F959EF392EE7D3A4B878C98E2B2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("01C6EB2D5C761F5B0F41195E09A7C5E1"),_T("01EDB7106ED8CE9E8F7BD7F14EC44611"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("013848370A40F0D07134E5F819A35BAA"),_T("01AA5DCFB1E3186C06CED70E710F15C0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("018A502DE0262FC6DC8403269363DDAA"),_T("01931CC3681EB77CAE72911CE36B4E45"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("01B9EBFD77569CE29D8C032DA51DAD85"),_T("01BAD4B2C44FC0802AD488E3B5325405"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("018892FB2CB156925F1964F3023E30B0"),_T("01C678B5E26E2424556FF4830079520C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("017548B546BB0963B26B44611755A70D"),_T("01C985AE33A5F28E8BAB1D3ED75ED2A1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("01DF82190E252AC7A11162C378E74D8F"),_T("01F6A274D8F0CBC5C82B7B67941C1C8E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("0105CCB4C4B348AE594D640D47A029B7"),_T("014CE1370398E06CCA7E7635DA264D67"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("0125B5D4DAD31F73197E943B1FA80710"),_T("012B5C9C9DE2B306557D7F6F0ABBC33F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("0195EEA7C7FFC31874CB47F55A731440"),_T("01EA701641AE57738E101037BBDFBAC4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("015BFED124534D3E92BBF2906045F273"),_T("0190E3CE4CB1DEB9C26685C28EE19669"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePix6900ZOOM"),_T(""),_T("01DB93351D55A5C6665EB31A9849CC52"),_T("01DE4A1BA4CE22FA6FB6A0A223F62D8F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePixS1Pro"),_T(""),_T("013FA8B0D97468662280A7C33A960DD7"),_T("014B6B976D0DF6E350AD535F4BEA101F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("FUJIFILM"),_T("FinePixS2Pro"),_T(""),_T("014D9616BBF7E071E910B93ABFB21C27"),_T("018734006FEA2D30B1C0A8F47A50FF74"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Hewlett-Packard"),_T("HP PhotoSmart C935 (V03.46)"),_T(""),_T("013A863D37AA0BE299071B31D3548CC5"),_T("01704C1F618115BDBB14771D54A2F822"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Hewlett-Packard"),_T("HP PhotoSmart R707 (V01.00)"),_T(""),_T("01205DF2136851A02AF30ADF84ABA11E"),_T("01205DF2136851A02AF30ADF84ABA11E"),_T("1x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Hewlett-Packard"),_T("HP PhotoSmart R707 (V01.00)"),_T(""),_T("0116133E48F8ECEDAB742EBF6BAC284F"),_T("01631DCA5E69DD1AD024465A7AA266E0"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Hewlett-Packard"),_T("HP PhotoSmart R707 (V01.00)"),_T(""),_T("0116133E48F8ECEDAB742EBF6BAC284F"),_T("01631DCA5E69DD1AD024465A7AA266E0"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Hewlett-Packard"),_T("HP PhotoSmart R707 (V01.00)d"),_T(""),_T("01205DF2136851A02AF30ADF84ABA11E"),_T("01205DF2136851A02AF30ADF84ABA11E"),_T("1x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Hewlett-Packard"),_T("HP PhotoSmart R707 (V01.00)d"),_T(""),_T("0116133E48F8ECEDAB742EBF6BAC284F"),_T("01631DCA5E69DD1AD024465A7AA266E0"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Hewlett-Packard"),_T("HP PhotoSmart R707 (V01.00)d"),_T(""),_T("0116133E48F8ECEDAB742EBF6BAC284F"),_T("01631DCA5E69DD1AD024465A7AA266E0"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Hewlett-Packard Company"),_T("HP PhotoSmart 315"),_T(""),_T("019199CA85730911299600A6D6C93A8B"),_T("01A383DA6BF7479D28B19AA0074FCF71"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("DiMAGE A200"),_T(""),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("DiMAGE A200"),_T(""),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("DiMAGE A200"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("DiMAGE A200"),_T(""),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("DiMAGE A200"),_T(""),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("DiMAGE A200"),_T(""),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("DiMAGE A200"),_T(""),_T("01BD24596581D7A1535AFC805B0D60A2"),_T("01D47AD28A985151B705F90864369E2C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("DiMAGE A200"),_T(""),_T("012876087A56CFCA7CFEC7D254AD88D7"),_T("01C6BBED27FF2B3D0E26E4009B66E38B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("DiMAGE X1"),_T(""),_T("01605B36C27A91863BAE84A614E5A6E4"),_T("01F92B192C6A8A1E122F5E86BF586B21"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("DiMAGE Z5"),_T(""),_T("01574BED6DDCCAA822CC146FBC040AD3"),_T("01B58D1B77454977FCFDA55DD2461963"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("MAXXUM 5D"),_T(""),_T("01DC669AEC37FB0775F2E831266AF705"),_T("01DC669AEC37FB0775F2E831266AF705"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("MAXXUM 7D"),_T(""),_T("01DC669AEC37FB0775F2E831266AF705"),_T("01DC669AEC37FB0775F2E831266AF705"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KONICA MINOLTA"),_T("MAXXUM 7D"),_T(""),_T("010C6FB9C20DA535F1E85B7129DDA2C8"),_T("013F4575982733FD3AC4FC46459ECCBB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE A2"),_T(""),_T("0151D6730547B1732F1428518F41C9F6"),_T("0180267FA9A456EDEBBCEE6011CB1AA3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE A2"),_T(""),_T("011158B7475856AC9E477562F1AE68DE"),_T("01BEF7217A1C2BD460A84D645491083C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE Z2"),_T(""),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE Z2"),_T(""),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE Z2"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE Z2"),_T(""),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE Z2"),_T(""),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE Z2"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE Z2"),_T(""),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE Z2"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Konica Minolta Camera, Inc."),_T("DiMAGE Z2"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("KYOCERA"),_T("FC-S3"),_T(""),_T("01CAE3D12075ADF4431488E73D758A9F"),_T("01CCD42AB84A46D8AC1AA4A68125A0DD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("LEICA"),_T("DIGILUX 2"),_T(""),_T("01A80023CDC86D90CD9F92AF55575482"),_T("01B2EADEE5D2C6887670513AD186ACB5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("LEICA"),_T("DIGILUX 2"),_T(""),_T("0131425FDE6F5E75E059E0550C40F980"),_T("015893E2971294882CF4EBDD82414044"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("LEICA"),_T("DIGILUX 2"),_T(""),_T("01550C3F4489ABC67200B2CED3B02537"),_T("019D8ABB0272467D0F475E3CAB7B0978"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("LEICA"),_T("DIGILUX 2"),_T(""),_T("0143E2834A286CF542FA2972C0478CC5"),_T("01D122D556870F2E0FBA1EB2B32EB550"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("LEICA"),_T("DIGILUX 2"),_T(""),_T("016F84D0243E6A5B2CC1572E5CA4948E"),_T("01E13E8834276D783C8B088EA2E071B3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("LEICA"),_T("DIGILUX 2"),_T(""),_T("01146210F8F782499562164D98588DF7"),_T("01416268426EA8AA822C30E62CB99184"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("LEICA"),_T("DIGILUX 2"),_T(""),_T("0120BC9F7FBDE71C9F7AF75F1271DE8E"),_T("0168E10B1946222765F3952D9095AA5E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("LEICA"),_T("DIGILUX 2"),_T(""),_T("01B02D6252495A2B9D08BBBBFEA0369C"),_T("01C44B75CC82D3AE8CA47C53C0367FA1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Leica Camera AG"),_T("M8 Digital Camera"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Leica Camera AG"),_T("M8 Digital Camera"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Leica Camera AG"),_T("M8 Digital Camera"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE 7Hi"),_T(""),_T("0151D6730547B1732F1428518F41C9F6"),_T("0180267FA9A456EDEBBCEE6011CB1AA3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE 7Hi"),_T(""),_T("011158B7475856AC9E477562F1AE68DE"),_T("01BEF7217A1C2BD460A84D645491083C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("Dimage EX"),_T(""),_T("014CBA7CF41D9FFFD11933E748C4AC6E"),_T("014CBA7CF41D9FFFD11933E748C4AC6E"),_T("1x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("Dimage EX"),_T(""),_T("014CBA7CF41D9FFFD11933E748C4AC6E"),_T("014CBA7CF41D9FFFD11933E748C4AC6E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE F100"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE F100"),_T(""),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE F100"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE F100"),_T(""),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE F100"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE F100"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE F100"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE F100"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE S304"),_T(""),_T("0184192EB1977CC6268343E6D3134191"),_T("01F0AFDCFFFAA57D4AD7C0227EE1B579"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Minolta Co., Ltd."),_T("DiMAGE S304"),_T(""),_T("011158B7475856AC9E477562F1AE68DE"),_T("01BEF7217A1C2BD460A84D645491083C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX L12"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P2"),_T("FINE"),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("0135744CED39E5E2D1D49B97A23E3ED4"),_T("01F8F364323CCDD63F0F238CA9CDCEB1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("013CB9B72088B06DE7931FD5B1C1A049"),_T("01AC143B735AABE226CF68DF7824E697"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("01574BED6DDCCAA822CC146FBC040AD3"),_T("01B58D1B77454977FCFDA55DD2461963"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("0144E26FB9BA003C2AF6A895D6E9CEAF"),_T("01B8E50677C21B70F8FC7A5FB398B8E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("013C26239BC3004EC0E1984F79A2E053"),_T("0159C4239254A897A6B1DA7E87648344"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("01533B110E20F3AC48999897834373DB"),_T("017CEDD8688FEFC6B8CAE0968021824A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("01B9E92D5CE414394429CCED76B89949"),_T("01C1C1593753CDBB62B9FD282846CFC7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("0163462BFBD4A64917560469CB201547"),_T("01AC950CF614B011A45DBA57653F8034"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("01764A58772BF2B2118E21F2035E3536"),_T("01A192EB488B778995905709D072210A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("01B58550F0786C24AD24DD26F9915727"),_T("01BC5FB692DA4A34C6A7D5438989B2F7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("015916E2168735FB572926A049B025DB"),_T("01F9ED4812F46CA42CB85C9371E94710"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("012706B411DF0C5629682D10083CB68A"),_T("0195F4BD0E07A4CDEF7400EC94BB5E75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P3"),_T("FINE"),_T("0159C3DD4607B9ACB9BB3F5D7191891A"),_T("01901016622EBC2E42EE162000A13DE3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("0134F2041810CE97DAAB408D5E71163C"),_T("01D831EF97768EF36E607FD5D85426FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("0123BAAA6DABBA3007987C5DD352F23A"),_T("0162F90EF60A9DB921AA87532AE23D68"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX P5000"),_T("FINE"),_T("012402B6D67E6105719FB11153F3C804"),_T("017E816CD8B40EB76B66F94A63ED38FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX S10"),_T("FINE"),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX S10"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX S10"),_T("FINE"),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX S10"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX S10"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX S10"),_T("FINE"),_T("0134F2041810CE97DAAB408D5E71163C"),_T("01D831EF97768EF36E607FD5D85426FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("COOLPIX S5"),_T("NORMAL"),_T("01625155BE84D00125E6E169DF4A2F65"),_T("01C54F8112BAF719522090C85C5E23F1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("0134F2041810CE97DAAB408D5E71163C"),_T("01D831EF97768EF36E607FD5D85426FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("01BD24596581D7A1535AFC805B0D60A2"),_T("01D47AD28A985151B705F90864369E2C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E2500"),_T("FINE"),_T("0155D875C95B74D0F3C5835A62516F48"),_T("01D38A25358EB7649A254E19F1D46600"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("FINE"),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("FINE"),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("FINE"),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("FINE"),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("FINE"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("NORMAL"),_T("013ACAC180247B71700A6278939D82A8"),_T("01C67F4B42859DDFF107237CE8D4B047"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("NORMAL"),_T("012876087A56CFCA7CFEC7D254AD88D7"),_T("01C6BBED27FF2B3D0E26E4009B66E38B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("NORMAL"),_T("0120996088E68CF9F70A20A414D14AE6"),_T("013E3A5D329BBCB6AAF62F2E18FF8127"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E3100"),_T("NORMAL"),_T("017659A2F9A530359CB8725D32B5BE6C"),_T("01F863D3F47BE8F243BFF177EAC1EDB4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4500"),_T("FINE"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4600"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("FINE"),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("FINE"),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("FINE"),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("FINE"),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("FINE"),_T("01625155BE84D00125E6E169DF4A2F65"),_T("01C54F8112BAF719522090C85C5E23F1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("FINE"),_T("0100E9AA36415D0482E7AD68EAF372C3"),_T("012840F1B30DA4789A3345257EEB59C9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("NORMAL"),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("NORMAL"),_T("010176D29AD13D3FFAC14F0D3932B95E"),_T("01A05E3557B786BCF9267EAB607AEE7C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E4800"),_T("NORMAL"),_T("016C4383FFABE35F063D8FCB331942C0"),_T("019DC7724B5425C464D28F2CF78F707E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5000"),_T("FINE"),_T("012402B6D67E6105719FB11153F3C804"),_T("017E816CD8B40EB76B66F94A63ED38FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5200"),_T("FINE"),_T("01BC50262FBBFF6362759E0D0536794E"),_T("01F4661730D2DB6A83CF98B0179EB03E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5200"),_T("FINE"),_T("013CB9B72088B06DE7931FD5B1C1A049"),_T("01AC143B735AABE226CF68DF7824E697"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5200"),_T("FINE"),_T("0144E26FB9BA003C2AF6A895D6E9CEAF"),_T("01B8E50677C21B70F8FC7A5FB398B8E4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5200"),_T("FINE"),_T("013C26239BC3004EC0E1984F79A2E053"),_T("0159C4239254A897A6B1DA7E87648344"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5200"),_T("FINE"),_T("01533B110E20F3AC48999897834373DB"),_T("017CEDD8688FEFC6B8CAE0968021824A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5200"),_T("FINE"),_T("01B9E92D5CE414394429CCED76B89949"),_T("01C1C1593753CDBB62B9FD282846CFC7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5200"),_T("FINE"),_T("0163462BFBD4A64917560469CB201547"),_T("01AC950CF614B011A45DBA57653F8034"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5200"),_T("FINE"),_T("0173F1E44DAC63C1C6803AEB21D68121"),_T("01A7CCF0C258A5AA0A372238704D3964"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5200"),_T("FINE"),_T("011ED6AAC481E84EB7DF7D6C55C35FDB"),_T("01F41F75DA85DCEE81F79C9BFD835249"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5400"),_T("FINE"),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5400"),_T("FINE"),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5400"),_T("FINE"),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5400"),_T("FINE"),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5400"),_T("FINE"),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5400"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5400"),_T("FINE"),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5400"),_T("FINE"),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5400"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5400"),_T("FINE"),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("01BD24596581D7A1535AFC805B0D60A2"),_T("01D47AD28A985151B705F90864369E2C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("FINE"),_T("012402B6D67E6105719FB11153F3C804"),_T("017E816CD8B40EB76B66F94A63ED38FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E5700"),_T("RAW"),_T("012933907CE4B9D3C27E3E9D4D50BFD6"),_T("012933907CE4B9D3C27E3E9D4D50BFD6"),_T("1x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E775"),_T("FINE"),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E775"),_T("FINE"),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E775"),_T("FINE"),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E775"),_T("FINE"),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E775"),_T("FINE"),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E775"),_T("FINE"),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E775"),_T("FINE"),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E775"),_T("FINE"),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E775"),_T("FINE"),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E775"),_T("FINE"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E7900"),_T("FINE"),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E7900"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E7900"),_T("FINE"),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E7900"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E7900"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E7900"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E7900"),_T("FINE"),_T("01BD24596581D7A1535AFC805B0D60A2"),_T("01D47AD28A985151B705F90864369E2C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E7900"),_T("NORMAL"),_T("012876087A56CFCA7CFEC7D254AD88D7"),_T("01C6BBED27FF2B3D0E26E4009B66E38B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E7900"),_T("NORMAL"),_T("01625155BE84D00125E6E169DF4A2F65"),_T("01C54F8112BAF719522090C85C5E23F1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8400"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8400"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8400"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8400"),_T("FINE"),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8700"),_T("FINE"),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8800"),_T("EXTRA"),_T("0124AC8790656DF23F8070E2A880B501"),_T("016CC716D191DBD0BB21F1090184405D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8800"),_T("FINE"),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8800"),_T("FINE"),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E8800"),_T("FINE"),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E885"),_T("FINE"),_T("0165B3F1B409A4D8D5F2ADFFA970D3A5"),_T("0165B3F1B409A4D8D5F2ADFFA970D3A5"),_T("1x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E885"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E885"),_T("FINE"),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E885"),_T("FINE"),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E885"),_T("FINE"),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E885"),_T("FINE"),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E885"),_T("FINE"),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E885"),_T("FINE"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E885"),_T("FINE"),_T("010F50672F14B4A88409AEC86E9DECE9"),_T("01C3B4FE62DF9A99F1CA8A5C17AC7711"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E885"),_T("FINE"),_T("0134F2041810CE97DAAB408D5E71163C"),_T("01D831EF97768EF36E607FD5D85426FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E995"),_T("FINE"),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("E995"),_T("FINE"),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D1"),_T("FINE"),_T("012A783CCEA06D57AFD2961BDCAB0D55"),_T("01C09FE954D02261612AB2F26E6C71AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D100"),_T("FINE"),_T("012F557E656D34C0A277B8470E9C4514"),_T("01E600E35F0A8CD0D9FE2D31B998D709"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D1H"),_T("FINE"),_T("012F557E656D34C0A277B8470E9C4514"),_T("01E600E35F0A8CD0D9FE2D31B998D709"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D1X"),_T("FINE"),_T("012D53B2BC8DEEC423C726A99B23EFFB"),_T("01342830C284AABC77AEBE2A43D20C2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D200"),_T("FINE"),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D200"),_T("FINE"),_T("0103A1C445586D96DAFDC06542FD9968"),_T("016F5C933A7B31BA8437BDB3DE186E60"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D200"),_T("FINE"),_T("012F557E656D34C0A277B8470E9C4514"),_T("01E600E35F0A8CD0D9FE2D31B998D709"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D200"),_T("FINE"),_T("0119C6E2A0C136712CC82D09D3AD6D47"),_T("0165098BC665654C03482EBA8880EB6D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D200"),_T("FINE"),_T("0120A81C1C6B471497B2C39DD796FE4D"),_T("015E09F77A7C92CAAEEEB1C80AE632CD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D200"),_T("FINE"),_T("01292260CD87AAB3D2B0BC3DD8B4776C"),_T("016D5EE47029175386D08F8ED963988D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D200"),_T("FINE"),_T("012D53B2BC8DEEC423C726A99B23EFFB"),_T("01342830C284AABC77AEBE2A43D20C2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D200"),_T("FINE"),_T("012A783CCEA06D57AFD2961BDCAB0D55"),_T("01C09FE954D02261612AB2F26E6C71AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D2H"),_T("FINE"),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D2H"),_T("FINE"),_T("0103A1C445586D96DAFDC06542FD9968"),_T("016F5C933A7B31BA8437BDB3DE186E60"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D2H"),_T("FINE"),_T("012F557E656D34C0A277B8470E9C4514"),_T("01E600E35F0A8CD0D9FE2D31B998D709"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D2H"),_T("FINE"),_T("012D53B2BC8DEEC423C726A99B23EFFB"),_T("01342830C284AABC77AEBE2A43D20C2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D2X"),_T("FINE"),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D2X"),_T("FINE"),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D3"),_T("FINE"),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D300"),_T("FINE"),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40"),_T("FINE"),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40"),_T("FINE"),_T("0103A1C445586D96DAFDC06542FD9968"),_T("016F5C933A7B31BA8437BDB3DE186E60"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40"),_T("FINE"),_T("012F557E656D34C0A277B8470E9C4514"),_T("01E600E35F0A8CD0D9FE2D31B998D709"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40"),_T("FINE"),_T("012D53B2BC8DEEC423C726A99B23EFFB"),_T("01342830C284AABC77AEBE2A43D20C2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40"),_T("FINE"),_T("0114ED88173433C4BF99F0569EA94D90"),_T("019E0FC5DA517712EF95A6C1789E61D0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40"),_T("FINE"),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40"),_T("FINE"),_T("01D13AFD01FF0B6EC46EA4081D25BB4D"),_T("01FF5BA518B453CC8F224A4C85505196"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40"),_T("FINE"),_T("010406665318412F7AE7B4533F75EB76"),_T("019363EF9F2ECA136B352D0C47E63CF1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40X"),_T("FINE"),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40X"),_T("FINE"),_T("0103A1C445586D96DAFDC06542FD9968"),_T("016F5C933A7B31BA8437BDB3DE186E60"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40X"),_T("FINE"),_T("014277D1DDB84253758F0F33BA54C7A2"),_T("0149438163B8EE0EE5F349FB365DC931"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40X"),_T("FINE"),_T("0120A81C1C6B471497B2C39DD796FE4D"),_T("015E09F77A7C92CAAEEEB1C80AE632CD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40X"),_T("FINE"),_T("017211BC8C6161BCE36DB4E91A7A575F"),_T("018C775AA14027570ED51F477477AA84"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D40X"),_T("NORMAL"),_T("016316C80954E937BBAC5CCDC94A2ABF"),_T("01CA96F6D54E052A082B32260A1C363F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D50"),_T("FINE"),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D50"),_T("FINE"),_T("0103A1C445586D96DAFDC06542FD9968"),_T("016F5C933A7B31BA8437BDB3DE186E60"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D50"),_T("FINE"),_T("012D53B2BC8DEEC423C726A99B23EFFB"),_T("01342830C284AABC77AEBE2A43D20C2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D50"),_T("FINE"),_T("01337EA310F3CF72C36B8AA6F7B5B042"),_T("014D068B9432D4C85F0F18F767DD368B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D50"),_T("FINE"),_T("010CC33FB192BF2F6D9CB720360C5711"),_T("010F766EEF9BFC2D9829794E01D705EE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D70"),_T("FINE"),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D70"),_T("FINE"),_T("0103A1C445586D96DAFDC06542FD9968"),_T("016F5C933A7B31BA8437BDB3DE186E60"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D70"),_T("FINE"),_T("012D53B2BC8DEEC423C726A99B23EFFB"),_T("01342830C284AABC77AEBE2A43D20C2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D70s"),_T("FINE"),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D80"),_T("FINE"),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D80"),_T("FINE"),_T("0103A1C445586D96DAFDC06542FD9968"),_T("016F5C933A7B31BA8437BDB3DE186E60"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D80"),_T("FINE"),_T("012F557E656D34C0A277B8470E9C4514"),_T("01E600E35F0A8CD0D9FE2D31B998D709"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D80"),_T("FINE"),_T("014277D1DDB84253758F0F33BA54C7A2"),_T("0149438163B8EE0EE5F349FB365DC931"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D80"),_T("FINE"),_T("0119C6E2A0C136712CC82D09D3AD6D47"),_T("0165098BC665654C03482EBA8880EB6D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("NIKON"),_T("NIKON D80"),_T("FINE"),_T("0100CFEEBE21B71A129B9F5EE8B64138"),_T("013D4003F1AB977990BD3347854082B2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Nokia"),_T("N73"),_T(""),_T("0155D875C95B74D0F3C5835A62516F48"),_T("01D38A25358EB7649A254E19F1D46600"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("C770UZ"),_T(""),_T("0123BAAA6DABBA3007987C5DD352F23A"),_T("0162F90EF60A9DB921AA87532AE23D68"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("C8080WZ"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("C8080WZ"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("C8080WZ"),_T(""),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("C8080WZ"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("C8080WZ"),_T(""),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("C8080WZ"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("C8080WZ"),_T(""),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("C8080WZ"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("C8080WZ"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("E-1"),_T(""),_T("0187D263643F75F6F2CEC032888A2A45"),_T("019DD36729BF82BD2C25365F97212ABB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("E-1"),_T(""),_T("011441CDDA3078A5D1C163B3B0FFE1C5"),_T("01282C395BF9B7D99C09B71B657DA58C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("E-1"),_T(""),_T("01D3C9C5AEB96A3600596D1BA8DCC518"),_T("01EFDDEBC09FEA0E4DEB1D6C1FFD424F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("E-1"),_T(""),_T("01039FEC4F02406097182040B3440305"),_T("01C964F0D2B4E38AF575BA1091609062"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("E-1"),_T(""),_T("014C4539278C70EB2F211DC2F3761A69"),_T("01E71E41ABAAD4BA2E4ABF26D2C1B49F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("E-1"),_T(""),_T("0113CB6928D4C44D92A529E750A1FAFD"),_T("011E8E0FD2B78118E39762BC0450B648"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("E-1"),_T(""),_T("012C6E06AB117D45972ED8E94A710463"),_T("01AFE9065B19F00A9A8B58AFEAC4B1C5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("E-1"),_T(""),_T("013BC890BA91666EE60A15E994089ADA"),_T("0187516AAE96E1CD50E9790E171BDD62"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("E-1"),_T(""),_T("0113C1943346397ACF92F02CD561001E"),_T("015782DCFB7A5EA4709477A956907A78"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("u30D,S410D,u410D"),_T(""),_T("014C1A2E427DED32AEA6FC03D0CA9B9C"),_T("01F48E8F658B3553CB6924724D135FE5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("u30D,S410D,u410D"),_T(""),_T("015B3D5A0AE6A4FF8E8DA3F6968F2C7B"),_T("01ADD0B7D7B22B46B4143A083E870995"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("u30D,S410D,u410D"),_T(""),_T("011B3C84FF1F9B0A5C68B6781CB9BC0A"),_T("01500507100E23146C1873FF72BAEEE0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("u30D,S410D,u410D"),_T(""),_T("0118DA9BA52EBDA65A929FBC36A5F758"),_T("01B2F246631E655B3A537725164E404B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS CORPORATION"),_T("u30D,S410D,u410D"),_T(""),_T("011E80B74A9DC355244D05164A4E66DF"),_T("0189751B3EF2F5EE04B8401B1E7D9CAA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("C70Z,C7000Z"),_T(""),_T("0124AC8790656DF23F8070E2A880B501"),_T("016CC716D191DBD0BB21F1090184405D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("C70Z,C7000Z"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("013CCB589498C2FA69ACF4F31643BCDF"),_T("016EA42E1A814C8939C7329EE6CD1252"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("013EB82FF071762D5AD4098D6AAF6D46"),_T("01AC121D8B78786E79DB87C9244D6F9A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("0112276B312502E900C3ED93B9354F72"),_T("0172D8A74BE9D7F5922EE1FB37F03545"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("015B3D5A0AE6A4FF8E8DA3F6968F2C7B"),_T("01ADD0B7D7B22B46B4143A083E870995"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("011B3C84FF1F9B0A5C68B6781CB9BC0A"),_T("01500507100E23146C1873FF72BAEEE0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("014E2DD4DD4202955FAC8AC87B8BFE84"),_T("0170631E9C7CC7A0A4FF1BDCF40CE12F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("0118DA9BA52EBDA65A929FBC36A5F758"),_T("01B2F246631E655B3A537725164E404B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("011E80B74A9DC355244D05164A4E66DF"),_T("0189751B3EF2F5EE04B8401B1E7D9CAA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("01285979F5130214FEF7EA318B17BE50"),_T("01828B0DFD8C4EB651271D2476EA41E1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("013DED50ECAF324351680E680845F9E6"),_T("018E7EFB95EB0916122B1D3FF6C89439"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("0134A7CE8E7585FE1F943D0026551384"),_T("01C3C7E7FDAAC42F2237CCEE8D1B92C4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-300"),_T(""),_T("01BEBBD5B162549AF3F1A738360943F6"),_T("01C4D090385B1E48E69F9367A8DCCBFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("018A97EF0C8856D9155F90A770C73067"),_T("01F68622EE6EF782C32ACC2CCF6A9907"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("012F3FD7C72F5D59DD9BA311EC3435A8"),_T("017969AD15F95DA89D67B4C0D349E522"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("0137BCC4D1028471DB9567121B8F5ACD"),_T("014181969D6481A1AFA279ACD0D4A59A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("013CCB589498C2FA69ACF4F31643BCDF"),_T("016EA42E1A814C8939C7329EE6CD1252"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("013EB82FF071762D5AD4098D6AAF6D46"),_T("01AC121D8B78786E79DB87C9244D6F9A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("014C1A2E427DED32AEA6FC03D0CA9B9C"),_T("01F48E8F658B3553CB6924724D135FE5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("015B3D5A0AE6A4FF8E8DA3F6968F2C7B"),_T("01ADD0B7D7B22B46B4143A083E870995"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("011B3C84FF1F9B0A5C68B6781CB9BC0A"),_T("01500507100E23146C1873FF72BAEEE0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("0183D94237D2A1462CF8884A2C58566B"),_T("01D2027538B7350A8CE3D2F9769B1071"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("0125417F733714AD6039B7B11F310C6B"),_T("016B64AD420E45930EB2675A84E11185"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("01285979F5130214FEF7EA318B17BE50"),_T("01828B0DFD8C4EB651271D2476EA41E1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("0108E559ED0A4C154B52686E91A352F1"),_T("014BD89E61593032748E58BD71B5571C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("0134FDC769F9513D03884B184C3B8474"),_T("01913604EDD203CB3CB8EF8D9405CC78"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("015867A80D31E8FBB5FA03FA5F803379"),_T("01CA611F74EAD0841DB3817C6FD50452"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("01C5E85A4DBCD5E098F88522E4ACDEB3"),_T("01FF0DBEC5FE494C16A5BFBB0692551C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-330"),_T(""),_T("018C33F34E14965F901D87E2F5059D76"),_T("01A2863D209D69C318C2D791ED4A198B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("012F3FD7C72F5D59DD9BA311EC3435A8"),_T("017969AD15F95DA89D67B4C0D349E522"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("013CCB589498C2FA69ACF4F31643BCDF"),_T("016EA42E1A814C8939C7329EE6CD1252"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("01357CD849370F4A172BD943451FE6B4"),_T("01E09C16F2846C46555213A7AB078A89"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("0101668016F68201E1DE902B7B3BD405"),_T("017C85A24795A05A2D425BE9067F3A00"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("0101668016F68201E1DE902B7B3BD405"),_T("017C85A24795A05A2D425BE9067F3A00"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("017C1051F7D1293ED3C00F4184A341C2"),_T("01CA25316D7681E90F1842212F04B5D7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("012A1EE3560CFC313F7C5D69E076BF72"),_T("013F7C8964CD3311BDA99091421C2891"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("01D77879D457F2AC7CE9764A5EABF214"),_T("01FFE2AA1D8016FBFC7567FAD3422E88"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("01206338DD44330548732C39C9898CB9"),_T("017ED526927F046AB92EEBAC17992610"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("01BEBBD5B162549AF3F1A738360943F6"),_T("01C4D090385B1E48E69F9367A8DCCBFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("01BEBBD5B162549AF3F1A738360943F6"),_T("01C4D090385B1E48E69F9367A8DCCBFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("01770BAFC79685F009A0606BD51581B1"),_T("01A02E2722752A1B6A5D21B38C8BE458"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("010D83AB9B456604FD5FC580CE3C2AD6"),_T("0188C66E91A12D1245AAD86FB4CA0591"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("01C5E85A4DBCD5E098F88522E4ACDEB3"),_T("01FF0DBEC5FE494C16A5BFBB0692551C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("01090555AE667AAFCC8690487D7ECFE7"),_T("0162B11FBE64420AD051A9204EC87256"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("013EEEE54844728CBFE64276B0896C4D"),_T("0163ADA62CF0747605CA7A66D8CE3BFF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("015B622B91A46CAED9398308D57CE89D"),_T("0160F37925702D99E90C7D82F42F2A22"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("016282E23CADE6A86B7D47670FF06CB6"),_T("016476CE7011709FF925C9C788A84894"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-400"),_T(""),_T("010F11D5FAE835C77D3DD8BB379FA484"),_T("01397D113392AA4E41EC9521C95A62B6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("013EB82FF071762D5AD4098D6AAF6D46"),_T("01AC121D8B78786E79DB87C9244D6F9A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("011706BAD6FC19A0F82C2DB0A76B9159"),_T("0166661BCE268A3178BFA5236FEF46F4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("011706BAD6FC19A0F82C2DB0A76B9159"),_T("0166661BCE268A3178BFA5236FEF46F4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("010590710A3F937EB8251BCE9037F8AB"),_T("012C9982B9ACBEA744752FD914C747E9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("013DED50ECAF324351680E680845F9E6"),_T("018E7EFB95EB0916122B1D3FF6C89439"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("017975CE66AC80239C28B5632F819EBA"),_T("01F1467C227A678A990547B58196DF5A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("0101668016F68201E1DE902B7B3BD405"),_T("017C85A24795A05A2D425BE9067F3A00"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("0143053BDE5FE1EF59EACEEDC1024A96"),_T("01DDE10D1E165421147E3B9137B15516"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("017C1051F7D1293ED3C00F4184A341C2"),_T("01CA25316D7681E90F1842212F04B5D7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("01B4A7A245551276F6519788823E2D60"),_T("01C5790C084B60EA44FCB4AC30219DE2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("012A1EE3560CFC313F7C5D69E076BF72"),_T("013F7C8964CD3311BDA99091421C2891"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("01BEBBD5B162549AF3F1A738360943F6"),_T("01C4D090385B1E48E69F9367A8DCCBFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("0119884C6EF97B8C8F7C2D47001CB7B1"),_T("01BE372491F24996F0B2105E372D0E2A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("016A22859FB33004511CB5B91680D0DE"),_T("019E3A4A333DBA72C95F0949E49AD767"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("010B19115B7E61CE2DB4BDA480120DEA"),_T("01BF61EACB8030C7AACFDB5A3A2CA383"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-410"),_T(""),_T("010D0A1D6CEE42FC5EA16089A0E5146F"),_T("011CE222910EB9DE43A04A865A42EB52"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-500"),_T(""),_T("0118DA9BA52EBDA65A929FBC36A5F758"),_T("01B2F246631E655B3A537725164E404B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("E-510"),_T(""),_T("01D77879D457F2AC7CE9764A5EABF214"),_T("01FFE2AA1D8016FBFC7567FAD3422E88"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("FE240/X795"),_T(""),_T("0124AC8790656DF23F8070E2A880B501"),_T("016CC716D191DBD0BB21F1090184405D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("0124AC8790656DF23F8070E2A880B501"),_T("016CC716D191DBD0BB21F1090184405D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("011B20DC56FAA4C14E9139389EC259DE"),_T("016C1F26F78CB9D45A1D5F244123CAA1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("01372CAD9800E68C2F9E94BC751B63C5"),_T("01B6EA567DCF6C0BED12D64BC86AA700"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("012402B6D67E6105719FB11153F3C804"),_T("017E816CD8B40EB76B66F94A63ED38FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("0178BAF59FA3A93E45912D1A3AB3DFA4"),_T("0183C6D8ADA5B5856CB6C4CEAFA87628"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("010176D29AD13D3FFAC14F0D3932B95E"),_T("01A05E3557B786BCF9267EAB607AEE7C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP310"),_T(""),_T("0100E9AA36415D0482E7AD68EAF372C3"),_T("012840F1B30DA4789A3345257EEB59C9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP320"),_T(""),_T("010176D29AD13D3FFAC14F0D3932B95E"),_T("01A05E3557B786BCF9267EAB607AEE7C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP500UZ"),_T(""),_T("0124AC8790656DF23F8070E2A880B501"),_T("016CC716D191DBD0BB21F1090184405D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP500UZ"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP500UZ"),_T(""),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP500UZ"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP500UZ"),_T(""),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP550UZ"),_T(""),_T("0124AC8790656DF23F8070E2A880B501"),_T("016CC716D191DBD0BB21F1090184405D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP550UZ"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP550UZ"),_T(""),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP550UZ"),_T(""),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP550UZ"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP550UZ"),_T(""),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("SP550UZ"),_T(""),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("012F3FD7C72F5D59DD9BA311EC3435A8"),_T("017969AD15F95DA89D67B4C0D349E522"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("0137BCC4D1028471DB9567121B8F5ACD"),_T("014181969D6481A1AFA279ACD0D4A59A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("013EB82FF071762D5AD4098D6AAF6D46"),_T("01AC121D8B78786E79DB87C9244D6F9A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("0112276B312502E900C3ED93B9354F72"),_T("0172D8A74BE9D7F5922EE1FB37F03545"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("015B3D5A0AE6A4FF8E8DA3F6968F2C7B"),_T("01ADD0B7D7B22B46B4143A083E870995"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("011B3C84FF1F9B0A5C68B6781CB9BC0A"),_T("01500507100E23146C1873FF72BAEEE0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("014E2DD4DD4202955FAC8AC87B8BFE84"),_T("0170631E9C7CC7A0A4FF1BDCF40CE12F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("0107FCA83F17FA8F5DE5DE87C97ACB66"),_T("01161EE3B094F778304EE8AEB19C0F7B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("018E60C998DDC4CFE972FB9D6819E93E"),_T("018EBE4A99EFD4F4C02B09C7AA308353"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("01C274A79362E9D34711FC55D55E432A"),_T("01C2DDB7BB8068B253FE087C9B6DA9F1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("013E5D266F98E0E4BA51DEEB63949B4C"),_T("01935D9820EE9DF4858BDDEC7A36F27A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("01592ABB5E932D863CF0B8D4344F4A8D"),_T("01CFAE5113F841AE9D212DBED3A37CE2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("017C1051F7D1293ED3C00F4184A341C2"),_T("01CA25316D7681E90F1842212F04B5D7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("0101092454C6BA70F329E8323BA37A62"),_T("01D3F187A0B029D75287067CC329CBEB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("0171FDB6AA66F1C1C71E52F49A6501AA"),_T("019B93D2807091FEA62161B7F3B2E1D0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("01BEBBD5B162549AF3F1A738360943F6"),_T("01C4D090385B1E48E69F9367A8DCCBFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("0185B6CAB5D7A16084F11BAA56C09541"),_T("01FF11A44402FB7E615760C82130FE07"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("01770BAFC79685F009A0606BD51581B1"),_T("01A02E2722752A1B6A5D21B38C8BE458"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("0124A376C93414B16308422029BE7EB2"),_T("016711181F86C56184198107A8B1B2CD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("01379C8FD2662AEAAD76CB1511BB084E"),_T("019EEAD0E94E444AE0CFCFD8FF684314"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("01784AF43BDB59E131697740D9F749C9"),_T("01C5A7E5F1316C4FC792054221B3AC36"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("0111F4F3A18657DCC662CD8EB1FE4027"),_T("013D6612D6D58DA0317FE1F808207124"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("018C33F34E14965F901D87E2F5059D76"),_T("01A2863D209D69C318C2D791ED4A198B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniD,Stylus V"),_T(""),_T("015B7616FEF5459D7774B52FF73427C9"),_T("016EC1CD6EC54DC6BA7A7F51B9DCDFEC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u-miniS,StylusVS"),_T("shq"),_T("013EB82FF071762D5AD4098D6AAF6D46"),_T("01AC121D8B78786E79DB87C9244D6F9A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("u1000/S1000"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("013EB82FF071762D5AD4098D6AAF6D46"),_T("01AC121D8B78786E79DB87C9244D6F9A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("0118DA9BA52EBDA65A929FBC36A5F758"),_T("01B2F246631E655B3A537725164E404B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("011E80B74A9DC355244D05164A4E66DF"),_T("0189751B3EF2F5EE04B8401B1E7D9CAA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("0145CCFB3CFD657AA47D68857C73808B"),_T("0187CDB41EB378C587B76E9CD566D8C0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("0140475FCF05578FC1534AE1012A3E6C"),_T("0146DF88F666D7A82A0C6993869E5D19"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("0108E559ED0A4C154B52686E91A352F1"),_T("014BD89E61593032748E58BD71B5571C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("01357CD849370F4A172BD943451FE6B4"),_T("01E09C16F2846C46555213A7AB078A89"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("01B4A7A245551276F6519788823E2D60"),_T("01C5790C084B60EA44FCB4AC30219DE2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("012A1EE3560CFC313F7C5D69E076BF72"),_T("013F7C8964CD3311BDA99091421C2891"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("01206338DD44330548732C39C9898CB9"),_T("017ED526927F046AB92EEBAC17992610"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("01078E5F33C358C11D6FC20E07947670"),_T("01EF9D257F85D6DF20DCEEB140CEED51"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("0171FDB6AA66F1C1C71E52F49A6501AA"),_T("019B93D2807091FEA62161B7F3B2E1D0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("01BEBBD5B162549AF3F1A738360943F6"),_T("01C4D090385B1E48E69F9367A8DCCBFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("0116B512F11CB253BE375B6F9D1A4DF1"),_T("01BEC1DC1E365603C9A1F34A5203AB1A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("0106565AA8AF8C8B175E2099D8554A55"),_T("01E0BA388CD18FF5EE51C8A0B4B9BC8B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("0148E4615DD64A838FAFB981A86B933F"),_T("01B8633F273963FCAA0BB07A1E3D0806"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("01770BAFC79685F009A0606BD51581B1"),_T("01A02E2722752A1B6A5D21B38C8BE458"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("013B9A18346B48620A5B169E05D2145A"),_T("01E39C266F548F608B50BE9F45058DEC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("010D7E6A57E24111A336CFCFAE264013"),_T("018DCEB3BF68D1005ED718D23FCADF0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("0150771598CCA9FA1386C8CF7CAAE2C8"),_T("01EDAFDF283C0E3E5329BECC28481DEA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("01934C08AE04B95306C45924D92EDB7A"),_T("01F06F8AC2AF95397733F5D7FC833D60"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("01784AF43BDB59E131697740D9F749C9"),_T("01C5A7E5F1316C4FC792054221B3AC36"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("012F5BEAA2D4FFCFF102170F7B20EB0C"),_T("01FFD76F9A7419BFA21F6F377E1B9AF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("013AFFABCB152E7A0BD9109F12B9615E"),_T("015D476129065AC43A136F8E534FC24A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS IMAGING CORP."),_T("uD800,S800"),_T(""),_T("017CC9274A8BBAFF7C6C947CA346C10D"),_T("01FEA10B14C47C75407F3A4D09A7D902"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("010F50672F14B4A88409AEC86E9DECE9"),_T("01C3B4FE62DF9A99F1CA8A5C17AC7711"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("0134F2041810CE97DAAB408D5E71163C"),_T("01D831EF97768EF36E607FD5D85426FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("01BD24596581D7A1535AFC805B0D60A2"),_T("01D47AD28A985151B705F90864369E2C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("0123BAAA6DABBA3007987C5DD352F23A"),_T("0162F90EF60A9DB921AA87532AE23D68"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("01387A14AF75DC6963F040C1239B7DED"),_T("0196457BE1E9E30F00715A3DDE8B160C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("012402B6D67E6105719FB11153F3C804"),_T("017E816CD8B40EB76B66F94A63ED38FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("01AC139E31B941CA0F2C5B5A0BFCDFC0"),_T("01F3D5B0FBE08EC4AAE9E1E4238BF215"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("0155D875C95B74D0F3C5835A62516F48"),_T("01D38A25358EB7649A254E19F1D46600"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("012876087A56CFCA7CFEC7D254AD88D7"),_T("01C6BBED27FF2B3D0E26E4009B66E38B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("018F43694F4E9A49C24613CE0DB777A1"),_T("01BFD6DFF74A169EDA4F585691B1C832"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("01625155BE84D00125E6E169DF4A2F65"),_T("01C54F8112BAF719522090C85C5E23F1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("010300D2A3C0CEB8216F7C59B96AFB16"),_T("014F706DC17A4AF11117D50B414F348C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("0175BAF3251040E0EFB2930B73328E7F"),_T("01DC499064BA9264D591FDE9071DFD89"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("010176D29AD13D3FFAC14F0D3932B95E"),_T("01A05E3557B786BCF9267EAB607AEE7C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C2000Z"),_T(""),_T("01851AAA60C021C5E9C1235B2509BD09"),_T("01D126D2AA41BC051273FED404386FCF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("0124AC8790656DF23F8070E2A880B501"),_T("016CC716D191DBD0BB21F1090184405D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("018AD79CC6A9406F7CEA6B76F46AED2D"),_T("018B0C44364D83741C0A27927E2FAC1F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("010F50672F14B4A88409AEC86E9DECE9"),_T("01C3B4FE62DF9A99F1CA8A5C17AC7711"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("01387A14AF75DC6963F040C1239B7DED"),_T("0196457BE1E9E30F00715A3DDE8B160C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("01AC139E31B941CA0F2C5B5A0BFCDFC0"),_T("01F3D5B0FBE08EC4AAE9E1E4238BF215"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("0155D875C95B74D0F3C5835A62516F48"),_T("01D38A25358EB7649A254E19F1D46600"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("010300D2A3C0CEB8216F7C59B96AFB16"),_T("014F706DC17A4AF11117D50B414F348C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("01625155BE84D00125E6E169DF4A2F65"),_T("01C54F8112BAF719522090C85C5E23F1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C3040Z"),_T(""),_T("0138A8D4ECE59F41D2EB9AF5168B6675"),_T("01CA9A809F737BA668C16DDE52E74092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C40Z,D40Z"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C40Z,D40Z"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C40Z,D40Z"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C40Z,D40Z"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C40Z,D40Z"),_T(""),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C40Z,D40Z"),_T(""),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C40Z,D40Z"),_T(""),_T("01387A14AF75DC6963F040C1239B7DED"),_T("0196457BE1E9E30F00715A3DDE8B160C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C40Z,D40Z"),_T(""),_T("0123BAAA6DABBA3007987C5DD352F23A"),_T("0162F90EF60A9DB921AA87532AE23D68"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C40Z,D40Z"),_T(""),_T("010300D2A3C0CEB8216F7C59B96AFB16"),_T("014F706DC17A4AF11117D50B414F348C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C40Z,D40Z"),_T(""),_T("0175BAF3251040E0EFB2930B73328E7F"),_T("01DC499064BA9264D591FDE9071DFD89"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("0165B3F1B409A4D8D5F2ADFFA970D3A5"),_T("0165B3F1B409A4D8D5F2ADFFA970D3A5"),_T("1x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("010F50672F14B4A88409AEC86E9DECE9"),_T("01C3B4FE62DF9A99F1CA8A5C17AC7711"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("01AC139E31B941CA0F2C5B5A0BFCDFC0"),_T("01F3D5B0FBE08EC4AAE9E1E4238BF215"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("012876087A56CFCA7CFEC7D254AD88D7"),_T("01C6BBED27FF2B3D0E26E4009B66E38B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("0178BAF59FA3A93E45912D1A3AB3DFA4"),_T("0183C6D8ADA5B5856CB6C4CEAFA87628"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("018F43694F4E9A49C24613CE0DB777A1"),_T("01BFD6DFF74A169EDA4F585691B1C832"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("0175BAF3251040E0EFB2930B73328E7F"),_T("01DC499064BA9264D591FDE9071DFD89"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("0138A8D4ECE59F41D2EB9AF5168B6675"),_T("01CA9A809F737BA668C16DDE52E74092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("0120996088E68CF9F70A20A414D14AE6"),_T("013E3A5D329BBCB6AAF62F2E18FF8127"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("01786593B7990A17B0D81B6DF749470E"),_T("01DF37EBC825495EA04E9B311B77D309"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("01403088D08B8A2712CA648846151E07"),_T("01BABD681F45ABBA1BDCF41992781236"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("017659A2F9A530359CB8725D32B5BE6C"),_T("01F863D3F47BE8F243BFF177EAC1EDB4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C700UZ"),_T(""),_T("016A9F39EDF7E9DCAF8BE822C2266077"),_T("01F0A31D3842CFD4B7E09178F141E14B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("C740UZ"),_T(""),_T("01851AAA60C021C5E9C1235B2509BD09"),_T("01D126D2AA41BC051273FED404386FCF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("0128413C51CDA1AB1E7E157A61FD358B"),_T("01689B8D30387E1072A93C36BFF81DEC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("0117BDDBF4C4D5F2BD473867C268B992"),_T("01D67415634AF487A644D544967B5229"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("01D72E86D9A71586407B16573061BE82"),_T("01FEE178671C154C42FD7275DA10C8B2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("01CC5054634686211425F9313789330E"),_T("01D7C1596EF390EC64D371F4BBEED4CA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("0190F389112850389D210F01DAC49ECC"),_T("01973B91796499966833E12D9F47D6F8"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("011950D41F42D21E97D50473114BE0D7"),_T("01B93C2C9074C39E346E44112D11515B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("01ABAB9098FBA1D73C384C3A89D54D36"),_T("01D88924E59DBFEDA69DB6878301F4AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("015D76974F1AAEE7318546F8817042CF"),_T("0192A37A39ECDB4EE3204E56E17613AF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("01ED3E764331690417CFB0B6760E3CF9"),_T("01FECF64497ADED556DB6690691B2F04"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("01379268F9FBE19C81CC00CD70598366"),_T("01F07D7BAE71080B3DD911AD4E97F511"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("0182FC9E34E7EF518A5E521A73CB9150"),_T("01963E3DBE697A70C122A3973E90CB59"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("01B0F9A7C7E350A1B701261420EC769E"),_T("01CDE58F50CD625612AE7FD49FB98473"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("0181E0FA93A7C8FFBFAED0AB0A682EDF"),_T("01F73ED16F0BD0F7C73BD44D4839ED4D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("015B0307770D08EE38047293E49F7B95"),_T("018B755668E420798B44C06DEEF7A0B3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("016EA0E7A46C136F2ABA8A0E865CBC21"),_T("01A15B41B7F74EB6449B8F8319248967"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("017DF1BD8B33D55134DD3E46656ED053"),_T("01A093ACDCA80186F422983344D97150"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("0139D8C8782FE5A30C4C88D9FCAE8181"),_T("01CC38B6FCB0DEA0A013C4D914641E40"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("0164182DB61A14805CAA4F70E0415E53"),_T("0173FB6497370EE93BAE2DCDEE79E8AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("017858AF71B9A633FD70AEAB659B3300"),_T("01DACE21BB46E12DD3BC4727CD8D8210"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("01069AD821B0103E56E421C38B5B2CD6"),_T("011497B7CD73D9D25DC361F5A34BDEB9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("01794DB02469022B32443CA60688C148"),_T("01F86D4ECED7E890C68BE9D10E56274F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("017C0F23D27AAEAD889A664DC26AD545"),_T("01E97DB27309D1AB029F5BFF06FB3B75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("016398A5D03E9FA5A5974B9EABF113B7"),_T("01ADC2FDBC49253897195A5B8165F49C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("019444DDF02185A1932271ABB5EA43C2"),_T("01F912E034059159BF429BDBA8B7F988"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-10"),_T(""),_T("01C61A250680030358EF5227D70D1087"),_T("01E9E47BD2E94A56F17ADC1CD1D859D8"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("0108C44AD56089B4CD27462EF0E9E40B"),_T("01AD4F667053A6FBA82E3D2B0BC4A566"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("0128413C51CDA1AB1E7E157A61FD358B"),_T("01689B8D30387E1072A93C36BFF81DEC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("0117BDDBF4C4D5F2BD473867C268B992"),_T("01D67415634AF487A644D544967B5229"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("01CC5054634686211425F9313789330E"),_T("01D7C1596EF390EC64D371F4BBEED4CA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("0190F389112850389D210F01DAC49ECC"),_T("01973B91796499966833E12D9F47D6F8"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("011950D41F42D21E97D50473114BE0D7"),_T("01B93C2C9074C39E346E44112D11515B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("015D76974F1AAEE7318546F8817042CF"),_T("0192A37A39ECDB4EE3204E56E17613AF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("01ED3E764331690417CFB0B6760E3CF9"),_T("01FECF64497ADED556DB6690691B2F04"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("01379268F9FBE19C81CC00CD70598366"),_T("01F07D7BAE71080B3DD911AD4E97F511"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("0182FC9E34E7EF518A5E521A73CB9150"),_T("01963E3DBE697A70C122A3973E90CB59"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("0145C214D721F708E0D4B76BCF1D4AAD"),_T("01EDD76E1D040E754652CDF54F4C9BA1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("01590C75F0867760D72D155295E96425"),_T("01E27BBE5161A0E68048D0A194534D74"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("016EE1A32255BAAB84FC58ED3890502C"),_T("01A5D351507261639CE450B127B1475A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("E-20,E-20N,E-20P"),_T(""),_T("01A83536481A79EC40C50C791F1E4220"),_T("01FABFD178D6926A37E77FEA3B1A0C37"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("014A1C89C73A29E281A843479E0D8270"),_T("01FF143D8822FDACA79A68AA47A453B1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("0113C1943346397ACF92F02CD561001E"),_T("015782DCFB7A5EA4709477A956907A78"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("01065AFF4925691D6682020FE0351289"),_T("012B7A93E0F5D34E6922626FE3FDD0B5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("013C7B66311D04188EBDC1B1F80C5CD1"),_T("01607C40C6F84F1EC927665858404823"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("01992C72E3F2F6CE2A20CD738B766D9A"),_T("019DB237D8FE714224C756060548A8F9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("012221FB6D96695F14C7B12D99EA4E73"),_T("01D1729230BA2DF3602BE06F32BA0D5A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("0153A4E107A161D4EE844C4AC1E91AC0"),_T("01C2B103DC657341EB06FDADCFCFC1FC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("01732E8C7483DF76164E47EA5F45C18C"),_T("01EB3595DF117750F757BF015FBCC9D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("015EA26684DB82F5A340C79D9B28B646"),_T("01EE83B10EFF28C203E3B706416A5799"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("018C1CCB93439920B33C7AD4CA75C7BE"),_T("018D1DB0D777A5B623FA247CC2E649F2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("010A73C6212633C5BC7D1A24AD3F64C6"),_T("011227482A91BAC69AE87BA6F0494F96"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("OLYMPUS OPTICAL CO.,LTD"),_T("X-2,C-50Z"),_T(""),_T("01336A7453832F56E158AFBA35CCCE6A"),_T("0194012593362B6F226D47AEC452FA45"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("0107DF00A3B3CC0618E1780640E7C637"),_T("01F909EF7883AFD92617F844C239E03F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("013C5D9A83F33B70EDD0EF4B175E4734"),_T("017B0CF969CF5E15D58B94F64DB0EDC1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("0138462F3B064F5A2D2735BCBD535472"),_T("01390D38EF6A011B05DD7B36A364A3BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("013DC48B707181D2512BD55D72EEBCF0"),_T("01DEFE52F8A7964EC92CAA476C1081C5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("018E071D7C6333CCA941AF3F86C4B040"),_T("01F1BC59628C27605A47B1DD4DAFBD2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("01C91F94EE93568591EB96DA028179AF"),_T("01E1BD28E783DDA36EE9EF9124CB40AE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("0122D115001A0F43E9F12CAF15140921"),_T("019590EE31CB1F94A5E95BB6D8A4D15B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("01CFFACD05293AA908AF4316230788E9"),_T("01DD5B33181B223F8AB26AEBDC6E8E84"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("01198346965EB20066F6D7B6831E9C95"),_T("013E95521791B5B70228DE9E899234B3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("013161476484359DD4D9CF9409A8D7CD"),_T("014BF262F2540BDB3D5AF1ADF46B1BDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("014D667B6CED05284B47E4C66FF4C609"),_T("015FC89EA6DB6E3DD7F8D77D7FA4480F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("0104627D31E6BCB51040B2A47F908518"),_T("01C451DC68A972D099D1DAD1E315CF22"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX01"),_T(""),_T("0177E3A26E664A95E6BAE877F3FA8E8B"),_T("01D3F65CE838517AA4ED750EDB8521D1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX7"),_T(""),_T("0123BC6810721B28DDD0F4F3DCAA6277"),_T("019D8B7008873790DEF7D64A73B50A81"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX7"),_T(""),_T("0192E3B46CA4AA3BB9DEF414E8A36D12"),_T("01AD7C7F5EA54145C6376424C02FDCC1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX7"),_T(""),_T("011FA861380627C4E0D18BB1BE206178"),_T("0146D98747195222CB35EE2DA5F9BC3E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX7"),_T(""),_T("010F3953A08A959619F07E0BB01C8BF5"),_T("018C5063107B6A1357AC6031F8B67D42"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX7"),_T(""),_T("0116E95EEDDF8CF3518E815BA203C615"),_T("017C4ABD754ABA2830C2F2ED1FE33B8C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX7"),_T(""),_T("01693AAEEDEEA2DAF003F0981E32DB6D"),_T("01F2AD7A47E5E5458D3391E48F0862BC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX7"),_T(""),_T("011F65BAC64F587C94E637D842323019"),_T("01310F546088EDA9A94120D7EC70423B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX7"),_T(""),_T("018141C2FC543690C76BA6C90CD1E379"),_T("01A5531E48945A567D9DDED506CAD64D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("013DC48B707181D2512BD55D72EEBCF0"),_T("01DEFE52F8A7964EC92CAA476C1081C5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("018E071D7C6333CCA941AF3F86C4B040"),_T("01F1BC59628C27605A47B1DD4DAFBD2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("0186B5A9C29AD0C22B08617BAAF8B2F3"),_T("01AADE46228BCCA9AAC3BE09EF986623"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("0122D115001A0F43E9F12CAF15140921"),_T("019590EE31CB1F94A5E95BB6D8A4D15B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("01CFFACD05293AA908AF4316230788E9"),_T("01DD5B33181B223F8AB26AEBDC6E8E84"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("014145865FE9A3D75612AD65CD0BF9C3"),_T("01680307DDD5C5366799674555B5BD2D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("013EF0E302E6BBE0C2AA0D9D85AF7990"),_T("014B2BC31CF89A8DC2B2C962A8CF82A6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("01198346965EB20066F6D7B6831E9C95"),_T("013E95521791B5B70228DE9E899234B3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("013161476484359DD4D9CF9409A8D7CD"),_T("014BF262F2540BDB3D5AF1ADF46B1BDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("014D667B6CED05284B47E4C66FF4C609"),_T("015FC89EA6DB6E3DD7F8D77D7FA4480F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("011D37296ED90033C19351777AAB0B38"),_T("01B2922FE979931BFD2586AB0267B31B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("011377E8CCEBED5DFA86FC8ACF2295C2"),_T("01ADCA18F8F8F4DF33ACD56F393A645A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FX9"),_T(""),_T("01E4CF70D3F4FC5894F625131F820CF3"),_T("01F9F607F691635857AE5C87E726A252"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("0123BC6810721B28DDD0F4F3DCAA6277"),_T("019D8B7008873790DEF7D64A73B50A81"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("0192E3B46CA4AA3BB9DEF414E8A36D12"),_T("01AD7C7F5EA54145C6376424C02FDCC1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("011FA861380627C4E0D18BB1BE206178"),_T("0146D98747195222CB35EE2DA5F9BC3E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("011030DDD6A189F70FE3BA4CEDA10C0E"),_T("018FEC9B7763A5FBF41B927640234A6F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("01A78DD347695335597BFB27B18CEEE2"),_T("01F449D1310A4BCC04588AA07DC6F457"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("010F3953A08A959619F07E0BB01C8BF5"),_T("018C5063107B6A1357AC6031F8B67D42"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("012E2FD711E336593E1E6661771EFF20"),_T("01BE5250860C140A34674091C55CCD0E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("0116E95EEDDF8CF3518E815BA203C615"),_T("017C4ABD754ABA2830C2F2ED1FE33B8C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("011F65BAC64F587C94E637D842323019"),_T("01310F546088EDA9A94120D7EC70423B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("0123684778F7F6D955AC459FBD1120CA"),_T("01BFD2C50315AD2DAE445AC96459B822"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("017E4C77A22222A6F09A53D932091662"),_T("01B7487CFD91880BA0489F67866571DF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("0114007765A43A934A4DDC8A61E1562A"),_T("014BE2D26B383E99C16FF976EA5DFFB0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("0139D09DC9BF32F37522D4ECF507D39D"),_T("01D444AE0369695BF6F8AE7357012B48"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ20"),_T(""),_T("011CACC20EDB7B88165442D9C282E155"),_T("01D53767A9769BEFDD0487B8CED92BD6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("01146210F8F782499562164D98588DF7"),_T("01416268426EA8AA822C30E62CB99184"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("01B02D6252495A2B9D08BBBBFEA0369C"),_T("01C44B75CC82D3AE8CA47C53C0367FA1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("014B3173926CDBA56C1E13038A53D12A"),_T("01CBA0981E28CD632712D268FB362E38"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("01A025B984771F2A9EAE24823D6AB63B"),_T("01DA5E9CB2E45878BD8FC0BE2F4DB4E2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("0153A205814CDE04D1706E59E8013027"),_T("01B0C46A0378B6F005FB98832273680E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("011B7750DE6D43BDE2BC3D14BBAD7414"),_T("013FA3066503A7D23032FC9D0987D322"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("011FA861380627C4E0D18BB1BE206178"),_T("0146D98747195222CB35EE2DA5F9BC3E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("01A78DD347695335597BFB27B18CEEE2"),_T("01F449D1310A4BCC04588AA07DC6F457"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("019653C54EB7D48750695B068423FF76"),_T("01B0180D7EED5FE5736800864F71B097"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("012E2FD711E336593E1E6661771EFF20"),_T("01BE5250860C140A34674091C55CCD0E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("0116E95EEDDF8CF3518E815BA203C615"),_T("017C4ABD754ABA2830C2F2ED1FE33B8C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("012A2AD50650A8B9646E8D9ABD3BFA88"),_T("018F2017595154F0F6593A89BC701E3F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("0123684778F7F6D955AC459FBD1120CA"),_T("01BFD2C50315AD2DAE445AC96459B822"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ3"),_T(""),_T("018141C2FC543690C76BA6C90CD1E379"),_T("01A5531E48945A567D9DDED506CAD64D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ30"),_T(""),_T("01B02D6252495A2B9D08BBBBFEA0369C"),_T("01C44B75CC82D3AE8CA47C53C0367FA1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ30"),_T(""),_T("011B7750DE6D43BDE2BC3D14BBAD7414"),_T("013FA3066503A7D23032FC9D0987D322"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ30"),_T(""),_T("0123BC6810721B28DDD0F4F3DCAA6277"),_T("019D8B7008873790DEF7D64A73B50A81"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ30"),_T(""),_T("011030DDD6A189F70FE3BA4CEDA10C0E"),_T("018FEC9B7763A5FBF41B927640234A6F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ30"),_T(""),_T("014BF769355E127A5014D2B5C2238F0B"),_T("01BCA265FDE2DDF5E1AF22F54434D125"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ30"),_T(""),_T("014BA11590681A399B60019E89D95551"),_T("0196E966C2B3709B7836B021787B3EAA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ30"),_T(""),_T("010F3953A08A959619F07E0BB01C8BF5"),_T("018C5063107B6A1357AC6031F8B67D42"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ30"),_T(""),_T("012E2FD711E336593E1E6661771EFF20"),_T("01BE5250860C140A34674091C55CCD0E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ30"),_T(""),_T("0116E95EEDDF8CF3518E815BA203C615"),_T("017C4ABD754ABA2830C2F2ED1FE33B8C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ30"),_T(""),_T("011F65BAC64F587C94E637D842323019"),_T("01310F546088EDA9A94120D7EC70423B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ5"),_T(""),_T("0123BC6810721B28DDD0F4F3DCAA6277"),_T("019D8B7008873790DEF7D64A73B50A81"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ5"),_T(""),_T("011FA861380627C4E0D18BB1BE206178"),_T("0146D98747195222CB35EE2DA5F9BC3E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ5"),_T(""),_T("01A78DD347695335597BFB27B18CEEE2"),_T("01F449D1310A4BCC04588AA07DC6F457"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ5"),_T(""),_T("019653C54EB7D48750695B068423FF76"),_T("01B0180D7EED5FE5736800864F71B097"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ5"),_T(""),_T("010F3953A08A959619F07E0BB01C8BF5"),_T("018C5063107B6A1357AC6031F8B67D42"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ5"),_T(""),_T("012E2FD711E336593E1E6661771EFF20"),_T("01BE5250860C140A34674091C55CCD0E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ5"),_T(""),_T("01AF869E9C11B22A86704F305C873B54"),_T("01C9C269CF6A8DC6FB6E7690FBD22450"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ5"),_T(""),_T("0139D09DC9BF32F37522D4ECF507D39D"),_T("01D444AE0369695BF6F8AE7357012B48"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ50"),_T("high"),_T("0138462F3B064F5A2D2735BCBD535472"),_T("01390D38EF6A011B05DD7B36A364A3BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ7"),_T(""),_T("01146210F8F782499562164D98588DF7"),_T("01416268426EA8AA822C30E62CB99184"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ7"),_T(""),_T("011B7750DE6D43BDE2BC3D14BBAD7414"),_T("013FA3066503A7D23032FC9D0987D322"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ7"),_T(""),_T("0123BC6810721B28DDD0F4F3DCAA6277"),_T("019D8B7008873790DEF7D64A73B50A81"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ7"),_T(""),_T("0192E3B46CA4AA3BB9DEF414E8A36D12"),_T("01AD7C7F5EA54145C6376424C02FDCC1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ7"),_T(""),_T("01A78DD347695335597BFB27B18CEEE2"),_T("01F449D1310A4BCC04588AA07DC6F457"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ7"),_T(""),_T("014BF769355E127A5014D2B5C2238F0B"),_T("01BCA265FDE2DDF5E1AF22F54434D125"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ7"),_T(""),_T("010F3953A08A959619F07E0BB01C8BF5"),_T("018C5063107B6A1357AC6031F8B67D42"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ7"),_T(""),_T("0116E95EEDDF8CF3518E815BA203C615"),_T("017C4ABD754ABA2830C2F2ED1FE33B8C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ7"),_T(""),_T("012A2AD50650A8B9646E8D9ABD3BFA88"),_T("018F2017595154F0F6593A89BC701E3F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ7"),_T(""),_T("0101829004C47D7E3F6B71F56536BA02"),_T("018AAE1A612B247686EFDA55966E7683"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("01146210F8F782499562164D98588DF7"),_T("01416268426EA8AA822C30E62CB99184"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("0120BC9F7FBDE71C9F7AF75F1271DE8E"),_T("0168E10B1946222765F3952D9095AA5E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("01AE77654BD30AB3892163E998A7CA6F"),_T("01CC4AC83792BB0CEEE11B2F773B71B5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("0191A7EB3030A81F80E2059E5295F271"),_T("01D17DB6368FB3C5EB068CBD52B219AA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("01B02D6252495A2B9D08BBBBFEA0369C"),_T("01C44B75CC82D3AE8CA47C53C0367FA1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("0168D26319E840447DE0FEB6916D097B"),_T("0198F32FC612493C4B8E63A36538B44E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("014B3173926CDBA56C1E13038A53D12A"),_T("01CBA0981E28CD632712D268FB362E38"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("014A1828D4C5D5228632ED107E5E372E"),_T("01F277EEA6356BA671EA2224C96CE68D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("01A025B984771F2A9EAE24823D6AB63B"),_T("01DA5E9CB2E45878BD8FC0BE2F4DB4E2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("0153A205814CDE04D1706E59E8013027"),_T("01B0C46A0378B6F005FB98832273680E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("011B7750DE6D43BDE2BC3D14BBAD7414"),_T("013FA3066503A7D23032FC9D0987D322"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("0123BC6810721B28DDD0F4F3DCAA6277"),_T("019D8B7008873790DEF7D64A73B50A81"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("0192E3B46CA4AA3BB9DEF414E8A36D12"),_T("01AD7C7F5EA54145C6376424C02FDCC1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("01A78DD347695335597BFB27B18CEEE2"),_T("01F449D1310A4BCC04588AA07DC6F457"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("014BF769355E127A5014D2B5C2238F0B"),_T("01BCA265FDE2DDF5E1AF22F54434D125"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("014BA11590681A399B60019E89D95551"),_T("0196E966C2B3709B7836B021787B3EAA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("01D9CAAD4A2D7DC83A6BADAFD0C00425"),_T("01F0CD875838DE7997852185F2378B4F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-FZ8"),_T(""),_T("0101829004C47D7E3F6B71F56536BA02"),_T("018AAE1A612B247686EFDA55966E7683"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-L1"),_T(""),_T("0169FCFCCC4D6CE6959541DC098BE408"),_T("01F9C0838D8AFDB904555F93BFAF238C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("01B02D6252495A2B9D08BBBBFEA0369C"),_T("01C44B75CC82D3AE8CA47C53C0367FA1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("011B7750DE6D43BDE2BC3D14BBAD7414"),_T("013FA3066503A7D23032FC9D0987D322"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("0192E3B46CA4AA3BB9DEF414E8A36D12"),_T("01AD7C7F5EA54145C6376424C02FDCC1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("011FA861380627C4E0D18BB1BE206178"),_T("0146D98747195222CB35EE2DA5F9BC3E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("011030DDD6A189F70FE3BA4CEDA10C0E"),_T("018FEC9B7763A5FBF41B927640234A6F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("014BF769355E127A5014D2B5C2238F0B"),_T("01BCA265FDE2DDF5E1AF22F54434D125"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("010F3953A08A959619F07E0BB01C8BF5"),_T("018C5063107B6A1357AC6031F8B67D42"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("012A2AD50650A8B9646E8D9ABD3BFA88"),_T("018F2017595154F0F6593A89BC701E3F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("018141C2FC543690C76BA6C90CD1E379"),_T("01A5531E48945A567D9DDED506CAD64D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("0114007765A43A934A4DDC8A61E1562A"),_T("014BE2D26B383E99C16FF976EA5DFFB0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("01A03C8460297BF48BC8FEB4FC637382"),_T("01A63CAA9BF37144D54CD5FEAB904CA3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX1"),_T(""),_T("013A0E62CC533A8F06C9241B1663A995"),_T("018C97A3CA4FA22079CC8A732C2EDFCB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("0107DF00A3B3CC0618E1780640E7C637"),_T("01F909EF7883AFD92617F844C239E03F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("013C5D9A83F33B70EDD0EF4B175E4734"),_T("017B0CF969CF5E15D58B94F64DB0EDC1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("0138462F3B064F5A2D2735BCBD535472"),_T("01390D38EF6A011B05DD7B36A364A3BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("013DC48B707181D2512BD55D72EEBCF0"),_T("01DEFE52F8A7964EC92CAA476C1081C5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("018E071D7C6333CCA941AF3F86C4B040"),_T("01F1BC59628C27605A47B1DD4DAFBD2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("0186B5A9C29AD0C22B08617BAAF8B2F3"),_T("01AADE46228BCCA9AAC3BE09EF986623"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("016D44ECEDC69CC32EFDBDB3FA52FF2F"),_T("017FD44400AB16F1FE452C02524238A1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("014145865FE9A3D75612AD65CD0BF9C3"),_T("01680307DDD5C5366799674555B5BD2D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("013161476484359DD4D9CF9409A8D7CD"),_T("014BF262F2540BDB3D5AF1ADF46B1BDB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("014293DC259CA2AD60B54C5E1DBD5BE4"),_T("017F0898D918195BE28D075579313D0D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("01768F9D9AD459A2F0E12FF8FE7E58E7"),_T("01C8DAFC2B195EF06BE17FB14795E4FF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("01958DB41B5F276E1BFD5C17CC07BC50"),_T("01CD2F6EDA89988406EECE9D8C492B93"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("011DD5F353F534B7B9CBEE2412A65D5E"),_T("01E9E0E0460B869897F4107EBEFDC638"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("01E4CF70D3F4FC5894F625131F820CF3"),_T("01F9F607F691635857AE5C87E726A252"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("0134C04B9EA21B43C4EF2F5E9398FAED"),_T("0142C40B3C1A8BE418B8A6BAE99BF4B7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("01BB46E7CAF6065E33DD28A6E7EC9C03"),_T("01D4047F04C7C32C6FDDBBF5D71F4CFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LX2"),_T(""),_T("011C71CDD4C0F8F2CE09A808B280931A"),_T("01629B48C0D9C3358A36F1ADC61E01FA"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LZ2"),_T(""),_T("018132019BC5CC9867CC79E9250560C5"),_T("01CF7D282F68C01148D58EE95918704B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LZ2"),_T(""),_T("01198346965EB20066F6D7B6831E9C95"),_T("013E95521791B5B70228DE9E899234B3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LZ2"),_T(""),_T("014293DC259CA2AD60B54C5E1DBD5BE4"),_T("017F0898D918195BE28D075579313D0D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LZ2"),_T(""),_T("014D667B6CED05284B47E4C66FF4C609"),_T("015FC89EA6DB6E3DD7F8D77D7FA4480F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LZ2"),_T(""),_T("011D37296ED90033C19351777AAB0B38"),_T("01B2922FE979931BFD2586AB0267B31B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LZ2"),_T(""),_T("012D088BCB11234F4DD3B0306BE621EF"),_T("01E45AC07E04EF2C5E8A37C82A60666F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LZ2"),_T(""),_T("01BC09B19EB1EA65D20FEB9309259336"),_T("01E8286E6F2FE6CDD265F8441DC7B59C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LZ2"),_T(""),_T("017AF37B1EB466ADBB6C646D90A56E15"),_T("01E8D1E4A12056DADDE7152A0B9115B3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LZ3"),_T(""),_T("018132019BC5CC9867CC79E9250560C5"),_T("01CF7D282F68C01148D58EE95918704B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-LZ7"),_T("fine"),_T("01146210F8F782499562164D98588DF7"),_T("01416268426EA8AA822C30E62CB99184"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("0182C24E1E5290C73AD84A7813FCC7AE"),_T("01C7160A775B4F76BC0438656E0FF092"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("013C5D9A83F33B70EDD0EF4B175E4734"),_T("017B0CF969CF5E15D58B94F64DB0EDC1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("0138462F3B064F5A2D2735BCBD535472"),_T("01390D38EF6A011B05DD7B36A364A3BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("013DC48B707181D2512BD55D72EEBCF0"),_T("01DEFE52F8A7964EC92CAA476C1081C5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("018E071D7C6333CCA941AF3F86C4B040"),_T("01F1BC59628C27605A47B1DD4DAFBD2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("01C91F94EE93568591EB96DA028179AF"),_T("01E1BD28E783DDA36EE9EF9124CB40AE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("0122D115001A0F43E9F12CAF15140921"),_T("019590EE31CB1F94A5E95BB6D8A4D15B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("01CFFACD05293AA908AF4316230788E9"),_T("01DD5B33181B223F8AB26AEBDC6E8E84"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("013EF0E302E6BBE0C2AA0D9D85AF7990"),_T("014B2BC31CF89A8DC2B2C962A8CF82A6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("018132019BC5CC9867CC79E9250560C5"),_T("01CF7D282F68C01148D58EE95918704B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("01198346965EB20066F6D7B6831E9C95"),_T("013E95521791B5B70228DE9E899234B3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Panasonic"),_T("DMC-TZ1"),_T(""),_T("011377E8CCEBED5DFA86FC8ACF2295C2"),_T("01ADCA18F8F8F4DF33ACD56F393A645A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX *ist D"),_T(""),_T("012ECC6A2CB8921C19D4E9ADDE045BE0"),_T("0198B0E9CEFCFC54ED3BBAA91F3947F9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX *ist DS"),_T(""),_T("012ECC6A2CB8921C19D4E9ADDE045BE0"),_T("0198B0E9CEFCFC54ED3BBAA91F3947F9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX *ist DS"),_T(""),_T("012ECC6A2CB8921C19D4E9ADDE045BE0"),_T("0198B0E9CEFCFC54ED3BBAA91F3947F9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX K100D"),_T(""),_T("012ECC6A2CB8921C19D4E9ADDE045BE0"),_T("0198B0E9CEFCFC54ED3BBAA91F3947F9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX K10D"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX K10D"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("0162BC9F7A5892E2F2DB22C82006610B"),_T("01EA5346C5145C7930905DCF6B31F083"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("0150263B9EFAF0D3F1436478F497AF5A"),_T("018370CF802E9CF8FE79E29232CCD3AC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("010F50672F14B4A88409AEC86E9DECE9"),_T("01C3B4FE62DF9A99F1CA8A5C17AC7711"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("0134F2041810CE97DAAB408D5E71163C"),_T("01D831EF97768EF36E607FD5D85426FB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("01BD24596581D7A1535AFC805B0D60A2"),_T("01D47AD28A985151B705F90864369E2C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("0123BAAA6DABBA3007987C5DD352F23A"),_T("0162F90EF60A9DB921AA87532AE23D68"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("0155D875C95B74D0F3C5835A62516F48"),_T("01D38A25358EB7649A254E19F1D46600"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("012876087A56CFCA7CFEC7D254AD88D7"),_T("01C6BBED27FF2B3D0E26E4009B66E38B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("018F43694F4E9A49C24613CE0DB777A1"),_T("01BFD6DFF74A169EDA4F585691B1C832"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 550"),_T(""),_T("0182230692721ADF5DCBFB56F747490C"),_T("01DD92C0CD7077A88C49139F2F15908D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 750Z"),_T(""),_T("0130E17CF819C676B0C4E1D92B29E3D0"),_T("0148099C19C2AEEB10F7C98672C9FEF5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio 750Z"),_T(""),_T("015B3AC73951F0F8C2B83654AF587152"),_T("01BE05B882F033CCDFE7838FB2FE84F0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio A10"),_T(""),_T("010D5F6137BC7E0D9264FCE27CEE56F2"),_T("010D5F6137BC7E0D9264FCE27CEE56F2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio A20"),_T(""),_T("0196A4A230303DA672148A7723BA0A45"),_T("0196A4A230303DA672148A7723BA0A45"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio A20"),_T(""),_T("0110E4095D5E65A4ED3A79082BD1651D"),_T("0110E4095D5E65A4ED3A79082BD1651D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio A30"),_T(""),_T("0196A4A230303DA672148A7723BA0A45"),_T("0196A4A230303DA672148A7723BA0A45"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio M40"),_T(""),_T("010F0CB84C835BB4FCCCF6EE02335430"),_T("016C2B10163D7D4D412E22C026BBFE2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("01173DFDB15AEF0B8F8F7DBA935075C0"),_T("016B6E94C94F71C50644EB0FB3B797CA"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("011B5DB93D1920C4F22FE30C9D74B019"),_T("01817C5AAF8167836BE4F1FE59FC19CA"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("014021C1D4CC4D086AE9ECB4D74059E1"),_T("01B02C50605DC2BF1D4287C381033DEA"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("01B22FB5EA6896651D50C9AF6449C755"),_T("01B5D1CEC9EA1F3901B90F24ABD896AE"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("01069E2E226122744E5D3FCC5BD907DA"),_T("01135841705661AB895ACB4A742D5334"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("0137D4B64EF02801FFFCBB0CC37E6D14"),_T("018DE75B8C39571DE5D80B55ED6E40DB"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("01536F16BCEC1264BC0511A540801E5B"),_T("01968C8117F844F9A6419C4F192FA3A9"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("018C348769A146C48CDAD42B7E612974"),_T("01B90E7E70A6F27BB4153922849C5700"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("0121CCFD7E28555BAA5181244B39E4D4"),_T("016B0E8A7220EB2CAF7F1319967FC91A"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("012E4AFBCA09CE8FD90460247DF139AF"),_T("01900BBA2DFF8FFEE4C1C9ABDA1C2745"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("012C67677590471A0359CE86EE1D78FA"),_T("01AC53FE16B3241E100A052B316C5739"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("015D00310664D41A4A6D2E0E2F340385"),_T("01ABF0D27535C31F6BE2559024D247CB"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("012345305944D817D0C161C7B54BAF5C"),_T("017DDCB884AFEF1F6DD72AEA5D125933"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("014BA1BDD0180359CC4190D6229FFDDF"),_T("01C6957B3588A513847B8FA541A6F154"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("0110ED34D89C23D3FE25D19D8F11C7B7"),_T("0162043D57592A98CC22BBCC1C7E1EFC"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("0176898E9E79FCA6F38E219E765888DD"),_T("017BB107FA4D61F8B85BCD845DDD93B4"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("013F8DB7C0AE9774B157A59660DCEF10"),_T("01F196CA415D9FF6662FA9A3AF99F1AC"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S"),_T(""),_T("017D4C33EF2B651D308D32F6DF71963D"),_T("01AF9D48ABD1FE131FBB9D5CCB3EC659"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S5i"),_T(""),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S5i"),_T(""),_T("01A0FB219D74904EAF637293A0F31493"),_T("01E3F3BE628274E6C1D4856D8DC20D0E"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S5i"),_T(""),_T("01158B0D515E752B1B0716889F2B3371"),_T("017BBA44ECD57A9B2E59D0D6967F1623"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S5i"),_T(""),_T("013B1FC692BCCE8DBBAEA5BD4DC13F87"),_T("01DB220936AEBE1D36FDF3382FD48D2E"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S5i"),_T(""),_T("018A97EF0C8856D9155F90A770C73067"),_T("01F68622EE6EF782C32ACC2CCF6A9907"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S5i"),_T(""),_T("011ED04C97FD28B94C49DA6F353F6EC7"),_T("015CDC228C3E4F86A815998B228353E7"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S5i"),_T(""),_T("01534F696E6036C0F788B7E655AC8296"),_T("01DFBB572EC62EA7B91E6179FDE95E64"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S5i"),_T(""),_T("01133005CDA1908ED26E50DDB781DF3D"),_T("0160796D6F8855EA95ECF106A9654836"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("PENTAX"),_T("PENTAX Optio S5i"),_T(""),_T("01C02F25034BDF89C44B5D4FF79274B0"),_T("01ECDD6995EAB2286B85FC2B730162B6"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Research In Motion"),_T("BlackBerry 8100"),_T(""),_T("0155D875C95B74D0F3C5835A62516F48"),_T("01D38A25358EB7649A254E19F1D46600"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Research In Motion"),_T("BlackBerry 8220"),_T(""),_T("015058863386110B7045FC40D0B47450"),_T("017B270E20A299F9D227B485DD5A9BC0"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Research In Motion"),_T("BlackBerry 9530"),_T("Superfine"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("01407EB22CA143AC5D93A6849A7FEAA7"),_T("0157FE31F260013F0ADA57D0F1717DB4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("0120A81C1C6B471497B2C39DD796FE4D"),_T("015E09F77A7C92CAAEEEB1C80AE632CD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("012E8AB1306B60B6F8E1D673C857EE3A"),_T("01930E8CA4514118CCC2A71CD51FB6A6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("016F77F4F618340DFA8D4DB85506B0D7"),_T("01726AA8F1753F6CFA3AEC3EC6A8F818"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("012D53B2BC8DEEC423C726A99B23EFFB"),_T("01342830C284AABC77AEBE2A43D20C2F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("0140C3DDA9D3F807E4D5FD42CB7F7401"),_T("019407145AD5FCC16FEC932CCBC8A9AD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("0166D7C4514A1B5BF17A8A31C90EF2D3"),_T("01E4481CC143080346658FEE1819556F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("01A940AF62216A26DC513D6BDA9F0701"),_T("01CE6F38DBA971F907620725AC62EDF6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("01D5393400D7C7676C33FFE7B0058C2B"),_T("01ECDF62417BAFECAB21ED7394C3302E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("011E63634FA82881580FDA27C4236F17"),_T("017BB1C8854A1FE91C2AAC2B0C5DCED7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("014E56BC9BC75A3853C76762DBA89741"),_T("018A49571355BE8367CF9B25F2D7BDA4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("015DF0EF77AA51618EF0438E14C99A7C"),_T("01C5A27A11860EEEC6677C345637D3A6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("01916A2F71719701991D51B431766405"),_T("0194DE526E131B12BA9CA01B3623B401"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("014263F0A2FDCD405EEB3E857088CF2B"),_T("0198BD9B01BE7BDFC5734F86B17A4B4E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("010CC33FB192BF2F6D9CB720360C5711"),_T("010F766EEF9BFC2D9829794E01D705EE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("010B3F0B475B9082D702F9C46AC041F7"),_T("014E7F78F0BB99F85D5A30D64641C1AD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("0172A66D9B79583F96160F0977E50ABB"),_T("01E6372FFE99AA515645F757C6A7829A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("01E231E0B0AD1CA2327570EF255B58A5"),_T("01EEDC9369B1AE507AD0EAC4A9FAFADE"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("0138D93AD569F4A6DDA706D4C29ECF62"),_T("01832CCB523483953FAA4D9EF090AD7A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("017C6B0B992BF83D07547D6D3DD9E327"),_T("01A1B2B680A7A1010AFC443A26B4AB93"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("0118E8265FC7C96FE9E57D127154C1EF"),_T("0190FEEF53AEA16907E09255D2D7431A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("0109795E5DB4D422FE6B1949FF142172"),_T("016A02998856C8628E975A95B2293848"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("01A465994803BB73ECB03A30E32A9599"),_T("01B3BD820D3A06A710CA6BA6D6B4B639"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("012C1E92CE901A9022CB5FD8282E00DB"),_T("019102DFD4F30C9EAA8B16AF21908898"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("01773241DB0BF4F8D415F19CEBB787C3"),_T("0191FDD3348E5D33208A12821DA15F11"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("RICOH"),_T("GR Digital"),_T(""),_T("0141CE8E21211A09448DCACE8DC51CD4"),_T("01BEE51B29F37D8A5A7BC31C63A652BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01C6769F955C867455C153847C74E6EF"),_T("01EC1CBF6C8662E52114F39EE148CEF7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("0113A2B410CA72B083DF5810A3E3B864"),_T("0156501AF03F0CAA64E7A7956E73BA36"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01855CE0D173027D32B5235EA39D7A1A"),_T("0196BB1FB30F48B5813991708301ECF7"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01B654B54E59A5BD891D0D46B0AE5700"),_T("01CE3648755C5E28D788D4D41892D74F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("019811E20AFD55A42B1C23F704AA9455"),_T("01CD08024A418DA37AF5E3C310299FAC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("0138DF7EECCBD6DFA2AA97A7ED98F9C9"),_T("01822C655B2A1BBFD1095FA6CF8CDC4F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01E3AF5C11ECBA1BDED80818B86A11D7"),_T("01F3BC7FCF52B7F7062B9460473B9128"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("010B2D80F047E0F70631DE68432DAF6B"),_T("01A258C809C4EAC518FAB39067B15EFF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("013E22A3FCAE62D2BD90C219E36F1146"),_T("0149B05374B1345932869E6372ED0485"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("013F402F00B9A0C3102B989150765365"),_T("015BC8A6314A5E90EFD59DF85EE4AC83"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("0184DCF92E592A5982ACC908BA00A472"),_T("01A0D60381102F12B8B8B7AFE0AFEEA1"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("019D7E45EEE96AB2F2F117390DBB5CE6"),_T("01CA95CC822CEF61DE2D1A73DC0253D2"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01683B19EFCF77DD132F0FA65417C2B8"),_T("0196C06916DEAB56AAE98FA378D1533E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("0142C33C0C4072C4FE6CF0D692AEA8DF"),_T("019E26D1A1D23881A7FFAFB39D0863B5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01584549461851E6B504905DBA2404AE"),_T("016738090663999BED71FF0ABE2C3247"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01A5020E4F4CC608563561E25F924693"),_T("01F4A5628F4904EB870522FF06D62F82"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01A464CBA79019D90DB72915151295A4"),_T("01D38A3553CEE799B0E0D1645CB4B9F5"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01903CBB5777CC392122384B2778F808"),_T("019BF9AB7533677149C6F2022D1A6398"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01D8241004A2F31D77D8AE109E2C1965"),_T("01F7B1DA8FFC33821446BCC0360B89FD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("012B47549F5F32EE33A1FFBDB56E2899"),_T("014F1DA0331B7D42C7B19A7841722055"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("015F52865AF840E866CE4FC92CBA216E"),_T("018CD4FE97236D5ACA212D9945920F07"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01098170130C8E4660FCADF13D54D691"),_T("017C96A497120FCD8FBF9C3A08AD9FFC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01349952A8F476A506636F184C339776"),_T("01EA0154C99CDE8FB89FB42F9D5FDAB9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("010B2D80F047E0F70631DE68432DAF6B"),_T("01A258C809C4EAC518FAB39067B15EFF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("0101795CE0D98BABE2BD57034849C925"),_T("01A7FF8625C86B3E99E55BF02B8C438E"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("013E22A3FCAE62D2BD90C219E36F1146"),_T("0149B05374B1345932869E6372ED0485"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("0141808604FB9D4DA90E3B5B6F8C9434"),_T("01E4FE15DD3789354DA16A873745D01F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T(""),_T(""),_T("01094BA340F15215478EA7244B41C831"),_T("016774C49D2D9056742699631887A1F3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("Samsung Techwin"),_T("Digimax V50/a5"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("Pro 815"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("Pro 815"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("Pro 815"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("Pro 815"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("Pro 815"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("Pro 815"),_T(""),_T("01387A14AF75DC6963F040C1239B7DED"),_T("0196457BE1E9E30F00715A3DDE8B160C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("Pro 815"),_T(""),_T("010300D2A3C0CEB8216F7C59B96AFB16"),_T("014F706DC17A4AF11117D50B414F348C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV 7, NV 7"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV 7, NV 7"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV 7, NV 7"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV 7, NV 7"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV 7, NV 7"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV 7, NV 7"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV 7, NV 7"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV 7, NV 7"),_T(""),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV10, NV10"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV10, NV10"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV10, NV10"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV10, NV10"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV10, NV10"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SAMSUNG TECHWIN"),_T("VLUU NV10, NV10"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("01687A34DFCE112C64A9A8B662405FB5"),_T("01A711E09E62AE95248FF0B5F8FED76A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("01D85DF4F5A6AEEE0EB14899034DC2CC"),_T("01DE4C91AB91D804F823DDBBEFED0C80"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("01942B85D5DFEDD8B2BA6B1113B78EE2"),_T("0195A50084E3EAFB04010E04AC831A0A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("0118F69D273A291E8C84DC722CA95DF5"),_T("01192BB7696A82DAA10BCBDB0538FBF9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("010F50672F14B4A88409AEC86E9DECE9"),_T("01C3B4FE62DF9A99F1CA8A5C17AC7711"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("01BD24596581D7A1535AFC805B0D60A2"),_T("01D47AD28A985151B705F90864369E2C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("01AC139E31B941CA0F2C5B5A0BFCDFC0"),_T("01F3D5B0FBE08EC4AAE9E1E4238BF215"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SEIKO EPSON CORP."),_T("PhotoPC 3000Z"),_T(""),_T("0155D875C95B74D0F3C5835A62516F48"),_T("01D38A25358EB7649A254E19F1D46600"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SIGMA"),_T("SIGMA SD10"),_T("Qual:12"),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("1x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SIGMA"),_T("SIGMA SD10"),_T("Qual:12"),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("1x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SIGMA"),_T("SIGMA SD14"),_T("Qual:12"),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("1x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SIGMA"),_T("SIGMA SD14"),_T("Qual:12"),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("1x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SIGMA"),_T("SIGMA SD9"),_T(""),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("01B4A094E3299D54C686AAC3A9E68DA3"),_T("01E79C7A6F55D80F5CBA8BE9834FCFBC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("017D916C205AEFFD4A087EBF94C7506E"),_T("01B41E10A3065957FB93F928542E3BE8"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("0123A1A8835A75EE1DE4DDDB26B19F17"),_T("01D587857C3B50B1C030DD163E85021B"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("015109957D8D4AFEF6E13F4663725048"),_T("01DF5042708CA669A4CD1454906667C4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("019CE3957D32D1795897B849160802E5"),_T("01AE0DBDE466823C5A17DED45D11DB22"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT"),_T(""),_T("011DEA5F26F562AB40D55A90630F7653"),_T("01A6F8AC827B402FC7F102B182B2CFC9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("CYBERSHOT U"),_T(""),_T("012D821C6AB210E2A753BE053B8F55D0"),_T("0182408A81A4ABF04D4A34A8A5E98C58"),_T("2x2"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-F828"),_T(""),_T("013E4F4032D7BBB022EA8A4DD2A79AA1"),_T("015DD46C027E5E984C8305753B29931D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-F828"),_T(""),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-F828"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-F828"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-F828"),_T(""),_T("011DEA5F26F562AB40D55A90630F7653"),_T("01A6F8AC827B402FC7F102B182B2CFC9"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-F88"),_T(""),_T("013E4F4032D7BBB022EA8A4DD2A79AA1"),_T("015DD46C027E5E984C8305753B29931D"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-F88"),_T(""),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-F88"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-F88"),_T(""),_T("011599F2B12AC57E3846AB3F9B84F65C"),_T("01B95B9EB7508DC0C23E40DFC6BE2512"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H1"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H1"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H1"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H1"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H1"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H2"),_T(""),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H2"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H2"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H2"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H2"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H2"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H2"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H2"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H5"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H5"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H5"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H5"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H5"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H5"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("010F50672F14B4A88409AEC86E9DECE9"),_T("01C3B4FE62DF9A99F1CA8A5C17AC7711"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H7"),_T(""),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("010F50672F14B4A88409AEC86E9DECE9"),_T("01C3B4FE62DF9A99F1CA8A5C17AC7711"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("01387A14AF75DC6963F040C1239B7DED"),_T("0196457BE1E9E30F00715A3DDE8B160C"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("0175BAF3251040E0EFB2930B73328E7F"),_T("01DC499064BA9264D591FDE9071DFD89"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("014D29278FD055B04D8FCEF52F63568B"),_T("01EECF7F5B388E02EEE84ABDCF4CECCB"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-H9"),_T(""),_T("01786593B7990A17B0D81B6DF749470E"),_T("01DF37EBC825495EA04E9B311B77D309"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-L1"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-L1"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-L1"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-L1"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-L1"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-L1"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-N1"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-N2"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-P150"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-P150"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-P150"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-P150"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-P200"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-P200"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-P200"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-P200"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-P200"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-R1"),_T(""),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-R1"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-R1"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-R1"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-R1"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-R1"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-S90"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-S90"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-S90"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-S90"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-S90"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-S90"),_T(""),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-T100"),_T(""),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V1"),_T(""),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V1"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V1"),_T(""),_T("01B4A094E3299D54C686AAC3A9E68DA3"),_T("01E79C7A6F55D80F5CBA8BE9834FCFBC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V1"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V1"),_T(""),_T("017D916C205AEFFD4A087EBF94C7506E"),_T("01B41E10A3065957FB93F928542E3BE8"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V1"),_T(""),_T("015109957D8D4AFEF6E13F4663725048"),_T("01DF5042708CA669A4CD1454906667C4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V1"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V1"),_T(""),_T("019CE3957D32D1795897B849160802E5"),_T("01AE0DBDE466823C5A17DED45D11DB22"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V3"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V3"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V3"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-V3"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W1"),_T(""),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W35"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W55"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W7"),_T(""),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W7"),_T(""),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W7"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W7"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W7"),_T(""),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W7"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W7"),_T(""),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W70"),_T(""),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSC-W80"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSLR-A100"),_T(""),_T("0138E0E373A395C2E98FF667B21870CC"),_T("0138E0E373A395C2E98FF667B21870CC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("DSLR-A700"),_T(""),_T("0138E0E373A395C2E98FF667B21870CC"),_T("0138E0E373A395C2E98FF667B21870CC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("SONY"),_T(""),_T("011B33BAEED0A54091895B8D5389FA91"),_T("01E5F053039A59A823FEDC91959822BF"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("SONY"),_T(""),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("SONY"),_T(""),_T("01B4A094E3299D54C686AAC3A9E68DA3"),_T("01E79C7A6F55D80F5CBA8BE9834FCFBC"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("SONY"),_T(""),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("SONY"),_T(""),_T("017D916C205AEFFD4A087EBF94C7506E"),_T("01B41E10A3065957FB93F928542E3BE8"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("SONY"),_T(""),_T("015109957D8D4AFEF6E13F4663725048"),_T("01DF5042708CA669A4CD1454906667C4"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("SONY"),_T(""),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("SONY"),_T(""),_T("019CE3957D32D1795897B849160802E5"),_T("01AE0DBDE466823C5A17DED45D11DB22"),_T("2x1"),_T(""),_T("")}, -{ ENUM_EDITOR_CAM,_T("SONY"),_T("SONY"),_T(""),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T("2x1"),_T(""),_T("")}, +{ ENUM_EDITOR_CAM,"10.0M 3X digital camera","DigitalCam","","01ABDC51F42E1B9894AD6BA6180AEC08","01D0F3FAE71E7CE4E25ED195F2599491","2x1","",""}, +{ ENUM_EDITOR_CAM,"???","Treo 680","","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x2","",""}, +{ ENUM_EDITOR_CAM,"Apple","iPhone","","01114839EC1207E51E21B08385DF6974","01234D2E8848CB268F789EBB63EE1B8D","2x2","",""}, +{ ENUM_EDITOR_CAM,"Asahi Optical Co.,Ltd","PENTAX Optio 330","","0152B022B4F4AC1741AF3BA5F0B4C3C6","01AF9C2CD0D6D3B4EA273D052679C144","2x2","",""}, +{ ENUM_EDITOR_CAM,"Asahi Optical Co.,Ltd","PENTAX Optio 330","","01012CAE6B2A83F4ECFDC9516C93825E","01E53DA9892B36ADAAEAC58897E28B7B","2x2","",""}, +{ ENUM_EDITOR_CAM,"Asahi Optical Co.,Ltd","PENTAX Optio 330","","015CEBBBDF89445196B16C9736466726","01EC96C762F7941278E3F5584E9B100C","2x2","",""}, +{ ENUM_EDITOR_CAM,"Asahi Optical Co.,Ltd","PENTAX Optio 330","","013489D0392A3692A8D7389782C0A6EB","0166B131CC98588533F1D93ACE79AA1A","2x2","",""}, +{ ENUM_EDITOR_CAM,"Asahi Optical Co.,Ltd","PENTAX Optio 330","","0123D54F3D383A3E64A10DE0D5A97816","016EE147C94FA14FFEB80BC6FA4614C8","2x2","",""}, +{ ENUM_EDITOR_CAM,"Asahi Optical Co.,Ltd","PENTAX Optio 430","","0152B022B4F4AC1741AF3BA5F0B4C3C6","01AF9C2CD0D6D3B4EA273D052679C144","2x2","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 300","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 330","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 330","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 40","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 40","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 400","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 400","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 50","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 50","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 55","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 70","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 700","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 700","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 750","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 800 IS","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 850 IS","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 850 IS","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 860 IS","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 900Ti","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS 900Ti","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon DIGITAL IXUS II","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 10D","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 10D","norm","017C9D4907C58FFF90C29510E8DD23EB","01C8A7D568C582C8D42E10882ECA7701","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 20D","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 300D DIGITAL","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 30D","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 350D DIGITAL","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 400D DIGITAL","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 40D","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 40D","norm","017C9D4907C58FFF90C29510E8DD23EB","01C8A7D568C582C8D42E10882ECA7701","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 450D","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 500D","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 500D","norm","017C9D4907C58FFF90C29510E8DD23EB","01C8A7D568C582C8D42E10882ECA7701","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 50D","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 550D","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 5D","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 5D Mark II","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 5D Mark III","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 600D","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 60D","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS 7D","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS D30","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS D60","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS DIGITAL REBEL","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS DIGITAL REBEL XS","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS DIGITAL REBEL XSi","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS DIGITAL REBEL XT","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS DIGITAL REBEL XTi","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS DIGITAL REBEL XTi","fine","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS REBEL T1i","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS REBEL T2i","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS REBEL T3i","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS-1D","fine","017211BC8C6161BCE36DB4E91A7A575F","018C775AA14027570ED51F477477AA84","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS-1D Mark II","fine","01693B4A9D484C7DF321A6051F241493","01F308C26BBCCE3A8D1E869927236116","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS-1D Mark II","fine","014E3B2CA236245A8E6AC25D4C0547B5","016FF2A5B4DCC046A3499C4E12912CBE","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS-1D Mark III","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS-1DS","fine","017211BC8C6161BCE36DB4E91A7A575F","018C775AA14027570ED51F477477AA84","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS-1Ds Mark II","fine","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon EOS-1Ds Mark III","fine","018F98F7BF412181D34F86F1A3BCD26F","01A5A96C366F3E76B00DA5ED55BB3238","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A20","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A20","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A40","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A430","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A460","superfine","0197DCCA5A22C4279E039DC052C60443","01F240E7FA65AB2E40EFA1C2CCEE3726","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A510","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A520","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A520","norm","01536581ECEFBFB9C18C278E79905118","01D91E583DD0037108266E42ED3A262C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A520","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A60","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A620","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A620","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A630","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A640","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A640","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A650 IS","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A70","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A700","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A710 IS","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A710 IS","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A720 IS","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A75","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A95","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot A95","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G1","fine","0166C6447A130A0EB12268E3E74C2545","01FEF02BAC5C13D1C39BCA4E342A8434","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G1","superfine","01D98D90B542316CF007C19CB4C99545","01D98D90B542316CF007C19CB4C99545","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G10","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G11","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G12","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G2","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G2","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G3","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G5","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G6","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G6","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G7","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G7","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G7","superfine","0197DCCA5A22C4279E039DC052C60443","01F240E7FA65AB2E40EFA1C2CCEE3726","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot G9","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot Pro1","fine","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot Pro1","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S1 IS","fine","018567C5DEAAD7EF4120A002519DC287","01BD35C96FB5A5B7BBD37BEAE0E8938C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S1 IS","superfine","012292153D6B64A48C045C10DA4FC0F9","01C11E397A687C7513E1034BC24F4710","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S2 IS","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S2 IS","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S20","fine","0166C6447A130A0EB12268E3E74C2545","01FEF02BAC5C13D1C39BCA4E342A8434","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S20","superfine","01254D92D792D2CB6523C82CF3641DB5","01AF89B1822B526790CC093D6D374A09","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S200","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S3 IS","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S3 IS","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S30","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S40","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S45","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S45","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S5 IS","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S50","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S60","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S70","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S80","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot S80","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot SD1000","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot SD20","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot SD300","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot SD40","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot SD400","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot SD600","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot SD800 IS","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot SD800 IS","norm","01A9490A915CC37ECB6E1256F8E6644B","01B61A33CB5EFDF80F505C0224D3B563","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot SD800 IS","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot SD950 IS","fine","01A84EC0DDFAE937A0336DB825C85028","01A9B171AA8560DD8EA55A93D29361E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"Canon","Canon PowerShot TX1","superfine","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","0114ACEDA8F9481F39E84EFF05320A75","012FCA6D6632CA1A4A7BDD6231B32535","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","010901E28B712B0A893D88C64200A77C","01A458CA927F61177265F104EFC3B6DB","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","0154891CBD5437A548A3C052C118AA0B","01B36319ECD00B49D67C9A766B774E2C","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","0106EE66B9A3CCA78E456DBD4F70C75A","0109875B03DEB01C981AD4D394F5366C","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","0101D11D279551CC7C4CA86A8F39A41A","0161415C082A4312146D7F5C39BA5ED1","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","0186E4B502CA67A194BF25F837844D8D","01A32782FC02530A42591F1F4F464F3F","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","01284370CBB386736D9945F4CC9B67D2","01CCC7E166F2A263B79D58383140B8A1","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","01072BA17E81B063A400664BBDF89044","01C4A90CB8D7B176C23A657F10AF4F62","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","01642B5F591CE08B51B5D0D2493A956D","01A431C10DF789D73EDA19939C228D84","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","01C839B17EE76D0157A2AAE990D683B4","01FE40687C4282564075351F339BDCAD","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","0186895D7C5F2BBA6028D98DBA7CEA73","01CD2D081D75FDCD853C8C66B5A9E79B","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","01878DA912905F4FB26A085F27638E14","01B6670DB7E3D9B5378D0B4D54F84632","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","014D370BE2BDBDBCB33569C338FECF5C","01FEDC6036672378F31AAE0AE2E28E0E","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","016BB57ACC9696E011186EC286CFC185","01ADDA416DCF3BBC8649DC7495FF09F8","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","0191369E9D5A81193E62D58452CC5DDB","01AE39A80FB5251F44103926ED2EC3E2","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","01D8752CBB2AE66D6F4CFB775D59A7A5","01F6B4F4795B85ADB326FD80B4993D68","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","012DE9EF5B39566F08E4864A0E6734F1","01508825BF8EACB426BE13B9F647B278","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","01646DA44D608C8154DCF8F04E540FC1","01D5F912A2CAC1141FEDFAD87B2A66D1","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","013C143987565282044C2DAC1A068436","01879A52F82348EFAC4D95E0C53D88D7","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-3000EX","","011A671A74533E934228664BC17AB47F","01B002679AE502C39E114EF2B5FC0306","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","011B35D8688C01551FDE78BFFB8F1C57","014E650C236D4FC2D83EF2A6226A8A9B","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","01081B465B20737AFAD71D785AC239B0","016A90369C5FDF1067FE96D982AD2119","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","01BAAEE4D1A66BBB7F4F0E88411017E5","01CC1C78C52A9250EC2589572EEE1985","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","012C5B50BF9AE8AAB4A56B596E435A92","017ACD82E5B0B9829E9213B645C356D6","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","01CC03D9AD8BD65C811C26485454F57F","01CF95ACB5EC9CE5A1DECCE25E5353D8","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","015A33449827A6024F4F2088B40487FF","01FC69409FCF1FF801C9ECE870FF52F2","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","0104176A29E2524FBA25A9905E4F23B8","01F2D9EBEA054E050687EF4CD4A3BC43","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","01AD43A6537A8BFA5B99A6DD691C86CA","01AF1667B04F8576816B0BDCD7C2DE43","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","0158C4F5686476668DB83B0E530AD342","01F04E7D6E8E71B08B3426073D69212E","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","0188DCDAB979EC7D09A12202F2B774AF","01CC33C98E3EA1AF8D6BA30C49E3F2DD","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO","QV-4000","","011AE1522C59D1CDBABB1F8AE9C18859","0129A2541B4DC116666C667A9E7798C3","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-P700","","01158B0D515E752B1B0716889F2B3371","017BBA44ECD57A9B2E59D0D6967F1623","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-P700","","018A97EF0C8856D9155F90A770C73067","01F68622EE6EF782C32ACC2CCF6A9907","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-P700","","0102294DDB25E3C1C60F5C5DC104F7B5","016B3CB8CC79372F62EC1BF4D84C018E","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","01307DB502FD0796E12F5BBEB51B4AB2","01663330C80C57C3B23D93665BCA78AD","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","013E4F4032D7BBB022EA8A4DD2A79AA1","015DD46C027E5E984C8305753B29931D","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","01D0473D74948D7D40D56AE4618F18FA","01E2C847E07C54190944A74B136E452B","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","016457926DC23B96DCB1158EC97FA41F","01CF9466A7F18116407263F3C571385B","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","013EB813C8BBDFFF0B4E8A901F467A53","016E3BEA7C7F7A2699A831BD7D810755","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","01541589583CE2044639D04AFA5D92EC","01C87F3D55EDD94FF768CD3D6C4C5EB9","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","01538B160141A7D4D5EC996041B13927","01CD00B4F906A2D48B87B432BD90C47F","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","01E4024724CFD9D59967431BE3D4B5F7","01FC172DB6898BD03C724F65B292E2DB","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","0189899374B6A91C23CE16E82E10860A","01A03ED33AF152520F69668A6384F1CD","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","01762465923F7F2BDED202DCC9EC1C61","019BA0F4F58AB3E2D5503B48FBE64BCD","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","0125B10AC281E131BEEF59122D2A50D9","018613B9EDD3B80CD5532CEDB56E179A","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","012004B942B765F1D36C13D9037D6FBC","01DB30EDD5E692FCF2A005916617DEAD","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","0105A3A5351DF1752ED496F68DAA2FBB","01732657CD1F44D5B7321E556A8612DA","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","012345305944D817D0C161C7B54BAF5C","017DDCB884AFEF1F6DD72AEA5D125933","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z3","","012EE70617EAFF0FC7A699EDF281D96C","0140748F1853345BF32A08347F94C9A4","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","0114F4E9F4E455967FE80C4ED10EBDAD","01680D1FE97C0D264CA8043A194C8133","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","01158B0D515E752B1B0716889F2B3371","017BBA44ECD57A9B2E59D0D6967F1623","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","0151361D87566A29C7953F5D17496970","01C9FD0688443EC6A4EA219C6875EF80","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","013B1FC692BCCE8DBBAEA5BD4DC13F87","01DB220936AEBE1D36FDF3382FD48D2E","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","018A97EF0C8856D9155F90A770C73067","01F68622EE6EF782C32ACC2CCF6A9907","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","0102E487A27A09D7582FA1E0001EDDA8","011B1F3139A11C00C8AF37C1E3BC177F","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","01282B7C952CA521A46610097AF44D85","01D66E67E2B232758F87834EF50590B5","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","01133005CDA1908ED26E50DDB781DF3D","0160796D6F8855EA95ECF106A9654836","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","01898FC95FA9A32B051449450C4D2A12","01C2E8DD6BF896D8E02C99FF30979C44","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","0153055EA4D756EC9F6475B3C09E7C01","01FD90D92E90DBA384669EADB3F577C6","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","01353F8208A74D70DE394C36EF9E1930","0187F5E28A0687D5CCFCFC88CAE032D6","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","01E58965F8067668C66AFED5D75C697A","01E9F3EA3C7492A27953F6010EEC4018","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","012EB4552CC504B451C1DB9919AF87B4","01E45CAEA1F7F87027D080E583B4E4B2","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","0181E59CD24EF8789C041D42B8AD1D5A","01E463C57C904FE7ACC294AD6019A96D","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","0141C8BCEE79DCFDA074E3C07736416A","01DE5CEEED245872C6FCA585F661116B","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","01140A9EB6A29B75A94DAA83062EDF86","015EF8EB6F5D14FB23AB7ABDC958138A","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","01573FFE0766609566191C1833D6F679","0183874EA1080211719853DD0F1BCF07","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD","EX-Z750","","01A06F04F4B4D355BA155DEF93666C41","01B46D5D99ED73CD4F3240EC47C43EFA","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-S1","","0101A7F739C69F00359D8B85CC34F0FB","01367C97B8AC950F6F131433253F02B6","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-V7","","010A617846E6CF420B022872292301CF","01DB0DF2EAE120F08CE3C4D7878A4E22","2x1","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","0114F4E9F4E455967FE80C4ED10EBDAD","01680D1FE97C0D264CA8043A194C8133","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","015810C34129CDE961B762FC29DAD759","01A966EEF909399816B26D62AA2361A1","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","01158B0D515E752B1B0716889F2B3371","017BBA44ECD57A9B2E59D0D6967F1623","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","0151361D87566A29C7953F5D17496970","01C9FD0688443EC6A4EA219C6875EF80","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","0174AE9734728759DD35CDC2E31AA7A1","018F56C5185CA8141F9A004ABF9D73D8","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","012FF3521C45C6DAEEA460C7BDD6DCCC","0187425514C2B6F84D4F22EF7A9D9C40","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","0142650EF71E4211C4C81828541A77F8","0194F0978127E72F4314C73250B9E6B4","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","017968F1F9AEE81D13441ECE60DA6BEA","01A370D713D9ABF8C828A06FCBB25860","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","011BFA3463AE7DAC4A6D3902FB1C0108","01739F243032DF6F0262F85D7A36CFE5","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","011A3E23EC6F242909B20639EB7205D8","01823F6AF5D968093CE92BB16C4A4988","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","0129FE5A01A618B61ABCC5F50F960D20","01F091FFC7E5B8779C78222894121BDF","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","01898FC95FA9A32B051449450C4D2A12","01C2E8DD6BF896D8E02C99FF30979C44","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","011D3D09F48DCC50F94890D1C9A69C5B","01E26E34B5F5E005BA9F75037796E619","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","0133226BF13534FDE68EFC2D88AE82CE","01B9E5BE874A359DE08D0316A0177506","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","014AAC72448AB92C4302572620B7F4AC","014DCA2B0866A92BD9B6839AFC50A1D6","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","0185FECE30CB0A7EB5E37B6A11BD6836","01B3720783EA3E69C14BBFBF06757E64","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","0142BB80C46874F3726D3A8EEED24A3F","014789A946A1654649745D9ABDEAAE79","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","013041C49E6936277A0AB6A1E36A2E56","01C7A2FB7E82A978A31032E710B85EEE","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","015A69E9850D5D1EEAC2BA4108D0314C","01FAA2C9873B4E3B098860660F4C910D","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z1000","","01AE4DFAA5863EF3F54DA3BB2BF35E66","01B67A85A646A481EF7378F757E236D1","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","EX-Z60","","0149FA5635438A0954FA8059E2793FB3","01F127B5443FBD96B3025F295D69BE9F","2x2","",""}, +{ ENUM_EDITOR_CAM,"CASIO COMPUTER CO.,LTD.","QV-R3","","0123352933C37236F67F03EB6B0E3A91","0153CE6A2850A881FA5219B4669EE67C","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK C875 ZOOM DIGITAL CAMERA","","01BBFCF1173FB5AFEACBC1D065B6DC5B","01BBFCF1173FB5AFEACBC1D065B6DC5B","2x2","",""}, +{ ENUM_EDITOR_CAM,"Eastman Kodak Company","KODAK DC265 ZOOM DIGITAL CAMERA (V01.00)","","0108DD2F610E7A2995F0205A2B110768","0108DD2F610E7A2995F0205A2B110768","2x2","",""}, +{ ENUM_EDITOR_CAM,"Eastman Kodak Company","KODAK DC265 ZOOM DIGITAL CAMERA (V01.00)","","01641718AE2C9861D8B6FA297AFF7345","01641718AE2C9861D8B6FA297AFF7345","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK DC280 ZOOM DIGITAL CAMERA","","0108DD2F610E7A2995F0205A2B110768","0108DD2F610E7A2995F0205A2B110768","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK DC280 ZOOM DIGITAL CAMERA","","01641718AE2C9861D8B6FA297AFF7345","01641718AE2C9861D8B6FA297AFF7345","2x2","",""}, +{ ENUM_EDITOR_CAM,"Eastman Kodak Company","KODAK DC290 Zoom Digital Camera (V01.00)","","0108DD2F610E7A2995F0205A2B110768","0108DD2F610E7A2995F0205A2B110768","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK DC4800 ZOOM DIGITAL CAMERA","","01BBFCF1173FB5AFEACBC1D065B6DC5B","01BBFCF1173FB5AFEACBC1D065B6DC5B","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK DX4900 ZOOM DIGITAL CAMERA","","01BBFCF1173FB5AFEACBC1D065B6DC5B","01BBFCF1173FB5AFEACBC1D065B6DC5B","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK DX7590 ZOOM DIGITAL CAMERA","","01761CEA379B4F7A4F77D06279E8050F","01761CEA379B4F7A4F77D06279E8050F","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK DX7590 ZOOM DIGITAL CAMERA","","01761CEA379B4F7A4F77D06279E8050F","01761CEA379B4F7A4F77D06279E8050F","1x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK LS753 ZOOM DIGITAL CAMERA","Best","01BBFCF1173FB5AFEACBC1D065B6DC5B","01BBFCF1173FB5AFEACBC1D065B6DC5B","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P712 ZOOM DIGITAL CAMERA","Basic","01625155BE84D00125E6E169DF4A2F65","01C54F8112BAF719522090C85C5E23F1","1x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P712 ZOOM DIGITAL CAMERA","Fine","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","1x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P712 ZOOM DIGITAL CAMERA","Standard","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","1x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P850 ZOOM DIGITAL CAMERA","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P850 ZOOM DIGITAL CAMERA","","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P850 ZOOM DIGITAL CAMERA","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P850 ZOOM DIGITAL CAMERA","","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P850 ZOOM DIGITAL CAMERA","","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P850 ZOOM DIGITAL CAMERA","","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P850 ZOOM DIGITAL CAMERA","","0134F2041810CE97DAAB408D5E71163C","01D831EF97768EF36E607FD5D85426FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P850 ZOOM DIGITAL CAMERA","","01BD24596581D7A1535AFC805B0D60A2","01D47AD28A985151B705F90864369E2C","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P850 ZOOM DIGITAL CAMERA","","0184C9EBAD799D9C4AFE7B97932F42C5","01F0A787A4F48EE0145B0243DD91F234","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","0124AC8790656DF23F8070E2A880B501","016CC716D191DBD0BB21F1090184405D","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","1x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","1x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","1x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","1x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","0134F2041810CE97DAAB408D5E71163C","01D831EF97768EF36E607FD5D85426FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK P880 ZOOM DIGITAL CAMERA","","0178BAF59FA3A93E45912D1A3AB3DFA4","0183C6D8ADA5B5856CB6C4CEAFA87628","1x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK V610 DUAL LENS DIGITAL CAMERA","","01BBFCF1173FB5AFEACBC1D065B6DC5B","01BBFCF1173FB5AFEACBC1D065B6DC5B","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK V705 DUAL LENS DIGITAL CAMERA","","01BBFCF1173FB5AFEACBC1D065B6DC5B","01BBFCF1173FB5AFEACBC1D065B6DC5B","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK Z612 ZOOM DIGITAL CAMERA","","01BBFCF1173FB5AFEACBC1D065B6DC5B","01BBFCF1173FB5AFEACBC1D065B6DC5B","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK Z650 ZOOM DIGITAL CAMERA","","01BBFCF1173FB5AFEACBC1D065B6DC5B","01BBFCF1173FB5AFEACBC1D065B6DC5B","2x2","",""}, +{ ENUM_EDITOR_CAM,"EASTMAN KODAK COMPANY","KODAK Z740 ZOOM DIGITAL CAMERA","","01BBFCF1173FB5AFEACBC1D065B6DC5B","01BBFCF1173FB5AFEACBC1D065B6DC5B","2x2","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix A330","high","016177AB8D6680CE1D5BD42F16970EBB","01CF7260141AA84FBDC5E47A35118EBF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix A700","","01144982047160D8F5F6F1353EF1713C","01EE606D916D8DBD24D301A85169CE58","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0107970B1B893B56DEC2A2B1B0B797B1","0115AB45CC9CD386DAC1E6E7DAB33CD6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","01DE1EEA3B2C88A57A1D3894C9F4CA25","01EEFBA4B1584A8B8B670D9EAB8D0C9D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0143A9114D57AEC803D47AB9AA1DAC8E","01E0F7F87C972B220E1203E00D78FF1E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0136AAFA05459AEFAABBB57620F4604F","01B995B722D53ADDC6AA4D06115AFE4F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0167ADE27CBB81EED41B08E8DD91919C","017FA6A0E82890CD1734E1435D5EED33","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","01144982047160D8F5F6F1353EF1713C","01EE606D916D8DBD24D301A85169CE58","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","016FA4721E4BDCA33AB0243056ED052F","01B0ACBB0E5167B3D432056CDFF87C98","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0194A30D59C5D4F233C204CCCD9383E0","01D69C67E78A7244D23671EB2DEDF6C1","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","018DDDBEBFE9897574F2601B234742B0","01EDD07571B6983644D2B38B88D520A6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","010D98BF96F187A0C2C69857A2532D3A","01A30B61A5E49BF4ED08B00CFE7916BE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","01300CF6E26C44CA6E1F7E002E90E29B","01C97D0146AF14BC73CBB75FBC2DEA7D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","01209694C019817E5160C77ECB0E6E73","01A6E0CFCF95398C049C8A6A8CB5662F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","01322A55C3F539232F9F48AC5DCA0072","01448D46E463836F6191E0916423365A","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0145F26B95FF8AF15D1A7DC64355F872","016D15F943FA53E2F9E93A89A926B850","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","011F72189F16FB63160539354A378C18","01B57B0DB97AF420331DCB82522A4FC0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0105CCB4C4B348AE594D640D47A029B7","014CE1370398E06CCA7E7635DA264D67","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0114487FCFC83B9264E0E8E7CEB018C1","01775E6DC2982017FD3CADA42C020735","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0175096CD9CB339136584317671A190F","01FFAD541AE2A57B779D1092D1D36CC6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","010B56EF40829B8C4322CA40EC09F38E","01EDC31567D017E237CD52453C45DD19","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0143F7DAE2EA08DE30DA14FE894C3D07","017C6D26409ACAF1615DE04A6B9C9C7C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","01A88E1F6EE058E7ED3461A41319E940","01F2199FD2DDA564B7B2C2B509C9B867","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","012C11691B3D750330F68718791E6D82","016F2A0902423BB51F4C00CB28EC2AC2","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","","0158A6F94ACA7479ADC3CE97BCCF6067","01966CF476E457732318E23BED0FACFB","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","fine","0115FB8DBBBF91B4B9D9F034824CB8DE","013855ED9741DF50B314E3AC7E2F6A3F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E550","normal","01131D987286C9F06E27B89F8CB39055","01E3FB9A93F491AF8D8D25B6C85C60AF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix E900","","016FA4721E4BDCA33AB0243056ED052F","01B0ACBB0E5167B3D432056CDFF87C98","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","018E2B0BAB1091B759DA4A36C1498434","01B3E93337A2DC7DB01EFC7F0B9260BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","01511F2752713A5E416E7F52CAACC00F","01652DC355F8FE9317D1ACD1B61F3BFD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","0142BD6537DD267D5315D93E3199D296","019F6B8CF9E4A7B141FF8C23430ABB79","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","0126DF310012A2906C931B68FFE4A4FF","01EDEA44DA225D6BAAA693F15D5D9FA4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","01CF6837934F5586370A3208A5964B35","01CFFF16E1C60E2DBE37A43C7DC375A6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","01F66DD3883F0537836AF63904F782EA","01F683F377BF9221D4B797F47699DB46","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","01DE1EEA3B2C88A57A1D3894C9F4CA25","01EEFBA4B1584A8B8B670D9EAB8D0C9D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","0103AF85E3D5BCF4E131B579BE784A54","011FB35319800515F3B1AF9C01B98F5C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","015263B1DEF7F49143B25A7399503908","01D9E2046C67FBA14257D043ABD80227","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","01DC8EA12E8F9DE73C730CE2710B6CB1","01FCD32DF9F3AF71786DD78DC0800136","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","0143172307C00E1BF25477E64B4D871E","0149D17CAB38C9B9FEBDBA1E18354E75","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","0103D886A565CB92A2C07B1E83283938","01B0DFFF3B86F30AB053C9E4D90E2857","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","01775803404B1F6E51DA270D875AE21C","018DE101321099CA44B3BBB7A971FC1D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","0135B9D3FA43F42B228C8D68559183A1","01E9A7153A4282CFAFCB55AE330A529D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","0136AAFA05459AEFAABBB57620F4604F","01B995B722D53ADDC6AA4D06115AFE4F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","0167ADE27CBB81EED41B08E8DD91919C","017FA6A0E82890CD1734E1435D5EED33","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","01E63EEB1C76EA886EB86D05A4BF6453","01EE5B1290C0B04E02A7A5909D728E53","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","01AB6FC5F47A256B85A06A20DF7A2E73","01D33FAE924EC067B2FA25060B9DBDDE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","01322A55C3F539232F9F48AC5DCA0072","01448D46E463836F6191E0916423365A","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","014D07412D807AFD47466BC3B2DCFD20","018571F62223F9611C5C82E33361D715","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","01269559519B7DD8BEF85FD3A3D36098","01699EC66C077829BFC5A565F2406A2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","0106D2E82ED326912ACBE67C2156F424","01389549659E667495B6C42EE144CB04","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","016177AB8D6680CE1D5BD42F16970EBB","01CF7260141AA84FBDC5E47A35118EBF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F10","","0187E258D1C4458BF14E95702CCA2CF9","01E68E3620535112F02B2D1133033A90","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","012DA6A8179D685C316E3561ECFDFBBD","012DA6A8179D685C316E3561ECFDFBBD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","013659FB683254FC54DDE61474AF809C","0174AB5078929D8E287FECAA4B30532E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0177F18C71320F7FF7F3B037DD101223","01D9F611647071948F3807C5C4C97964","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","01159F4F09FFCFDABE48FC7C23DCF0CA","018E6E27D7203B16A8C808E94F67089F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","018C380E60DF1314784C827EFEC4087F","01C4776D91252150EA3E030855ED4E70","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0107970B1B893B56DEC2A2B1B0B797B1","0115AB45CC9CD386DAC1E6E7DAB33CD6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0142BD6537DD267D5315D93E3199D296","019F6B8CF9E4A7B141FF8C23430ABB79","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0125360719B8F561A961A8205CA300A6","01A12CBCB3929F4F50A2361636A2C17F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0133353D7ACF8F6FFD9C833C91C2DE82","01DCD75B2D981DCBA8F67F138F5A4689","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","01CF6837934F5586370A3208A5964B35","01CFFF16E1C60E2DBE37A43C7DC375A6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","01DE1EEA3B2C88A57A1D3894C9F4CA25","01EEFBA4B1584A8B8B670D9EAB8D0C9D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0103AF85E3D5BCF4E131B579BE784A54","011FB35319800515F3B1AF9C01B98F5C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","015263B1DEF7F49143B25A7399503908","01D9E2046C67FBA14257D043ABD80227","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","01DC8EA12E8F9DE73C730CE2710B6CB1","01FCD32DF9F3AF71786DD78DC0800136","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0103D886A565CB92A2C07B1E83283938","01B0DFFF3B86F30AB053C9E4D90E2857","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0143A9114D57AEC803D47AB9AA1DAC8E","01E0F7F87C972B220E1203E00D78FF1E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0113F8BF2685232C081221544B886BE3","014A4D2D56D0003594C4ECB8139B08D4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0135B9D3FA43F42B228C8D68559183A1","01E9A7153A4282CFAFCB55AE330A529D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","01340755C56A1C1E8A7E59A1B3BA24D8","0159C96D7604CE74484E5E1BFDECC62E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","01E63EEB1C76EA886EB86D05A4BF6453","01EE5B1290C0B04E02A7A5909D728E53","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","019CAE8BAA4E0901A8132DB0460252E6","01D6C978E3AABF216D5CAACF54F63412","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0132B6121FABF922EC108ED2299A4DF8","01B1D99243F7145290F94B0DDB143DF1","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","013848370A40F0D07134E5F819A35BAA","01AA5DCFB1E3186C06CED70E710F15C0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F30","","0173377CDE7592A2713170C463771BCF","01D784735642AA8E091C60FEE5FD1DBD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","0109D9B765ADC9B8A749C830F9A87C0C","01F47FF18B844BA5E3163DC1BB954612","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","0103E19EF10910FD9D0710852668A178","01D5BC8CE7BC209B25A8C8648FB61439","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","013AB20A7D024D1D24EE5CA8A01B8A2E","015620909103A039B8D64818100C3538","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","012FCE7A1A81837C7F3783AA9F2CB0CF","01BDD87262EF899D2EA565BAEBFF8285","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","012BFCCAF570BA39D7758A93212F4FE6","01383B54C4063EEBA23F13AB1415BB64","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","01EF23B16E6DF6EFE5F4E183E476188A","01F57F9E26A77E824BF4EA1D93EBFEB6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","0137DD0B0E26F694CBB317E21B4AE230","01DEB47B3440B79A7568ADAAC0B5D4E1","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","0124A6EC131285715A0E4C5C37AACFE8","01381ECEF3CA87CC5B27C32FC8FCADD0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","01229C5AA062D88A9449065018371866","015A18E7902796EB4DBDE8A5AC7CDC91","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","018EDB93CFE7F86ECE0E37F92C374F62","0191E43084B599DC909907C4BA82070A","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","01537B41C7887A54ABAAB2B14836B7F6","01CA67189FF26224721E329BB73A2CF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","0127BA5075AD35F0F85D15DE0568818E","012A90C987751ECEF261E62CC88755B5","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","013CD57992DEE9AF4FF18916A1BAF695","018849D06D074410D0C51A22F8DECE87","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","014B5F0D2E14DA1836880E0B71113A23","0178844318AA60BEBB0F3D39BFA7C282","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","014F28993E97414C40DFD0B6C3F53AEA","01581A04F9ABEEDFFCF3917BB2C925A7","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F700","","0105B30BB6043B3CC5A9518A60947F04","011D5E41D0A9E07F8DC8ECBC923E1A50","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","0102FD60B1BEE5C1D4E09C430F3BAF8E","016A742831A8B18944908F8FE6667FF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","01CF6837934F5586370A3208A5964B35","01CFFF16E1C60E2DBE37A43C7DC375A6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","0103AF85E3D5BCF4E131B579BE784A54","011FB35319800515F3B1AF9C01B98F5C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","0136909CD8B831B7F2A1A40DDFE711FA","013DD960D0C3B58269535DF656FA87AE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","016FA4721E4BDCA33AB0243056ED052F","01B0ACBB0E5167B3D432056CDFF87C98","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","01E63EEB1C76EA886EB86D05A4BF6453","01EE5B1290C0B04E02A7A5909D728E53","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","010591CD94BABC13B571DEDB9A76B196","01F0E53A1233A692F0D17371293F5342","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","013848370A40F0D07134E5F819A35BAA","01AA5DCFB1E3186C06CED70E710F15C0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","011F13E54D8728C8486C2D0547B93C00","01E981EDB38DC8239E54BA4805C26B74","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","012840C2B1FCCDE2221D57CD894F5898","015F4AA8F8D3132E1FAF5DB940997359","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","014953E487E86BCA6BB01842D37A3979","01CBF30DCDFF5964440C0DD7A1DC9DDD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","0125B5D4DAD31F73197E943B1FA80710","012B5C9C9DE2B306557D7F6F0ABBC33F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","0195EEA7C7FFC31874CB47F55A731440","01EA701641AE57738E101037BBDFBAC4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","0177F851C3B1746C6F3ED95C768B72AF","01A2D84750639B253394A2BC702BBA64","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","011C906212D8A2C45BA66ED96B57DD16","018F1C3E1FDB4A1785F9BF63ACC5DD1B","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","012F2EE5B50FBD87AF3DD370C98D4E3A","01CF07DB139C22B4C3B7B59640D0EE06","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","010E3334FC94179364A056207AE42ACB","01BBD1C9C6E595E3D97E4CC4D24E0066","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","015D43A40A0602CAFB865C7620995223","018D283C92404C7F768254885EFD5DA2","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","015BDA2DD1B591063B1D47998A5BF147","018E9408F19306B79381D994B812C431","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","0124A6EC131285715A0E4C5C37AACFE8","01381ECEF3CA87CC5B27C32FC8FCADD0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","01450C56AA66881CD17F96A041FC17F7","01BD74F16BA271F7A0438D79AFC746C5","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","01A88E1F6EE058E7ED3461A41319E940","01F2199FD2DDA564B7B2C2B509C9B867","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix F810","","0155A48050753EA001FBAF229F98C84B","01E7CEA6D4523C9769B9D7E3C0D1CA78","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S20Pro","","01AC5C1171760A3C309B7156A91E7E65","01CA4C33113E1681E0196932FB6D9D81","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","01089D27A104A81CE3A986763DEF98B8","016783137CC0098188020126C5327C0D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","018E2B0BAB1091B759DA4A36C1498434","01B3E93337A2DC7DB01EFC7F0B9260BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","01511F2752713A5E416E7F52CAACC00F","01652DC355F8FE9317D1ACD1B61F3BFD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","0107970B1B893B56DEC2A2B1B0B797B1","0115AB45CC9CD386DAC1E6E7DAB33CD6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","0126DF310012A2906C931B68FFE4A4FF","01EDEA44DA225D6BAAA693F15D5D9FA4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","0133353D7ACF8F6FFD9C833C91C2DE82","01DCD75B2D981DCBA8F67F138F5A4689","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","0103AF85E3D5BCF4E131B579BE784A54","011FB35319800515F3B1AF9C01B98F5C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","01338863A9E9D87C756424FEB020BD98","01D90BFC434FAD5B68EA3351CF827D30","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","0143172307C00E1BF25477E64B4D871E","0149D17CAB38C9B9FEBDBA1E18354E75","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","0103D886A565CB92A2C07B1E83283938","01B0DFFF3B86F30AB053C9E4D90E2857","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","01775803404B1F6E51DA270D875AE21C","018DE101321099CA44B3BBB7A971FC1D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","0143A9114D57AEC803D47AB9AA1DAC8E","01E0F7F87C972B220E1203E00D78FF1E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","0126DAA916EC369FF8B1797B107C375F","01BAC7FF877B99FA2EFE0B0BC9A51F70","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","01A1E20150A519300E142C5DFF57F49D","01A9F212229355222B1DF6D1C6BA36CE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","0135B9D3FA43F42B228C8D68559183A1","01E9A7153A4282CFAFCB55AE330A529D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","0147C9CEBD36DF9A8FC10C197C655B9A","01CBF7CACE5354346E834F315D68854C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","01340755C56A1C1E8A7E59A1B3BA24D8","0159C96D7604CE74484E5E1BFDECC62E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","016FA4721E4BDCA33AB0243056ED052F","01B0ACBB0E5167B3D432056CDFF87C98","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","014D07412D807AFD47466BC3B2DCFD20","018571F62223F9611C5C82E33361D715","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","017548B546BB0963B26B44611755A70D","01C985AE33A5F28E8BAB1D3ED75ED2A1","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S3Pro","","014899659B5DFB996E7E35C3DA1F6211","017230BF5CE1D091A27340E31A89BF61","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","0154B9751596FC0D25ADC6F9D2B6B274","01D07180C64D9BDF825A5304B71E751F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","019F5DB74FAF31A9F4895A9A007E0A01","01ADB3065BA5B24F87745074E70B7C54","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","011C1CA26C33CE3E87B733EC41F1E233","019938269F4D594DE389F9C1DE231D9A","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","010E3334FC94179364A056207AE42ACB","01BBD1C9C6E595E3D97E4CC4D24E0066","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","01991A5434F416A7CCBDACDB066BDFA5","01E1BB8350885874B0A7C8C9750985BB","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","016C0C68D03E7317DDED0A07B2492CA2","019C0C77CBCDFB463BAA8F0543FA3BC4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","0124A6EC131285715A0E4C5C37AACFE8","01381ECEF3CA87CC5B27C32FC8FCADD0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","01A88E1F6EE058E7ED3461A41319E940","01F2199FD2DDA564B7B2C2B509C9B867","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","01062F81528A1594FFBFF7BEED6584DA","01DE2EFED0143FDF402CD486CF4B67F4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","01A30316FC14ABE0576A6D39338B489F","01AE9F3C5615392B7144D385A82925AD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","0155A48050753EA001FBAF229F98C84B","01E7CEA6D4523C9769B9D7E3C0D1CA78","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","014F28993E97414C40DFD0B6C3F53AEA","01581A04F9ABEEDFFCF3917BB2C925A7","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","01172B3480B05799AA98FAB9BBACA31C","017E24A44A691C3AAC93AA741E7BA8BE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","013C282F2F9C1270D6FC8DD4E334CBE9","017D5A53E3ABF75F2FBAA66DE6804CA6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","0120638613ED08DC3B923EC45E3F2BDB","01F85A256DFDBBC84214D566AB8AACFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5000","","0123530416265D640E4E07C606357E5A","012978B985997C7A0597D7CAC69525DA","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","01089D27A104A81CE3A986763DEF98B8","016783137CC0098188020126C5327C0D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","018E2B0BAB1091B759DA4A36C1498434","01B3E93337A2DC7DB01EFC7F0B9260BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","0126DF310012A2906C931B68FFE4A4FF","01EDEA44DA225D6BAAA693F15D5D9FA4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","01F66DD3883F0537836AF63904F782EA","01F683F377BF9221D4B797F47699DB46","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","01DE1EEA3B2C88A57A1D3894C9F4CA25","01EEFBA4B1584A8B8B670D9EAB8D0C9D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","0103AF85E3D5BCF4E131B579BE784A54","011FB35319800515F3B1AF9C01B98F5C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","015263B1DEF7F49143B25A7399503908","01D9E2046C67FBA14257D043ABD80227","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","01338863A9E9D87C756424FEB020BD98","01D90BFC434FAD5B68EA3351CF827D30","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","01DC8EA12E8F9DE73C730CE2710B6CB1","01FCD32DF9F3AF71786DD78DC0800136","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","014D9616BBF7E071E910B93ABFB21C27","018734006FEA2D30B1C0A8F47A50FF74","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","0136AAFA05459AEFAABBB57620F4604F","01B995B722D53ADDC6AA4D06115AFE4F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","0147C9CEBD36DF9A8FC10C197C655B9A","01CBF7CACE5354346E834F315D68854C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","013FA8B0D97468662280A7C33A960DD7","014B6B976D0DF6E350AD535F4BEA101F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","0115FB8DBBBF91B4B9D9F034824CB8DE","013855ED9741DF50B314E3AC7E2F6A3F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","01BD62DE4967E5CD3906D337D28B5905","01C9C71A684334A614FC1F7BE6A00D15","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","01AB6FC5F47A256B85A06A20DF7A2E73","01D33FAE924EC067B2FA25060B9DBDDE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","011A4E131AE6141F56175D11C0FF08F3","019C6D82AB51688BCFEF61E51C4C4B89","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","01209694C019817E5160C77ECB0E6E73","01A6E0CFCF95398C049C8A6A8CB5662F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","016ADD09C60862FD6F0B9452EC614AD8","017B24E070670F38FE2761B505BF97C4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","01322A55C3F539232F9F48AC5DCA0072","01448D46E463836F6191E0916423365A","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","014F18BED4590DE7A0360B979D6C1EC0","016FC2A0F1990575069647DB51BF5D98","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","011F72189F16FB63160539354A378C18","01B57B0DB97AF420331DCB82522A4FC0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","011A0B6A5E2CD8D701387C1B92673C51","01424F959EF392EE7D3A4B878C98E2B2","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5500","","011A80B1C9B879845EFE6653EA3D3C98","01423B8723E1E7758F00E44D42A3A2CB","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","012DA6A8179D685C316E3561ECFDFBBD","012DA6A8179D685C316E3561ECFDFBBD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","0129F7BBA55E2EAEB8C9E3BDDBA7B64A","014363233109D50BE8328B6044FE1D58","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","019EF19678BB82F6281BF75BEE17635A","01B721616C882F82F632C9C9A02029A3","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","013659FB683254FC54DDE61474AF809C","0174AB5078929D8E287FECAA4B30532E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","0177F18C71320F7FF7F3B037DD101223","01D9F611647071948F3807C5C4C97964","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","01089D27A104A81CE3A986763DEF98B8","016783137CC0098188020126C5327C0D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","018C380E60DF1314784C827EFEC4087F","01C4776D91252150EA3E030855ED4E70","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","01511F2752713A5E416E7F52CAACC00F","01652DC355F8FE9317D1ACD1B61F3BFD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","0107970B1B893B56DEC2A2B1B0B797B1","0115AB45CC9CD386DAC1E6E7DAB33CD6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","0126DF310012A2906C931B68FFE4A4FF","01EDEA44DA225D6BAAA693F15D5D9FA4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","0133353D7ACF8F6FFD9C833C91C2DE82","01DCD75B2D981DCBA8F67F138F5A4689","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","01CF6837934F5586370A3208A5964B35","01CFFF16E1C60E2DBE37A43C7DC375A6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","01DE1EEA3B2C88A57A1D3894C9F4CA25","01EEFBA4B1584A8B8B670D9EAB8D0C9D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","01DC8EA12E8F9DE73C730CE2710B6CB1","01FCD32DF9F3AF71786DD78DC0800136","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","013FA8B0D97468662280A7C33A960DD7","014B6B976D0DF6E350AD535F4BEA101F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S5Pro","","0115FB8DBBBF91B4B9D9F034824CB8DE","013855ED9741DF50B314E3AC7E2F6A3F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6000fd","normal","0121D8EB73BAC21E4308A56F22BCB342","01AA1D853FAC38D9FC8DC1E65CED1574","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6000fd","normal","01BEB83A517518E7E38D6457D7B098DE","01EF98C649CA056505C41E28C21A354E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S602 ZOOM","","01C6EB2D5C761F5B0F41195E09A7C5E1","01EDB7106ED8CE9E8F7BD7F14EC44611","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S602 ZOOM","","012840C2B1FCCDE2221D57CD894F5898","015F4AA8F8D3132E1FAF5DB940997359","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S602 ZOOM","","0153F536ECB43EAF05B3724640284BC1","01E70A0FD3DB0A5288CF9E983B6F9531","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S602 ZOOM","","01315E29DF55971D2E1D34104AC3E495","01928C9C997CDBA38DA512091CF1A7F1","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","012DA6A8179D685C316E3561ECFDFBBD","012DA6A8179D685C316E3561ECFDFBBD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","0129F7BBA55E2EAEB8C9E3BDDBA7B64A","014363233109D50BE8328B6044FE1D58","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","019EF19678BB82F6281BF75BEE17635A","01B721616C882F82F632C9C9A02029A3","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","018C380E60DF1314784C827EFEC4087F","01C4776D91252150EA3E030855ED4E70","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","018E2B0BAB1091B759DA4A36C1498434","01B3E93337A2DC7DB01EFC7F0B9260BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","01511F2752713A5E416E7F52CAACC00F","01652DC355F8FE9317D1ACD1B61F3BFD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","0125360719B8F561A961A8205CA300A6","01A12CBCB3929F4F50A2361636A2C17F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","0102FD60B1BEE5C1D4E09C430F3BAF8E","016A742831A8B18944908F8FE6667FF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","0133353D7ACF8F6FFD9C833C91C2DE82","01DCD75B2D981DCBA8F67F138F5A4689","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","01DE1EEA3B2C88A57A1D3894C9F4CA25","01EEFBA4B1584A8B8B670D9EAB8D0C9D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","0103AF85E3D5BCF4E131B579BE784A54","011FB35319800515F3B1AF9C01B98F5C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","01338863A9E9D87C756424FEB020BD98","01D90BFC434FAD5B68EA3351CF827D30","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","01DC8EA12E8F9DE73C730CE2710B6CB1","01FCD32DF9F3AF71786DD78DC0800136","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","0143172307C00E1BF25477E64B4D871E","0149D17CAB38C9B9FEBDBA1E18354E75","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","0103D886A565CB92A2C07B1E83283938","01B0DFFF3B86F30AB053C9E4D90E2857","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","01775803404B1F6E51DA270D875AE21C","018DE101321099CA44B3BBB7A971FC1D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","01A1E20150A519300E142C5DFF57F49D","01A9F212229355222B1DF6D1C6BA36CE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","0135B9D3FA43F42B228C8D68559183A1","01E9A7153A4282CFAFCB55AE330A529D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","015533F5B111AD9E51590E42BF1CF318","018AE8620E8E1B95D1C8FD0338613321","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","01986403D0DB39CED56956CC83185747","01D8F9653754860125F8983DB814867D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","01BD62DE4967E5CD3906D337D28B5905","01C9C71A684334A614FC1F7BE6A00D15","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","01AB6FC5F47A256B85A06A20DF7A2E73","01D33FAE924EC067B2FA25060B9DBDDE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","01300CF6E26C44CA6E1F7E002E90E29B","01C97D0146AF14BC73CBB75FBC2DEA7D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","016ADD09C60862FD6F0B9452EC614AD8","017B24E070670F38FE2761B505BF97C4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S6500fd","","0173E1FDEFE1767FC62734B7FD5B4FE6","017EFC8A48D105AD27C16C3EC1B7A211","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","01986403D0DB39CED56956CC83185747","01D8F9653754860125F8983DB814867D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","0139C3609C7439A2677D0591BAA17CA0","017CE35D279F1A8B21080E0AE6C53CAD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","01870F12535AD117686AA38D87F4F230","01F1932E46B612094A22F38BD5FF970E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","011A0B6A5E2CD8D701387C1B92673C51","01424F959EF392EE7D3A4B878C98E2B2","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","0153F536ECB43EAF05B3724640284BC1","01E70A0FD3DB0A5288CF9E983B6F9531","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","01B87A9323B8323DBBF8D268C8DA5CCB","01FA3743550ECF2375FD313472BC7415","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","01269559519B7DD8BEF85FD3A3D36098","01699EC66C077829BFC5A565F2406A2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","0195EEA7C7FFC31874CB47F55A731440","01EA701641AE57738E101037BBDFBAC4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","012ACF619E4947C6342F0DFA82B454F4","017696925674863D4E93611CF53FE982","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","0158F705D871236CACBC097D8FF7E553","01C46C517D157C7456DAB45044446CB2","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","01D44FF54148D7672B0F9F149588C216","01FCF038CB0AFCB826D6834D3B9BB7FF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","01B6370B0E1246DC33A50DE4AFAE3064","01C32DF8021355EF8B5777806A810BFE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","01932B6BF7C7C4EA0676C13FE773E9F0","01B0A192C8D2D9B359A6A71DBFC65DE7","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","01C1350830CDC224402C69FBBA4B4D32","01C40C78BB04798DE6386B16D6CA2F48","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","0160C13457E7492844700B1E2765A7C2","017374AB9A06F5B7D9C547A5D586B0BE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","011593FAC397BE3E35F132DA00BB55C1","014D9687F924E7724F494F7538C9C7EF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S7000","","014412B6367A91A2120C56FE9DEDCF7A","0199DFAF205A8F5ED6131F8C9D4E7C4C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","012DA6A8179D685C316E3561ECFDFBBD","012DA6A8179D685C316E3561ECFDFBBD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","0129F7BBA55E2EAEB8C9E3BDDBA7B64A","014363233109D50BE8328B6044FE1D58","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","013659FB683254FC54DDE61474AF809C","0174AB5078929D8E287FECAA4B30532E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","0177F18C71320F7FF7F3B037DD101223","01D9F611647071948F3807C5C4C97964","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","01089D27A104A81CE3A986763DEF98B8","016783137CC0098188020126C5327C0D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","01159F4F09FFCFDABE48FC7C23DCF0CA","018E6E27D7203B16A8C808E94F67089F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","018E2B0BAB1091B759DA4A36C1498434","01B3E93337A2DC7DB01EFC7F0B9260BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","0142BD6537DD267D5315D93E3199D296","019F6B8CF9E4A7B141FF8C23430ABB79","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","0168B62B2672A1EA16B5EEFCE01A5D3D","01DA3B84475F74FFA005D8B903F9305C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","01004744D797C2E65F6E10A01801F988","0126C34F057B641EA35917CAE5BABD04","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","0125360719B8F561A961A8205CA300A6","01A12CBCB3929F4F50A2361636A2C17F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","01CF6837934F5586370A3208A5964B35","01CFFF16E1C60E2DBE37A43C7DC375A6","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","01DE1EEA3B2C88A57A1D3894C9F4CA25","01EEFBA4B1584A8B8B670D9EAB8D0C9D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","01338863A9E9D87C756424FEB020BD98","01D90BFC434FAD5B68EA3351CF827D30","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","01775803404B1F6E51DA270D875AE21C","018DE101321099CA44B3BBB7A971FC1D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","0126DAA916EC369FF8B1797B107C375F","01BAC7FF877B99FA2EFE0B0BC9A51F70","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","0147C9CEBD36DF9A8FC10C197C655B9A","01CBF7CACE5354346E834F315D68854C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","0115FB8DBBBF91B4B9D9F034824CB8DE","013855ED9741DF50B314E3AC7E2F6A3F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","01DF82190E252AC7A11162C378E74D8F","01F6A274D8F0CBC5C82B7B67941C1C8E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","014899659B5DFB996E7E35C3DA1F6211","017230BF5CE1D091A27340E31A89BF61","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","015BFED124534D3E92BBF2906045F273","0190E3CE4CB1DEB9C26685C28EE19669","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix S9500","","01B6890F97E3942CF6210514EAD0B4DF","01F14DAD8C7B9AAAC1F8DB9C88E21E3F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix V10","fine","01DC8EA12E8F9DE73C730CE2710B6CB1","01FCD32DF9F3AF71786DD78DC0800136","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix2650","","0173E1FDEFE1767FC62734B7FD5B4FE6","017EFC8A48D105AD27C16C3EC1B7A211","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix2650","","0103BCA9D0FF326CE25144CF5AE1D884","019F7525A3CBF83459E6870C7D506833","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","0139C3609C7439A2677D0591BAA17CA0","017CE35D279F1A8B21080E0AE6C53CAD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","019CAE8BAA4E0901A8132DB0460252E6","01D6C978E3AABF216D5CAACF54F63412","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","01300CF6E26C44CA6E1F7E002E90E29B","01C97D0146AF14BC73CBB75FBC2DEA7D","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","0131856988BD7B6B71E3C17784F3B1DF","0164A6B8BA79A38657D4129B88C1E935","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","012EFDA0756DC8F02E1314E0A85E38DA","0150B33D240B71C570632E01FEB03F89","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","0117AFF0AC55A9FA9B557341ED28AA4F","019FC66891E7C2CB433015662520C0B7","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","0102C9551E830545C18B70A571480094","01F15F441249A8D22F60EE46C1A5E212","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","0178484D9EC1A5ECCEAE50569236B015","01A26D8FAC66BE2064402779D63E7401","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","014B61CBCC7D97DD7DB61C0EFD0AB9D3","0171C28AC02233CEF51F1715DD281396","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","019A4D45AE6936BB8BEC4EDE730117CD","01A11FE6F7D27DC64C8B2B33D2897452","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","017058A60BB7E5ABA088618FFB832B0A","01EE2DF6C151E5ACD0A3486FBF4E13BE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","0120638613ED08DC3B923EC45E3F2BDB","01F85A256DFDBBC84214D566AB8AACFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","01162961AA289CC2513853FB31F0ACDB","0120F0B88A52100F82FEABC058B05CBF","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","015474DAE40565467683F60E7D6B6F73","01B3F14AE750544D9C9AD20F6B823CEC","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","015CE917BCF8AC73508BA0C75E562B75","01F42AADEAF7C0257B27DCBE24A2EAC0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","01957F28DB8A7D2E18F08AEA246A4DE3","01E323A0DF8F66AE1E221AE79A931716","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","01406565599DBF14F8047FC359DD66A6","017D5401D16B226E8EC07EDDA05439CD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","0189E78B2B76067BD8FD61F468E67EB1","01F59D383C499039CF4F238405E5F9C3","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix40i","","013F606C45AD191612B28EEF1CF6D7F9","0170C371C8D24158A7740555A3D0254E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix4700 ZOOM","","01B9EBFD77569CE29D8C032DA51DAD85","01BAD4B2C44FC0802AD488E3B5325405","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix4700 ZOOM","","01BF1089DB13798CF30FA0B6E186875D","01F21F74C1D6A089ACB1C6E39E624E84","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","01400713A3B10D105792E66D14AE5117","019624AE422BF7F88A92118F611DD996","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","016ADD09C60862FD6F0B9452EC614AD8","017B24E070670F38FE2761B505BF97C4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","01322A55C3F539232F9F48AC5DCA0072","01448D46E463836F6191E0916423365A","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","014D07412D807AFD47466BC3B2DCFD20","018571F62223F9611C5C82E33361D715","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","011F72189F16FB63160539354A378C18","01B57B0DB97AF420331DCB82522A4FC0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","018A502DE0262FC6DC8403269363DDAA","01931CC3681EB77CAE72911CE36B4E45","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","012840C2B1FCCDE2221D57CD894F5898","015F4AA8F8D3132E1FAF5DB940997359","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","017AAFD0B2845F41BAEC5521AF7E60BE","017CFBCEBE300D30A2D3DEAD73C002D0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","011BC0CF1B8F6C86A969EDB72AF27E24","01C994AFEBE3496186FC47707252ED30","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","0107F7F326C0D058D0FC463309D21C61","01FADF48C0D5EFBD05CA31667FBD79DE","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","01314A8C33DC01682816CD4AFE0E7B96","01FF7EAC06B780BA2C3FC2E5C66BFF3C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","0108B1AD56CEBAD5367B758EE1A63F18","017AC2BA97E4EDA4876AD2D0189C8F06","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","01927DE8CDA4A34FD981CA1E4BA453B3","01DC11991BE26BEBDC12355CA2257CB1","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","013FB5BDF7687EB994ECEB079C294E87","01D99CAE0607C1F221C77094F1740AFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","01F555C022AB19D485F62E5008BC0722","01FD0F0A93A98D049E8365862CBC20EB","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","01957F28DB8A7D2E18F08AEA246A4DE3","01E323A0DF8F66AE1E221AE79A931716","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6800 ZOOM","","016DFAF277299189E9A1092D09A50FFE","01E0D78873374FD205A32162BC32DC8E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","0126DAA916EC369FF8B1797B107C375F","01BAC7FF877B99FA2EFE0B0BC9A51F70","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","015533F5B111AD9E51590E42BF1CF318","018AE8620E8E1B95D1C8FD0338613321","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","0139C3609C7439A2677D0591BAA17CA0","017CE35D279F1A8B21080E0AE6C53CAD","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","0161149FCDDF874DEC4C938ED855AACC","01D3BAD36E511A7EAC1E7792840C74B5","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","019CAE8BAA4E0901A8132DB0460252E6","01D6C978E3AABF216D5CAACF54F63412","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","011A4E131AE6141F56175D11C0FF08F3","019C6D82AB51688BCFEF61E51C4C4B89","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","016ADD09C60862FD6F0B9452EC614AD8","017B24E070670F38FE2761B505BF97C4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","0132B6121FABF922EC108ED2299A4DF8","01B1D99243F7145290F94B0DDB143DF1","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","010591CD94BABC13B571DEDB9A76B196","01F0E53A1233A692F0D17371293F5342","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","013220D5B0D1F5FE11D1EF6E38C75F28","01FF04703C85EEC5589CB5AFC641A3B8","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","0145F26B95FF8AF15D1A7DC64355F872","016D15F943FA53E2F9E93A89A926B850","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","014F18BED4590DE7A0360B979D6C1EC0","016FC2A0F1990575069647DB51BF5D98","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","011A0B6A5E2CD8D701387C1B92673C51","01424F959EF392EE7D3A4B878C98E2B2","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","01C6EB2D5C761F5B0F41195E09A7C5E1","01EDB7106ED8CE9E8F7BD7F14EC44611","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","013848370A40F0D07134E5F819A35BAA","01AA5DCFB1E3186C06CED70E710F15C0","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","018A502DE0262FC6DC8403269363DDAA","01931CC3681EB77CAE72911CE36B4E45","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","01B9EBFD77569CE29D8C032DA51DAD85","01BAD4B2C44FC0802AD488E3B5325405","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","018892FB2CB156925F1964F3023E30B0","01C678B5E26E2424556FF4830079520C","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","017548B546BB0963B26B44611755A70D","01C985AE33A5F28E8BAB1D3ED75ED2A1","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","01DF82190E252AC7A11162C378E74D8F","01F6A274D8F0CBC5C82B7B67941C1C8E","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","0105CCB4C4B348AE594D640D47A029B7","014CE1370398E06CCA7E7635DA264D67","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","0125B5D4DAD31F73197E943B1FA80710","012B5C9C9DE2B306557D7F6F0ABBC33F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","0195EEA7C7FFC31874CB47F55A731440","01EA701641AE57738E101037BBDFBAC4","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","015BFED124534D3E92BBF2906045F273","0190E3CE4CB1DEB9C26685C28EE19669","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePix6900ZOOM","","01DB93351D55A5C6665EB31A9849CC52","01DE4A1BA4CE22FA6FB6A0A223F62D8F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePixS1Pro","","013FA8B0D97468662280A7C33A960DD7","014B6B976D0DF6E350AD535F4BEA101F","2x1","",""}, +{ ENUM_EDITOR_CAM,"FUJIFILM","FinePixS2Pro","","014D9616BBF7E071E910B93ABFB21C27","018734006FEA2D30B1C0A8F47A50FF74","2x1","",""}, +{ ENUM_EDITOR_CAM,"Hewlett-Packard","HP PhotoSmart C935 (V03.46)","","013A863D37AA0BE299071B31D3548CC5","01704C1F618115BDBB14771D54A2F822","2x2","",""}, +{ ENUM_EDITOR_CAM,"Hewlett-Packard","HP PhotoSmart R707 (V01.00)","","01205DF2136851A02AF30ADF84ABA11E","01205DF2136851A02AF30ADF84ABA11E","1x1","",""}, +{ ENUM_EDITOR_CAM,"Hewlett-Packard","HP PhotoSmart R707 (V01.00)","","0116133E48F8ECEDAB742EBF6BAC284F","01631DCA5E69DD1AD024465A7AA266E0","2x2","",""}, +{ ENUM_EDITOR_CAM,"Hewlett-Packard","HP PhotoSmart R707 (V01.00)","","0116133E48F8ECEDAB742EBF6BAC284F","01631DCA5E69DD1AD024465A7AA266E0","2x2","",""}, +{ ENUM_EDITOR_CAM,"Hewlett-Packard","HP PhotoSmart R707 (V01.00d)","","01205DF2136851A02AF30ADF84ABA11E","01205DF2136851A02AF30ADF84ABA11E","1x1","",""}, +{ ENUM_EDITOR_CAM,"Hewlett-Packard","HP PhotoSmart R707 (V01.00d)","","0116133E48F8ECEDAB742EBF6BAC284F","01631DCA5E69DD1AD024465A7AA266E0","2x2","",""}, +{ ENUM_EDITOR_CAM,"Hewlett-Packard","HP PhotoSmart R707 (V01.00d)","","0116133E48F8ECEDAB742EBF6BAC284F","01631DCA5E69DD1AD024465A7AA266E0","2x2","",""}, +{ ENUM_EDITOR_CAM,"Hewlett-Packard Company","HP PhotoSmart 315","","019199CA85730911299600A6D6C93A8B","01A383DA6BF7479D28B19AA0074FCF71","2x2","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","DiMAGE A200","","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","DiMAGE A200","","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","DiMAGE A200","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","DiMAGE A200","","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","DiMAGE A200","","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","DiMAGE A200","","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","DiMAGE A200","","01BD24596581D7A1535AFC805B0D60A2","01D47AD28A985151B705F90864369E2C","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","DiMAGE A200","","012876087A56CFCA7CFEC7D254AD88D7","01C6BBED27FF2B3D0E26E4009B66E38B","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","DiMAGE X1","","01605B36C27A91863BAE84A614E5A6E4","01F92B192C6A8A1E122F5E86BF586B21","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","DiMAGE Z5","","01574BED6DDCCAA822CC146FBC040AD3","01B58D1B77454977FCFDA55DD2461963","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","MAXXUM 5D","","01DC669AEC37FB0775F2E831266AF705","01DC669AEC37FB0775F2E831266AF705","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","MAXXUM 7D","","01DC669AEC37FB0775F2E831266AF705","01DC669AEC37FB0775F2E831266AF705","2x1","",""}, +{ ENUM_EDITOR_CAM,"KONICA MINOLTA","MAXXUM 7D","","010C6FB9C20DA535F1E85B7129DDA2C8","013F4575982733FD3AC4FC46459ECCBB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE A2","","0151D6730547B1732F1428518F41C9F6","0180267FA9A456EDEBBCEE6011CB1AA3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE A2","","011158B7475856AC9E477562F1AE68DE","01BEF7217A1C2BD460A84D645491083C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE Z2","","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE Z2","","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE Z2","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE Z2","","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE Z2","","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE Z2","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE Z2","","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE Z2","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"Konica Minolta Camera, Inc.","DiMAGE Z2","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"KYOCERA","FC-S3","","01CAE3D12075ADF4431488E73D758A9F","01CCD42AB84A46D8AC1AA4A68125A0DD","2x1","",""}, +{ ENUM_EDITOR_CAM,"LEICA","DIGILUX 2","","01A80023CDC86D90CD9F92AF55575482","01B2EADEE5D2C6887670513AD186ACB5","2x1","",""}, +{ ENUM_EDITOR_CAM,"LEICA","DIGILUX 2","","0131425FDE6F5E75E059E0550C40F980","015893E2971294882CF4EBDD82414044","2x1","",""}, +{ ENUM_EDITOR_CAM,"LEICA","DIGILUX 2","","01550C3F4489ABC67200B2CED3B02537","019D8ABB0272467D0F475E3CAB7B0978","2x1","",""}, +{ ENUM_EDITOR_CAM,"LEICA","DIGILUX 2","","0143E2834A286CF542FA2972C0478CC5","01D122D556870F2E0FBA1EB2B32EB550","2x1","",""}, +{ ENUM_EDITOR_CAM,"LEICA","DIGILUX 2","","016F84D0243E6A5B2CC1572E5CA4948E","01E13E8834276D783C8B088EA2E071B3","2x1","",""}, +{ ENUM_EDITOR_CAM,"LEICA","DIGILUX 2","","01146210F8F782499562164D98588DF7","01416268426EA8AA822C30E62CB99184","2x1","",""}, +{ ENUM_EDITOR_CAM,"LEICA","DIGILUX 2","","0120BC9F7FBDE71C9F7AF75F1271DE8E","0168E10B1946222765F3952D9095AA5E","2x1","",""}, +{ ENUM_EDITOR_CAM,"LEICA","DIGILUX 2","","01B02D6252495A2B9D08BBBBFEA0369C","01C44B75CC82D3AE8CA47C53C0367FA1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Leica Camera AG","M8 Digital Camera","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"Leica Camera AG","M8 Digital Camera","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"Leica Camera AG","M8 Digital Camera","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE 7Hi","","0151D6730547B1732F1428518F41C9F6","0180267FA9A456EDEBBCEE6011CB1AA3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE 7Hi","","011158B7475856AC9E477562F1AE68DE","01BEF7217A1C2BD460A84D645491083C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","Dimage EX","","014CBA7CF41D9FFFD11933E748C4AC6E","014CBA7CF41D9FFFD11933E748C4AC6E","1x2","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","Dimage EX","","014CBA7CF41D9FFFD11933E748C4AC6E","014CBA7CF41D9FFFD11933E748C4AC6E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE F100","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE F100","","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE F100","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE F100","","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE F100","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE F100","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE F100","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE F100","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE S304","","0184192EB1977CC6268343E6D3134191","01F0AFDCFFFAA57D4AD7C0227EE1B579","2x1","",""}, +{ ENUM_EDITOR_CAM,"Minolta Co., Ltd.","DiMAGE S304","","011158B7475856AC9E477562F1AE68DE","01BEF7217A1C2BD460A84D645491083C","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX L12","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P2","FINE","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","0135744CED39E5E2D1D49B97A23E3ED4","01F8F364323CCDD63F0F238CA9CDCEB1","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","013CB9B72088B06DE7931FD5B1C1A049","01AC143B735AABE226CF68DF7824E697","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","01574BED6DDCCAA822CC146FBC040AD3","01B58D1B77454977FCFDA55DD2461963","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","0144E26FB9BA003C2AF6A895D6E9CEAF","01B8E50677C21B70F8FC7A5FB398B8E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","013C26239BC3004EC0E1984F79A2E053","0159C4239254A897A6B1DA7E87648344","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","01533B110E20F3AC48999897834373DB","017CEDD8688FEFC6B8CAE0968021824A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","01B9E92D5CE414394429CCED76B89949","01C1C1593753CDBB62B9FD282846CFC7","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","0163462BFBD4A64917560469CB201547","01AC950CF614B011A45DBA57653F8034","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","01764A58772BF2B2118E21F2035E3536","01A192EB488B778995905709D072210A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","01B58550F0786C24AD24DD26F9915727","01BC5FB692DA4A34C6A7D5438989B2F7","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","015916E2168735FB572926A049B025DB","01F9ED4812F46CA42CB85C9371E94710","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","012706B411DF0C5629682D10083CB68A","0195F4BD0E07A4CDEF7400EC94BB5E75","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P3","FINE","0159C3DD4607B9ACB9BB3F5D7191891A","01901016622EBC2E42EE162000A13DE3","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","0134F2041810CE97DAAB408D5E71163C","01D831EF97768EF36E607FD5D85426FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","0123BAAA6DABBA3007987C5DD352F23A","0162F90EF60A9DB921AA87532AE23D68","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX P5000","FINE","012402B6D67E6105719FB11153F3C804","017E816CD8B40EB76B66F94A63ED38FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX S10","FINE","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX S10","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX S10","FINE","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX S10","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX S10","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX S10","FINE","0134F2041810CE97DAAB408D5E71163C","01D831EF97768EF36E607FD5D85426FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","COOLPIX S5","NORMAL","01625155BE84D00125E6E169DF4A2F65","01C54F8112BAF719522090C85C5E23F1","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","0134F2041810CE97DAAB408D5E71163C","01D831EF97768EF36E607FD5D85426FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","01BD24596581D7A1535AFC805B0D60A2","01D47AD28A985151B705F90864369E2C","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E2500","FINE","0155D875C95B74D0F3C5835A62516F48","01D38A25358EB7649A254E19F1D46600","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","FINE","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","FINE","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","FINE","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","FINE","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","FINE","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","NORMAL","013ACAC180247B71700A6278939D82A8","01C67F4B42859DDFF107237CE8D4B047","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","NORMAL","012876087A56CFCA7CFEC7D254AD88D7","01C6BBED27FF2B3D0E26E4009B66E38B","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","NORMAL","0120996088E68CF9F70A20A414D14AE6","013E3A5D329BBCB6AAF62F2E18FF8127","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E3100","NORMAL","017659A2F9A530359CB8725D32B5BE6C","01F863D3F47BE8F243BFF177EAC1EDB4","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4500","FINE","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4600","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","FINE","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","FINE","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","FINE","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","FINE","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","FINE","01625155BE84D00125E6E169DF4A2F65","01C54F8112BAF719522090C85C5E23F1","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","FINE","0100E9AA36415D0482E7AD68EAF372C3","012840F1B30DA4789A3345257EEB59C9","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","NORMAL","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","NORMAL","010176D29AD13D3FFAC14F0D3932B95E","01A05E3557B786BCF9267EAB607AEE7C","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E4800","NORMAL","016C4383FFABE35F063D8FCB331942C0","019DC7724B5425C464D28F2CF78F707E","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5000","FINE","012402B6D67E6105719FB11153F3C804","017E816CD8B40EB76B66F94A63ED38FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5200","FINE","01BC50262FBBFF6362759E0D0536794E","01F4661730D2DB6A83CF98B0179EB03E","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5200","FINE","013CB9B72088B06DE7931FD5B1C1A049","01AC143B735AABE226CF68DF7824E697","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5200","FINE","0144E26FB9BA003C2AF6A895D6E9CEAF","01B8E50677C21B70F8FC7A5FB398B8E4","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5200","FINE","013C26239BC3004EC0E1984F79A2E053","0159C4239254A897A6B1DA7E87648344","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5200","FINE","01533B110E20F3AC48999897834373DB","017CEDD8688FEFC6B8CAE0968021824A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5200","FINE","01B9E92D5CE414394429CCED76B89949","01C1C1593753CDBB62B9FD282846CFC7","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5200","FINE","0163462BFBD4A64917560469CB201547","01AC950CF614B011A45DBA57653F8034","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5200","FINE","0173F1E44DAC63C1C6803AEB21D68121","01A7CCF0C258A5AA0A372238704D3964","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5200","FINE","011ED6AAC481E84EB7DF7D6C55C35FDB","01F41F75DA85DCEE81F79C9BFD835249","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5400","FINE","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5400","FINE","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5400","FINE","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5400","FINE","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5400","FINE","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5400","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5400","FINE","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5400","FINE","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5400","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5400","FINE","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","01BD24596581D7A1535AFC805B0D60A2","01D47AD28A985151B705F90864369E2C","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","FINE","012402B6D67E6105719FB11153F3C804","017E816CD8B40EB76B66F94A63ED38FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E5700","RAW","012933907CE4B9D3C27E3E9D4D50BFD6","012933907CE4B9D3C27E3E9D4D50BFD6","1x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E775","FINE","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E775","FINE","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E775","FINE","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E775","FINE","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E775","FINE","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E775","FINE","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E775","FINE","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E775","FINE","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E775","FINE","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E775","FINE","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E7900","FINE","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E7900","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E7900","FINE","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E7900","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E7900","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E7900","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E7900","FINE","01BD24596581D7A1535AFC805B0D60A2","01D47AD28A985151B705F90864369E2C","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E7900","NORMAL","012876087A56CFCA7CFEC7D254AD88D7","01C6BBED27FF2B3D0E26E4009B66E38B","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E7900","NORMAL","01625155BE84D00125E6E169DF4A2F65","01C54F8112BAF719522090C85C5E23F1","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8400","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8400","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8400","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8400","FINE","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8700","FINE","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8800","EXTRA","0124AC8790656DF23F8070E2A880B501","016CC716D191DBD0BB21F1090184405D","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8800","FINE","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8800","FINE","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E8800","FINE","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E885","FINE","0165B3F1B409A4D8D5F2ADFFA970D3A5","0165B3F1B409A4D8D5F2ADFFA970D3A5","1x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E885","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E885","FINE","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E885","FINE","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E885","FINE","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E885","FINE","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E885","FINE","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E885","FINE","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E885","FINE","010F50672F14B4A88409AEC86E9DECE9","01C3B4FE62DF9A99F1CA8A5C17AC7711","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E885","FINE","0134F2041810CE97DAAB408D5E71163C","01D831EF97768EF36E607FD5D85426FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E995","FINE","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","E995","FINE","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D1","FINE","012A783CCEA06D57AFD2961BDCAB0D55","01C09FE954D02261612AB2F26E6C71AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D100","FINE","012F557E656D34C0A277B8470E9C4514","01E600E35F0A8CD0D9FE2D31B998D709","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D1H","FINE","012F557E656D34C0A277B8470E9C4514","01E600E35F0A8CD0D9FE2D31B998D709","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D1X","FINE","012D53B2BC8DEEC423C726A99B23EFFB","01342830C284AABC77AEBE2A43D20C2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D200","FINE","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D200","FINE","0103A1C445586D96DAFDC06542FD9968","016F5C933A7B31BA8437BDB3DE186E60","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D200","FINE","012F557E656D34C0A277B8470E9C4514","01E600E35F0A8CD0D9FE2D31B998D709","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D200","FINE","0119C6E2A0C136712CC82D09D3AD6D47","0165098BC665654C03482EBA8880EB6D","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D200","FINE","0120A81C1C6B471497B2C39DD796FE4D","015E09F77A7C92CAAEEEB1C80AE632CD","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D200","FINE","01292260CD87AAB3D2B0BC3DD8B4776C","016D5EE47029175386D08F8ED963988D","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D200","FINE","012D53B2BC8DEEC423C726A99B23EFFB","01342830C284AABC77AEBE2A43D20C2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D200","FINE","012A783CCEA06D57AFD2961BDCAB0D55","01C09FE954D02261612AB2F26E6C71AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D2H","FINE","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D2H","FINE","0103A1C445586D96DAFDC06542FD9968","016F5C933A7B31BA8437BDB3DE186E60","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D2H","FINE","012F557E656D34C0A277B8470E9C4514","01E600E35F0A8CD0D9FE2D31B998D709","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D2H","FINE","012D53B2BC8DEEC423C726A99B23EFFB","01342830C284AABC77AEBE2A43D20C2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D2X","FINE","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D2X","FINE","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D3","FINE","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D300","FINE","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40","FINE","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40","FINE","0103A1C445586D96DAFDC06542FD9968","016F5C933A7B31BA8437BDB3DE186E60","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40","FINE","012F557E656D34C0A277B8470E9C4514","01E600E35F0A8CD0D9FE2D31B998D709","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40","FINE","012D53B2BC8DEEC423C726A99B23EFFB","01342830C284AABC77AEBE2A43D20C2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40","FINE","0114ED88173433C4BF99F0569EA94D90","019E0FC5DA517712EF95A6C1789E61D0","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40","FINE","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40","FINE","01D13AFD01FF0B6EC46EA4081D25BB4D","01FF5BA518B453CC8F224A4C85505196","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40","FINE","010406665318412F7AE7B4533F75EB76","019363EF9F2ECA136B352D0C47E63CF1","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40X","FINE","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40X","FINE","0103A1C445586D96DAFDC06542FD9968","016F5C933A7B31BA8437BDB3DE186E60","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40X","FINE","014277D1DDB84253758F0F33BA54C7A2","0149438163B8EE0EE5F349FB365DC931","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40X","FINE","0120A81C1C6B471497B2C39DD796FE4D","015E09F77A7C92CAAEEEB1C80AE632CD","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40X","FINE","017211BC8C6161BCE36DB4E91A7A575F","018C775AA14027570ED51F477477AA84","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D40X","NORMAL","016316C80954E937BBAC5CCDC94A2ABF","01CA96F6D54E052A082B32260A1C363F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D50","FINE","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D50","FINE","0103A1C445586D96DAFDC06542FD9968","016F5C933A7B31BA8437BDB3DE186E60","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D50","FINE","012D53B2BC8DEEC423C726A99B23EFFB","01342830C284AABC77AEBE2A43D20C2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D50","FINE","01337EA310F3CF72C36B8AA6F7B5B042","014D068B9432D4C85F0F18F767DD368B","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D50","FINE","010CC33FB192BF2F6D9CB720360C5711","010F766EEF9BFC2D9829794E01D705EE","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D70","FINE","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D70","FINE","0103A1C445586D96DAFDC06542FD9968","016F5C933A7B31BA8437BDB3DE186E60","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D70","FINE","012D53B2BC8DEEC423C726A99B23EFFB","01342830C284AABC77AEBE2A43D20C2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D70s","FINE","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D80","FINE","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D80","FINE","0103A1C445586D96DAFDC06542FD9968","016F5C933A7B31BA8437BDB3DE186E60","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D80","FINE","012F557E656D34C0A277B8470E9C4514","01E600E35F0A8CD0D9FE2D31B998D709","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D80","FINE","014277D1DDB84253758F0F33BA54C7A2","0149438163B8EE0EE5F349FB365DC931","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D80","FINE","0119C6E2A0C136712CC82D09D3AD6D47","0165098BC665654C03482EBA8880EB6D","2x1","",""}, +{ ENUM_EDITOR_CAM,"NIKON","NIKON D80","FINE","0100CFEEBE21B71A129B9F5EE8B64138","013D4003F1AB977990BD3347854082B2","2x1","",""}, +{ ENUM_EDITOR_CAM,"Nokia","N73","","0155D875C95B74D0F3C5835A62516F48","01D38A25358EB7649A254E19F1D46600","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","C770UZ","","0123BAAA6DABBA3007987C5DD352F23A","0162F90EF60A9DB921AA87532AE23D68","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","C8080WZ","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","C8080WZ","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","C8080WZ","","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","C8080WZ","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","C8080WZ","","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","C8080WZ","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","C8080WZ","","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","C8080WZ","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","C8080WZ","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","E-1","","0187D263643F75F6F2CEC032888A2A45","019DD36729BF82BD2C25365F97212ABB","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","E-1","","011441CDDA3078A5D1C163B3B0FFE1C5","01282C395BF9B7D99C09B71B657DA58C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","E-1","","01D3C9C5AEB96A3600596D1BA8DCC518","01EFDDEBC09FEA0E4DEB1D6C1FFD424F","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","E-1","","01039FEC4F02406097182040B3440305","01C964F0D2B4E38AF575BA1091609062","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","E-1","","014C4539278C70EB2F211DC2F3761A69","01E71E41ABAAD4BA2E4ABF26D2C1B49F","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","E-1","","0113CB6928D4C44D92A529E750A1FAFD","011E8E0FD2B78118E39762BC0450B648","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","E-1","","012C6E06AB117D45972ED8E94A710463","01AFE9065B19F00A9A8B58AFEAC4B1C5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","E-1","","013BC890BA91666EE60A15E994089ADA","0187516AAE96E1CD50E9790E171BDD62","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","E-1","","0113C1943346397ACF92F02CD561001E","015782DCFB7A5EA4709477A956907A78","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","u30D,S410D,u410D","","014C1A2E427DED32AEA6FC03D0CA9B9C","01F48E8F658B3553CB6924724D135FE5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","u30D,S410D,u410D","","015B3D5A0AE6A4FF8E8DA3F6968F2C7B","01ADD0B7D7B22B46B4143A083E870995","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","u30D,S410D,u410D","","011B3C84FF1F9B0A5C68B6781CB9BC0A","01500507100E23146C1873FF72BAEEE0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","u30D,S410D,u410D","","0118DA9BA52EBDA65A929FBC36A5F758","01B2F246631E655B3A537725164E404B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS CORPORATION","u30D,S410D,u410D","","011E80B74A9DC355244D05164A4E66DF","0189751B3EF2F5EE04B8401B1E7D9CAA","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","C70Z,C7000Z","","0124AC8790656DF23F8070E2A880B501","016CC716D191DBD0BB21F1090184405D","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","C70Z,C7000Z","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","013CCB589498C2FA69ACF4F31643BCDF","016EA42E1A814C8939C7329EE6CD1252","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","013EB82FF071762D5AD4098D6AAF6D46","01AC121D8B78786E79DB87C9244D6F9A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","0112276B312502E900C3ED93B9354F72","0172D8A74BE9D7F5922EE1FB37F03545","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","015B3D5A0AE6A4FF8E8DA3F6968F2C7B","01ADD0B7D7B22B46B4143A083E870995","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","011B3C84FF1F9B0A5C68B6781CB9BC0A","01500507100E23146C1873FF72BAEEE0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","014E2DD4DD4202955FAC8AC87B8BFE84","0170631E9C7CC7A0A4FF1BDCF40CE12F","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","0118DA9BA52EBDA65A929FBC36A5F758","01B2F246631E655B3A537725164E404B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","011E80B74A9DC355244D05164A4E66DF","0189751B3EF2F5EE04B8401B1E7D9CAA","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","01285979F5130214FEF7EA318B17BE50","01828B0DFD8C4EB651271D2476EA41E1","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","013DED50ECAF324351680E680845F9E6","018E7EFB95EB0916122B1D3FF6C89439","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","0134A7CE8E7585FE1F943D0026551384","01C3C7E7FDAAC42F2237CCEE8D1B92C4","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-300","","01BEBBD5B162549AF3F1A738360943F6","01C4D090385B1E48E69F9367A8DCCBFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","018A97EF0C8856D9155F90A770C73067","01F68622EE6EF782C32ACC2CCF6A9907","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","012F3FD7C72F5D59DD9BA311EC3435A8","017969AD15F95DA89D67B4C0D349E522","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","0137BCC4D1028471DB9567121B8F5ACD","014181969D6481A1AFA279ACD0D4A59A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","013CCB589498C2FA69ACF4F31643BCDF","016EA42E1A814C8939C7329EE6CD1252","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","013EB82FF071762D5AD4098D6AAF6D46","01AC121D8B78786E79DB87C9244D6F9A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","014C1A2E427DED32AEA6FC03D0CA9B9C","01F48E8F658B3553CB6924724D135FE5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","015B3D5A0AE6A4FF8E8DA3F6968F2C7B","01ADD0B7D7B22B46B4143A083E870995","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","011B3C84FF1F9B0A5C68B6781CB9BC0A","01500507100E23146C1873FF72BAEEE0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","0183D94237D2A1462CF8884A2C58566B","01D2027538B7350A8CE3D2F9769B1071","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","0125417F733714AD6039B7B11F310C6B","016B64AD420E45930EB2675A84E11185","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","01285979F5130214FEF7EA318B17BE50","01828B0DFD8C4EB651271D2476EA41E1","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","0108E559ED0A4C154B52686E91A352F1","014BD89E61593032748E58BD71B5571C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","0134FDC769F9513D03884B184C3B8474","01913604EDD203CB3CB8EF8D9405CC78","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","015867A80D31E8FBB5FA03FA5F803379","01CA611F74EAD0841DB3817C6FD50452","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","01C5E85A4DBCD5E098F88522E4ACDEB3","01FF0DBEC5FE494C16A5BFBB0692551C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-330","","018C33F34E14965F901D87E2F5059D76","01A2863D209D69C318C2D791ED4A198B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","012F3FD7C72F5D59DD9BA311EC3435A8","017969AD15F95DA89D67B4C0D349E522","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","013CCB589498C2FA69ACF4F31643BCDF","016EA42E1A814C8939C7329EE6CD1252","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","01357CD849370F4A172BD943451FE6B4","01E09C16F2846C46555213A7AB078A89","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","0101668016F68201E1DE902B7B3BD405","017C85A24795A05A2D425BE9067F3A00","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","0101668016F68201E1DE902B7B3BD405","017C85A24795A05A2D425BE9067F3A00","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","017C1051F7D1293ED3C00F4184A341C2","01CA25316D7681E90F1842212F04B5D7","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","012A1EE3560CFC313F7C5D69E076BF72","013F7C8964CD3311BDA99091421C2891","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","01D77879D457F2AC7CE9764A5EABF214","01FFE2AA1D8016FBFC7567FAD3422E88","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","01206338DD44330548732C39C9898CB9","017ED526927F046AB92EEBAC17992610","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","01BEBBD5B162549AF3F1A738360943F6","01C4D090385B1E48E69F9367A8DCCBFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","01BEBBD5B162549AF3F1A738360943F6","01C4D090385B1E48E69F9367A8DCCBFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","01770BAFC79685F009A0606BD51581B1","01A02E2722752A1B6A5D21B38C8BE458","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","010D83AB9B456604FD5FC580CE3C2AD6","0188C66E91A12D1245AAD86FB4CA0591","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","01C5E85A4DBCD5E098F88522E4ACDEB3","01FF0DBEC5FE494C16A5BFBB0692551C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","01090555AE667AAFCC8690487D7ECFE7","0162B11FBE64420AD051A9204EC87256","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","013EEEE54844728CBFE64276B0896C4D","0163ADA62CF0747605CA7A66D8CE3BFF","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","015B622B91A46CAED9398308D57CE89D","0160F37925702D99E90C7D82F42F2A22","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","016282E23CADE6A86B7D47670FF06CB6","016476CE7011709FF925C9C788A84894","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-400","","010F11D5FAE835C77D3DD8BB379FA484","01397D113392AA4E41EC9521C95A62B6","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","013EB82FF071762D5AD4098D6AAF6D46","01AC121D8B78786E79DB87C9244D6F9A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","011706BAD6FC19A0F82C2DB0A76B9159","0166661BCE268A3178BFA5236FEF46F4","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","011706BAD6FC19A0F82C2DB0A76B9159","0166661BCE268A3178BFA5236FEF46F4","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","010590710A3F937EB8251BCE9037F8AB","012C9982B9ACBEA744752FD914C747E9","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","013DED50ECAF324351680E680845F9E6","018E7EFB95EB0916122B1D3FF6C89439","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","017975CE66AC80239C28B5632F819EBA","01F1467C227A678A990547B58196DF5A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","0101668016F68201E1DE902B7B3BD405","017C85A24795A05A2D425BE9067F3A00","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","0143053BDE5FE1EF59EACEEDC1024A96","01DDE10D1E165421147E3B9137B15516","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","017C1051F7D1293ED3C00F4184A341C2","01CA25316D7681E90F1842212F04B5D7","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","01B4A7A245551276F6519788823E2D60","01C5790C084B60EA44FCB4AC30219DE2","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","012A1EE3560CFC313F7C5D69E076BF72","013F7C8964CD3311BDA99091421C2891","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","01BEBBD5B162549AF3F1A738360943F6","01C4D090385B1E48E69F9367A8DCCBFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","0119884C6EF97B8C8F7C2D47001CB7B1","01BE372491F24996F0B2105E372D0E2A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","016A22859FB33004511CB5B91680D0DE","019E3A4A333DBA72C95F0949E49AD767","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","010B19115B7E61CE2DB4BDA480120DEA","01BF61EACB8030C7AACFDB5A3A2CA383","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-410","","010D0A1D6CEE42FC5EA16089A0E5146F","011CE222910EB9DE43A04A865A42EB52","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-500","","0118DA9BA52EBDA65A929FBC36A5F758","01B2F246631E655B3A537725164E404B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","E-510","","01D77879D457F2AC7CE9764A5EABF214","01FFE2AA1D8016FBFC7567FAD3422E88","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","FE240/X795","","0124AC8790656DF23F8070E2A880B501","016CC716D191DBD0BB21F1090184405D","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","0124AC8790656DF23F8070E2A880B501","016CC716D191DBD0BB21F1090184405D","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","011B20DC56FAA4C14E9139389EC259DE","016C1F26F78CB9D45A1D5F244123CAA1","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","01372CAD9800E68C2F9E94BC751B63C5","01B6EA567DCF6C0BED12D64BC86AA700","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","012402B6D67E6105719FB11153F3C804","017E816CD8B40EB76B66F94A63ED38FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","0178BAF59FA3A93E45912D1A3AB3DFA4","0183C6D8ADA5B5856CB6C4CEAFA87628","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","010176D29AD13D3FFAC14F0D3932B95E","01A05E3557B786BCF9267EAB607AEE7C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP310","","0100E9AA36415D0482E7AD68EAF372C3","012840F1B30DA4789A3345257EEB59C9","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP320","","010176D29AD13D3FFAC14F0D3932B95E","01A05E3557B786BCF9267EAB607AEE7C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP500UZ","","0124AC8790656DF23F8070E2A880B501","016CC716D191DBD0BB21F1090184405D","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP500UZ","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP500UZ","","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP500UZ","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP500UZ","","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP550UZ","","0124AC8790656DF23F8070E2A880B501","016CC716D191DBD0BB21F1090184405D","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP550UZ","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP550UZ","","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP550UZ","","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP550UZ","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP550UZ","","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","SP550UZ","","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","012F3FD7C72F5D59DD9BA311EC3435A8","017969AD15F95DA89D67B4C0D349E522","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","0137BCC4D1028471DB9567121B8F5ACD","014181969D6481A1AFA279ACD0D4A59A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","013EB82FF071762D5AD4098D6AAF6D46","01AC121D8B78786E79DB87C9244D6F9A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","0112276B312502E900C3ED93B9354F72","0172D8A74BE9D7F5922EE1FB37F03545","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","015B3D5A0AE6A4FF8E8DA3F6968F2C7B","01ADD0B7D7B22B46B4143A083E870995","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","011B3C84FF1F9B0A5C68B6781CB9BC0A","01500507100E23146C1873FF72BAEEE0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","014E2DD4DD4202955FAC8AC87B8BFE84","0170631E9C7CC7A0A4FF1BDCF40CE12F","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","0107FCA83F17FA8F5DE5DE87C97ACB66","01161EE3B094F778304EE8AEB19C0F7B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","018E60C998DDC4CFE972FB9D6819E93E","018EBE4A99EFD4F4C02B09C7AA308353","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","01C274A79362E9D34711FC55D55E432A","01C2DDB7BB8068B253FE087C9B6DA9F1","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","013E5D266F98E0E4BA51DEEB63949B4C","01935D9820EE9DF4858BDDEC7A36F27A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","01592ABB5E932D863CF0B8D4344F4A8D","01CFAE5113F841AE9D212DBED3A37CE2","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","017C1051F7D1293ED3C00F4184A341C2","01CA25316D7681E90F1842212F04B5D7","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","0101092454C6BA70F329E8323BA37A62","01D3F187A0B029D75287067CC329CBEB","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","0171FDB6AA66F1C1C71E52F49A6501AA","019B93D2807091FEA62161B7F3B2E1D0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","01BEBBD5B162549AF3F1A738360943F6","01C4D090385B1E48E69F9367A8DCCBFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","0185B6CAB5D7A16084F11BAA56C09541","01FF11A44402FB7E615760C82130FE07","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","01770BAFC79685F009A0606BD51581B1","01A02E2722752A1B6A5D21B38C8BE458","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","0124A376C93414B16308422029BE7EB2","016711181F86C56184198107A8B1B2CD","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","01379C8FD2662AEAAD76CB1511BB084E","019EEAD0E94E444AE0CFCFD8FF684314","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","01784AF43BDB59E131697740D9F749C9","01C5A7E5F1316C4FC792054221B3AC36","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","0111F4F3A18657DCC662CD8EB1FE4027","013D6612D6D58DA0317FE1F808207124","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","018C33F34E14965F901D87E2F5059D76","01A2863D209D69C318C2D791ED4A198B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniD,Stylus V","","015B7616FEF5459D7774B52FF73427C9","016EC1CD6EC54DC6BA7A7F51B9DCDFEC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u-miniS,StylusVS","shq","013EB82FF071762D5AD4098D6AAF6D46","01AC121D8B78786E79DB87C9244D6F9A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","u1000/S1000","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","013EB82FF071762D5AD4098D6AAF6D46","01AC121D8B78786E79DB87C9244D6F9A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","0118DA9BA52EBDA65A929FBC36A5F758","01B2F246631E655B3A537725164E404B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","011E80B74A9DC355244D05164A4E66DF","0189751B3EF2F5EE04B8401B1E7D9CAA","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","0145CCFB3CFD657AA47D68857C73808B","0187CDB41EB378C587B76E9CD566D8C0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","0140475FCF05578FC1534AE1012A3E6C","0146DF88F666D7A82A0C6993869E5D19","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","0108E559ED0A4C154B52686E91A352F1","014BD89E61593032748E58BD71B5571C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","01357CD849370F4A172BD943451FE6B4","01E09C16F2846C46555213A7AB078A89","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","01B4A7A245551276F6519788823E2D60","01C5790C084B60EA44FCB4AC30219DE2","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","012A1EE3560CFC313F7C5D69E076BF72","013F7C8964CD3311BDA99091421C2891","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","01206338DD44330548732C39C9898CB9","017ED526927F046AB92EEBAC17992610","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","01078E5F33C358C11D6FC20E07947670","01EF9D257F85D6DF20DCEEB140CEED51","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","0171FDB6AA66F1C1C71E52F49A6501AA","019B93D2807091FEA62161B7F3B2E1D0","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","01BEBBD5B162549AF3F1A738360943F6","01C4D090385B1E48E69F9367A8DCCBFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","0116B512F11CB253BE375B6F9D1A4DF1","01BEC1DC1E365603C9A1F34A5203AB1A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","0106565AA8AF8C8B175E2099D8554A55","01E0BA388CD18FF5EE51C8A0B4B9BC8B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","0148E4615DD64A838FAFB981A86B933F","01B8633F273963FCAA0BB07A1E3D0806","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","01770BAFC79685F009A0606BD51581B1","01A02E2722752A1B6A5D21B38C8BE458","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","013B9A18346B48620A5B169E05D2145A","01E39C266F548F608B50BE9F45058DEC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","010D7E6A57E24111A336CFCFAE264013","018DCEB3BF68D1005ED718D23FCADF0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","0150771598CCA9FA1386C8CF7CAAE2C8","01EDAFDF283C0E3E5329BECC28481DEA","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","01934C08AE04B95306C45924D92EDB7A","01F06F8AC2AF95397733F5D7FC833D60","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","01784AF43BDB59E131697740D9F749C9","01C5A7E5F1316C4FC792054221B3AC36","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","012F5BEAA2D4FFCFF102170F7B20EB0C","01FFD76F9A7419BFA21F6F377E1B9AF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","013AFFABCB152E7A0BD9109F12B9615E","015D476129065AC43A136F8E534FC24A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS IMAGING CORP.","uD800,S800","","017CC9274A8BBAFF7C6C947CA346C10D","01FEA10B14C47C75407F3A4D09A7D902","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","010F50672F14B4A88409AEC86E9DECE9","01C3B4FE62DF9A99F1CA8A5C17AC7711","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","0134F2041810CE97DAAB408D5E71163C","01D831EF97768EF36E607FD5D85426FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","01BD24596581D7A1535AFC805B0D60A2","01D47AD28A985151B705F90864369E2C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","0123BAAA6DABBA3007987C5DD352F23A","0162F90EF60A9DB921AA87532AE23D68","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","01387A14AF75DC6963F040C1239B7DED","0196457BE1E9E30F00715A3DDE8B160C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","012402B6D67E6105719FB11153F3C804","017E816CD8B40EB76B66F94A63ED38FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","01AC139E31B941CA0F2C5B5A0BFCDFC0","01F3D5B0FBE08EC4AAE9E1E4238BF215","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","0155D875C95B74D0F3C5835A62516F48","01D38A25358EB7649A254E19F1D46600","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","012876087A56CFCA7CFEC7D254AD88D7","01C6BBED27FF2B3D0E26E4009B66E38B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","018F43694F4E9A49C24613CE0DB777A1","01BFD6DFF74A169EDA4F585691B1C832","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","01625155BE84D00125E6E169DF4A2F65","01C54F8112BAF719522090C85C5E23F1","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","010300D2A3C0CEB8216F7C59B96AFB16","014F706DC17A4AF11117D50B414F348C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","0175BAF3251040E0EFB2930B73328E7F","01DC499064BA9264D591FDE9071DFD89","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","010176D29AD13D3FFAC14F0D3932B95E","01A05E3557B786BCF9267EAB607AEE7C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C2000Z","","01851AAA60C021C5E9C1235B2509BD09","01D126D2AA41BC051273FED404386FCF","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","0124AC8790656DF23F8070E2A880B501","016CC716D191DBD0BB21F1090184405D","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","018AD79CC6A9406F7CEA6B76F46AED2D","018B0C44364D83741C0A27927E2FAC1F","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","010F50672F14B4A88409AEC86E9DECE9","01C3B4FE62DF9A99F1CA8A5C17AC7711","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","01387A14AF75DC6963F040C1239B7DED","0196457BE1E9E30F00715A3DDE8B160C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","01AC139E31B941CA0F2C5B5A0BFCDFC0","01F3D5B0FBE08EC4AAE9E1E4238BF215","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","0155D875C95B74D0F3C5835A62516F48","01D38A25358EB7649A254E19F1D46600","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","010300D2A3C0CEB8216F7C59B96AFB16","014F706DC17A4AF11117D50B414F348C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","01625155BE84D00125E6E169DF4A2F65","01C54F8112BAF719522090C85C5E23F1","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C3040Z","","0138A8D4ECE59F41D2EB9AF5168B6675","01CA9A809F737BA668C16DDE52E74092","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C40Z,D40Z","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C40Z,D40Z","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C40Z,D40Z","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C40Z,D40Z","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C40Z,D40Z","","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C40Z,D40Z","","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C40Z,D40Z","","01387A14AF75DC6963F040C1239B7DED","0196457BE1E9E30F00715A3DDE8B160C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C40Z,D40Z","","0123BAAA6DABBA3007987C5DD352F23A","0162F90EF60A9DB921AA87532AE23D68","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C40Z,D40Z","","010300D2A3C0CEB8216F7C59B96AFB16","014F706DC17A4AF11117D50B414F348C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C40Z,D40Z","","0175BAF3251040E0EFB2930B73328E7F","01DC499064BA9264D591FDE9071DFD89","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","0165B3F1B409A4D8D5F2ADFFA970D3A5","0165B3F1B409A4D8D5F2ADFFA970D3A5","1x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","010F50672F14B4A88409AEC86E9DECE9","01C3B4FE62DF9A99F1CA8A5C17AC7711","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","01AC139E31B941CA0F2C5B5A0BFCDFC0","01F3D5B0FBE08EC4AAE9E1E4238BF215","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","012876087A56CFCA7CFEC7D254AD88D7","01C6BBED27FF2B3D0E26E4009B66E38B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","0178BAF59FA3A93E45912D1A3AB3DFA4","0183C6D8ADA5B5856CB6C4CEAFA87628","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","018F43694F4E9A49C24613CE0DB777A1","01BFD6DFF74A169EDA4F585691B1C832","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","0175BAF3251040E0EFB2930B73328E7F","01DC499064BA9264D591FDE9071DFD89","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","0138A8D4ECE59F41D2EB9AF5168B6675","01CA9A809F737BA668C16DDE52E74092","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","0120996088E68CF9F70A20A414D14AE6","013E3A5D329BBCB6AAF62F2E18FF8127","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","01786593B7990A17B0D81B6DF749470E","01DF37EBC825495EA04E9B311B77D309","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","01403088D08B8A2712CA648846151E07","01BABD681F45ABBA1BDCF41992781236","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","017659A2F9A530359CB8725D32B5BE6C","01F863D3F47BE8F243BFF177EAC1EDB4","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C700UZ","","016A9F39EDF7E9DCAF8BE822C2266077","01F0A31D3842CFD4B7E09178F141E14B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","C740UZ","","01851AAA60C021C5E9C1235B2509BD09","01D126D2AA41BC051273FED404386FCF","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","0128413C51CDA1AB1E7E157A61FD358B","01689B8D30387E1072A93C36BFF81DEC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","0117BDDBF4C4D5F2BD473867C268B992","01D67415634AF487A644D544967B5229","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","01D72E86D9A71586407B16573061BE82","01FEE178671C154C42FD7275DA10C8B2","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","01CC5054634686211425F9313789330E","01D7C1596EF390EC64D371F4BBEED4CA","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","0190F389112850389D210F01DAC49ECC","01973B91796499966833E12D9F47D6F8","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","011950D41F42D21E97D50473114BE0D7","01B93C2C9074C39E346E44112D11515B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","01ABAB9098FBA1D73C384C3A89D54D36","01D88924E59DBFEDA69DB6878301F4AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","015D76974F1AAEE7318546F8817042CF","0192A37A39ECDB4EE3204E56E17613AF","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","01ED3E764331690417CFB0B6760E3CF9","01FECF64497ADED556DB6690691B2F04","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","01379268F9FBE19C81CC00CD70598366","01F07D7BAE71080B3DD911AD4E97F511","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","0182FC9E34E7EF518A5E521A73CB9150","01963E3DBE697A70C122A3973E90CB59","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","01B0F9A7C7E350A1B701261420EC769E","01CDE58F50CD625612AE7FD49FB98473","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","0181E0FA93A7C8FFBFAED0AB0A682EDF","01F73ED16F0BD0F7C73BD44D4839ED4D","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","015B0307770D08EE38047293E49F7B95","018B755668E420798B44C06DEEF7A0B3","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","016EA0E7A46C136F2ABA8A0E865CBC21","01A15B41B7F74EB6449B8F8319248967","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","017DF1BD8B33D55134DD3E46656ED053","01A093ACDCA80186F422983344D97150","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","0139D8C8782FE5A30C4C88D9FCAE8181","01CC38B6FCB0DEA0A013C4D914641E40","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","0164182DB61A14805CAA4F70E0415E53","0173FB6497370EE93BAE2DCDEE79E8AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","017858AF71B9A633FD70AEAB659B3300","01DACE21BB46E12DD3BC4727CD8D8210","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","01069AD821B0103E56E421C38B5B2CD6","011497B7CD73D9D25DC361F5A34BDEB9","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","01794DB02469022B32443CA60688C148","01F86D4ECED7E890C68BE9D10E56274F","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","017C0F23D27AAEAD889A664DC26AD545","01E97DB27309D1AB029F5BFF06FB3B75","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","016398A5D03E9FA5A5974B9EABF113B7","01ADC2FDBC49253897195A5B8165F49C","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","019444DDF02185A1932271ABB5EA43C2","01F912E034059159BF429BDBA8B7F988","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-10","","01C61A250680030358EF5227D70D1087","01E9E47BD2E94A56F17ADC1CD1D859D8","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","0108C44AD56089B4CD27462EF0E9E40B","01AD4F667053A6FBA82E3D2B0BC4A566","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","0128413C51CDA1AB1E7E157A61FD358B","01689B8D30387E1072A93C36BFF81DEC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","0117BDDBF4C4D5F2BD473867C268B992","01D67415634AF487A644D544967B5229","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","01CC5054634686211425F9313789330E","01D7C1596EF390EC64D371F4BBEED4CA","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","0190F389112850389D210F01DAC49ECC","01973B91796499966833E12D9F47D6F8","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","011950D41F42D21E97D50473114BE0D7","01B93C2C9074C39E346E44112D11515B","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","015D76974F1AAEE7318546F8817042CF","0192A37A39ECDB4EE3204E56E17613AF","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","01ED3E764331690417CFB0B6760E3CF9","01FECF64497ADED556DB6690691B2F04","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","01379268F9FBE19C81CC00CD70598366","01F07D7BAE71080B3DD911AD4E97F511","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","0182FC9E34E7EF518A5E521A73CB9150","01963E3DBE697A70C122A3973E90CB59","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","0145C214D721F708E0D4B76BCF1D4AAD","01EDD76E1D040E754652CDF54F4C9BA1","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","01590C75F0867760D72D155295E96425","01E27BBE5161A0E68048D0A194534D74","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","016EE1A32255BAAB84FC58ED3890502C","01A5D351507261639CE450B127B1475A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","E-20,E-20N,E-20P","","01A83536481A79EC40C50C791F1E4220","01FABFD178D6926A37E77FEA3B1A0C37","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","014A1C89C73A29E281A843479E0D8270","01FF143D8822FDACA79A68AA47A453B1","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","0113C1943346397ACF92F02CD561001E","015782DCFB7A5EA4709477A956907A78","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","01065AFF4925691D6682020FE0351289","012B7A93E0F5D34E6922626FE3FDD0B5","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","013C7B66311D04188EBDC1B1F80C5CD1","01607C40C6F84F1EC927665858404823","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","01992C72E3F2F6CE2A20CD738B766D9A","019DB237D8FE714224C756060548A8F9","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","012221FB6D96695F14C7B12D99EA4E73","01D1729230BA2DF3602BE06F32BA0D5A","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","0153A4E107A161D4EE844C4AC1E91AC0","01C2B103DC657341EB06FDADCFCFC1FC","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","01732E8C7483DF76164E47EA5F45C18C","01EB3595DF117750F757BF015FBCC9D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","015EA26684DB82F5A340C79D9B28B646","01EE83B10EFF28C203E3B706416A5799","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","018C1CCB93439920B33C7AD4CA75C7BE","018D1DB0D777A5B623FA247CC2E649F2","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","010A73C6212633C5BC7D1A24AD3F64C6","011227482A91BAC69AE87BA6F0494F96","2x1","",""}, +{ ENUM_EDITOR_CAM,"OLYMPUS OPTICAL CO.,LTD","X-2,C-50Z","","01336A7453832F56E158AFBA35CCCE6A","0194012593362B6F226D47AEC452FA45","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","0107DF00A3B3CC0618E1780640E7C637","01F909EF7883AFD92617F844C239E03F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","013C5D9A83F33B70EDD0EF4B175E4734","017B0CF969CF5E15D58B94F64DB0EDC1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","0138462F3B064F5A2D2735BCBD535472","01390D38EF6A011B05DD7B36A364A3BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","013DC48B707181D2512BD55D72EEBCF0","01DEFE52F8A7964EC92CAA476C1081C5","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","018E071D7C6333CCA941AF3F86C4B040","01F1BC59628C27605A47B1DD4DAFBD2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","01C91F94EE93568591EB96DA028179AF","01E1BD28E783DDA36EE9EF9124CB40AE","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","0122D115001A0F43E9F12CAF15140921","019590EE31CB1F94A5E95BB6D8A4D15B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","01CFFACD05293AA908AF4316230788E9","01DD5B33181B223F8AB26AEBDC6E8E84","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","01198346965EB20066F6D7B6831E9C95","013E95521791B5B70228DE9E899234B3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","013161476484359DD4D9CF9409A8D7CD","014BF262F2540BDB3D5AF1ADF46B1BDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","014D667B6CED05284B47E4C66FF4C609","015FC89EA6DB6E3DD7F8D77D7FA4480F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","0104627D31E6BCB51040B2A47F908518","01C451DC68A972D099D1DAD1E315CF22","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX01","","0177E3A26E664A95E6BAE877F3FA8E8B","01D3F65CE838517AA4ED750EDB8521D1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX7","","0123BC6810721B28DDD0F4F3DCAA6277","019D8B7008873790DEF7D64A73B50A81","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX7","","0192E3B46CA4AA3BB9DEF414E8A36D12","01AD7C7F5EA54145C6376424C02FDCC1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX7","","011FA861380627C4E0D18BB1BE206178","0146D98747195222CB35EE2DA5F9BC3E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX7","","010F3953A08A959619F07E0BB01C8BF5","018C5063107B6A1357AC6031F8B67D42","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX7","","0116E95EEDDF8CF3518E815BA203C615","017C4ABD754ABA2830C2F2ED1FE33B8C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX7","","01693AAEEDEEA2DAF003F0981E32DB6D","01F2AD7A47E5E5458D3391E48F0862BC","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX7","","011F65BAC64F587C94E637D842323019","01310F546088EDA9A94120D7EC70423B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX7","","018141C2FC543690C76BA6C90CD1E379","01A5531E48945A567D9DDED506CAD64D","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","013DC48B707181D2512BD55D72EEBCF0","01DEFE52F8A7964EC92CAA476C1081C5","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","018E071D7C6333CCA941AF3F86C4B040","01F1BC59628C27605A47B1DD4DAFBD2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","0186B5A9C29AD0C22B08617BAAF8B2F3","01AADE46228BCCA9AAC3BE09EF986623","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","0122D115001A0F43E9F12CAF15140921","019590EE31CB1F94A5E95BB6D8A4D15B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","01CFFACD05293AA908AF4316230788E9","01DD5B33181B223F8AB26AEBDC6E8E84","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","014145865FE9A3D75612AD65CD0BF9C3","01680307DDD5C5366799674555B5BD2D","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","013EF0E302E6BBE0C2AA0D9D85AF7990","014B2BC31CF89A8DC2B2C962A8CF82A6","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","01198346965EB20066F6D7B6831E9C95","013E95521791B5B70228DE9E899234B3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","013161476484359DD4D9CF9409A8D7CD","014BF262F2540BDB3D5AF1ADF46B1BDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","014D667B6CED05284B47E4C66FF4C609","015FC89EA6DB6E3DD7F8D77D7FA4480F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","011D37296ED90033C19351777AAB0B38","01B2922FE979931BFD2586AB0267B31B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","011377E8CCEBED5DFA86FC8ACF2295C2","01ADCA18F8F8F4DF33ACD56F393A645A","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FX9","","01E4CF70D3F4FC5894F625131F820CF3","01F9F607F691635857AE5C87E726A252","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","0123BC6810721B28DDD0F4F3DCAA6277","019D8B7008873790DEF7D64A73B50A81","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","0192E3B46CA4AA3BB9DEF414E8A36D12","01AD7C7F5EA54145C6376424C02FDCC1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","011FA861380627C4E0D18BB1BE206178","0146D98747195222CB35EE2DA5F9BC3E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","011030DDD6A189F70FE3BA4CEDA10C0E","018FEC9B7763A5FBF41B927640234A6F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","01A78DD347695335597BFB27B18CEEE2","01F449D1310A4BCC04588AA07DC6F457","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","010F3953A08A959619F07E0BB01C8BF5","018C5063107B6A1357AC6031F8B67D42","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","012E2FD711E336593E1E6661771EFF20","01BE5250860C140A34674091C55CCD0E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","0116E95EEDDF8CF3518E815BA203C615","017C4ABD754ABA2830C2F2ED1FE33B8C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","011F65BAC64F587C94E637D842323019","01310F546088EDA9A94120D7EC70423B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","0123684778F7F6D955AC459FBD1120CA","01BFD2C50315AD2DAE445AC96459B822","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","017E4C77A22222A6F09A53D932091662","01B7487CFD91880BA0489F67866571DF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","0114007765A43A934A4DDC8A61E1562A","014BE2D26B383E99C16FF976EA5DFFB0","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","0139D09DC9BF32F37522D4ECF507D39D","01D444AE0369695BF6F8AE7357012B48","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ20","","011CACC20EDB7B88165442D9C282E155","01D53767A9769BEFDD0487B8CED92BD6","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","01146210F8F782499562164D98588DF7","01416268426EA8AA822C30E62CB99184","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","01B02D6252495A2B9D08BBBBFEA0369C","01C44B75CC82D3AE8CA47C53C0367FA1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","014B3173926CDBA56C1E13038A53D12A","01CBA0981E28CD632712D268FB362E38","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","01A025B984771F2A9EAE24823D6AB63B","01DA5E9CB2E45878BD8FC0BE2F4DB4E2","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","0153A205814CDE04D1706E59E8013027","01B0C46A0378B6F005FB98832273680E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","011B7750DE6D43BDE2BC3D14BBAD7414","013FA3066503A7D23032FC9D0987D322","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","011FA861380627C4E0D18BB1BE206178","0146D98747195222CB35EE2DA5F9BC3E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","01A78DD347695335597BFB27B18CEEE2","01F449D1310A4BCC04588AA07DC6F457","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","019653C54EB7D48750695B068423FF76","01B0180D7EED5FE5736800864F71B097","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","012E2FD711E336593E1E6661771EFF20","01BE5250860C140A34674091C55CCD0E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","0116E95EEDDF8CF3518E815BA203C615","017C4ABD754ABA2830C2F2ED1FE33B8C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","012A2AD50650A8B9646E8D9ABD3BFA88","018F2017595154F0F6593A89BC701E3F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","0123684778F7F6D955AC459FBD1120CA","01BFD2C50315AD2DAE445AC96459B822","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ3","","018141C2FC543690C76BA6C90CD1E379","01A5531E48945A567D9DDED506CAD64D","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ30","","01B02D6252495A2B9D08BBBBFEA0369C","01C44B75CC82D3AE8CA47C53C0367FA1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ30","","011B7750DE6D43BDE2BC3D14BBAD7414","013FA3066503A7D23032FC9D0987D322","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ30","","0123BC6810721B28DDD0F4F3DCAA6277","019D8B7008873790DEF7D64A73B50A81","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ30","","011030DDD6A189F70FE3BA4CEDA10C0E","018FEC9B7763A5FBF41B927640234A6F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ30","","014BF769355E127A5014D2B5C2238F0B","01BCA265FDE2DDF5E1AF22F54434D125","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ30","","014BA11590681A399B60019E89D95551","0196E966C2B3709B7836B021787B3EAA","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ30","","010F3953A08A959619F07E0BB01C8BF5","018C5063107B6A1357AC6031F8B67D42","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ30","","012E2FD711E336593E1E6661771EFF20","01BE5250860C140A34674091C55CCD0E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ30","","0116E95EEDDF8CF3518E815BA203C615","017C4ABD754ABA2830C2F2ED1FE33B8C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ30","","011F65BAC64F587C94E637D842323019","01310F546088EDA9A94120D7EC70423B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ5","","0123BC6810721B28DDD0F4F3DCAA6277","019D8B7008873790DEF7D64A73B50A81","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ5","","011FA861380627C4E0D18BB1BE206178","0146D98747195222CB35EE2DA5F9BC3E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ5","","01A78DD347695335597BFB27B18CEEE2","01F449D1310A4BCC04588AA07DC6F457","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ5","","019653C54EB7D48750695B068423FF76","01B0180D7EED5FE5736800864F71B097","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ5","","010F3953A08A959619F07E0BB01C8BF5","018C5063107B6A1357AC6031F8B67D42","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ5","","012E2FD711E336593E1E6661771EFF20","01BE5250860C140A34674091C55CCD0E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ5","","01AF869E9C11B22A86704F305C873B54","01C9C269CF6A8DC6FB6E7690FBD22450","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ5","","0139D09DC9BF32F37522D4ECF507D39D","01D444AE0369695BF6F8AE7357012B48","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ50","high","0138462F3B064F5A2D2735BCBD535472","01390D38EF6A011B05DD7B36A364A3BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ7","","01146210F8F782499562164D98588DF7","01416268426EA8AA822C30E62CB99184","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ7","","011B7750DE6D43BDE2BC3D14BBAD7414","013FA3066503A7D23032FC9D0987D322","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ7","","0123BC6810721B28DDD0F4F3DCAA6277","019D8B7008873790DEF7D64A73B50A81","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ7","","0192E3B46CA4AA3BB9DEF414E8A36D12","01AD7C7F5EA54145C6376424C02FDCC1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ7","","01A78DD347695335597BFB27B18CEEE2","01F449D1310A4BCC04588AA07DC6F457","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ7","","014BF769355E127A5014D2B5C2238F0B","01BCA265FDE2DDF5E1AF22F54434D125","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ7","","010F3953A08A959619F07E0BB01C8BF5","018C5063107B6A1357AC6031F8B67D42","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ7","","0116E95EEDDF8CF3518E815BA203C615","017C4ABD754ABA2830C2F2ED1FE33B8C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ7","","012A2AD50650A8B9646E8D9ABD3BFA88","018F2017595154F0F6593A89BC701E3F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ7","","0101829004C47D7E3F6B71F56536BA02","018AAE1A612B247686EFDA55966E7683","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","01146210F8F782499562164D98588DF7","01416268426EA8AA822C30E62CB99184","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","0120BC9F7FBDE71C9F7AF75F1271DE8E","0168E10B1946222765F3952D9095AA5E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","01AE77654BD30AB3892163E998A7CA6F","01CC4AC83792BB0CEEE11B2F773B71B5","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","0191A7EB3030A81F80E2059E5295F271","01D17DB6368FB3C5EB068CBD52B219AA","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","01B02D6252495A2B9D08BBBBFEA0369C","01C44B75CC82D3AE8CA47C53C0367FA1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","0168D26319E840447DE0FEB6916D097B","0198F32FC612493C4B8E63A36538B44E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","014B3173926CDBA56C1E13038A53D12A","01CBA0981E28CD632712D268FB362E38","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","014A1828D4C5D5228632ED107E5E372E","01F277EEA6356BA671EA2224C96CE68D","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","01A025B984771F2A9EAE24823D6AB63B","01DA5E9CB2E45878BD8FC0BE2F4DB4E2","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","0153A205814CDE04D1706E59E8013027","01B0C46A0378B6F005FB98832273680E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","011B7750DE6D43BDE2BC3D14BBAD7414","013FA3066503A7D23032FC9D0987D322","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","0123BC6810721B28DDD0F4F3DCAA6277","019D8B7008873790DEF7D64A73B50A81","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","0192E3B46CA4AA3BB9DEF414E8A36D12","01AD7C7F5EA54145C6376424C02FDCC1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","01A78DD347695335597BFB27B18CEEE2","01F449D1310A4BCC04588AA07DC6F457","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","014BF769355E127A5014D2B5C2238F0B","01BCA265FDE2DDF5E1AF22F54434D125","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","014BA11590681A399B60019E89D95551","0196E966C2B3709B7836B021787B3EAA","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","01D9CAAD4A2D7DC83A6BADAFD0C00425","01F0CD875838DE7997852185F2378B4F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-FZ8","","0101829004C47D7E3F6B71F56536BA02","018AAE1A612B247686EFDA55966E7683","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-L1","","0169FCFCCC4D6CE6959541DC098BE408","01F9C0838D8AFDB904555F93BFAF238C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","01B02D6252495A2B9D08BBBBFEA0369C","01C44B75CC82D3AE8CA47C53C0367FA1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","011B7750DE6D43BDE2BC3D14BBAD7414","013FA3066503A7D23032FC9D0987D322","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","0192E3B46CA4AA3BB9DEF414E8A36D12","01AD7C7F5EA54145C6376424C02FDCC1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","011FA861380627C4E0D18BB1BE206178","0146D98747195222CB35EE2DA5F9BC3E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","011030DDD6A189F70FE3BA4CEDA10C0E","018FEC9B7763A5FBF41B927640234A6F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","014BF769355E127A5014D2B5C2238F0B","01BCA265FDE2DDF5E1AF22F54434D125","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","010F3953A08A959619F07E0BB01C8BF5","018C5063107B6A1357AC6031F8B67D42","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","012A2AD50650A8B9646E8D9ABD3BFA88","018F2017595154F0F6593A89BC701E3F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","018141C2FC543690C76BA6C90CD1E379","01A5531E48945A567D9DDED506CAD64D","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","0114007765A43A934A4DDC8A61E1562A","014BE2D26B383E99C16FF976EA5DFFB0","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","01A03C8460297BF48BC8FEB4FC637382","01A63CAA9BF37144D54CD5FEAB904CA3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX1","","013A0E62CC533A8F06C9241B1663A995","018C97A3CA4FA22079CC8A732C2EDFCB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","0107DF00A3B3CC0618E1780640E7C637","01F909EF7883AFD92617F844C239E03F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","013C5D9A83F33B70EDD0EF4B175E4734","017B0CF969CF5E15D58B94F64DB0EDC1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","0138462F3B064F5A2D2735BCBD535472","01390D38EF6A011B05DD7B36A364A3BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","013DC48B707181D2512BD55D72EEBCF0","01DEFE52F8A7964EC92CAA476C1081C5","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","018E071D7C6333CCA941AF3F86C4B040","01F1BC59628C27605A47B1DD4DAFBD2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","0186B5A9C29AD0C22B08617BAAF8B2F3","01AADE46228BCCA9AAC3BE09EF986623","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","016D44ECEDC69CC32EFDBDB3FA52FF2F","017FD44400AB16F1FE452C02524238A1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","014145865FE9A3D75612AD65CD0BF9C3","01680307DDD5C5366799674555B5BD2D","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","013161476484359DD4D9CF9409A8D7CD","014BF262F2540BDB3D5AF1ADF46B1BDB","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","014293DC259CA2AD60B54C5E1DBD5BE4","017F0898D918195BE28D075579313D0D","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","01768F9D9AD459A2F0E12FF8FE7E58E7","01C8DAFC2B195EF06BE17FB14795E4FF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","01958DB41B5F276E1BFD5C17CC07BC50","01CD2F6EDA89988406EECE9D8C492B93","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","011DD5F353F534B7B9CBEE2412A65D5E","01E9E0E0460B869897F4107EBEFDC638","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","01E4CF70D3F4FC5894F625131F820CF3","01F9F607F691635857AE5C87E726A252","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","0134C04B9EA21B43C4EF2F5E9398FAED","0142C40B3C1A8BE418B8A6BAE99BF4B7","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","01BB46E7CAF6065E33DD28A6E7EC9C03","01D4047F04C7C32C6FDDBBF5D71F4CFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LX2","","011C71CDD4C0F8F2CE09A808B280931A","01629B48C0D9C3358A36F1ADC61E01FA","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LZ2","","018132019BC5CC9867CC79E9250560C5","01CF7D282F68C01148D58EE95918704B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LZ2","","01198346965EB20066F6D7B6831E9C95","013E95521791B5B70228DE9E899234B3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LZ2","","014293DC259CA2AD60B54C5E1DBD5BE4","017F0898D918195BE28D075579313D0D","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LZ2","","014D667B6CED05284B47E4C66FF4C609","015FC89EA6DB6E3DD7F8D77D7FA4480F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LZ2","","011D37296ED90033C19351777AAB0B38","01B2922FE979931BFD2586AB0267B31B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LZ2","","012D088BCB11234F4DD3B0306BE621EF","01E45AC07E04EF2C5E8A37C82A60666F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LZ2","","01BC09B19EB1EA65D20FEB9309259336","01E8286E6F2FE6CDD265F8441DC7B59C","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LZ2","","017AF37B1EB466ADBB6C646D90A56E15","01E8D1E4A12056DADDE7152A0B9115B3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LZ3","","018132019BC5CC9867CC79E9250560C5","01CF7D282F68C01148D58EE95918704B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-LZ7","fine","01146210F8F782499562164D98588DF7","01416268426EA8AA822C30E62CB99184","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","0182C24E1E5290C73AD84A7813FCC7AE","01C7160A775B4F76BC0438656E0FF092","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","013C5D9A83F33B70EDD0EF4B175E4734","017B0CF969CF5E15D58B94F64DB0EDC1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","0138462F3B064F5A2D2735BCBD535472","01390D38EF6A011B05DD7B36A364A3BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","013DC48B707181D2512BD55D72EEBCF0","01DEFE52F8A7964EC92CAA476C1081C5","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","018E071D7C6333CCA941AF3F86C4B040","01F1BC59628C27605A47B1DD4DAFBD2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","01C91F94EE93568591EB96DA028179AF","01E1BD28E783DDA36EE9EF9124CB40AE","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","0122D115001A0F43E9F12CAF15140921","019590EE31CB1F94A5E95BB6D8A4D15B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","01CFFACD05293AA908AF4316230788E9","01DD5B33181B223F8AB26AEBDC6E8E84","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","013EF0E302E6BBE0C2AA0D9D85AF7990","014B2BC31CF89A8DC2B2C962A8CF82A6","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","018132019BC5CC9867CC79E9250560C5","01CF7D282F68C01148D58EE95918704B","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","01198346965EB20066F6D7B6831E9C95","013E95521791B5B70228DE9E899234B3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Panasonic","DMC-TZ1","","011377E8CCEBED5DFA86FC8ACF2295C2","01ADCA18F8F8F4DF33ACD56F393A645A","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX *ist D","","012ECC6A2CB8921C19D4E9ADDE045BE0","0198B0E9CEFCFC54ED3BBAA91F3947F9","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX *ist DS","","012ECC6A2CB8921C19D4E9ADDE045BE0","0198B0E9CEFCFC54ED3BBAA91F3947F9","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX *ist DS","","012ECC6A2CB8921C19D4E9ADDE045BE0","0198B0E9CEFCFC54ED3BBAA91F3947F9","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX K100D","","012ECC6A2CB8921C19D4E9ADDE045BE0","0198B0E9CEFCFC54ED3BBAA91F3947F9","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX K10D","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX K10D","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","0162BC9F7A5892E2F2DB22C82006610B","01EA5346C5145C7930905DCF6B31F083","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","0150263B9EFAF0D3F1436478F497AF5A","018370CF802E9CF8FE79E29232CCD3AC","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","010F50672F14B4A88409AEC86E9DECE9","01C3B4FE62DF9A99F1CA8A5C17AC7711","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","0134F2041810CE97DAAB408D5E71163C","01D831EF97768EF36E607FD5D85426FB","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","01BD24596581D7A1535AFC805B0D60A2","01D47AD28A985151B705F90864369E2C","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","0123BAAA6DABBA3007987C5DD352F23A","0162F90EF60A9DB921AA87532AE23D68","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","0155D875C95B74D0F3C5835A62516F48","01D38A25358EB7649A254E19F1D46600","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","012876087A56CFCA7CFEC7D254AD88D7","01C6BBED27FF2B3D0E26E4009B66E38B","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","018F43694F4E9A49C24613CE0DB777A1","01BFD6DFF74A169EDA4F585691B1C832","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 550","","0182230692721ADF5DCBFB56F747490C","01DD92C0CD7077A88C49139F2F15908D","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 750Z","","0130E17CF819C676B0C4E1D92B29E3D0","0148099C19C2AEEB10F7C98672C9FEF5","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio 750Z","","015B3AC73951F0F8C2B83654AF587152","01BE05B882F033CCDFE7838FB2FE84F0","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio A10","","010D5F6137BC7E0D9264FCE27CEE56F2","010D5F6137BC7E0D9264FCE27CEE56F2","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio A20","","0196A4A230303DA672148A7723BA0A45","0196A4A230303DA672148A7723BA0A45","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio A20","","0110E4095D5E65A4ED3A79082BD1651D","0110E4095D5E65A4ED3A79082BD1651D","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio A30","","0196A4A230303DA672148A7723BA0A45","0196A4A230303DA672148A7723BA0A45","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio M40","","010F0CB84C835BB4FCCCF6EE02335430","016C2B10163D7D4D412E22C026BBFE2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","01173DFDB15AEF0B8F8F7DBA935075C0","016B6E94C94F71C50644EB0FB3B797CA","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","011B5DB93D1920C4F22FE30C9D74B019","01817C5AAF8167836BE4F1FE59FC19CA","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","014021C1D4CC4D086AE9ECB4D74059E1","01B02C50605DC2BF1D4287C381033DEA","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","01B22FB5EA6896651D50C9AF6449C755","01B5D1CEC9EA1F3901B90F24ABD896AE","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","01069E2E226122744E5D3FCC5BD907DA","01135841705661AB895ACB4A742D5334","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","0137D4B64EF02801FFFCBB0CC37E6D14","018DE75B8C39571DE5D80B55ED6E40DB","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","01536F16BCEC1264BC0511A540801E5B","01968C8117F844F9A6419C4F192FA3A9","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","018C348769A146C48CDAD42B7E612974","01B90E7E70A6F27BB4153922849C5700","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","0121CCFD7E28555BAA5181244B39E4D4","016B0E8A7220EB2CAF7F1319967FC91A","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","012E4AFBCA09CE8FD90460247DF139AF","01900BBA2DFF8FFEE4C1C9ABDA1C2745","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","012C67677590471A0359CE86EE1D78FA","01AC53FE16B3241E100A052B316C5739","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","015D00310664D41A4A6D2E0E2F340385","01ABF0D27535C31F6BE2559024D247CB","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","012345305944D817D0C161C7B54BAF5C","017DDCB884AFEF1F6DD72AEA5D125933","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","014BA1BDD0180359CC4190D6229FFDDF","01C6957B3588A513847B8FA541A6F154","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","0110ED34D89C23D3FE25D19D8F11C7B7","0162043D57592A98CC22BBCC1C7E1EFC","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","0176898E9E79FCA6F38E219E765888DD","017BB107FA4D61F8B85BCD845DDD93B4","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","013F8DB7C0AE9774B157A59660DCEF10","01F196CA415D9FF6662FA9A3AF99F1AC","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S","","017D4C33EF2B651D308D32F6DF71963D","01AF9D48ABD1FE131FBB9D5CCB3EC659","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S5i","","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S5i","","01A0FB219D74904EAF637293A0F31493","01E3F3BE628274E6C1D4856D8DC20D0E","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S5i","","01158B0D515E752B1B0716889F2B3371","017BBA44ECD57A9B2E59D0D6967F1623","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S5i","","013B1FC692BCCE8DBBAEA5BD4DC13F87","01DB220936AEBE1D36FDF3382FD48D2E","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S5i","","018A97EF0C8856D9155F90A770C73067","01F68622EE6EF782C32ACC2CCF6A9907","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S5i","","011ED04C97FD28B94C49DA6F353F6EC7","015CDC228C3E4F86A815998B228353E7","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S5i","","01534F696E6036C0F788B7E655AC8296","01DFBB572EC62EA7B91E6179FDE95E64","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S5i","","01133005CDA1908ED26E50DDB781DF3D","0160796D6F8855EA95ECF106A9654836","2x2","",""}, +{ ENUM_EDITOR_CAM,"PENTAX","PENTAX Optio S5i","","01C02F25034BDF89C44B5D4FF79274B0","01ECDD6995EAB2286B85FC2B730162B6","2x2","",""}, +{ ENUM_EDITOR_CAM,"Research In Motion","BlackBerry 8100","","0155D875C95B74D0F3C5835A62516F48","01D38A25358EB7649A254E19F1D46600","2x1","",""}, +{ ENUM_EDITOR_CAM,"Research In Motion","BlackBerry 8220","","015058863386110B7045FC40D0B47450","017B270E20A299F9D227B485DD5A9BC0","2x1","",""}, +{ ENUM_EDITOR_CAM,"Research In Motion","BlackBerry 9530","Superfine","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x2","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","01407EB22CA143AC5D93A6849A7FEAA7","0157FE31F260013F0ADA57D0F1717DB4","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","0120A81C1C6B471497B2C39DD796FE4D","015E09F77A7C92CAAEEEB1C80AE632CD","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","012E8AB1306B60B6F8E1D673C857EE3A","01930E8CA4514118CCC2A71CD51FB6A6","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","016F77F4F618340DFA8D4DB85506B0D7","01726AA8F1753F6CFA3AEC3EC6A8F818","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","012D53B2BC8DEEC423C726A99B23EFFB","01342830C284AABC77AEBE2A43D20C2F","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","0140C3DDA9D3F807E4D5FD42CB7F7401","019407145AD5FCC16FEC932CCBC8A9AD","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","0166D7C4514A1B5BF17A8A31C90EF2D3","01E4481CC143080346658FEE1819556F","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","01A940AF62216A26DC513D6BDA9F0701","01CE6F38DBA971F907620725AC62EDF6","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","01D5393400D7C7676C33FFE7B0058C2B","01ECDF62417BAFECAB21ED7394C3302E","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","011E63634FA82881580FDA27C4236F17","017BB1C8854A1FE91C2AAC2B0C5DCED7","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","014E56BC9BC75A3853C76762DBA89741","018A49571355BE8367CF9B25F2D7BDA4","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","015DF0EF77AA51618EF0438E14C99A7C","01C5A27A11860EEEC6677C345637D3A6","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","01916A2F71719701991D51B431766405","0194DE526E131B12BA9CA01B3623B401","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","014263F0A2FDCD405EEB3E857088CF2B","0198BD9B01BE7BDFC5734F86B17A4B4E","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","010CC33FB192BF2F6D9CB720360C5711","010F766EEF9BFC2D9829794E01D705EE","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","010B3F0B475B9082D702F9C46AC041F7","014E7F78F0BB99F85D5A30D64641C1AD","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","0172A66D9B79583F96160F0977E50ABB","01E6372FFE99AA515645F757C6A7829A","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","01E231E0B0AD1CA2327570EF255B58A5","01EEDC9369B1AE507AD0EAC4A9FAFADE","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","0138D93AD569F4A6DDA706D4C29ECF62","01832CCB523483953FAA4D9EF090AD7A","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","017C6B0B992BF83D07547D6D3DD9E327","01A1B2B680A7A1010AFC443A26B4AB93","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","0118E8265FC7C96FE9E57D127154C1EF","0190FEEF53AEA16907E09255D2D7431A","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","0109795E5DB4D422FE6B1949FF142172","016A02998856C8628E975A95B2293848","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","01A465994803BB73ECB03A30E32A9599","01B3BD820D3A06A710CA6BA6D6B4B639","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","012C1E92CE901A9022CB5FD8282E00DB","019102DFD4F30C9EAA8B16AF21908898","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","01773241DB0BF4F8D415F19CEBB787C3","0191FDD3348E5D33208A12821DA15F11","2x1","",""}, +{ ENUM_EDITOR_CAM,"RICOH","GR Digital","","0141CE8E21211A09448DCACE8DC51CD4","01BEE51B29F37D8A5A7BC31C63A652BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01C6769F955C867455C153847C74E6EF","01EC1CBF6C8662E52114F39EE148CEF7","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","0113A2B410CA72B083DF5810A3E3B864","0156501AF03F0CAA64E7A7956E73BA36","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01855CE0D173027D32B5235EA39D7A1A","0196BB1FB30F48B5813991708301ECF7","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01B654B54E59A5BD891D0D46B0AE5700","01CE3648755C5E28D788D4D41892D74F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","019811E20AFD55A42B1C23F704AA9455","01CD08024A418DA37AF5E3C310299FAC","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","0138DF7EECCBD6DFA2AA97A7ED98F9C9","01822C655B2A1BBFD1095FA6CF8CDC4F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01E3AF5C11ECBA1BDED80818B86A11D7","01F3BC7FCF52B7F7062B9460473B9128","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","010B2D80F047E0F70631DE68432DAF6B","01A258C809C4EAC518FAB39067B15EFF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","013E22A3FCAE62D2BD90C219E36F1146","0149B05374B1345932869E6372ED0485","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","013F402F00B9A0C3102B989150765365","015BC8A6314A5E90EFD59DF85EE4AC83","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","0184DCF92E592A5982ACC908BA00A472","01A0D60381102F12B8B8B7AFE0AFEEA1","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","019D7E45EEE96AB2F2F117390DBB5CE6","01CA95CC822CEF61DE2D1A73DC0253D2","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01683B19EFCF77DD132F0FA65417C2B8","0196C06916DEAB56AAE98FA378D1533E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","0142C33C0C4072C4FE6CF0D692AEA8DF","019E26D1A1D23881A7FFAFB39D0863B5","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01584549461851E6B504905DBA2404AE","016738090663999BED71FF0ABE2C3247","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01A5020E4F4CC608563561E25F924693","01F4A5628F4904EB870522FF06D62F82","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01A464CBA79019D90DB72915151295A4","01D38A3553CEE799B0E0D1645CB4B9F5","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01903CBB5777CC392122384B2778F808","019BF9AB7533677149C6F2022D1A6398","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01D8241004A2F31D77D8AE109E2C1965","01F7B1DA8FFC33821446BCC0360B89FD","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","012B47549F5F32EE33A1FFBDB56E2899","014F1DA0331B7D42C7B19A7841722055","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","015F52865AF840E866CE4FC92CBA216E","018CD4FE97236D5ACA212D9945920F07","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01098170130C8E4660FCADF13D54D691","017C96A497120FCD8FBF9C3A08AD9FFC","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01349952A8F476A506636F184C339776","01EA0154C99CDE8FB89FB42F9D5FDAB9","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","010B2D80F047E0F70631DE68432DAF6B","01A258C809C4EAC518FAB39067B15EFF","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","0101795CE0D98BABE2BD57034849C925","01A7FF8625C86B3E99E55BF02B8C438E","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","013E22A3FCAE62D2BD90C219E36F1146","0149B05374B1345932869E6372ED0485","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","0141808604FB9D4DA90E3B5B6F8C9434","01E4FE15DD3789354DA16A873745D01F","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","","","01094BA340F15215478EA7244B41C831","016774C49D2D9056742699631887A1F3","2x1","",""}, +{ ENUM_EDITOR_CAM,"Samsung Techwin","Digimax V50/a5","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","Pro 815","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","Pro 815","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","Pro 815","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","Pro 815","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","Pro 815","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","Pro 815","","01387A14AF75DC6963F040C1239B7DED","0196457BE1E9E30F00715A3DDE8B160C","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","Pro 815","","010300D2A3C0CEB8216F7C59B96AFB16","014F706DC17A4AF11117D50B414F348C","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV 7, NV 7","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV 7, NV 7","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV 7, NV 7","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV 7, NV 7","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV 7, NV 7","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV 7, NV 7","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV 7, NV 7","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV 7, NV 7","","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV10, NV10","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV10, NV10","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV10, NV10","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV10, NV10","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV10, NV10","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SAMSUNG TECHWIN","VLUU NV10, NV10","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","01687A34DFCE112C64A9A8B662405FB5","01A711E09E62AE95248FF0B5F8FED76A","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","01D85DF4F5A6AEEE0EB14899034DC2CC","01DE4C91AB91D804F823DDBBEFED0C80","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","01942B85D5DFEDD8B2BA6B1113B78EE2","0195A50084E3EAFB04010E04AC831A0A","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","0118F69D273A291E8C84DC722CA95DF5","01192BB7696A82DAA10BCBDB0538FBF9","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","010F50672F14B4A88409AEC86E9DECE9","01C3B4FE62DF9A99F1CA8A5C17AC7711","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","01BD24596581D7A1535AFC805B0D60A2","01D47AD28A985151B705F90864369E2C","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","01AC139E31B941CA0F2C5B5A0BFCDFC0","01F3D5B0FBE08EC4AAE9E1E4238BF215","2x1","",""}, +{ ENUM_EDITOR_CAM,"SEIKO EPSON CORP.","PhotoPC 3000Z","","0155D875C95B74D0F3C5835A62516F48","01D38A25358EB7649A254E19F1D46600","2x1","",""}, +{ ENUM_EDITOR_CAM,"SIGMA","SIGMA SD10","Qual:12","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","1x1","",""}, +{ ENUM_EDITOR_CAM,"SIGMA","SIGMA SD10","Qual:12","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","1x1","",""}, +{ ENUM_EDITOR_CAM,"SIGMA","SIGMA SD14","Qual:12","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","1x1","",""}, +{ ENUM_EDITOR_CAM,"SIGMA","SIGMA SD14","Qual:12","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","1x1","",""}, +{ ENUM_EDITOR_CAM,"SIGMA","SIGMA SD9","","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","2x2","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","01B4A094E3299D54C686AAC3A9E68DA3","01E79C7A6F55D80F5CBA8BE9834FCFBC","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","017D916C205AEFFD4A087EBF94C7506E","01B41E10A3065957FB93F928542E3BE8","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","0123A1A8835A75EE1DE4DDDB26B19F17","01D587857C3B50B1C030DD163E85021B","2x2","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","015109957D8D4AFEF6E13F4663725048","01DF5042708CA669A4CD1454906667C4","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","019CE3957D32D1795897B849160802E5","01AE0DBDE466823C5A17DED45D11DB22","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT","","011DEA5F26F562AB40D55A90630F7653","01A6F8AC827B402FC7F102B182B2CFC9","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","CYBERSHOT U","","012D821C6AB210E2A753BE053B8F55D0","0182408A81A4ABF04D4A34A8A5E98C58","2x2","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-F828","","013E4F4032D7BBB022EA8A4DD2A79AA1","015DD46C027E5E984C8305753B29931D","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-F828","","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-F828","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-F828","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-F828","","011DEA5F26F562AB40D55A90630F7653","01A6F8AC827B402FC7F102B182B2CFC9","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-F88","","013E4F4032D7BBB022EA8A4DD2A79AA1","015DD46C027E5E984C8305753B29931D","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-F88","","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-F88","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-F88","","011599F2B12AC57E3846AB3F9B84F65C","01B95B9EB7508DC0C23E40DFC6BE2512","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H1","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H1","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H1","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H1","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H1","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H2","","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H2","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H2","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H2","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H2","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H2","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H2","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H2","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H5","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H5","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H5","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H5","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H5","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H5","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","010F50672F14B4A88409AEC86E9DECE9","01C3B4FE62DF9A99F1CA8A5C17AC7711","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H7","","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","010F50672F14B4A88409AEC86E9DECE9","01C3B4FE62DF9A99F1CA8A5C17AC7711","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","01387A14AF75DC6963F040C1239B7DED","0196457BE1E9E30F00715A3DDE8B160C","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","0175BAF3251040E0EFB2930B73328E7F","01DC499064BA9264D591FDE9071DFD89","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","014D29278FD055B04D8FCEF52F63568B","01EECF7F5B388E02EEE84ABDCF4CECCB","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-H9","","01786593B7990A17B0D81B6DF749470E","01DF37EBC825495EA04E9B311B77D309","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-L1","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-L1","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-L1","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-L1","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-L1","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-L1","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-N1","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-N2","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-P150","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-P150","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-P150","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-P150","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-P200","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-P200","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-P200","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-P200","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-P200","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-R1","","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-R1","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-R1","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-R1","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-R1","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-R1","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-S90","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-S90","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-S90","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-S90","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-S90","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-S90","","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-T100","","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V1","","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V1","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V1","","01B4A094E3299D54C686AAC3A9E68DA3","01E79C7A6F55D80F5CBA8BE9834FCFBC","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V1","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V1","","017D916C205AEFFD4A087EBF94C7506E","01B41E10A3065957FB93F928542E3BE8","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V1","","015109957D8D4AFEF6E13F4663725048","01DF5042708CA669A4CD1454906667C4","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V1","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V1","","019CE3957D32D1795897B849160802E5","01AE0DBDE466823C5A17DED45D11DB22","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V3","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V3","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V3","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-V3","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W1","","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W35","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W55","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W7","","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W7","","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W7","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W7","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W7","","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W7","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W7","","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W70","","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSC-W80","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSLR-A100","","0138E0E373A395C2E98FF667B21870CC","0138E0E373A395C2E98FF667B21870CC","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","DSLR-A700","","0138E0E373A395C2E98FF667B21870CC","0138E0E373A395C2E98FF667B21870CC","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","SONY","","011B33BAEED0A54091895B8D5389FA91","01E5F053039A59A823FEDC91959822BF","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","SONY","","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","SONY","","01B4A094E3299D54C686AAC3A9E68DA3","01E79C7A6F55D80F5CBA8BE9834FCFBC","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","SONY","","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","SONY","","017D916C205AEFFD4A087EBF94C7506E","01B41E10A3065957FB93F928542E3BE8","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","SONY","","015109957D8D4AFEF6E13F4663725048","01DF5042708CA669A4CD1454906667C4","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","SONY","","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","SONY","","019CE3957D32D1795897B849160802E5","01AE0DBDE466823C5A17DED45D11DB22","2x1","",""}, +{ ENUM_EDITOR_CAM,"SONY","SONY","","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","2x1","",""}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T(""),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("000-001"),_T("0138D27C7EEF02B3AB3313CD713E8134"),_T("01D70ED96E34F308DB1A0848A943DDC4"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("002"),_T("011386C6B52F40BADA59DA38760E742F"),_T("0139107E395BC07B318B5EC0E9F6A283"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("003"),_T("0159463DC4E43388BCC153A437842F15"),_T("017A8FCB62FED5062A6DB85334F299DF"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("004"),_T("01130984F055CB0734DFE9120AE608A9"),_T("01A5CE7EC04CE304D74A544A905A8125"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("005-600"),_T("012CCAA4D0460DAD73BE0DECDBA04E21"),_T("0136AB2C178AF7EC6F22CE56DCF2F0AB"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("007"),_T("019833C578EB378FFBFACA37C5E3F219"),_T("01F95C855A1F379C3CC789A80D610101"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("008"),_T("01303D41327C5F81D755996EA1C8F1DC"),_T("0158FB8C5B854AE80A56BD090B82AAAA"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("009"),_T("017AAEFBFFFEC743BE469EC9596717F1"),_T("01A488D7614F4AC0E683C477AD5DCB0D"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("010-011"),_T("0150F2E76158ACE070DADA0C1B2EF396"),_T("01FABEDD10226CF93CB1E7390586140C"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("012"),_T("0105694D3A60EF8B068790263E3C1F64"),_T("011A74C0287957F725CC611660CDFF39"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("013"),_T("01703B12AB08246102043E762591206E"),_T("01DFA2CCC4055F0DB26870FEAABC5C09"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("014"),_T("011B207D670A565F68E79A7BE837635D"),_T("0138F3064037793EA8824A88441C3379"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("015-016"),_T("0147438D96A1D4C93DAE41F36DF4B9C4"),_T("01C19077E605B2CAE33BCEFFAC7AC110"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("017"),_T("016C045902D3F378009ECC6AA271124A"),_T("01D4890A48F5290F27CFDB5BED360D78"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("018"),_T("014BFFD73E371DE01C8CC4B30F2FF7B5"),_T("019D01D87616A4737618729D6DFC552E"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("019"),_T("0189543DDE1BE069368F49B421EFB312"),_T("01B628D80BF1F36B67F3643C0B43B4E1"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("020-021"),_T("017589061A7DA6B30DF34A514AF87692"),_T("01BFFB5FB1318ECC4541CCE316813CFD"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("022"),_T("013E7D04521AC131191558F1EBFC1422"),_T("0157A84F104FDBAB29766F29B675609D"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("023"),_T("01443D23B61DFE645C516FA7D26ED0E0"),_T("01F78F60C79374F89F8BC8EB5AF95047"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("024"),_T("01CADEEA6D4C87A401681BE2BF6189FE"),_T("01F59FC240430708D00AE746922891E0"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("025-026"),_T("017539FD56DF939BCE98C6579237C990"),_T("019A22644832C0A7E445677EBCAC1281"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("027"),_T("01204B752AAEBE51E57D06CB3FDCB48B"),_T("0181DC7BD18DD9FDE59E76F26E5541F2"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("028"),_T("01788CB9C83CF50B847C8A7760659544"),_T("017E9DCD06418EBF8D8CE2FEA4D19C32"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("029"),_T("013C5B4643DD6ADF550B23C67A4DFB25"),_T("018288F50215A7693617F920D19AF81F"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("030-031"),_T("011214AF9B0A7890D8DC588CC88A5FEB"),_T("01BF7D3BEAAC4CD8821795FADAA05AB9"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("032"),_T("010455DF473F62044D313A95F6B8C203"),_T("0117B6A72284D6C5F2F5D52D583C9A9C"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("033"),_T("0107E24545E03C45A2C8806D4D11E64E"),_T("01CEC660B66A2A9A8F27CE73E2F7FD7F"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("034"),_T("015239267819AD908CBF72984A9EE8AD"),_T("015819A335BC138743DB48271ED66D38"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("035-036"),_T("010C69E37CDA707F8DB41957E1BE8721"),_T("013EE695988AE5866D3BC80C01EDF1AD"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("037"),_T("010F99140A5A95CC42052808231CAF3D"),_T("01DD988FBC2A1D333FEBF0BB3B46C680"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("038"),_T("010D2888FB173C6821C5958697347F8F"),_T("01E3534FF692FAE47CB617751CEDEAFE"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("039"),_T("01929371778243D865240876945323C9"),_T("01F4AE9E56FD1F2D7895EF779F7521A1"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("040-041"),_T("0190F119A0B474CB73448F1895BFBE31"),_T("01F25CBB83BCD0E1E894F20647D07476"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("042"),_T("01973F7E8EFBBF63B293A4A7D0951902"),_T("01AFAECC1EC469727C0D3A0F618718A7"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("043"),_T("014EDA494C563A45977F05858B440735"),_T("01ADAD0EA6FAC8EC39E6BB9F80A2B5FC"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("044"),_T("01212BB4A3C5DB6702F929C338CC483A"),_T("01DA92F4AB571727EE61689446AB8ECE"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("045-046"),_T("010CC15B4643F88FC4A52E0A85D791F7"),_T("0187A1A2912E4742B24CC3B3AD0A1465"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("047"),_T("01A5EE2681EE6E4FEFA887661A193308"),_T("01E27A642E2D09EFF8B133F03B603282"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("048"),_T("01010BA0CB90E6E8B55F0ACAA8CB1D21"),_T("01FD78538EF8960FF993257E5050AE48"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("049"),_T("0114717D20FD02CF5321B7A85D8440CC"),_T("0145BF8B1C7367D83231FC6721828A9B"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("050-051"),_T("0134368B6244F8CE214E1D6FB34735A3"),_T("01F6CBD459813DD2CA23C36B6ACB720D"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("052"),_T("012CB626F43DA8BF2607C70F9B7D0977"),_T("01EA643AE20A86AA7DD4DF1DDCD76718"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("053"),_T("013A5F729164EFFCF0EB088CD45D926D"),_T("01E3B128CDFFB87298D438EE74DDA17B"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("054"),_T("013E58AF3BB40DD88C5E49C7F9CAB7B0"),_T("01FF0D5D047A4AD1FDE3A2AEBDB7C15B"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("055-056"),_T("013BE45647CC6624E7EF97898D19F980"),_T("0196B6D81E1EC891B78A6FC41E501EE6"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("057"),_T("01D0E43E7DEF23651B8F486C4563E9BE"),_T("01E0FEAB3A81C6D7345A32C58AB7D51B"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("058"),_T("0188F1BEBBC334B3B3A5081174406414"),_T("01F4B2D39E4017CF1952BDF84A27956F"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("059"),_T("01BA98C687122EA41579AF0D55D7D9F1"),_T("01DBB3556C945DDEA930FEE96C922B32"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("060-061"),_T("010493046013812E6A60F1C947BCF98E"),_T("014FDEE94CD6BB3894EB72C2FD3435EC"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("062"),_T("0182A8273EA432A275A98785F1155CF9"),_T("018B736BBB7A6A9B377113556592970E"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("063"),_T("019322C0F935CB3E8BF358BE02009F10"),_T("01D7C033447017E64166566306B613BD"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("064"),_T("0168A35C180D94AFCF3908195B2EF41E"),_T("01B53A0C930F891E5584A9837F4D20C7"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("065-066"),_T("019523E1FC78374CA437AC1B93E6C27D"),_T("01EC82A09F1E8B8BDA6C9AC3412D4DD4"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("067"),_T("0157B8F21222421A6F55931F84FBB4C1"),_T("01E0433F7723F6AF60219478207469FA"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("068"),_T("0106A1E243ED8C5EECD9FFA83BD9D909"),_T("0135E338E512D2981F53A6F796BBE716"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("069"),_T("015DFAB1D0C62A768D000FF66F670AA7"),_T("0173A34A3257A4FDDF4CCCF7FCB09B6D"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("070-071"),_T("0124237EA3BAF7E687617C56C9FEF44F"),_T("01BE27B1A4F277018ECF621F9EE4357B"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("072"),_T("01381A44131973EA2D012A7F90BF1B65"),_T("01AF00436DA7962818EF111E9602E267"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("073"),_T("0180B24C0D600C69D5EE50E5E7D9FF05"),_T("01BE134082E3654CBC17B64F4CA74D81"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("074"),_T("0113C0115C6CB65A9D176FF7F12DB8F4"),_T("01D879A5B03C9C261E0B13051091F939"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("075-076"),_T("0119470A4796C6D8835FEF17B32D6ACD"),_T("01549824A2982D54A86FBF6FCB58EBF3"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("077"),_T("018417A6CAFD7B99E68D62AE1ED533FB"),_T("01A75327FAD0DAD29E63A3A036C9C747"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("078"),_T("015D89F31A0A1F179BB64CED49905491"),_T("01FAC3701288FA83A4C1789873781568"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("079"),_T("0103354594ADA873431D96F400633A46"),_T("01373828E35FA443AB1D6D36D9FF0BD8"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("080-081"),_T("01E97EB12F8E60E014045751764986DB"),_T("01EEB2D93138615B3BA17C3FBF4F1ED8"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("082"),_T("011C34BE0A49E7129E2106129B25F06C"),_T("01A7C687C179664D7E5162D5675C9A89"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("083"),_T("012FC28E2C2D7D8176873702AEFB212D"),_T("01DDDE2C5DF0F5AC0F1161042D26656D"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("084"),_T("0166C9CC3967807247B93C0D2A168BE9"),_T("01A71FC79AF7E6117788FDAD38A9AD08"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("085-086"),_T("0154DFF319B59E71D47D1ED5C4FBF4E6"),_T("01AAB0140714ACCCCA606490053A1605"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("087"),_T("014822F5A31DCCE335A3DAE44D884780"),_T("01AA752557C5F34B1E2A3CF2E95AF769"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("088"),_T("018FCD649AAEFF642CBF273A36A60F6F"),_T("01EE90F9E15CEC725BC6E0A4B37F0207"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("089"),_T("0133A0EF20C997C87B68A9DFAB282361"),_T("015A336EE0553841153E22FBAB2CD372"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("090-091"),_T("0125AF4DAC2A62E600F6D03E05B7CF91"),_T("01F33F7F8758DADA8F99200CA44FD75B"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("092"),_T("0188801020BE0484F499413EA7ABB724"),_T("01C5315718D1D19AD0CA15A2F68DF5EC"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("093"),_T("01CA6A328C0296B896419261BAD2C8F2"),_T("01EB561F2389361E8994280294CD5423"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("094"),_T("01EA97D21A38A7C290E6C7117A14A83B"),_T("01F8845FE0E2B565A12A92AD8D0F29CC"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("095-096"),_T("0112FFC96229344A2CA6DA90B2E81A6C"),_T("019667373D982CBA9786618B7B663240"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("097"),_T("0129A0C3AD12541D54E6703AD419C527"),_T("0134C26D9B1EDEC747FA07E745F6B46E"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("098"),_T("017A81B04AA9ED5DBFA356169028C91F"),_T("01FD06EF44E5CB187E7A4A87CC2D9D66"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("099"),_T("0100B8C4E482C33F2A505D7261E2CC99"),_T("011C7429AB80690F18978FD375BD831A"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("ACDSee"),_T(""),_T("100"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T(""),_T("ACD Systems"),_T("ACDSee")}, -{ ENUM_EDITOR_SW, _T("Adobe DNG Converter"),_T(""),_T(""),_T("01C2DDA29A1B5DCCD5E217CF9C558A62"),_T("01C2DDA29A1B5DCCD5E217CF9C558A62"),_T(""),_T("Adobe DNG"),_T("Adobe DNG Converter")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 00"),_T("012325931C8FA8522A0DC6856C8FB483"),_T("012325931C8FA8522A0DC6856C8FB483"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 01"),_T("010C5D6B4748A678290EC5AE783A8A68"),_T("010C5D6B4748A678290EC5AE783A8A68"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 02"),_T("01FF0B6A3E240ECF49A8B06AA2743D25"),_T("01FF0B6A3E240ECF49A8B06AA2743D25"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 03"),_T("0107D8E0D4EE2910BEB0A984F3D17E30"),_T("0107D8E0D4EE2910BEB0A984F3D17E30"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 04"),_T("01FA347CB7C707FD008CDAD7367966C6"),_T("01FA347CB7C707FD008CDAD7367966C6"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 05"),_T("01B7D42A6678B6F1F20EB05FFC2A8EB9"),_T("01B7D42A6678B6F1F20EB05FFC2A8EB9"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 05"),_T("01C2DDA29A1B5DCCD5E217CF9C558A62"),_T("01C2DDA29A1B5DCCD5E217CF9C558A62"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 06"),_T("01C695AC8819C200F1D13C16468312F5"),_T("01C695AC8819C200F1D13C16468312F5"),_T(""),_T(""),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 06"),_T("01A90005BBDC3F23A80123EF0B4E4A28"),_T("01A90005BBDC3F23A80123EF0B4E4A28"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 07"),_T("014219E79BBC5C20BABF374762AAA745"),_T("014219E79BBC5C20BABF374762AAA745"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 08"),_T("01180AF3DE63318828A86409EF4013DD"),_T("01180AF3DE63318828A86409EF4013DD"),_T(""),_T(""),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 08"),_T("01A20F69263117021CD16AEF44D6E650"),_T("01A20F69263117021CD16AEF44D6E650"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 09"),_T("0108A9C11C74DD59416AC689A4C00A55"),_T("0108A9C11C74DD59416AC689A4C00A55"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 09"),_T("0108A0C92E083893457EBEE6BC99F12C"),_T("0108A0C92E083893457EBEE6BC99F12C"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 10"),_T("0166B0BC0B82C8233430BF67FA31C829"),_T("0166B0BC0B82C8233430BF67FA31C829"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 10 grayscale"),_T("01398BCF6C3CD3F191AC7651DE1572A1"),_T("01398BCF6C3CD3F191AC7651DE1572A1"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 11"),_T("014C6C24A9EE0C6BDCC1598CEECCE808"),_T("014C6C24A9EE0C6BDCC1598CEECCE808"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 12"),_T("01C1158E443D1C90F302FF6BE49DDD87"),_T("01C1158E443D1C90F302FF6BE49DDD87"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save As 12"),_T("01DADDC4908E9BA57CC067EEAD54E67D"),_T("01DADDC4908E9BA57CC067EEAD54E67D"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 000"),_T("0130B2A516BC06C5D54B8D26507991E2"),_T("0130B2A516BC06C5D54B8D26507991E2"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 001"),_T("0119A7B4F14DEB5431CBFC2EA7D3EDDD"),_T("0119A7B4F14DEB5431CBFC2EA7D3EDDD"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 002"),_T("0103D2DC208BB2DA8027302DF5B27C1A"),_T("0103D2DC208BB2DA8027302DF5B27C1A"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 003"),_T("01BBFF6CB5ABCB09C381E6EB26F8C249"),_T("01BBFF6CB5ABCB09C381E6EB26F8C249"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 004"),_T("018DC509622FE322961BBE39FD51C38B"),_T("018DC509622FE322961BBE39FD51C38B"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 005"),_T("016FF5235A28B97875366ECA87B244CE"),_T("016FF5235A28B97875366ECA87B244CE"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 006"),_T("01F898E2D1E6AE15A446A9032C87121F"),_T("01F898E2D1E6AE15A446A9032C87121F"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 007"),_T("01EC4E95D6F4850EE65667888E006EE4"),_T("01EC4E95D6F4850EE65667888E006EE4"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 008"),_T("01A8073AA8F327DC2EE84DF61F069132"),_T("01A8073AA8F327DC2EE84DF61F069132"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 009"),_T("01E371BB7D76C099C71CB29CFDD825CA"),_T("01E371BB7D76C099C71CB29CFDD825CA"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 010"),_T("01E36CB9967B0DC1C592A39666BF877E"),_T("01E36CB9967B0DC1C592A39666BF877E"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 011"),_T("012629A5C57929287862ADA25BE00E70"),_T("012629A5C57929287862ADA25BE00E70"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 012"),_T("01A600EAD4B56FC377169141936A9012"),_T("01A600EAD4B56FC377169141936A9012"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 013"),_T("017C5C5E45660BA6CBCB3227428E6F59"),_T("017C5C5E45660BA6CBCB3227428E6F59"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 014"),_T("016CFC2E78B9BEF288E515994861ED2A"),_T("016CFC2E78B9BEF288E515994861ED2A"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 015"),_T("01BB9DB9D84C1FF90F10393E786EFA37"),_T("01BB9DB9D84C1FF90F10393E786EFA37"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 016"),_T("01FC38C12A3488DA75DB0206D349C35A"),_T("01FC38C12A3488DA75DB0206D349C35A"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 017"),_T("01DD25CDB86D38D4032D6EE9E877B827"),_T("01DD25CDB86D38D4032D6EE9E877B827"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 018"),_T("01A8ACB503430091613C58F4448510BD"),_T("01A8ACB503430091613C58F4448510BD"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 019"),_T("01621F1AC8A1B3152136EE2348440AEE"),_T("01621F1AC8A1B3152136EE2348440AEE"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 020"),_T("01753BA0EF85AD1B1C66F2724B9879EA"),_T("01753BA0EF85AD1B1C66F2724B9879EA"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 020"),_T("016191A38B30FA96ED932E8F03ABD75C"),_T("016191A38B30FA96ED932E8F03ABD75C"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 022"),_T("01BAEFC08D867839BB67FAA24A7004D0"),_T("01BAEFC08D867839BB67FAA24A7004D0"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 023"),_T("0109594B7BD71FF6EB4CBA341F4528EB"),_T("0109594B7BD71FF6EB4CBA341F4528EB"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 024"),_T("01C95456509D376179DBC2536A11AB80"),_T("01C95456509D376179DBC2536A11AB80"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 026"),_T("0124BB387BF72FB204C341839BD9CCB5"),_T("0124BB387BF72FB204C341839BD9CCB5"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 027"),_T("012044A3BA7CE9E4F17D98D49684AFEA"),_T("012044A3BA7CE9E4F17D98D49684AFEA"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 028"),_T("01107F5F085067D02D0ABE0F1F84012E"),_T("01107F5F085067D02D0ABE0F1F84012E"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 030"),_T("01F73A1839315AEFC5DB2DF9EE8D0977"),_T("01F73A1839315AEFC5DB2DF9EE8D0977"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 031"),_T("0184411BB50011A44DCFE3D51D1A17AF"),_T("0184411BB50011A44DCFE3D51D1A17AF"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 033"),_T("015E5E79CEE9B0FE744F68E5F6F8BFDA"),_T("015E5E79CEE9B0FE744F68E5F6F8BFDA"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 035"),_T("010C825A320E0BD3B93090391B319625"),_T("010C825A320E0BD3B93090391B319625"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 036"),_T("01382BDFE1AED73EE5F30BF0D2044852"),_T("01382BDFE1AED73EE5F30BF0D2044852"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 038"),_T("015582D4CEA4ECEC52CE6EE9A1222C95"),_T("015582D4CEA4ECEC52CE6EE9A1222C95"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 040"),_T("012BD5B2A563F55EAAE0128203CC68F6"),_T("012BD5B2A563F55EAAE0128203CC68F6"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 041"),_T("019849132013D5323EF4E2B2702C9737"),_T("019849132013D5323EF4E2B2702C9737"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 043"),_T("01DDC09F3332E25EA20962B3FEF3BF23"),_T("01DDC09F3332E25EA20962B3FEF3BF23"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 044"),_T("01651D50C387514D0E61092260CB0258"),_T("01651D50C387514D0E61092260CB0258"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 046"),_T("0101E499902CA45920E16A202657C0E2"),_T("0101E499902CA45920E16A202657C0E2"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 048"),_T("01024F682A8AFB5D96B1B7A6339B7D45"),_T("01024F682A8AFB5D96B1B7A6339B7D45"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 049"),_T("014861235F177CE4A79C1A0C43816AF5"),_T("014861235F177CE4A79C1A0C43816AF5"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 050"),_T("011E122B2E1C9BB19DCC0C0BC8E74E25"),_T("011E122B2E1C9BB19DCC0C0BC8E74E25"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 052"),_T("01B561565D8F26E36922E8AA5FC12D45"),_T("01B561565D8F26E36922E8AA5FC12D45"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 053"),_T("01431604AA6CF86A5300CE0553C058B8"),_T("01431604AA6CF86A5300CE0553C058B8"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 054"),_T("011B9E3A3334C136B755003D2CAF305C"),_T("011B9E3A3334C136B755003D2CAF305C"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 056"),_T("011226BD3AB7415091D91106E6512A0A"),_T("011226BD3AB7415091D91106E6512A0A"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 057"),_T("01301727419256BBE49DEA4A0532ABF4"),_T("01301727419256BBE49DEA4A0532ABF4"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 059"),_T("01296F65B9EFEB0E469475600B17D622"),_T("01296F65B9EFEB0E469475600B17D622"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 060"),_T("01C26040DB5181BA3B5CD7A813FAD209"),_T("01C26040DB5181BA3B5CD7A813FAD209"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 061"),_T("019CD397A6F3412E605D89ACE6D5E1E7"),_T("019CD397A6F3412E605D89ACE6D5E1E7"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 062"),_T("01203021460C376D8D31D57C3F4BDD55"),_T("01203021460C376D8D31D57C3F4BDD55"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 063"),_T("01438E0E3B5EE9CC5380F611E5168979"),_T("01438E0E3B5EE9CC5380F611E5168979"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 064"),_T("0142F9A14A2DB18F9A8E42521497910D"),_T("0142F9A14A2DB18F9A8E42521497910D"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 065"),_T("01803D95BA4C7F1CDA486B171BB30DBA"),_T("01803D95BA4C7F1CDA486B171BB30DBA"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 065"),_T("01EDA06D0F21C77828F6D5BF5BB25EB8"),_T("01EDA06D0F21C77828F6D5BF5BB25EB8"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 066"),_T("0139B00110F2F44D5E6F220C1CEACC39"),_T("0139B00110F2F44D5E6F220C1CEACC39"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 067"),_T("0182FE1F69533D6A2C675D7985752298"),_T("0182FE1F69533D6A2C675D7985752298"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 068"),_T("014A714C9F3FCF306F101BB7109B7FC7"),_T("014A714C9F3FCF306F101BB7109B7FC7"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 069"),_T("01C553050D6EBAC845BEC1A2B2ED35A8"),_T("01C553050D6EBAC845BEC1A2B2ED35A8"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 070"),_T("019CAD91870AF68B20FEF745FB5B191C"),_T("019CAD91870AF68B20FEF745FB5B191C"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 071"),_T("0170812268185A8C590F16B3DBAB22BC"),_T("0170812268185A8C590F16B3DBAB22BC"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 072"),_T("016743557ABCB147A79BFA185DA3EA15"),_T("016743557ABCB147A79BFA185DA3EA15"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 074"),_T("017DCB1A1B1D8B591A3B04771041A382"),_T("017DCB1A1B1D8B591A3B04771041A382"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 075"),_T("013E5A347BEB5C2FD641B1432B342192"),_T("013E5A347BEB5C2FD641B1432B342192"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 076"),_T("01DA170CA3AA855A5CB8D95C5A4B8E38"),_T("01DA170CA3AA855A5CB8D95C5A4B8E38"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 077"),_T("010DCEC5469DFE9A25FD53D3D268A638"),_T("010DCEC5469DFE9A25FD53D3D268A638"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 078"),_T("01025266C31FCCE9E081B1E73F65C152"),_T("01025266C31FCCE9E081B1E73F65C152"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 079"),_T("012BCCCA56539844F0D270A0A6CCAF85"),_T("012BCCCA56539844F0D270A0A6CCAF85"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 080"),_T("014FC9D32AB50D2E78A55796DA2CBEC6"),_T("014FC9D32AB50D2E78A55796DA2CBEC6"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 081"),_T("012B9DCBF402DF17158CBF6E64206F32"),_T("012B9DCBF402DF17158CBF6E64206F32"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 082"),_T("0130B6BD32634AEFB97B70F20976FC86"),_T("0130B6BD32634AEFB97B70F20976FC86"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 083"),_T("0189D2AED788E6E598C992F4260F351A"),_T("0189D2AED788E6E598C992F4260F351A"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 084"),_T("01BBEA4DA57CB2723835E42CC4E0BCAC"),_T("01BBEA4DA57CB2723835E42CC4E0BCAC"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 086"),_T("01A001542F2B6107CEA432CE45AF8100"),_T("01A001542F2B6107CEA432CE45AF8100"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 087"),_T("0128FDDB85CB7E37EEC547C9FBD4E8CF"),_T("0128FDDB85CB7E37EEC547C9FBD4E8CF"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 088"),_T("01943E417C105E1AD39161CA8C5EE06E"),_T("01943E417C105E1AD39161CA8C5EE06E"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 089"),_T("017981A780D2FB52E811A9DFB5E211DB"),_T("017981A780D2FB52E811A9DFB5E211DB"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 090"),_T("01D3C14A2EE08C94A55B15E2ADB46AE4"),_T("01D3C14A2EE08C94A55B15E2ADB46AE4"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 091"),_T("0132C1F3B949A09A0C059E9CF70DBADF"),_T("0132C1F3B949A09A0C059E9CF70DBADF"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 092"),_T("01495A5CA34A31036C80CE720821A2AE"),_T("01495A5CA34A31036C80CE720821A2AE"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 094"),_T("011366606521191E3BF568FFE4F0ED0C"),_T("011366606521191E3BF568FFE4F0ED0C"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 095"),_T("010BCBF1E31BE554B4429AF04CA58C0E"),_T("010BCBF1E31BE554B4429AF04CA58C0E"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 096"),_T("0192B42FED2A30C8D0E60CDC1200ADF4"),_T("0192B42FED2A30C8D0E60CDC1200ADF4"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 097"),_T("014007E37B551E53208F1585B40B99E0"),_T("014007E37B551E53208F1585B40B99E0"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 098"),_T("0126C30B910B29E7FF76843991A77790"),_T("0126C30B910B29E7FF76843991A77790"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 099"),_T("0144B08D172AE0B1285A07DECA206F71"),_T("0144B08D172AE0B1285A07DECA206F71"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop"),_T(""),_T("Save For Web 100"),_T("01E76B1145D4662F80BA198358A896A4"),_T("01E76B1145D4662F80BA198358A896A4"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 021"),_T("01A9B3D4EF8B5D8C732F94BD7AF4ECA6"),_T("01A9B3D4EF8B5D8C732F94BD7AF4ECA6"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 025"),_T("019389FA50B73A7B9D6D0094FED486CC"),_T("019389FA50B73A7B9D6D0094FED486CC"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 029"),_T("012D9007B37C05C003535E8D4B15EDD9"),_T("012D9007B37C05C003535E8D4B15EDD9"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 032"),_T("01A8466B2DB77E8F85B7364B729FADF0"),_T("01A8466B2DB77E8F85B7364B729FADF0"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 034"),_T("01FC7D123C99FF761F2865AF43F03A4B"),_T("01FC7D123C99FF761F2865AF43F03A4B"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 037"),_T("014B8AB1944327D4DD81AD3F69001F86"),_T("014B8AB1944327D4DD81AD3F69001F86"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 039"),_T("0175F8DAB418C9B17A5FB722EB309BA6"),_T("0175F8DAB418C9B17A5FB722EB309BA6"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 042"),_T("01791EA97528DA2BD02082933CEDD4F2"),_T("01791EA97528DA2BD02082933CEDD4F2"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 045"),_T("0153DE55B52852BBB966CE1FF54FAF81"),_T("0153DE55B52852BBB966CE1FF54FAF81"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 047"),_T("01A13C373289893FD824792E79CD8115"),_T("01A13C373289893FD824792E79CD8115"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 055"),_T("010CCF22A3D98B7E94C08FB611403AE1"),_T("010CCF22A3D98B7E94C08FB611403AE1"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 058"),_T("019F3067B720B4F8428DEFC96661167C"),_T("019F3067B720B4F8428DEFC96661167C"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 073"),_T("01347EEB18BCBCBA043C274F38C6554B"),_T("01347EEB18BCBCBA043C274F38C6554B"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 085"),_T("01F43B7B625F02D2AAD575F9A61842FC"),_T("01F43B7B625F02D2AAD575F9A61842FC"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Mac"),_T(""),_T("Save For Web 093"),_T("01A8A4A60156C103EC5C645224C142EF"),_T("01A8A4A60156C103EC5C645224C142EF"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Mac")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 021"),_T("0175AFC5ABBC32B32E4D2F4CDAC93F69"),_T("0175AFC5ABBC32B32E4D2F4CDAC93F69"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 025"),_T("019CC391D4B06A06E29474EA82801C4A"),_T("019CC391D4B06A06E29474EA82801C4A"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 029"),_T("01177339640EEDC5DC811AF1B7744459"),_T("01177339640EEDC5DC811AF1B7744459"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 032"),_T("01F659D3E69B6A840FA8DAC5FC8275C0"),_T("01F659D3E69B6A840FA8DAC5FC8275C0"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 034"),_T("013DD4ED1AA14061D16D1DDDAF48E6C2"),_T("013DD4ED1AA14061D16D1DDDAF48E6C2"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 037"),_T("017C2DB1BAB171B59D51799C4FCF0E8F"),_T("017C2DB1BAB171B59D51799C4FCF0E8F"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 039"),_T("011AAAD2F0102BC6AC01D65C7BBC0334"),_T("011AAAD2F0102BC6AC01D65C7BBC0334"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 042"),_T("0103D86E0E6E0CC85740ACD6CA691A6A"),_T("0103D86E0E6E0CC85740ACD6CA691A6A"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 045"),_T("01653BBDF05CD614839A275CE9B6912E"),_T("01653BBDF05CD614839A275CE9B6912E"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 047"),_T("010EF9F94D9E759DA75E1C3A969BEC70"),_T("010EF9F94D9E759DA75E1C3A969BEC70"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 051"),_T("01D2AB7D4DF7A989D35E7A065E3779BB"),_T("01D2AB7D4DF7A989D35E7A065E3779BB"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 055"),_T("0112676ABC8BB7D03ED0B1A9E2ED214D"),_T("0112676ABC8BB7D03ED0B1A9E2ED214D"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 058"),_T("01A06D860B61A8C65172CB737CFE81D6"),_T("01A06D860B61A8C65172CB737CFE81D6"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 073"),_T("012A76A99AE7EFAF680F8A583E4A2B3B"),_T("012A76A99AE7EFAF680F8A583E4A2B3B"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 085"),_T("0125E813312F55DE92C0A2C020B90589"),_T("0125E813312F55DE92C0A2C020B90589"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop -Win"),_T(""),_T("Save For Web 093"),_T("01CAD52BFD97C6E39A4FEDA5CC104BCC"),_T("01CAD52BFD97C6E39A4FEDA5CC104BCC"),_T(""),_T("Adobe Photoshop"),_T("Adobe Photoshop -Win")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop 7.0"),_T(""),_T("Save As 07"),_T("0165B3F1B409A4D8D5F2ADFFA970D3A5"),_T("0165B3F1B409A4D8D5F2ADFFA970D3A5"),_T(""),_T(""),_T("Adobe Photoshop 7.0")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop 7.0"),_T(""),_T("Save As 07"),_T("012D821C6AB210E2A753BE053B8F55D0"),_T("0182408A81A4ABF04D4A34A8A5E98C58"),_T(""),_T(""),_T("Adobe Photoshop 7.0")}, -{ ENUM_EDITOR_SW, _T("Adobe Photoshop Elements 2.0"),_T(""),_T("Save As 10"),_T("012933907CE4B9D3C27E3E9D4D50BFD6"),_T("012933907CE4B9D3C27E3E9D4D50BFD6"),_T(""),_T(""),_T("Adobe Photoshop Elements 2.0")}, -{ ENUM_EDITOR_SW, _T("Adobe Photosop"),_T(""),_T("Save For Web 050"),_T("011E122B2E1C9BB19DCC0C0BC8E74E25"),_T("011E122B2E1C9BB19DCC0C0BC8E74E25"),_T(""),_T("Adobe Photosop"),_T("Adobe Photosop")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("000-004"),_T("01E1BDDF6C45DBEC46FC48B60BBF6018"),_T("01EA5E13EF082CE6D445C4AC8ED703A8"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("005"),_T("0126FBCAC54E5F8913BF1675612B5D23"),_T("0198D256A3203CC67CF1559EEB39D216"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("006"),_T("011C793F9E71B996834C395C0A4B987F"),_T("0168CEC66029B4B5237F887CCAA2E604"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("007"),_T("01645CC0CC50F54D1173CA3E454AF54A"),_T("019D7FA63C16339F44D67D45FD8603E6"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("008"),_T("01677A30C503901718398BF6931FC51E"),_T("019BB42ADFFE3152B70CF024B826D7CC"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("009"),_T("014939B82901487C3A444099F486237D"),_T("01CBF5EB43E3104104B28258D417ACC1"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("010"),_T("012B2C7ABA69A72048A5B864F1AC4070"),_T("01574C5E6F3D7293E84BE75D886A3917"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("011"),_T("0188AC3A8F2B0B70FA22245542E991CC"),_T("01935D7534EFAB6901A7DA9159BA60BF"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("012"),_T("0126FB4D1191A9B77D790FA3A446B071"),_T("0198C08C7D5E51753E7EC3FC7FD294C9"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("013"),_T("01539AF5226D7FD8CA9423F5C1A7E61D"),_T("0170D73C45D867BD2AD75B49D7254C24"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("014"),_T("0172C9440F7071B4EE7CA7BEF484B84E"),_T("01DFEEAB4A038C174D2F19BF66A13231"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("015"),_T("01466F83C333E94A420A1D981B0B18C1"),_T("01B2C325E900FF46A26E2EE89FDDB2A2"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("016"),_T("01C0446E7A2D20CBEBA8F2DB3E3FF514"),_T("01E90614933C79BC205EE1EF74699CB1"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("017"),_T("010047DB57AB7D7DD5FB3D0F5000D53D"),_T("019A9BEE3E8EFAD46391AD433C755815"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("018"),_T("016E007C33B426D996676779A6526DF1"),_T("01A3914684E4EE020AF3A5D193681E58"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("019"),_T("01934D7DA423E24105014F3C048391F7"),_T("01B24B2CB41352E7BC79EF13D24F8E33"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("020"),_T("016592D04ACA0DD271C5C2BC90E1333F"),_T("01807A26F1DD1849F1D287C4D0788B23"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("021"),_T("016480046FB50102942EDEF00B61C36F"),_T("018E070FB96C25B959564A5AA94C35E6"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("022"),_T("016B59B05B49931DC6084E11616D64EC"),_T("016FD94ED31FF30D8E1C25587E0D85F7"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("023"),_T("01878E1F2B458AA806240872FB43DDAA"),_T("018BB3F9D4DA424384A51D624CD3D9FE"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("024"),_T("015CFC6C2D58274E98FBBA4F6321D1AF"),_T("01EB319F71755E65CE61657E4E9A99B0"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("025 (Low)"),_T("0106CC8A4D86406631698CAD623295E7"),_T("01D7939BF6193E9BA33B39FB00E1692D"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("026"),_T("01225CBD60ED2AD10620D8DF77E71FB0"),_T("013B9648B48BFF6B7B099F3FD651F248"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("027"),_T("012131D6E147D0DDA17559B6D8F0E7A1"),_T("016254A60390F098D16CF2F9F8D46D41"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("028"),_T("012B4382271961958103C7343BE6ABD5"),_T("015F8C12B50F26B6E80F167F0FF47455"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("029"),_T("01CB490B7BED73A82A4DC3F14D8BB4A8"),_T("01FBCB539A90B10CEADEB86252E28589"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("030"),_T("012DCC7188B68F08CA475B836A696D35"),_T("01D3C50126F751A336DB7979BD55A2B0"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("031"),_T("0129DD41201CBABC51D0DA67D61D1D0A"),_T("0139B0F3163DF554094E7C3C575C8283"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("032"),_T("0125CEF1CADB3F9B61DB1C76882632EE"),_T("0130DBC822B41A84DB23DED722875DEB"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("033"),_T("01295A789D11EFBEB1271894A616C2B6"),_T("01EE25BE492A83676EBD2DD27DAB6EF4"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("034"),_T("014A5317C1D0D7E249AFE179EDC78D44"),_T("01F141F71B11831A417055F56CDBDBAF"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("035"),_T("019F943F9911D5A92F7FD316D5257911"),_T("01F5EACFE329B4A0B3D933BAA129D992"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("036"),_T("01157C3DC3F654CAE8DC773C6875C501"),_T("01E10E17D6553EDAA3980DD8442849E8"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("037"),_T("0102FD53DA7E2BF17C286459EB6D9527"),_T("0157C76A130F5344634EA4EEDA0A1D5B"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("038"),_T("0188BF9F540DFEEFA3A9C802EEC8CD13"),_T("01A778499CDDA9D909D5227FD9B90D18"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("039"),_T("018D62D7C4DE7E96267B7DB39A83794A"),_T("01BA683B8D4A9C52CE491558E648008E"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("040"),_T("01204FC209870A3BBFC7845EAF5759CC"),_T("0124B5353984D3B55CE4761AD15F513A"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("041"),_T("0106F49F3A8C3ED55BE59D17CFBF3021"),_T("01314FAD6CA3B2292CCD7BA1FE3BA6AA"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("042"),_T("0107889833E58EAD62F3C831ADA56423"),_T("01C6E60E4501F3D32F128664DCE3D284"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("043"),_T("01137E2463CDDFCD699A73035661A466"),_T("01A747D368B7ED07DD3B26292D80ECFB"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("044"),_T("0133919E64E56D9E74D9EF2745A71459"),_T("01589D2B6C93E184413F1FC5AC3B9BE9"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("045"),_T("018E870D2F9AFC8B03C5DC4492682F64"),_T("01E325F50092F947E74B2CC234700C31"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("046"),_T("01872032961FF2B3646C019B7E9B108F"),_T("01A6301376639A3410E4F662FD058A2F"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("047"),_T("0158976B662BDACF2273BB1C473A164D"),_T("017BCE5EF37920D90E7111FE8BD58598"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("048"),_T("012C8DE2056525DE9FE92443C605A78A"),_T("0194CECD16D9F462DCDCAAEF81F3ADBA"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("049"),_T("0182230692721ADF5DCBFB56F747490C"),_T("01DD92C0CD7077A88C49139F2F15908D"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("050 (Normal)"),_T("0175BAF3251040E0EFB2930B73328E7F"),_T("01DC499064BA9264D591FDE9071DFD89"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("051"),_T("019A47660E47871B3671ED47AC3CC5A0"),_T("01A1C753C3B952DEB5279ECB0BF65C2C"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("052"),_T("01120B3AD85F4C8E3EAFB2795C0B48F2"),_T("011CE1667822D0847E888CB66C5C580A"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("053"),_T("0141CE8E21211A09448DCACE8DC51CD4"),_T("01BEE51B29F37D8A5A7BC31C63A652BF"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("054"),_T("010024C0F1734B148CECCD76EE92D9A1"),_T("01E80B819244DB40BC79151703625E2F"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("055"),_T("01260E87C3F8E7D82C26F75E6E6AF47C"),_T("012FD11B66B6BDC21718EC7B400264A1"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("056"),_T("0161BBFB99218AA2D308B872914C25D3"),_T("0193EF2EDE9B800A47B1668DAC55A133"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("057"),_T("012444027658BD665BB7AD2C119EA883"),_T("012551DDF21B7F7A80EA5E9DD6B0896C"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("058"),_T("0142CC6174741D661E2C9E071B69422E"),_T("01C350C443A4740D913952AFB00253F2"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("059"),_T("01056C44719BDAC0034D5A55E16F47A4"),_T("01E9E33A72E2F73E8FB9307D47BA5286"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("060"),_T("011968874FC0524E5485DA781700EDAF"),_T("0164D08E1D3B43F9DF9C6925DF9791AD"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("061"),_T("0134C01EB38234AE0E6AC6DAF079B326"),_T("01A15B86B56D87ACB7B5E9BBC2569B2C"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("062"),_T("012E13089848657B9B5CDB998090F7F5"),_T("01E932F45D4F1478D2D273CD62DBDECB"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("063"),_T("0119EDAD5E9B000BDDBA8753B120A229"),_T("01DE4177A47A2F2676F6B2B3A0080023"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("064"),_T("012C1E92CE901A9022CB5FD8282E00DB"),_T("019102DFD4F30C9EAA8B16AF21908898"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("065"),_T("010C5E83B4718AA6A399FF23B50A7F96"),_T("01597ACBE29F0E07FA071884AB89D3CF"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("066"),_T("01B1DDF4CB8DA7D900F69CED5A0A04D0"),_T("01F8D63A18117D01CD1294E5AB131C8C"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("067"),_T("01758A3E0C28B68036CD45CFC3EB1216"),_T("0197E99A8AE184E3D3E3C6C3C5FEF99F"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("068"),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("069"),_T("0162FE55E33782E1688BFB4B0EAE65B4"),_T("0190321C4F531E73CBEFEB2A68A93EA0"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("070"),_T("01784541057E8D5DE839E26D360E7B9B"),_T("0190F856F3F2E4FBD1A8EA7EECE2AC97"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("071"),_T("01612B6026E2956027E1F1A429384D0B"),_T("0187EF25A41FE4767D1716CD0D3241B6"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("072"),_T("0160DE46E1DD853827062BD015E0007C"),_T("01C180F0D55998C9159D07F2FABBCB1A"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("073"),_T("01887E4A16BFD89384CCF99F476255AC"),_T("01BD26E97FB262E36DC19C7C3890813F"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("074"),_T("017FC4A11DAF71E5DA854E663AAC411D"),_T("01906ECAFA199DFFA6789731CEF5E958"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("075 (High)"),_T("0147A204E29CA6BB54C62A51E403109C"),_T("01A1625280C51FF5D66CD5588DB795E2"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("076"),_T("01220C476CFC53783AC6AB5EB1A97F0D"),_T("01C250F6680836A53A23AB81808F9A0A"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("077"),_T("01598BE63D08B2CEDA32C2C52352CE48"),_T("016BE18CF2724156D4B72F612AD90E97"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("078"),_T("0170120584A0850B1F6E0B9D80D90B31"),_T("01C351E4E8F43FB78EB16F77F64E894D"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("079"),_T("01B84306903A0AF41E7FF28543937201"),_T("01ECBCB4C4CAEFADF8CE7D835B93CD59"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("080"),_T("01191863A92FA362537A80411114BBC3"),_T("01D7D42C1C869993B7E598D7C109534B"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("081"),_T("0158CE52C54D397B53221DD19E8ACDED"),_T("01AA907DA83C09A2A65361F78978711F"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("082"),_T("011C4430355A5A7DC629AF44FF04226B"),_T("01A815DCC9C4C2F64AE295D37ACA0F7E"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("083"),_T("01512628D15A91E8E2F10B54339B8F97"),_T("01CDEE40A34EE162A13F228C5578D9CF"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("084"),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("085"),_T("015E76BF0DE87FB5F316AA09C0140F63"),_T("01EF24522F0FAAF04D2AAE329E929E9A"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("086"),_T("0124BB115473A2FDF8761E456E0479E5"),_T("016A0C5AF55E177945D9CA4325B15B66"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("087"),_T("0160BB5124EC40826352E9552F12F291"),_T("01E5D37BA619FF16E45EE495903E19D4"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("088"),_T("016517142B3160A02B540042E07047B7"),_T("01A2E59FC2CABC23E9813AE1501F4592"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("089"),_T("0177216E93088FE251EADA34A3527681"),_T("01F836392A26F87859B328DE1EB0E05A"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("090"),_T("0114ED88173433C4BF99F0569EA94D90"),_T("019E0FC5DA517712EF95A6C1789E61D0"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("091"),_T("014992BEE7D2FAA63304B0F1263B685C"),_T("01DC1DDDE2A9FBFA4FAA4C6E202E2CFE"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("092"),_T("013970FDDE9C9CA2CC8F0082375FFCB8"),_T("01A098C96CAA97E3171F4A90451B4CB1"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("093"),_T("01195C98AC99FFB4127537310F066964"),_T("01ADB5F03BA5F38B0F507E3D71E627FC"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("094"),_T("012AE29B4321410985D1B1B400901D6A"),_T("0155B057A3CF7EB81659AEB7BEB76C7E"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("095"),_T("0117778062C5DEB6B73DF9E5B4148858"),_T("01387F274E7398893466910CFCDB77F7"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("096"),_T("0166D7C4514A1B5BF17A8A31C90EF2D3"),_T("01E4481CC143080346658FEE1819556F"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("097"),_T("01456AE94047979A32863FE4D17BE1B0"),_T("018EE88E37BAC6C8133370617AD31752"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("098"),_T("0111DB73E1FEA8BD01B0960F519AA102"),_T("01BF46EDE189625817DDCD2078B14615"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("099"),_T("010391CFAC472ACA504A2866EE657963"),_T("0143211291F265B8A813CF926B8C057D"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple ImageIO.framework"),_T(""),_T("100 (Best)"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T(""),_T(""),_T("Apple ImageIO.framework")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0000-0063 (Least)"),_T("011C88CCAB514CC4A787F898B6E6EE24"),_T("01C63F17235F997C6F997B87B01184EA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0064-0080"),_T("010C95C1C2130A78D3FC22D9FC14E720"),_T("01D35577208E868CB177450A5F916D44"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0081-0092"),_T("0165D7D8186AAC0B25CCBBAD42B1C8E7"),_T("01A5449AF732DA14FCD0C06726602345"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0093-0101"),_T("01A0B3390F3E3FBA8E0934D3A0D43DA7"),_T("01D50AACEC5C12098C7E95D7002EE7E9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0102-0109"),_T("01800B30CFE9217CBB8ED38308657045"),_T("019BC80D7BA9D1A6DA22935FD2076D0E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0110-0116"),_T("0163DE1D571705F29A4E0F9EDD415669"),_T("01A0B785F91E0A94A4CDE7AC8D98ED25"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0117-0122"),_T("010F76D7444606E67A155424D3E374DA"),_T("01BF0F617041503990DE36C6989878CD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0123-0127"),_T("01999239E7FC36CD7392D754FAAA519A"),_T("01B738F6EB8AB273740302236E6D3DFF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0128-0133"),_T("01BACF6DEA7CFE4408147A6FDBE6F370"),_T("01BAF402B2F4B9DB94C239DA866A32AE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0134-0137"),_T("01AC9A9855E4AC5C155158207E3661E9"),_T("01F26BA2ED5D94674D5367C9DF97913F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0138-0142"),_T("0158368371EF557D54B5C5885E827AB7"),_T("01FD1430AC02ED9CACAD174917D3962B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0143-0146"),_T("011EA21ED48A1140575230458A58CD21"),_T("01702B3CFF2B096D8556B5235D21212A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0147-0150"),_T("0128E20D2CDA4930602AF70D82D522FB"),_T("01A5EC263C62A85FE940A82FB9A0BBD5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0151-0154"),_T("012E67FC156AFCDF75878E4D58407D5D"),_T("0159A5F2A6B04D5AC38ECE33D1566E0F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0155-0157"),_T("0131B676C793FF00970E4A7522C59A35"),_T("01E81ECCBB93900A2CC55954CB731F4C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0158-0161"),_T("0179A7B1E2CCB0B4FBA690EE835B0E41"),_T("018FC7296FA535ED107586AE591C28DD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0162-0164"),_T("0174FC3355E9634E5D67D66637548DD9"),_T("01803B4A2775C2AE8447860D31EE740F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0165-0167"),_T("017231B2B696C41FD41146CB8F260F82"),_T("01C018FF15BA3C3ECA9F6FC169409E4F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0168-0170"),_T("01187EBC3CCC817414146831110B5714"),_T("01FE56C7FB69FC18FE3A98FC6FBB9831"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0171-0173"),_T("0102F290BB55CE87D3A705BF37818931"),_T("012D6428363A50CB868C7FEEB1BB7A40"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0174-0176"),_T("017B200FB5E3EA74BF9569227EA666AA"),_T("01EBE28348FAAEC3D1ECA43A1A5BCD10"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0177-0179"),_T("017F7AD7B07FA891B9B7EEB3CC921E88"),_T("01CF270B256B8BBD3007EE9C2EF4CD58"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0180-0182"),_T("011FAC9E26D30E962A6C4F180E2F0B69"),_T("0198CD00F64E119A82C25BB4DA8D8F3D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0183-0184"),_T("01307A78223F839F3BA2CDAD683CCB9A"),_T("017E03CD31C931DA2E862647E433FF21"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0185-0187"),_T("01C531722B2F47394AA9062F21C78BF9"),_T("01F47B4EAFE308D7B688AA053D3E2107"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0188-0189"),_T("015E1131DB3861BDA89E4D376820098E"),_T("016BF49E27301A47B42DB44FD5E13BD7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0190-0191"),_T("010299130D04450933C15078BFF5207F"),_T("013EAC782791858F72B8519395E3CA80"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0192-0194"),_T("015DEBB2E2AE030CEA8A9058EA35D9A3"),_T("01ED2508642E02D9EF8FC3D62AEFD374"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0195-0196"),_T("01931F59C7630A1B2F93F317B961F956"),_T("01CBA97D70360CA0BDFA5DE6BDA81E72"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0197-0198"),_T("013BF16740D3351AF9695E6407C98CCD"),_T("01FF0D33D2B66880A08992BFC079D67E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0199-0201"),_T("01BE7402223A77113BA5B256C9C6F0A0"),_T("01E387C75185B38F03F72755FED78E23"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0202-0203"),_T("0101D798797EEDCB716D01E9249F9323"),_T("011BDF304280BC0CEF755487C1768AE1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0204-0205"),_T("0140E6C2E321FC84E4CC0E8E3E673605"),_T("01FF35BDA8A4920D7005942922170945"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0206-0207"),_T("01CDB2D0D2E48C9A334625947D5A03F3"),_T("01EB372FC55553561BBBC6A0F611811B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0208-0209"),_T("011282E3D3EA6EBB3E82A40E23457C4F"),_T("01FEF40DD58BB15342E27EEA563FAB91"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0210-0211"),_T("014BC1B7DF73E3859FB55B83662212F8"),_T("01D3D577995401BD13AD3DE5486F5410"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0212-0213"),_T("0170CE9375BB242C57042017076B26B7"),_T("01A090554DB6AC19AD0F115CF5C50C74"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0214-0215"),_T("016077995DA06695B9A79FC106DF90EB"),_T("019666EA7B2AAB54FF488C4FB1433D61"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0216-0217"),_T("01AFA5864E7B1831A46CE24922753EC1"),_T("01CB502FE905AFF42FE7974CCFA79E46"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0218"),_T("0154257DC075384E68903518B2E50833"),_T("01EC276018BCAB863F37703644F7E482"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0219-0220"),_T("016B40F14F627EF116C2BF5AEEF0911B"),_T("01CFCC57C80681053827D570ABB8C4F7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0221-0222"),_T("0184F5D819677C7C5F3DC67449EF1AF8"),_T("01BA88DE9F5ED718592D424347B544CA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0223-0224"),_T("011D0A500F8B772AA87957260AE2418A"),_T("016CB90C820ABF22026718C383C64852"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0225"),_T("018A0C0FBDE2385861078D1E0E66796F"),_T("01F5D68FBA719FF3C8F685FD57815658"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0226-0227"),_T("0175767D251F6D9462228543A21FC1FC"),_T("01A0DAF5AD35F93E1AC7A3C1688020DB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0228-0229"),_T("0155688A51658EF2A4D620E851251F2D"),_T("01ECDC70524EDBF9578ED76CB371ADD2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0230"),_T("0133F8440ED95E1CF6A22C633094E486"),_T("013665FB4674E8A03B1F5BB1FF4FE50A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0231-0232"),_T("011806C4A142F558FA34B7DA152A88D1"),_T("01B458CAD46CB1AD102CD19867C1F31D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0233-0234"),_T("015F4B1408D5D32314E622C007EC0E36"),_T("018918B22E5A0BD03DDD40A9EFF7ADA0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0235"),_T("011649A2C018937D2D6A6866EB9EA878"),_T("01F685EDE4697F7A54BEC8AD02747C0B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0236-0237"),_T("012EFFFBAC08525942D3B5A87FE5E8BF"),_T("019890C73537B5F3DE4525C640D0E5D5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0238"),_T("0142FE3E6227A5F805714FA78EE78FE0"),_T("0167D8ED180A72D688875A06F4C97A71"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0239-0240"),_T("0152CF7CC5A3E51C147B2F73B41061A8"),_T("019C5BE56272F419FDBDFFF2EE6C7BE5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0241"),_T("014B5051F8A15FDA93313FFB0CA80305"),_T("01D4220BC754A34CC3433BAC02C9DB44"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0242-0243"),_T("013CBB074AD3516731972B97FA633214"),_T("01FF2959188C37BB821EF4E005EF5A2C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0244"),_T("0120C506E3D67A32E14D4C311F08E049"),_T("0172226C0CDE175D59148C13FB22493D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0245-0246"),_T("012D01E9C979A65B61567B0CF43B1D2A"),_T("01A2B82DBF8317BD7DE51A6C2AEFC8C0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0247"),_T("013B712701EF86BECB39ADB93CC6AC92"),_T("017C22C408DFE161695256C8817821E2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0248-0249"),_T("017A0B79755B97F8E1B7239217EF8F1A"),_T("01E51FC640553BD5F7FDFE9F788B963E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0250"),_T("012BC876798D084DDDC8B15C0A888F0A"),_T("018128A750BE8ECAC95B90355C90F731"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0251"),_T("016590247EF75642C69D0E6549AB3F2D"),_T("01AE46F4AD34864476F6D3705E8E09EE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0252-0253"),_T("017E30CC8BF30E23C3D3D90E5AD81CB2"),_T("01F56B299ABF062A81CEFEC4E0EC858E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0254"),_T("015C2B61451212F09BA3C35FD11B8ABA"),_T("01784446567C08E4C0A3758BD3FE916F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0255"),_T("017D1C0CAB3D8BD6F9059B970B088BDC"),_T("01DFD59D9409C9AF49BB3D0F2A5E6C6A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0256-0257 (Low)"),_T("014196C461DEFB74E00440F3D2991D05"),_T("015F02EEE7A4CB7824E4F4D7558D75CA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0258"),_T("0167F8273061B6E3F9C4E45CE7DC3A6D"),_T("01DE720A4E7464E54FC0341D1020F40B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0259"),_T("010ED5474FA470D1FC43BB3433EC9D05"),_T("01B5CB99F543185E58AE0DB5CDF3A4D2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0260-0261"),_T("01B1D257C3F23179C939AA7DD1161F63"),_T("01BE43D3203CC0B00E48300C5DEB59A5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0262"),_T("015DAD73756A5193368D6517AF1D8493"),_T("01E017C96864CC2FD2AAA0046F70DB94"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0263"),_T("013DB11464FBC46A7C47478AA9A9D7AE"),_T("01B720AAC9BBE757EAAB0FAA1203B361"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0264-0265"),_T("0132ED26C8B816CE8850B895F4DCE3E8"),_T("01FFAA9B7400390FE7470715071D796E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0266"),_T("0169AED3A0F67E2C8488D72A6011961C"),_T("016B2C899283273B1E568196B9F0EC8F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0267"),_T("01E614AD096C0BBC6D3930B1C21D6F4A"),_T("01E761C004EF5A8603F3EB8198E2BF9F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0268"),_T("01499A7445CF67E1F91FD160221DFDB3"),_T("01A5F149E6942061F725B5F7BB29EE75"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0269"),_T("01379F5D785888DE67F8869769133BFE"),_T("01F1F074159797A96356BF36921E9221"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0270-0271"),_T("0144B7952F8D9D40A7DD27993540A022"),_T("01FDE9CA3F612ADD0BC23A4F7D883666"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0272"),_T("012E96FA94C824F9A8640AEA33DAE4C2"),_T("01FDCDF2BE27B0A172840806A70E21A6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0273"),_T("017C6B6BC4D2D426AC637CB266713EA3"),_T("01DE1EF2CAAFF234AB731F79D04A8A60"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0274"),_T("010E204824CFF3EFEB296E548D2831F6"),_T("01916B4116500E60BE5D144985FA237D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0275"),_T("0138088D42874B0741D3FC58F5573AF1"),_T("017E3E77F3505D19F7327DD7D2724FED"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0276"),_T("01098D59ED7C8AC69F2C1E20CF4E0CAC"),_T("01C6BB26799012DB2BCC96DA02220221"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0277-0278"),_T("01CA592B0A278C10375A6E4148FE6419"),_T("01E286256520B9A7B43B0222D0E69999"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0279"),_T("016A44AAF01EF90192F4573EAFEFAEDC"),_T("01A657B1A018AFFA2179C715508B0F25"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0280"),_T("01503F4EEBA4820DF555885B90A5C917"),_T("0188F1B513AEC3F28F4F34D7E2A79BFA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0281"),_T("0124752B6F53B757FF5AB259745EDDD3"),_T("01525932818E982A26993F09F4F92CB8"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0282"),_T("015AC49AF7DB5476531A72E670AB4655"),_T("01B2B99A8CBD11198C31AFAAD8640EF3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0283"),_T("014C59B66345954B61A51EAAAFBE6889"),_T("01542847E3D874AF2170840C401F0434"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0284"),_T("014991356E69A0C83FCE1B5326252396"),_T("01C75BC71D33F654F794FF5CFE6728CE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0285"),_T("016A5848CD54767A21084D3EBA1C8595"),_T("01942F78687AD71C00190D68849FE0C1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0286"),_T("0133BB7F25BB79CCA360CEBBE3C8CBD6"),_T("0198DFCF876DA1E81E92B7E9949D8155"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0287"),_T("01398276696E8F035EAEEB7B9AECD452"),_T("0155FF2B6BAE4AE1D1635FE67CCE8D0F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0288"),_T("01132101C4CEA4A437B39210AD463702"),_T("01637425BDE8E6F7E84F802802E9D126"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0289"),_T("0178B0F881697D3A35A0FF5EADEBBAB2"),_T("01DE18A63B1C8834DA9226AFED6724CF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0290"),_T("0153E02513D840FC99FE0B60EC6E5DC7"),_T("01C3F4EE67393C17F132E1C81761B80E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0291-0292"),_T("019D857D65A18858930E1E7D5D6B289B"),_T("01B1EB1585D954B41CDF72C01898778D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0293"),_T("01DE0FBFCDC2F65D93BA930372F59D41"),_T("01F94CFD5C2E1015E6EA3C240FCF11A1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0294"),_T("0192CBEA07A900E2422BCDA4741A3A00"),_T("01F9FABD244E1E79A0DC4CD9ADC55D48"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0295"),_T("01A25C1DDB83C5A4F020FF827B4E72B6"),_T("01D08774A3271E73C3E78532FDDE88EB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0296"),_T("018034E260B462D6E0F8ABFC8A3BB907"),_T("01F01BD0FBF6771B2850F5934646E944"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0297"),_T("016FF758B448E2511C296CBB45D3B033"),_T("0199D82603D51297B1F867AA942AE20A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0298"),_T("01AD570D9BB42F2D764F482FC66D3A97"),_T("01C47B48A2D9AA094611619C24AC2CB5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0299"),_T("012FBAE8007C11A27D87235DD8A08605"),_T("013CBF9607270A1954C81E459DD4F336"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0300"),_T("01C5200A6DBF9165C917066FA4860C0C"),_T("01FF6D37252274C859416FA6F98AC090"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0301"),_T("0116153BACF3F792E59FF7836DDAE7D8"),_T("0121A96A82547450CF8F58BF84284C15"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0302"),_T("0109E20C03C96B7AEF53CA5EAA5AD1DF"),_T("0114B45FD68923F2128B84DF8A6F3CCB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0303"),_T("01D50D828028DF78913C1B8DABECCEEC"),_T("01E004DBF278C6DFFD3189B29FE6093E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0304"),_T("015F75D0539DB0AA33DE9086D3D634AB"),_T("01D561C82C0BF4F7C83321A6DBED8824"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0305"),_T("0126229976467EACBF032D4C5A2D127F"),_T("016BB7A9E6546985118526AA7631651C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0306"),_T("010B8E92977DA6223CBE535BBF4A4367"),_T("0190F4E50734B3691B95FF3AB0F2D858"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0307"),_T("012E91AA6F00BAAD85F8F2B6BAD82926"),_T("01DB44FD317523A4D3C0A5C56340D7AC"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0308"),_T("01772ED0AD3C1C1BFFC38E66898E3A35"),_T("01B0F92606B6AE035255B817ACAC850C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0309"),_T("01E1865EA4F6ECE601AC4422624C6121"),_T("01F7FFE8BE356C30D30EAEF9D85EC512"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0310"),_T("01A33A9D8610B69649BD2CA4291CC025"),_T("01B1997E3D406AB0A132C98A655550C9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0311"),_T("016EDA1C4521F0E5445B34F1345661EF"),_T("01F413B54D77AACC10C5EBAF527DE7DD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0312"),_T("017269EE6347D641396E6CE4EEC55545"),_T("0176C0087432177BDECB6B0564EDDD75"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0313"),_T("016BC2EE578196DA4ABC2BF857D60F14"),_T("018A160913B05A8E2A50F81D6F69EA46"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0314"),_T("01556C09EA00DD3C189F2BDA34787961"),_T("016371B1B482BFD9A55E101227864AA9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0315"),_T("01A22C90AA6B01914EF92C2EDD4399AE"),_T("01ABB8850DBCB396508E3A42659A9EE3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0316"),_T("016CB97F1CFD2C57C286C575F7F99531"),_T("01804E265A2A88E90D54A114FC8DDDE7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0317"),_T("019407B1682B8D28EC04607FA2B19EC3"),_T("01FFBFD4B46EAC504CD923FFB9E49131"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0318"),_T("015F455CD02BC42D60842BEFCD24E35E"),_T("01BE7EA9208B1F968C165587E7957E82"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0319"),_T("011D57FF8285857AA73865075C50B528"),_T("01EE6332FE27FACA6561FB159CD2C165"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0320"),_T("01B103E031429E917A31E86C3DA634DA"),_T("01F502A2624B1A16EB133755300467CD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0321"),_T("01325ED8501E998C8603C6B115102D5E"),_T("0139FD353945B81AA25529086E0CC5A3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0322-0324"),_T("012514374A61C0E0205A43EC2CC2DA8B"),_T("01298A5758D10D013E0130A6B560A15B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0325"),_T("0133FC69E52E74319F110B4486B8B0D8"),_T("017FEB124293E03634B25E85B537A2E9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0326"),_T("016D7EDE7606414D991E6952E80EE1F7"),_T("01D115190D8DC08B0088CEBD49ABDF3D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0327"),_T("012BFA25EC8A81E6A52D3EDD9EFFBB7A"),_T("01F64137199157B9971E5368174CC3E6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0328"),_T("01CA390C3C7A086D1F674E0F8DE3E487"),_T("01EA3E9E6C1AF5D15ED5E617A2D3D89F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0329"),_T("018AA265EEE919D20B4D74CB4CBCD9FF"),_T("01B0F2C7ECCAF189E47337AE0B2BE871"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0330"),_T("0138B43587335B7136A83646BB8C8444"),_T("016FC91B845047794BC8718125DC1D22"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0331"),_T("010706DCEC9384FCD911CE7EF6F9AA10"),_T("01DF585825BD040888218151BB180485"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0332"),_T("017A73E137683F2CF27F35A8EA277B2D"),_T("01ABB6CF48A47B6B69ACD617CA381C96"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0333"),_T("0172CBBAFDC69B2DB22550D9FFFDD5DA"),_T("018A1D72EF163CB05CC015BDAB62E943"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0334"),_T("0115214D14B7DBBE80708BF92F07C0E5"),_T("017AA2772964687B2C60899FC0DDF260"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0335"),_T("01BA0E6EAF685E372997C5158873A934"),_T("01E720041665A7B0028E31EB34495D45"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0336"),_T("010C82C21FFB556423D2E1AEA09D6AC3"),_T("01ADCE0CBE4B4BD36E8990DCA71F41FD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0337"),_T("017A6A4E8D40701EDD2BE40F880699A7"),_T("01F2C7A73B2E5BFBCE9E680FCF33B732"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0338"),_T("0113FADEC57583A1B8DF0EA04A8984FA"),_T("014A17E0D9EAE8D5CCFEADB7A409172E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0339"),_T("01B54851F7FAFFE3F3FFB0C98045C20F"),_T("01CD762DB17AE5F82C0534B07A265DFD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0340"),_T("0106D7625E411877CAA338676E05E5AB"),_T("01E04BE11B708F7730D5A91B89AAA914"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0341"),_T("01DEEF0C26CDB5F18CB5C30AC67D10DF"),_T("01E6FBB5A4BF581F87F339D62578258A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0342"),_T("0196CC9924E6BD959AE089F5862BA560"),_T("01D8CB2710CC698C40143FF0E146E3BF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0343"),_T("0197C4CC8A2121EB59A6E3400A8295EF"),_T("01F136537F044C37185E4D19C744AD9E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0344"),_T("011EC85456FAD165DBF5C6A5007C3E07"),_T("01805F382A0E1E5D4D49D5612C5B1FA2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0345"),_T("0161F9E8EE00BA1E250B7D55F186F72C"),_T("01CBEA20A3945A17C97EDB92D1A3F8C1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0346"),_T("01488B03814992ED43EF64D8659F28BA"),_T("01D730E0F6C17C9617BCDC128B90C379"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0347"),_T("015CC783479C3D9A25A18AE2C2FCF0EA"),_T("016D96CCCD278808EF958DD1C5315158"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0348"),_T("01A4190E753515CDBA00BEA808B04D1A"),_T("01FC1898602DF6895977522E10374788"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0349"),_T("0111982B37FDFA77D6C9C7356D9548D0"),_T("017E046DBD0AD3AFA3BD1443BB27D017"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0350"),_T("01273B05269AB49659658826842AC1AA"),_T("01851D05C185ADA1F03BA1DD7EB693BD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0351"),_T("014B69771DC99F42CF7E75A92453A27F"),_T("0163F1FB5A0DCBA8FE6D85138E1F9338"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0352"),_T("0132FFC1D7FEBB3B053AC02AD51A16A0"),_T("0158A45982834ED63790DC6DF9C6A626"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0353"),_T("0107A54863D862C397614B7A892B7C6E"),_T("010ACB017888870B12D192AACBD700FF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0354"),_T("0103CB9729158D46CF1DB0689CA14F7D"),_T("0132626CADD62AF02D5FD0DF263B71D3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0355"),_T("01C9AB1473B3FB383D976870F68AE1EE"),_T("01D58ADDAA7168BB2208616E8E37FAA4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0356"),_T("019140D94D7A9941798F2A71CA5437D6"),_T("01B52C9B356883331ADB76B001F7F391"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0357"),_T("01AD256679DDC2EDD0DBE80F157D88AE"),_T("01E1C17643BC7FFAFB439F32EA785BD1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0358"),_T("017CAA0B0B61BCE22B54D21D2890EE91"),_T("01A817DB5F8B63ED712C4E5726334B7B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0359"),_T("01B72416616B03EC44EE529F97A61DCB"),_T("01DF2FC19A3231A7DB9F482D79B38A62"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0360"),_T("0159B37AE98E23EBE3CC1A4F3B5D1EFC"),_T("01D2D675F82D7B1AF96E84C473447C62"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0361"),_T("014CDC93234C1379FE22988D7402782C"),_T("01A8A9D00F826AEAD001518F2CD437B5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0362"),_T("01B993B11363C5FA17FE7D38FCF8C2F4"),_T("01D377C41EC4C2584EE46CB3A4436280"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0363"),_T("01EB34994D5E62FC5E52F8DDEFE3D2F4"),_T("01F598EBE426AEE87D8F456C07B7EFF6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0364"),_T("0119CF37863A6A7F7EF49EAD67AF66E0"),_T("016723371317F92E47C1364768EA973A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0365"),_T("01787808AA17389825519FF453F8BFB6"),_T("01EBD34BDA688D36A8AD061F1095AE64"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0366"),_T("01E24A057CCF3F9D4E36888CD54AFDDA"),_T("01E9C7A6AA13FF21D1EB0B0C0096A915"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0367"),_T("014820A0E94228F9300AC1C09F07AEA6"),_T("01559974BDEC2A6063D9929B872E2A61"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0368"),_T("010558C701B4128C1C5E4E6C90F78286"),_T("0116171C8A2FC260EC329F719E262E0E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0369"),_T("0147126750ACC655ADDE82C1EFF1C0D3"),_T("01AAF51AFB5BA9B5505C1A9081C8DF57"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0370"),_T("0152506665FCB02684140B07D207A770"),_T("01BB0D0BE601F1B02E43FA4AC95605C5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0371"),_T("01DB04A9499D69E56B91AC0DC16F22EB"),_T("01E24EF7397BC708EF485D8CDFB19973"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0372"),_T("014FF9AFBE7E78E178C583D0F2125008"),_T("01D39DF0A6282B2C2398C38DEFBFF1B1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0373"),_T("01D782AF987ED53E7E4082935788895F"),_T("01DBF5EDF65B6D3F953F7D78CB8646B5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0374"),_T("0127E66E3B0B4204DAB9A632C5EC0767"),_T("014ABD9E2286076902B40329C4E8E6A5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0375"),_T("0141DBB33F21E5ED0522800C8BF949B1"),_T("016E46DAFFB0299EAE565529E35572AC"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0376"),_T("011DF0955ED033F1136A7590B06E90B5"),_T("01B747309643CBC602FB70CA27DE7F55"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0377"),_T("01C3F32F5E678D3A7423DE27C938F01A"),_T("01D84EA5162D47C996A6777BC27504BB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0378"),_T("010DFF2B2F6AA668ED2612ADE8C9B3C2"),_T("01EDA6A155F9852329767462E5CD76C2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0379"),_T("01D3C34273ECB6591C4E721E283A640C"),_T("01F62E7C97C688FDF31B6E2F81454F94"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0380"),_T("0171F9A47B9B30D078F234F4418ACE45"),_T("01B5F0DDCCE9EBE5969E992D01129CF5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0381"),_T("01974F95F7C16468E32AD38170E510EA"),_T("019C1DAFA502776E7BAAC4747AB3332F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0382"),_T("019782C31B0C831845D73F5543BC98BE"),_T("01E15F4211BDD6C4F5E0F77E9326D1CE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0383"),_T("0177AC904C4E007252A91C25DCBB14EB"),_T("01DF68AB84D32B71FAD42C11B73B6BB8"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0384"),_T("011400D468605B952AE88B8B10A18171"),_T("01DA14E2A02A7AD3469068CD7F038457"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0385"),_T("0155EF820020ADFABE1533A4F67C0B80"),_T("01C481734231F722C7445B0C55C84239"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0386"),_T("010E6513BE81BED0D4B36BD462D666E8"),_T("0134F1B277A728D903AFD77DB4619C00"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0387"),_T("01989BEAC872A1B99539690065A39C54"),_T("01A02FDF2E7F6DBB0A71AFCF077AED79"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0388"),_T("01540532C51FA06508D087686FD0DCFF"),_T("01D0DFB151D286F2298B6B28FAC28546"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0389"),_T("01950F306D0ACDBACB1E943077B6C502"),_T("01A1D2743EA64B7003A8866879ACD83C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0390"),_T("010520B3289F6C115E6C7FB5FF94AD23"),_T("011393F781C1F5604BBBE037EA344772"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0391"),_T("014291231A0D750BD42E7379AB2EC9A7"),_T("0155BC2CEB317B56429D72E3832C276B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0392"),_T("0119045ACB656B2AA89B8B7E7AA9A11C"),_T("0181F7838B94CC005C4D9415A9FC4AC5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0393"),_T("0108315A37ECD25AB2C3C7D34D8FAEE6"),_T("018EBB3CEB30AC32525A83E9674F4AD2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0394"),_T("0146224B58B822FA02B2550303B29173"),_T("01C941D2C9C9D882C499CF6C3B606ABF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0395"),_T("01B0AE5A64CD5462E66AE5E3E03A619C"),_T("01CD547BDD05B363D522676F3D639052"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0396"),_T("01812B79812DA11637F57EF135221694"),_T("01EBDB2DE50293CD4DF8563A62CC6BD7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0397"),_T("01135549E44963F5BED69C19E01A626A"),_T("01D082E1F33592E8ED3C0D04C34ADDF2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0398"),_T("013643035BD0BBCF2848799DDF50EC2A"),_T("013851E6565FCD218A8178D6C6A177A1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0399"),_T("01003B03E43F3C08EF305568D1EAA2C4"),_T("01040E165069A205217F6A88EC5AEEED"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0400"),_T("01764B33356D627246D9BDE18256C8F3"),_T("01DA8ADB8F6C79F85E968B77B23B1636"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0401"),_T("014DCDA30453F991F9C987E71F33A01D"),_T("0192427F2575D9764AEBFE1887CA89C2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0402"),_T("01B03481E5EE1AF8A0D9CF4B6D0C9B7E"),_T("01D28F1C9D3EDA1FADD49B775A70994C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0403"),_T("011A1AD05F4E69637D54F7644F73A677"),_T("01F0A14448D6798A5AEEE50E8C24544E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0404"),_T("0146220BE1E3384C10CE628D5C8FFF66"),_T("014B01295466371C1D24CA6CD2CA6C9A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0405"),_T("014DF9897E85EA56455369FCDD6F6E70"),_T("01877A475F66FE110F7B8A3A816A9133"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0406"),_T("013D8437D836E4297D1772BAC1E5F43E"),_T("015E43C944E17354042EBC370845C575"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0407"),_T("0148FC19E8FBB1851F30AE5F45112705"),_T("0161A26E905FA28126885B6AF72A8D1D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0408"),_T("01C637C2623EE02B60F7F0A6B3FDD32A"),_T("01FD447287C5C847EC6545B2B8CB387C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0409"),_T("013DB44FDC160E2254E0FC7175AF4A4B"),_T("0194A4989DAE98C41ED27CC38AE1E04C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0410"),_T("01369181F64CC932F704247634847989"),_T("01F40C8B0BE2B857818AB7D54AD1700B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0411"),_T("0139A96A7EF90701633DF35E361484C9"),_T("01634F996ABAFB8624801B6BC71E0EB8"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0412"),_T("013BE218116F5C424D76F2889433ABC9"),_T("01F21D487E1140F08F6ED715C608283A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0413"),_T("01386F898D3FF042622254961860D2C1"),_T("0175C60DE795C1DBEC7FA2569E7C4BCE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0414"),_T("011344654042CFE5285074B9F759FE54"),_T("0156573AD1A42BB73D971215B649BFAA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0415"),_T("0140F1E3574A5277EDB2B7D62DB91A73"),_T("01A3CFDE5BB74875D0CD9845A0CD0579"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0416"),_T("01254CDD816D22F1274A2408AF25D54A"),_T("01A60E05A006B83663C13F79E518EF68"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0417"),_T("014C1996E3D5846DC928502735000E1E"),_T("0170BDFC71B6904408B13C98438A3F73"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0418"),_T("01268E71573851865FFC033A73EDA838"),_T("01B8E57A1D406AFDEEC40992332407EB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0419"),_T("011C34244A1783F3081F338394B63FDF"),_T("016406DD22AE88220391FDC65315C5AD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0420"),_T("010A6E0576302CA936E447F4618A8431"),_T("0114DA572C12C1D8AE051ACF5A968E96"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0421"),_T("015BF7F9F6764C265708C62043034F68"),_T("01C29B72AD423BCDA0B3413A8628AA87"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0422"),_T("0130BC5C262DE544C733420AC8384EAE"),_T("0199B34FC298156BAE8E81C9D04ACE15"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0423"),_T("013382A238A823BE795E8D8D5BCD2A2F"),_T("01986EC7F03B04BF24F244C32880FAA0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0424"),_T("0198EAD8D50C4408C1D37D44C3443C3B"),_T("01CD3B8FBA42269AEEBA7D8F9656C68E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0425"),_T("0131E2F41BA4D1CCC0F9DD6178DFCF4D"),_T("01509FC32735787D681CFD1BD18758BA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0426"),_T("011E7A4569DBA0E121E81D91462DE65F"),_T("016C961BE702BA452A489DF42A99FAFA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0427"),_T("01324B15EEECCFDE0D7A907E54A4C8BA"),_T("01B29068D17071B95DEF63969BF07253"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0428"),_T("01C7A2581BDE73567E3F07F99A904A72"),_T("01D7AEBAD9445D81EF0C99DBB30AF533"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0429"),_T("012891FD6E0DCC297BB5AD1D057353C2"),_T("0159A1AA837820FF99E28074A49CD849"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0430"),_T("0147411E31D4761D3303D58AC31C2B52"),_T("01F78B8C83226968EABF8E6FEEFA0CDD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0431"),_T("019A48C7F1949EE3F71EFDDEA395C4BE"),_T("01C53231B84B5784FF30F8C59BD01B14"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0432"),_T("010BDC7D1187FF0CB1CC6783A6199A36"),_T("01778D57EE62B36E06D41C8DC1A6E325"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0433"),_T("0175371036D9DE51EDAA0144E0A199CC"),_T("01AAF3BEB2C40054C86617289EF54FCF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0434"),_T("01331210DC5BB6795AA27B45B7AF373C"),_T("01FD55DE693D807A56CD1312F90489FA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0435"),_T("013E49E627D57319B424AD1FC37D9ED1"),_T("014DC069EF03293A2F0F42BD66D827B4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0436"),_T("019A93C48B520B1C40B9E7F3F6C6E473"),_T("01CFF2CFDBA3E60F9DFB4898F9E09816"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0437"),_T("01B0CE0F01EFBF706846A02896471923"),_T("01B9A8DD143D350ACB16069CBE1AD772"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0438"),_T("0185F3A0CE832BCCCE4DC841C5080CA7"),_T("01BFCDD7D711F3A95C288EE3035688D0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0439"),_T("016A5E7F4B01C1E50C9F29A36772EEE2"),_T("0189C05B83E027D45FE58BB3DC2579EE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0440"),_T("01B0A8D9978F8EF27815C03F48AB841D"),_T("01F34A28FABF97747395BB712AC37AE9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0441"),_T("0180E29802FE7454A524F36FE0B6B43A"),_T("01B6E6284CA2C0A3046839BFAEF215EA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0442"),_T("01A2B2EEE6F4EDCC72F54984E6409CDC"),_T("01B7C182BEBB12D0D557CB87715350A0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0443"),_T("0120474BD1393DEE893F4D918F8A3BED"),_T("01FAC7D572FE578DBE58A68BFD29F75B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0444"),_T("013C95A781126474E7935C84880C1363"),_T("016D3F0FE62365F68006C20886E6652B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0445"),_T("01140702441D18A8B38FF0AB59FDDE87"),_T("016793590F30219FAE2FC6A30C6CE624"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0446"),_T("01227400E7A08A512FFB19410CB9220F"),_T("0187B8FCF67A7E3DCB9B86374A48E31B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0447"),_T("011D931D35DD43E4D64643598BC6D2B1"),_T("01FC51D4686A6A12459792FEA57DFD41"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0448"),_T("018C55FB6FD97073BC8637B8203940B7"),_T("01CDFC8965E4A7BF7B44B86BE150A2C2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0449"),_T("01A2EEB0662AE55C1294513B6DC109BF"),_T("01D3EBC5FFC2A0A96533DD881E068D6B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0450"),_T("0191EB02D6A1677CB75B2C8505E352F4"),_T("01F866C46749929C0598EABA0DDEC439"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0451"),_T("013AC1A7E3E9D9CC676CCD7A543DB582"),_T("01D75C158973ED2DAEC8B07F552CF938"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0452"),_T("0157532D8B0C1B683254879AADA840C2"),_T("01DE075217BE9633DC710384A4D6EDD9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0453"),_T("0174C6747387A33B3A96B6323A15B8B6"),_T("01A95551F1C9CD937B95D861456ECC97"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0454"),_T("012C392B5613E551A6821FA0E54F8CFD"),_T("019B5FF7C37E4BF52F9FE041251C7BB9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0455"),_T("0105F9C080293209E3AEBE1CECCC7D4A"),_T("01412D3CE77A43A575221DFF8CBC28D4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0456"),_T("01199A62B009B1F466CB0E0E6404EE08"),_T("01A2D9C8FEF5C4E019E77966B259016B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0457"),_T("018E848CD3DF1DBDB5D82CE001CDB448"),_T("01ACEB6CEDF0722C80924FDB80FB7D70"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0458"),_T("015BA90DD391A7F10D2C01DB2166FCB6"),_T("01C6212E754EC57178CBCB82946709CA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0459"),_T("012803DC9428F1BD30D74DED1B197AC8"),_T("01D96024DEAB04F4882E3DC5609C28FF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0460"),_T("014B284F6780E8431B6782F7C3FB2443"),_T("0190740B961CD87EBF3396052B5C8A61"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0461"),_T("010B19115B7E61CE2DB4BDA480120DEA"),_T("01BF61EACB8030C7AACFDB5A3A2CA383"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0462"),_T("0148F74AFF4C0FEFD9AA0038F0D06096"),_T("01E9206DCEB55FD53A45A1FC49D0B0D6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0463"),_T("0133F236363BB55A3DC0C6487232F70D"),_T("01FC63F6C6038C347FC3CB3F4600EB52"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0464-0465"),_T("017F4D6A4D88E1F797C7244C6D159DC1"),_T("01C49F65720FB8B657FF0BEA2FD7C3C7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0466-0467"),_T("012D821C6AB210E2A753BE053B8F55D0"),_T("0182408A81A4ABF04D4A34A8A5E98C58"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0468"),_T("013AC1608F7A083FA54F0ABC612E36C8"),_T("017EED788940B9E835B3EAE7CC4EB840"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0469"),_T("016B4A8253BFBD3B16FDE14E5A2C2E78"),_T("01E65D760D8EABCACFDA5F7D80EE41B1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0470"),_T("015641547A6E6FA36EAF79B1E50EE7DD"),_T("01C4A96E0D533D4CE4AF07371FC45AEE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0471"),_T("010722A0620056E9A2FF35D172ED6BA3"),_T("01789360A074D94FBF180890C02F8CF1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0472"),_T("01A0A7C8FAD86CD51719B4D11B809A75"),_T("01E5FCE7A9DD101E94A9E32B66E8C4EE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0473"),_T("019D13E47EAD93B95DFE2D80B9FB81E6"),_T("01C55AAD2822F315C3E2D3F0CD4000A7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0474"),_T("01353632E1E04A7081884271A93A13B1"),_T("0159E5C814BC1605AEE28A0EE89E4F0A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0475"),_T("01977A5680033292F498E7CF4EB62437"),_T("0199439B7E7464FEA9A6FC0FC1285B9E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0476"),_T("011CAE68B99D05085FC30546A1DB3452"),_T("018463C3E6CABB68E655411E87FBFCB4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0477"),_T("014FAF505C1A45011F1E99F280135A18"),_T("01CF2E949F6F3973B17077A6DCD078CC"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0478"),_T("01C02512D0005A0849AB22F0BDDC0E2B"),_T("01DF7500501CAE9F89E0CC7660CDDF72"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0479"),_T("010F353D6181F73F425C37F9A1282695"),_T("0159E6F0AF54E1502B58942F96A0A2B0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0480"),_T("0140B3EDC42BED8D7893372A2EE399A5"),_T("0188BCF4D70EED40EAB0A6AE12C8856E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0481"),_T("01390D43C65FD5DF5DA1CF416607E83C"),_T("01D95D92A1702017D722D918EB17D7E9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0482"),_T("013319E9ACFC1592EA3707443D41379B"),_T("01C641A80FA9F17A2F80671405FA645D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0483"),_T("0193978466E8C45B530015DAD9771756"),_T("01B431F54E253079EFBC6E35AA851485"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0484"),_T("010AF02A7E11380A8E7048EC838C9146"),_T("0174C6950A3ECB17C3EDAE3943CA0E74"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0485"),_T("01A37EC6A34E45D9E324A41C3C1F8D0A"),_T("01E56E1F28A07DA431A8E941A4ED3D6F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0486"),_T("019BFA737D93AE4E810BCEC1BF622FE1"),_T("01F604112EDD2CD75252A3F4E7914186"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0487"),_T("011E8FC3005D787803DC61391250E11C"),_T("01260816124E68FB34B3C5A968652188"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0488"),_T("0180ED9DF7C292F9E6EE10AA0EC33D93"),_T("01DBCB52A9F4D5EF652ADE91D3DBC20F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0489"),_T("013CE5A98CA06564271913E97E17091C"),_T("01CA8DB74626EB5ADDDE924CBB808177"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0490"),_T("018C33F34E14965F901D87E2F5059D76"),_T("01A2863D209D69C318C2D791ED4A198B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0491"),_T("01CC427EE894AC6DA5233F1BB70DA151"),_T("01D392E7B3F2274DA633A257D3335513"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0492"),_T("016AE6407F27503483641CB265E3666F"),_T("01ED61C6EB014A13D153CCB63075CADE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0493"),_T("016A8B9D3E06915B6057C1A4E9925FAF"),_T("01EADF79B040CBDA0A3329190FFF5E60"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0494"),_T("011C975826DF4E650B123D6CBD745FEF"),_T("01A9583C33385BE8C5D9AA8DF5C4A2A9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0495"),_T("0186DDA3C99987029C896738E83A6423"),_T("01A083083E3BF1EB8EA792091F3FDEAB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0496"),_T("01013C1CD527C24F7C5DB1A915507C76"),_T("01EA1DEEE251FDD2C98F1A1E7CF06DB0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0497"),_T("0115991B24A2457586CC3A252FAEDF93"),_T("012B0F71ACD29195BD62C24AAD206F86"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0498"),_T("0174EE93AABA2457FB0A41BCAE94A025"),_T("01B6C9DDB75BE6F5A0AFC904F69999BE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0499"),_T("01AC981B3281A80EEA9A1EE13766901D"),_T("01EFF430D5EA2DED89B39B35669A4889"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0500"),_T("010A9056CAEBB877BB3ADA1540D60D26"),_T("016FE42D5D9723FEE0EEE84FF3D859A0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0501"),_T("012B575006786ECBF308796237665A0D"),_T("0187FE84BF2728468C1F8DAD7BAC74D6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0502"),_T("0114F3762062837D521FC2EE9DA92199"),_T("01826894D6D5FCEF1DE9F84C2E926253"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0503"),_T("012D23D883E0AD3058D4CAF7CFEA8160"),_T("01ABE7D58F64F0BACB5F3745A1571F8C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0504"),_T("01412DDD7EF447F4BE51597651384825"),_T("018B9740A2EF139B8A4CABE1EA9082BF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0505"),_T("0104D700393677934A3376EE0EF59B10"),_T("014E439B42B0BC98DE98769652F16506"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0506"),_T("010ECBD9D88CECC0BFC1D6EDCDA59A5A"),_T("01210F00D2B4E698BFE43D6500739FCD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0507"),_T("0116F7ED80AA7FB5288AB995FA31E7C8"),_T("015B8CB1DC0E7027278339C4A2548446"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0508"),_T("013B3824930D0195BED318AAE153C0AA"),_T("0159AF9A6C1A473B1BA1D3B1A1ADEA62"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0509"),_T("0135589828B5D78F89F92CFF0BAD7B1F"),_T("013D977C1BBFC9367671545500BAF3A8"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0510"),_T("010A47B0AAC2F9AF94E42FCB5F9784DE"),_T("01D59C3006B20C6C80E322B72E56BC61"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0511"),_T("01EBA0DB74E96523A5EFFC5591CA7710"),_T("01FA385AAC22610419A213399C6090ED"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0512 (Medium)"),_T("0119EF3DDFC8AFAE643E7D5C02A7BD06"),_T("01D050F7B28604722499747F698AE37B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0513"),_T("013BA6E39F3A8198BC9CC8BBE88CC7E8"),_T("0148D2AD5FB27F03DD7EF6494E374DF3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0514"),_T("013829C572356A4F2C6F81A1B4909309"),_T("013E47531452F2C6FE57201ADF6EE8ED"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0515"),_T("017874969F6A9CC97F2867FA0A05E7B4"),_T("01DAFBE1190C8C50FD91602E042E2FF5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0516"),_T("018A74BE1C5A6707E2DA4057C7A4FE5C"),_T("01F92C3E6FEEF1D9EB564CC49B8CB41C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0517"),_T("013E2307EAA7A15304CF3B76CBF7C16A"),_T("01EE0AD6E211AACA392B5E03530E9C09"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0518"),_T("01C30FD636D41E1204C54F7D4607BE82"),_T("01D00D35AA2C30286149F79BAEACBA7C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0519"),_T("01173D1EBB33A4F2E070B5867F132C6E"),_T("01A266B175D7197CB016173224B78D9D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0520"),_T("01B3DA8CF02BDE7FA68D34243C140F69"),_T("01E9D25593908740A63E07F070225F1E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0521"),_T("0193C847546BD23021C382452F392451"),_T("01ABF300C7DB5E8A406DCC4F27517827"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0522"),_T("01483D27FEBDB0A0700DDC8B13447A29"),_T("0150AA0F3370CCD475ABA3F176C7246B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0523"),_T("018EB546459E180ED0A78376F0B86DD1"),_T("01C4C5A323B32B46E52F5A44DF16AE86"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0524"),_T("0149EDD8F40A4F402E9C85140D5F5E64"),_T("016592157E2278248194FD0CB1628859"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0525"),_T("012B9F12897CC495658FA7C8E71F6129"),_T("01A7688231540AA058762F89F7532D3D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0526"),_T("018AECA8CEB44F688DB3E833244D4F17"),_T("018CCCA6C1F54BC6DD537E90FC9BA14B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0527"),_T("018E05B59673206626E97C3D7EB3E533"),_T("01D99B8F7C5E1793F94EB6F0F1F5C413"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0528"),_T("019BB8FFFCBA7222C2603E5B4359CA95"),_T("01ACB248F872EC6A233D9828B10C2711"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0529"),_T("01725A3AA5DD3A8950439B2A12422310"),_T("01C63D32D890102FE2AE651723FC4658"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0530"),_T("0109874E43EEA38503A27E21619D3419"),_T("014510AF5A2662C30D8E86668401002F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0531"),_T("015B62A53E2AAE1F9C45F8E53D8615F8"),_T("016AD3B63321BDE3E3AFC869984AF05C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0532-0533"),_T("01315330924E21101CEA22D844F5DA75"),_T("01FF5B0059671E82BC316B53A3EA430B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0534"),_T("010F281AAFB3DAA7AB9579A81A32F83A"),_T("0179878902493D17D868B06656C11D49"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0535"),_T("01361651FFB7E4064EDD1CB4AC1F79E8"),_T("01F6F4526A88E2F8FD82962A49B970E7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0536"),_T("01CDF4161B9EAD0944C4C637713F890D"),_T("01F64488A68083AA011C86EDD9B6DB5F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0537"),_T("01041AFF93E2B634CF24E47D12B10123"),_T("01495220A029A18FE0BBFF73BBBE2A76"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0538"),_T("011CEDE2297091B8203EFA1EA2099CE9"),_T("01DF29B9885FF8B13FE401DD941DD6DC"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0539"),_T("01BDA2739C2D2EED4F87164EF88E8424"),_T("01E5201E2D8E6D430410D083445CB274"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0540"),_T("011AFCF5E21D51C4C46E47E4836536DF"),_T("01572CAF26F97C3991673130F5B79406"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0541"),_T("0177A848BE829FB1D0CA048C07803325"),_T("017B428D20074AD5EA7D1B5A1F1E9B54"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0542"),_T("017A6B4FE4405C5D571F6EF30CC6754C"),_T("01EA537E8D3B4E668D1762C74DAF2916"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0543"),_T("011E948E332DDBFBAD817997E6496D08"),_T("013EC1BED397021141FBBAE1E85A10E7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0544"),_T("01079651EEF6AEAF5559E1ABF169AA9A"),_T("01646999D0D1059FBADEC52358A8E186"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0545"),_T("01199F4840E879CF90C93F2A3C032765"),_T("01824E11B5A82C46E2979AC1EB972FD6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0546"),_T("01D467159EF7FC037D4BC15975425DB0"),_T("01E07FF8FDA5AFD0F161A6916A487FF6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0547"),_T("01337CCAB01F142FFB043309C1BE89ED"),_T("01D9E65ABF15551CA1E4E850CAC18341"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0548"),_T("014D94DD0540F158FB57C393AABE6446"),_T("019AFB1E0C3E302F1A4FD4A872A06043"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0549"),_T("0158258EA1FD2608AB5B950D7F4ACEB8"),_T("018F0A6CDEB1D850B343B4AA3C6BAF47"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0550"),_T("0172F4A74DC5EAE3E3211EEB52E8E2D6"),_T("0175533E6936247A24A4E723429BE097"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0551-0552"),_T("01215F8B546A79060EE355A2E97B66F0"),_T("0148A415D0B4F9D30AE5AFCE60FD785B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0553"),_T("0130A8F30CE48AEDB0BA769B98F622E0"),_T("01C2B78C71BC9D738A4A98016B6166AB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0554"),_T("012B879B089D4682F35808BB55E714CC"),_T("012C7B5581572F1B7E656E2506297A25"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0555"),_T("016DA97EE5CBA9DB6AFE79095C8B67A8"),_T("01EEDA8D76433F3826EF1D55DBAFB6DF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0556"),_T("019217C84EEB33F8F15541663490144F"),_T("01DE7129878875B91093EEFB15F4ADAE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0557"),_T("010CA54F01885376F1BC40C9443F09C9"),_T("01DCCC15C2CFFBD8726C36AF07432733"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0558"),_T("01529AC7132D369E6C8153BF022A572F"),_T("019D0AEA75EFC29E8E40EC2CF0D2F52A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0559"),_T("017ABA62F8D535F93EC1748A6CC8930C"),_T("018F557B9267C9728DF25AFC88375EA9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0560"),_T("01D0CCC1F1497C77980638AB280C571D"),_T("01E0A9A04CB177D7C1B9DC126FFC24BB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0561"),_T("011AEC06FC3F1F97B6B511D8291BDEA3"),_T("016497F7069C0C1B3DEEC411B70492EF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0562"),_T("011020A8CE017867DBAEFE0AD14F6766"),_T("013C6F7BC009FB2C14B5CD427986C52B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0563"),_T("016D89BCB9CFA1EBDD85664CFC4F28BF"),_T("01E28F5CCACCC03267E34838C87F40A5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0564"),_T("011A24D4D1F20D578607BC06AB1C570E"),_T("0169E3418F2F19EE06D7E139133BC098"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0565"),_T("013DD6F8235429E6C462178C6BB4607B"),_T("01539D2AEFB11A47144BE2DF97712599"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0566"),_T("0142ABD5F13DC0E83CBD65CACA5B5B89"),_T("016739FA7498D8D0EFDC177C323DC489"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0567"),_T("0186A524B452BD06FE2B3514423D66CD"),_T("01E27A9C1791474E596B64F9FBFF6F3A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0568"),_T("013FDD18059D23A2022F75AD850AE91B"),_T("01D43AA02F96D9715FCC389EC237D9D5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0569"),_T("0196F647E3787E7D1D8D435C25682A43"),_T("01A2A6C89226F66B40054A4E11C68A09"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0570"),_T("0160F53AA8AE22485E9FE1A3B5626243"),_T("01717E8FB416A5B5B6AB7A21773907B6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0571"),_T("013D8ACC259EA3DEFA871BDA970004EF"),_T("017964C23B09E531380036E45A0034F2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0572"),_T("011BDB09582A077704EF571A2DAECC0D"),_T("013A79D63066295F6721AF900B86D7D6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0573"),_T("01405E2A203BD650AF23FFB5BABCA259"),_T("0196E4626FF74CA6CD5324A9EA119AC5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0574"),_T("01196A438AEA19420E2EBFA693B24A3F"),_T("01CBD656AFC34BFE37ED9AAF5A6C9660"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0575"),_T("01A4BD144F232B5FD61732389CA2C61A"),_T("01F3FD2303A977F8AE85BFCFF1A4B2C7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0576"),_T("011A501544AD16AE1BF926EDB16D7E60"),_T("01E2E90275E1D6117E1FC4EFBCB2E758"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0577"),_T("014F5E4309F2016B7C520C8C4D6124BE"),_T("017239CF21D05D985CE2E362A59DA3C8"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0578"),_T("01784AF43BDB59E131697740D9F749C9"),_T("01C5A7E5F1316C4FC792054221B3AC36"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0579"),_T("01BBCC62EDC5EFD02521156E8DFD4E59"),_T("01F65EB9B59FC85FD2F5A9BDB5C6439F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0580"),_T("01B370B0CF9B39814C9FB285A1DE7BAA"),_T("01F691898CCAF8B18EC7B7584B589F3A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0581"),_T("0141BB96199D04625C3ECCD6C377A54A"),_T("01438D96391F5059A791DD54559C497C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0582"),_T("0118B4C9F3738AD70982BCF1A3233800"),_T("012ECCB297F3B309984AF91FC7E42410"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0583"),_T("0163D2A5B396C6CE9F37619A295DD844"),_T("016B9E564AEEB38875F3CD83336826E0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0584"),_T("012FE2E13FB0F51F392900520178EFB3"),_T("012FF7557920FBA525E636A6B2EE6C63"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0585"),_T("01D31D3A897C16C7B6BB261C790A8AB8"),_T("01FD51C58147F6698BBF8E432570EFFA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0586"),_T("013DFE922200A5859E4FEA6FE22D2E08"),_T("01FB2A709E8B47A7A6108285951BF8EE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0587"),_T("01934C08AE04B95306C45924D92EDB7A"),_T("01F06F8AC2AF95397733F5D7FC833D60"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0588"),_T("010E8C8B4657B99C292ACFAB5E054D0F"),_T("01594781802807E4A112EAD772B47FE3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0589"),_T("010C3512EF011615AE08B5A0F5A18AE2"),_T("01A1D847941C44FEBC8CAD6AEE81CD6D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0590"),_T("017D7FCED13E3FD6F5EBEE434968FFA3"),_T("01D7F59588D2F21D4AF073A86EED0E97"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0591"),_T("0131E43B8F3B7E1F7CA44D4FD2845948"),_T("019532E04894BE1217FD71D5AA70076B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0592"),_T("019ADD607FAC29CCFB1F7000B6F0B1CC"),_T("01C7EFE68D0ACEDC6FFEB38920F24073"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0593"),_T("01625B46D4345A960398554960E1F0EF"),_T("017AF6F64CFF7AD017DB776E9FDCF93B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0594"),_T("01063D3B7A459A1960B574873CD009AF"),_T("015395E9D289D85143E3FF829DC467AF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0595"),_T("01A19DE721362B0F81BEC7026A251C41"),_T("01F06464DF9D98E3BE5F8A4432E741F7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0596"),_T("011F4079C2BE836A4397BF10DFB77189"),_T("019E8705241279BA567FF049A067A535"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0597"),_T("0181C78303E484735F45F80B309F77B3"),_T("01C65CE052D427878D7BA214B0FEF229"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0598"),_T("012BBC4A2210601C2CBC1BEB2AB380B3"),_T("01A23773A58813A23C918B720C8493A7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0599"),_T("011F86E82D6FB033A3728AB3D9A20821"),_T("01E281EE027BD7CDA97FBFF07490AF6F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0600"),_T("0150771598CCA9FA1386C8CF7CAAE2C8"),_T("01EDAFDF283C0E3E5329BECC28481DEA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0601"),_T("0119390DA0FFE0A164F2B3760794E0FB"),_T("014B962B7070DA78C91C4582405DFAF7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0602"),_T("010DCE4BECEE1A505B5E19BB0129831C"),_T("019F2B93445875DE45079688AF263FFB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0603"),_T("014695B0F2B5DBFCBC7A03C6ED5DE395"),_T("019FDF3B64184478EDC7A78DF1D326E3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0604"),_T("0111FB1DA18149736B19222FB0C4A0A1"),_T("01E3EDEB2B9B5ED080E3F91434B8E5FF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0605"),_T("01207A7BCD539CE50B1544D3CB8583B3"),_T("0175C3EDD1F83ECD543667A4A5A15EDF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0606"),_T("010B878577817EEBF329605E67824DC3"),_T("01F057E232007EE31E5CC9EBC15500F6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0607"),_T("0183BA956E2DF949FB2E214319A9A040"),_T("01FDC2A61BE20A287FA3C5FBC5F4C07D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0608"),_T("015FF2926021E3547CA1F5315A4DA91E"),_T("01E1789C081C5773459525805DD3F1B5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0609"),_T("0116E36C7C1FF430775A8F1B094B702C"),_T("01423DD4B032F187954986F03046B94E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0610"),_T("018AD14B2718E06FCC8FD3AE04D0E5B9"),_T("01EC01F52AA6AADD763BC047C59A9539"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0611"),_T("016B60B93469A1C699D34DAB3F52815D"),_T("01CA5228F2A7274064DF65F76BA1BD18"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0612"),_T("01CAC8F32305645BB022CDB9F1F5FEB4"),_T("01FE086949D3703F241B43EEAF4BE3F9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0613"),_T("015C31B9B2364EBADD1D4536165B821F"),_T("019FB982D1E089899459D0E691A72943"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0614"),_T("01504404B1E5B7AEF9AC9E53255288FD"),_T("0170192E66D245932BAD94179C879C1A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0615"),_T("013A71FACCB23F78B9336C910825E01F"),_T("01B17BDA706ABA44257C8EB44CEA537C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0616-0617"),_T("0196628E172FF577C928908747304A38"),_T("01C39B962D89A8056C280F5C53AA4E33"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0618-0619"),_T("0124A376C93414B16308422029BE7EB2"),_T("016711181F86C56184198107A8B1B2CD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0620"),_T("014E931AD85225E17346BEA135A657D1"),_T("0176AF1071F4DA4385E3EC0AAF79E0A5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0621"),_T("01C5E85A4DBCD5E098F88522E4ACDEB3"),_T("01FF0DBEC5FE494C16A5BFBB0692551C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0622"),_T("019432D6DFF23214B94AC29AC87B52B2"),_T("01A532FD0DE2B08102AB44F9787AB6A9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0623"),_T("011741406FC79BACD3B1C13EB30B853E"),_T("01993F9BFB22858B5BC8AF0AC8515D05"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0624"),_T("015B2ADDFD60C24DE90610C30F427C4D"),_T("01FB749C238A45ACEEE9444DC04BE7D3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0625"),_T("01B311F09CBF18BF46103A6B6D7B9953"),_T("01B31D6ADDEEDEA05C958DBC1BBFAB16"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0626"),_T("010CDD5C0042D54FA7BA6C6EA26266C5"),_T("010DE710D720BE30A4AB6817DECF3E5B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0627"),_T("0195D5A9021B6E9EFFAF0AC55974F935"),_T("01DE59024EC091DEBE4ECFA08A5810E0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0628"),_T("014F58F2AC03A1B61EC73CE42476E1F8"),_T("01EC1D716C02DCA253E31D3A5D20C36D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0629"),_T("01487F70349A520AECFBFDA44FC4C26E"),_T("01AF0FBD376861C070FF41A61EEE92A9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0630"),_T("0100BCD7BCF205B784EC2FD26A19A465"),_T("01AF190F303F9923D63B01083EA3C49E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0631"),_T("01A0609D0ADDD544B7B07FCE1A238E27"),_T("01FF054416CCC06B35E291724A8E625D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0632"),_T("013487E10453F3F6D820C2C9A96FF542"),_T("01E35CF64B08F3DD08E1C3A202F95D94"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0633"),_T("0105B163264E4581A4DE2E599939277F"),_T("01E58F0DE89BEC1891B16F53685F230B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0634"),_T("01266999C06F1F36BE31A19ABCC56A8B"),_T("01B85C9AF7657E7CB676E4A3935E1498"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0635"),_T("014D979D3B9289B763D5328F6846BCB5"),_T("016892C835463DF5EFB7A4F91353C529"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0636"),_T("013B179FBF51592750480D2C9919927B"),_T("01F7471FC574BDADBD57D16CA9C90CC7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0637"),_T("018F406B4CC441E964548BEBBC60D623"),_T("01E87175DD7C18E5C5FA6BA8159C94FB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0638"),_T("010FF686CE1C605FDEBA93787A633D61"),_T("017A49933AFBA16618C0096EA41750E9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0639"),_T("014D7FD735E513C363BDB6201C0820FF"),_T("01F4308CC79989831DCBFA85A1C12703"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0640-0641"),_T("0149635D84D269B43578215A80FF5B06"),_T("014CB31B469512AE67304AE64C2A8574"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0642"),_T("0185B6CAB5D7A16084F11BAA56C09541"),_T("01FF11A44402FB7E615760C82130FE07"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0643"),_T("011CBEAD1346460F0F8A4E20B0074383"),_T("0147F3187321624D43B73C65D464CC5C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0644"),_T("01421C0E478349B038A86473E0A74EE1"),_T("01AC2A9B988883C81A8B40D71D20F9D4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0645"),_T("0109DB86288598A2D3AF4CD477AE59DE"),_T("017806A15D182315F03686D7BD9573AE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0646"),_T("01E0B7CCEAF32A708F20880A05359EF2"),_T("01EBAA5744E1C88BC4C63DFD7A4DAA78"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0647"),_T("018019FFDA1E0C06D29271B2AFC990C3"),_T("01B473BFE6AABAED9113D75360449B5D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0648-0649"),_T("0120539057468B71AE1A38509164BB83"),_T("018F551209CB3D9F50F65921B0AE905A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0650"),_T("01451F027933100BE142E67765B629F9"),_T("01BC131EAA3BF14CE0AAD581C8A59A93"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0651"),_T("01341AAB8FA2577137E21496D2E4444A"),_T("016ADE70C44F0656895FC835AF292C95"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0652"),_T("01BE3EAAEF8FD7220B84AF159E8FDA8D"),_T("01D6E132612A02FD07D5D91C2167636C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0653"),_T("0135F0E85BD17FFAD0FC0AB864383039"),_T("01933455E651433AFE5B3304BCF6972C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0654"),_T("01595EF5515383D023051550499B7C4B"),_T("01F3EA2A5B38FCA29B828E2A19F5CA85"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0655"),_T("01F05366224EA4A7C8041B85AC412B51"),_T("01FFD79267B38B946762B575DA8060DC"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0656"),_T("01D3634F4F993FC19742733E6172A1D2"),_T("01F8156E2700659AD1B9E005FBE11E2E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0657"),_T("01BB4E3F9D40B7FE627B32F0A14F0ECF"),_T("01FEEA836C2FA04443C4258414FBE09E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0658"),_T("015A2EECB6F997E58B971DDD5E4F3599"),_T("017EB8D13251EBFAFEB0D2CDEEBF64E5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0659"),_T("0107B1BDF3D8DD5E2E667AD0D90AC1F7"),_T("01B1E0F7A0134D6ED55DB4E7E0FAD481"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0660-0661"),_T("0160EDE6DA1EE97DAB0FADF77C10CDE2"),_T("01DF9A73AA539A6A4441AC16A3815F5D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0662"),_T("0105D86A361A46843E24A65FCFDB3F5B"),_T("01DEBDE71AA7E6AC6670B89A240391C9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0663"),_T("014AF66861DA40F04E840F02196310BD"),_T("0160E51964C3F8814CEECE4A8564EA4E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0664"),_T("0108CB6C68D2169DC93F75F24BCC20E0"),_T("01EAD5F0FAFAA20FC6FDD7C086E30695"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0665"),_T("0161A0473A80FA6AE22E47A4D5D4BDD9"),_T("01AE72B0E17F3DFC763EDB0933A2008E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0666"),_T("01366A59F1EC5DAE2EBA473E9FE39E90"),_T("01CBF8333B24EBE49FD91A3168DD15CF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0667"),_T("014E78244F8874EAB07FA03C9477830E"),_T("01A3B985AA3238882AE1D45645C3EFB7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0668"),_T("010F4C2826D9C7DC2BFA69FDA415ADC1"),_T("017FE93CC0DFCC3CEB6242E8E806277A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0669-0671"),_T("0126A2FA3C22164DF0A9EB95998349AD"),_T("013ABC0489729523BAA273DDD79E35AA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0672-0673"),_T("0106565AA8AF8C8B175E2099D8554A55"),_T("01E0BA388CD18FF5EE51C8A0B4B9BC8B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0674"),_T("019E8548175BAB4AC73A6B0EE259B1EE"),_T("01C7EBECA6AA280425623EE8A755D84F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0675"),_T("011760944E0002C67B50606C1EDDB005"),_T("01ED37EDF7A8B09E7D7ECC52CC1777C0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0676"),_T("0110CA7CB1A26824094B92768B72F626"),_T("01A97EC414E6B9D3F0C20A92332451C2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0677"),_T("011D1D8F80824BA994ECF22E00794B4D"),_T("01D253009A4156E5D55CF596A190D6DA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0678"),_T("01EEC69368D94F689DB28B50BE9FF1F6"),_T("01F2B0B2D717144B98A57ECAC8E2B038"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0679"),_T("0126C4DC25352BCB8FC2CDCE18D302FB"),_T("01CE70B3DB930A0E07D8C9A234DE9223"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0680"),_T("017EDC69FB4953E49F1D392B50700474"),_T("01EEDACA91CABEEB1E30461B5AC8796B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0681"),_T("011ABCCE7FF704A1134987C9381FE453"),_T("0199CF079A275C3D6502744E1F9FA38B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0682"),_T("0116B512F11CB253BE375B6F9D1A4DF1"),_T("01BEC1DC1E365603C9A1F34A5203AB1A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0683"),_T("016041089623F059C1430DFD4415742C"),_T("01639DC99BFA73C1BD89B69E5D75B6CE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0684"),_T("01990B0BF37BE0DD67515AAE6027E7C0"),_T("01C3542AAEAC14324AE9F432ECDEC50A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0685"),_T("01A06E83B4C8414944D4EAFB97B4CECF"),_T("01A21489B17889130F5B25ED2D63F389"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0686"),_T("01A1633366696868B8E8B4B66E2D91D9"),_T("01BFE49AD49262F4BFE51C4976876EDE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0687"),_T("018BE6F95DB41D49A6334B754B62A954"),_T("01E1E7982C7D30F713503B6337A79754"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0688-0689"),_T("01BEBBD5B162549AF3F1A738360943F6"),_T("01C4D090385B1E48E69F9367A8DCCBFC"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0690"),_T("019DBA0836EDED58AB112FA7A6CD90EA"),_T("01EF7849D3DFA50329C62AAEFC27AB72"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0691"),_T("0192D8EEC8BE959ABCBB1050E0AF26F5"),_T("01C4D7E9E7EEDB2C8C811FF57C4205FC"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0692"),_T("014E74B3253E7AC260C60C2E726CE1C7"),_T("016AE7499A4B36DE74967AAE39181B65"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0693"),_T("011012D7160D574CB213546EEC0AA2B6"),_T("014E086B045D6A4CF049FC03A1B0648F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0694-0695"),_T("0121AE462CA220728E6487173DD04DD7"),_T("01EC69DF19534B2AFB4E7666135F531D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0696"),_T("0115E10B04E689E43D807BCB48C8E684"),_T("0161B5930D64896B3698E8170E80F0E1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0697"),_T("012E18617B47370407C6F580545F063F"),_T("018A2BA552B11CC325831C5829E1532C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0698"),_T("01138552102BE957D7D106EA02237416"),_T("0122DEA62DA2B0EFC7A50EA650D55824"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0699"),_T("0197F05D7485FA7A5BE930FD519BA672"),_T("01E86D710032E0FB8A4E92234B04C87D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0700"),_T("01995D63218D76C0A444960AB08ADCB5"),_T("01D724E5E046090F8847360B3956A5EF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0701"),_T("0143AAD72758786BAF42C240C82BF85F"),_T("014BE257E635D3B51336CDB730220372"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0702"),_T("013A0BCD88068C2474C6209C7842BBA9"),_T("01C705210854348EAFC54248BA482EE4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0703-0704"),_T("0171FDB6AA66F1C1C71E52F49A6501AA"),_T("019B93D2807091FEA62161B7F3B2E1D0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0705"),_T("011A11D1467C51885297BEA1677EF0E1"),_T("013C878262ED898982788866AFDBA53B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0706"),_T("011EF334A1F5878DAC969B2D975C5C9E"),_T("0151F34783E62115D851AEDEA5BBFB27"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0707"),_T("010970729EA8DA34D6D0ADD6C4FCC0A0"),_T("01ACDF4A1A6A1B9BACAF9AEB517F15B8"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0708"),_T("01160C0A461223FCA14B803999C77063"),_T("01B9872378DF042302B5C61A0CEFEAFA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0709"),_T("0107F990EA052C704D000EA613E98071"),_T("011E23C05DF15EA242AAFE0CC9643CF3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0710"),_T("014883EC107C372F451881A92BE75B6E"),_T("01B357CE02A83DE3A4D3E0C44DE16D0C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0711-0712"),_T("01F2C7208522D584AC48F29E773739DD"),_T("01F9349EFF2EB352576B06239703115B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0713"),_T("0163DDFECE4F9B9D9BBDD1C3218DC4F9"),_T("01946EF487B9339E9F437A8C69CAFB7D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0714"),_T("01521970584A867B2C85489A407ED5EF"),_T("01D6D0CE4DE7EB6FF07F75BF91AEF714"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0715"),_T("01281F3839F9C167EBC0E90C500A1E8F"),_T("01E68A9ABE6EFBCA99D8717B314A7741"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0716-0717"),_T("0134A7CE8E7585FE1F943D0026551384"),_T("01C3C7E7FDAAC42F2237CCEE8D1B92C4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0718-0719"),_T("01739900893E6A9FB4F49DFCCD467491"),_T("01E24F33D9CE2357188A51C84D73F420"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0720"),_T("019AD443DD29FACE2373D25E8878B52C"),_T("01BBFF1EDFB76F360E8AC44C50664558"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0721"),_T("015867A80D31E8FBB5FA03FA5F803379"),_T("01CA611F74EAD0841DB3817C6FD50452"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0722"),_T("019D394C31BAEF3FE5BAE653A1D94E6A"),_T("019F86D96446A0EE774B229DB9E9C70A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0723"),_T("01314DFD630E4D8D003E2E246A8FB607"),_T("01458C161B002F44A3AE037676107702"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0724"),_T("0124838C508E0A6EF0691B431E4DE939"),_T("0161609B0BD3A95476488D33433FB88A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0725"),_T("011439EC069399C29235DBE644C41565"),_T("01A31CB55665B8A1742F7B24CD82043D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0726"),_T("015E67C21DDA3E3E85D76DF6E615C687"),_T("019604DBEDDFFDC04EE4E5BC07C7B923"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0727"),_T("01982BF3FE2D349DC94C81AA03E16A3B"),_T("01E5810D6E525A705831B7F249F6F31F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0728"),_T("0134FDC769F9513D03884B184C3B8474"),_T("01913604EDD203CB3CB8EF8D9405CC78"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0729"),_T("0162D8F4C6DD019A9AFF0FC19670B4F0"),_T("01BD06018FE3B154414A43FC5CA06F29"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0730"),_T("017787AB0E4AD17C47D14721F54D5971"),_T("01A1F107D32BCAD79BB1214426FA22D8"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0731"),_T("010D35A572945A6446414647ACDE17DF"),_T("013C8FC492A94D57518D5A6F4334BA05"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0732-0733"),_T("0131752C78490CCEF74111CFCC6DB4C7"),_T("015EB9DC9CBA819105338EE47BB9EFD6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0734"),_T("016008E06C048D93C910F8BEF91EF52B"),_T("0189A268B377E7AAA01A50D60463C6EE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0735"),_T("01206338DD44330548732C39C9898CB9"),_T("017ED526927F046AB92EEBAC17992610"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0736"),_T("01818E92F0073502F31D955D37E59D8E"),_T("0196F98AD9CB86564728563FC852D224"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0737-0738"),_T("0141106A1E34C06A8380D76407F372D1"),_T("01A8170DE4B3744E99F652BAF9619BD4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0739-0740"),_T("01740D301664CC994E2774767C6CC8BA"),_T("01C5C3949889B3CC407EEF13097624E0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0741"),_T("01D77879D457F2AC7CE9764A5EABF214"),_T("01FFE2AA1D8016FBFC7567FAD3422E88"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0742"),_T("0154631648919D9452C7DDD081D65951"),_T("01FAD332C48948D9D5F2F60EA3F72346"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0743-0744"),_T("016E4A931CE4379D90486BB66C817C15"),_T("01B2EF3F66BA798CF28E7118704285D8"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0745"),_T("0165C1C102FBCA737CD716E4C74F5F67"),_T("01F7DF156ED778A5B7B9DF1D76B260B3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0746"),_T("010505557AB62F0F334BAD93FB293C67"),_T("01D7D2943230E0A362F28BB7D5043970"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0747"),_T("0134A989953EE55331EEA4B4C88C1561"),_T("016FA522EFE695EC8D2B20F5406A42AE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0748"),_T("012C70106E9761CB2E4312F05D4F2327"),_T("013421859AF35CB606A5893F8CF5CB79"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0749"),_T("01B17B4F3DE2FE7251021BCD49927983"),_T("01C75766F98D2588DE309F55B5AD027F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0750"),_T("0151BC4E6B5B7EA9383ABF9771D0E92F"),_T("0173793CB90A12F80B5A9B80F1225E82"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0751"),_T("01B162F68E01A9A6EC7EC41718BC0334"),_T("01C3291FC9ECA84F53EC6DC60CFA120F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0752-0753"),_T("01412E8689908AC0E032CB0DC91B6F98"),_T("01F2EA617A2830FD0DF622A0E5B4E8B5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0754"),_T("01E13ADF486BC5299E981CBB75DF9574"),_T("01F6DDAD42951DD69C8226FDEFCC86AB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0755"),_T("012A1EE3560CFC313F7C5D69E076BF72"),_T("013F7C8964CD3311BDA99091421C2891"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0756-0758"),_T("010CC33C83738B5BE1816E06A1B0FB79"),_T("01728A7E3A3E47F0D19A2E84D52B40CB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0759-0760"),_T("0181345A53E4630DBECDDCDEBF8A92EB"),_T("01C6F728BA0618067E7CB7B9085076B9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0761"),_T("011E0EEB08CE87632FB21DBB368AF7C5"),_T("0155E29B6B1B65DF62F287769B080931"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0762"),_T("0116A748C26B59FA71A99BFD2FAA79EF"),_T("01172C6CE09A4259ED382FFD81A4A11E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0763"),_T("01B4A7A245551276F6519788823E2D60"),_T("01C5790C084B60EA44FCB4AC30219DE2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0764"),_T("015E6B9E0BC59FFCE339C28E2832299D"),_T("017A3E8BF45A6D4CD135CA7A8938819F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0765-0766"),_T("010F9B8A1133847B8CEB1A79257CEF9D"),_T("0162DDF780B1C003D8880718FA48DB65"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0767-0768 (High)"),_T("0114CE573067A530B2672439300A277B"),_T("01262585BD65203A8835AF165D372114"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0769"),_T("0129E09178207BE8FE53C58F9D6F7E56"),_T("01E01CC2DCDFFC31C0EF530FD447EEF4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0770"),_T("01D2E279C32DD15835EC16E2F3D3B0FB"),_T("01D80B17931E38658364310BD16F8BFA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0771"),_T("0143053BDE5FE1EF59EACEEDC1024A96"),_T("01DDE10D1E165421147E3B9137B15516"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0772"),_T("01188EAC9079CE45BA48409E5D0DC617"),_T("01D3D9F44C41E759AEA2E43BEB180FB8"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0773"),_T("0140F64413ED8154715044EFFA4C6DBC"),_T("01CE1750DECF954F386D907BEEE8A084"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0774"),_T("0147F5708EB9017D13A442BB46F75E77"),_T("015DD487C40FAC0BBBE57DC1C32602BA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0775-0776"),_T("01556C85BAD1C7ECAF21965C9EF39CD1"),_T("01AA8404ECEA9EBB446977EE9E308261"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0777"),_T("014940406434BA7B331A890F17E5A4E4"),_T("0190EDE593AAE35F2BB4DB0B502B3A29"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0778"),_T("015D8C258F267F4FFB925A1BA05140D3"),_T("0166C31FE604DCCAF3D8516BBC6D6BF0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0779"),_T("010494BCA62C248ED17298891C5B8FB3"),_T("0111AD6C0B52D5EA87C854C6B95A0E78"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0780-0781"),_T("01236434B32DE2735236C07E2129C50A"),_T("01A1F1281B2849D0BEFA12FEDD813F2D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0782"),_T("01EA5C943C3AB6EA9E1DC2AF7C352A8B"),_T("01F8AE977EE16043673AFEDA1F040DD7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0783"),_T("016A712A246EA22F747C859C41EC9FF8"),_T("01AC5276059C21D3C8444FC965885DA9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0784"),_T("01175ECFD976F119F93651FB69518BF9"),_T("016DF4BADEC1F1987780BC7A97F9F9F5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0785-0786"),_T("01108E81657F5FDDFE07806F26D8C9C8"),_T("01AE1C3A9DF92782A37F536B8FAEAA73"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0787"),_T("0101668016F68201E1DE902B7B3BD405"),_T("017C85A24795A05A2D425BE9067F3A00"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0788"),_T("011EE79632F3450F748B960C5C0FD35E"),_T("01D5E807FD481CD4F36602BDD73E2324"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0789"),_T("017FDC063B80AD6B76AF635FB23C4AEB"),_T("01F4591ACCE7C655F7EBB222BB35CC69"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0790"),_T("019F0C3919379CA2A9964B9DC0335110"),_T("01FFF828D20AC20FBC46EDDBF6936EBF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0791-0792"),_T("01303A83ACA1D50A22EEF083FDDC1273"),_T("019FCD20A1B623236C7917F3C322A000"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0793-0795"),_T("015DD2631DD75A3AFAD94A72003DCFA7"),_T("01CED8758CB2471DB965A29A872A3E16"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0796-0798"),_T("017975CE66AC80239C28B5632F819EBA"),_T("01F1467C227A678A990547B58196DF5A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0799"),_T("01A35F7D4A3B8775ECC4D1F486596DD4"),_T("01D095BEA29226BF600C6A51E99E010B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0800"),_T("017B0C62BD790E165D6EB9F56DB10744"),_T("01D4860F7B7EFBB4A11C50883E5CCDC3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0801"),_T("01B06F3B1E8A89F18F67ACFFB5E5E35A"),_T("01C490A27EED0BB557CD91A099D5C3CF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0802-0804"),_T("01494FE7130F7036E5D8B269B054E7D5"),_T("0197A3DA88F11D33F5088D40266DE48E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0805"),_T("013DED50ECAF324351680E680845F9E6"),_T("018E7EFB95EB0916122B1D3FF6C89439"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0806-0807"),_T("01A2DB43DDC2ED6652939254D7509F87"),_T("01B3284A595854CC24387CB570612183"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0808"),_T("01A6AE04333E98EC67A2B90FCC0F9A63"),_T("01BC4197B84B745BB832C82C583529F4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0809"),_T("01D2AE72BAA1964FC202C90413A3174C"),_T("01E93D154CD964675A0291F4F06802E7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0810"),_T("013D6DBD55EC9139611AA94FB22DEB87"),_T("01C4E7DE76032D0739E6EB92BFACAF6B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0811-0813"),_T("01A6ED22E09B0C61E0E894677782A239"),_T("01C83B9A79A2D4AA5DF605154502229B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0814"),_T("010590710A3F937EB8251BCE9037F8AB"),_T("012C9982B9ACBEA744752FD914C747E9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0815"),_T("01A75EC893B771D1BF06D639521C6E75"),_T("01F08859E484A8F53DABB093CF402F13"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0816"),_T("0102089A411F9831A81443CF562AE24F"),_T("010A52696752917FD55A62CCA9F2058B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0817"),_T("01282D9DB4C3B247FF24A74235006856"),_T("013B7EBD5151E2B6DCCEEF706A75BD08"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0818"),_T("011EAFD32BC3364849CC84F731276A52"),_T("017DD830BB02481BFF8637E8A819369C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0819"),_T("01A7D8F5C012A126E71976DFA6A69E6E"),_T("01FF8CF4DA3465E35A0CC6A5D7BA32D4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0820"),_T("01244F193E8F5F3AB7F387838D34BFAF"),_T("0148301FE7106E0F911CDD856ED99AA9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0821"),_T("0124D625856B9A359557F200C36C20F0"),_T("01A272D8217E7D598E465A181BE43734"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0822-0824"),_T("011706BAD6FC19A0F82C2DB0A76B9159"),_T("0166661BCE268A3178BFA5236FEF46F4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0825"),_T("01357CD849370F4A172BD943451FE6B4"),_T("01E09C16F2846C46555213A7AB078A89"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0826"),_T("011A9829DD6E60F8BE182A4882EAF93E"),_T("01D64FD999BF5167B5CB3A096CAF4FC3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0827-0829"),_T("0162041423D36713D42A487912D6A225"),_T("0193365A1BC7AD1982C4F78F826FB382"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0830-0832"),_T("01296B6B24C38AFE7DCDDF9A12522B26"),_T("0158B7297BFC62B638C3224453BCD0E2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0833-0834"),_T("01269870C93BA30F725724603796F8FE"),_T("017666F1CB6BA0A85EEA665BC022D0AE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0835"),_T("014E86D6BD4286FEE473EC57587367F2"),_T("01D6A399C2605C19C14CB55BE64408D0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0836"),_T("0140196F2394032EFE2FBA1AED7D0FC9"),_T("017816277EABE53FCD6A910E6518F7F5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0837"),_T("01882E8022338D9D7EAF94E75B19EA8C"),_T("01B75181D1C02E9F3612094C00A0332B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0838-0839"),_T("01764C27E26D66AE8655F92AA4315343"),_T("01A904FD8D4B558341C396714729CBAA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0840"),_T("01067F36BCC213919EF14EE4512A9168"),_T("01F2F7DE16E0EEEC8BC9E52790994976"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0841"),_T("016FCE873589B972B238EAC7220189AB"),_T("018F8BEC8170A0C9B0AE7E1CA506E8CA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0842"),_T("01708D99409B901485052582D9D25FB1"),_T("01DF1EB7BFDEAA245BC4703876AE4AA5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0843"),_T("017B83D10654AC54A91EC88CCDBB1F3A"),_T("01E4697D5F927E28531335C748BDBC56"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0844"),_T("01362ECE09C2145375024C3401B038E5"),_T("01445193C5622F1538DCE90617F4A281"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0845"),_T("01D18103D4A56B2FF588FF7622CACBB4"),_T("01F75814A4F7BDD1DFF9AAC1B8B08995"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0846-0849"),_T("010A1DBA635B790F53C6FC0BB82D22B8"),_T("01F812F4416ACC7CA376817D3D214573"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0850"),_T("0104B096E5766291BB33A43D3D84818B"),_T("018074541C8331661660C2B91C3B0485"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0851-0852"),_T("013D1B431D2B129506124324FC27843F"),_T("01D31512C2C1FB60074B7D9471B7B5DD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0853"),_T("015815FBF233497A852248AECC2AD894"),_T("01798BE292A44D1B825CBC07A1A92998"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0854"),_T("0162688EDC2692044347B4C2D042D932"),_T("0177FADE315CE89A775CD1AB71F48D1F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0855-0856"),_T("013E5D266F98E0E4BA51DEEB63949B4C"),_T("01935D9820EE9DF4858BDDEC7A36F27A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0857"),_T("01002542B0D746E9574F530CB7A01879"),_T("015240A57D2EA2D411CFA2609493FF7F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0858"),_T("019F9FF19A8808B484AAEC973EC632F5"),_T("01DE9CBE6384981AB6F497009BA343FD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0859-0860"),_T("0160843783D38DA64A32A35C10E95F8E"),_T("019A4883A109C97A8A91C53564D294CE"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0861-0863"),_T("01BECD23BB2BA6B32AAF7D02FD3AD9D6"),_T("01DAD10C5CACA29498C2A3496900F0D2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0864"),_T("011FAE984D4239F67E3197A56E6E8B1F"),_T("015BEA542F03A7DEBD40C6C83B835CD0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0865"),_T("010EC5DF81A47D7B35E364DB0286B38D"),_T("014C231A3F4D8ED66189A008D6BE59AC"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0866"),_T("0181644723CC0B619C843E94F9DF3FB1"),_T("0186CF4D27D784DCBC9149FA45EA51EF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0867"),_T("0103C35DB787348230A5FA7F97887BA6"),_T("0131AEA501B09E8749B0F68991EF4538"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0868"),_T("018B7FBC04AA06CE3B87746A5B55064F"),_T("01E25A56685F14707F600B7AFCC408A3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0869"),_T("010FC500A34E29F8D4F20F849D24167D"),_T("01C94752FA9E07B9CACF5C1BDB701CD3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0870"),_T("014F4D5995A52BAD57003BC299E453F7"),_T("01FD443C54431C10C23F2479127E9609"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0871-0872"),_T("01318BE3C32ABEC748B143223E421F71"),_T("015683460D89CF3616DFE135A3AECC92"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0873-0875"),_T("019E0432CAFC6F51A86A80B85868846E"),_T("01C88F78E035E50AC5454EFD84354580"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0876-0877"),_T("0140AA346D76225BAC4320B2E4A6883D"),_T("01E29D9F775424374223E006EA7B73BF"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0878-0880"),_T("0145300F9C6A04E10EE27C6B45A9746F"),_T("01CED08B797A882E66ED900C302C3F22"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0881-0886"),_T("01C9D74F9D2AC23742FFB0DDF28DD890"),_T("01F5760662EABE073CDBD655E81D5CF5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0887"),_T("01592F6CF2E6D2CEB5B023ED7B3DB768"),_T("01E6AE16DF74E071B44CB5E6135A3875"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0888-0890"),_T("016FA758A5FD41BA9757D26600661FDD"),_T("01FFFBD71EEEC84292194F59C1AE8C35"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0891-0893"),_T("0182506132D5C42D898911DE2FC8E20E"),_T("01F7AA219DF03B306462A9742C13E7CA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0894"),_T("0153E38C981DE75EF937FF0A5E4D3E35"),_T("01FC66A3E0467C4A8EC59BF968D2F133"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0895"),_T("0137BE74FDA5DF7CC4268BD46A70FC4E"),_T("01DD84F796ED019DEED72FAA460B62B4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0896"),_T("0196C918EE5DAA4CB4CEDE3FC36EA29F"),_T("019829A61BF6891AF3496006CB7A9227"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0897-0898"),_T("014241152DABD4B60ABC5816CEE1417E"),_T("019E9B714DC34B87388054423FEC8167"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0899"),_T("0171ABA63ABCB22DD39052088B9B0E14"),_T("01D85FCEFFBA040249D0FD61210C252C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0900-0901"),_T("012FD7E7C0496E485D16796E87322A12"),_T("019FDD88B2761291AE473B23072748E7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0902"),_T("0138872865D1A708920CE687813953F2"),_T("0139D006CBBA38F7F9CE8AEA103C095D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0903"),_T("01DF111C519CC6ABF27C30574B3405BD"),_T("01E055E3FFD73824E68FF94AFD9470AB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0904-0905"),_T("017FD330B167DFB68140C5FB5C9568AD"),_T("019007F0F583B54FB0E344BD7CB23E6C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0906"),_T("01A202BC3BDA93D933E3094438696126"),_T("01FAA64089CD85A14E3D9F65CB7D950D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0907-0908"),_T("01C274A79362E9D34711FC55D55E432A"),_T("01C2DDB7BB8068B253FE087C9B6DA9F1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0909-0910"),_T("019C6EA04C3648025A7C6421D38391AD"),_T("01A093402E7C86841FF0976DE9747406"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0911-0914"),_T("01055F01B835B9E22A70C00F4506CC1E"),_T("01F04D7E62919092320B205F5FC1CDEA"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0915-0917"),_T("01519C01EF10AB5923C7DEF7CF451AD1"),_T("0178A29EDD3726918889CB57C86BEC60"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0918-0920"),_T("01903AE5E5B23C9A5AA94CEF21515929"),_T("01D745557D2D8E39A360BA6991107154"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0921-0922"),_T("0140475FCF05578FC1534AE1012A3E6C"),_T("0146DF88F666D7A82A0C6993869E5D19"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0923-0924"),_T("015816A392487668D55F25DDBDA7C372"),_T("017999550C7E510079EA2F7385D40A68"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0925-0926"),_T("019B6B0E53931422A906687B7022A0CE"),_T("019C316BC6926ADA711EB8BC46071961"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0927"),_T("01698ECEA56E44E858B5001C65223773"),_T("016EFCBDBE78119FBABB3400F579BBEB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0928"),_T("01581755543FD36EBDB20BBC01BC6631"),_T("01E7D74B14934BC43D3B8DD34618B277"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0929"),_T("010C0CD447B7CBF6965F9170562F20F6"),_T("01F71E70719574F7F55CDCCFAB64B0F9"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0930"),_T("013B6D40EE1AB3DA18D6E6610C858DAD"),_T("01D89B879D7407DCCD764666375A9BC4"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0931"),_T("011C5DE8171A9695B0520737183C0764"),_T("014836903D604574382F05B733ECC80D"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0932-0933"),_T("013AFDEC9FCE9811633541BB297D6A31"),_T("01A6507F4D6EA152B6D6D15DEA8438E7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0934-0936"),_T("01C78FEF1A1B50D8078AA7ECE43CA83F"),_T("01CE1A263791F67AFA794CD7C9CC2D7B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0937-0938"),_T("01183D63F171792FE6CE4CDADA65B869"),_T("01AFCBFFDAB1A380DE71C6A0BED9F5D2"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0939"),_T("01285979F5130214FEF7EA318B17BE50"),_T("01828B0DFD8C4EB651271D2476EA41E1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0940"),_T("0164A85D3DD37F489487BB34EA3C971F"),_T("0175EE5CAA89C22F49971415D2628DFC"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0941-0943"),_T("011C6E8D2A68E4026F432C1FDBD5AD86"),_T("01418786671986A64A643046489E8A14"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0944-0946"),_T("017CBE1D96DC15F458694A6CC1DAB180"),_T("01B7AA5E0A74E22F6A5C58A339B211D1"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0947-0948"),_T("0161AC18EADB56CABBC756804A4A9941"),_T("0187694299147CD57FEBF35D7FFE260F"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0949-0951"),_T("0141327E255C3A13433042918367AA9C"),_T("01EA8B13B98E14EC4215FEDE05C44727"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0952-0954"),_T("01D3986A649C4593CF9A19B4D8E3EA4A"),_T("01F356138F798D2FA9AC84B3DFD26C92"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0955"),_T("0145CCFB3CFD657AA47D68857C73808B"),_T("0187CDB41EB378C587B76E9CD566D8C0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0956-0957"),_T("012F07144A72589BEF23F77C2919D01C"),_T("014F11F503B94F47BCC76381C94217A6"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0958"),_T("01858F2371E6FD5D2B022A862C9403CD"),_T("01C7E4C843A994F4D1E403D1DC069301"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0959-0961"),_T("012154F06AD8C10650176D38CA037FF0"),_T("01EA79B38EDD5146D5F476914A8E71BD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0962"),_T("01155074C742DE05033EE1BA458A9425"),_T("015B548A7412D0EE0ADAB5E2DCE23EFD"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0963-0967"),_T("011CFBFE38980EECFF0A34C6388CE105"),_T("0163ADF771C4E12D63D3C9788E2FDBE3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0968-0970"),_T("0105906605B0B1F3486C3C8CF3D57D6B"),_T("01D6B0B146317ED757EC77F7DB2BFF28"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0971"),_T("013691ABD953028C3F53D6804CC70AE9"),_T("0150B09A0E3882C6F8A5E1AAF5E03B0B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0972-0973"),_T("0125417F733714AD6039B7B11F310C6B"),_T("016B64AD420E45930EB2675A84E11185"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0974"),_T("0146A06271D0F045EBB5F9FBDB2CA380"),_T("0199BD0C5E50BEB3391B3BA83E20460C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0975-0977"),_T("011530FE3D2596A1DBF9B21DC0C768BB"),_T("01F398CC38FFA11AE6A27DA61479D2DB"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0978-0979"),_T("01030E4D425BF53637B25750A7D2EC3F"),_T("013753A38766C7184F81BE47535374A7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0980-0984"),_T("011434D104CFA9756DDB849B1C7CA6CA"),_T("01F237DB76339A845B8D23936B8161B3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0985-0987"),_T("0176EA31FD79529A42C9E966CBD37ECA"),_T("01B8CD4E7BA416EA9FABE965D9F0D53A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0988-0991"),_T("013A02A0143E2E6C70448EEBEE4AE013"),_T("0172EB3632373F14D4872D664B0356D0"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0992-0993"),_T("01409A21C0503864B6F3013D3F92DC02"),_T("01580E49C26E88C02076AD62914EC02A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0994-0996"),_T("0104A8440AFAEE765A1F31C7367B5D82"),_T("01A787B438945DA50535AC583C384183"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0997-0998"),_T("01828FAD99129D943E92AA8D2B2C72C1"),_T("01F1ABA1A836A48B95926B8850C6CDA7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("0999-1000"),_T("0188E600659A5FC4DA9DE8ED6300E542"),_T("01DDCF7F20D3F3D8FBFC7DC191980795"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1001-1002"),_T("017DA7EED6877ECE524C1B3C4986B048"),_T("01CF347986890DBA777C4C82C82910A3"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1003"),_T("0149FCF072B1E749E71ED0979D875CD8"),_T("014F7DCA1C9B2157092412A48B32A1A5"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1004"),_T("0113ABE207B0829CBBD35025982A7F66"),_T("0171F3D4D3B81286D4FD1B096E06998C"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1005-1006"),_T("01581FD78C224E87707122C4FEADBC07"),_T("01D6264DA2D1D946944131F4692C2874"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1007-1009"),_T("0109FB92C942C66AFC32B3687428C6D0"),_T("019BC9FACE95D1842B0CFCF9649D84DC"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1010-1013"),_T("012E357594FCD55C23DE9B211BC27C8B"),_T("0170F23CF35057B264F6163C0CC7743B"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1014-1016"),_T("0183D94237D2A1462CF8884A2C58566B"),_T("01D2027538B7350A8CE3D2F9769B1071"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1017"),_T("011763A76D06504E23FC3843EB35ED62"),_T("01FB54D501D5628BB7E7BDB128FD8A99"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1018-1020"),_T("0161F31183C82FA6B3675AEFCC73D858"),_T("01E90C213C988C624D42B2EFBFEA3CD7"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1021-1023"),_T("019D0859B90DD978F84DF3C7F8A725FC"),_T("01A5C5922845AA40ADB38740B5BB205A"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Apple Quicktime"),_T(""),_T("1024 (Best)"),_T("0137276AE93D501787EB606694966C4E"),_T("0137276AE93D501787EB606694966C4E"),_T(""),_T(""),_T("Apple Quicktime")}, -{ ENUM_EDITOR_SW, _T("Corel Photopaint v8.0"),_T(""),_T("high (comp 12%)"),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T(""),_T(""),_T("Corel Photopaint v8.0")}, -{ ENUM_EDITOR_SW, _T("Digital Photo Professional"),_T(""),_T("01"),_T("01371CDFD05D688A5EF29310462CEBFD"),_T("01F098E22EBE7D3E0D31DD1FE0B14FD6"),_T(""),_T("Digital Photo Professional"),_T("Digital Photo Professional")}, -{ ENUM_EDITOR_SW, _T("Digital Photo Professional"),_T(""),_T("02"),_T("01264E8FC69DB0D4E823310AC4A62F5B"),_T("01FAB2BA2D9A80FB421DC6981F422A94"),_T(""),_T("Digital Photo Professional"),_T("Digital Photo Professional")}, -{ ENUM_EDITOR_SW, _T("Digital Photo Professional"),_T(""),_T("03"),_T("01472DFFD69C61F0236252CEC3D93A59"),_T("01AA29A71CF32688CAA00C0345252BE3"),_T(""),_T("Digital Photo Professional"),_T("Digital Photo Professional")}, -{ ENUM_EDITOR_SW, _T("Digital Photo Professional"),_T(""),_T("04"),_T("01925341B1402B2B890C20539B2994B4"),_T("01A506A5268ADF6774AD1DD49F250957"),_T(""),_T("Digital Photo Professional"),_T("Digital Photo Professional")}, -{ ENUM_EDITOR_SW, _T("Digital Photo Professional"),_T(""),_T("05"),_T("012D821C6AB210E2A753BE053B8F55D0"),_T("0182408A81A4ABF04D4A34A8A5E98C58"),_T(""),_T("Digital Photo Professional"),_T("Digital Photo Professional")}, -{ ENUM_EDITOR_SW, _T("Digital Photo Professional"),_T(""),_T("06"),_T("018F43694F4E9A49C24613CE0DB777A1"),_T("01BFD6DFF74A169EDA4F585691B1C832"),_T(""),_T("Digital Photo Professional"),_T("Digital Photo Professional")}, -{ ENUM_EDITOR_SW, _T("Digital Photo Professional"),_T(""),_T("07"),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T(""),_T("Digital Photo Professional"),_T("Digital Photo Professional")}, -{ ENUM_EDITOR_SW, _T("Digital Photo Professional"),_T(""),_T("08"),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T(""),_T("Digital Photo Professional"),_T("Digital Photo Professional")}, -{ ENUM_EDITOR_SW, _T("Digital Photo Professional"),_T(""),_T("09"),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T(""),_T("Digital Photo Professional"),_T("Digital Photo Professional")}, -{ ENUM_EDITOR_SW, _T("Digital Photo Professional"),_T(""),_T("10"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T(""),_T("Digital Photo Professional"),_T("Digital Photo Professional")}, -{ ENUM_EDITOR_SW, _T("FixFoto"),_T(""),_T("fine"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T(""),_T(""),_T("FixFoto")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("001"),_T("017B7355162223C173A4E4C88F05C9DA"),_T("018EAAFCAA0AB2E88D21C57EB8C43B91"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("001 Baseline"),_T("015E8EF249156A7517F33D04EC88B72D"),_T("015E8EF249156A7517F33D04EC88B72D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("001 Baseline Gray"),_T("01297F26422C08EAC152895BC06C7499"),_T("01297F26422C08EAC152895BC06C7499"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("001 Gray"),_T("0163D6CB88C86210E76F0E31048B0BF6"),_T("01A6E4ED4705E839FA28074138B05070"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("002"),_T("014DD72F134192F5A8218CD57E7E92F7"),_T("01530695A44D097615A909810255552D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("002 Baseline"),_T("015F7A9618EB2A868C7550DA1329990A"),_T("019EAF74910A2D5AC97092B7AF4836DC"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("002 Baseline Gray"),_T("01486C07E83005735F04D0A4A27068E8"),_T("01C14F2467E51D7674E2DD062263F7BB"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("002 Gray"),_T("012598FEF5AFB0C3E676833AF10CCCA9"),_T("01C5DF373FF773BDAFEE6185D00369C9"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("003"),_T("010D93534ECBE41A03AD908F7C2F65D0"),_T("01225387EEF2A87E35871B03DD67611E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("003 Baseline"),_T("014180871C124E13E1D1ECC15766B3AD"),_T("01B78E9757D16F4C222B8FCDB3E0009B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("003 Baseline Gray"),_T("01A263063939FF920070C72232265CEE"),_T("01D1D80702D2418283DB0B64B688F06C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("003 Gray"),_T("01179B1DF96EE5FE56253A215543EC1E"),_T("01BAF3E5B99E4B484E5BA182B172D98B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("004"),_T("01E8961863E6A06BD0F830F728EA4280"),_T("01F7A160536DC08D336A2F1631F7F3DC"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("004 Baseline"),_T("01A97DA12E54D66FBFBCAE0D5E991CA7"),_T("01B75FA66F48AA9134AEB973912F5002"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("004 Baseline Gray"),_T("01351162C4FB4ABBC45E7C31F97176ED"),_T("018BEC3F23835B6B6E1CE317E248E55F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("004 Gray"),_T("011236A3C64BA1BA9F5FFB1C8AD211E7"),_T("01DF43FC1624F3D0509022EE7B4D153D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("005"),_T("0148D4A3A57AA9F4CCC1A1ABE2B3EBD3"),_T("019F85C1F6EA55C6C11B0816CEEE394E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("005 Baseline"),_T("015D763BE94566375ED64FA6BBC90CBC"),_T("01E9BD6C6EA39F1EC280CCAB84E9F838"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("005 Baseline Gray"),_T("0127C219A56CD59294E419F50B3CD5A4"),_T("01B7927F22D541B45898138DCCBCB8BF"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("005 Gray"),_T("014403414AAC4820C77EF45FF0983FA1"),_T("01DD93A182BEE09075A38D13E48CEEB5"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("006"),_T("01557CBD43FA30C074C5F867B271E4FF"),_T("01C74923F623DA3353728D4F65A65560"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("006 Baseline"),_T("0178C88CE971F4895B97F162B6F4D9EB"),_T("01E5D4A5B704442CFB9AB125C61B8380"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("006 Baseline Gray"),_T("013452C3086DA41E7287EFA1BFA8B2AB"),_T("016D6A0A694A62C56E5743868BB0D41E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("006 Gray"),_T("0114BECC99AF2EFEB4E15210F5371B75"),_T("019844D405FFF1D861D36BEB52217DE2"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("007"),_T("01B8C90AD9A893E6C04A131099DFACA7"),_T("01D85E50FA0EE5AD5E0DC4E56D3B433D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("007 Baseline"),_T("0164AE108050FA4F61234DC514D83948"),_T("017D8F5DD41BE2AF4D193065A10D9C8B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("007 Baseline Gray"),_T("01012B878EF734B659BA1CFFC2B5D2E1"),_T("01501DCF3CBA9EB2E717BEDDE3219788"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("007 Gray"),_T("015A4FEE9D68729E5C58D9026790CD83"),_T("01EC84DC35C178247C3E04B54D808ED9"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("008"),_T("01D8CA571F91B40B212432DF0B1293AA"),_T("01FD4538ACD2D3959E31924320F447A3"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("008 Baseline"),_T("01B366D312409D49FBD66A7271A7880E"),_T("01ED8C761580D6160951141E756C4373"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("008 Baseline Gray"),_T("010BD1B6B651D091E4611F312F853D55"),_T("01E0F07D87CFF3B690BB7BD4BFD3F0D5"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("008 Gray"),_T("010E8D52A10CA78D233C33E2B2CB2511"),_T("01D0F02822F32FFE1F21A1A5CA33CBBC"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("009"),_T("0165A32069B4C1CE7B097FE2261689E2"),_T("01CB76360C6CCD24100452C09CEEB761"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("009 Baseline"),_T("010A73E1E045C32AD1C406E7EB3EBF09"),_T("01804FAAD1B26D898E85F75DF30C2F22"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("009 Baseline Gray"),_T("01735AE9B21723B1A0B1086693F921F4"),_T("0193567FAD350593014BE7683825EFFC"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("009 Gray"),_T("01376345AA246B6B1E13EAE20EAE4CA5"),_T("016CDF096CA0416A303787481AFA38A1"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("010"),_T("01A1BA2ACAA09A184A268313A90E5EB4"),_T("01D0E8A480D3D5EE22490A21A32F430B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("010 Baseline"),_T("0196F2BCA047EAD712F1E724146172C2"),_T("0199D6A2E65FCBEB7FC729FFBD7733F1"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("010 Baseline Gray"),_T("016431D22F1312535059CE905D3B7D36"),_T("01D9554FEA5607D2524F36810B49C6E3"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("010 Gray"),_T("014C3AFFE67BA40C08BE705C298DD947"),_T("016800F71365CD51678A09C7D22020AD"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("011"),_T("0104DD1B8565682F6243C8B6B495538E"),_T("0113AA4194BAED61D2EBFD5D249A7C3B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("011 Baseline"),_T("0136A16196FF2A6919912E549E28DB1F"),_T("01B321156125107374C0494726A4E615"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("011 Baseline Gray"),_T("010D74B305577D4C0EF9A4FA81208E2A"),_T("019ABE12869B59CCBF0D08884F809733"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("011 Gray"),_T("013EDCA35DC95867FAEF6504D946AB88"),_T("0173CA54240C852D2162D2D60C70BD1E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("012"),_T("010141597D7D13E15FAFCBE3655018CA"),_T("01A1ACA48E2530DA49D13E6A1A00D351"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("012 Baseline"),_T("019F0B1DA2B01FF4A8215F8BAAB61652"),_T("01DB6989B11A4E8962133E089391A871"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("012 Baseline Gray"),_T("013BE7534F6F10E0DB3569A5DCAC59D1"),_T("0195CA1CAA708E6D5202211255BBAA7C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("012 Gray"),_T("018F446D264CD997BAF04D04B05A91B9"),_T("018F616CE930D4500CB63FFD1E2F97EF"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("013"),_T("0108C12043C674298E68F922A4F9D8E3"),_T("01F32CCDBCF6D70A6F162E68B71B9292"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("013 Baseline"),_T("01FAFD5D6C3FF57FEC50542A8049FFBE"),_T("01FB327F2708133773A7C1C2ADF015C8"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("013 Baseline Gray"),_T("01A9A53936E293CAA737CAF361CA4EB1"),_T("01C5522783D57656739934F7FAD62AFF"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("013 Gray"),_T("010064FC378FCADA298C6E19AE772386"),_T("01F924075E607C892E5ED487B66C33C5"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("014"),_T("01B8FF4C5FB2480CC2FA203338B3FB49"),_T("01F2515A4D47E94F00444E125569ADEC"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("014 Baseline"),_T("0111ED3FE874F467004F42442A4D5EC1"),_T("01D0B329A0D3E31ED35C294BDBED9B6F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("014 Baseline Gray"),_T("01DE5FE34EADFA8BDA32D377565E1141"),_T("01EE3682E1D03DFFFB284257ABB9C199"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("014 Gray"),_T("01CA028CF12DA7C6A38D88F9E80D2B75"),_T("01F385384D8FBB00459FF944F49EF187"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("015"),_T("0105A3D95D2D36DE9351313E30D8E945"),_T("013C3A43642D2E8325A76C3818B3C324"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("015 Baseline"),_T("0137B43FA77C7778CA3ADF9EACBE244A"),_T("01DD0F98215EAF68D95CA29504642470"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("015 Baseline Gray"),_T("015F641253537182AB95B7377533CEC9"),_T("01782BAC6D4C5814864EA1E787F1DD17"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("015 Gray"),_T("014FAB780D8D2E126D37C285196C56C3"),_T("01B81286514AF4681D5269E7A69FB780"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("016"),_T("01382B45F768D75423502D2E8B4FA067"),_T("01809D564FFB50A4B041FA568A15C9E6"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("016 Baseline"),_T("0120A091F04D17628FED6C97DEEB280A"),_T("0188331717200FC0BB9554D2A03CC9FE"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("016 Baseline Gray"),_T("0113DF3F814D89D622254D755BAB04CF"),_T("01C825971AE124C75253EB75D5D58FB9"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("016 Gray"),_T("016709ECACA8BFACE513721F290F23EF"),_T("0196AF8D3EAD94D6E97505361B1F1358"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("017"),_T("01DC148567DCB4285F93B78611674D07"),_T("01E94E7F685174FAD107E3ED5E42BE92"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("017 Baseline"),_T("01758F4E39DFACE5EA5D12F9E0B34014"),_T("01FB6608C70A5EE84888DC0BAFC6B5B5"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("017 Baseline Gray"),_T("017391E08342C2EC22792EF337EF549D"),_T("0177E5CD64BA1F01B9E7CEB33B14CF35"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("017 Gray"),_T("010153C5A5FF4AF26A0091FA8B9678B0"),_T("01552F1E4906CECE8137F1BB9BA2D8B7"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("018"),_T("01057FAB300BDD64B97BA4568CB14B5D"),_T("015C51EA21C7499D0C90807ACE472F04"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("018 Baseline"),_T("012B46FBA4F602C5E2A9E53273F92CC2"),_T("01B34903143AE2C4148C20975CD59793"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("018 Baseline Gray"),_T("014B75D8C642D3B15BBAF66297C036A9"),_T("0162C12D22B2E3019AFB303E26DA4045"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("018 Gray"),_T("017FE7B01030048A75A0A5A3766C2398"),_T("01EF118D91165F6B8109179E315F2197"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("019"),_T("01F28319610130A4962D2F2471A47B44"),_T("01F9DE9286B554D02751D1F9BC1FABBF"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("019 Baseline"),_T("01371CDFD05D688A5EF29310462CEBFD"),_T("01F098E22EBE7D3E0D31DD1FE0B14FD6"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("019 Baseline Gray"),_T("011BF44C288ED88757E92D649BF545C6"),_T("01EE49101C014F8EAF5D98C5A39B6A7C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("019 Gray"),_T("0161AF5C8A6D83C8F6BEF3334AFA19FF"),_T("01DF20D95132EFD134BA9742BE28DD2D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("020"),_T("010D756CE419BC1DC5A66488DA103E59"),_T("018772B3B18E10C3B6A30048454AE64F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("020 Baseline"),_T("01992DA20A6C319816DB7D1B2930DE70"),_T("01C26E64C91D1F3AF498FC128F3DB745"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("020 Baseline Gray"),_T("0189AA319F67514100ABE60A7A217A0F"),_T("01DB8A3598F8CF5C597313B21AE58C40"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("020 Gray"),_T("0128762025414333A77880F582836FB9"),_T("019F14524F3D4172188A4F25CFBF7015"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("021"),_T("010B8F48DDFF29779D862905F7915174"),_T("01230BD3DB98C5BF6519D7E6F7814119"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("021 Baseline"),_T("01031013E022B4BDE27ACB2BA5506995"),_T("018C081C9DA097E46EE51742F0DCAE8F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("021 Baseline Gray"),_T("01257B6D36CBD8F417A2DE61BFB93FF8"),_T("01935FA65F1AA4AF2852C9166E38A46E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("021 Gray"),_T("015A99179502B880756AA0BEA60CC4AA"),_T("01B5750AD0FB01E2ED32BD82C1D81DA0"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("022"),_T("01DAFBF5D1DB29911AD6E3C28B177C52"),_T("01F26E0C642B9F63BF509154038FE4B4"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("022 Baseline"),_T("0156DA0F6CB05402768A8D3DD04ECC6C"),_T("0163FB39B3ABD9B660E34373AB7D493C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("022 Baseline Gray"),_T("011FFEB512FB1C5FEC87B20A0393C51B"),_T("0174462842394EBE92A30BF2C0218121"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("022 Gray"),_T("0144B39F0745FE14081460A17C9F0EDD"),_T("01790532CABF49AD76891FFD62356BC1"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("023"),_T("0127817626115968C5209E0DE893658C"),_T("018A1898AFD039F134389BD9C3BD1207"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("023 Baseline"),_T("01E54E7B9935A1823BD7813756967A82"),_T("01FDE410993C16AC3DD3215B90356FBB"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("023 Baseline Gray"),_T("017847DED0D72816ED793C0653399846"),_T("01F861D1354732586D40BC1FD35DD41E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("023 Gray"),_T("014822C68A0E484A993E17FCF585C83C"),_T("01B42FC018510E940575716D9F2CC132"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("024"),_T("01AD1431E7E7E855D5882888C08FEDCE"),_T("01DF495B594519EB683D744308BFCC3C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("024 Baseline Gray"),_T("0199F8E5AA2715706C5D86E6C063AED0"),_T("01AB425B0BB561E5D81F73461FCFD53C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("024 Gray"),_T("0199F8E5AA2715706C5D86E6C063AED0"),_T("01AB425B0BB561E5D81F73461FCFD53C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("025"),_T("01E1BDDF6C45DBEC46FC48B60BBF6018"),_T("01EA5E13EF082CE6D445C4AC8ED703A8"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("025 Gray"),_T("010E9D90B70F67A74998A33E2617EFEA"),_T("017EFD436979334F7462F6D419A0409F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("026"),_T("0151A009EDF99BEB2F36F3144CAC3AA8"),_T("017CE6C1F0D1E4AD2C6A76454B0DC6D6"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("026 Gray"),_T("01350FAC262F271A402061E7A92657A7"),_T("017C4553F75B9286974C886AEBC452CD"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("027"),_T("011AA95A067A44EFE4ED594A7A10A60D"),_T("01A4D8C74D429DFFA9E7E8CA28A5037D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("027 Gray"),_T("013E02157EB5DB737A047347048D690F"),_T("017A7F16CE910CD41DB40D254B8E3C00"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("028"),_T("019086A16FAAA8C9EB3BFAE9CC6F096C"),_T("01C66E4A63F60FBEE086C72C84BB3BAA"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("028 Gray"),_T("017766E2B681D23724D1C8D83AF21ED9"),_T("01EF36845FE887FDA32AE0CEFE9301E8"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("029"),_T("019420068645B04E0AB5B600562E4D34"),_T("01D3E4499654186CEF7A4B146040D88F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("029 Gray"),_T("010EA6645EF02F7CD84388BDB49DD441"),_T("01812B12E4C29E5CE6CD24A08B080E82"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("030"),_T("0167A32FCC8F153A51B2AFF207149263"),_T("01C530B87D23AF05C825E5F17C117894"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("030 Gray"),_T("01B864B56117822F710C17F001F5F51E"),_T("01DA9F3B7A014E2E21DB6BD7F2400787"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("031"),_T("0120240537230FF485E6F7B275736D66"),_T("0168C32A593FFC45927D116D1D8C8D5A"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("031 Gray"),_T("01E7214A25C754357E0BA14BBEF0C3C5"),_T("01FF8A40330C94B23ABA5B8B776533CF"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("032"),_T("0179A42A607F414795D1C0AA4F7812B1"),_T("01A7D58273508268F0027B337E9B9B45"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("032 Gray"),_T("0150F18D85D9427B5B10534D4C691403"),_T("01A1EF24C114372F78BEC3686E4DCE06"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("033"),_T("01305AB319A9D55BB8D687C882D81F4B"),_T("01F713F3A15722B9E150D9FDC208057C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("033 Gray"),_T("01790540992153EBB158E27DAECDE058"),_T("01D877F04A272A12FE8F5226CB015902"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("034"),_T("015246209B28B1C08EE92BF82AFD7252"),_T("01816E05E735E241697A1F2B1A8FF6FE"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("034 Gray"),_T("019899F0FC9916880F066BC0BE7856D5"),_T("01DA91F2DFA45AA049601EFDD45D53B6"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("035"),_T("0183F20270F106C2C089DDDFE2D6C626"),_T("01E3AB977A4827AE486B1D7E3940E953"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("035 Gray"),_T("011264D15B226B6331EA524A178CF762"),_T("0134EFE39D2DABDC6235B0CB9146EF57"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("036"),_T("01264E8FC69DB0D4E823310AC4A62F5B"),_T("01FAB2BA2D9A80FB421DC6981F422A94"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("036 Gray"),_T("012DF7E87095F3A4D07DBC92373D9B4F"),_T("01FC66F233B3BE25F29099CC55B0885E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("037"),_T("0121590D0BEDF72A4143EC952F460381"),_T("01E628E7BB9ABFE61671ADD29C40C494"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("037 Gray"),_T("015A3EBC8CE27C2263ACFE59FDEAA9FD"),_T("015F3D8E92A854F7DD672416B986181D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("038"),_T("0142CD8148CDCF1773B5033BC4F6DB7C"),_T("0175F083CDB8B43AC45869AD5F233302"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("038 Gray"),_T("014EBD5319703B5C799FF67F85369A24"),_T("015C41B94BA775521381E9A3DD1D0E67"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("039"),_T("01225CBD60ED2AD10620D8DF77E71FB0"),_T("013B9648B48BFF6B7B099F3FD651F248"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("039 Gray"),_T("016841AE563FF5A1202CA89697227C79"),_T("01D2BE9EDDEFF1E984B81E79E3FED82F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("040"),_T("012247F7591F152CB8F0A9859A5CAE7B"),_T("01E9C459D99D5A7EB868FD7782AEE67D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("040 Gray"),_T("0120CDD2204490080A40263C61858CB3"),_T("016C2734A1E5D1B70EF40A6C3188BE69"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("041"),_T("0127C46FF50D958B8B384E6F0AD2E8A8"),_T("01B7CECFBDFB72C303882D2CAFC59A74"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("041 Gray"),_T("0113B0EF4E7461BB505737FC88B5D0BD"),_T("012388C889FE36A02B05F47E5AA2A6A5"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("042"),_T("0129E22447C9DAF1C399DD56A361ED12"),_T("018F8CD5A5C334B58F55752E4E490831"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("042 Gray"),_T("0157890A2FEAAC8D8C821656B843D3BD"),_T("01DE4AFC5FA19B360DF6CD75CA6F2630"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("043"),_T("010B2A78965C750E17CD6AFC82E4C383"),_T("0121DE7AB63C9FB70AD06BFE55115CC0"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("043 Gray"),_T("0168C82969D81B945688F0F3C440C12A"),_T("01DE38198CCB700A64CD2856AE6F6E95"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("044"),_T("0123A1A8835A75EE1DE4DDDB26B19F17"),_T("01D587857C3B50B1C030DD163E85021B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("044 Gray"),_T("010B836AADC68BAE29CA32563548136E"),_T("0180F16550B7AEEE50ED1E9F3B979BDC"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("045"),_T("0186F9C1D60513E78DA10AB8A11EBF2F"),_T("01EAA96641C0139DBE4744ACFB0635C9"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("045 Gray"),_T("01E8A97442C3AB91BE7A459F832B1542"),_T("01F1F92020C2A577FED4E54284E9F4D3"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("046"),_T("0179F3FF136D4ED422E37B67FD7540C0"),_T("01E59C1A56C91BC1B050D764A2503A6A"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("046 Gray"),_T("014BDF62789FCD30F49D651762C762C3"),_T("01EDF4068076CF390F5E992CF8D7671B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("047"),_T("01C2C5F19300276881675802CA117AFF"),_T("01DE888ABC6D1237F227292F3C2CA6AF"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("047 Gray"),_T("0133957C29272CBD22C122D57BFCFAF4"),_T("0162031166211D6FD11E0E0459196DBE"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("048"),_T("01AE707BB10E5B75C6C1C72950710BC2"),_T("01FBCE244CA094EF3E713642A284AE75"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("048 Gray"),_T("01DE8416C14C4A77B0775116285A5FD0"),_T("01F9D08C289E2816F7948FA464F14D6E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("049"),_T("019D38AE2A0593E6CA1796D340F9C8C4"),_T("019D75AD2E9F9F3E32AFC268217DD894"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("049 Gray"),_T("01B3F9CB307D6EA42C70BA3F1A1A3980"),_T("01F1B3CA3A9317E0BF83E26BC15EFE6D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("050"),_T("0133FC69E52E74319F110B4486B8B0D8"),_T("017FEB124293E03634B25E85B537A2E9"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("050 Gray"),_T("01D721791D863035D28A72BCB3992FAD"),_T("01F2F9B33C8A515088AB4F8A57BD09F2"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("051"),_T("01472DFFD69C61F0236252CEC3D93A59"),_T("01AA29A71CF32688CAA00C0345252BE3"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("051 Gray"),_T("0152A96E81A2E16D04079E533F08CA43"),_T("01EEF4B339A3CE53F9006963F1F88998"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("052"),_T("01BB95128BBB51E2CDB18EE3464EB78A"),_T("01C77ED677A7444C7303760B540151A3"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("052 Gray"),_T("01C3D3D11D66BA55032A2889E25E6D3D"),_T("01C9A767730799D049B2C57B960C115E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("053"),_T("011D227275F2AC493D1A6A1492BB77C0"),_T("01ED7F994B85E53AF98F2BC8A1D76759"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("053 Gray"),_T("0157AED65A17EE6DFA6F71DF01F4B464"),_T("01C74D9D2760A28FADB0C8E62D8D6458"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("054"),_T("01621500A3E854663655E2A69AB304A1"),_T("01C937495DA1BD772ACC0DA4E9E2DECC"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("054 Gray"),_T("0165074F1C9E973ADE6C604727FAA835"),_T("01DAB04F1D318845D3C7E5B40F90870C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("055"),_T("01B740329A84086970A6293DC09A8FCC"),_T("01C32360C87E4BDE82548DE301DEA159"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("055 Gray"),_T("010615CF2AA5E0D93B8D36C96DB4642F"),_T("01261D04EA4EA8D29F63053627ADAC54"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("056"),_T("0137761655C50D80F4162817A18A3920"),_T("015047A760AA50A563D0ECFAC4386056"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("056 Gray"),_T("01116F0DFF19B83CB7A5F3247636284F"),_T("0126F525F78C06384CF5250CEA75639F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("057"),_T("0116C72F9570BAC3A7EBA653C02444AC"),_T("015CBFF3B2FDEBE2602CB83EFC2688DC"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("057 Gray"),_T("013B67ABCAF2C9F654181EDB1CA63717"),_T("013F9615D6C1C61EE57178F7DC50B0DB"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("058"),_T("016AB252DEC4F6934FE95D58A15F7DB7"),_T("01D1328F2F91E725469044B4063D1C4F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("058 Gray"),_T("019E75CAE868EF1C82E59DE7533922A2"),_T("01F8470BFA03E0E546FA08E72CFFF65C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("059"),_T("01BEBCC9A81E85194989409335851B32"),_T("01C6EA1A6A3BB78C164A83168D921736"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("059 Gray"),_T("014EF48C7F135B7586EBC027F4B06478"),_T("01E6C2A5F8BA5B973206CA732E425EE8"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("060"),_T("01195A026C32F022A48BC36FD0D4D64D"),_T("01F08A12F2ADAE77844686384A57586C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("060 Gray"),_T("015A51E4B01EE84E2841914511C8AC32"),_T("01DB43FAA6FA415E716878737358C331"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("061"),_T("0185CD228521305D8A3490CBF8A409B7"),_T("018C8552EF8C257A88F67B3C878F027A"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("061 Gray"),_T("018A4084F15493F2D2D86D4D372B3227"),_T("01BC3F21BE4C67B1793F135A8202D542"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("062"),_T("01C16479F816F0780B7B435C0A260E1B"),_T("01F8B58DB77D7D86532D621723DB8696"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("062 Gray"),_T("010889A479D668E1B0ADEC6718AD824B"),_T("012284AC8BBDFBB3E9DBC94C06947C32"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("063"),_T("0123A1DCFED52D07F5EC102A1DD65CC4"),_T("01E267EAC491A4E9E29D44F8A908273F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("063 Gray"),_T("01794D803B2513E44FC0880D80F5C6ED"),_T("01EC07C26593B71842880ECA0F97A4EA"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("064"),_T("01925341B1402B2B890C20539B2994B4"),_T("01A506A5268ADF6774AD1DD49F250957"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("064 Gray"),_T("0109EB325DDBC8BE92C9FEA5FC094F05"),_T("01A737652BBA7373792E10CDDFC1F37A"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("065"),_T("0139091A8EB09D2E5B08BF57DA89136A"),_T("01FD829AFC9398AA4692176577CC045B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("065 Gray"),_T("0163F622658A1D5A34EE2A0C0CC7E753"),_T("01DFA0762D896CC0D28EBFD72C4636C8"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("066"),_T("010973B55CB8F35CEC6BE27E8A6114C3"),_T("011C1D7F8A70B35D705697AD7C3035FE"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("066 Gray"),_T("0197BC85139932CD93236BF56D9600D3"),_T("01BB08DD8016C1A52BA05BCC1B70D418"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("067"),_T("0115B960DFCCAED914805028D6BE5B9E"),_T("01E46A79F6348351DC69F39906F79815"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("067 Gray"),_T("01322D28A106B1D69A67397D203DC2AB"),_T("015B7AADF7F79F1022ED982956F1A354"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("068"),_T("012BE1B445368E603FC22008BD93022A"),_T("01A5343F7E0036358F115437CDDF62AD"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("068 Gray"),_T("017FB581F809207921A8B4FC49053BC9"),_T("019D0460FCE1BE7CB21EDECDB459A189"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("069"),_T("019440CF19661C1F7828F27EB76A8DFA"),_T("01F80863A47C93BAE0AA573CA22BC24C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("069 Gray"),_T("010495CE0D8FB4A4C0A3F5C82D8EE71E"),_T("01AAE70F705BFA52EE947CBEBB9D4F3F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("070"),_T("012E11ED043029D57BEF07015C8706F5"),_T("01CB9E06BC0516835D9AD2264F9E2DB8"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("070 Gray"),_T("011D54A91F2767E204B3156EF7D939B9"),_T("01C3CAF8C48F2C9E84AF3750B68EF1FE"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("071"),_T("011975EE86201F10E48E4F365C73A839"),_T("01B8FDD60747E53114DC15797CC09B4E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("071 Gray"),_T("017124153ECD2C1080FB1C81DE3E8966"),_T("01B85C5272CC4E0F18B4296963627C55"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("072"),_T("016A9F39EDF7E9DCAF8BE822C2266077"),_T("01F0A31D3842CFD4B7E09178F141E14B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("072 Gray"),_T("01040344A2DB072C102867283CB40094"),_T("01EBED1BEF3A14275D6F99C39E693140"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("073"),_T("017659A2F9A530359CB8725D32B5BE6C"),_T("01F863D3F47BE8F243BFF177EAC1EDB4"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("073 Gray"),_T("012A4FCCFBB2E5EB17ABF53CB8CE19D8"),_T("01C1F982D08F1A78A5165145F51496D2"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("074"),_T("01403088D08B8A2712CA648846151E07"),_T("01BABD681F45ABBA1BDCF41992781236"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("074 Gray"),_T("017B6F3C3060C8FBDC545D51B689926D"),_T("01FAA30172673DECEDD32E154151FEE3"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("075"),_T("012D821C6AB210E2A753BE053B8F55D0"),_T("0182408A81A4ABF04D4A34A8A5E98C58"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("075 Gray"),_T("019C6C4CB99521A5680C96B0EE999485"),_T("01C8ADEC252DAF2DD41A3F13A6B26952"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("076"),_T("01786593B7990A17B0D81B6DF749470E"),_T("01DF37EBC825495EA04E9B311B77D309"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("076 Gray"),_T("01DC3D7DB9ACC994536C4DB9946E9711"),_T("01DCCEE0F68DE87E7373AC29C1CBB49E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("077"),_T("017326197BBD2E1FDD0E11F8566B9AF0"),_T("01E130328507AD3C0BBF764713BAA825"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("077 Gray"),_T("0141F107BB584F14E87768245DB3AF76"),_T("01F1541340407C08EA76A4FCFE8072B2"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("078"),_T("0120996088E68CF9F70A20A414D14AE6"),_T("013E3A5D329BBCB6AAF62F2E18FF8127"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("078 Gray"),_T("0121F5AA8F3FDC544FE971687552237B"),_T("01702C9DDEEF45423E653771CC795E0F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("079"),_T("0182230692721ADF5DCBFB56F747490C"),_T("01DD92C0CD7077A88C49139F2F15908D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("079 Gray"),_T("018FF6814B9CECD349F3C68DB05AE935"),_T("01A3E3C211808C98C590BCA8648EADF0"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("080"),_T("0175BAF3251040E0EFB2930B73328E7F"),_T("01DC499064BA9264D591FDE9071DFD89"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("080 Gray"),_T("015025DF3475A3F29C67076450ACA130"),_T("01E0394825707E498E84188416172B0E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("081"),_T("014D29278FD055B04D8FCEF52F63568B"),_T("01EECF7F5B388E02EEE84ABDCF4CECCB"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("081 Gray"),_T("01AF22414DC63BEA0C335DE6D1375597"),_T("01B475A679A93E2BC96403919A8EC24B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("082"),_T("0138A8D4ECE59F41D2EB9AF5168B6675"),_T("01CA9A809F737BA668C16DDE52E74092"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("082 Gray"),_T("017FF59AA3FE074887A5BFBD5F62022A"),_T("01FEA37B95E38ED4CAD108207F94128D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("083"),_T("010300D2A3C0CEB8216F7C59B96AFB16"),_T("014F706DC17A4AF11117D50B414F348C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("083 Gray"),_T("01051ABAFD203A1D4605907C8543F055"),_T("019B7D8C1A094ECB4CBB5B828420356E"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("084"),_T("018F43694F4E9A49C24613CE0DB777A1"),_T("01BFD6DFF74A169EDA4F585691B1C832"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("084 Gray"),_T("01B5F6A0FFE77B77435B2FCAEE7C6F80"),_T("01F3041C2B3DF3709A124468F429A720"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("085"),_T("0155D875C95B74D0F3C5835A62516F48"),_T("01D38A25358EB7649A254E19F1D46600"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("085 Gray"),_T("0130FCE1BA83C767EA3CB8DB23D92289"),_T("0181EC6986C4F1EABDE468325BA3A394"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("086"),_T("01AC139E31B941CA0F2C5B5A0BFCDFC0"),_T("01F3D5B0FBE08EC4AAE9E1E4238BF215"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("086 Gray"),_T("0114DB57CAB32401E0507B831E2A52E4"),_T("0146686A83711D8227677BFBBA638030"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("087"),_T("01387A14AF75DC6963F040C1239B7DED"),_T("0196457BE1E9E30F00715A3DDE8B160C"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("087 Gray"),_T("012000BE0A51DBE0A2C9892010AA5F52"),_T("01ED8F3F34064DE4F66E3020450CB51D"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("088"),_T("0197DD04E9338FA3B25733603CE7B284"),_T("01EDFA7E57FD291021994E804A3F8B7A"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("088 Gray"),_T("01087F903C023E08A98F0AFFDECEB92E"),_T("01FD306EB29345CD98B6A5745F0E7E75"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("089"),_T("010F50672F14B4A88409AEC86E9DECE9"),_T("01C3B4FE62DF9A99F1CA8A5C17AC7711"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("089 Gray"),_T("0151EDAED564F03C97DECD9354C9E257"),_T("0196AB42568EED23B00AA7EA62C8A2EB"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("090"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("090 Gray"),_T("015C645021E37D3469A6B652789383DB"),_T("01D400C125EB43B05762A66347B271F7"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("091"),_T("019F3987F634C2AABC21F2AF9FF4A0DD"),_T("01B96BF26D34997052B944BCAE85EB75"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("091 Gray"),_T("012D8D2AA086D89492158B78E1409893"),_T("0176BA0E25E41748CB30F6A569C793C5"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("092"),_T("01557A9AE226A38386271DFE13D64298"),_T("0167FCEDBA3A8E8CF822163DB3564762"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("092 Gray"),_T("0142C7713D66971ABCD4705A86C69165"),_T("015BF30464B173AD153EB6FDF2F443F9"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("093"),_T("01B47B996CFDAA5BBAD40B9496314C1B"),_T("01BFF13DEB883EF04BEF63AE789B06D3"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("093 Gray"),_T("011D2972762547222591CBAA7C61AF23"),_T("01A6F243D0894ED6B08CD932F2C5F096"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("094"),_T("019A5A3F4E1CAB2BEA76F978702613E2"),_T("01F870A8F8261FC607E1DE4C088B1B47"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("094 Gray"),_T("01945002AD5673EA722BE69C865C25FD"),_T("01985BEA05A4061A6B7350876FD023A6"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("095"),_T("01E6610D026E8E6FE4BECEA9B3328A63"),_T("01E764F3ECB6C14A51FF83F1FF6D546B"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("095 Gray"),_T("01154D4A58716A0D3591A6CD38D1A6B1"),_T("018667606B031F3EB98BE15F21933033"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("096"),_T("0124512C758C4EA7689FD76F2327664F"),_T("01943EFC55D71F0B8BD5172B58D4D1E6"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("096 Gray"),_T("01A02F112389AEA183D45DF351CCA76E"),_T("01AF02847E47B29390CD232AD89735D3"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("097"),_T("010564D93F295ADB889B91604DC82EE1"),_T("014302FE54745F4DBB58A0D51CDC66BD"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("097 Gray"),_T("01078E051231C5656C68E628BC44D34D"),_T("01635537D06C5A911C84767FCEC61FCE"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("098"),_T("01081C0D2E757D5A5E24734E147CE6B9"),_T("019C33083B8FA8E4D2CED45F06F0B201"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("098 Gray"),_T("017165E9E48151933AC85B03ABADF71F"),_T("01C7F75AB9E45A76BAA81B38A8BC3AC6"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("099"),_T("01C7F83908166C226C06A44017421732"),_T("01D3EFDD3855C42AE3E0E6289F1A6726"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("099 Gray"),_T("0169F10B74745DE17CC5BDC51629A6AF"),_T("018177A3B8C276E1BE69C65555927CA7"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("100"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IJG Library"),_T(""),_T("100 Gray"),_T("01BC2BB6764A7F9709F829E766D93AAE"),_T("01BC2BB6764A7F9709F829E766D93AAE"),_T(""),_T(""),_T("IJG Library")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("000"),_T("0165AC93CC56CD962E10217D526A4E41"),_T("0165AC93CC56CD962E10217D526A4E41"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("001"),_T("01320332E53ADAA0073CE0CEC27FE3F1"),_T("01320332E53ADAA0073CE0CEC27FE3F1"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("002"),_T("01E036E949A895A37821CD14EBB4A675"),_T("01E036E949A895A37821CD14EBB4A675"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("003"),_T("0174A31FB9ACE562DE1A8E872E9CCD87"),_T("0174A31FB9ACE562DE1A8E872E9CCD87"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("004"),_T("01A134A20B2372BEE6603196DED7BC1C"),_T("01A134A20B2372BEE6603196DED7BC1C"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("005"),_T("01B1BB61E82C7572D6BACAC16B9416E2"),_T("01B1BB61E82C7572D6BACAC16B9416E2"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("006"),_T("01683DDDC33FB58B75F62B69669762EB"),_T("01683DDDC33FB58B75F62B69669762EB"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("007"),_T("01D83C9B11E571CEB80835C5F27A7325"),_T("01D83C9B11E571CEB80835C5F27A7325"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("008"),_T("01062ACF66978332F99F455BF1BF02CA"),_T("01062ACF66978332F99F455BF1BF02CA"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("009"),_T("0191560E1D00D2548C2B84CBD38E4F90"),_T("0191560E1D00D2548C2B84CBD38E4F90"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("010"),_T("01F70CA7113363A125152495402F4B3A"),_T("01F70CA7113363A125152495402F4B3A"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("011"),_T("011AEBA34603BBF13149C2DF6F0D515B"),_T("011AEBA34603BBF13149C2DF6F0D515B"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("012"),_T("01A7F1472D707FA981CD95BB2704BD51"),_T("01A7F1472D707FA981CD95BB2704BD51"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("013"),_T("012390AAF66ACC40F1E0BBDAC7F7C121"),_T("012390AAF66ACC40F1E0BBDAC7F7C121"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("014"),_T("01057F114EFF86B7EEAEB29B44D91FFB"),_T("01057F114EFF86B7EEAEB29B44D91FFB"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("015"),_T("0118EC3E8E053C034DF05BE8B0F57955"),_T("0118EC3E8E053C034DF05BE8B0F57955"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("016"),_T("011707F5512F6B6A5DC49A505D01AE6E"),_T("011707F5512F6B6A5DC49A505D01AE6E"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("017"),_T("011AE0EE6EC94BEE7A9A6B044A61140F"),_T("011AE0EE6EC94BEE7A9A6B044A61140F"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("018"),_T("01DBFA99FEAD99E45BF3F8E87A6DC496"),_T("01DBFA99FEAD99E45BF3F8E87A6DC496"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("019"),_T("0179A73F972B0B3F50D1E7F08E6BCBAC"),_T("0179A73F972B0B3F50D1E7F08E6BCBAC"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("020"),_T("01256E630ECC0F36AC9A66A059BB8822"),_T("01256E630ECC0F36AC9A66A059BB8822"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("021"),_T("014A56275ACC27F844CADDB17F98F26E"),_T("014A56275ACC27F844CADDB17F98F26E"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("022"),_T("01D42506093CA9EF8A953FD39AC01065"),_T("01D42506093CA9EF8A953FD39AC01065"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("023"),_T("01C9E68E93AA669A128AEF8CA399229B"),_T("01C9E68E93AA669A128AEF8CA399229B"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("024"),_T("015E1F710449F305ABFDB69069868E75"),_T("015E1F710449F305ABFDB69069868E75"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("025"),_T("01F610DAE4667E04A680FB5290680918"),_T("01F610DAE4667E04A680FB5290680918"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("026"),_T("019E8BED749941E7119D32CF7596D03C"),_T("019E8BED749941E7119D32CF7596D03C"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("027"),_T("016B1EFCF5EB29A6EC6C9B60543F3310"),_T("016B1EFCF5EB29A6EC6C9B60543F3310"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("028"),_T("012921014AF19689F7F763C9B0C45326"),_T("012921014AF19689F7F763C9B0C45326"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("029"),_T("0101A87A5738D68CBBD00DD5A6E243FE"),_T("0101A87A5738D68CBBD00DD5A6E243FE"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("030"),_T("01A33578C3220069FEAAA7E75291FD7D"),_T("01A33578C3220069FEAAA7E75291FD7D"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("031"),_T("01182426BB9EE261B719D69D33F2B292"),_T("01182426BB9EE261B719D69D33F2B292"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("032"),_T("0105B6A25A9C3CC6C116D3C1423C9911"),_T("0105B6A25A9C3CC6C116D3C1423C9911"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("033"),_T("011B084C50C703C19F8139A65F872BFB"),_T("011B084C50C703C19F8139A65F872BFB"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("034"),_T("01368977779D7F6794C6D8ED97A15DDB"),_T("01368977779D7F6794C6D8ED97A15DDB"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("035"),_T("016D0A6F0008E38FF4871D6FA2FDF670"),_T("016D0A6F0008E38FF4871D6FA2FDF670"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("036"),_T("015DBB98F058A2FCF2E2C4E2F4DEE19A"),_T("015DBB98F058A2FCF2E2C4E2F4DEE19A"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("037"),_T("01F3C4686DB5BF716079413E8E797364"),_T("01F3C4686DB5BF716079413E8E797364"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("038"),_T("0125A88E7EE182C7AE60C2D4D7164AA5"),_T("0125A88E7EE182C7AE60C2D4D7164AA5"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("039"),_T("0153AFED056FAF18883C6E96B1030880"),_T("0153AFED056FAF18883C6E96B1030880"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("040"),_T("01B6C23631B1BEEB8BE9B8B02DCFA8B5"),_T("01B6C23631B1BEEB8BE9B8B02DCFA8B5"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("041"),_T("01123CD019B873459AAD3952CEB8D1A3"),_T("01123CD019B873459AAD3952CEB8D1A3"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("042"),_T("01A8E1140B0BF7461026A4809DBEAEB6"),_T("01A8E1140B0BF7461026A4809DBEAEB6"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("043"),_T("01581A0E69C1827A70976EB09BE96F8B"),_T("01581A0E69C1827A70976EB09BE96F8B"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("044"),_T("016BEC3E5671BBE6E32F29E7A000314A"),_T("016BEC3E5671BBE6E32F29E7A000314A"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("045"),_T("0177C479CC3569F601E2D189FF09093D"),_T("0177C479CC3569F601E2D189FF09093D"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("046"),_T("011D2C9DBC773C3786D8F5402609FBF7"),_T("011D2C9DBC773C3786D8F5402609FBF7"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("047"),_T("0108BF398EF6D0B8ABC608669F239502"),_T("0108BF398EF6D0B8ABC608669F239502"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("048"),_T("01C6EF48FB38D410960A4B5295402D13"),_T("01C6EF48FB38D410960A4B5295402D13"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("049"),_T("01DC96B5A5DA85F89903453952815094"),_T("01DC96B5A5DA85F89903453952815094"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("050"),_T("019F146786D0C38328847A24D182AE7B"),_T("019F146786D0C38328847A24D182AE7B"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("051"),_T("01B7F57F8C74ED65BEBE6869D2E21460"),_T("01B7F57F8C74ED65BEBE6869D2E21460"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("052"),_T("013A6B5B0036C84A990351B774AA806F"),_T("013A6B5B0036C84A990351B774AA806F"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("053"),_T("01793AD27ACF46FE764114536DED4202"),_T("01793AD27ACF46FE764114536DED4202"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("054"),_T("011032D627D34988AFB0C81BB38AB10F"),_T("011032D627D34988AFB0C81BB38AB10F"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("055"),_T("01EADC023F4E5C5AAA1AC39A8DB1FDA2"),_T("01EADC023F4E5C5AAA1AC39A8DB1FDA2"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("056"),_T("01542C4D2A5514D93FE3364CE687C454"),_T("01542C4D2A5514D93FE3364CE687C454"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("057"),_T("01813B424C27FE594BE7BD3343E0A611"),_T("01813B424C27FE594BE7BD3343E0A611"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("058"),_T("017900994312A5DE5F9FAE88C288E214"),_T("017900994312A5DE5F9FAE88C288E214"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("059"),_T("0191BE33AB50852173F373BFB13EDF79"),_T("0191BE33AB50852173F373BFB13EDF79"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("060"),_T("011D3C2904614E246C4B468A20F3A936"),_T("011D3C2904614E246C4B468A20F3A936"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("061"),_T("012A482E2BF56F6F79CC68F954B9E546"),_T("012A482E2BF56F6F79CC68F954B9E546"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("062"),_T("01EFC4FB222400071490FEFB4758227A"),_T("01EFC4FB222400071490FEFB4758227A"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("063"),_T("018116332ABC764D7A310A24BE177139"),_T("018116332ABC764D7A310A24BE177139"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("064"),_T("01C9755B12B233887E9324B085D765CF"),_T("01C9755B12B233887E9324B085D765CF"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("065"),_T("010066231D4ED98B946D06673BC5461A"),_T("010066231D4ED98B946D06673BC5461A"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("066"),_T("01A22CB689E1CE541A6F9C90B5BAAD45"),_T("01A22CB689E1CE541A6F9C90B5BAAD45"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("067"),_T("016D25B5E4025E5C6CD9669925D466AF"),_T("016D25B5E4025E5C6CD9669925D466AF"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("068"),_T("01081855DC7D86A3C49FFCD1FD0872E3"),_T("01081855DC7D86A3C49FFCD1FD0872E3"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("069"),_T("01B4CBB1E2072AF552406AAE4F6229C8"),_T("01B4CBB1E2072AF552406AAE4F6229C8"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("070"),_T("019F9FFECDE5E7D2C16CC9690B8D1F84"),_T("019F9FFECDE5E7D2C16CC9690B8D1F84"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("071"),_T("01365815032821702D1D930EBAB3A018"),_T("01365815032821702D1D930EBAB3A018"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("072"),_T("01C52D343FE84C9F630B12E74D24FC3C"),_T("01C52D343FE84C9F630B12E74D24FC3C"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("073"),_T("01D9875CC6270A5D1F95C86812F2332B"),_T("01D9875CC6270A5D1F95C86812F2332B"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("074"),_T("01DDDA3E938F3F32BDA4C6FB2580C07D"),_T("01DDDA3E938F3F32BDA4C6FB2580C07D"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("075"),_T("01AD10A6B3BC47A7087FA4AA6DD82A84"),_T("01AD10A6B3BC47A7087FA4AA6DD82A84"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("076"),_T("018858FFFFCA04022B685715553469F7"),_T("018858FFFFCA04022B685715553469F7"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("077"),_T("0161B033070AD7DF62ED0D0C5E738D2F"),_T("0161B033070AD7DF62ED0D0C5E738D2F"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("078"),_T("01E1FE1B4167D1DB9E61B353A0C222A0"),_T("01E1FE1B4167D1DB9E61B353A0C222A0"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("079"),_T("01B88714C0895C6C53D6BE36937A449A"),_T("01B88714C0895C6C53D6BE36937A449A"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("080"),_T("01E6BB7915E70A0580A079D7A78298B5"),_T("01E6BB7915E70A0580A079D7A78298B5"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("081"),_T("01535ED71A83B97108BCEB895970043B"),_T("01535ED71A83B97108BCEB895970043B"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("082"),_T("01DF44F9FB42F388184BE63D97FAAF59"),_T("01DF44F9FB42F388184BE63D97FAAF59"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("083"),_T("010B5C07E62A9FB8E0EC07F424F91BC7"),_T("010B5C07E62A9FB8E0EC07F424F91BC7"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("084"),_T("0186FD4E87FED64154FD29050DCDE911"),_T("0186FD4E87FED64154FD29050DCDE911"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("085"),_T("019CB44E34BBC199CCDE9949BC3C81AA"),_T("019CB44E34BBC199CCDE9949BC3C81AA"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("086"),_T("0102F441777107372DDBA78ECC612F95"),_T("0102F441777107372DDBA78ECC612F95"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("087"),_T("01F77B3D704D81FC9679311833807D2F"),_T("01F77B3D704D81FC9679311833807D2F"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("088"),_T("01DA4D763CA09070FE565F16F98AA391"),_T("01DA4D763CA09070FE565F16F98AA391"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("089"),_T("01F1DAF5AEE48C7A85C561856ABA0ABD"),_T("01F1DAF5AEE48C7A85C561856ABA0ABD"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("090"),_T("01AD2B3452A92FE3564BFC87014D17CB"),_T("01AD2B3452A92FE3564BFC87014D17CB"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("091"),_T("01EF6B2FB59A6F333BAD5FF3CA481240"),_T("01EF6B2FB59A6F333BAD5FF3CA481240"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("092"),_T("017B4CC93608A96F242BDD539E9CB8FF"),_T("017B4CC93608A96F242BDD539E9CB8FF"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("093"),_T("0142A062D95E6067C4B0B791526A0C5D"),_T("0142A062D95E6067C4B0B791526A0C5D"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("094"),_T("0121303C9E720270C0931427D9D0FB2F"),_T("0121303C9E720270C0931427D9D0FB2F"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("095"),_T("016C410AD0D0DBF3709961EDBEDD7D0B"),_T("016C410AD0D0DBF3709961EDBEDD7D0B"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("096"),_T("010E60C5B6D1D2C9163A91ADC454B219"),_T("010E60C5B6D1D2C9163A91ADC454B219"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("097"),_T("01550366890863E706A41B5610F6156C"),_T("01550366890863E706A41B5610F6156C"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("098"),_T("01E4DEC5DF580F8461F51E4430A0C612"),_T("01E4DEC5DF580F8461F51E4430A0C612"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("099"),_T("01E4DEC5DF580F8461F51E4430A0C612"),_T("01E4DEC5DF580F8461F51E4430A0C612"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("IMatch"),_T(""),_T("100"),_T("01E4DEC5DF580F8461F51E4430A0C612"),_T("01E4DEC5DF580F8461F51E4430A0C612"),_T(""),_T(""),_T("IMatch")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("002"),_T("010D9693F4FC34B402EFA979BED34733"),_T("0193B6220463E5A621ED25A53EC2FE7D"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("003"),_T("01AE4339D18A0F80E83AC68ECA3F29D2"),_T("01D73AB11CDEE244F9E6F86AA656DCF4"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("004"),_T("0130D16765220C8A13FDA6E7015EBA60"),_T("015829A3515B899B026896D737523095"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("005"),_T("010F16DA7E39F9FA0D360306D844BE1C"),_T("0162806319221CD47AFBE36563122286"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("006"),_T("014B8E3BB9C7F7469A34DE7ACA0E3E14"),_T("01D1781C33BA6C700844CF5F06F64D26"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("007"),_T("011EDDE09B712B924A2BE665A74AE914"),_T("01AC05807AE1A285B2B1F24793ACB8AC"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("008"),_T("014682A529B0B422C82557495769AF92"),_T("01A9CF2158FAE4057FC08722ABD92D67"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("009"),_T("016D0D6BB91282D033CCC41AD6BF3CB2"),_T("01FB5E38DB85808DEDE20EAA84BB9812"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("010"),_T("0101092454C6BA70F329E8323BA37A62"),_T("01D3F187A0B029D75287067CC329CBEB"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("011"),_T("01241D8A9C72BB77B5EFE13F46E0A694"),_T("01886D873F6F6F190084AA8EACCFA7E4"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("012"),_T("015916E2168735FB572926A049B025DB"),_T("01F9ED4812F46CA42CB85C9371E94710"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("013"),_T("011ED6AAC481E84EB7DF7D6C55C35FDB"),_T("01F41F75DA85DCEE81F79C9BFD835249"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("014"),_T("0159C3DD4607B9ACB9BB3F5D7191891A"),_T("01901016622EBC2E42EE162000A13DE3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("015"),_T("018390F607F757E2E42726F5EBB576FB"),_T("01EED88C9C6EB2CA6E048972F144CFB2"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("016"),_T("01160566E2F95BA1BF0BD7EE4B0A539A"),_T("01705560C1E678DDFB67349C3C510B2F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("017"),_T("010317C21733B42EA85718360A1ED6D4"),_T("016D83AC7EBE1C58D15569E4FD4EB650"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("018"),_T("012791C800B2CCB875FE41FCA751D076"),_T("01C78E1BE13FDF35BFD3DFC789ADED0B"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("019"),_T("0134A4CABB20CE957BF7F286CF8A4F77"),_T("017A10221C34E697EB4F3D9BE678A664"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("020"),_T("01013FFDF2B833139BDC7D30DB3F6F9C"),_T("012A1A7AE01B91CCAC1C5264E444A3C6"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("021"),_T("01347AC5D164854F8C771A7799867FDC"),_T("017A11C185DAD8B8246F46BC6BBF60EE"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("022"),_T("01166750E43638B43D2714F203408D38"),_T("014D35DD5AA484B2B89A705B009D6BF1"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("023"),_T("018FF7549D7AE5B9D1D2A61A0DFD584F"),_T("01EF84DB7BFD56AE1AFA2694BEB10676"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("024"),_T("0196A9589F2F3BA0D42D937C1A94312E"),_T("01E28097831F0F7B6A5C17D31F74E2D4"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("025"),_T("01CAA4241F9ACC590059C92CC8203E75"),_T("01F7BF349603DA557C8CD6EE7D9C5AC7"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("026"),_T("01561E29456A1AFB859025E2407C7077"),_T("01ABF64A97B6FEF8218EF1EFB776B9FB"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("027"),_T("01821498C3A572DA347E2C024EA303BA"),_T("018BF7FA5F45481749B5AA32797564B6"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("028"),_T("01EB64439B48102135509A2A19152640"),_T("01F5C4A96AE81125E1987D0CF03389F6"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("029"),_T("0144DB8DCD47372608E2295E4EC309B1"),_T("0155964EA581F823AD5ED60982BD2BF2"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("030"),_T("0109523D0200F111FBDFB63DC27DE296"),_T("01AFDE21B58FF9781CD22B60E20F22B1"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("031"),_T("01872C7AE0162EF140AE3C5F5EA39753"),_T("01A5762018316067F45B5D0B30E0E4A2"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("032"),_T("01626CBD0BAEB519B4FA1DB9C280013E"),_T("01646D280597178A2C5344688EEC6E0E"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("033"),_T("0165A4432B13F5117EC466B6DAD5D5A3"),_T("018C4E45F08A156DB04F70F5BB708721"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("034"),_T("0169F22E635E72757DA817F4AF5095EA"),_T("01B18BB69C0824C715BB005F1A4184A9"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("035"),_T("0174A6099629A3AC2A4D187945772A2A"),_T("017DF8CA578501893092725F3B7918D9"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("036"),_T("0170FC9571E8D70265DCADC8049444DE"),_T("0188936C9FF8F4EF33C8F9AE1E337D27"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("037"),_T("01DFE417CBBC628DDC8BB3A78AAD5B33"),_T("01EC396D7F0CBA8C375512E739C7F90F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("038"),_T("013628F4E46C5B171E4B808B8AE2863A"),_T("015D15A0EDFC7D0175E0949D6A450524"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("039"),_T("015ABF68E584D7D7C8877F6FD98C184D"),_T("01DF9616AF38E538261F7AE8571E31BB"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("040"),_T("010605B0608B08F2892492F6CCA254BF"),_T("01166CDDF24FC9B5437579E30667C774"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("041"),_T("011EBBE3EE74E33567F2CEE7BC6C8F38"),_T("01965362F06FCE474BDDFDE09F119CDF"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("042"),_T("01E8295EED0260AAF623B72423E17B17"),_T("01F8EC33907B45D062A8398A2DD3045A"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("043"),_T("01AA8A959B286BC0E480F7362A790200"),_T("01F34AF7BB0266B24D3F018B77BD1D99"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("044"),_T("0132A165637742AD0D3C9EDAF84DC95C"),_T("017EC1C29F2449DA50B3FF30061C6DC3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("045"),_T("01380D2C3886D54F05AF501141908A08"),_T("01463C19A046A5A6DDC79555E325AFF6"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("046"),_T("011FFD5C27656C7C753976FFBA50FEB1"),_T("01E189AB820A6C612129C5D7E0BD72E3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("047"),_T("01548A239BF2C6CC1255CD26F1B840F0"),_T("01F16C6F4375E2055EC31A45A14F3DC2"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("048"),_T("01182829CF6E8D0845AB1F3BF52D9F9F"),_T("0158C3EE617A20028F15D0F25A425D98"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("049"),_T("0121C7DF0C348A2A5E4D4B7CF62D94CD"),_T("017FC54345ADFFD6C7946694E7E49122"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("050"),_T("0133FC69E52E74319F110B4486B8B0D8"),_T("017FEB124293E03634B25E85B537A2E9"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("051"),_T("010CBC45D3C5260863E839BFC2235A81"),_T("01CFBBD314CF6CEB5248469C5E3C2CA3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("052"),_T("019D1C17E70D8AC5C9B6DEE7A30827C8"),_T("01F0547180BAB8A5C8329D7DB6F3F954"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("053"),_T("013146F1F80E20B7C32B0319B214A919"),_T("01FBA1F3C2CCA3C78748DD5C4CC80562"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("054"),_T("01BC27930C37DABFE67EFD9E4AB54437"),_T("01C01A9A5554405594E81AB4C371B932"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("055"),_T("01B72C7BF56F55753B1265BDFF439069"),_T("01F08AA3ED4A18353A524A66691D73CE"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("056"),_T("019A22EAFA396CDD0CDC430C61FFA430"),_T("01D67A64BE0EA692C0EEDDE2EE719535"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("057"),_T("010ECB885D4D576D5C5932FF5A6A5092"),_T("0113B452EDEA1714691CB6333FD0729D"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("058"),_T("015E4B9F3BEAB958F015B81710C84810"),_T("01AD6C71352216EF35FE8520F5D1E82F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("059"),_T("0163526F62E82D53C0DAD905D35C4599"),_T("01A9FC9DF742C7FF082F03A6F87EC381"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("060"),_T("0175E68D4D293E2FA784C8CE11DF5516"),_T("0184D878A64B40EF526E5A6EF6BCBCEF"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("061"),_T("012300395A15B1B6D203FA8393593157"),_T("0134E076C67CEBD6283F4ACFD9BFF5A3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("062"),_T("01F9E4690F1C0BC76BEC16928BAE9A88"),_T("01FDA2A2C7470CAFD274D9FB41AAF0F1"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("063"),_T("0107317B76A298F1175B4BACA2B107F9"),_T("01CB912C521BE4AE1FDB4C842587E7E2"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("064"),_T("012440B020AE88BF95B81B31641CF09C"),_T("01D32149DD50948136591D5F368DF581"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("065"),_T("0141CDC5CFC490A7B8C049F9D93AAF73"),_T("015FECEF7EDC0B3AF333347FF17321AA"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("066"),_T("01A6F76F7CF17EFC800AF2483ED2557C"),_T("01FEBD27FF945E96DF972ADFD2FE0F6B"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("067"),_T("015DAF6A68DCC4478A45C180F88C9DFA"),_T("0198059D58EFC7D276E91AE2E90D2A4C"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("068"),_T("012166ED0C275FFE159418B2A2113CA1"),_T("017B601F4F41E04CD8EECB9337CCBBDE"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("069"),_T("01433F7C61DAA7495770AAF88AE7039A"),_T("01C86AB6D8F5303BDA47B88623E417A3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("070"),_T("012A78934E0D22A24AE899907336F46D"),_T("01E52224D11398FC4821FD4E938BE877"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("071"),_T("011F669669DAA96DAB5C7517A5172089"),_T("01B558FAE56F5994211E6B916577F868"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("072"),_T("014170590155C13FE856CBA528EA920B"),_T("01A343DFC0DB4F646D3063066740BAC6"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("073"),_T("016FDE4F110A6334F0973B29DBF22C85"),_T("01A325BC80221BD481A6D37355FBF9B4"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("074"),_T("011F4D6A97876DA82E951074BC74A097"),_T("01D970DCACCC1D81A2DE8E3E4C3385FF"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("075"),_T("012C8E823FB3F009A733E7B91A146A96"),_T("015DDB4F6B6A8D3A5E934B7C70F69CD0"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("076"),_T("0106E6569633D7A5DE7A24F1D08042CB"),_T("01A8904FBE491ADF0B62FFBDDA4A0FE0"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("077"),_T("0110ECE968535091C39AA238A6E17E83"),_T("01F62C6E04151C290FE6E475B5FFA56E"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("078"),_T("01607299E0B0D313EB869C0789AC56EF"),_T("01D29EE49F2811E430569C8C43F1046A"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("079"),_T("0143DE5B546751703206B2C5335698C0"),_T("01D8674E4E744A68D5BDA4A2543C8B59"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("080"),_T("017608CABE0D8EA50F98359E3B90E58F"),_T("019DA014E50CBF279074EDD8ABA2BFDC"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("081"),_T("01BB618731B0CC9F1EFB45293DFD6379"),_T("01CC621547D81C1FDB424C8B013725A3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("082"),_T("01653DEB309B7D3BE24668026E2BFCA6"),_T("01926E63F4B81298BA87F4C5D8D22700"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("083"),_T("01B0DFEB26DC3CEEF172C10114D1D1F8"),_T("01D100852DA3DF0BE3145A12152DA87D"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("084"),_T("011DD9AF3EC835F5AAD56D8BAA6CA058"),_T("01925CCD917C507DBE547DBAAA5F00FB"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("085"),_T("0145E6BAC626BA2061E26CD9120D3D0D"),_T("017158FF2EC09CAA79A63E1AD371972F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("086"),_T("012D19D8472A61C74A2FECE822664F24"),_T("016E3AB5C1681D786D7EC6AC65EE8C4D"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("087"),_T("011D4CBBB874BC0438B7A82B99F61024"),_T("0121AC61D63E0CE991E5EAA2092B944E"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("088"),_T("01AB6F0F127632E95789CE3F207AE6A6"),_T("01E6B6C5713F5E884C46C5675ED26B2A"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("089"),_T("010F8FE41C7B8EEF01699F91C5E071CD"),_T("0191086A01F0D774B7C509E5D26E51FB"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("090"),_T("0133F539C3C8F7349AB3CD95449C0A43"),_T("015C031486FE1D68DBF351CABB2FA562"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("091"),_T("012D7B879B3DD39080026AECF90ACBE1"),_T("0172C829A8BAABAAA7CD03665971F951"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("092"),_T("01AC6BEDFBF8FC68178A60F6A58703F7"),_T("01B930D70CB78DCB1F19B54BB01CE5FE"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("093"),_T("018E1BB7E1BBB283FD6CC7B63222D184"),_T("01FE4D541951F248E3CFECF937A8B15A"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("094"),_T("01573D26512CB20F26EE9D8BAB4F8F92"),_T("01CCB2F17A97E15E403FEDA856E0AC26"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("095"),_T("011D8D1C132B3AC1E38E908794BC12CD"),_T("019479014B4DADCCAB900417DC5E5E6B"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("096"),_T("012182815ACD54C5ED046112CF86B17B"),_T("01A95CE911A6B592AAD4BBB9A3389530"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("097"),_T("012DAB79295978802275F2EB275F3018"),_T("0177CAD866B69CF219E809A260A615D9"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("098"),_T("016DEBEAFAB638EB0FFEFFC01DBD5A93"),_T("0180FE9314CF21561495056C7829A1E8"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("099"),_T("01023A9C5ADDAD46F387B97385DDAD8E"),_T("016ACE6BDC9B15A229DA6C3803765017"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("100"),_T("01E1BDDF6C45DBEC46FC48B60BBF6018"),_T("01EA5E13EF082CE6D445C4AC8ED703A8"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("101"),_T("010141ECC5CC1790D53255A8DDDC833B"),_T("0128F95E9DE7849E634EA71562327BE4"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("102"),_T("01171F54307EDF50C03ABD8B00DFF08F"),_T("01EBA7D8ECE07830AEA584123271D1A0"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("103"),_T("0101666C809358D2E81FB42FDC63B2DD"),_T("01020222E6F191065FAD2BCC51533280"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("104"),_T("0140D612069F8FAA681E9DBAB8D9422F"),_T("01B6390FABC6D36F61EA3E9C567460B9"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("105"),_T("0142F71E2A5FE68B77119E652C497DA1"),_T("018D7B491F46CFDAAD58ADDADA7C69D6"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("106"),_T("012CE2C6E38F70422E1A4088817E8D1E"),_T("01513A242FDAC9DF86CB10B1983401E9"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("107"),_T("01A73E3CBBB3D58EBF7D305DFE82CDDF"),_T("01B11D8D4DF6FC62A0483F8C5B1B574C"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("108"),_T("0139868D2E3D0B299C5B53E1242B73FA"),_T("0157E6A56B0F86CB33286A66C826AB1D"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("109"),_T("015F3E7E52A9BB54D2968B9502E56B7D"),_T("01A587DD053AC0EEA85252AE153A306A"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("110"),_T("01445B141C321629DE1D172989A5DB00"),_T("01B1FA9AB8E9FFFF4EC9D7E534523430"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("111"),_T("010CCCF0E35063085F6B99EDFBE9FAD2"),_T("01246F5CFD63CC8F8E3B018FD8C5A2E6"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("112"),_T("0172FE66433D5A303BEC3A7B3598413F"),_T("017807CE8752D7040EB8911BE11F2ECF"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("113"),_T("01CCC60FEDECE33BD4D5B9BF147C328C"),_T("01F69436326FFFE5A7D587753E51D235"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("114"),_T("010A74D30FE24B0CB7F0714BDB698933"),_T("014862165168A1D16D354D47BF688216"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("115"),_T("0127FA6EB0ADEF10211E9FB0E9A4CE57"),_T("01637285D6262ABE6DD31424675DCA08"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("116"),_T("015231DA2358880432B85B5B09B81C38"),_T("0165997FDB5C071D28926403F749AFA9"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("117"),_T("0122411D52D4ED1253B058F4DB022E90"),_T("017BD507D2EE0655298312CCDC880665"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("118"),_T("0102ABB0AE862BF7F819435579E6247D"),_T("01C447FB8247749E4E567A704E428D45"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("119"),_T("01126218AC9A43474C6A20E003B0C745"),_T("014453F2D9017D5D4027E745F2BC013B"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("120"),_T("01E1475EDCD07BEB173E37EA2B175775"),_T("01FF6858DD9272AFA62AE816476D3F42"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("121"),_T("015A290A921D1A61039ADE4601870B45"),_T("01BAB47CF076E57F011C308687C0201E"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("122"),_T("0117761DB6D57310D87DF66FA37FA55C"),_T("018A985588DFC6CF1B7041CF90C6A01F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("123"),_T("0126D303D0E3903B7ED22854AC5FCB5B"),_T("016AC4AFE871A1B87AF7A266958E4B7F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("124"),_T("015166A24C308C040FC15EEFBDADEF43"),_T("01D3EBF7841ED02AD1A7EF5D50DE2781"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("125"),_T("013432620EF3C94ABA4B8B43893CBFDA"),_T("016A83ADE0CD4955D9C5BB5A834D3350"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("126"),_T("01154A4B654FC14A1FB5EDFB6CF9A330"),_T("018153B33F1C1B5ACD8B558368063A47"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("127"),_T("017A3F21468542DFB663AC22203C535D"),_T("01C556D1672AEACA3D59BC16856EC458"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("128"),_T("01CA214289E25D814ACFE0605450D369"),_T("01EC39946C595C89370B197CF1AD9DC4"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("129"),_T("01B3BE8967B35123F5470C114ACC4D85"),_T("01F6D1933E1977C3AE2CAB28D26B6CA9"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("130"),_T("011603DB4A43142175F911A9B1499D15"),_T("011CAE4214885A1BCBD6DAAB17E21962"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("131"),_T("013C262FCCF1880A24A3363BAA52F0D7"),_T("01804C67D073E9FBE759D0F4F3BB4851"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("132"),_T("015C3D3593910C5D68881301400627D7"),_T("01A884BE8038BE0699E63FE0FEF708C3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("133"),_T("01C3FC4C442C82D1BF964721F2E83566"),_T("01F2A5444C2F00BC66A710CFCEFC63CC"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("134"),_T("01BD674544CEF9938C18F992D9593D60"),_T("01F44452EAED42EFDC058888F8655295"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("135"),_T("013231BCD4DB6238F254737F0694AAFB"),_T("0148B37E9F2C9FF9FEE1CFFDBFC5440E"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("136"),_T("017BA30AF567FA508880537B53AF1DC9"),_T("018C8428B7F6B8A7B458218052063827"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("137"),_T("01BFC4478AE7B73B41E50ECD28DBFA78"),_T("01EDE8F336941947589F52BA8F913588"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("138"),_T("0197AF7CBDDA618AD03F38469CE36C27"),_T("01C303C78B3C6EDB05B6BAB9D33DC066"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("139"),_T("01423D270D41FF070AB1A59D0D2DACA2"),_T("01A5635F552D35C292C9846F7E70FDDB"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("140"),_T("0105B2B68B41A49822BE48D950359C15"),_T("017E9E409FD0EBFA51AE02E48650D4B4"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("141"),_T("01694E63CF8AD00C095B3EAC43F48A54"),_T("01D656714D974C633FF925601A2AF00E"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("142"),_T("0101B13F55983BAB29E383AD562DFAC7"),_T("016C6AF5FC276A23D80328BDC9BED33F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("143"),_T("011200DAB55F8121374DB751C9E8F5B9"),_T("01F4EE9BA4BF7817C586B0D8DB0F738F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("144"),_T("01871DA90985CBE76C50D726831A91B1"),_T("01A689041103AB59CEA476222A0794D3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("145"),_T("01803640D2420EE067C0F563CBB95DE7"),_T("018353485340A2010A4A235B1BCAFA81"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("146"),_T("0163E75D86848F86284BF139FCA3549C"),_T("018E709178CFC5A916BC344AED26F220"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("147"),_T("014688C0BD278F52D4C50C521655F66E"),_T("01A63DB18F873AA2840962B31DA9C817"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("148"),_T("013CD318BFF36E64B4F278E711DEA604"),_T("0178483C1EE5DE57BF953F86759EAB3C"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("149"),_T("0155C0982CB5A63BFF9B5253574EB035"),_T("017771204B2B4085EE4A71FACEB2046F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("150"),_T("0130B52BECDCA022AC4351FE4488C78D"),_T("01F38689DFAE7F18B9D7A757C417F4A0"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("151"),_T("01339152D762290475AFE687085AF946"),_T("01BBFACDC2C7A3247BBA0275D5635997"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("152"),_T("010174B064BCE4CD8904BDE2323DB30B"),_T("01D21DA353D298FB3AD6A2293B6426B1"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("153"),_T("016A859C353655704E95D1423022EE6C"),_T("01D50D9CED27295D1F94C394791DD27E"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("154"),_T("012EAF2E5A37A39FCB90FE9B8E1B0125"),_T("01F995FE2845306D1F0CD1B2CC247389"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("155"),_T("016420AE56F486BA2525D85AADBB339B"),_T("0192A18C2F74AF061E7CB0662E81DF0C"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("156"),_T("0121D7F3B29A19C137ABF1FE953E93BC"),_T("01314DD06C5D624036E01B45E67A72FD"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("157"),_T("0180B0D0F6E0B42EB78DE66CB363B1F3"),_T("01E0F93EC976F33BA219E94567133B38"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("158"),_T("011EDE482D6C91D1A4D0EB1649192E0C"),_T("01A2317C79DFC4F5432A9AA284132E48"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("159"),_T("01201CA64783CE8188860A0ED0EE8730"),_T("019A99D60146E0563333B96672A27086"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("160"),_T("013D415F6D9A2E3632F2352A34460202"),_T("016A76DBFDED5D2370F7C9911987F883"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("161"),_T("0139CF17C9F433E3D69FDB6C5D0310DE"),_T("01A31F28A468D32AECF98CCA09DF5CEC"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("162"),_T("011C6E5426A01F87557A250C2AA29217"),_T("01FF5A009E8BC1DFCC3EF5C219A2580F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("163"),_T("0181CEEB6A4808DB5DF406CA356EA961"),_T("01E61B13DDB271A5FA8431CD7C3632D4"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("164"),_T("01584D00FFE9D5F4C0B18C1F1057AC2D"),_T("018D851B69B22F754C61D7A7D404804E"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("165"),_T("014FCBCD7DCC32E728AB11E41D340CF1"),_T("0197C7717AF680AEADE069E4CF5566F1"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("166"),_T("01D9EF9AA868719114E7ED681CE15A80"),_T("01DB08AFB949C6BF5038EACE89C16AF7"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("167"),_T("018E8E0FB96EDD8C810FAC4BCAF5A1E3"),_T("01D71CE75395343B02463C9015B0077A"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("168"),_T("01BB9CD692E53154B43C6E55FE0649E3"),_T("01F9292523447EF171ED57B21DF0651F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("169"),_T("01148E465BBA17AC2D3C2767495085EC"),_T("01CC996391449E53060289135E622C37"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("170"),_T("0118A98A7AC7645546854D5B2607BC18"),_T("012CF14DB7C0EA2649CE8BDB7748771D"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("171"),_T("0164BF7D624C6777E83DF8D8010ED1F9"),_T("01B3BA7DFA2A96138260DD56B020A299"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("172"),_T("015D5A7A503EF9A79E0B9DCFA4D9AFCC"),_T("01ACF9CB7740C2AED7B849D1DECFDE07"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("173"),_T("016C18E771F0FDF4509C2867B02497DC"),_T("01E395B45299AFD9C7AFCC8962DD186C"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("174"),_T("0110C90DC53738A78030D81B591AC85D"),_T("018B7DEACF116730086494CD41B1E76C"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("175"),_T("0140AA92AF90106991CEC0EF43EA9457"),_T("017816F27EC5ABF5CD34DA0349DF8A50"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("176"),_T("01542922E77EA9907DA7C63A53EC0C2E"),_T("016A09CF30769985052767C629566149"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("177"),_T("0161A5E2DCDB62920B9288658957C449"),_T("01AC8FD2461869A913BA2E4985388C42"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("178"),_T("017D9D0947EB2CDE8A79CD4C5D869F0A"),_T("01ADF6C704CD3999A14BAB1779AC5C60"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("179"),_T("010EE1BA682A0A601783CEB29267810B"),_T("0163A30EFC0120551D66A798698035A6"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("180"),_T("01592BDC96DF403C97961FE9DA3A2873"),_T("018F8F43094A2B3F41538DACAA06D0D3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("181"),_T("01B1C5AB82A4EF3ABC574D4A987DF7B6"),_T("01D5D6195B4B127BF216B37F6AE34346"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("182"),_T("012CB7FA2A05A9C81BFE5BD830CB8A86"),_T("018AE56FA30610ED2C3220D469C4AD5B"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("183"),_T("01AA46313DCA7147FB76F9C16DB95E53"),_T("01F925D9FF424F37F9DF4651AD5F49AD"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("184"),_T("014A437C6777FE25CCCE2E0839514344"),_T("0197A285BBA2E336F5400798A1EFDBCF"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("185"),_T("0139A1775B95631AED1643F9B9A10BDF"),_T("01A89B8115E4C07B1F2E1DCEA21660E6"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("186"),_T("011293704A25B4573D946F959C1D283F"),_T("019DE085FCB086DC1FCB3B64BE663827"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("187"),_T("013C181981A0D19412F53D2569584165"),_T("01D600AB45ECA09E45C6E4A1694C8234"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("188"),_T("0186832C45BEE501811E977BA184521E"),_T("01E0CA9FA53234ED9CB1B7EE41F97683"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("189"),_T("01583D62D92E147E1D3D96D8DA75BAE9"),_T("01CCA0E74AAE418E55199FD145DBDAD6"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("190"),_T("01B2E2402508AC74AD6F6EA806B0F602"),_T("01D69A0BBAB8B513E1DE2A46CA907F9C"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("191"),_T("01256DD2320743579D3BD609B41C037F"),_T("01C5BBFE5839CB149B1B081A21F9CBAE"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("192"),_T("017A13BED0629B650E766E8D9E902BE8"),_T("0194A980726F85C2B181025329A20120"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("193"),_T("01CE303D379D6D4EEAAC4F32AA5F9C8A"),_T("01E0BA091563681A70A97C05E08CA118"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("194"),_T("01966DA267048952B7F85C0660AEDAB7"),_T("01D83116882941AB191165216E83B03D"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("195"),_T("013CE8D7CB46B01AB54AD46A328AF3AA"),_T("01F6A1D4ED560049F4B94EF1FAB50A0F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("196"),_T("01766DFB4AB8AE4CE255F51D1C2312FE"),_T("0187FC645536F1FB632D8796CFE484FE"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("197"),_T("01AE734C85730B30D8A65855EADCBE46"),_T("01C34818A36E8B5A64CB40DBBCBD20C4"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("198"),_T("018D6DAF0BE5233A8244A19F82B5F783"),_T("01BC7B2D25E7FAAC23A9321CEA6608F7"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("199"),_T("011C08D93C5BFD6DA098F0E85C9B8C10"),_T("0179ABBF6FF7A03F9CC1A55B9BAFB8C1"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("200"),_T("01A23B72BEF75A4E84326F02773A7CD4"),_T("01F992EEBCBFBD7BA60314C1F508D728"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("201"),_T("0164FD8242063595E29DBE312830045C"),_T("016B7D40D8A542B883A5A780D2F57B07"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("202"),_T("016A90CDEBC44629F2D139F33D7A082B"),_T("019A1095D5923CE1794BF6EAD8A0AE86"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("203"),_T("0143659D8A7CAC20D791A6470D18BF27"),_T("0186DECD51204231FF26E916F8BC6F90"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("204"),_T("0183D0F6865F5A0C20413AA23E39E6AE"),_T("01878A9644BB3814E0E1BE55B726F810"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("205"),_T("01067CC09A86C82ED44C5296F627096D"),_T("013574316F410F500CE9DA3ED49B3CAF"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("206"),_T("0153F4AD836330A3FC327D63AF81E863"),_T("01967A578FEF8961D357B89CED883312"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("207"),_T("016368A72B2B4BE76F9FCCD24F3A3C4B"),_T("018673DABE870D0E382895336312C4F8"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("208"),_T("018DCFF341F4F16AC152899FFC9930A7"),_T("0194EFE42E510AF76A28FFFFB6A7109B"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("209"),_T("011D2D343B318B4B5EFBF3F5C4881374"),_T("0182376C5A57A22ED63A7BCC1DD15911"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("210"),_T("01C57A8AC130A22BD9E70B7280C3AF8B"),_T("01D412F55562351219D4B55EDA8D0183"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("211"),_T("011287B0EB965E0AB995996E463D8C21"),_T("013FC028BB33B3987DA4AFECE7BE836D"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("212"),_T("019AF0457038CA90921962EA4FC4B12E"),_T("01A382427977006432BFC0A0D6DA182A"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("213"),_T("0146CDA3DB8EC26BCE23148D2FADA063"),_T("01F30BEDB60E5F3669F59D7198D45EF9"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("214"),_T("010126E4E8112C268A97D40B8421A0C9"),_T("0144BF7E909DF76D25EF67B16728CA4C"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("215"),_T("01A497218747EFBF5FFCFF4C61845DA9"),_T("01F32A37604FDB29829BF69982A68AE2"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("216"),_T("013AE04D42C99D1D5008EE57142DBC9D"),_T("018631FAEAEA70CD642BEC283EE4F3EB"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("217"),_T("013A9C3C0ADA3BA6B2B4CB88B152E09E"),_T("016E7F3413FB9588D354D13AEB0A88AD"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("218"),_T("0107C3298B9AB5BA68FC43789937CA16"),_T("01595DD440ACA9FFBAE70759814218FE"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("219"),_T("01255F0C43AB1B5464BF2D833BF27787"),_T("01CE214CC2913402217CD79EF7584985"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("220"),_T("015CF4D420F0E3D87331EE66BB41BE9A"),_T("01798F13B32C295E3E39B49BE584AC9B"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("221"),_T("01661CB22D78899647C86A9D9F92CAD7"),_T("01F5EDAE84DC99823D86B5496ABC2A79"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("222"),_T("0154F14EB75877AFB568497E7FC7CCBB"),_T("01775B723C027C05DFD6DD71017D515D"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("223"),_T("01A64EA770E38F02927517A018E54FD2"),_T("01E35A7F2F1DF754D0CECA1ABAEADFA8"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("224"),_T("013B1972A84DA747D33289E5ACFBAE77"),_T("01F23FE5D6A15F805E18CF9CC2DDBF71"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("225"),_T("01A42CDA1EB0DB0234D37F0D06214861"),_T("01AAF044D3BC677F6804DCC38090AB74"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("226"),_T("0187F687E7CFC90BD8518C964C538F2D"),_T("01CD907285C824C02EB4FB7311A43889"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("227"),_T("015BA337FFF960BFCC41C15D995361C5"),_T("0182C745E667724C80A4080E3517307E"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("228"),_T("01A588522161B622C80027D364E2CE91"),_T("01C8E41883DC5F8DD639B824267F6991"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("229"),_T("010158703CBDC2502B5F7FFE72014C50"),_T("01FC0EBBCF963C663F27D830FAD042C3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("230"),_T("015E6B81C8409882B2B0D546DA93CB7E"),_T("018BCD69EEBE6987253212436A43A262"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("231"),_T("014685AD0F428DFE382F2DED801DD446"),_T("01B5F5CC8F2DF2C2356B0AB8506BA6FC"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("232"),_T("012EE742281152FB69DA4BCDB7E48228"),_T("0143EE9337F64E88CF82F85CEED491AC"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("233"),_T("01C037C9626C78E998AE4A0C077217B4"),_T("01FFFFFE13DC2E4FBA0E232166BA0A2B"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("234"),_T("0173E7F4C05E1BDE13591D1A70547F58"),_T("01B88AEF44B633912FF522A2283D92DF"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("235"),_T("01B61EED62EA03D8DDAA0BC17C02BE15"),_T("01EACC9E71FD3C7BD4B96A5C4BD54B46"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("236"),_T("012D45681EF3306674FCA37F12F89280"),_T("01E59B28E1D5C5FDF1FD1EA9DDFD7B3C"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("237"),_T("01EDD0CA4BA6DC4C0086DA4297C3D865"),_T("01F0EA54DC032CE660E74B8B5240F99F"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("238"),_T("0104D37DA3235B719B234B623476B037"),_T("01AE3AF247D1AD117B64AE6FCAFAD4B8"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("239"),_T("015C70BD35420A1F830D4D991B916AEC"),_T("01DBE0E8ED24D6CE2AC474056129AC53"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("240"),_T("010288A3B93D05F58058450F28B9B6F4"),_T("01AAD89E1E172FC5A7D0ED619A260BCB"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("241"),_T("01C5ADB0AE807AE5A5330F1B229B433D"),_T("01FE51092BF5C41E7BAE4B17CED51713"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("242"),_T("010A17DD2B09E7A3623A8EEF835719E0"),_T("0179D27DDEB67C90D4DA618597354EAE"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("243"),_T("01781D7E083EB7FBE29D1AF750DA5D49"),_T("017F6AA3C29782B775EDE527ABE44CE3"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("244"),_T("016E16E7BEFFAFB5B36269859A28A697"),_T("01F826EEA44BE8B3A36F0D87F2842411"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("245"),_T("0127825DA69B73164498FDFAD3FFA42B"),_T("0170AB98468291247AC14A209FC73661"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("246"),_T("019EB8A2E48C4E5B629E3E1DA7A9DF90"),_T("01E3299F5B80CC928C920D8D5A524D33"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("247"),_T("011A20E9C62F1E0CF16816969601A633"),_T("01C1D36F16C9F16B49417F0E94E74875"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("248"),_T("0179116263EC482BA2A2614BAC024ACA"),_T("018A306477F9B53A684F317173580B77"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("249"),_T("0103612119DE6616AB89AF4AD81AE337"),_T("016E47B08C6C290EE22B52F2B7154041"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("250-251"),_T("0196F2BCA047EAD712F1E724146172C2"),_T("0199D6A2E65FCBEB7FC729FFBD7733F1"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("252"),_T("01BB7F7FDBEFFD8B50C4581EE95632F8"),_T("01F4581774AF48A7CE129726B80159E9"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("253"),_T("016C9B02F44E7FD2F1FE9FBD8ACC158E"),_T("01C6BCF73B3325EAF95402536045B239"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("254"),_T("01010A5F7A0EE7B384B71F416DE97A7D"),_T("01318A9A5A7B2E880424831584BDD5E2"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("LEAD Technologies Inc"),_T(""),_T("255"),_T("01188DD39C08F3C6857DFBB1B7DEE0AA"),_T("019B1D02367E98B7B6C2C8C1878E8C86"),_T(""),_T(""),_T("LEAD Technologies Inc")}, -{ ENUM_EDITOR_SW, _T("Matlab"),_T(""),_T("75"),_T("019C6C4CB99521A5680C96B0EE999485"),_T("01C8ADEC252DAF2DD41A3F13A6B26952"),_T(""),_T("Matlab"),_T("Matlab")}, -{ ENUM_EDITOR_SW, _T("MS Office Pic Mgr"),_T(""),_T(""),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T(""),_T(""),_T("MS Office Pic Mgr")}, -{ ENUM_EDITOR_SW, _T("MS Paint"),_T(""),_T(""),_T("012D821C6AB210E2A753BE053B8F55D0"),_T("0182408A81A4ABF04D4A34A8A5E98C58"),_T(""),_T(""),_T("MS Paint")}, -{ ENUM_EDITOR_SW, _T("MS Visio"),_T(""),_T(""),_T("012D821C6AB210E2A753BE053B8F55D0"),_T("0182408A81A4ABF04D4A34A8A5E98C58"),_T(""),_T(""),_T("MS Visio")}, -{ ENUM_EDITOR_SW, _T("MS Windows Photo Gallery"),_T(""),_T(""),_T("01C6138A3E892EC7CD6F55F578FDD086"),_T("01F86317ECF8E38342C13A63423ADFDB"),_T(""),_T("Microsoft Windows Photo Gallery"),_T("MS Windows Photo Gallery")}, -{ ENUM_EDITOR_SW, _T("Nikon Scan"),_T(""),_T("Excellent Quality"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T(""),_T("Nikon Scan"),_T("Nikon Scan")}, -{ ENUM_EDITOR_SW, _T("Paint Shop Pro"),_T(""),_T(""),_T("0198C5EAC1FD06F70494FC588808EA60"),_T("01EE638764A3ACF4F505DF2864906AC9"),_T(""),_T("Paint Shop Pro"),_T("Paint Shop Pro")}, -{ ENUM_EDITOR_SW, _T("Paint.NET"),_T(""),_T("050"),_T("0133FC69E52E74319F110B4486B8B0D8"),_T("017FEB124293E03634B25E85B537A2E9"),_T(""),_T("Paint.NET"),_T("Paint.NET")}, -{ ENUM_EDITOR_SW, _T("Picasa"),_T(""),_T("065 (Minimum)"),_T("0139091A8EB09D2E5B08BF57DA89136A"),_T("01FD829AFC9398AA4692176577CC045B"),_T(""),_T("Picasa"),_T("Picasa")}, -{ ENUM_EDITOR_SW, _T("Picasa"),_T(""),_T("085 (Normal)"),_T("0155D875C95B74D0F3C5835A62516F48"),_T("01D38A25358EB7649A254E19F1D46600"),_T(""),_T("Picasa"),_T("Picasa")}, -{ ENUM_EDITOR_SW, _T("Picasa"),_T(""),_T("100 (Maximum)"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T(""),_T("Picasa"),_T("Picasa")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("01-02"),_T("014FC9D32AB50D2E78A55796DA2CBEC6"),_T("014FC9D32AB50D2E78A55796DA2CBEC6"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("03"),_T("013B7D3CA9CB31130CA7139D25B7A8A4"),_T("014969EC6B9209AB4F927921A5888DEC"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("04"),_T("0106F0377342CFA5A3143FF45CD28994"),_T("015A029AAD57B7CF8B62685C6013B390"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("05"),_T("013DFD2C7376334D7E79543CDAAC4910"),_T("0168601A9309B12FF6663D1F0136AFED"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("06"),_T("0175BBCB841A26513150597603D62BF6"),_T("01E523DD30A14718A8953D0C5612B3EB"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("07"),_T("01134024651373C4D6D52691F50D6586"),_T("01556DD156C6B8656EDE632E14B091E7"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("08"),_T("01031D5074818334ABA6C355F5560090"),_T("0134BF791F72302FF2B4E1AB17C648D0"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("09"),_T("012B194EE141D44DAB6B42D3CF93CAD1"),_T("01D95481ACA60A50D2B8C5085BC83312"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("10"),_T("01C79DA0631E8F88841CDA26F6094C3D"),_T("01DB3970B526B734EA8EE2C65A70AE0F"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("11"),_T("01CE5B6AC816554311EED0F18B9B7B44"),_T("01EC62868B595D0C25ED770649D1280C"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("12"),_T("015EA76216925F6290C9E5D53D3969FA"),_T("01D81968C245475537CA4224A630C63D"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("13"),_T("012E28D014C5944E3724F593D5124973"),_T("01678B2664F0FCA111021154313AAF00"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("14"),_T("01406236F6F26D47D8F8C9E90F56FF27"),_T("018353E30DB3225FAF549B62C74EA23E"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("15"),_T("0196D68851992632D8AFBC72A97C02CE"),_T("01A286D2DBF8E54AC7AF60EA475D8C18"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("16"),_T("014F8A218A85D2867A1915A25F21403C"),_T("018BAC2514EAA8FFA6EDDACF71A53463"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("17"),_T("018199F91BFAFFAE0512D079EE507FC9"),_T("01DA8188C92117746BB7C34FD21088EE"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("18"),_T("01AD8CC7B0BEA52AA46695E00836D283"),_T("01C30D636777D304332C9E7D4DA6774C"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("19"),_T("0176C54DD01B825DB07AC652FDB58481"),_T("018A25EDFEBEEC4C1F13F85B0AC1FA91"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("20"),_T("01481C9AD7F23611A304A703A06EE9BC"),_T("01FC2ECF39D66CBC7D8E03447C7084C5"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("21"),_T("010FF14E5BDE6B9935D34EF0059DEB80"),_T("013BBBB068DF184D7E914EC1D0672958"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("22"),_T("016943FBC2A3BDF1386CDF1466A64854"),_T("01D79F265CED6CFD247F77FCCA968B13"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("23"),_T("016AC4AAB8FB52EF9543CF9DF32C0B04"),_T("01AC672449D5493D950D03AE8BA9F139"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("24"),_T("01BE458C95B49B42A6D67B928462CD83"),_T("01EF33F114A7BE4AB5A1746B36EEF7AB"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("25"),_T("013C67C96F075EDC35E17465A7C5CD78"),_T("01FA8C758837FA7911AD460B42B2384C"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("26"),_T("014802F109EFC228031D3217A9E114AD"),_T("01C527DE13328C300574C033048946BD"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("27"),_T("0146FBA7A23D57869F711A19F742AFD5"),_T("018AC27D2F6543212645814BA65E3C46"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("28"),_T("016BF7C2A3A5AFF828BBE8F19656DB36"),_T("01757BFFF1D76B9945B8C69814064267"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("29"),_T("0177F0948D0988BDD99B6D282498F7AC"),_T("01A3C305AE69B5EDB57D0A3D10584170"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("30"),_T("015C0F02DB07641172802B72A8A8ADE5"),_T("0166BECC9447792D7865590A4C22013C"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("31"),_T("016EBF81B56DFED63B29607AD297F144"),_T("01C1479CA8401A0BC01F0FF8982A5F0E"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("32"),_T("010068DC8ED499DA2B7E7FC64AE69DE6"),_T("016E4E591440BD5EC00EA595295E8C09"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("33"),_T("017476AB316DA91A21832475A2201E6E"),_T("01D20D87FB61F87434F81EAAD953E615"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("34"),_T("01653199EACFE67EC85007845F9C594A"),_T("01EF4DF707B0E636502496C3742DA65F"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("35"),_T("015A74BACF3E03F8CFC7A5A8B6210945"),_T("01A1995ABC25A1DB4A7E0DD89ACA09CA"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("36"),_T("017B2235BAD77C7750DAFB57D6BB8B1E"),_T("01D954326D446FC53B6CA18688ECBC45"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("37"),_T("0128F93C4708384183AFC1455E285628"),_T("0129DE2A443CF44E76BCDDCE66FD45F1"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("38"),_T("01177B26BF1D2E7CEF9DC415E5CFEF2F"),_T("013CBF347EEF13561018AD28B7FD11CF"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("39"),_T("016CCC82267AF456EEEEC62A048E61E9"),_T("018FA3C125BF76156C39EF16D5FA403D"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("40"),_T("017791019EA30BF0AF439F2E01DBF795"),_T("0198AECAF49D80A7704AE1E61B4285E1"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("41"),_T("0128EB73EA061E4143110E0DDB2D5086"),_T("018E1C45D953E59A7F3A2173134A831B"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("42"),_T("0112464E22EA96E1FA24B4108D94490A"),_T("01A657E6F9DD5DC6EC526EACAD4CF981"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("43"),_T("0103E99FFBF410A1F5F80144C1AC8976"),_T("01EDA600FE79E9EE3F1803B85DFC709D"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("44"),_T("0104555079C4CF6202C7D6FEC9FDCCCD"),_T("01BA2F06B3F98DA4CA9FCE843A463ACF"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("45"),_T("0128BC847341313AD2A08BD6666476AE"),_T("015229DAB8A23610BA0A6D2C7C4D8D3A"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("46"),_T("01A78B98E2DE6C68D64137A136C0E9FF"),_T("01DE6B69C756C0EED2FD0BC17F6F73F2"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("47"),_T("01AE68DDDCA0196DCE436DEB1B9F9F55"),_T("01FD082F93AFC83E35DD27E55DC5DEB8"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("48"),_T("018030F65F41018A1EF44D2B74D1BB46"),_T("01B4BFFD8A1ACDE587DC39E5D8D7BA72"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("49"),_T("0101F557FB8C1C6C7123D97611884BC0"),_T("016BD88BC1A3A973FEC2E9130CED025E"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("50"),_T("018F43D8975ECD7B1A5BCAE44908FC68"),_T("01E8F427C47F9BAAF87A0DC3F1417759"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("51"),_T("0163ABC310674EBF8008372F0519C06E"),_T("019F6C9A1AFAECF5B25451304135A7D6"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("52"),_T("016F22947C74E50976B8F269F1729522"),_T("01A7A98CF7792A01D4A9E0F2D7534D97"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("53"),_T("014A9CB34479FB4A6CB53D671AF8F591"),_T("01ECEA3248E5614D47154A5F7811C869"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("54"),_T("018652B3DAD29F910C60328D324DA00E"),_T("01D00CE104DE38D0C2D2E11FA40D1B65"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("55"),_T("01065DAFCEA1DA071991649F1395E4AE"),_T("01744013B24B70E6CD252884F1683D7D"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("56"),_T("0139F277F697F731DD23793026C6AFF7"),_T("01D96E2E7C00D75C074CCD1049CA8E0F"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("57"),_T("012A186EBDF5C89419616B0D2EAAD5F3"),_T("01844D8B71E242CA8C88D6B30EF493C8"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("58"),_T("012E25DEC73667282FE995A2480F3898"),_T("01A2370EF178FFDFCBB099B836A2A9C6"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("59"),_T("01331C3A2F6F1EE69C2680DE11339FFB"),_T("01A1198E53AC4E466134CCE3BB932EA7"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("60"),_T("01C4C8F52D63C2600019D3389DB29248"),_T("01F1AC2B0A274B9BA11F22DEF5FD08F4"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("61"),_T("011136E78D87BB3CBB07B86C5389CC86"),_T("01B23F2BA3D9EEE6AC1E1C14A11AE93F"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("62"),_T("012DC58305C26A0605CE4624F5EC79A7"),_T("01B5C303E87AA0D13CC289B9E9F50779"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("63"),_T("0126FE4F83EC4002AB986D8FF233C3A6"),_T("0170FB005850265D208B40F54248E3A9"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("64"),_T("01672E8C86836203704D51FFDDF8D229"),_T("017509677D6681D926CD6FC7E7CEF27C"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("65"),_T("011839BC9F708E7C1780C99F7DA52AA6"),_T("016C1CFC7BB403C79DF0E3C14C348609"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("66"),_T("0152F13FCD2990EF7DC3C457AE14F6CD"),_T("0167EAFD58DB869351761D7AF42D3376"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("67"),_T("0100FC284EC4398EE30E1FA6C893B717"),_T("0154EE10CFE4FEB99F262AD41571CA07"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("68"),_T("0165D09DE19E8DE361ACB1D46D398A34"),_T("01811AC4E5252B14A65E5E221EC9267C"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("69"),_T("016EDFB389F79A837E2EB91DD26CECEB"),_T("01761256820BF8C1F26BD9AFEF56DE4E"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("70"),_T("018A66F4CAB0C46AC4B9AA6DBE4C9208"),_T("01A88A93A3529C7ECAA3176280FEE0D2"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("The JPEG Wizard2"),_T(""),_T("71"),_T("0103AEB2D5B835F3E556862994F777F3"),_T("01F59933CC03EBFE4CCAF43C60980CBE"),_T(""),_T(""),_T("The JPEG Wizard2")}, -{ ENUM_EDITOR_SW, _T("ZoomBrowser EX"),_T(""),_T("high"),_T("013BA18D5561625796E986FDBC09F846"),_T("01AC57E12793DFA7C46C704625C5AF0F"),_T(""),_T(""),_T("ZoomBrowser EX")}, -{ ENUM_EDITOR_SW, _T("ZoomBrowser EX"),_T(""),_T("highest"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T(""),_T(""),_T("ZoomBrowser EX")}, -{ ENUM_EDITOR_SW, _T("ZoomBrowser EX"),_T(""),_T("low"),_T("012D821C6AB210E2A753BE053B8F55D0"),_T("0182408A81A4ABF04D4A34A8A5E98C58"),_T(""),_T(""),_T("ZoomBrowser EX")}, -{ ENUM_EDITOR_SW, _T("ZoomBrowser EX"),_T(""),_T("medium"),_T("0155D875C95B74D0F3C5835A62516F48"),_T("01D38A25358EB7649A254E19F1D46600"),_T(""),_T(""),_T("ZoomBrowser EX")}, +{ ENUM_EDITOR_SW, "ACDSee","","","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","000-001","0138D27C7EEF02B3AB3313CD713E8134","01D70ED96E34F308DB1A0848A943DDC4","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","002","011386C6B52F40BADA59DA38760E742F","0139107E395BC07B318B5EC0E9F6A283","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","003","0159463DC4E43388BCC153A437842F15","017A8FCB62FED5062A6DB85334F299DF","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","004","01130984F055CB0734DFE9120AE608A9","01A5CE7EC04CE304D74A544A905A8125","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","005-600","012CCAA4D0460DAD73BE0DECDBA04E21","0136AB2C178AF7EC6F22CE56DCF2F0AB","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","007","019833C578EB378FFBFACA37C5E3F219","01F95C855A1F379C3CC789A80D610101","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","008","01303D41327C5F81D755996EA1C8F1DC","0158FB8C5B854AE80A56BD090B82AAAA","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","009","017AAEFBFFFEC743BE469EC9596717F1","01A488D7614F4AC0E683C477AD5DCB0D","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","010-011","0150F2E76158ACE070DADA0C1B2EF396","01FABEDD10226CF93CB1E7390586140C","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","012","0105694D3A60EF8B068790263E3C1F64","011A74C0287957F725CC611660CDFF39","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","013","01703B12AB08246102043E762591206E","01DFA2CCC4055F0DB26870FEAABC5C09","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","014","011B207D670A565F68E79A7BE837635D","0138F3064037793EA8824A88441C3379","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","015-016","0147438D96A1D4C93DAE41F36DF4B9C4","01C19077E605B2CAE33BCEFFAC7AC110","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","017","016C045902D3F378009ECC6AA271124A","01D4890A48F5290F27CFDB5BED360D78","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","018","014BFFD73E371DE01C8CC4B30F2FF7B5","019D01D87616A4737618729D6DFC552E","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","019","0189543DDE1BE069368F49B421EFB312","01B628D80BF1F36B67F3643C0B43B4E1","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","020-021","017589061A7DA6B30DF34A514AF87692","01BFFB5FB1318ECC4541CCE316813CFD","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","022","013E7D04521AC131191558F1EBFC1422","0157A84F104FDBAB29766F29B675609D","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","023","01443D23B61DFE645C516FA7D26ED0E0","01F78F60C79374F89F8BC8EB5AF95047","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","024","01CADEEA6D4C87A401681BE2BF6189FE","01F59FC240430708D00AE746922891E0","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","025-026","017539FD56DF939BCE98C6579237C990","019A22644832C0A7E445677EBCAC1281","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","027","01204B752AAEBE51E57D06CB3FDCB48B","0181DC7BD18DD9FDE59E76F26E5541F2","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","028","01788CB9C83CF50B847C8A7760659544","017E9DCD06418EBF8D8CE2FEA4D19C32","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","029","013C5B4643DD6ADF550B23C67A4DFB25","018288F50215A7693617F920D19AF81F","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","030-031","011214AF9B0A7890D8DC588CC88A5FEB","01BF7D3BEAAC4CD8821795FADAA05AB9","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","032","010455DF473F62044D313A95F6B8C203","0117B6A72284D6C5F2F5D52D583C9A9C","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","033","0107E24545E03C45A2C8806D4D11E64E","01CEC660B66A2A9A8F27CE73E2F7FD7F","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","034","015239267819AD908CBF72984A9EE8AD","015819A335BC138743DB48271ED66D38","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","035-036","010C69E37CDA707F8DB41957E1BE8721","013EE695988AE5866D3BC80C01EDF1AD","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","037","010F99140A5A95CC42052808231CAF3D","01DD988FBC2A1D333FEBF0BB3B46C680","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","038","010D2888FB173C6821C5958697347F8F","01E3534FF692FAE47CB617751CEDEAFE","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","039","01929371778243D865240876945323C9","01F4AE9E56FD1F2D7895EF779F7521A1","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","040-041","0190F119A0B474CB73448F1895BFBE31","01F25CBB83BCD0E1E894F20647D07476","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","042","01973F7E8EFBBF63B293A4A7D0951902","01AFAECC1EC469727C0D3A0F618718A7","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","043","014EDA494C563A45977F05858B440735","01ADAD0EA6FAC8EC39E6BB9F80A2B5FC","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","044","01212BB4A3C5DB6702F929C338CC483A","01DA92F4AB571727EE61689446AB8ECE","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","045-046","010CC15B4643F88FC4A52E0A85D791F7","0187A1A2912E4742B24CC3B3AD0A1465","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","047","01A5EE2681EE6E4FEFA887661A193308","01E27A642E2D09EFF8B133F03B603282","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","048","01010BA0CB90E6E8B55F0ACAA8CB1D21","01FD78538EF8960FF993257E5050AE48","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","049","0114717D20FD02CF5321B7A85D8440CC","0145BF8B1C7367D83231FC6721828A9B","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","050-051","0134368B6244F8CE214E1D6FB34735A3","01F6CBD459813DD2CA23C36B6ACB720D","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","052","012CB626F43DA8BF2607C70F9B7D0977","01EA643AE20A86AA7DD4DF1DDCD76718","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","053","013A5F729164EFFCF0EB088CD45D926D","01E3B128CDFFB87298D438EE74DDA17B","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","054","013E58AF3BB40DD88C5E49C7F9CAB7B0","01FF0D5D047A4AD1FDE3A2AEBDB7C15B","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","055-056","013BE45647CC6624E7EF97898D19F980","0196B6D81E1EC891B78A6FC41E501EE6","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","057","01D0E43E7DEF23651B8F486C4563E9BE","01E0FEAB3A81C6D7345A32C58AB7D51B","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","058","0188F1BEBBC334B3B3A5081174406414","01F4B2D39E4017CF1952BDF84A27956F","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","059","01BA98C687122EA41579AF0D55D7D9F1","01DBB3556C945DDEA930FEE96C922B32","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","060-061","010493046013812E6A60F1C947BCF98E","014FDEE94CD6BB3894EB72C2FD3435EC","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","062","0182A8273EA432A275A98785F1155CF9","018B736BBB7A6A9B377113556592970E","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","063","019322C0F935CB3E8BF358BE02009F10","01D7C033447017E64166566306B613BD","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","064","0168A35C180D94AFCF3908195B2EF41E","01B53A0C930F891E5584A9837F4D20C7","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","065-066","019523E1FC78374CA437AC1B93E6C27D","01EC82A09F1E8B8BDA6C9AC3412D4DD4","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","067","0157B8F21222421A6F55931F84FBB4C1","01E0433F7723F6AF60219478207469FA","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","068","0106A1E243ED8C5EECD9FFA83BD9D909","0135E338E512D2981F53A6F796BBE716","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","069","015DFAB1D0C62A768D000FF66F670AA7","0173A34A3257A4FDDF4CCCF7FCB09B6D","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","070-071","0124237EA3BAF7E687617C56C9FEF44F","01BE27B1A4F277018ECF621F9EE4357B","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","072","01381A44131973EA2D012A7F90BF1B65","01AF00436DA7962818EF111E9602E267","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","073","0180B24C0D600C69D5EE50E5E7D9FF05","01BE134082E3654CBC17B64F4CA74D81","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","074","0113C0115C6CB65A9D176FF7F12DB8F4","01D879A5B03C9C261E0B13051091F939","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","075-076","0119470A4796C6D8835FEF17B32D6ACD","01549824A2982D54A86FBF6FCB58EBF3","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","077","018417A6CAFD7B99E68D62AE1ED533FB","01A75327FAD0DAD29E63A3A036C9C747","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","078","015D89F31A0A1F179BB64CED49905491","01FAC3701288FA83A4C1789873781568","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","079","0103354594ADA873431D96F400633A46","01373828E35FA443AB1D6D36D9FF0BD8","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","080-081","01E97EB12F8E60E014045751764986DB","01EEB2D93138615B3BA17C3FBF4F1ED8","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","082","011C34BE0A49E7129E2106129B25F06C","01A7C687C179664D7E5162D5675C9A89","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","083","012FC28E2C2D7D8176873702AEFB212D","01DDDE2C5DF0F5AC0F1161042D26656D","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","084","0166C9CC3967807247B93C0D2A168BE9","01A71FC79AF7E6117788FDAD38A9AD08","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","085-086","0154DFF319B59E71D47D1ED5C4FBF4E6","01AAB0140714ACCCCA606490053A1605","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","087","014822F5A31DCCE335A3DAE44D884780","01AA752557C5F34B1E2A3CF2E95AF769","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","088","018FCD649AAEFF642CBF273A36A60F6F","01EE90F9E15CEC725BC6E0A4B37F0207","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","089","0133A0EF20C997C87B68A9DFAB282361","015A336EE0553841153E22FBAB2CD372","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","090-091","0125AF4DAC2A62E600F6D03E05B7CF91","01F33F7F8758DADA8F99200CA44FD75B","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","092","0188801020BE0484F499413EA7ABB724","01C5315718D1D19AD0CA15A2F68DF5EC","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","093","01CA6A328C0296B896419261BAD2C8F2","01EB561F2389361E8994280294CD5423","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","094","01EA97D21A38A7C290E6C7117A14A83B","01F8845FE0E2B565A12A92AD8D0F29CC","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","095-096","0112FFC96229344A2CA6DA90B2E81A6C","019667373D982CBA9786618B7B663240","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","097","0129A0C3AD12541D54E6703AD419C527","0134C26D9B1EDEC747FA07E745F6B46E","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","098","017A81B04AA9ED5DBFA356169028C91F","01FD06EF44E5CB187E7A4A87CC2D9D66","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","099","0100B8C4E482C33F2A505D7261E2CC99","011C7429AB80690F18978FD375BD831A","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "ACDSee","","100","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","","ACD Systems","ACDSee"}, +{ ENUM_EDITOR_SW, "Adobe DNG Converter","","","01C2DDA29A1B5DCCD5E217CF9C558A62","01C2DDA29A1B5DCCD5E217CF9C558A62","","Adobe DNG","Adobe DNG Converter"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 00","012325931C8FA8522A0DC6856C8FB483","012325931C8FA8522A0DC6856C8FB483","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 01","010C5D6B4748A678290EC5AE783A8A68","010C5D6B4748A678290EC5AE783A8A68","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 02","01FF0B6A3E240ECF49A8B06AA2743D25","01FF0B6A3E240ECF49A8B06AA2743D25","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 03","0107D8E0D4EE2910BEB0A984F3D17E30","0107D8E0D4EE2910BEB0A984F3D17E30","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 04","01FA347CB7C707FD008CDAD7367966C6","01FA347CB7C707FD008CDAD7367966C6","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 05","01B7D42A6678B6F1F20EB05FFC2A8EB9","01B7D42A6678B6F1F20EB05FFC2A8EB9","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 05","01C2DDA29A1B5DCCD5E217CF9C558A62","01C2DDA29A1B5DCCD5E217CF9C558A62","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 06","01C695AC8819C200F1D13C16468312F5","01C695AC8819C200F1D13C16468312F5","","","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 06","01A90005BBDC3F23A80123EF0B4E4A28","01A90005BBDC3F23A80123EF0B4E4A28","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 07","014219E79BBC5C20BABF374762AAA745","014219E79BBC5C20BABF374762AAA745","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 08","01180AF3DE63318828A86409EF4013DD","01180AF3DE63318828A86409EF4013DD","","","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 08","01A20F69263117021CD16AEF44D6E650","01A20F69263117021CD16AEF44D6E650","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 09","0108A9C11C74DD59416AC689A4C00A55","0108A9C11C74DD59416AC689A4C00A55","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 09","0108A0C92E083893457EBEE6BC99F12C","0108A0C92E083893457EBEE6BC99F12C","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 10","0166B0BC0B82C8233430BF67FA31C829","0166B0BC0B82C8233430BF67FA31C829","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 10 grayscale","01398BCF6C3CD3F191AC7651DE1572A1","01398BCF6C3CD3F191AC7651DE1572A1","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 11","014C6C24A9EE0C6BDCC1598CEECCE808","014C6C24A9EE0C6BDCC1598CEECCE808","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 12","01C1158E443D1C90F302FF6BE49DDD87","01C1158E443D1C90F302FF6BE49DDD87","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save As 12","01DADDC4908E9BA57CC067EEAD54E67D","01DADDC4908E9BA57CC067EEAD54E67D","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 000","0130B2A516BC06C5D54B8D26507991E2","0130B2A516BC06C5D54B8D26507991E2","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 001","0119A7B4F14DEB5431CBFC2EA7D3EDDD","0119A7B4F14DEB5431CBFC2EA7D3EDDD","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 002","0103D2DC208BB2DA8027302DF5B27C1A","0103D2DC208BB2DA8027302DF5B27C1A","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 003","01BBFF6CB5ABCB09C381E6EB26F8C249","01BBFF6CB5ABCB09C381E6EB26F8C249","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 004","018DC509622FE322961BBE39FD51C38B","018DC509622FE322961BBE39FD51C38B","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 005","016FF5235A28B97875366ECA87B244CE","016FF5235A28B97875366ECA87B244CE","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 006","01F898E2D1E6AE15A446A9032C87121F","01F898E2D1E6AE15A446A9032C87121F","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 007","01EC4E95D6F4850EE65667888E006EE4","01EC4E95D6F4850EE65667888E006EE4","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 008","01A8073AA8F327DC2EE84DF61F069132","01A8073AA8F327DC2EE84DF61F069132","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 009","01E371BB7D76C099C71CB29CFDD825CA","01E371BB7D76C099C71CB29CFDD825CA","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 010","01E36CB9967B0DC1C592A39666BF877E","01E36CB9967B0DC1C592A39666BF877E","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 011","012629A5C57929287862ADA25BE00E70","012629A5C57929287862ADA25BE00E70","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 012","01A600EAD4B56FC377169141936A9012","01A600EAD4B56FC377169141936A9012","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 013","017C5C5E45660BA6CBCB3227428E6F59","017C5C5E45660BA6CBCB3227428E6F59","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 014","016CFC2E78B9BEF288E515994861ED2A","016CFC2E78B9BEF288E515994861ED2A","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 015","01BB9DB9D84C1FF90F10393E786EFA37","01BB9DB9D84C1FF90F10393E786EFA37","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 016","01FC38C12A3488DA75DB0206D349C35A","01FC38C12A3488DA75DB0206D349C35A","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 017","01DD25CDB86D38D4032D6EE9E877B827","01DD25CDB86D38D4032D6EE9E877B827","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 018","01A8ACB503430091613C58F4448510BD","01A8ACB503430091613C58F4448510BD","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 019","01621F1AC8A1B3152136EE2348440AEE","01621F1AC8A1B3152136EE2348440AEE","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 020","01753BA0EF85AD1B1C66F2724B9879EA","01753BA0EF85AD1B1C66F2724B9879EA","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 020","016191A38B30FA96ED932E8F03ABD75C","016191A38B30FA96ED932E8F03ABD75C","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 022","01BAEFC08D867839BB67FAA24A7004D0","01BAEFC08D867839BB67FAA24A7004D0","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 023","0109594B7BD71FF6EB4CBA341F4528EB","0109594B7BD71FF6EB4CBA341F4528EB","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 024","01C95456509D376179DBC2536A11AB80","01C95456509D376179DBC2536A11AB80","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 026","0124BB387BF72FB204C341839BD9CCB5","0124BB387BF72FB204C341839BD9CCB5","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 027","012044A3BA7CE9E4F17D98D49684AFEA","012044A3BA7CE9E4F17D98D49684AFEA","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 028","01107F5F085067D02D0ABE0F1F84012E","01107F5F085067D02D0ABE0F1F84012E","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 030","01F73A1839315AEFC5DB2DF9EE8D0977","01F73A1839315AEFC5DB2DF9EE8D0977","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 031","0184411BB50011A44DCFE3D51D1A17AF","0184411BB50011A44DCFE3D51D1A17AF","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 033","015E5E79CEE9B0FE744F68E5F6F8BFDA","015E5E79CEE9B0FE744F68E5F6F8BFDA","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 035","010C825A320E0BD3B93090391B319625","010C825A320E0BD3B93090391B319625","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 036","01382BDFE1AED73EE5F30BF0D2044852","01382BDFE1AED73EE5F30BF0D2044852","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 038","015582D4CEA4ECEC52CE6EE9A1222C95","015582D4CEA4ECEC52CE6EE9A1222C95","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 040","012BD5B2A563F55EAAE0128203CC68F6","012BD5B2A563F55EAAE0128203CC68F6","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 041","019849132013D5323EF4E2B2702C9737","019849132013D5323EF4E2B2702C9737","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 043","01DDC09F3332E25EA20962B3FEF3BF23","01DDC09F3332E25EA20962B3FEF3BF23","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 044","01651D50C387514D0E61092260CB0258","01651D50C387514D0E61092260CB0258","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 046","0101E499902CA45920E16A202657C0E2","0101E499902CA45920E16A202657C0E2","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 048","01024F682A8AFB5D96B1B7A6339B7D45","01024F682A8AFB5D96B1B7A6339B7D45","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 049","014861235F177CE4A79C1A0C43816AF5","014861235F177CE4A79C1A0C43816AF5","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 050","011E122B2E1C9BB19DCC0C0BC8E74E25","011E122B2E1C9BB19DCC0C0BC8E74E25","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 052","01B561565D8F26E36922E8AA5FC12D45","01B561565D8F26E36922E8AA5FC12D45","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 053","01431604AA6CF86A5300CE0553C058B8","01431604AA6CF86A5300CE0553C058B8","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 054","011B9E3A3334C136B755003D2CAF305C","011B9E3A3334C136B755003D2CAF305C","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 056","011226BD3AB7415091D91106E6512A0A","011226BD3AB7415091D91106E6512A0A","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 057","01301727419256BBE49DEA4A0532ABF4","01301727419256BBE49DEA4A0532ABF4","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 059","01296F65B9EFEB0E469475600B17D622","01296F65B9EFEB0E469475600B17D622","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 060","01C26040DB5181BA3B5CD7A813FAD209","01C26040DB5181BA3B5CD7A813FAD209","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 061","019CD397A6F3412E605D89ACE6D5E1E7","019CD397A6F3412E605D89ACE6D5E1E7","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 062","01203021460C376D8D31D57C3F4BDD55","01203021460C376D8D31D57C3F4BDD55","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 063","01438E0E3B5EE9CC5380F611E5168979","01438E0E3B5EE9CC5380F611E5168979","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 064","0142F9A14A2DB18F9A8E42521497910D","0142F9A14A2DB18F9A8E42521497910D","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 065","01803D95BA4C7F1CDA486B171BB30DBA","01803D95BA4C7F1CDA486B171BB30DBA","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 065","01EDA06D0F21C77828F6D5BF5BB25EB8","01EDA06D0F21C77828F6D5BF5BB25EB8","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 066","0139B00110F2F44D5E6F220C1CEACC39","0139B00110F2F44D5E6F220C1CEACC39","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 067","0182FE1F69533D6A2C675D7985752298","0182FE1F69533D6A2C675D7985752298","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 068","014A714C9F3FCF306F101BB7109B7FC7","014A714C9F3FCF306F101BB7109B7FC7","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 069","01C553050D6EBAC845BEC1A2B2ED35A8","01C553050D6EBAC845BEC1A2B2ED35A8","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 070","019CAD91870AF68B20FEF745FB5B191C","019CAD91870AF68B20FEF745FB5B191C","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 071","0170812268185A8C590F16B3DBAB22BC","0170812268185A8C590F16B3DBAB22BC","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 072","016743557ABCB147A79BFA185DA3EA15","016743557ABCB147A79BFA185DA3EA15","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 074","017DCB1A1B1D8B591A3B04771041A382","017DCB1A1B1D8B591A3B04771041A382","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 075","013E5A347BEB5C2FD641B1432B342192","013E5A347BEB5C2FD641B1432B342192","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 076","01DA170CA3AA855A5CB8D95C5A4B8E38","01DA170CA3AA855A5CB8D95C5A4B8E38","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 077","010DCEC5469DFE9A25FD53D3D268A638","010DCEC5469DFE9A25FD53D3D268A638","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 078","01025266C31FCCE9E081B1E73F65C152","01025266C31FCCE9E081B1E73F65C152","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 079","012BCCCA56539844F0D270A0A6CCAF85","012BCCCA56539844F0D270A0A6CCAF85","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 080","014FC9D32AB50D2E78A55796DA2CBEC6","014FC9D32AB50D2E78A55796DA2CBEC6","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 081","012B9DCBF402DF17158CBF6E64206F32","012B9DCBF402DF17158CBF6E64206F32","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 082","0130B6BD32634AEFB97B70F20976FC86","0130B6BD32634AEFB97B70F20976FC86","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 083","0189D2AED788E6E598C992F4260F351A","0189D2AED788E6E598C992F4260F351A","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 084","01BBEA4DA57CB2723835E42CC4E0BCAC","01BBEA4DA57CB2723835E42CC4E0BCAC","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 086","01A001542F2B6107CEA432CE45AF8100","01A001542F2B6107CEA432CE45AF8100","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 087","0128FDDB85CB7E37EEC547C9FBD4E8CF","0128FDDB85CB7E37EEC547C9FBD4E8CF","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 088","01943E417C105E1AD39161CA8C5EE06E","01943E417C105E1AD39161CA8C5EE06E","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 089","017981A780D2FB52E811A9DFB5E211DB","017981A780D2FB52E811A9DFB5E211DB","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 090","01D3C14A2EE08C94A55B15E2ADB46AE4","01D3C14A2EE08C94A55B15E2ADB46AE4","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 091","0132C1F3B949A09A0C059E9CF70DBADF","0132C1F3B949A09A0C059E9CF70DBADF","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 092","01495A5CA34A31036C80CE720821A2AE","01495A5CA34A31036C80CE720821A2AE","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 094","011366606521191E3BF568FFE4F0ED0C","011366606521191E3BF568FFE4F0ED0C","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 095","010BCBF1E31BE554B4429AF04CA58C0E","010BCBF1E31BE554B4429AF04CA58C0E","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 096","0192B42FED2A30C8D0E60CDC1200ADF4","0192B42FED2A30C8D0E60CDC1200ADF4","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 097","014007E37B551E53208F1585B40B99E0","014007E37B551E53208F1585B40B99E0","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 098","0126C30B910B29E7FF76843991A77790","0126C30B910B29E7FF76843991A77790","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 099","0144B08D172AE0B1285A07DECA206F71","0144B08D172AE0B1285A07DECA206F71","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop","","Save For Web 100","01E76B1145D4662F80BA198358A896A4","01E76B1145D4662F80BA198358A896A4","","Adobe Photoshop","Adobe Photoshop"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 021","01A9B3D4EF8B5D8C732F94BD7AF4ECA6","01A9B3D4EF8B5D8C732F94BD7AF4ECA6","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 025","019389FA50B73A7B9D6D0094FED486CC","019389FA50B73A7B9D6D0094FED486CC","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 029","012D9007B37C05C003535E8D4B15EDD9","012D9007B37C05C003535E8D4B15EDD9","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 032","01A8466B2DB77E8F85B7364B729FADF0","01A8466B2DB77E8F85B7364B729FADF0","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 034","01FC7D123C99FF761F2865AF43F03A4B","01FC7D123C99FF761F2865AF43F03A4B","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 037","014B8AB1944327D4DD81AD3F69001F86","014B8AB1944327D4DD81AD3F69001F86","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 039","0175F8DAB418C9B17A5FB722EB309BA6","0175F8DAB418C9B17A5FB722EB309BA6","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 042","01791EA97528DA2BD02082933CEDD4F2","01791EA97528DA2BD02082933CEDD4F2","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 045","0153DE55B52852BBB966CE1FF54FAF81","0153DE55B52852BBB966CE1FF54FAF81","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 047","01A13C373289893FD824792E79CD8115","01A13C373289893FD824792E79CD8115","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 055","010CCF22A3D98B7E94C08FB611403AE1","010CCF22A3D98B7E94C08FB611403AE1","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 058","019F3067B720B4F8428DEFC96661167C","019F3067B720B4F8428DEFC96661167C","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 073","01347EEB18BCBCBA043C274F38C6554B","01347EEB18BCBCBA043C274F38C6554B","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 085","01F43B7B625F02D2AAD575F9A61842FC","01F43B7B625F02D2AAD575F9A61842FC","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Mac","","Save For Web 093","01A8A4A60156C103EC5C645224C142EF","01A8A4A60156C103EC5C645224C142EF","","Adobe Photoshop","Adobe Photoshop -Mac"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 021","0175AFC5ABBC32B32E4D2F4CDAC93F69","0175AFC5ABBC32B32E4D2F4CDAC93F69","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 025","019CC391D4B06A06E29474EA82801C4A","019CC391D4B06A06E29474EA82801C4A","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 029","01177339640EEDC5DC811AF1B7744459","01177339640EEDC5DC811AF1B7744459","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 032","01F659D3E69B6A840FA8DAC5FC8275C0","01F659D3E69B6A840FA8DAC5FC8275C0","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 034","013DD4ED1AA14061D16D1DDDAF48E6C2","013DD4ED1AA14061D16D1DDDAF48E6C2","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 037","017C2DB1BAB171B59D51799C4FCF0E8F","017C2DB1BAB171B59D51799C4FCF0E8F","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 039","011AAAD2F0102BC6AC01D65C7BBC0334","011AAAD2F0102BC6AC01D65C7BBC0334","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 042","0103D86E0E6E0CC85740ACD6CA691A6A","0103D86E0E6E0CC85740ACD6CA691A6A","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 045","01653BBDF05CD614839A275CE9B6912E","01653BBDF05CD614839A275CE9B6912E","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 047","010EF9F94D9E759DA75E1C3A969BEC70","010EF9F94D9E759DA75E1C3A969BEC70","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 051","01D2AB7D4DF7A989D35E7A065E3779BB","01D2AB7D4DF7A989D35E7A065E3779BB","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 055","0112676ABC8BB7D03ED0B1A9E2ED214D","0112676ABC8BB7D03ED0B1A9E2ED214D","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 058","01A06D860B61A8C65172CB737CFE81D6","01A06D860B61A8C65172CB737CFE81D6","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 073","012A76A99AE7EFAF680F8A583E4A2B3B","012A76A99AE7EFAF680F8A583E4A2B3B","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 085","0125E813312F55DE92C0A2C020B90589","0125E813312F55DE92C0A2C020B90589","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop -Win","","Save For Web 093","01CAD52BFD97C6E39A4FEDA5CC104BCC","01CAD52BFD97C6E39A4FEDA5CC104BCC","","Adobe Photoshop","Adobe Photoshop -Win"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop 7.0","","Save As 07","0165B3F1B409A4D8D5F2ADFFA970D3A5","0165B3F1B409A4D8D5F2ADFFA970D3A5","","","Adobe Photoshop 7.0"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop 7.0","","Save As 07","012D821C6AB210E2A753BE053B8F55D0","0182408A81A4ABF04D4A34A8A5E98C58","","","Adobe Photoshop 7.0"}, +{ ENUM_EDITOR_SW, "Adobe Photoshop Elements 2.0","","Save As 10","012933907CE4B9D3C27E3E9D4D50BFD6","012933907CE4B9D3C27E3E9D4D50BFD6","","","Adobe Photoshop Elements 2.0"}, +{ ENUM_EDITOR_SW, "Adobe Photosop","","Save For Web 050","011E122B2E1C9BB19DCC0C0BC8E74E25","011E122B2E1C9BB19DCC0C0BC8E74E25","","Adobe Photosop","Adobe Photosop"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","000-004","01E1BDDF6C45DBEC46FC48B60BBF6018","01EA5E13EF082CE6D445C4AC8ED703A8","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","005","0126FBCAC54E5F8913BF1675612B5D23","0198D256A3203CC67CF1559EEB39D216","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","006","011C793F9E71B996834C395C0A4B987F","0168CEC66029B4B5237F887CCAA2E604","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","007","01645CC0CC50F54D1173CA3E454AF54A","019D7FA63C16339F44D67D45FD8603E6","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","008","01677A30C503901718398BF6931FC51E","019BB42ADFFE3152B70CF024B826D7CC","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","009","014939B82901487C3A444099F486237D","01CBF5EB43E3104104B28258D417ACC1","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","010","012B2C7ABA69A72048A5B864F1AC4070","01574C5E6F3D7293E84BE75D886A3917","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","011","0188AC3A8F2B0B70FA22245542E991CC","01935D7534EFAB6901A7DA9159BA60BF","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","012","0126FB4D1191A9B77D790FA3A446B071","0198C08C7D5E51753E7EC3FC7FD294C9","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","013","01539AF5226D7FD8CA9423F5C1A7E61D","0170D73C45D867BD2AD75B49D7254C24","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","014","0172C9440F7071B4EE7CA7BEF484B84E","01DFEEAB4A038C174D2F19BF66A13231","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","015","01466F83C333E94A420A1D981B0B18C1","01B2C325E900FF46A26E2EE89FDDB2A2","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","016","01C0446E7A2D20CBEBA8F2DB3E3FF514","01E90614933C79BC205EE1EF74699CB1","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","017","010047DB57AB7D7DD5FB3D0F5000D53D","019A9BEE3E8EFAD46391AD433C755815","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","018","016E007C33B426D996676779A6526DF1","01A3914684E4EE020AF3A5D193681E58","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","019","01934D7DA423E24105014F3C048391F7","01B24B2CB41352E7BC79EF13D24F8E33","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","020","016592D04ACA0DD271C5C2BC90E1333F","01807A26F1DD1849F1D287C4D0788B23","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","021","016480046FB50102942EDEF00B61C36F","018E070FB96C25B959564A5AA94C35E6","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","022","016B59B05B49931DC6084E11616D64EC","016FD94ED31FF30D8E1C25587E0D85F7","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","023","01878E1F2B458AA806240872FB43DDAA","018BB3F9D4DA424384A51D624CD3D9FE","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","024","015CFC6C2D58274E98FBBA4F6321D1AF","01EB319F71755E65CE61657E4E9A99B0","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","025 (Low)","0106CC8A4D86406631698CAD623295E7","01D7939BF6193E9BA33B39FB00E1692D","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","026","01225CBD60ED2AD10620D8DF77E71FB0","013B9648B48BFF6B7B099F3FD651F248","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","027","012131D6E147D0DDA17559B6D8F0E7A1","016254A60390F098D16CF2F9F8D46D41","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","028","012B4382271961958103C7343BE6ABD5","015F8C12B50F26B6E80F167F0FF47455","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","029","01CB490B7BED73A82A4DC3F14D8BB4A8","01FBCB539A90B10CEADEB86252E28589","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","030","012DCC7188B68F08CA475B836A696D35","01D3C50126F751A336DB7979BD55A2B0","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","031","0129DD41201CBABC51D0DA67D61D1D0A","0139B0F3163DF554094E7C3C575C8283","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","032","0125CEF1CADB3F9B61DB1C76882632EE","0130DBC822B41A84DB23DED722875DEB","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","033","01295A789D11EFBEB1271894A616C2B6","01EE25BE492A83676EBD2DD27DAB6EF4","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","034","014A5317C1D0D7E249AFE179EDC78D44","01F141F71B11831A417055F56CDBDBAF","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","035","019F943F9911D5A92F7FD316D5257911","01F5EACFE329B4A0B3D933BAA129D992","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","036","01157C3DC3F654CAE8DC773C6875C501","01E10E17D6553EDAA3980DD8442849E8","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","037","0102FD53DA7E2BF17C286459EB6D9527","0157C76A130F5344634EA4EEDA0A1D5B","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","038","0188BF9F540DFEEFA3A9C802EEC8CD13","01A778499CDDA9D909D5227FD9B90D18","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","039","018D62D7C4DE7E96267B7DB39A83794A","01BA683B8D4A9C52CE491558E648008E","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","040","01204FC209870A3BBFC7845EAF5759CC","0124B5353984D3B55CE4761AD15F513A","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","041","0106F49F3A8C3ED55BE59D17CFBF3021","01314FAD6CA3B2292CCD7BA1FE3BA6AA","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","042","0107889833E58EAD62F3C831ADA56423","01C6E60E4501F3D32F128664DCE3D284","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","043","01137E2463CDDFCD699A73035661A466","01A747D368B7ED07DD3B26292D80ECFB","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","044","0133919E64E56D9E74D9EF2745A71459","01589D2B6C93E184413F1FC5AC3B9BE9","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","045","018E870D2F9AFC8B03C5DC4492682F64","01E325F50092F947E74B2CC234700C31","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","046","01872032961FF2B3646C019B7E9B108F","01A6301376639A3410E4F662FD058A2F","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","047","0158976B662BDACF2273BB1C473A164D","017BCE5EF37920D90E7111FE8BD58598","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","048","012C8DE2056525DE9FE92443C605A78A","0194CECD16D9F462DCDCAAEF81F3ADBA","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","049","0182230692721ADF5DCBFB56F747490C","01DD92C0CD7077A88C49139F2F15908D","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","050 (Normal)","0175BAF3251040E0EFB2930B73328E7F","01DC499064BA9264D591FDE9071DFD89","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","051","019A47660E47871B3671ED47AC3CC5A0","01A1C753C3B952DEB5279ECB0BF65C2C","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","052","01120B3AD85F4C8E3EAFB2795C0B48F2","011CE1667822D0847E888CB66C5C580A","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","053","0141CE8E21211A09448DCACE8DC51CD4","01BEE51B29F37D8A5A7BC31C63A652BF","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","054","010024C0F1734B148CECCD76EE92D9A1","01E80B819244DB40BC79151703625E2F","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","055","01260E87C3F8E7D82C26F75E6E6AF47C","012FD11B66B6BDC21718EC7B400264A1","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","056","0161BBFB99218AA2D308B872914C25D3","0193EF2EDE9B800A47B1668DAC55A133","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","057","012444027658BD665BB7AD2C119EA883","012551DDF21B7F7A80EA5E9DD6B0896C","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","058","0142CC6174741D661E2C9E071B69422E","01C350C443A4740D913952AFB00253F2","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","059","01056C44719BDAC0034D5A55E16F47A4","01E9E33A72E2F73E8FB9307D47BA5286","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","060","011968874FC0524E5485DA781700EDAF","0164D08E1D3B43F9DF9C6925DF9791AD","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","061","0134C01EB38234AE0E6AC6DAF079B326","01A15B86B56D87ACB7B5E9BBC2569B2C","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","062","012E13089848657B9B5CDB998090F7F5","01E932F45D4F1478D2D273CD62DBDECB","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","063","0119EDAD5E9B000BDDBA8753B120A229","01DE4177A47A2F2676F6B2B3A0080023","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","064","012C1E92CE901A9022CB5FD8282E00DB","019102DFD4F30C9EAA8B16AF21908898","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","065","010C5E83B4718AA6A399FF23B50A7F96","01597ACBE29F0E07FA071884AB89D3CF","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","066","01B1DDF4CB8DA7D900F69CED5A0A04D0","01F8D63A18117D01CD1294E5AB131C8C","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","067","01758A3E0C28B68036CD45CFC3EB1216","0197E99A8AE184E3D3E3C6C3C5FEF99F","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","068","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","069","0162FE55E33782E1688BFB4B0EAE65B4","0190321C4F531E73CBEFEB2A68A93EA0","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","070","01784541057E8D5DE839E26D360E7B9B","0190F856F3F2E4FBD1A8EA7EECE2AC97","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","071","01612B6026E2956027E1F1A429384D0B","0187EF25A41FE4767D1716CD0D3241B6","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","072","0160DE46E1DD853827062BD015E0007C","01C180F0D55998C9159D07F2FABBCB1A","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","073","01887E4A16BFD89384CCF99F476255AC","01BD26E97FB262E36DC19C7C3890813F","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","074","017FC4A11DAF71E5DA854E663AAC411D","01906ECAFA199DFFA6789731CEF5E958","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","075 (High)","0147A204E29CA6BB54C62A51E403109C","01A1625280C51FF5D66CD5588DB795E2","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","076","01220C476CFC53783AC6AB5EB1A97F0D","01C250F6680836A53A23AB81808F9A0A","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","077","01598BE63D08B2CEDA32C2C52352CE48","016BE18CF2724156D4B72F612AD90E97","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","078","0170120584A0850B1F6E0B9D80D90B31","01C351E4E8F43FB78EB16F77F64E894D","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","079","01B84306903A0AF41E7FF28543937201","01ECBCB4C4CAEFADF8CE7D835B93CD59","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","080","01191863A92FA362537A80411114BBC3","01D7D42C1C869993B7E598D7C109534B","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","081","0158CE52C54D397B53221DD19E8ACDED","01AA907DA83C09A2A65361F78978711F","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","082","011C4430355A5A7DC629AF44FF04226B","01A815DCC9C4C2F64AE295D37ACA0F7E","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","083","01512628D15A91E8E2F10B54339B8F97","01CDEE40A34EE162A13F228C5578D9CF","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","084","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","085","015E76BF0DE87FB5F316AA09C0140F63","01EF24522F0FAAF04D2AAE329E929E9A","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","086","0124BB115473A2FDF8761E456E0479E5","016A0C5AF55E177945D9CA4325B15B66","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","087","0160BB5124EC40826352E9552F12F291","01E5D37BA619FF16E45EE495903E19D4","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","088","016517142B3160A02B540042E07047B7","01A2E59FC2CABC23E9813AE1501F4592","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","089","0177216E93088FE251EADA34A3527681","01F836392A26F87859B328DE1EB0E05A","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","090","0114ED88173433C4BF99F0569EA94D90","019E0FC5DA517712EF95A6C1789E61D0","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","091","014992BEE7D2FAA63304B0F1263B685C","01DC1DDDE2A9FBFA4FAA4C6E202E2CFE","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","092","013970FDDE9C9CA2CC8F0082375FFCB8","01A098C96CAA97E3171F4A90451B4CB1","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","093","01195C98AC99FFB4127537310F066964","01ADB5F03BA5F38B0F507E3D71E627FC","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","094","012AE29B4321410985D1B1B400901D6A","0155B057A3CF7EB81659AEB7BEB76C7E","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","095","0117778062C5DEB6B73DF9E5B4148858","01387F274E7398893466910CFCDB77F7","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","096","0166D7C4514A1B5BF17A8A31C90EF2D3","01E4481CC143080346658FEE1819556F","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","097","01456AE94047979A32863FE4D17BE1B0","018EE88E37BAC6C8133370617AD31752","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","098","0111DB73E1FEA8BD01B0960F519AA102","01BF46EDE189625817DDCD2078B14615","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","099","010391CFAC472ACA504A2866EE657963","0143211291F265B8A813CF926B8C057D","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple ImageIO.framework","","100 (Best)","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","","","Apple ImageIO.framework"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0000-0063 (Least)","011C88CCAB514CC4A787F898B6E6EE24","01C63F17235F997C6F997B87B01184EA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0064-0080","010C95C1C2130A78D3FC22D9FC14E720","01D35577208E868CB177450A5F916D44","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0081-0092","0165D7D8186AAC0B25CCBBAD42B1C8E7","01A5449AF732DA14FCD0C06726602345","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0093-0101","01A0B3390F3E3FBA8E0934D3A0D43DA7","01D50AACEC5C12098C7E95D7002EE7E9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0102-0109","01800B30CFE9217CBB8ED38308657045","019BC80D7BA9D1A6DA22935FD2076D0E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0110-0116","0163DE1D571705F29A4E0F9EDD415669","01A0B785F91E0A94A4CDE7AC8D98ED25","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0117-0122","010F76D7444606E67A155424D3E374DA","01BF0F617041503990DE36C6989878CD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0123-0127","01999239E7FC36CD7392D754FAAA519A","01B738F6EB8AB273740302236E6D3DFF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0128-0133","01BACF6DEA7CFE4408147A6FDBE6F370","01BAF402B2F4B9DB94C239DA866A32AE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0134-0137","01AC9A9855E4AC5C155158207E3661E9","01F26BA2ED5D94674D5367C9DF97913F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0138-0142","0158368371EF557D54B5C5885E827AB7","01FD1430AC02ED9CACAD174917D3962B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0143-0146","011EA21ED48A1140575230458A58CD21","01702B3CFF2B096D8556B5235D21212A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0147-0150","0128E20D2CDA4930602AF70D82D522FB","01A5EC263C62A85FE940A82FB9A0BBD5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0151-0154","012E67FC156AFCDF75878E4D58407D5D","0159A5F2A6B04D5AC38ECE33D1566E0F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0155-0157","0131B676C793FF00970E4A7522C59A35","01E81ECCBB93900A2CC55954CB731F4C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0158-0161","0179A7B1E2CCB0B4FBA690EE835B0E41","018FC7296FA535ED107586AE591C28DD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0162-0164","0174FC3355E9634E5D67D66637548DD9","01803B4A2775C2AE8447860D31EE740F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0165-0167","017231B2B696C41FD41146CB8F260F82","01C018FF15BA3C3ECA9F6FC169409E4F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0168-0170","01187EBC3CCC817414146831110B5714","01FE56C7FB69FC18FE3A98FC6FBB9831","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0171-0173","0102F290BB55CE87D3A705BF37818931","012D6428363A50CB868C7FEEB1BB7A40","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0174-0176","017B200FB5E3EA74BF9569227EA666AA","01EBE28348FAAEC3D1ECA43A1A5BCD10","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0177-0179","017F7AD7B07FA891B9B7EEB3CC921E88","01CF270B256B8BBD3007EE9C2EF4CD58","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0180-0182","011FAC9E26D30E962A6C4F180E2F0B69","0198CD00F64E119A82C25BB4DA8D8F3D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0183-0184","01307A78223F839F3BA2CDAD683CCB9A","017E03CD31C931DA2E862647E433FF21","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0185-0187","01C531722B2F47394AA9062F21C78BF9","01F47B4EAFE308D7B688AA053D3E2107","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0188-0189","015E1131DB3861BDA89E4D376820098E","016BF49E27301A47B42DB44FD5E13BD7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0190-0191","010299130D04450933C15078BFF5207F","013EAC782791858F72B8519395E3CA80","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0192-0194","015DEBB2E2AE030CEA8A9058EA35D9A3","01ED2508642E02D9EF8FC3D62AEFD374","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0195-0196","01931F59C7630A1B2F93F317B961F956","01CBA97D70360CA0BDFA5DE6BDA81E72","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0197-0198","013BF16740D3351AF9695E6407C98CCD","01FF0D33D2B66880A08992BFC079D67E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0199-0201","01BE7402223A77113BA5B256C9C6F0A0","01E387C75185B38F03F72755FED78E23","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0202-0203","0101D798797EEDCB716D01E9249F9323","011BDF304280BC0CEF755487C1768AE1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0204-0205","0140E6C2E321FC84E4CC0E8E3E673605","01FF35BDA8A4920D7005942922170945","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0206-0207","01CDB2D0D2E48C9A334625947D5A03F3","01EB372FC55553561BBBC6A0F611811B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0208-0209","011282E3D3EA6EBB3E82A40E23457C4F","01FEF40DD58BB15342E27EEA563FAB91","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0210-0211","014BC1B7DF73E3859FB55B83662212F8","01D3D577995401BD13AD3DE5486F5410","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0212-0213","0170CE9375BB242C57042017076B26B7","01A090554DB6AC19AD0F115CF5C50C74","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0214-0215","016077995DA06695B9A79FC106DF90EB","019666EA7B2AAB54FF488C4FB1433D61","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0216-0217","01AFA5864E7B1831A46CE24922753EC1","01CB502FE905AFF42FE7974CCFA79E46","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0218","0154257DC075384E68903518B2E50833","01EC276018BCAB863F37703644F7E482","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0219-0220","016B40F14F627EF116C2BF5AEEF0911B","01CFCC57C80681053827D570ABB8C4F7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0221-0222","0184F5D819677C7C5F3DC67449EF1AF8","01BA88DE9F5ED718592D424347B544CA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0223-0224","011D0A500F8B772AA87957260AE2418A","016CB90C820ABF22026718C383C64852","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0225","018A0C0FBDE2385861078D1E0E66796F","01F5D68FBA719FF3C8F685FD57815658","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0226-0227","0175767D251F6D9462228543A21FC1FC","01A0DAF5AD35F93E1AC7A3C1688020DB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0228-0229","0155688A51658EF2A4D620E851251F2D","01ECDC70524EDBF9578ED76CB371ADD2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0230","0133F8440ED95E1CF6A22C633094E486","013665FB4674E8A03B1F5BB1FF4FE50A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0231-0232","011806C4A142F558FA34B7DA152A88D1","01B458CAD46CB1AD102CD19867C1F31D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0233-0234","015F4B1408D5D32314E622C007EC0E36","018918B22E5A0BD03DDD40A9EFF7ADA0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0235","011649A2C018937D2D6A6866EB9EA878","01F685EDE4697F7A54BEC8AD02747C0B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0236-0237","012EFFFBAC08525942D3B5A87FE5E8BF","019890C73537B5F3DE4525C640D0E5D5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0238","0142FE3E6227A5F805714FA78EE78FE0","0167D8ED180A72D688875A06F4C97A71","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0239-0240","0152CF7CC5A3E51C147B2F73B41061A8","019C5BE56272F419FDBDFFF2EE6C7BE5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0241","014B5051F8A15FDA93313FFB0CA80305","01D4220BC754A34CC3433BAC02C9DB44","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0242-0243","013CBB074AD3516731972B97FA633214","01FF2959188C37BB821EF4E005EF5A2C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0244","0120C506E3D67A32E14D4C311F08E049","0172226C0CDE175D59148C13FB22493D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0245-0246","012D01E9C979A65B61567B0CF43B1D2A","01A2B82DBF8317BD7DE51A6C2AEFC8C0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0247","013B712701EF86BECB39ADB93CC6AC92","017C22C408DFE161695256C8817821E2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0248-0249","017A0B79755B97F8E1B7239217EF8F1A","01E51FC640553BD5F7FDFE9F788B963E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0250","012BC876798D084DDDC8B15C0A888F0A","018128A750BE8ECAC95B90355C90F731","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0251","016590247EF75642C69D0E6549AB3F2D","01AE46F4AD34864476F6D3705E8E09EE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0252-0253","017E30CC8BF30E23C3D3D90E5AD81CB2","01F56B299ABF062A81CEFEC4E0EC858E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0254","015C2B61451212F09BA3C35FD11B8ABA","01784446567C08E4C0A3758BD3FE916F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0255","017D1C0CAB3D8BD6F9059B970B088BDC","01DFD59D9409C9AF49BB3D0F2A5E6C6A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0256-0257 (Low)","014196C461DEFB74E00440F3D2991D05","015F02EEE7A4CB7824E4F4D7558D75CA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0258","0167F8273061B6E3F9C4E45CE7DC3A6D","01DE720A4E7464E54FC0341D1020F40B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0259","010ED5474FA470D1FC43BB3433EC9D05","01B5CB99F543185E58AE0DB5CDF3A4D2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0260-0261","01B1D257C3F23179C939AA7DD1161F63","01BE43D3203CC0B00E48300C5DEB59A5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0262","015DAD73756A5193368D6517AF1D8493","01E017C96864CC2FD2AAA0046F70DB94","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0263","013DB11464FBC46A7C47478AA9A9D7AE","01B720AAC9BBE757EAAB0FAA1203B361","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0264-0265","0132ED26C8B816CE8850B895F4DCE3E8","01FFAA9B7400390FE7470715071D796E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0266","0169AED3A0F67E2C8488D72A6011961C","016B2C899283273B1E568196B9F0EC8F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0267","01E614AD096C0BBC6D3930B1C21D6F4A","01E761C004EF5A8603F3EB8198E2BF9F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0268","01499A7445CF67E1F91FD160221DFDB3","01A5F149E6942061F725B5F7BB29EE75","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0269","01379F5D785888DE67F8869769133BFE","01F1F074159797A96356BF36921E9221","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0270-0271","0144B7952F8D9D40A7DD27993540A022","01FDE9CA3F612ADD0BC23A4F7D883666","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0272","012E96FA94C824F9A8640AEA33DAE4C2","01FDCDF2BE27B0A172840806A70E21A6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0273","017C6B6BC4D2D426AC637CB266713EA3","01DE1EF2CAAFF234AB731F79D04A8A60","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0274","010E204824CFF3EFEB296E548D2831F6","01916B4116500E60BE5D144985FA237D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0275","0138088D42874B0741D3FC58F5573AF1","017E3E77F3505D19F7327DD7D2724FED","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0276","01098D59ED7C8AC69F2C1E20CF4E0CAC","01C6BB26799012DB2BCC96DA02220221","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0277-0278","01CA592B0A278C10375A6E4148FE6419","01E286256520B9A7B43B0222D0E69999","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0279","016A44AAF01EF90192F4573EAFEFAEDC","01A657B1A018AFFA2179C715508B0F25","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0280","01503F4EEBA4820DF555885B90A5C917","0188F1B513AEC3F28F4F34D7E2A79BFA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0281","0124752B6F53B757FF5AB259745EDDD3","01525932818E982A26993F09F4F92CB8","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0282","015AC49AF7DB5476531A72E670AB4655","01B2B99A8CBD11198C31AFAAD8640EF3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0283","014C59B66345954B61A51EAAAFBE6889","01542847E3D874AF2170840C401F0434","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0284","014991356E69A0C83FCE1B5326252396","01C75BC71D33F654F794FF5CFE6728CE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0285","016A5848CD54767A21084D3EBA1C8595","01942F78687AD71C00190D68849FE0C1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0286","0133BB7F25BB79CCA360CEBBE3C8CBD6","0198DFCF876DA1E81E92B7E9949D8155","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0287","01398276696E8F035EAEEB7B9AECD452","0155FF2B6BAE4AE1D1635FE67CCE8D0F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0288","01132101C4CEA4A437B39210AD463702","01637425BDE8E6F7E84F802802E9D126","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0289","0178B0F881697D3A35A0FF5EADEBBAB2","01DE18A63B1C8834DA9226AFED6724CF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0290","0153E02513D840FC99FE0B60EC6E5DC7","01C3F4EE67393C17F132E1C81761B80E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0291-0292","019D857D65A18858930E1E7D5D6B289B","01B1EB1585D954B41CDF72C01898778D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0293","01DE0FBFCDC2F65D93BA930372F59D41","01F94CFD5C2E1015E6EA3C240FCF11A1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0294","0192CBEA07A900E2422BCDA4741A3A00","01F9FABD244E1E79A0DC4CD9ADC55D48","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0295","01A25C1DDB83C5A4F020FF827B4E72B6","01D08774A3271E73C3E78532FDDE88EB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0296","018034E260B462D6E0F8ABFC8A3BB907","01F01BD0FBF6771B2850F5934646E944","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0297","016FF758B448E2511C296CBB45D3B033","0199D82603D51297B1F867AA942AE20A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0298","01AD570D9BB42F2D764F482FC66D3A97","01C47B48A2D9AA094611619C24AC2CB5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0299","012FBAE8007C11A27D87235DD8A08605","013CBF9607270A1954C81E459DD4F336","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0300","01C5200A6DBF9165C917066FA4860C0C","01FF6D37252274C859416FA6F98AC090","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0301","0116153BACF3F792E59FF7836DDAE7D8","0121A96A82547450CF8F58BF84284C15","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0302","0109E20C03C96B7AEF53CA5EAA5AD1DF","0114B45FD68923F2128B84DF8A6F3CCB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0303","01D50D828028DF78913C1B8DABECCEEC","01E004DBF278C6DFFD3189B29FE6093E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0304","015F75D0539DB0AA33DE9086D3D634AB","01D561C82C0BF4F7C83321A6DBED8824","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0305","0126229976467EACBF032D4C5A2D127F","016BB7A9E6546985118526AA7631651C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0306","010B8E92977DA6223CBE535BBF4A4367","0190F4E50734B3691B95FF3AB0F2D858","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0307","012E91AA6F00BAAD85F8F2B6BAD82926","01DB44FD317523A4D3C0A5C56340D7AC","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0308","01772ED0AD3C1C1BFFC38E66898E3A35","01B0F92606B6AE035255B817ACAC850C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0309","01E1865EA4F6ECE601AC4422624C6121","01F7FFE8BE356C30D30EAEF9D85EC512","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0310","01A33A9D8610B69649BD2CA4291CC025","01B1997E3D406AB0A132C98A655550C9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0311","016EDA1C4521F0E5445B34F1345661EF","01F413B54D77AACC10C5EBAF527DE7DD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0312","017269EE6347D641396E6CE4EEC55545","0176C0087432177BDECB6B0564EDDD75","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0313","016BC2EE578196DA4ABC2BF857D60F14","018A160913B05A8E2A50F81D6F69EA46","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0314","01556C09EA00DD3C189F2BDA34787961","016371B1B482BFD9A55E101227864AA9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0315","01A22C90AA6B01914EF92C2EDD4399AE","01ABB8850DBCB396508E3A42659A9EE3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0316","016CB97F1CFD2C57C286C575F7F99531","01804E265A2A88E90D54A114FC8DDDE7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0317","019407B1682B8D28EC04607FA2B19EC3","01FFBFD4B46EAC504CD923FFB9E49131","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0318","015F455CD02BC42D60842BEFCD24E35E","01BE7EA9208B1F968C165587E7957E82","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0319","011D57FF8285857AA73865075C50B528","01EE6332FE27FACA6561FB159CD2C165","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0320","01B103E031429E917A31E86C3DA634DA","01F502A2624B1A16EB133755300467CD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0321","01325ED8501E998C8603C6B115102D5E","0139FD353945B81AA25529086E0CC5A3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0322-0324","012514374A61C0E0205A43EC2CC2DA8B","01298A5758D10D013E0130A6B560A15B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0325","0133FC69E52E74319F110B4486B8B0D8","017FEB124293E03634B25E85B537A2E9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0326","016D7EDE7606414D991E6952E80EE1F7","01D115190D8DC08B0088CEBD49ABDF3D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0327","012BFA25EC8A81E6A52D3EDD9EFFBB7A","01F64137199157B9971E5368174CC3E6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0328","01CA390C3C7A086D1F674E0F8DE3E487","01EA3E9E6C1AF5D15ED5E617A2D3D89F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0329","018AA265EEE919D20B4D74CB4CBCD9FF","01B0F2C7ECCAF189E47337AE0B2BE871","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0330","0138B43587335B7136A83646BB8C8444","016FC91B845047794BC8718125DC1D22","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0331","010706DCEC9384FCD911CE7EF6F9AA10","01DF585825BD040888218151BB180485","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0332","017A73E137683F2CF27F35A8EA277B2D","01ABB6CF48A47B6B69ACD617CA381C96","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0333","0172CBBAFDC69B2DB22550D9FFFDD5DA","018A1D72EF163CB05CC015BDAB62E943","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0334","0115214D14B7DBBE80708BF92F07C0E5","017AA2772964687B2C60899FC0DDF260","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0335","01BA0E6EAF685E372997C5158873A934","01E720041665A7B0028E31EB34495D45","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0336","010C82C21FFB556423D2E1AEA09D6AC3","01ADCE0CBE4B4BD36E8990DCA71F41FD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0337","017A6A4E8D40701EDD2BE40F880699A7","01F2C7A73B2E5BFBCE9E680FCF33B732","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0338","0113FADEC57583A1B8DF0EA04A8984FA","014A17E0D9EAE8D5CCFEADB7A409172E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0339","01B54851F7FAFFE3F3FFB0C98045C20F","01CD762DB17AE5F82C0534B07A265DFD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0340","0106D7625E411877CAA338676E05E5AB","01E04BE11B708F7730D5A91B89AAA914","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0341","01DEEF0C26CDB5F18CB5C30AC67D10DF","01E6FBB5A4BF581F87F339D62578258A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0342","0196CC9924E6BD959AE089F5862BA560","01D8CB2710CC698C40143FF0E146E3BF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0343","0197C4CC8A2121EB59A6E3400A8295EF","01F136537F044C37185E4D19C744AD9E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0344","011EC85456FAD165DBF5C6A5007C3E07","01805F382A0E1E5D4D49D5612C5B1FA2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0345","0161F9E8EE00BA1E250B7D55F186F72C","01CBEA20A3945A17C97EDB92D1A3F8C1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0346","01488B03814992ED43EF64D8659F28BA","01D730E0F6C17C9617BCDC128B90C379","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0347","015CC783479C3D9A25A18AE2C2FCF0EA","016D96CCCD278808EF958DD1C5315158","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0348","01A4190E753515CDBA00BEA808B04D1A","01FC1898602DF6895977522E10374788","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0349","0111982B37FDFA77D6C9C7356D9548D0","017E046DBD0AD3AFA3BD1443BB27D017","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0350","01273B05269AB49659658826842AC1AA","01851D05C185ADA1F03BA1DD7EB693BD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0351","014B69771DC99F42CF7E75A92453A27F","0163F1FB5A0DCBA8FE6D85138E1F9338","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0352","0132FFC1D7FEBB3B053AC02AD51A16A0","0158A45982834ED63790DC6DF9C6A626","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0353","0107A54863D862C397614B7A892B7C6E","010ACB017888870B12D192AACBD700FF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0354","0103CB9729158D46CF1DB0689CA14F7D","0132626CADD62AF02D5FD0DF263B71D3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0355","01C9AB1473B3FB383D976870F68AE1EE","01D58ADDAA7168BB2208616E8E37FAA4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0356","019140D94D7A9941798F2A71CA5437D6","01B52C9B356883331ADB76B001F7F391","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0357","01AD256679DDC2EDD0DBE80F157D88AE","01E1C17643BC7FFAFB439F32EA785BD1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0358","017CAA0B0B61BCE22B54D21D2890EE91","01A817DB5F8B63ED712C4E5726334B7B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0359","01B72416616B03EC44EE529F97A61DCB","01DF2FC19A3231A7DB9F482D79B38A62","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0360","0159B37AE98E23EBE3CC1A4F3B5D1EFC","01D2D675F82D7B1AF96E84C473447C62","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0361","014CDC93234C1379FE22988D7402782C","01A8A9D00F826AEAD001518F2CD437B5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0362","01B993B11363C5FA17FE7D38FCF8C2F4","01D377C41EC4C2584EE46CB3A4436280","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0363","01EB34994D5E62FC5E52F8DDEFE3D2F4","01F598EBE426AEE87D8F456C07B7EFF6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0364","0119CF37863A6A7F7EF49EAD67AF66E0","016723371317F92E47C1364768EA973A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0365","01787808AA17389825519FF453F8BFB6","01EBD34BDA688D36A8AD061F1095AE64","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0366","01E24A057CCF3F9D4E36888CD54AFDDA","01E9C7A6AA13FF21D1EB0B0C0096A915","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0367","014820A0E94228F9300AC1C09F07AEA6","01559974BDEC2A6063D9929B872E2A61","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0368","010558C701B4128C1C5E4E6C90F78286","0116171C8A2FC260EC329F719E262E0E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0369","0147126750ACC655ADDE82C1EFF1C0D3","01AAF51AFB5BA9B5505C1A9081C8DF57","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0370","0152506665FCB02684140B07D207A770","01BB0D0BE601F1B02E43FA4AC95605C5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0371","01DB04A9499D69E56B91AC0DC16F22EB","01E24EF7397BC708EF485D8CDFB19973","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0372","014FF9AFBE7E78E178C583D0F2125008","01D39DF0A6282B2C2398C38DEFBFF1B1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0373","01D782AF987ED53E7E4082935788895F","01DBF5EDF65B6D3F953F7D78CB8646B5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0374","0127E66E3B0B4204DAB9A632C5EC0767","014ABD9E2286076902B40329C4E8E6A5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0375","0141DBB33F21E5ED0522800C8BF949B1","016E46DAFFB0299EAE565529E35572AC","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0376","011DF0955ED033F1136A7590B06E90B5","01B747309643CBC602FB70CA27DE7F55","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0377","01C3F32F5E678D3A7423DE27C938F01A","01D84EA5162D47C996A6777BC27504BB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0378","010DFF2B2F6AA668ED2612ADE8C9B3C2","01EDA6A155F9852329767462E5CD76C2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0379","01D3C34273ECB6591C4E721E283A640C","01F62E7C97C688FDF31B6E2F81454F94","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0380","0171F9A47B9B30D078F234F4418ACE45","01B5F0DDCCE9EBE5969E992D01129CF5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0381","01974F95F7C16468E32AD38170E510EA","019C1DAFA502776E7BAAC4747AB3332F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0382","019782C31B0C831845D73F5543BC98BE","01E15F4211BDD6C4F5E0F77E9326D1CE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0383","0177AC904C4E007252A91C25DCBB14EB","01DF68AB84D32B71FAD42C11B73B6BB8","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0384","011400D468605B952AE88B8B10A18171","01DA14E2A02A7AD3469068CD7F038457","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0385","0155EF820020ADFABE1533A4F67C0B80","01C481734231F722C7445B0C55C84239","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0386","010E6513BE81BED0D4B36BD462D666E8","0134F1B277A728D903AFD77DB4619C00","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0387","01989BEAC872A1B99539690065A39C54","01A02FDF2E7F6DBB0A71AFCF077AED79","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0388","01540532C51FA06508D087686FD0DCFF","01D0DFB151D286F2298B6B28FAC28546","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0389","01950F306D0ACDBACB1E943077B6C502","01A1D2743EA64B7003A8866879ACD83C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0390","010520B3289F6C115E6C7FB5FF94AD23","011393F781C1F5604BBBE037EA344772","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0391","014291231A0D750BD42E7379AB2EC9A7","0155BC2CEB317B56429D72E3832C276B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0392","0119045ACB656B2AA89B8B7E7AA9A11C","0181F7838B94CC005C4D9415A9FC4AC5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0393","0108315A37ECD25AB2C3C7D34D8FAEE6","018EBB3CEB30AC32525A83E9674F4AD2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0394","0146224B58B822FA02B2550303B29173","01C941D2C9C9D882C499CF6C3B606ABF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0395","01B0AE5A64CD5462E66AE5E3E03A619C","01CD547BDD05B363D522676F3D639052","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0396","01812B79812DA11637F57EF135221694","01EBDB2DE50293CD4DF8563A62CC6BD7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0397","01135549E44963F5BED69C19E01A626A","01D082E1F33592E8ED3C0D04C34ADDF2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0398","013643035BD0BBCF2848799DDF50EC2A","013851E6565FCD218A8178D6C6A177A1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0399","01003B03E43F3C08EF305568D1EAA2C4","01040E165069A205217F6A88EC5AEEED","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0400","01764B33356D627246D9BDE18256C8F3","01DA8ADB8F6C79F85E968B77B23B1636","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0401","014DCDA30453F991F9C987E71F33A01D","0192427F2575D9764AEBFE1887CA89C2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0402","01B03481E5EE1AF8A0D9CF4B6D0C9B7E","01D28F1C9D3EDA1FADD49B775A70994C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0403","011A1AD05F4E69637D54F7644F73A677","01F0A14448D6798A5AEEE50E8C24544E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0404","0146220BE1E3384C10CE628D5C8FFF66","014B01295466371C1D24CA6CD2CA6C9A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0405","014DF9897E85EA56455369FCDD6F6E70","01877A475F66FE110F7B8A3A816A9133","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0406","013D8437D836E4297D1772BAC1E5F43E","015E43C944E17354042EBC370845C575","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0407","0148FC19E8FBB1851F30AE5F45112705","0161A26E905FA28126885B6AF72A8D1D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0408","01C637C2623EE02B60F7F0A6B3FDD32A","01FD447287C5C847EC6545B2B8CB387C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0409","013DB44FDC160E2254E0FC7175AF4A4B","0194A4989DAE98C41ED27CC38AE1E04C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0410","01369181F64CC932F704247634847989","01F40C8B0BE2B857818AB7D54AD1700B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0411","0139A96A7EF90701633DF35E361484C9","01634F996ABAFB8624801B6BC71E0EB8","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0412","013BE218116F5C424D76F2889433ABC9","01F21D487E1140F08F6ED715C608283A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0413","01386F898D3FF042622254961860D2C1","0175C60DE795C1DBEC7FA2569E7C4BCE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0414","011344654042CFE5285074B9F759FE54","0156573AD1A42BB73D971215B649BFAA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0415","0140F1E3574A5277EDB2B7D62DB91A73","01A3CFDE5BB74875D0CD9845A0CD0579","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0416","01254CDD816D22F1274A2408AF25D54A","01A60E05A006B83663C13F79E518EF68","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0417","014C1996E3D5846DC928502735000E1E","0170BDFC71B6904408B13C98438A3F73","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0418","01268E71573851865FFC033A73EDA838","01B8E57A1D406AFDEEC40992332407EB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0419","011C34244A1783F3081F338394B63FDF","016406DD22AE88220391FDC65315C5AD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0420","010A6E0576302CA936E447F4618A8431","0114DA572C12C1D8AE051ACF5A968E96","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0421","015BF7F9F6764C265708C62043034F68","01C29B72AD423BCDA0B3413A8628AA87","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0422","0130BC5C262DE544C733420AC8384EAE","0199B34FC298156BAE8E81C9D04ACE15","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0423","013382A238A823BE795E8D8D5BCD2A2F","01986EC7F03B04BF24F244C32880FAA0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0424","0198EAD8D50C4408C1D37D44C3443C3B","01CD3B8FBA42269AEEBA7D8F9656C68E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0425","0131E2F41BA4D1CCC0F9DD6178DFCF4D","01509FC32735787D681CFD1BD18758BA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0426","011E7A4569DBA0E121E81D91462DE65F","016C961BE702BA452A489DF42A99FAFA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0427","01324B15EEECCFDE0D7A907E54A4C8BA","01B29068D17071B95DEF63969BF07253","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0428","01C7A2581BDE73567E3F07F99A904A72","01D7AEBAD9445D81EF0C99DBB30AF533","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0429","012891FD6E0DCC297BB5AD1D057353C2","0159A1AA837820FF99E28074A49CD849","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0430","0147411E31D4761D3303D58AC31C2B52","01F78B8C83226968EABF8E6FEEFA0CDD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0431","019A48C7F1949EE3F71EFDDEA395C4BE","01C53231B84B5784FF30F8C59BD01B14","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0432","010BDC7D1187FF0CB1CC6783A6199A36","01778D57EE62B36E06D41C8DC1A6E325","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0433","0175371036D9DE51EDAA0144E0A199CC","01AAF3BEB2C40054C86617289EF54FCF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0434","01331210DC5BB6795AA27B45B7AF373C","01FD55DE693D807A56CD1312F90489FA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0435","013E49E627D57319B424AD1FC37D9ED1","014DC069EF03293A2F0F42BD66D827B4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0436","019A93C48B520B1C40B9E7F3F6C6E473","01CFF2CFDBA3E60F9DFB4898F9E09816","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0437","01B0CE0F01EFBF706846A02896471923","01B9A8DD143D350ACB16069CBE1AD772","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0438","0185F3A0CE832BCCCE4DC841C5080CA7","01BFCDD7D711F3A95C288EE3035688D0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0439","016A5E7F4B01C1E50C9F29A36772EEE2","0189C05B83E027D45FE58BB3DC2579EE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0440","01B0A8D9978F8EF27815C03F48AB841D","01F34A28FABF97747395BB712AC37AE9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0441","0180E29802FE7454A524F36FE0B6B43A","01B6E6284CA2C0A3046839BFAEF215EA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0442","01A2B2EEE6F4EDCC72F54984E6409CDC","01B7C182BEBB12D0D557CB87715350A0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0443","0120474BD1393DEE893F4D918F8A3BED","01FAC7D572FE578DBE58A68BFD29F75B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0444","013C95A781126474E7935C84880C1363","016D3F0FE62365F68006C20886E6652B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0445","01140702441D18A8B38FF0AB59FDDE87","016793590F30219FAE2FC6A30C6CE624","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0446","01227400E7A08A512FFB19410CB9220F","0187B8FCF67A7E3DCB9B86374A48E31B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0447","011D931D35DD43E4D64643598BC6D2B1","01FC51D4686A6A12459792FEA57DFD41","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0448","018C55FB6FD97073BC8637B8203940B7","01CDFC8965E4A7BF7B44B86BE150A2C2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0449","01A2EEB0662AE55C1294513B6DC109BF","01D3EBC5FFC2A0A96533DD881E068D6B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0450","0191EB02D6A1677CB75B2C8505E352F4","01F866C46749929C0598EABA0DDEC439","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0451","013AC1A7E3E9D9CC676CCD7A543DB582","01D75C158973ED2DAEC8B07F552CF938","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0452","0157532D8B0C1B683254879AADA840C2","01DE075217BE9633DC710384A4D6EDD9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0453","0174C6747387A33B3A96B6323A15B8B6","01A95551F1C9CD937B95D861456ECC97","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0454","012C392B5613E551A6821FA0E54F8CFD","019B5FF7C37E4BF52F9FE041251C7BB9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0455","0105F9C080293209E3AEBE1CECCC7D4A","01412D3CE77A43A575221DFF8CBC28D4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0456","01199A62B009B1F466CB0E0E6404EE08","01A2D9C8FEF5C4E019E77966B259016B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0457","018E848CD3DF1DBDB5D82CE001CDB448","01ACEB6CEDF0722C80924FDB80FB7D70","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0458","015BA90DD391A7F10D2C01DB2166FCB6","01C6212E754EC57178CBCB82946709CA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0459","012803DC9428F1BD30D74DED1B197AC8","01D96024DEAB04F4882E3DC5609C28FF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0460","014B284F6780E8431B6782F7C3FB2443","0190740B961CD87EBF3396052B5C8A61","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0461","010B19115B7E61CE2DB4BDA480120DEA","01BF61EACB8030C7AACFDB5A3A2CA383","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0462","0148F74AFF4C0FEFD9AA0038F0D06096","01E9206DCEB55FD53A45A1FC49D0B0D6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0463","0133F236363BB55A3DC0C6487232F70D","01FC63F6C6038C347FC3CB3F4600EB52","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0464-0465","017F4D6A4D88E1F797C7244C6D159DC1","01C49F65720FB8B657FF0BEA2FD7C3C7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0466-0467","012D821C6AB210E2A753BE053B8F55D0","0182408A81A4ABF04D4A34A8A5E98C58","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0468","013AC1608F7A083FA54F0ABC612E36C8","017EED788940B9E835B3EAE7CC4EB840","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0469","016B4A8253BFBD3B16FDE14E5A2C2E78","01E65D760D8EABCACFDA5F7D80EE41B1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0470","015641547A6E6FA36EAF79B1E50EE7DD","01C4A96E0D533D4CE4AF07371FC45AEE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0471","010722A0620056E9A2FF35D172ED6BA3","01789360A074D94FBF180890C02F8CF1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0472","01A0A7C8FAD86CD51719B4D11B809A75","01E5FCE7A9DD101E94A9E32B66E8C4EE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0473","019D13E47EAD93B95DFE2D80B9FB81E6","01C55AAD2822F315C3E2D3F0CD4000A7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0474","01353632E1E04A7081884271A93A13B1","0159E5C814BC1605AEE28A0EE89E4F0A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0475","01977A5680033292F498E7CF4EB62437","0199439B7E7464FEA9A6FC0FC1285B9E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0476","011CAE68B99D05085FC30546A1DB3452","018463C3E6CABB68E655411E87FBFCB4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0477","014FAF505C1A45011F1E99F280135A18","01CF2E949F6F3973B17077A6DCD078CC","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0478","01C02512D0005A0849AB22F0BDDC0E2B","01DF7500501CAE9F89E0CC7660CDDF72","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0479","010F353D6181F73F425C37F9A1282695","0159E6F0AF54E1502B58942F96A0A2B0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0480","0140B3EDC42BED8D7893372A2EE399A5","0188BCF4D70EED40EAB0A6AE12C8856E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0481","01390D43C65FD5DF5DA1CF416607E83C","01D95D92A1702017D722D918EB17D7E9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0482","013319E9ACFC1592EA3707443D41379B","01C641A80FA9F17A2F80671405FA645D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0483","0193978466E8C45B530015DAD9771756","01B431F54E253079EFBC6E35AA851485","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0484","010AF02A7E11380A8E7048EC838C9146","0174C6950A3ECB17C3EDAE3943CA0E74","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0485","01A37EC6A34E45D9E324A41C3C1F8D0A","01E56E1F28A07DA431A8E941A4ED3D6F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0486","019BFA737D93AE4E810BCEC1BF622FE1","01F604112EDD2CD75252A3F4E7914186","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0487","011E8FC3005D787803DC61391250E11C","01260816124E68FB34B3C5A968652188","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0488","0180ED9DF7C292F9E6EE10AA0EC33D93","01DBCB52A9F4D5EF652ADE91D3DBC20F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0489","013CE5A98CA06564271913E97E17091C","01CA8DB74626EB5ADDDE924CBB808177","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0490","018C33F34E14965F901D87E2F5059D76","01A2863D209D69C318C2D791ED4A198B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0491","01CC427EE894AC6DA5233F1BB70DA151","01D392E7B3F2274DA633A257D3335513","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0492","016AE6407F27503483641CB265E3666F","01ED61C6EB014A13D153CCB63075CADE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0493","016A8B9D3E06915B6057C1A4E9925FAF","01EADF79B040CBDA0A3329190FFF5E60","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0494","011C975826DF4E650B123D6CBD745FEF","01A9583C33385BE8C5D9AA8DF5C4A2A9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0495","0186DDA3C99987029C896738E83A6423","01A083083E3BF1EB8EA792091F3FDEAB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0496","01013C1CD527C24F7C5DB1A915507C76","01EA1DEEE251FDD2C98F1A1E7CF06DB0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0497","0115991B24A2457586CC3A252FAEDF93","012B0F71ACD29195BD62C24AAD206F86","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0498","0174EE93AABA2457FB0A41BCAE94A025","01B6C9DDB75BE6F5A0AFC904F69999BE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0499","01AC981B3281A80EEA9A1EE13766901D","01EFF430D5EA2DED89B39B35669A4889","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0500","010A9056CAEBB877BB3ADA1540D60D26","016FE42D5D9723FEE0EEE84FF3D859A0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0501","012B575006786ECBF308796237665A0D","0187FE84BF2728468C1F8DAD7BAC74D6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0502","0114F3762062837D521FC2EE9DA92199","01826894D6D5FCEF1DE9F84C2E926253","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0503","012D23D883E0AD3058D4CAF7CFEA8160","01ABE7D58F64F0BACB5F3745A1571F8C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0504","01412DDD7EF447F4BE51597651384825","018B9740A2EF139B8A4CABE1EA9082BF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0505","0104D700393677934A3376EE0EF59B10","014E439B42B0BC98DE98769652F16506","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0506","010ECBD9D88CECC0BFC1D6EDCDA59A5A","01210F00D2B4E698BFE43D6500739FCD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0507","0116F7ED80AA7FB5288AB995FA31E7C8","015B8CB1DC0E7027278339C4A2548446","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0508","013B3824930D0195BED318AAE153C0AA","0159AF9A6C1A473B1BA1D3B1A1ADEA62","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0509","0135589828B5D78F89F92CFF0BAD7B1F","013D977C1BBFC9367671545500BAF3A8","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0510","010A47B0AAC2F9AF94E42FCB5F9784DE","01D59C3006B20C6C80E322B72E56BC61","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0511","01EBA0DB74E96523A5EFFC5591CA7710","01FA385AAC22610419A213399C6090ED","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0512 (Medium)","0119EF3DDFC8AFAE643E7D5C02A7BD06","01D050F7B28604722499747F698AE37B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0513","013BA6E39F3A8198BC9CC8BBE88CC7E8","0148D2AD5FB27F03DD7EF6494E374DF3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0514","013829C572356A4F2C6F81A1B4909309","013E47531452F2C6FE57201ADF6EE8ED","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0515","017874969F6A9CC97F2867FA0A05E7B4","01DAFBE1190C8C50FD91602E042E2FF5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0516","018A74BE1C5A6707E2DA4057C7A4FE5C","01F92C3E6FEEF1D9EB564CC49B8CB41C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0517","013E2307EAA7A15304CF3B76CBF7C16A","01EE0AD6E211AACA392B5E03530E9C09","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0518","01C30FD636D41E1204C54F7D4607BE82","01D00D35AA2C30286149F79BAEACBA7C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0519","01173D1EBB33A4F2E070B5867F132C6E","01A266B175D7197CB016173224B78D9D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0520","01B3DA8CF02BDE7FA68D34243C140F69","01E9D25593908740A63E07F070225F1E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0521","0193C847546BD23021C382452F392451","01ABF300C7DB5E8A406DCC4F27517827","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0522","01483D27FEBDB0A0700DDC8B13447A29","0150AA0F3370CCD475ABA3F176C7246B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0523","018EB546459E180ED0A78376F0B86DD1","01C4C5A323B32B46E52F5A44DF16AE86","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0524","0149EDD8F40A4F402E9C85140D5F5E64","016592157E2278248194FD0CB1628859","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0525","012B9F12897CC495658FA7C8E71F6129","01A7688231540AA058762F89F7532D3D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0526","018AECA8CEB44F688DB3E833244D4F17","018CCCA6C1F54BC6DD537E90FC9BA14B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0527","018E05B59673206626E97C3D7EB3E533","01D99B8F7C5E1793F94EB6F0F1F5C413","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0528","019BB8FFFCBA7222C2603E5B4359CA95","01ACB248F872EC6A233D9828B10C2711","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0529","01725A3AA5DD3A8950439B2A12422310","01C63D32D890102FE2AE651723FC4658","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0530","0109874E43EEA38503A27E21619D3419","014510AF5A2662C30D8E86668401002F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0531","015B62A53E2AAE1F9C45F8E53D8615F8","016AD3B63321BDE3E3AFC869984AF05C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0532-0533","01315330924E21101CEA22D844F5DA75","01FF5B0059671E82BC316B53A3EA430B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0534","010F281AAFB3DAA7AB9579A81A32F83A","0179878902493D17D868B06656C11D49","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0535","01361651FFB7E4064EDD1CB4AC1F79E8","01F6F4526A88E2F8FD82962A49B970E7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0536","01CDF4161B9EAD0944C4C637713F890D","01F64488A68083AA011C86EDD9B6DB5F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0537","01041AFF93E2B634CF24E47D12B10123","01495220A029A18FE0BBFF73BBBE2A76","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0538","011CEDE2297091B8203EFA1EA2099CE9","01DF29B9885FF8B13FE401DD941DD6DC","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0539","01BDA2739C2D2EED4F87164EF88E8424","01E5201E2D8E6D430410D083445CB274","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0540","011AFCF5E21D51C4C46E47E4836536DF","01572CAF26F97C3991673130F5B79406","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0541","0177A848BE829FB1D0CA048C07803325","017B428D20074AD5EA7D1B5A1F1E9B54","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0542","017A6B4FE4405C5D571F6EF30CC6754C","01EA537E8D3B4E668D1762C74DAF2916","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0543","011E948E332DDBFBAD817997E6496D08","013EC1BED397021141FBBAE1E85A10E7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0544","01079651EEF6AEAF5559E1ABF169AA9A","01646999D0D1059FBADEC52358A8E186","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0545","01199F4840E879CF90C93F2A3C032765","01824E11B5A82C46E2979AC1EB972FD6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0546","01D467159EF7FC037D4BC15975425DB0","01E07FF8FDA5AFD0F161A6916A487FF6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0547","01337CCAB01F142FFB043309C1BE89ED","01D9E65ABF15551CA1E4E850CAC18341","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0548","014D94DD0540F158FB57C393AABE6446","019AFB1E0C3E302F1A4FD4A872A06043","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0549","0158258EA1FD2608AB5B950D7F4ACEB8","018F0A6CDEB1D850B343B4AA3C6BAF47","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0550","0172F4A74DC5EAE3E3211EEB52E8E2D6","0175533E6936247A24A4E723429BE097","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0551-0552","01215F8B546A79060EE355A2E97B66F0","0148A415D0B4F9D30AE5AFCE60FD785B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0553","0130A8F30CE48AEDB0BA769B98F622E0","01C2B78C71BC9D738A4A98016B6166AB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0554","012B879B089D4682F35808BB55E714CC","012C7B5581572F1B7E656E2506297A25","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0555","016DA97EE5CBA9DB6AFE79095C8B67A8","01EEDA8D76433F3826EF1D55DBAFB6DF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0556","019217C84EEB33F8F15541663490144F","01DE7129878875B91093EEFB15F4ADAE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0557","010CA54F01885376F1BC40C9443F09C9","01DCCC15C2CFFBD8726C36AF07432733","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0558","01529AC7132D369E6C8153BF022A572F","019D0AEA75EFC29E8E40EC2CF0D2F52A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0559","017ABA62F8D535F93EC1748A6CC8930C","018F557B9267C9728DF25AFC88375EA9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0560","01D0CCC1F1497C77980638AB280C571D","01E0A9A04CB177D7C1B9DC126FFC24BB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0561","011AEC06FC3F1F97B6B511D8291BDEA3","016497F7069C0C1B3DEEC411B70492EF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0562","011020A8CE017867DBAEFE0AD14F6766","013C6F7BC009FB2C14B5CD427986C52B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0563","016D89BCB9CFA1EBDD85664CFC4F28BF","01E28F5CCACCC03267E34838C87F40A5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0564","011A24D4D1F20D578607BC06AB1C570E","0169E3418F2F19EE06D7E139133BC098","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0565","013DD6F8235429E6C462178C6BB4607B","01539D2AEFB11A47144BE2DF97712599","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0566","0142ABD5F13DC0E83CBD65CACA5B5B89","016739FA7498D8D0EFDC177C323DC489","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0567","0186A524B452BD06FE2B3514423D66CD","01E27A9C1791474E596B64F9FBFF6F3A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0568","013FDD18059D23A2022F75AD850AE91B","01D43AA02F96D9715FCC389EC237D9D5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0569","0196F647E3787E7D1D8D435C25682A43","01A2A6C89226F66B40054A4E11C68A09","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0570","0160F53AA8AE22485E9FE1A3B5626243","01717E8FB416A5B5B6AB7A21773907B6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0571","013D8ACC259EA3DEFA871BDA970004EF","017964C23B09E531380036E45A0034F2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0572","011BDB09582A077704EF571A2DAECC0D","013A79D63066295F6721AF900B86D7D6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0573","01405E2A203BD650AF23FFB5BABCA259","0196E4626FF74CA6CD5324A9EA119AC5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0574","01196A438AEA19420E2EBFA693B24A3F","01CBD656AFC34BFE37ED9AAF5A6C9660","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0575","01A4BD144F232B5FD61732389CA2C61A","01F3FD2303A977F8AE85BFCFF1A4B2C7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0576","011A501544AD16AE1BF926EDB16D7E60","01E2E90275E1D6117E1FC4EFBCB2E758","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0577","014F5E4309F2016B7C520C8C4D6124BE","017239CF21D05D985CE2E362A59DA3C8","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0578","01784AF43BDB59E131697740D9F749C9","01C5A7E5F1316C4FC792054221B3AC36","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0579","01BBCC62EDC5EFD02521156E8DFD4E59","01F65EB9B59FC85FD2F5A9BDB5C6439F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0580","01B370B0CF9B39814C9FB285A1DE7BAA","01F691898CCAF8B18EC7B7584B589F3A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0581","0141BB96199D04625C3ECCD6C377A54A","01438D96391F5059A791DD54559C497C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0582","0118B4C9F3738AD70982BCF1A3233800","012ECCB297F3B309984AF91FC7E42410","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0583","0163D2A5B396C6CE9F37619A295DD844","016B9E564AEEB38875F3CD83336826E0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0584","012FE2E13FB0F51F392900520178EFB3","012FF7557920FBA525E636A6B2EE6C63","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0585","01D31D3A897C16C7B6BB261C790A8AB8","01FD51C58147F6698BBF8E432570EFFA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0586","013DFE922200A5859E4FEA6FE22D2E08","01FB2A709E8B47A7A6108285951BF8EE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0587","01934C08AE04B95306C45924D92EDB7A","01F06F8AC2AF95397733F5D7FC833D60","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0588","010E8C8B4657B99C292ACFAB5E054D0F","01594781802807E4A112EAD772B47FE3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0589","010C3512EF011615AE08B5A0F5A18AE2","01A1D847941C44FEBC8CAD6AEE81CD6D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0590","017D7FCED13E3FD6F5EBEE434968FFA3","01D7F59588D2F21D4AF073A86EED0E97","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0591","0131E43B8F3B7E1F7CA44D4FD2845948","019532E04894BE1217FD71D5AA70076B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0592","019ADD607FAC29CCFB1F7000B6F0B1CC","01C7EFE68D0ACEDC6FFEB38920F24073","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0593","01625B46D4345A960398554960E1F0EF","017AF6F64CFF7AD017DB776E9FDCF93B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0594","01063D3B7A459A1960B574873CD009AF","015395E9D289D85143E3FF829DC467AF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0595","01A19DE721362B0F81BEC7026A251C41","01F06464DF9D98E3BE5F8A4432E741F7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0596","011F4079C2BE836A4397BF10DFB77189","019E8705241279BA567FF049A067A535","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0597","0181C78303E484735F45F80B309F77B3","01C65CE052D427878D7BA214B0FEF229","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0598","012BBC4A2210601C2CBC1BEB2AB380B3","01A23773A58813A23C918B720C8493A7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0599","011F86E82D6FB033A3728AB3D9A20821","01E281EE027BD7CDA97FBFF07490AF6F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0600","0150771598CCA9FA1386C8CF7CAAE2C8","01EDAFDF283C0E3E5329BECC28481DEA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0601","0119390DA0FFE0A164F2B3760794E0FB","014B962B7070DA78C91C4582405DFAF7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0602","010DCE4BECEE1A505B5E19BB0129831C","019F2B93445875DE45079688AF263FFB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0603","014695B0F2B5DBFCBC7A03C6ED5DE395","019FDF3B64184478EDC7A78DF1D326E3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0604","0111FB1DA18149736B19222FB0C4A0A1","01E3EDEB2B9B5ED080E3F91434B8E5FF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0605","01207A7BCD539CE50B1544D3CB8583B3","0175C3EDD1F83ECD543667A4A5A15EDF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0606","010B878577817EEBF329605E67824DC3","01F057E232007EE31E5CC9EBC15500F6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0607","0183BA956E2DF949FB2E214319A9A040","01FDC2A61BE20A287FA3C5FBC5F4C07D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0608","015FF2926021E3547CA1F5315A4DA91E","01E1789C081C5773459525805DD3F1B5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0609","0116E36C7C1FF430775A8F1B094B702C","01423DD4B032F187954986F03046B94E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0610","018AD14B2718E06FCC8FD3AE04D0E5B9","01EC01F52AA6AADD763BC047C59A9539","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0611","016B60B93469A1C699D34DAB3F52815D","01CA5228F2A7274064DF65F76BA1BD18","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0612","01CAC8F32305645BB022CDB9F1F5FEB4","01FE086949D3703F241B43EEAF4BE3F9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0613","015C31B9B2364EBADD1D4536165B821F","019FB982D1E089899459D0E691A72943","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0614","01504404B1E5B7AEF9AC9E53255288FD","0170192E66D245932BAD94179C879C1A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0615","013A71FACCB23F78B9336C910825E01F","01B17BDA706ABA44257C8EB44CEA537C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0616-0617","0196628E172FF577C928908747304A38","01C39B962D89A8056C280F5C53AA4E33","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0618-0619","0124A376C93414B16308422029BE7EB2","016711181F86C56184198107A8B1B2CD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0620","014E931AD85225E17346BEA135A657D1","0176AF1071F4DA4385E3EC0AAF79E0A5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0621","01C5E85A4DBCD5E098F88522E4ACDEB3","01FF0DBEC5FE494C16A5BFBB0692551C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0622","019432D6DFF23214B94AC29AC87B52B2","01A532FD0DE2B08102AB44F9787AB6A9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0623","011741406FC79BACD3B1C13EB30B853E","01993F9BFB22858B5BC8AF0AC8515D05","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0624","015B2ADDFD60C24DE90610C30F427C4D","01FB749C238A45ACEEE9444DC04BE7D3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0625","01B311F09CBF18BF46103A6B6D7B9953","01B31D6ADDEEDEA05C958DBC1BBFAB16","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0626","010CDD5C0042D54FA7BA6C6EA26266C5","010DE710D720BE30A4AB6817DECF3E5B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0627","0195D5A9021B6E9EFFAF0AC55974F935","01DE59024EC091DEBE4ECFA08A5810E0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0628","014F58F2AC03A1B61EC73CE42476E1F8","01EC1D716C02DCA253E31D3A5D20C36D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0629","01487F70349A520AECFBFDA44FC4C26E","01AF0FBD376861C070FF41A61EEE92A9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0630","0100BCD7BCF205B784EC2FD26A19A465","01AF190F303F9923D63B01083EA3C49E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0631","01A0609D0ADDD544B7B07FCE1A238E27","01FF054416CCC06B35E291724A8E625D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0632","013487E10453F3F6D820C2C9A96FF542","01E35CF64B08F3DD08E1C3A202F95D94","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0633","0105B163264E4581A4DE2E599939277F","01E58F0DE89BEC1891B16F53685F230B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0634","01266999C06F1F36BE31A19ABCC56A8B","01B85C9AF7657E7CB676E4A3935E1498","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0635","014D979D3B9289B763D5328F6846BCB5","016892C835463DF5EFB7A4F91353C529","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0636","013B179FBF51592750480D2C9919927B","01F7471FC574BDADBD57D16CA9C90CC7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0637","018F406B4CC441E964548BEBBC60D623","01E87175DD7C18E5C5FA6BA8159C94FB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0638","010FF686CE1C605FDEBA93787A633D61","017A49933AFBA16618C0096EA41750E9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0639","014D7FD735E513C363BDB6201C0820FF","01F4308CC79989831DCBFA85A1C12703","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0640-0641","0149635D84D269B43578215A80FF5B06","014CB31B469512AE67304AE64C2A8574","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0642","0185B6CAB5D7A16084F11BAA56C09541","01FF11A44402FB7E615760C82130FE07","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0643","011CBEAD1346460F0F8A4E20B0074383","0147F3187321624D43B73C65D464CC5C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0644","01421C0E478349B038A86473E0A74EE1","01AC2A9B988883C81A8B40D71D20F9D4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0645","0109DB86288598A2D3AF4CD477AE59DE","017806A15D182315F03686D7BD9573AE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0646","01E0B7CCEAF32A708F20880A05359EF2","01EBAA5744E1C88BC4C63DFD7A4DAA78","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0647","018019FFDA1E0C06D29271B2AFC990C3","01B473BFE6AABAED9113D75360449B5D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0648-0649","0120539057468B71AE1A38509164BB83","018F551209CB3D9F50F65921B0AE905A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0650","01451F027933100BE142E67765B629F9","01BC131EAA3BF14CE0AAD581C8A59A93","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0651","01341AAB8FA2577137E21496D2E4444A","016ADE70C44F0656895FC835AF292C95","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0652","01BE3EAAEF8FD7220B84AF159E8FDA8D","01D6E132612A02FD07D5D91C2167636C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0653","0135F0E85BD17FFAD0FC0AB864383039","01933455E651433AFE5B3304BCF6972C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0654","01595EF5515383D023051550499B7C4B","01F3EA2A5B38FCA29B828E2A19F5CA85","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0655","01F05366224EA4A7C8041B85AC412B51","01FFD79267B38B946762B575DA8060DC","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0656","01D3634F4F993FC19742733E6172A1D2","01F8156E2700659AD1B9E005FBE11E2E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0657","01BB4E3F9D40B7FE627B32F0A14F0ECF","01FEEA836C2FA04443C4258414FBE09E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0658","015A2EECB6F997E58B971DDD5E4F3599","017EB8D13251EBFAFEB0D2CDEEBF64E5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0659","0107B1BDF3D8DD5E2E667AD0D90AC1F7","01B1E0F7A0134D6ED55DB4E7E0FAD481","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0660-0661","0160EDE6DA1EE97DAB0FADF77C10CDE2","01DF9A73AA539A6A4441AC16A3815F5D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0662","0105D86A361A46843E24A65FCFDB3F5B","01DEBDE71AA7E6AC6670B89A240391C9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0663","014AF66861DA40F04E840F02196310BD","0160E51964C3F8814CEECE4A8564EA4E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0664","0108CB6C68D2169DC93F75F24BCC20E0","01EAD5F0FAFAA20FC6FDD7C086E30695","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0665","0161A0473A80FA6AE22E47A4D5D4BDD9","01AE72B0E17F3DFC763EDB0933A2008E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0666","01366A59F1EC5DAE2EBA473E9FE39E90","01CBF8333B24EBE49FD91A3168DD15CF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0667","014E78244F8874EAB07FA03C9477830E","01A3B985AA3238882AE1D45645C3EFB7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0668","010F4C2826D9C7DC2BFA69FDA415ADC1","017FE93CC0DFCC3CEB6242E8E806277A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0669-0671","0126A2FA3C22164DF0A9EB95998349AD","013ABC0489729523BAA273DDD79E35AA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0672-0673","0106565AA8AF8C8B175E2099D8554A55","01E0BA388CD18FF5EE51C8A0B4B9BC8B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0674","019E8548175BAB4AC73A6B0EE259B1EE","01C7EBECA6AA280425623EE8A755D84F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0675","011760944E0002C67B50606C1EDDB005","01ED37EDF7A8B09E7D7ECC52CC1777C0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0676","0110CA7CB1A26824094B92768B72F626","01A97EC414E6B9D3F0C20A92332451C2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0677","011D1D8F80824BA994ECF22E00794B4D","01D253009A4156E5D55CF596A190D6DA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0678","01EEC69368D94F689DB28B50BE9FF1F6","01F2B0B2D717144B98A57ECAC8E2B038","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0679","0126C4DC25352BCB8FC2CDCE18D302FB","01CE70B3DB930A0E07D8C9A234DE9223","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0680","017EDC69FB4953E49F1D392B50700474","01EEDACA91CABEEB1E30461B5AC8796B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0681","011ABCCE7FF704A1134987C9381FE453","0199CF079A275C3D6502744E1F9FA38B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0682","0116B512F11CB253BE375B6F9D1A4DF1","01BEC1DC1E365603C9A1F34A5203AB1A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0683","016041089623F059C1430DFD4415742C","01639DC99BFA73C1BD89B69E5D75B6CE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0684","01990B0BF37BE0DD67515AAE6027E7C0","01C3542AAEAC14324AE9F432ECDEC50A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0685","01A06E83B4C8414944D4EAFB97B4CECF","01A21489B17889130F5B25ED2D63F389","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0686","01A1633366696868B8E8B4B66E2D91D9","01BFE49AD49262F4BFE51C4976876EDE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0687","018BE6F95DB41D49A6334B754B62A954","01E1E7982C7D30F713503B6337A79754","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0688-0689","01BEBBD5B162549AF3F1A738360943F6","01C4D090385B1E48E69F9367A8DCCBFC","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0690","019DBA0836EDED58AB112FA7A6CD90EA","01EF7849D3DFA50329C62AAEFC27AB72","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0691","0192D8EEC8BE959ABCBB1050E0AF26F5","01C4D7E9E7EEDB2C8C811FF57C4205FC","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0692","014E74B3253E7AC260C60C2E726CE1C7","016AE7499A4B36DE74967AAE39181B65","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0693","011012D7160D574CB213546EEC0AA2B6","014E086B045D6A4CF049FC03A1B0648F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0694-0695","0121AE462CA220728E6487173DD04DD7","01EC69DF19534B2AFB4E7666135F531D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0696","0115E10B04E689E43D807BCB48C8E684","0161B5930D64896B3698E8170E80F0E1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0697","012E18617B47370407C6F580545F063F","018A2BA552B11CC325831C5829E1532C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0698","01138552102BE957D7D106EA02237416","0122DEA62DA2B0EFC7A50EA650D55824","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0699","0197F05D7485FA7A5BE930FD519BA672","01E86D710032E0FB8A4E92234B04C87D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0700","01995D63218D76C0A444960AB08ADCB5","01D724E5E046090F8847360B3956A5EF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0701","0143AAD72758786BAF42C240C82BF85F","014BE257E635D3B51336CDB730220372","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0702","013A0BCD88068C2474C6209C7842BBA9","01C705210854348EAFC54248BA482EE4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0703-0704","0171FDB6AA66F1C1C71E52F49A6501AA","019B93D2807091FEA62161B7F3B2E1D0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0705","011A11D1467C51885297BEA1677EF0E1","013C878262ED898982788866AFDBA53B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0706","011EF334A1F5878DAC969B2D975C5C9E","0151F34783E62115D851AEDEA5BBFB27","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0707","010970729EA8DA34D6D0ADD6C4FCC0A0","01ACDF4A1A6A1B9BACAF9AEB517F15B8","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0708","01160C0A461223FCA14B803999C77063","01B9872378DF042302B5C61A0CEFEAFA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0709","0107F990EA052C704D000EA613E98071","011E23C05DF15EA242AAFE0CC9643CF3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0710","014883EC107C372F451881A92BE75B6E","01B357CE02A83DE3A4D3E0C44DE16D0C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0711-0712","01F2C7208522D584AC48F29E773739DD","01F9349EFF2EB352576B06239703115B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0713","0163DDFECE4F9B9D9BBDD1C3218DC4F9","01946EF487B9339E9F437A8C69CAFB7D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0714","01521970584A867B2C85489A407ED5EF","01D6D0CE4DE7EB6FF07F75BF91AEF714","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0715","01281F3839F9C167EBC0E90C500A1E8F","01E68A9ABE6EFBCA99D8717B314A7741","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0716-0717","0134A7CE8E7585FE1F943D0026551384","01C3C7E7FDAAC42F2237CCEE8D1B92C4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0718-0719","01739900893E6A9FB4F49DFCCD467491","01E24F33D9CE2357188A51C84D73F420","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0720","019AD443DD29FACE2373D25E8878B52C","01BBFF1EDFB76F360E8AC44C50664558","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0721","015867A80D31E8FBB5FA03FA5F803379","01CA611F74EAD0841DB3817C6FD50452","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0722","019D394C31BAEF3FE5BAE653A1D94E6A","019F86D96446A0EE774B229DB9E9C70A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0723","01314DFD630E4D8D003E2E246A8FB607","01458C161B002F44A3AE037676107702","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0724","0124838C508E0A6EF0691B431E4DE939","0161609B0BD3A95476488D33433FB88A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0725","011439EC069399C29235DBE644C41565","01A31CB55665B8A1742F7B24CD82043D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0726","015E67C21DDA3E3E85D76DF6E615C687","019604DBEDDFFDC04EE4E5BC07C7B923","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0727","01982BF3FE2D349DC94C81AA03E16A3B","01E5810D6E525A705831B7F249F6F31F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0728","0134FDC769F9513D03884B184C3B8474","01913604EDD203CB3CB8EF8D9405CC78","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0729","0162D8F4C6DD019A9AFF0FC19670B4F0","01BD06018FE3B154414A43FC5CA06F29","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0730","017787AB0E4AD17C47D14721F54D5971","01A1F107D32BCAD79BB1214426FA22D8","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0731","010D35A572945A6446414647ACDE17DF","013C8FC492A94D57518D5A6F4334BA05","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0732-0733","0131752C78490CCEF74111CFCC6DB4C7","015EB9DC9CBA819105338EE47BB9EFD6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0734","016008E06C048D93C910F8BEF91EF52B","0189A268B377E7AAA01A50D60463C6EE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0735","01206338DD44330548732C39C9898CB9","017ED526927F046AB92EEBAC17992610","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0736","01818E92F0073502F31D955D37E59D8E","0196F98AD9CB86564728563FC852D224","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0737-0738","0141106A1E34C06A8380D76407F372D1","01A8170DE4B3744E99F652BAF9619BD4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0739-0740","01740D301664CC994E2774767C6CC8BA","01C5C3949889B3CC407EEF13097624E0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0741","01D77879D457F2AC7CE9764A5EABF214","01FFE2AA1D8016FBFC7567FAD3422E88","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0742","0154631648919D9452C7DDD081D65951","01FAD332C48948D9D5F2F60EA3F72346","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0743-0744","016E4A931CE4379D90486BB66C817C15","01B2EF3F66BA798CF28E7118704285D8","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0745","0165C1C102FBCA737CD716E4C74F5F67","01F7DF156ED778A5B7B9DF1D76B260B3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0746","010505557AB62F0F334BAD93FB293C67","01D7D2943230E0A362F28BB7D5043970","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0747","0134A989953EE55331EEA4B4C88C1561","016FA522EFE695EC8D2B20F5406A42AE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0748","012C70106E9761CB2E4312F05D4F2327","013421859AF35CB606A5893F8CF5CB79","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0749","01B17B4F3DE2FE7251021BCD49927983","01C75766F98D2588DE309F55B5AD027F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0750","0151BC4E6B5B7EA9383ABF9771D0E92F","0173793CB90A12F80B5A9B80F1225E82","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0751","01B162F68E01A9A6EC7EC41718BC0334","01C3291FC9ECA84F53EC6DC60CFA120F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0752-0753","01412E8689908AC0E032CB0DC91B6F98","01F2EA617A2830FD0DF622A0E5B4E8B5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0754","01E13ADF486BC5299E981CBB75DF9574","01F6DDAD42951DD69C8226FDEFCC86AB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0755","012A1EE3560CFC313F7C5D69E076BF72","013F7C8964CD3311BDA99091421C2891","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0756-0758","010CC33C83738B5BE1816E06A1B0FB79","01728A7E3A3E47F0D19A2E84D52B40CB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0759-0760","0181345A53E4630DBECDDCDEBF8A92EB","01C6F728BA0618067E7CB7B9085076B9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0761","011E0EEB08CE87632FB21DBB368AF7C5","0155E29B6B1B65DF62F287769B080931","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0762","0116A748C26B59FA71A99BFD2FAA79EF","01172C6CE09A4259ED382FFD81A4A11E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0763","01B4A7A245551276F6519788823E2D60","01C5790C084B60EA44FCB4AC30219DE2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0764","015E6B9E0BC59FFCE339C28E2832299D","017A3E8BF45A6D4CD135CA7A8938819F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0765-0766","010F9B8A1133847B8CEB1A79257CEF9D","0162DDF780B1C003D8880718FA48DB65","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0767-0768 (High)","0114CE573067A530B2672439300A277B","01262585BD65203A8835AF165D372114","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0769","0129E09178207BE8FE53C58F9D6F7E56","01E01CC2DCDFFC31C0EF530FD447EEF4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0770","01D2E279C32DD15835EC16E2F3D3B0FB","01D80B17931E38658364310BD16F8BFA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0771","0143053BDE5FE1EF59EACEEDC1024A96","01DDE10D1E165421147E3B9137B15516","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0772","01188EAC9079CE45BA48409E5D0DC617","01D3D9F44C41E759AEA2E43BEB180FB8","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0773","0140F64413ED8154715044EFFA4C6DBC","01CE1750DECF954F386D907BEEE8A084","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0774","0147F5708EB9017D13A442BB46F75E77","015DD487C40FAC0BBBE57DC1C32602BA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0775-0776","01556C85BAD1C7ECAF21965C9EF39CD1","01AA8404ECEA9EBB446977EE9E308261","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0777","014940406434BA7B331A890F17E5A4E4","0190EDE593AAE35F2BB4DB0B502B3A29","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0778","015D8C258F267F4FFB925A1BA05140D3","0166C31FE604DCCAF3D8516BBC6D6BF0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0779","010494BCA62C248ED17298891C5B8FB3","0111AD6C0B52D5EA87C854C6B95A0E78","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0780-0781","01236434B32DE2735236C07E2129C50A","01A1F1281B2849D0BEFA12FEDD813F2D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0782","01EA5C943C3AB6EA9E1DC2AF7C352A8B","01F8AE977EE16043673AFEDA1F040DD7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0783","016A712A246EA22F747C859C41EC9FF8","01AC5276059C21D3C8444FC965885DA9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0784","01175ECFD976F119F93651FB69518BF9","016DF4BADEC1F1987780BC7A97F9F9F5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0785-0786","01108E81657F5FDDFE07806F26D8C9C8","01AE1C3A9DF92782A37F536B8FAEAA73","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0787","0101668016F68201E1DE902B7B3BD405","017C85A24795A05A2D425BE9067F3A00","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0788","011EE79632F3450F748B960C5C0FD35E","01D5E807FD481CD4F36602BDD73E2324","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0789","017FDC063B80AD6B76AF635FB23C4AEB","01F4591ACCE7C655F7EBB222BB35CC69","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0790","019F0C3919379CA2A9964B9DC0335110","01FFF828D20AC20FBC46EDDBF6936EBF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0791-0792","01303A83ACA1D50A22EEF083FDDC1273","019FCD20A1B623236C7917F3C322A000","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0793-0795","015DD2631DD75A3AFAD94A72003DCFA7","01CED8758CB2471DB965A29A872A3E16","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0796-0798","017975CE66AC80239C28B5632F819EBA","01F1467C227A678A990547B58196DF5A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0799","01A35F7D4A3B8775ECC4D1F486596DD4","01D095BEA29226BF600C6A51E99E010B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0800","017B0C62BD790E165D6EB9F56DB10744","01D4860F7B7EFBB4A11C50883E5CCDC3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0801","01B06F3B1E8A89F18F67ACFFB5E5E35A","01C490A27EED0BB557CD91A099D5C3CF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0802-0804","01494FE7130F7036E5D8B269B054E7D5","0197A3DA88F11D33F5088D40266DE48E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0805","013DED50ECAF324351680E680845F9E6","018E7EFB95EB0916122B1D3FF6C89439","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0806-0807","01A2DB43DDC2ED6652939254D7509F87","01B3284A595854CC24387CB570612183","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0808","01A6AE04333E98EC67A2B90FCC0F9A63","01BC4197B84B745BB832C82C583529F4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0809","01D2AE72BAA1964FC202C90413A3174C","01E93D154CD964675A0291F4F06802E7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0810","013D6DBD55EC9139611AA94FB22DEB87","01C4E7DE76032D0739E6EB92BFACAF6B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0811-0813","01A6ED22E09B0C61E0E894677782A239","01C83B9A79A2D4AA5DF605154502229B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0814","010590710A3F937EB8251BCE9037F8AB","012C9982B9ACBEA744752FD914C747E9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0815","01A75EC893B771D1BF06D639521C6E75","01F08859E484A8F53DABB093CF402F13","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0816","0102089A411F9831A81443CF562AE24F","010A52696752917FD55A62CCA9F2058B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0817","01282D9DB4C3B247FF24A74235006856","013B7EBD5151E2B6DCCEEF706A75BD08","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0818","011EAFD32BC3364849CC84F731276A52","017DD830BB02481BFF8637E8A819369C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0819","01A7D8F5C012A126E71976DFA6A69E6E","01FF8CF4DA3465E35A0CC6A5D7BA32D4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0820","01244F193E8F5F3AB7F387838D34BFAF","0148301FE7106E0F911CDD856ED99AA9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0821","0124D625856B9A359557F200C36C20F0","01A272D8217E7D598E465A181BE43734","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0822-0824","011706BAD6FC19A0F82C2DB0A76B9159","0166661BCE268A3178BFA5236FEF46F4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0825","01357CD849370F4A172BD943451FE6B4","01E09C16F2846C46555213A7AB078A89","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0826","011A9829DD6E60F8BE182A4882EAF93E","01D64FD999BF5167B5CB3A096CAF4FC3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0827-0829","0162041423D36713D42A487912D6A225","0193365A1BC7AD1982C4F78F826FB382","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0830-0832","01296B6B24C38AFE7DCDDF9A12522B26","0158B7297BFC62B638C3224453BCD0E2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0833-0834","01269870C93BA30F725724603796F8FE","017666F1CB6BA0A85EEA665BC022D0AE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0835","014E86D6BD4286FEE473EC57587367F2","01D6A399C2605C19C14CB55BE64408D0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0836","0140196F2394032EFE2FBA1AED7D0FC9","017816277EABE53FCD6A910E6518F7F5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0837","01882E8022338D9D7EAF94E75B19EA8C","01B75181D1C02E9F3612094C00A0332B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0838-0839","01764C27E26D66AE8655F92AA4315343","01A904FD8D4B558341C396714729CBAA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0840","01067F36BCC213919EF14EE4512A9168","01F2F7DE16E0EEEC8BC9E52790994976","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0841","016FCE873589B972B238EAC7220189AB","018F8BEC8170A0C9B0AE7E1CA506E8CA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0842","01708D99409B901485052582D9D25FB1","01DF1EB7BFDEAA245BC4703876AE4AA5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0843","017B83D10654AC54A91EC88CCDBB1F3A","01E4697D5F927E28531335C748BDBC56","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0844","01362ECE09C2145375024C3401B038E5","01445193C5622F1538DCE90617F4A281","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0845","01D18103D4A56B2FF588FF7622CACBB4","01F75814A4F7BDD1DFF9AAC1B8B08995","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0846-0849","010A1DBA635B790F53C6FC0BB82D22B8","01F812F4416ACC7CA376817D3D214573","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0850","0104B096E5766291BB33A43D3D84818B","018074541C8331661660C2B91C3B0485","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0851-0852","013D1B431D2B129506124324FC27843F","01D31512C2C1FB60074B7D9471B7B5DD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0853","015815FBF233497A852248AECC2AD894","01798BE292A44D1B825CBC07A1A92998","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0854","0162688EDC2692044347B4C2D042D932","0177FADE315CE89A775CD1AB71F48D1F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0855-0856","013E5D266F98E0E4BA51DEEB63949B4C","01935D9820EE9DF4858BDDEC7A36F27A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0857","01002542B0D746E9574F530CB7A01879","015240A57D2EA2D411CFA2609493FF7F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0858","019F9FF19A8808B484AAEC973EC632F5","01DE9CBE6384981AB6F497009BA343FD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0859-0860","0160843783D38DA64A32A35C10E95F8E","019A4883A109C97A8A91C53564D294CE","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0861-0863","01BECD23BB2BA6B32AAF7D02FD3AD9D6","01DAD10C5CACA29498C2A3496900F0D2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0864","011FAE984D4239F67E3197A56E6E8B1F","015BEA542F03A7DEBD40C6C83B835CD0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0865","010EC5DF81A47D7B35E364DB0286B38D","014C231A3F4D8ED66189A008D6BE59AC","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0866","0181644723CC0B619C843E94F9DF3FB1","0186CF4D27D784DCBC9149FA45EA51EF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0867","0103C35DB787348230A5FA7F97887BA6","0131AEA501B09E8749B0F68991EF4538","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0868","018B7FBC04AA06CE3B87746A5B55064F","01E25A56685F14707F600B7AFCC408A3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0869","010FC500A34E29F8D4F20F849D24167D","01C94752FA9E07B9CACF5C1BDB701CD3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0870","014F4D5995A52BAD57003BC299E453F7","01FD443C54431C10C23F2479127E9609","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0871-0872","01318BE3C32ABEC748B143223E421F71","015683460D89CF3616DFE135A3AECC92","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0873-0875","019E0432CAFC6F51A86A80B85868846E","01C88F78E035E50AC5454EFD84354580","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0876-0877","0140AA346D76225BAC4320B2E4A6883D","01E29D9F775424374223E006EA7B73BF","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0878-0880","0145300F9C6A04E10EE27C6B45A9746F","01CED08B797A882E66ED900C302C3F22","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0881-0886","01C9D74F9D2AC23742FFB0DDF28DD890","01F5760662EABE073CDBD655E81D5CF5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0887","01592F6CF2E6D2CEB5B023ED7B3DB768","01E6AE16DF74E071B44CB5E6135A3875","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0888-0890","016FA758A5FD41BA9757D26600661FDD","01FFFBD71EEEC84292194F59C1AE8C35","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0891-0893","0182506132D5C42D898911DE2FC8E20E","01F7AA219DF03B306462A9742C13E7CA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0894","0153E38C981DE75EF937FF0A5E4D3E35","01FC66A3E0467C4A8EC59BF968D2F133","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0895","0137BE74FDA5DF7CC4268BD46A70FC4E","01DD84F796ED019DEED72FAA460B62B4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0896","0196C918EE5DAA4CB4CEDE3FC36EA29F","019829A61BF6891AF3496006CB7A9227","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0897-0898","014241152DABD4B60ABC5816CEE1417E","019E9B714DC34B87388054423FEC8167","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0899","0171ABA63ABCB22DD39052088B9B0E14","01D85FCEFFBA040249D0FD61210C252C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0900-0901","012FD7E7C0496E485D16796E87322A12","019FDD88B2761291AE473B23072748E7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0902","0138872865D1A708920CE687813953F2","0139D006CBBA38F7F9CE8AEA103C095D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0903","01DF111C519CC6ABF27C30574B3405BD","01E055E3FFD73824E68FF94AFD9470AB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0904-0905","017FD330B167DFB68140C5FB5C9568AD","019007F0F583B54FB0E344BD7CB23E6C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0906","01A202BC3BDA93D933E3094438696126","01FAA64089CD85A14E3D9F65CB7D950D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0907-0908","01C274A79362E9D34711FC55D55E432A","01C2DDB7BB8068B253FE087C9B6DA9F1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0909-0910","019C6EA04C3648025A7C6421D38391AD","01A093402E7C86841FF0976DE9747406","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0911-0914","01055F01B835B9E22A70C00F4506CC1E","01F04D7E62919092320B205F5FC1CDEA","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0915-0917","01519C01EF10AB5923C7DEF7CF451AD1","0178A29EDD3726918889CB57C86BEC60","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0918-0920","01903AE5E5B23C9A5AA94CEF21515929","01D745557D2D8E39A360BA6991107154","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0921-0922","0140475FCF05578FC1534AE1012A3E6C","0146DF88F666D7A82A0C6993869E5D19","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0923-0924","015816A392487668D55F25DDBDA7C372","017999550C7E510079EA2F7385D40A68","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0925-0926","019B6B0E53931422A906687B7022A0CE","019C316BC6926ADA711EB8BC46071961","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0927","01698ECEA56E44E858B5001C65223773","016EFCBDBE78119FBABB3400F579BBEB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0928","01581755543FD36EBDB20BBC01BC6631","01E7D74B14934BC43D3B8DD34618B277","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0929","010C0CD447B7CBF6965F9170562F20F6","01F71E70719574F7F55CDCCFAB64B0F9","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0930","013B6D40EE1AB3DA18D6E6610C858DAD","01D89B879D7407DCCD764666375A9BC4","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0931","011C5DE8171A9695B0520737183C0764","014836903D604574382F05B733ECC80D","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0932-0933","013AFDEC9FCE9811633541BB297D6A31","01A6507F4D6EA152B6D6D15DEA8438E7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0934-0936","01C78FEF1A1B50D8078AA7ECE43CA83F","01CE1A263791F67AFA794CD7C9CC2D7B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0937-0938","01183D63F171792FE6CE4CDADA65B869","01AFCBFFDAB1A380DE71C6A0BED9F5D2","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0939","01285979F5130214FEF7EA318B17BE50","01828B0DFD8C4EB651271D2476EA41E1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0940","0164A85D3DD37F489487BB34EA3C971F","0175EE5CAA89C22F49971415D2628DFC","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0941-0943","011C6E8D2A68E4026F432C1FDBD5AD86","01418786671986A64A643046489E8A14","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0944-0946","017CBE1D96DC15F458694A6CC1DAB180","01B7AA5E0A74E22F6A5C58A339B211D1","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0947-0948","0161AC18EADB56CABBC756804A4A9941","0187694299147CD57FEBF35D7FFE260F","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0949-0951","0141327E255C3A13433042918367AA9C","01EA8B13B98E14EC4215FEDE05C44727","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0952-0954","01D3986A649C4593CF9A19B4D8E3EA4A","01F356138F798D2FA9AC84B3DFD26C92","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0955","0145CCFB3CFD657AA47D68857C73808B","0187CDB41EB378C587B76E9CD566D8C0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0956-0957","012F07144A72589BEF23F77C2919D01C","014F11F503B94F47BCC76381C94217A6","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0958","01858F2371E6FD5D2B022A862C9403CD","01C7E4C843A994F4D1E403D1DC069301","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0959-0961","012154F06AD8C10650176D38CA037FF0","01EA79B38EDD5146D5F476914A8E71BD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0962","01155074C742DE05033EE1BA458A9425","015B548A7412D0EE0ADAB5E2DCE23EFD","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0963-0967","011CFBFE38980EECFF0A34C6388CE105","0163ADF771C4E12D63D3C9788E2FDBE3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0968-0970","0105906605B0B1F3486C3C8CF3D57D6B","01D6B0B146317ED757EC77F7DB2BFF28","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0971","013691ABD953028C3F53D6804CC70AE9","0150B09A0E3882C6F8A5E1AAF5E03B0B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0972-0973","0125417F733714AD6039B7B11F310C6B","016B64AD420E45930EB2675A84E11185","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0974","0146A06271D0F045EBB5F9FBDB2CA380","0199BD0C5E50BEB3391B3BA83E20460C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0975-0977","011530FE3D2596A1DBF9B21DC0C768BB","01F398CC38FFA11AE6A27DA61479D2DB","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0978-0979","01030E4D425BF53637B25750A7D2EC3F","013753A38766C7184F81BE47535374A7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0980-0984","011434D104CFA9756DDB849B1C7CA6CA","01F237DB76339A845B8D23936B8161B3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0985-0987","0176EA31FD79529A42C9E966CBD37ECA","01B8CD4E7BA416EA9FABE965D9F0D53A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0988-0991","013A02A0143E2E6C70448EEBEE4AE013","0172EB3632373F14D4872D664B0356D0","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0992-0993","01409A21C0503864B6F3013D3F92DC02","01580E49C26E88C02076AD62914EC02A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0994-0996","0104A8440AFAEE765A1F31C7367B5D82","01A787B438945DA50535AC583C384183","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0997-0998","01828FAD99129D943E92AA8D2B2C72C1","01F1ABA1A836A48B95926B8850C6CDA7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","0999-1000","0188E600659A5FC4DA9DE8ED6300E542","01DDCF7F20D3F3D8FBFC7DC191980795","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1001-1002","017DA7EED6877ECE524C1B3C4986B048","01CF347986890DBA777C4C82C82910A3","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1003","0149FCF072B1E749E71ED0979D875CD8","014F7DCA1C9B2157092412A48B32A1A5","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1004","0113ABE207B0829CBBD35025982A7F66","0171F3D4D3B81286D4FD1B096E06998C","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1005-1006","01581FD78C224E87707122C4FEADBC07","01D6264DA2D1D946944131F4692C2874","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1007-1009","0109FB92C942C66AFC32B3687428C6D0","019BC9FACE95D1842B0CFCF9649D84DC","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1010-1013","012E357594FCD55C23DE9B211BC27C8B","0170F23CF35057B264F6163C0CC7743B","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1014-1016","0183D94237D2A1462CF8884A2C58566B","01D2027538B7350A8CE3D2F9769B1071","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1017","011763A76D06504E23FC3843EB35ED62","01FB54D501D5628BB7E7BDB128FD8A99","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1018-1020","0161F31183C82FA6B3675AEFCC73D858","01E90C213C988C624D42B2EFBFEA3CD7","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1021-1023","019D0859B90DD978F84DF3C7F8A725FC","01A5C5922845AA40ADB38740B5BB205A","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Apple Quicktime","","1024 (Best)","0137276AE93D501787EB606694966C4E","0137276AE93D501787EB606694966C4E","","","Apple Quicktime"}, +{ ENUM_EDITOR_SW, "Corel Photopaint v8.0","","high (comp 12%)","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","","","Corel Photopaint v8.0"}, +{ ENUM_EDITOR_SW, "Digital Photo Professional","","01","01371CDFD05D688A5EF29310462CEBFD","01F098E22EBE7D3E0D31DD1FE0B14FD6","","Digital Photo Professional","Digital Photo Professional"}, +{ ENUM_EDITOR_SW, "Digital Photo Professional","","02","01264E8FC69DB0D4E823310AC4A62F5B","01FAB2BA2D9A80FB421DC6981F422A94","","Digital Photo Professional","Digital Photo Professional"}, +{ ENUM_EDITOR_SW, "Digital Photo Professional","","03","01472DFFD69C61F0236252CEC3D93A59","01AA29A71CF32688CAA00C0345252BE3","","Digital Photo Professional","Digital Photo Professional"}, +{ ENUM_EDITOR_SW, "Digital Photo Professional","","04","01925341B1402B2B890C20539B2994B4","01A506A5268ADF6774AD1DD49F250957","","Digital Photo Professional","Digital Photo Professional"}, +{ ENUM_EDITOR_SW, "Digital Photo Professional","","05","012D821C6AB210E2A753BE053B8F55D0","0182408A81A4ABF04D4A34A8A5E98C58","","Digital Photo Professional","Digital Photo Professional"}, +{ ENUM_EDITOR_SW, "Digital Photo Professional","","06","018F43694F4E9A49C24613CE0DB777A1","01BFD6DFF74A169EDA4F585691B1C832","","Digital Photo Professional","Digital Photo Professional"}, +{ ENUM_EDITOR_SW, "Digital Photo Professional","","07","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","","Digital Photo Professional","Digital Photo Professional"}, +{ ENUM_EDITOR_SW, "Digital Photo Professional","","08","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","","Digital Photo Professional","Digital Photo Professional"}, +{ ENUM_EDITOR_SW, "Digital Photo Professional","","09","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","","Digital Photo Professional","Digital Photo Professional"}, +{ ENUM_EDITOR_SW, "Digital Photo Professional","","10","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","","Digital Photo Professional","Digital Photo Professional"}, +{ ENUM_EDITOR_SW, "FixFoto","","fine","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","","","FixFoto"}, +{ ENUM_EDITOR_SW, "IJG Library","","001","017B7355162223C173A4E4C88F05C9DA","018EAAFCAA0AB2E88D21C57EB8C43B91","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","001 Baseline","015E8EF249156A7517F33D04EC88B72D","015E8EF249156A7517F33D04EC88B72D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","001 Baseline Gray","01297F26422C08EAC152895BC06C7499","01297F26422C08EAC152895BC06C7499","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","001 Gray","0163D6CB88C86210E76F0E31048B0BF6","01A6E4ED4705E839FA28074138B05070","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","002","014DD72F134192F5A8218CD57E7E92F7","01530695A44D097615A909810255552D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","002 Baseline","015F7A9618EB2A868C7550DA1329990A","019EAF74910A2D5AC97092B7AF4836DC","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","002 Baseline Gray","01486C07E83005735F04D0A4A27068E8","01C14F2467E51D7674E2DD062263F7BB","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","002 Gray","012598FEF5AFB0C3E676833AF10CCCA9","01C5DF373FF773BDAFEE6185D00369C9","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","003","010D93534ECBE41A03AD908F7C2F65D0","01225387EEF2A87E35871B03DD67611E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","003 Baseline","014180871C124E13E1D1ECC15766B3AD","01B78E9757D16F4C222B8FCDB3E0009B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","003 Baseline Gray","01A263063939FF920070C72232265CEE","01D1D80702D2418283DB0B64B688F06C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","003 Gray","01179B1DF96EE5FE56253A215543EC1E","01BAF3E5B99E4B484E5BA182B172D98B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","004","01E8961863E6A06BD0F830F728EA4280","01F7A160536DC08D336A2F1631F7F3DC","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","004 Baseline","01A97DA12E54D66FBFBCAE0D5E991CA7","01B75FA66F48AA9134AEB973912F5002","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","004 Baseline Gray","01351162C4FB4ABBC45E7C31F97176ED","018BEC3F23835B6B6E1CE317E248E55F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","004 Gray","011236A3C64BA1BA9F5FFB1C8AD211E7","01DF43FC1624F3D0509022EE7B4D153D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","005","0148D4A3A57AA9F4CCC1A1ABE2B3EBD3","019F85C1F6EA55C6C11B0816CEEE394E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","005 Baseline","015D763BE94566375ED64FA6BBC90CBC","01E9BD6C6EA39F1EC280CCAB84E9F838","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","005 Baseline Gray","0127C219A56CD59294E419F50B3CD5A4","01B7927F22D541B45898138DCCBCB8BF","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","005 Gray","014403414AAC4820C77EF45FF0983FA1","01DD93A182BEE09075A38D13E48CEEB5","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","006","01557CBD43FA30C074C5F867B271E4FF","01C74923F623DA3353728D4F65A65560","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","006 Baseline","0178C88CE971F4895B97F162B6F4D9EB","01E5D4A5B704442CFB9AB125C61B8380","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","006 Baseline Gray","013452C3086DA41E7287EFA1BFA8B2AB","016D6A0A694A62C56E5743868BB0D41E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","006 Gray","0114BECC99AF2EFEB4E15210F5371B75","019844D405FFF1D861D36BEB52217DE2","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","007","01B8C90AD9A893E6C04A131099DFACA7","01D85E50FA0EE5AD5E0DC4E56D3B433D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","007 Baseline","0164AE108050FA4F61234DC514D83948","017D8F5DD41BE2AF4D193065A10D9C8B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","007 Baseline Gray","01012B878EF734B659BA1CFFC2B5D2E1","01501DCF3CBA9EB2E717BEDDE3219788","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","007 Gray","015A4FEE9D68729E5C58D9026790CD83","01EC84DC35C178247C3E04B54D808ED9","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","008","01D8CA571F91B40B212432DF0B1293AA","01FD4538ACD2D3959E31924320F447A3","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","008 Baseline","01B366D312409D49FBD66A7271A7880E","01ED8C761580D6160951141E756C4373","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","008 Baseline Gray","010BD1B6B651D091E4611F312F853D55","01E0F07D87CFF3B690BB7BD4BFD3F0D5","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","008 Gray","010E8D52A10CA78D233C33E2B2CB2511","01D0F02822F32FFE1F21A1A5CA33CBBC","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","009","0165A32069B4C1CE7B097FE2261689E2","01CB76360C6CCD24100452C09CEEB761","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","009 Baseline","010A73E1E045C32AD1C406E7EB3EBF09","01804FAAD1B26D898E85F75DF30C2F22","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","009 Baseline Gray","01735AE9B21723B1A0B1086693F921F4","0193567FAD350593014BE7683825EFFC","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","009 Gray","01376345AA246B6B1E13EAE20EAE4CA5","016CDF096CA0416A303787481AFA38A1","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","010","01A1BA2ACAA09A184A268313A90E5EB4","01D0E8A480D3D5EE22490A21A32F430B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","010 Baseline","0196F2BCA047EAD712F1E724146172C2","0199D6A2E65FCBEB7FC729FFBD7733F1","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","010 Baseline Gray","016431D22F1312535059CE905D3B7D36","01D9554FEA5607D2524F36810B49C6E3","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","010 Gray","014C3AFFE67BA40C08BE705C298DD947","016800F71365CD51678A09C7D22020AD","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","011","0104DD1B8565682F6243C8B6B495538E","0113AA4194BAED61D2EBFD5D249A7C3B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","011 Baseline","0136A16196FF2A6919912E549E28DB1F","01B321156125107374C0494726A4E615","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","011 Baseline Gray","010D74B305577D4C0EF9A4FA81208E2A","019ABE12869B59CCBF0D08884F809733","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","011 Gray","013EDCA35DC95867FAEF6504D946AB88","0173CA54240C852D2162D2D60C70BD1E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","012","010141597D7D13E15FAFCBE3655018CA","01A1ACA48E2530DA49D13E6A1A00D351","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","012 Baseline","019F0B1DA2B01FF4A8215F8BAAB61652","01DB6989B11A4E8962133E089391A871","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","012 Baseline Gray","013BE7534F6F10E0DB3569A5DCAC59D1","0195CA1CAA708E6D5202211255BBAA7C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","012 Gray","018F446D264CD997BAF04D04B05A91B9","018F616CE930D4500CB63FFD1E2F97EF","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","013","0108C12043C674298E68F922A4F9D8E3","01F32CCDBCF6D70A6F162E68B71B9292","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","013 Baseline","01FAFD5D6C3FF57FEC50542A8049FFBE","01FB327F2708133773A7C1C2ADF015C8","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","013 Baseline Gray","01A9A53936E293CAA737CAF361CA4EB1","01C5522783D57656739934F7FAD62AFF","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","013 Gray","010064FC378FCADA298C6E19AE772386","01F924075E607C892E5ED487B66C33C5","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","014","01B8FF4C5FB2480CC2FA203338B3FB49","01F2515A4D47E94F00444E125569ADEC","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","014 Baseline","0111ED3FE874F467004F42442A4D5EC1","01D0B329A0D3E31ED35C294BDBED9B6F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","014 Baseline Gray","01DE5FE34EADFA8BDA32D377565E1141","01EE3682E1D03DFFFB284257ABB9C199","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","014 Gray","01CA028CF12DA7C6A38D88F9E80D2B75","01F385384D8FBB00459FF944F49EF187","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","015","0105A3D95D2D36DE9351313E30D8E945","013C3A43642D2E8325A76C3818B3C324","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","015 Baseline","0137B43FA77C7778CA3ADF9EACBE244A","01DD0F98215EAF68D95CA29504642470","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","015 Baseline Gray","015F641253537182AB95B7377533CEC9","01782BAC6D4C5814864EA1E787F1DD17","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","015 Gray","014FAB780D8D2E126D37C285196C56C3","01B81286514AF4681D5269E7A69FB780","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","016","01382B45F768D75423502D2E8B4FA067","01809D564FFB50A4B041FA568A15C9E6","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","016 Baseline","0120A091F04D17628FED6C97DEEB280A","0188331717200FC0BB9554D2A03CC9FE","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","016 Baseline Gray","0113DF3F814D89D622254D755BAB04CF","01C825971AE124C75253EB75D5D58FB9","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","016 Gray","016709ECACA8BFACE513721F290F23EF","0196AF8D3EAD94D6E97505361B1F1358","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","017","01DC148567DCB4285F93B78611674D07","01E94E7F685174FAD107E3ED5E42BE92","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","017 Baseline","01758F4E39DFACE5EA5D12F9E0B34014","01FB6608C70A5EE84888DC0BAFC6B5B5","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","017 Baseline Gray","017391E08342C2EC22792EF337EF549D","0177E5CD64BA1F01B9E7CEB33B14CF35","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","017 Gray","010153C5A5FF4AF26A0091FA8B9678B0","01552F1E4906CECE8137F1BB9BA2D8B7","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","018","01057FAB300BDD64B97BA4568CB14B5D","015C51EA21C7499D0C90807ACE472F04","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","018 Baseline","012B46FBA4F602C5E2A9E53273F92CC2","01B34903143AE2C4148C20975CD59793","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","018 Baseline Gray","014B75D8C642D3B15BBAF66297C036A9","0162C12D22B2E3019AFB303E26DA4045","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","018 Gray","017FE7B01030048A75A0A5A3766C2398","01EF118D91165F6B8109179E315F2197","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","019","01F28319610130A4962D2F2471A47B44","01F9DE9286B554D02751D1F9BC1FABBF","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","019 Baseline","01371CDFD05D688A5EF29310462CEBFD","01F098E22EBE7D3E0D31DD1FE0B14FD6","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","019 Baseline Gray","011BF44C288ED88757E92D649BF545C6","01EE49101C014F8EAF5D98C5A39B6A7C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","019 Gray","0161AF5C8A6D83C8F6BEF3334AFA19FF","01DF20D95132EFD134BA9742BE28DD2D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","020","010D756CE419BC1DC5A66488DA103E59","018772B3B18E10C3B6A30048454AE64F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","020 Baseline","01992DA20A6C319816DB7D1B2930DE70","01C26E64C91D1F3AF498FC128F3DB745","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","020 Baseline Gray","0189AA319F67514100ABE60A7A217A0F","01DB8A3598F8CF5C597313B21AE58C40","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","020 Gray","0128762025414333A77880F582836FB9","019F14524F3D4172188A4F25CFBF7015","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","021","010B8F48DDFF29779D862905F7915174","01230BD3DB98C5BF6519D7E6F7814119","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","021 Baseline","01031013E022B4BDE27ACB2BA5506995","018C081C9DA097E46EE51742F0DCAE8F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","021 Baseline Gray","01257B6D36CBD8F417A2DE61BFB93FF8","01935FA65F1AA4AF2852C9166E38A46E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","021 Gray","015A99179502B880756AA0BEA60CC4AA","01B5750AD0FB01E2ED32BD82C1D81DA0","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","022","01DAFBF5D1DB29911AD6E3C28B177C52","01F26E0C642B9F63BF509154038FE4B4","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","022 Baseline","0156DA0F6CB05402768A8D3DD04ECC6C","0163FB39B3ABD9B660E34373AB7D493C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","022 Baseline Gray","011FFEB512FB1C5FEC87B20A0393C51B","0174462842394EBE92A30BF2C0218121","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","022 Gray","0144B39F0745FE14081460A17C9F0EDD","01790532CABF49AD76891FFD62356BC1","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","023","0127817626115968C5209E0DE893658C","018A1898AFD039F134389BD9C3BD1207","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","023 Baseline","01E54E7B9935A1823BD7813756967A82","01FDE410993C16AC3DD3215B90356FBB","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","023 Baseline Gray","017847DED0D72816ED793C0653399846","01F861D1354732586D40BC1FD35DD41E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","023 Gray","014822C68A0E484A993E17FCF585C83C","01B42FC018510E940575716D9F2CC132","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","024","01AD1431E7E7E855D5882888C08FEDCE","01DF495B594519EB683D744308BFCC3C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","024 Baseline Gray","0199F8E5AA2715706C5D86E6C063AED0","01AB425B0BB561E5D81F73461FCFD53C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","024 Gray","0199F8E5AA2715706C5D86E6C063AED0","01AB425B0BB561E5D81F73461FCFD53C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","025","01E1BDDF6C45DBEC46FC48B60BBF6018","01EA5E13EF082CE6D445C4AC8ED703A8","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","025 Gray","010E9D90B70F67A74998A33E2617EFEA","017EFD436979334F7462F6D419A0409F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","026","0151A009EDF99BEB2F36F3144CAC3AA8","017CE6C1F0D1E4AD2C6A76454B0DC6D6","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","026 Gray","01350FAC262F271A402061E7A92657A7","017C4553F75B9286974C886AEBC452CD","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","027","011AA95A067A44EFE4ED594A7A10A60D","01A4D8C74D429DFFA9E7E8CA28A5037D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","027 Gray","013E02157EB5DB737A047347048D690F","017A7F16CE910CD41DB40D254B8E3C00","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","028","019086A16FAAA8C9EB3BFAE9CC6F096C","01C66E4A63F60FBEE086C72C84BB3BAA","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","028 Gray","017766E2B681D23724D1C8D83AF21ED9","01EF36845FE887FDA32AE0CEFE9301E8","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","029","019420068645B04E0AB5B600562E4D34","01D3E4499654186CEF7A4B146040D88F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","029 Gray","010EA6645EF02F7CD84388BDB49DD441","01812B12E4C29E5CE6CD24A08B080E82","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","030","0167A32FCC8F153A51B2AFF207149263","01C530B87D23AF05C825E5F17C117894","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","030 Gray","01B864B56117822F710C17F001F5F51E","01DA9F3B7A014E2E21DB6BD7F2400787","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","031","0120240537230FF485E6F7B275736D66","0168C32A593FFC45927D116D1D8C8D5A","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","031 Gray","01E7214A25C754357E0BA14BBEF0C3C5","01FF8A40330C94B23ABA5B8B776533CF","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","032","0179A42A607F414795D1C0AA4F7812B1","01A7D58273508268F0027B337E9B9B45","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","032 Gray","0150F18D85D9427B5B10534D4C691403","01A1EF24C114372F78BEC3686E4DCE06","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","033","01305AB319A9D55BB8D687C882D81F4B","01F713F3A15722B9E150D9FDC208057C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","033 Gray","01790540992153EBB158E27DAECDE058","01D877F04A272A12FE8F5226CB015902","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","034","015246209B28B1C08EE92BF82AFD7252","01816E05E735E241697A1F2B1A8FF6FE","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","034 Gray","019899F0FC9916880F066BC0BE7856D5","01DA91F2DFA45AA049601EFDD45D53B6","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","035","0183F20270F106C2C089DDDFE2D6C626","01E3AB977A4827AE486B1D7E3940E953","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","035 Gray","011264D15B226B6331EA524A178CF762","0134EFE39D2DABDC6235B0CB9146EF57","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","036","01264E8FC69DB0D4E823310AC4A62F5B","01FAB2BA2D9A80FB421DC6981F422A94","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","036 Gray","012DF7E87095F3A4D07DBC92373D9B4F","01FC66F233B3BE25F29099CC55B0885E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","037","0121590D0BEDF72A4143EC952F460381","01E628E7BB9ABFE61671ADD29C40C494","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","037 Gray","015A3EBC8CE27C2263ACFE59FDEAA9FD","015F3D8E92A854F7DD672416B986181D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","038","0142CD8148CDCF1773B5033BC4F6DB7C","0175F083CDB8B43AC45869AD5F233302","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","038 Gray","014EBD5319703B5C799FF67F85369A24","015C41B94BA775521381E9A3DD1D0E67","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","039","01225CBD60ED2AD10620D8DF77E71FB0","013B9648B48BFF6B7B099F3FD651F248","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","039 Gray","016841AE563FF5A1202CA89697227C79","01D2BE9EDDEFF1E984B81E79E3FED82F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","040","012247F7591F152CB8F0A9859A5CAE7B","01E9C459D99D5A7EB868FD7782AEE67D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","040 Gray","0120CDD2204490080A40263C61858CB3","016C2734A1E5D1B70EF40A6C3188BE69","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","041","0127C46FF50D958B8B384E6F0AD2E8A8","01B7CECFBDFB72C303882D2CAFC59A74","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","041 Gray","0113B0EF4E7461BB505737FC88B5D0BD","012388C889FE36A02B05F47E5AA2A6A5","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","042","0129E22447C9DAF1C399DD56A361ED12","018F8CD5A5C334B58F55752E4E490831","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","042 Gray","0157890A2FEAAC8D8C821656B843D3BD","01DE4AFC5FA19B360DF6CD75CA6F2630","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","043","010B2A78965C750E17CD6AFC82E4C383","0121DE7AB63C9FB70AD06BFE55115CC0","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","043 Gray","0168C82969D81B945688F0F3C440C12A","01DE38198CCB700A64CD2856AE6F6E95","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","044","0123A1A8835A75EE1DE4DDDB26B19F17","01D587857C3B50B1C030DD163E85021B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","044 Gray","010B836AADC68BAE29CA32563548136E","0180F16550B7AEEE50ED1E9F3B979BDC","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","045","0186F9C1D60513E78DA10AB8A11EBF2F","01EAA96641C0139DBE4744ACFB0635C9","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","045 Gray","01E8A97442C3AB91BE7A459F832B1542","01F1F92020C2A577FED4E54284E9F4D3","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","046","0179F3FF136D4ED422E37B67FD7540C0","01E59C1A56C91BC1B050D764A2503A6A","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","046 Gray","014BDF62789FCD30F49D651762C762C3","01EDF4068076CF390F5E992CF8D7671B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","047","01C2C5F19300276881675802CA117AFF","01DE888ABC6D1237F227292F3C2CA6AF","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","047 Gray","0133957C29272CBD22C122D57BFCFAF4","0162031166211D6FD11E0E0459196DBE","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","048","01AE707BB10E5B75C6C1C72950710BC2","01FBCE244CA094EF3E713642A284AE75","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","048 Gray","01DE8416C14C4A77B0775116285A5FD0","01F9D08C289E2816F7948FA464F14D6E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","049","019D38AE2A0593E6CA1796D340F9C8C4","019D75AD2E9F9F3E32AFC268217DD894","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","049 Gray","01B3F9CB307D6EA42C70BA3F1A1A3980","01F1B3CA3A9317E0BF83E26BC15EFE6D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","050","0133FC69E52E74319F110B4486B8B0D8","017FEB124293E03634B25E85B537A2E9","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","050 Gray","01D721791D863035D28A72BCB3992FAD","01F2F9B33C8A515088AB4F8A57BD09F2","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","051","01472DFFD69C61F0236252CEC3D93A59","01AA29A71CF32688CAA00C0345252BE3","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","051 Gray","0152A96E81A2E16D04079E533F08CA43","01EEF4B339A3CE53F9006963F1F88998","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","052","01BB95128BBB51E2CDB18EE3464EB78A","01C77ED677A7444C7303760B540151A3","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","052 Gray","01C3D3D11D66BA55032A2889E25E6D3D","01C9A767730799D049B2C57B960C115E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","053","011D227275F2AC493D1A6A1492BB77C0","01ED7F994B85E53AF98F2BC8A1D76759","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","053 Gray","0157AED65A17EE6DFA6F71DF01F4B464","01C74D9D2760A28FADB0C8E62D8D6458","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","054","01621500A3E854663655E2A69AB304A1","01C937495DA1BD772ACC0DA4E9E2DECC","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","054 Gray","0165074F1C9E973ADE6C604727FAA835","01DAB04F1D318845D3C7E5B40F90870C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","055","01B740329A84086970A6293DC09A8FCC","01C32360C87E4BDE82548DE301DEA159","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","055 Gray","010615CF2AA5E0D93B8D36C96DB4642F","01261D04EA4EA8D29F63053627ADAC54","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","056","0137761655C50D80F4162817A18A3920","015047A760AA50A563D0ECFAC4386056","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","056 Gray","01116F0DFF19B83CB7A5F3247636284F","0126F525F78C06384CF5250CEA75639F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","057","0116C72F9570BAC3A7EBA653C02444AC","015CBFF3B2FDEBE2602CB83EFC2688DC","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","057 Gray","013B67ABCAF2C9F654181EDB1CA63717","013F9615D6C1C61EE57178F7DC50B0DB","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","058","016AB252DEC4F6934FE95D58A15F7DB7","01D1328F2F91E725469044B4063D1C4F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","058 Gray","019E75CAE868EF1C82E59DE7533922A2","01F8470BFA03E0E546FA08E72CFFF65C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","059","01BEBCC9A81E85194989409335851B32","01C6EA1A6A3BB78C164A83168D921736","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","059 Gray","014EF48C7F135B7586EBC027F4B06478","01E6C2A5F8BA5B973206CA732E425EE8","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","060","01195A026C32F022A48BC36FD0D4D64D","01F08A12F2ADAE77844686384A57586C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","060 Gray","015A51E4B01EE84E2841914511C8AC32","01DB43FAA6FA415E716878737358C331","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","061","0185CD228521305D8A3490CBF8A409B7","018C8552EF8C257A88F67B3C878F027A","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","061 Gray","018A4084F15493F2D2D86D4D372B3227","01BC3F21BE4C67B1793F135A8202D542","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","062","01C16479F816F0780B7B435C0A260E1B","01F8B58DB77D7D86532D621723DB8696","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","062 Gray","010889A479D668E1B0ADEC6718AD824B","012284AC8BBDFBB3E9DBC94C06947C32","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","063","0123A1DCFED52D07F5EC102A1DD65CC4","01E267EAC491A4E9E29D44F8A908273F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","063 Gray","01794D803B2513E44FC0880D80F5C6ED","01EC07C26593B71842880ECA0F97A4EA","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","064","01925341B1402B2B890C20539B2994B4","01A506A5268ADF6774AD1DD49F250957","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","064 Gray","0109EB325DDBC8BE92C9FEA5FC094F05","01A737652BBA7373792E10CDDFC1F37A","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","065","0139091A8EB09D2E5B08BF57DA89136A","01FD829AFC9398AA4692176577CC045B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","065 Gray","0163F622658A1D5A34EE2A0C0CC7E753","01DFA0762D896CC0D28EBFD72C4636C8","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","066","010973B55CB8F35CEC6BE27E8A6114C3","011C1D7F8A70B35D705697AD7C3035FE","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","066 Gray","0197BC85139932CD93236BF56D9600D3","01BB08DD8016C1A52BA05BCC1B70D418","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","067","0115B960DFCCAED914805028D6BE5B9E","01E46A79F6348351DC69F39906F79815","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","067 Gray","01322D28A106B1D69A67397D203DC2AB","015B7AADF7F79F1022ED982956F1A354","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","068","012BE1B445368E603FC22008BD93022A","01A5343F7E0036358F115437CDDF62AD","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","068 Gray","017FB581F809207921A8B4FC49053BC9","019D0460FCE1BE7CB21EDECDB459A189","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","069","019440CF19661C1F7828F27EB76A8DFA","01F80863A47C93BAE0AA573CA22BC24C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","069 Gray","010495CE0D8FB4A4C0A3F5C82D8EE71E","01AAE70F705BFA52EE947CBEBB9D4F3F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","070","012E11ED043029D57BEF07015C8706F5","01CB9E06BC0516835D9AD2264F9E2DB8","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","070 Gray","011D54A91F2767E204B3156EF7D939B9","01C3CAF8C48F2C9E84AF3750B68EF1FE","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","071","011975EE86201F10E48E4F365C73A839","01B8FDD60747E53114DC15797CC09B4E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","071 Gray","017124153ECD2C1080FB1C81DE3E8966","01B85C5272CC4E0F18B4296963627C55","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","072","016A9F39EDF7E9DCAF8BE822C2266077","01F0A31D3842CFD4B7E09178F141E14B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","072 Gray","01040344A2DB072C102867283CB40094","01EBED1BEF3A14275D6F99C39E693140","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","073","017659A2F9A530359CB8725D32B5BE6C","01F863D3F47BE8F243BFF177EAC1EDB4","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","073 Gray","012A4FCCFBB2E5EB17ABF53CB8CE19D8","01C1F982D08F1A78A5165145F51496D2","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","074","01403088D08B8A2712CA648846151E07","01BABD681F45ABBA1BDCF41992781236","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","074 Gray","017B6F3C3060C8FBDC545D51B689926D","01FAA30172673DECEDD32E154151FEE3","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","075","012D821C6AB210E2A753BE053B8F55D0","0182408A81A4ABF04D4A34A8A5E98C58","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","075 Gray","019C6C4CB99521A5680C96B0EE999485","01C8ADEC252DAF2DD41A3F13A6B26952","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","076","01786593B7990A17B0D81B6DF749470E","01DF37EBC825495EA04E9B311B77D309","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","076 Gray","01DC3D7DB9ACC994536C4DB9946E9711","01DCCEE0F68DE87E7373AC29C1CBB49E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","077","017326197BBD2E1FDD0E11F8566B9AF0","01E130328507AD3C0BBF764713BAA825","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","077 Gray","0141F107BB584F14E87768245DB3AF76","01F1541340407C08EA76A4FCFE8072B2","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","078","0120996088E68CF9F70A20A414D14AE6","013E3A5D329BBCB6AAF62F2E18FF8127","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","078 Gray","0121F5AA8F3FDC544FE971687552237B","01702C9DDEEF45423E653771CC795E0F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","079","0182230692721ADF5DCBFB56F747490C","01DD92C0CD7077A88C49139F2F15908D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","079 Gray","018FF6814B9CECD349F3C68DB05AE935","01A3E3C211808C98C590BCA8648EADF0","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","080","0175BAF3251040E0EFB2930B73328E7F","01DC499064BA9264D591FDE9071DFD89","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","080 Gray","015025DF3475A3F29C67076450ACA130","01E0394825707E498E84188416172B0E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","081","014D29278FD055B04D8FCEF52F63568B","01EECF7F5B388E02EEE84ABDCF4CECCB","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","081 Gray","01AF22414DC63BEA0C335DE6D1375597","01B475A679A93E2BC96403919A8EC24B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","082","0138A8D4ECE59F41D2EB9AF5168B6675","01CA9A809F737BA668C16DDE52E74092","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","082 Gray","017FF59AA3FE074887A5BFBD5F62022A","01FEA37B95E38ED4CAD108207F94128D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","083","010300D2A3C0CEB8216F7C59B96AFB16","014F706DC17A4AF11117D50B414F348C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","083 Gray","01051ABAFD203A1D4605907C8543F055","019B7D8C1A094ECB4CBB5B828420356E","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","084","018F43694F4E9A49C24613CE0DB777A1","01BFD6DFF74A169EDA4F585691B1C832","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","084 Gray","01B5F6A0FFE77B77435B2FCAEE7C6F80","01F3041C2B3DF3709A124468F429A720","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","085","0155D875C95B74D0F3C5835A62516F48","01D38A25358EB7649A254E19F1D46600","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","085 Gray","0130FCE1BA83C767EA3CB8DB23D92289","0181EC6986C4F1EABDE468325BA3A394","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","086","01AC139E31B941CA0F2C5B5A0BFCDFC0","01F3D5B0FBE08EC4AAE9E1E4238BF215","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","086 Gray","0114DB57CAB32401E0507B831E2A52E4","0146686A83711D8227677BFBBA638030","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","087","01387A14AF75DC6963F040C1239B7DED","0196457BE1E9E30F00715A3DDE8B160C","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","087 Gray","012000BE0A51DBE0A2C9892010AA5F52","01ED8F3F34064DE4F66E3020450CB51D","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","088","0197DD04E9338FA3B25733603CE7B284","01EDFA7E57FD291021994E804A3F8B7A","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","088 Gray","01087F903C023E08A98F0AFFDECEB92E","01FD306EB29345CD98B6A5745F0E7E75","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","089","010F50672F14B4A88409AEC86E9DECE9","01C3B4FE62DF9A99F1CA8A5C17AC7711","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","089 Gray","0151EDAED564F03C97DECD9354C9E257","0196AB42568EED23B00AA7EA62C8A2EB","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","090","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","090 Gray","015C645021E37D3469A6B652789383DB","01D400C125EB43B05762A66347B271F7","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","091","019F3987F634C2AABC21F2AF9FF4A0DD","01B96BF26D34997052B944BCAE85EB75","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","091 Gray","012D8D2AA086D89492158B78E1409893","0176BA0E25E41748CB30F6A569C793C5","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","092","01557A9AE226A38386271DFE13D64298","0167FCEDBA3A8E8CF822163DB3564762","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","092 Gray","0142C7713D66971ABCD4705A86C69165","015BF30464B173AD153EB6FDF2F443F9","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","093","01B47B996CFDAA5BBAD40B9496314C1B","01BFF13DEB883EF04BEF63AE789B06D3","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","093 Gray","011D2972762547222591CBAA7C61AF23","01A6F243D0894ED6B08CD932F2C5F096","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","094","019A5A3F4E1CAB2BEA76F978702613E2","01F870A8F8261FC607E1DE4C088B1B47","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","094 Gray","01945002AD5673EA722BE69C865C25FD","01985BEA05A4061A6B7350876FD023A6","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","095","01E6610D026E8E6FE4BECEA9B3328A63","01E764F3ECB6C14A51FF83F1FF6D546B","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","095 Gray","01154D4A58716A0D3591A6CD38D1A6B1","018667606B031F3EB98BE15F21933033","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","096","0124512C758C4EA7689FD76F2327664F","01943EFC55D71F0B8BD5172B58D4D1E6","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","096 Gray","01A02F112389AEA183D45DF351CCA76E","01AF02847E47B29390CD232AD89735D3","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","097","010564D93F295ADB889B91604DC82EE1","014302FE54745F4DBB58A0D51CDC66BD","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","097 Gray","01078E051231C5656C68E628BC44D34D","01635537D06C5A911C84767FCEC61FCE","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","098","01081C0D2E757D5A5E24734E147CE6B9","019C33083B8FA8E4D2CED45F06F0B201","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","098 Gray","017165E9E48151933AC85B03ABADF71F","01C7F75AB9E45A76BAA81B38A8BC3AC6","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","099","01C7F83908166C226C06A44017421732","01D3EFDD3855C42AE3E0E6289F1A6726","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","099 Gray","0169F10B74745DE17CC5BDC51629A6AF","018177A3B8C276E1BE69C65555927CA7","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","100","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IJG Library","","100 Gray","01BC2BB6764A7F9709F829E766D93AAE","01BC2BB6764A7F9709F829E766D93AAE","","","IJG Library"}, +{ ENUM_EDITOR_SW, "IMatch","","000","0165AC93CC56CD962E10217D526A4E41","0165AC93CC56CD962E10217D526A4E41","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","001","01320332E53ADAA0073CE0CEC27FE3F1","01320332E53ADAA0073CE0CEC27FE3F1","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","002","01E036E949A895A37821CD14EBB4A675","01E036E949A895A37821CD14EBB4A675","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","003","0174A31FB9ACE562DE1A8E872E9CCD87","0174A31FB9ACE562DE1A8E872E9CCD87","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","004","01A134A20B2372BEE6603196DED7BC1C","01A134A20B2372BEE6603196DED7BC1C","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","005","01B1BB61E82C7572D6BACAC16B9416E2","01B1BB61E82C7572D6BACAC16B9416E2","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","006","01683DDDC33FB58B75F62B69669762EB","01683DDDC33FB58B75F62B69669762EB","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","007","01D83C9B11E571CEB80835C5F27A7325","01D83C9B11E571CEB80835C5F27A7325","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","008","01062ACF66978332F99F455BF1BF02CA","01062ACF66978332F99F455BF1BF02CA","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","009","0191560E1D00D2548C2B84CBD38E4F90","0191560E1D00D2548C2B84CBD38E4F90","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","010","01F70CA7113363A125152495402F4B3A","01F70CA7113363A125152495402F4B3A","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","011","011AEBA34603BBF13149C2DF6F0D515B","011AEBA34603BBF13149C2DF6F0D515B","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","012","01A7F1472D707FA981CD95BB2704BD51","01A7F1472D707FA981CD95BB2704BD51","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","013","012390AAF66ACC40F1E0BBDAC7F7C121","012390AAF66ACC40F1E0BBDAC7F7C121","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","014","01057F114EFF86B7EEAEB29B44D91FFB","01057F114EFF86B7EEAEB29B44D91FFB","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","015","0118EC3E8E053C034DF05BE8B0F57955","0118EC3E8E053C034DF05BE8B0F57955","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","016","011707F5512F6B6A5DC49A505D01AE6E","011707F5512F6B6A5DC49A505D01AE6E","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","017","011AE0EE6EC94BEE7A9A6B044A61140F","011AE0EE6EC94BEE7A9A6B044A61140F","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","018","01DBFA99FEAD99E45BF3F8E87A6DC496","01DBFA99FEAD99E45BF3F8E87A6DC496","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","019","0179A73F972B0B3F50D1E7F08E6BCBAC","0179A73F972B0B3F50D1E7F08E6BCBAC","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","020","01256E630ECC0F36AC9A66A059BB8822","01256E630ECC0F36AC9A66A059BB8822","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","021","014A56275ACC27F844CADDB17F98F26E","014A56275ACC27F844CADDB17F98F26E","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","022","01D42506093CA9EF8A953FD39AC01065","01D42506093CA9EF8A953FD39AC01065","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","023","01C9E68E93AA669A128AEF8CA399229B","01C9E68E93AA669A128AEF8CA399229B","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","024","015E1F710449F305ABFDB69069868E75","015E1F710449F305ABFDB69069868E75","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","025","01F610DAE4667E04A680FB5290680918","01F610DAE4667E04A680FB5290680918","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","026","019E8BED749941E7119D32CF7596D03C","019E8BED749941E7119D32CF7596D03C","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","027","016B1EFCF5EB29A6EC6C9B60543F3310","016B1EFCF5EB29A6EC6C9B60543F3310","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","028","012921014AF19689F7F763C9B0C45326","012921014AF19689F7F763C9B0C45326","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","029","0101A87A5738D68CBBD00DD5A6E243FE","0101A87A5738D68CBBD00DD5A6E243FE","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","030","01A33578C3220069FEAAA7E75291FD7D","01A33578C3220069FEAAA7E75291FD7D","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","031","01182426BB9EE261B719D69D33F2B292","01182426BB9EE261B719D69D33F2B292","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","032","0105B6A25A9C3CC6C116D3C1423C9911","0105B6A25A9C3CC6C116D3C1423C9911","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","033","011B084C50C703C19F8139A65F872BFB","011B084C50C703C19F8139A65F872BFB","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","034","01368977779D7F6794C6D8ED97A15DDB","01368977779D7F6794C6D8ED97A15DDB","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","035","016D0A6F0008E38FF4871D6FA2FDF670","016D0A6F0008E38FF4871D6FA2FDF670","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","036","015DBB98F058A2FCF2E2C4E2F4DEE19A","015DBB98F058A2FCF2E2C4E2F4DEE19A","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","037","01F3C4686DB5BF716079413E8E797364","01F3C4686DB5BF716079413E8E797364","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","038","0125A88E7EE182C7AE60C2D4D7164AA5","0125A88E7EE182C7AE60C2D4D7164AA5","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","039","0153AFED056FAF18883C6E96B1030880","0153AFED056FAF18883C6E96B1030880","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","040","01B6C23631B1BEEB8BE9B8B02DCFA8B5","01B6C23631B1BEEB8BE9B8B02DCFA8B5","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","041","01123CD019B873459AAD3952CEB8D1A3","01123CD019B873459AAD3952CEB8D1A3","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","042","01A8E1140B0BF7461026A4809DBEAEB6","01A8E1140B0BF7461026A4809DBEAEB6","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","043","01581A0E69C1827A70976EB09BE96F8B","01581A0E69C1827A70976EB09BE96F8B","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","044","016BEC3E5671BBE6E32F29E7A000314A","016BEC3E5671BBE6E32F29E7A000314A","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","045","0177C479CC3569F601E2D189FF09093D","0177C479CC3569F601E2D189FF09093D","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","046","011D2C9DBC773C3786D8F5402609FBF7","011D2C9DBC773C3786D8F5402609FBF7","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","047","0108BF398EF6D0B8ABC608669F239502","0108BF398EF6D0B8ABC608669F239502","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","048","01C6EF48FB38D410960A4B5295402D13","01C6EF48FB38D410960A4B5295402D13","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","049","01DC96B5A5DA85F89903453952815094","01DC96B5A5DA85F89903453952815094","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","050","019F146786D0C38328847A24D182AE7B","019F146786D0C38328847A24D182AE7B","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","051","01B7F57F8C74ED65BEBE6869D2E21460","01B7F57F8C74ED65BEBE6869D2E21460","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","052","013A6B5B0036C84A990351B774AA806F","013A6B5B0036C84A990351B774AA806F","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","053","01793AD27ACF46FE764114536DED4202","01793AD27ACF46FE764114536DED4202","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","054","011032D627D34988AFB0C81BB38AB10F","011032D627D34988AFB0C81BB38AB10F","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","055","01EADC023F4E5C5AAA1AC39A8DB1FDA2","01EADC023F4E5C5AAA1AC39A8DB1FDA2","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","056","01542C4D2A5514D93FE3364CE687C454","01542C4D2A5514D93FE3364CE687C454","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","057","01813B424C27FE594BE7BD3343E0A611","01813B424C27FE594BE7BD3343E0A611","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","058","017900994312A5DE5F9FAE88C288E214","017900994312A5DE5F9FAE88C288E214","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","059","0191BE33AB50852173F373BFB13EDF79","0191BE33AB50852173F373BFB13EDF79","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","060","011D3C2904614E246C4B468A20F3A936","011D3C2904614E246C4B468A20F3A936","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","061","012A482E2BF56F6F79CC68F954B9E546","012A482E2BF56F6F79CC68F954B9E546","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","062","01EFC4FB222400071490FEFB4758227A","01EFC4FB222400071490FEFB4758227A","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","063","018116332ABC764D7A310A24BE177139","018116332ABC764D7A310A24BE177139","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","064","01C9755B12B233887E9324B085D765CF","01C9755B12B233887E9324B085D765CF","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","065","010066231D4ED98B946D06673BC5461A","010066231D4ED98B946D06673BC5461A","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","066","01A22CB689E1CE541A6F9C90B5BAAD45","01A22CB689E1CE541A6F9C90B5BAAD45","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","067","016D25B5E4025E5C6CD9669925D466AF","016D25B5E4025E5C6CD9669925D466AF","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","068","01081855DC7D86A3C49FFCD1FD0872E3","01081855DC7D86A3C49FFCD1FD0872E3","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","069","01B4CBB1E2072AF552406AAE4F6229C8","01B4CBB1E2072AF552406AAE4F6229C8","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","070","019F9FFECDE5E7D2C16CC9690B8D1F84","019F9FFECDE5E7D2C16CC9690B8D1F84","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","071","01365815032821702D1D930EBAB3A018","01365815032821702D1D930EBAB3A018","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","072","01C52D343FE84C9F630B12E74D24FC3C","01C52D343FE84C9F630B12E74D24FC3C","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","073","01D9875CC6270A5D1F95C86812F2332B","01D9875CC6270A5D1F95C86812F2332B","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","074","01DDDA3E938F3F32BDA4C6FB2580C07D","01DDDA3E938F3F32BDA4C6FB2580C07D","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","075","01AD10A6B3BC47A7087FA4AA6DD82A84","01AD10A6B3BC47A7087FA4AA6DD82A84","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","076","018858FFFFCA04022B685715553469F7","018858FFFFCA04022B685715553469F7","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","077","0161B033070AD7DF62ED0D0C5E738D2F","0161B033070AD7DF62ED0D0C5E738D2F","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","078","01E1FE1B4167D1DB9E61B353A0C222A0","01E1FE1B4167D1DB9E61B353A0C222A0","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","079","01B88714C0895C6C53D6BE36937A449A","01B88714C0895C6C53D6BE36937A449A","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","080","01E6BB7915E70A0580A079D7A78298B5","01E6BB7915E70A0580A079D7A78298B5","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","081","01535ED71A83B97108BCEB895970043B","01535ED71A83B97108BCEB895970043B","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","082","01DF44F9FB42F388184BE63D97FAAF59","01DF44F9FB42F388184BE63D97FAAF59","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","083","010B5C07E62A9FB8E0EC07F424F91BC7","010B5C07E62A9FB8E0EC07F424F91BC7","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","084","0186FD4E87FED64154FD29050DCDE911","0186FD4E87FED64154FD29050DCDE911","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","085","019CB44E34BBC199CCDE9949BC3C81AA","019CB44E34BBC199CCDE9949BC3C81AA","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","086","0102F441777107372DDBA78ECC612F95","0102F441777107372DDBA78ECC612F95","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","087","01F77B3D704D81FC9679311833807D2F","01F77B3D704D81FC9679311833807D2F","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","088","01DA4D763CA09070FE565F16F98AA391","01DA4D763CA09070FE565F16F98AA391","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","089","01F1DAF5AEE48C7A85C561856ABA0ABD","01F1DAF5AEE48C7A85C561856ABA0ABD","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","090","01AD2B3452A92FE3564BFC87014D17CB","01AD2B3452A92FE3564BFC87014D17CB","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","091","01EF6B2FB59A6F333BAD5FF3CA481240","01EF6B2FB59A6F333BAD5FF3CA481240","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","092","017B4CC93608A96F242BDD539E9CB8FF","017B4CC93608A96F242BDD539E9CB8FF","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","093","0142A062D95E6067C4B0B791526A0C5D","0142A062D95E6067C4B0B791526A0C5D","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","094","0121303C9E720270C0931427D9D0FB2F","0121303C9E720270C0931427D9D0FB2F","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","095","016C410AD0D0DBF3709961EDBEDD7D0B","016C410AD0D0DBF3709961EDBEDD7D0B","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","096","010E60C5B6D1D2C9163A91ADC454B219","010E60C5B6D1D2C9163A91ADC454B219","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","097","01550366890863E706A41B5610F6156C","01550366890863E706A41B5610F6156C","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","098","01E4DEC5DF580F8461F51E4430A0C612","01E4DEC5DF580F8461F51E4430A0C612","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","099","01E4DEC5DF580F8461F51E4430A0C612","01E4DEC5DF580F8461F51E4430A0C612","","","IMatch"}, +{ ENUM_EDITOR_SW, "IMatch","","100","01E4DEC5DF580F8461F51E4430A0C612","01E4DEC5DF580F8461F51E4430A0C612","","","IMatch"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","002","010D9693F4FC34B402EFA979BED34733","0193B6220463E5A621ED25A53EC2FE7D","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","003","01AE4339D18A0F80E83AC68ECA3F29D2","01D73AB11CDEE244F9E6F86AA656DCF4","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","004","0130D16765220C8A13FDA6E7015EBA60","015829A3515B899B026896D737523095","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","005","010F16DA7E39F9FA0D360306D844BE1C","0162806319221CD47AFBE36563122286","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","006","014B8E3BB9C7F7469A34DE7ACA0E3E14","01D1781C33BA6C700844CF5F06F64D26","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","007","011EDDE09B712B924A2BE665A74AE914","01AC05807AE1A285B2B1F24793ACB8AC","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","008","014682A529B0B422C82557495769AF92","01A9CF2158FAE4057FC08722ABD92D67","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","009","016D0D6BB91282D033CCC41AD6BF3CB2","01FB5E38DB85808DEDE20EAA84BB9812","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","010","0101092454C6BA70F329E8323BA37A62","01D3F187A0B029D75287067CC329CBEB","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","011","01241D8A9C72BB77B5EFE13F46E0A694","01886D873F6F6F190084AA8EACCFA7E4","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","012","015916E2168735FB572926A049B025DB","01F9ED4812F46CA42CB85C9371E94710","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","013","011ED6AAC481E84EB7DF7D6C55C35FDB","01F41F75DA85DCEE81F79C9BFD835249","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","014","0159C3DD4607B9ACB9BB3F5D7191891A","01901016622EBC2E42EE162000A13DE3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","015","018390F607F757E2E42726F5EBB576FB","01EED88C9C6EB2CA6E048972F144CFB2","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","016","01160566E2F95BA1BF0BD7EE4B0A539A","01705560C1E678DDFB67349C3C510B2F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","017","010317C21733B42EA85718360A1ED6D4","016D83AC7EBE1C58D15569E4FD4EB650","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","018","012791C800B2CCB875FE41FCA751D076","01C78E1BE13FDF35BFD3DFC789ADED0B","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","019","0134A4CABB20CE957BF7F286CF8A4F77","017A10221C34E697EB4F3D9BE678A664","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","020","01013FFDF2B833139BDC7D30DB3F6F9C","012A1A7AE01B91CCAC1C5264E444A3C6","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","021","01347AC5D164854F8C771A7799867FDC","017A11C185DAD8B8246F46BC6BBF60EE","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","022","01166750E43638B43D2714F203408D38","014D35DD5AA484B2B89A705B009D6BF1","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","023","018FF7549D7AE5B9D1D2A61A0DFD584F","01EF84DB7BFD56AE1AFA2694BEB10676","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","024","0196A9589F2F3BA0D42D937C1A94312E","01E28097831F0F7B6A5C17D31F74E2D4","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","025","01CAA4241F9ACC590059C92CC8203E75","01F7BF349603DA557C8CD6EE7D9C5AC7","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","026","01561E29456A1AFB859025E2407C7077","01ABF64A97B6FEF8218EF1EFB776B9FB","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","027","01821498C3A572DA347E2C024EA303BA","018BF7FA5F45481749B5AA32797564B6","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","028","01EB64439B48102135509A2A19152640","01F5C4A96AE81125E1987D0CF03389F6","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","029","0144DB8DCD47372608E2295E4EC309B1","0155964EA581F823AD5ED60982BD2BF2","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","030","0109523D0200F111FBDFB63DC27DE296","01AFDE21B58FF9781CD22B60E20F22B1","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","031","01872C7AE0162EF140AE3C5F5EA39753","01A5762018316067F45B5D0B30E0E4A2","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","032","01626CBD0BAEB519B4FA1DB9C280013E","01646D280597178A2C5344688EEC6E0E","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","033","0165A4432B13F5117EC466B6DAD5D5A3","018C4E45F08A156DB04F70F5BB708721","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","034","0169F22E635E72757DA817F4AF5095EA","01B18BB69C0824C715BB005F1A4184A9","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","035","0174A6099629A3AC2A4D187945772A2A","017DF8CA578501893092725F3B7918D9","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","036","0170FC9571E8D70265DCADC8049444DE","0188936C9FF8F4EF33C8F9AE1E337D27","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","037","01DFE417CBBC628DDC8BB3A78AAD5B33","01EC396D7F0CBA8C375512E739C7F90F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","038","013628F4E46C5B171E4B808B8AE2863A","015D15A0EDFC7D0175E0949D6A450524","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","039","015ABF68E584D7D7C8877F6FD98C184D","01DF9616AF38E538261F7AE8571E31BB","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","040","010605B0608B08F2892492F6CCA254BF","01166CDDF24FC9B5437579E30667C774","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","041","011EBBE3EE74E33567F2CEE7BC6C8F38","01965362F06FCE474BDDFDE09F119CDF","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","042","01E8295EED0260AAF623B72423E17B17","01F8EC33907B45D062A8398A2DD3045A","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","043","01AA8A959B286BC0E480F7362A790200","01F34AF7BB0266B24D3F018B77BD1D99","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","044","0132A165637742AD0D3C9EDAF84DC95C","017EC1C29F2449DA50B3FF30061C6DC3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","045","01380D2C3886D54F05AF501141908A08","01463C19A046A5A6DDC79555E325AFF6","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","046","011FFD5C27656C7C753976FFBA50FEB1","01E189AB820A6C612129C5D7E0BD72E3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","047","01548A239BF2C6CC1255CD26F1B840F0","01F16C6F4375E2055EC31A45A14F3DC2","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","048","01182829CF6E8D0845AB1F3BF52D9F9F","0158C3EE617A20028F15D0F25A425D98","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","049","0121C7DF0C348A2A5E4D4B7CF62D94CD","017FC54345ADFFD6C7946694E7E49122","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","050","0133FC69E52E74319F110B4486B8B0D8","017FEB124293E03634B25E85B537A2E9","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","051","010CBC45D3C5260863E839BFC2235A81","01CFBBD314CF6CEB5248469C5E3C2CA3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","052","019D1C17E70D8AC5C9B6DEE7A30827C8","01F0547180BAB8A5C8329D7DB6F3F954","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","053","013146F1F80E20B7C32B0319B214A919","01FBA1F3C2CCA3C78748DD5C4CC80562","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","054","01BC27930C37DABFE67EFD9E4AB54437","01C01A9A5554405594E81AB4C371B932","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","055","01B72C7BF56F55753B1265BDFF439069","01F08AA3ED4A18353A524A66691D73CE","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","056","019A22EAFA396CDD0CDC430C61FFA430","01D67A64BE0EA692C0EEDDE2EE719535","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","057","010ECB885D4D576D5C5932FF5A6A5092","0113B452EDEA1714691CB6333FD0729D","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","058","015E4B9F3BEAB958F015B81710C84810","01AD6C71352216EF35FE8520F5D1E82F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","059","0163526F62E82D53C0DAD905D35C4599","01A9FC9DF742C7FF082F03A6F87EC381","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","060","0175E68D4D293E2FA784C8CE11DF5516","0184D878A64B40EF526E5A6EF6BCBCEF","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","061","012300395A15B1B6D203FA8393593157","0134E076C67CEBD6283F4ACFD9BFF5A3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","062","01F9E4690F1C0BC76BEC16928BAE9A88","01FDA2A2C7470CAFD274D9FB41AAF0F1","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","063","0107317B76A298F1175B4BACA2B107F9","01CB912C521BE4AE1FDB4C842587E7E2","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","064","012440B020AE88BF95B81B31641CF09C","01D32149DD50948136591D5F368DF581","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","065","0141CDC5CFC490A7B8C049F9D93AAF73","015FECEF7EDC0B3AF333347FF17321AA","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","066","01A6F76F7CF17EFC800AF2483ED2557C","01FEBD27FF945E96DF972ADFD2FE0F6B","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","067","015DAF6A68DCC4478A45C180F88C9DFA","0198059D58EFC7D276E91AE2E90D2A4C","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","068","012166ED0C275FFE159418B2A2113CA1","017B601F4F41E04CD8EECB9337CCBBDE","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","069","01433F7C61DAA7495770AAF88AE7039A","01C86AB6D8F5303BDA47B88623E417A3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","070","012A78934E0D22A24AE899907336F46D","01E52224D11398FC4821FD4E938BE877","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","071","011F669669DAA96DAB5C7517A5172089","01B558FAE56F5994211E6B916577F868","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","072","014170590155C13FE856CBA528EA920B","01A343DFC0DB4F646D3063066740BAC6","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","073","016FDE4F110A6334F0973B29DBF22C85","01A325BC80221BD481A6D37355FBF9B4","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","074","011F4D6A97876DA82E951074BC74A097","01D970DCACCC1D81A2DE8E3E4C3385FF","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","075","012C8E823FB3F009A733E7B91A146A96","015DDB4F6B6A8D3A5E934B7C70F69CD0","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","076","0106E6569633D7A5DE7A24F1D08042CB","01A8904FBE491ADF0B62FFBDDA4A0FE0","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","077","0110ECE968535091C39AA238A6E17E83","01F62C6E04151C290FE6E475B5FFA56E","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","078","01607299E0B0D313EB869C0789AC56EF","01D29EE49F2811E430569C8C43F1046A","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","079","0143DE5B546751703206B2C5335698C0","01D8674E4E744A68D5BDA4A2543C8B59","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","080","017608CABE0D8EA50F98359E3B90E58F","019DA014E50CBF279074EDD8ABA2BFDC","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","081","01BB618731B0CC9F1EFB45293DFD6379","01CC621547D81C1FDB424C8B013725A3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","082","01653DEB309B7D3BE24668026E2BFCA6","01926E63F4B81298BA87F4C5D8D22700","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","083","01B0DFEB26DC3CEEF172C10114D1D1F8","01D100852DA3DF0BE3145A12152DA87D","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","084","011DD9AF3EC835F5AAD56D8BAA6CA058","01925CCD917C507DBE547DBAAA5F00FB","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","085","0145E6BAC626BA2061E26CD9120D3D0D","017158FF2EC09CAA79A63E1AD371972F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","086","012D19D8472A61C74A2FECE822664F24","016E3AB5C1681D786D7EC6AC65EE8C4D","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","087","011D4CBBB874BC0438B7A82B99F61024","0121AC61D63E0CE991E5EAA2092B944E","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","088","01AB6F0F127632E95789CE3F207AE6A6","01E6B6C5713F5E884C46C5675ED26B2A","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","089","010F8FE41C7B8EEF01699F91C5E071CD","0191086A01F0D774B7C509E5D26E51FB","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","090","0133F539C3C8F7349AB3CD95449C0A43","015C031486FE1D68DBF351CABB2FA562","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","091","012D7B879B3DD39080026AECF90ACBE1","0172C829A8BAABAAA7CD03665971F951","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","092","01AC6BEDFBF8FC68178A60F6A58703F7","01B930D70CB78DCB1F19B54BB01CE5FE","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","093","018E1BB7E1BBB283FD6CC7B63222D184","01FE4D541951F248E3CFECF937A8B15A","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","094","01573D26512CB20F26EE9D8BAB4F8F92","01CCB2F17A97E15E403FEDA856E0AC26","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","095","011D8D1C132B3AC1E38E908794BC12CD","019479014B4DADCCAB900417DC5E5E6B","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","096","012182815ACD54C5ED046112CF86B17B","01A95CE911A6B592AAD4BBB9A3389530","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","097","012DAB79295978802275F2EB275F3018","0177CAD866B69CF219E809A260A615D9","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","098","016DEBEAFAB638EB0FFEFFC01DBD5A93","0180FE9314CF21561495056C7829A1E8","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","099","01023A9C5ADDAD46F387B97385DDAD8E","016ACE6BDC9B15A229DA6C3803765017","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","100","01E1BDDF6C45DBEC46FC48B60BBF6018","01EA5E13EF082CE6D445C4AC8ED703A8","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","101","010141ECC5CC1790D53255A8DDDC833B","0128F95E9DE7849E634EA71562327BE4","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","102","01171F54307EDF50C03ABD8B00DFF08F","01EBA7D8ECE07830AEA584123271D1A0","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","103","0101666C809358D2E81FB42FDC63B2DD","01020222E6F191065FAD2BCC51533280","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","104","0140D612069F8FAA681E9DBAB8D9422F","01B6390FABC6D36F61EA3E9C567460B9","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","105","0142F71E2A5FE68B77119E652C497DA1","018D7B491F46CFDAAD58ADDADA7C69D6","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","106","012CE2C6E38F70422E1A4088817E8D1E","01513A242FDAC9DF86CB10B1983401E9","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","107","01A73E3CBBB3D58EBF7D305DFE82CDDF","01B11D8D4DF6FC62A0483F8C5B1B574C","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","108","0139868D2E3D0B299C5B53E1242B73FA","0157E6A56B0F86CB33286A66C826AB1D","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","109","015F3E7E52A9BB54D2968B9502E56B7D","01A587DD053AC0EEA85252AE153A306A","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","110","01445B141C321629DE1D172989A5DB00","01B1FA9AB8E9FFFF4EC9D7E534523430","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","111","010CCCF0E35063085F6B99EDFBE9FAD2","01246F5CFD63CC8F8E3B018FD8C5A2E6","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","112","0172FE66433D5A303BEC3A7B3598413F","017807CE8752D7040EB8911BE11F2ECF","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","113","01CCC60FEDECE33BD4D5B9BF147C328C","01F69436326FFFE5A7D587753E51D235","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","114","010A74D30FE24B0CB7F0714BDB698933","014862165168A1D16D354D47BF688216","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","115","0127FA6EB0ADEF10211E9FB0E9A4CE57","01637285D6262ABE6DD31424675DCA08","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","116","015231DA2358880432B85B5B09B81C38","0165997FDB5C071D28926403F749AFA9","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","117","0122411D52D4ED1253B058F4DB022E90","017BD507D2EE0655298312CCDC880665","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","118","0102ABB0AE862BF7F819435579E6247D","01C447FB8247749E4E567A704E428D45","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","119","01126218AC9A43474C6A20E003B0C745","014453F2D9017D5D4027E745F2BC013B","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","120","01E1475EDCD07BEB173E37EA2B175775","01FF6858DD9272AFA62AE816476D3F42","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","121","015A290A921D1A61039ADE4601870B45","01BAB47CF076E57F011C308687C0201E","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","122","0117761DB6D57310D87DF66FA37FA55C","018A985588DFC6CF1B7041CF90C6A01F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","123","0126D303D0E3903B7ED22854AC5FCB5B","016AC4AFE871A1B87AF7A266958E4B7F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","124","015166A24C308C040FC15EEFBDADEF43","01D3EBF7841ED02AD1A7EF5D50DE2781","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","125","013432620EF3C94ABA4B8B43893CBFDA","016A83ADE0CD4955D9C5BB5A834D3350","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","126","01154A4B654FC14A1FB5EDFB6CF9A330","018153B33F1C1B5ACD8B558368063A47","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","127","017A3F21468542DFB663AC22203C535D","01C556D1672AEACA3D59BC16856EC458","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","128","01CA214289E25D814ACFE0605450D369","01EC39946C595C89370B197CF1AD9DC4","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","129","01B3BE8967B35123F5470C114ACC4D85","01F6D1933E1977C3AE2CAB28D26B6CA9","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","130","011603DB4A43142175F911A9B1499D15","011CAE4214885A1BCBD6DAAB17E21962","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","131","013C262FCCF1880A24A3363BAA52F0D7","01804C67D073E9FBE759D0F4F3BB4851","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","132","015C3D3593910C5D68881301400627D7","01A884BE8038BE0699E63FE0FEF708C3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","133","01C3FC4C442C82D1BF964721F2E83566","01F2A5444C2F00BC66A710CFCEFC63CC","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","134","01BD674544CEF9938C18F992D9593D60","01F44452EAED42EFDC058888F8655295","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","135","013231BCD4DB6238F254737F0694AAFB","0148B37E9F2C9FF9FEE1CFFDBFC5440E","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","136","017BA30AF567FA508880537B53AF1DC9","018C8428B7F6B8A7B458218052063827","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","137","01BFC4478AE7B73B41E50ECD28DBFA78","01EDE8F336941947589F52BA8F913588","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","138","0197AF7CBDDA618AD03F38469CE36C27","01C303C78B3C6EDB05B6BAB9D33DC066","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","139","01423D270D41FF070AB1A59D0D2DACA2","01A5635F552D35C292C9846F7E70FDDB","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","140","0105B2B68B41A49822BE48D950359C15","017E9E409FD0EBFA51AE02E48650D4B4","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","141","01694E63CF8AD00C095B3EAC43F48A54","01D656714D974C633FF925601A2AF00E","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","142","0101B13F55983BAB29E383AD562DFAC7","016C6AF5FC276A23D80328BDC9BED33F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","143","011200DAB55F8121374DB751C9E8F5B9","01F4EE9BA4BF7817C586B0D8DB0F738F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","144","01871DA90985CBE76C50D726831A91B1","01A689041103AB59CEA476222A0794D3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","145","01803640D2420EE067C0F563CBB95DE7","018353485340A2010A4A235B1BCAFA81","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","146","0163E75D86848F86284BF139FCA3549C","018E709178CFC5A916BC344AED26F220","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","147","014688C0BD278F52D4C50C521655F66E","01A63DB18F873AA2840962B31DA9C817","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","148","013CD318BFF36E64B4F278E711DEA604","0178483C1EE5DE57BF953F86759EAB3C","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","149","0155C0982CB5A63BFF9B5253574EB035","017771204B2B4085EE4A71FACEB2046F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","150","0130B52BECDCA022AC4351FE4488C78D","01F38689DFAE7F18B9D7A757C417F4A0","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","151","01339152D762290475AFE687085AF946","01BBFACDC2C7A3247BBA0275D5635997","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","152","010174B064BCE4CD8904BDE2323DB30B","01D21DA353D298FB3AD6A2293B6426B1","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","153","016A859C353655704E95D1423022EE6C","01D50D9CED27295D1F94C394791DD27E","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","154","012EAF2E5A37A39FCB90FE9B8E1B0125","01F995FE2845306D1F0CD1B2CC247389","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","155","016420AE56F486BA2525D85AADBB339B","0192A18C2F74AF061E7CB0662E81DF0C","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","156","0121D7F3B29A19C137ABF1FE953E93BC","01314DD06C5D624036E01B45E67A72FD","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","157","0180B0D0F6E0B42EB78DE66CB363B1F3","01E0F93EC976F33BA219E94567133B38","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","158","011EDE482D6C91D1A4D0EB1649192E0C","01A2317C79DFC4F5432A9AA284132E48","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","159","01201CA64783CE8188860A0ED0EE8730","019A99D60146E0563333B96672A27086","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","160","013D415F6D9A2E3632F2352A34460202","016A76DBFDED5D2370F7C9911987F883","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","161","0139CF17C9F433E3D69FDB6C5D0310DE","01A31F28A468D32AECF98CCA09DF5CEC","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","162","011C6E5426A01F87557A250C2AA29217","01FF5A009E8BC1DFCC3EF5C219A2580F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","163","0181CEEB6A4808DB5DF406CA356EA961","01E61B13DDB271A5FA8431CD7C3632D4","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","164","01584D00FFE9D5F4C0B18C1F1057AC2D","018D851B69B22F754C61D7A7D404804E","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","165","014FCBCD7DCC32E728AB11E41D340CF1","0197C7717AF680AEADE069E4CF5566F1","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","166","01D9EF9AA868719114E7ED681CE15A80","01DB08AFB949C6BF5038EACE89C16AF7","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","167","018E8E0FB96EDD8C810FAC4BCAF5A1E3","01D71CE75395343B02463C9015B0077A","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","168","01BB9CD692E53154B43C6E55FE0649E3","01F9292523447EF171ED57B21DF0651F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","169","01148E465BBA17AC2D3C2767495085EC","01CC996391449E53060289135E622C37","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","170","0118A98A7AC7645546854D5B2607BC18","012CF14DB7C0EA2649CE8BDB7748771D","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","171","0164BF7D624C6777E83DF8D8010ED1F9","01B3BA7DFA2A96138260DD56B020A299","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","172","015D5A7A503EF9A79E0B9DCFA4D9AFCC","01ACF9CB7740C2AED7B849D1DECFDE07","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","173","016C18E771F0FDF4509C2867B02497DC","01E395B45299AFD9C7AFCC8962DD186C","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","174","0110C90DC53738A78030D81B591AC85D","018B7DEACF116730086494CD41B1E76C","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","175","0140AA92AF90106991CEC0EF43EA9457","017816F27EC5ABF5CD34DA0349DF8A50","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","176","01542922E77EA9907DA7C63A53EC0C2E","016A09CF30769985052767C629566149","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","177","0161A5E2DCDB62920B9288658957C449","01AC8FD2461869A913BA2E4985388C42","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","178","017D9D0947EB2CDE8A79CD4C5D869F0A","01ADF6C704CD3999A14BAB1779AC5C60","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","179","010EE1BA682A0A601783CEB29267810B","0163A30EFC0120551D66A798698035A6","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","180","01592BDC96DF403C97961FE9DA3A2873","018F8F43094A2B3F41538DACAA06D0D3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","181","01B1C5AB82A4EF3ABC574D4A987DF7B6","01D5D6195B4B127BF216B37F6AE34346","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","182","012CB7FA2A05A9C81BFE5BD830CB8A86","018AE56FA30610ED2C3220D469C4AD5B","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","183","01AA46313DCA7147FB76F9C16DB95E53","01F925D9FF424F37F9DF4651AD5F49AD","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","184","014A437C6777FE25CCCE2E0839514344","0197A285BBA2E336F5400798A1EFDBCF","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","185","0139A1775B95631AED1643F9B9A10BDF","01A89B8115E4C07B1F2E1DCEA21660E6","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","186","011293704A25B4573D946F959C1D283F","019DE085FCB086DC1FCB3B64BE663827","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","187","013C181981A0D19412F53D2569584165","01D600AB45ECA09E45C6E4A1694C8234","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","188","0186832C45BEE501811E977BA184521E","01E0CA9FA53234ED9CB1B7EE41F97683","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","189","01583D62D92E147E1D3D96D8DA75BAE9","01CCA0E74AAE418E55199FD145DBDAD6","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","190","01B2E2402508AC74AD6F6EA806B0F602","01D69A0BBAB8B513E1DE2A46CA907F9C","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","191","01256DD2320743579D3BD609B41C037F","01C5BBFE5839CB149B1B081A21F9CBAE","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","192","017A13BED0629B650E766E8D9E902BE8","0194A980726F85C2B181025329A20120","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","193","01CE303D379D6D4EEAAC4F32AA5F9C8A","01E0BA091563681A70A97C05E08CA118","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","194","01966DA267048952B7F85C0660AEDAB7","01D83116882941AB191165216E83B03D","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","195","013CE8D7CB46B01AB54AD46A328AF3AA","01F6A1D4ED560049F4B94EF1FAB50A0F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","196","01766DFB4AB8AE4CE255F51D1C2312FE","0187FC645536F1FB632D8796CFE484FE","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","197","01AE734C85730B30D8A65855EADCBE46","01C34818A36E8B5A64CB40DBBCBD20C4","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","198","018D6DAF0BE5233A8244A19F82B5F783","01BC7B2D25E7FAAC23A9321CEA6608F7","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","199","011C08D93C5BFD6DA098F0E85C9B8C10","0179ABBF6FF7A03F9CC1A55B9BAFB8C1","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","200","01A23B72BEF75A4E84326F02773A7CD4","01F992EEBCBFBD7BA60314C1F508D728","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","201","0164FD8242063595E29DBE312830045C","016B7D40D8A542B883A5A780D2F57B07","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","202","016A90CDEBC44629F2D139F33D7A082B","019A1095D5923CE1794BF6EAD8A0AE86","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","203","0143659D8A7CAC20D791A6470D18BF27","0186DECD51204231FF26E916F8BC6F90","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","204","0183D0F6865F5A0C20413AA23E39E6AE","01878A9644BB3814E0E1BE55B726F810","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","205","01067CC09A86C82ED44C5296F627096D","013574316F410F500CE9DA3ED49B3CAF","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","206","0153F4AD836330A3FC327D63AF81E863","01967A578FEF8961D357B89CED883312","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","207","016368A72B2B4BE76F9FCCD24F3A3C4B","018673DABE870D0E382895336312C4F8","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","208","018DCFF341F4F16AC152899FFC9930A7","0194EFE42E510AF76A28FFFFB6A7109B","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","209","011D2D343B318B4B5EFBF3F5C4881374","0182376C5A57A22ED63A7BCC1DD15911","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","210","01C57A8AC130A22BD9E70B7280C3AF8B","01D412F55562351219D4B55EDA8D0183","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","211","011287B0EB965E0AB995996E463D8C21","013FC028BB33B3987DA4AFECE7BE836D","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","212","019AF0457038CA90921962EA4FC4B12E","01A382427977006432BFC0A0D6DA182A","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","213","0146CDA3DB8EC26BCE23148D2FADA063","01F30BEDB60E5F3669F59D7198D45EF9","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","214","010126E4E8112C268A97D40B8421A0C9","0144BF7E909DF76D25EF67B16728CA4C","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","215","01A497218747EFBF5FFCFF4C61845DA9","01F32A37604FDB29829BF69982A68AE2","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","216","013AE04D42C99D1D5008EE57142DBC9D","018631FAEAEA70CD642BEC283EE4F3EB","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","217","013A9C3C0ADA3BA6B2B4CB88B152E09E","016E7F3413FB9588D354D13AEB0A88AD","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","218","0107C3298B9AB5BA68FC43789937CA16","01595DD440ACA9FFBAE70759814218FE","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","219","01255F0C43AB1B5464BF2D833BF27787","01CE214CC2913402217CD79EF7584985","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","220","015CF4D420F0E3D87331EE66BB41BE9A","01798F13B32C295E3E39B49BE584AC9B","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","221","01661CB22D78899647C86A9D9F92CAD7","01F5EDAE84DC99823D86B5496ABC2A79","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","222","0154F14EB75877AFB568497E7FC7CCBB","01775B723C027C05DFD6DD71017D515D","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","223","01A64EA770E38F02927517A018E54FD2","01E35A7F2F1DF754D0CECA1ABAEADFA8","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","224","013B1972A84DA747D33289E5ACFBAE77","01F23FE5D6A15F805E18CF9CC2DDBF71","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","225","01A42CDA1EB0DB0234D37F0D06214861","01AAF044D3BC677F6804DCC38090AB74","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","226","0187F687E7CFC90BD8518C964C538F2D","01CD907285C824C02EB4FB7311A43889","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","227","015BA337FFF960BFCC41C15D995361C5","0182C745E667724C80A4080E3517307E","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","228","01A588522161B622C80027D364E2CE91","01C8E41883DC5F8DD639B824267F6991","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","229","010158703CBDC2502B5F7FFE72014C50","01FC0EBBCF963C663F27D830FAD042C3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","230","015E6B81C8409882B2B0D546DA93CB7E","018BCD69EEBE6987253212436A43A262","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","231","014685AD0F428DFE382F2DED801DD446","01B5F5CC8F2DF2C2356B0AB8506BA6FC","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","232","012EE742281152FB69DA4BCDB7E48228","0143EE9337F64E88CF82F85CEED491AC","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","233","01C037C9626C78E998AE4A0C077217B4","01FFFFFE13DC2E4FBA0E232166BA0A2B","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","234","0173E7F4C05E1BDE13591D1A70547F58","01B88AEF44B633912FF522A2283D92DF","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","235","01B61EED62EA03D8DDAA0BC17C02BE15","01EACC9E71FD3C7BD4B96A5C4BD54B46","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","236","012D45681EF3306674FCA37F12F89280","01E59B28E1D5C5FDF1FD1EA9DDFD7B3C","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","237","01EDD0CA4BA6DC4C0086DA4297C3D865","01F0EA54DC032CE660E74B8B5240F99F","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","238","0104D37DA3235B719B234B623476B037","01AE3AF247D1AD117B64AE6FCAFAD4B8","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","239","015C70BD35420A1F830D4D991B916AEC","01DBE0E8ED24D6CE2AC474056129AC53","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","240","010288A3B93D05F58058450F28B9B6F4","01AAD89E1E172FC5A7D0ED619A260BCB","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","241","01C5ADB0AE807AE5A5330F1B229B433D","01FE51092BF5C41E7BAE4B17CED51713","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","242","010A17DD2B09E7A3623A8EEF835719E0","0179D27DDEB67C90D4DA618597354EAE","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","243","01781D7E083EB7FBE29D1AF750DA5D49","017F6AA3C29782B775EDE527ABE44CE3","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","244","016E16E7BEFFAFB5B36269859A28A697","01F826EEA44BE8B3A36F0D87F2842411","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","245","0127825DA69B73164498FDFAD3FFA42B","0170AB98468291247AC14A209FC73661","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","246","019EB8A2E48C4E5B629E3E1DA7A9DF90","01E3299F5B80CC928C920D8D5A524D33","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","247","011A20E9C62F1E0CF16816969601A633","01C1D36F16C9F16B49417F0E94E74875","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","248","0179116263EC482BA2A2614BAC024ACA","018A306477F9B53A684F317173580B77","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","249","0103612119DE6616AB89AF4AD81AE337","016E47B08C6C290EE22B52F2B7154041","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","250-251","0196F2BCA047EAD712F1E724146172C2","0199D6A2E65FCBEB7FC729FFBD7733F1","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","252","01BB7F7FDBEFFD8B50C4581EE95632F8","01F4581774AF48A7CE129726B80159E9","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","253","016C9B02F44E7FD2F1FE9FBD8ACC158E","01C6BCF73B3325EAF95402536045B239","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","254","01010A5F7A0EE7B384B71F416DE97A7D","01318A9A5A7B2E880424831584BDD5E2","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "LEAD Technologies Inc","","255","01188DD39C08F3C6857DFBB1B7DEE0AA","019B1D02367E98B7B6C2C8C1878E8C86","","","LEAD Technologies Inc"}, +{ ENUM_EDITOR_SW, "Matlab","","75","019C6C4CB99521A5680C96B0EE999485","01C8ADEC252DAF2DD41A3F13A6B26952","","Matlab","Matlab"}, +{ ENUM_EDITOR_SW, "MS Office Pic Mgr","","","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","","","MS Office Pic Mgr"}, +{ ENUM_EDITOR_SW, "MS Paint","","","012D821C6AB210E2A753BE053B8F55D0","0182408A81A4ABF04D4A34A8A5E98C58","","","MS Paint"}, +{ ENUM_EDITOR_SW, "MS Visio","","","012D821C6AB210E2A753BE053B8F55D0","0182408A81A4ABF04D4A34A8A5E98C58","","","MS Visio"}, +{ ENUM_EDITOR_SW, "MS Windows Photo Gallery","","","01C6138A3E892EC7CD6F55F578FDD086","01F86317ECF8E38342C13A63423ADFDB","","Microsoft Windows Photo Gallery","MS Windows Photo Gallery"}, +{ ENUM_EDITOR_SW, "Nikon Scan","","Excellent Quality","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","","Nikon Scan","Nikon Scan"}, +{ ENUM_EDITOR_SW, "Paint Shop Pro","","","0198C5EAC1FD06F70494FC588808EA60","01EE638764A3ACF4F505DF2864906AC9","","Paint Shop Pro","Paint Shop Pro"}, +{ ENUM_EDITOR_SW, "Paint.NET","","050","0133FC69E52E74319F110B4486B8B0D8","017FEB124293E03634B25E85B537A2E9","","Paint.NET","Paint.NET"}, +{ ENUM_EDITOR_SW, "Picasa","","065 (Minimum)","0139091A8EB09D2E5B08BF57DA89136A","01FD829AFC9398AA4692176577CC045B","","Picasa","Picasa"}, +{ ENUM_EDITOR_SW, "Picasa","","085 (Normal)","0155D875C95B74D0F3C5835A62516F48","01D38A25358EB7649A254E19F1D46600","","Picasa","Picasa"}, +{ ENUM_EDITOR_SW, "Picasa","","100 (Maximum)","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","","Picasa","Picasa"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","01-02","014FC9D32AB50D2E78A55796DA2CBEC6","014FC9D32AB50D2E78A55796DA2CBEC6","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","03","013B7D3CA9CB31130CA7139D25B7A8A4","014969EC6B9209AB4F927921A5888DEC","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","04","0106F0377342CFA5A3143FF45CD28994","015A029AAD57B7CF8B62685C6013B390","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","05","013DFD2C7376334D7E79543CDAAC4910","0168601A9309B12FF6663D1F0136AFED","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","06","0175BBCB841A26513150597603D62BF6","01E523DD30A14718A8953D0C5612B3EB","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","07","01134024651373C4D6D52691F50D6586","01556DD156C6B8656EDE632E14B091E7","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","08","01031D5074818334ABA6C355F5560090","0134BF791F72302FF2B4E1AB17C648D0","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","09","012B194EE141D44DAB6B42D3CF93CAD1","01D95481ACA60A50D2B8C5085BC83312","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","10","01C79DA0631E8F88841CDA26F6094C3D","01DB3970B526B734EA8EE2C65A70AE0F","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","11","01CE5B6AC816554311EED0F18B9B7B44","01EC62868B595D0C25ED770649D1280C","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","12","015EA76216925F6290C9E5D53D3969FA","01D81968C245475537CA4224A630C63D","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","13","012E28D014C5944E3724F593D5124973","01678B2664F0FCA111021154313AAF00","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","14","01406236F6F26D47D8F8C9E90F56FF27","018353E30DB3225FAF549B62C74EA23E","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","15","0196D68851992632D8AFBC72A97C02CE","01A286D2DBF8E54AC7AF60EA475D8C18","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","16","014F8A218A85D2867A1915A25F21403C","018BAC2514EAA8FFA6EDDACF71A53463","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","17","018199F91BFAFFAE0512D079EE507FC9","01DA8188C92117746BB7C34FD21088EE","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","18","01AD8CC7B0BEA52AA46695E00836D283","01C30D636777D304332C9E7D4DA6774C","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","19","0176C54DD01B825DB07AC652FDB58481","018A25EDFEBEEC4C1F13F85B0AC1FA91","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","20","01481C9AD7F23611A304A703A06EE9BC","01FC2ECF39D66CBC7D8E03447C7084C5","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","21","010FF14E5BDE6B9935D34EF0059DEB80","013BBBB068DF184D7E914EC1D0672958","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","22","016943FBC2A3BDF1386CDF1466A64854","01D79F265CED6CFD247F77FCCA968B13","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","23","016AC4AAB8FB52EF9543CF9DF32C0B04","01AC672449D5493D950D03AE8BA9F139","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","24","01BE458C95B49B42A6D67B928462CD83","01EF33F114A7BE4AB5A1746B36EEF7AB","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","25","013C67C96F075EDC35E17465A7C5CD78","01FA8C758837FA7911AD460B42B2384C","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","26","014802F109EFC228031D3217A9E114AD","01C527DE13328C300574C033048946BD","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","27","0146FBA7A23D57869F711A19F742AFD5","018AC27D2F6543212645814BA65E3C46","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","28","016BF7C2A3A5AFF828BBE8F19656DB36","01757BFFF1D76B9945B8C69814064267","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","29","0177F0948D0988BDD99B6D282498F7AC","01A3C305AE69B5EDB57D0A3D10584170","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","30","015C0F02DB07641172802B72A8A8ADE5","0166BECC9447792D7865590A4C22013C","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","31","016EBF81B56DFED63B29607AD297F144","01C1479CA8401A0BC01F0FF8982A5F0E","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","32","010068DC8ED499DA2B7E7FC64AE69DE6","016E4E591440BD5EC00EA595295E8C09","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","33","017476AB316DA91A21832475A2201E6E","01D20D87FB61F87434F81EAAD953E615","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","34","01653199EACFE67EC85007845F9C594A","01EF4DF707B0E636502496C3742DA65F","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","35","015A74BACF3E03F8CFC7A5A8B6210945","01A1995ABC25A1DB4A7E0DD89ACA09CA","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","36","017B2235BAD77C7750DAFB57D6BB8B1E","01D954326D446FC53B6CA18688ECBC45","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","37","0128F93C4708384183AFC1455E285628","0129DE2A443CF44E76BCDDCE66FD45F1","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","38","01177B26BF1D2E7CEF9DC415E5CFEF2F","013CBF347EEF13561018AD28B7FD11CF","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","39","016CCC82267AF456EEEEC62A048E61E9","018FA3C125BF76156C39EF16D5FA403D","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","40","017791019EA30BF0AF439F2E01DBF795","0198AECAF49D80A7704AE1E61B4285E1","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","41","0128EB73EA061E4143110E0DDB2D5086","018E1C45D953E59A7F3A2173134A831B","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","42","0112464E22EA96E1FA24B4108D94490A","01A657E6F9DD5DC6EC526EACAD4CF981","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","43","0103E99FFBF410A1F5F80144C1AC8976","01EDA600FE79E9EE3F1803B85DFC709D","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","44","0104555079C4CF6202C7D6FEC9FDCCCD","01BA2F06B3F98DA4CA9FCE843A463ACF","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","45","0128BC847341313AD2A08BD6666476AE","015229DAB8A23610BA0A6D2C7C4D8D3A","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","46","01A78B98E2DE6C68D64137A136C0E9FF","01DE6B69C756C0EED2FD0BC17F6F73F2","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","47","01AE68DDDCA0196DCE436DEB1B9F9F55","01FD082F93AFC83E35DD27E55DC5DEB8","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","48","018030F65F41018A1EF44D2B74D1BB46","01B4BFFD8A1ACDE587DC39E5D8D7BA72","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","49","0101F557FB8C1C6C7123D97611884BC0","016BD88BC1A3A973FEC2E9130CED025E","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","50","018F43D8975ECD7B1A5BCAE44908FC68","01E8F427C47F9BAAF87A0DC3F1417759","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","51","0163ABC310674EBF8008372F0519C06E","019F6C9A1AFAECF5B25451304135A7D6","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","52","016F22947C74E50976B8F269F1729522","01A7A98CF7792A01D4A9E0F2D7534D97","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","53","014A9CB34479FB4A6CB53D671AF8F591","01ECEA3248E5614D47154A5F7811C869","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","54","018652B3DAD29F910C60328D324DA00E","01D00CE104DE38D0C2D2E11FA40D1B65","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","55","01065DAFCEA1DA071991649F1395E4AE","01744013B24B70E6CD252884F1683D7D","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","56","0139F277F697F731DD23793026C6AFF7","01D96E2E7C00D75C074CCD1049CA8E0F","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","57","012A186EBDF5C89419616B0D2EAAD5F3","01844D8B71E242CA8C88D6B30EF493C8","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","58","012E25DEC73667282FE995A2480F3898","01A2370EF178FFDFCBB099B836A2A9C6","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","59","01331C3A2F6F1EE69C2680DE11339FFB","01A1198E53AC4E466134CCE3BB932EA7","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","60","01C4C8F52D63C2600019D3389DB29248","01F1AC2B0A274B9BA11F22DEF5FD08F4","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","61","011136E78D87BB3CBB07B86C5389CC86","01B23F2BA3D9EEE6AC1E1C14A11AE93F","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","62","012DC58305C26A0605CE4624F5EC79A7","01B5C303E87AA0D13CC289B9E9F50779","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","63","0126FE4F83EC4002AB986D8FF233C3A6","0170FB005850265D208B40F54248E3A9","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","64","01672E8C86836203704D51FFDDF8D229","017509677D6681D926CD6FC7E7CEF27C","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","65","011839BC9F708E7C1780C99F7DA52AA6","016C1CFC7BB403C79DF0E3C14C348609","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","66","0152F13FCD2990EF7DC3C457AE14F6CD","0167EAFD58DB869351761D7AF42D3376","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","67","0100FC284EC4398EE30E1FA6C893B717","0154EE10CFE4FEB99F262AD41571CA07","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","68","0165D09DE19E8DE361ACB1D46D398A34","01811AC4E5252B14A65E5E221EC9267C","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","69","016EDFB389F79A837E2EB91DD26CECEB","01761256820BF8C1F26BD9AFEF56DE4E","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","70","018A66F4CAB0C46AC4B9AA6DBE4C9208","01A88A93A3529C7ECAA3176280FEE0D2","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "The JPEG Wizard2","","71","0103AEB2D5B835F3E556862994F777F3","01F59933CC03EBFE4CCAF43C60980CBE","","","The JPEG Wizard2"}, +{ ENUM_EDITOR_SW, "ZoomBrowser EX","","high","013BA18D5561625796E986FDBC09F846","01AC57E12793DFA7C46C704625C5AF0F","","","ZoomBrowser EX"}, +{ ENUM_EDITOR_SW, "ZoomBrowser EX","","highest","01BBB1709AC9C1F89220D955A31A8F34","01BBB1709AC9C1F89220D955A31A8F34","","","ZoomBrowser EX"}, +{ ENUM_EDITOR_SW, "ZoomBrowser EX","","low","012D821C6AB210E2A753BE053B8F55D0","0182408A81A4ABF04D4A34A8A5E98C58","","","ZoomBrowser EX"}, +{ ENUM_EDITOR_SW, "ZoomBrowser EX","","medium","0155D875C95B74D0F3C5835A62516F48","01D38A25358EB7649A254E19F1D46600","","","ZoomBrowser EX"}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T(""),_T("01BBB1709AC9C1F89220D955A31A8F34"),_T("zsig"),_T(""),_T(""),_T("EOS Viewer Utility")}, + { ENUM_EDITOR_SW, "","","","01BBB1709AC9C1F89220D955A31A8F34","zsig","","","EOS Viewer Utility"}, // Other software strings to look for (known software), without trying to // match particular signature. - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("Capture NX"),_T("Nikon Capture NX")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("DiMAGE Master"),_T("DiMAGE Master")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("FUJIFILM RAW FILE CONVERTER"),_T("FUJIFILM RAW FILE CONVERTER")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("Image Compressor"),_T("Image Compressor")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("Image Data Converter SR"),_T("Sony Image Data Converter")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("KODAK PROFESSIONAL DCS Photo Desk"),_T("KODAK PROFESSIONAL DCS Photo Desk")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("Microsoft Windows Live Photo Gallery"),_T("MS Windows Live Photo Gallery")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("Nero PhotoSnap"),_T("Nero PhotoSnap")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("Nikon Capture Editor"),_T("Nikon Capture Editor")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("Nikon Scan"),_T("Nikon Scan")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("Nikon Transfer"),_T("Nikon Transfer")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("OLYMPUS Studio"),_T("OLYMPUS Studio")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("PENTAX PHOTO Laboratory"),_T("PENTAX PHOTO Laboratory")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("PENTAX PHOTO Browser"),_T("PENTAX PHOTO Browser")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("PictureProject"),_T("PictureProject")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("QuickTime"),_T("QuickTime")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("Roxio PhotoSuite"),_T("Roxio PhotoSuite")}, - { ENUM_EDITOR_SW, _T(""),_T(""),_T("zqual"),_T("zsig"),_T("zsig"),_T(""),_T("ViewNX"),_T("ViewNX")}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","Capture NX","Nikon Capture NX"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","DiMAGE Master","DiMAGE Master"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","FUJIFILM RAW FILE CONVERTER","FUJIFILM RAW FILE CONVERTER"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","Image Compressor","Image Compressor"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","Image Data Converter SR","Sony Image Data Converter"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","KODAK PROFESSIONAL DCS Photo Desk","KODAK PROFESSIONAL DCS Photo Desk"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","Microsoft Windows Live Photo Gallery","MS Windows Live Photo Gallery"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","Nero PhotoSnap","Nero PhotoSnap"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","Nikon Capture Editor","Nikon Capture Editor"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","Nikon Scan","Nikon Scan"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","Nikon Transfer","Nikon Transfer"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","OLYMPUS Studio","OLYMPUS Studio"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","PENTAX PHOTO Laboratory","PENTAX PHOTO Laboratory"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","PENTAX PHOTO Browser","PENTAX PHOTO Browser"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","PictureProject","PictureProject"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","QuickTime","QuickTime"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","Roxio PhotoSuite","Roxio PhotoSuite"}, + { ENUM_EDITOR_SW, "","","zqual","zsig","zsig","","ViewNX","ViewNX"}, // Unknown: @@ -3389,7 +3388,7 @@ const CompSigConst CDbSigs::m_sSigList[] = { // - DVWare 1.0 (Seen in AIPTEK DV 6800) // - IRSDK - { ENUM_EDITOR_UNSET, _T("*"),_T(""),_T(""),_T(""),_T(""),_T(""),_T(""),_T("")} + { ENUM_EDITOR_UNSET, "*","","","","","","",""} }; @@ -3400,30 +3399,30 @@ const CompSigConst CDbSigs::m_sSigList[] = { // Exceptions of make/model digicams/phones that don't // generally have makernotes present const CompExcMm CDbSigs::m_sExcMmNoMkrList[] = { - {_T("Apple"), _T("iPhone")}, // ? always the case? - {_T("CoreLogic"), _T("SAMSUNG")}, // strUmQual=swSamsung SGH-E900 - {_T("HTC"), _T("Hermes")}, // strUmQual=T-Mobile MDA Vario II (a.k.a HTC Hermes) - {_T("MOTOROLA"), _T("")}, // model=RAZRV3x - {_T("Nokia"), _T("")}, // model=5200 - {_T("???"), _T("Treo*")}, // model=Treo 680 - {_T("Research In Motion"), _T("")}, // model=BlackBerry 9000 (=Blackberry Bold) - {_T("RIM"), _T("")}, // model=BlackBerry 8100 (=Blackberry Pearl) - {_T("Sony Ericsson"), _T("")}, // model=K750i - {_T("SONY"), _T("DIGITALMAVICA")}, - {_T("SONY"), _T("CYBERSHOT")}, - {_T("SONY"), _T("CYBERSHOT U")}, - {_T("SONY"), _T("MAVICA")}, - {_T("SONY ERICSSON"), _T("")}, // model=SONY ERICSSON P990i - {_T("Vivitar"), _T("")}, // model=ViviCam3746 - {_T("*"), _T("")}, + {"Apple", "iPhone"}, // ? always the case? + {"CoreLogic", "SAMSUNG"}, // strUmQual=swSamsung SGH-E900 + {"HTC", "Hermes"}, // strUmQual=T-Mobile MDA Vario II (a.k.a HTC Hermes) + {"MOTOROLA", ""}, // model=RAZRV3x + {"Nokia", ""}, // model=5200 + {"???", "Treo*"}, // model=Treo 680 + {"Research In Motion", ""}, // model=BlackBerry 9000 (=Blackberry Bold) + {"RIM", ""}, // model=BlackBerry 8100 (=Blackberry Pearl) + {"Sony Ericsson", ""}, // model=K750i + {"SONY", "DIGITALMAVICA"}, + {"SONY", "CYBERSHOT"}, + {"SONY", "CYBERSHOT U"}, + {"SONY", "MAVICA"}, + {"SONY ERICSSON", ""}, // model=SONY ERICSSON P990i + {"Vivitar", ""}, // model=ViviCam3746 + {"*", ""}, }; // Make/models that are known "edited" const CompExcMm CDbSigs::m_sExcMmIsEditList[] = { - {_T("Noritsu"), _T("")}, // Lab - {_T("Mercury Peripherals Inc."), _T("DigitalCam Pro")}, // Scanner driver - {_T("*"), _T("")}, + {"Noritsu", ""}, // Lab + {"Mercury Peripherals Inc.", "DigitalCam Pro"}, // Scanner driver + {"*", ""}, }; // TODO: diff --git a/source/SnoopConfig.cpp b/source/SnoopConfig.cpp index cfdda2a..e9831bd 100644 --- a/source/SnoopConfig.cpp +++ b/source/SnoopConfig.cpp @@ -1,685 +1,789 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "StdAfx.h" -#include ".\snoopconfig.h" -#include "snoop.h" -#include "Registry.h" - -//#include // for SHGetFolderPath - - -// Define the defaults for the application configuration -CSnoopConfig::CSnoopConfig(void) -{ - - // Debug log - strDebugLogFname = _T(".\\JPEGsnoop-debug.log"); - fpDebugLog = NULL; - bDebugLogEnable = false; - - // Default to showing message dialogs - bInteractive = true; - - // Command-line modes - bGuiMode = true; - bCmdLineOpenEn = false; - strCmdLineOpenFname = _T(""); - bCmdLineOutputEn = false; // No output file specified - strCmdLineOutputFname = _T(""); - bCmdLineBatchEn = false; - strCmdLineBatchDirName = _T(""); - bCmdLineBatchRec = false; - bCmdLineExtractEn = false; - bCmdLineExtractDhtAvi = false; - bCmdLineBatchSrch = false; - bCmdLineDoneMsg = false; - - eCmdLineOffset = DEC_OFFSET_START; - nCmdLineOffsetPos = 0; - - bCmdLineHelp = false; - - nPosStart = 0; - - // -------------------------------- - // Registry settings - bDirty = false; // Have the registry options been dirtied? - bEulaAccepted = false; - bUpdateAuto = true; - nUpdateAutoDays = 14; // Check every 14 days - strUpdateLastChk = _T(""); - strDbDir = _T(""); - bReprocessAuto = false; - bDecodeScanImg = true; - bDecodeScanImgAc = false; // Coach message will be shown just in case - bSigSearch = true; - - bOutputScanDump = false; // Print snippet of scan data - bOutputDHTexpand = false; // Print expanded huffman tables - bDecodeMaker = false; - bDumpHistoY = false; - - // Difference in performance: 1dsmk2 image: - // Performance boost ~ 25% - bHistoEn = false; // Histogram & clipping stats enabled? - - bStatClipEn = false; // UNUSED: Enable Scan Decode clip stats? - - bDbSubmitNet = true; // Default to submit new DB entries to web - - bExifHideUnknown = true; // Default to hiding unknown EXIF tags - bRelaxedParsing = false; // Normal parsing stops on bad marker - - nErrMaxDecodeScan = 20; - - strBatchLastInput = _T("C:\\"); // Default batch processing directory (input) - strBatchLastOutput = _T("C:\\"); // Default batch processing directory (output) - strBatchExtensions = _T(".jpg,.jpeg"); // Default batch extension list - - bDecodeColorConvert = true; // Perform color convert after scan decode - - // Reset coach message flags - CoachReset(); - - // Reset the current filename - strCurFname = _T(""); - - // -------------------------------- - - - // Determine operating system - // Particularly for: WinHTTP functions - OSVERSIONINFO osvi; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - - GetVersionEx(&osvi); - - bIsWindowsNTorLater = (osvi.dwPlatformId >= VER_PLATFORM_WIN32_NT); - - bIsWindowsXPorLater = - ( (osvi.dwMajorVersion > 5) || - ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1) )); - - /* - // Debug code to output the version info - CString strTmp; - strTmp.Format(_T("OS Version: Platform=[%u] VerMajor=[%u] VerMinor=[%u] (>=NT:%s >=XP:%s)"), - osvi.dwPlatformId,osvi.dwMajorVersion,osvi.dwMinorVersion, - (bIsWindowsNTorLater)?"Y":"N",(bIsWindowsXPorLater)?"Y":"N"); - AfxMessageBox(strTmp); - */ - -} - -CSnoopConfig::~CSnoopConfig(void) -{ -} - - -// This is generally called after app initializes and registry -// has just been loaded. -void CSnoopConfig::UseDefaults() -{ - // Assume all settings are to their default values - // But some need copying over -} - -// Update the flag to mark the configuration as dirty / modified -// - This is used later to indicate that a resave is required -// -void CSnoopConfig::Dirty(bool mode) -{ - bDirty = mode; -} - -// Fetch all configuration values from the registry -void CSnoopConfig::RegistryLoad() -{ - CString strKeyPath; - CString strField; - CString strKeyFull; - - strKeyPath = REG_KEY_PATH; - - ///////////// - - strField = _T("General\\UserDbPath"); - strKeyFull = strKeyPath + strField; - CRegString regUserDbPath(strKeyFull,_T("???"),TRUE,HKEY_CURRENT_USER); - - // Try to load the registry entry - if ((CString)regUserDbPath == _T("???")) { - // None specified, so determine a suitable default - strDbDir = GetDefaultDbDir(); - bDirty = true; - - } else { - // Specified, so store in App Config struct - strDbDir = regUserDbPath; - } - - - - ////////////////// - - CString strCurDate; - CTime tmeToday = CTime::GetCurrentTime(); - strCurDate = tmeToday.Format(_T("%Y%m%d")); - - strField = _T("General\\UpdateLastChk"); - strKeyFull = strKeyPath + strField; - CRegString regUpdateLastChk(strKeyFull,_T("???"),TRUE,HKEY_CURRENT_USER); - - // Try to load the registry entry - if ((CString)regUpdateLastChk == _T("???")) { - // None specified, so determine a suitable default - strUpdateLastChk = strCurDate; - bDirty = true; - } else { - // Specified, so store in App Config struct - strUpdateLastChk = regUpdateLastChk; - } - - ////////////////// - -// RegistryLoadStr( _T("General\\UserDbPath"), "???", strDbDir); - RegistryLoadBool(_T("General\\UpdateAuto"), 999, bUpdateAuto); - RegistryLoadUint(_T("General\\UpdateAutoDays"), 999, nUpdateAutoDays); -// RegistryLoadStr( _T("General\\UpdateLastChk"), "???", strUpdateLastChk); - RegistryLoadBool(_T("General\\EulaAccepted"), 999, bEulaAccepted); - RegistryLoadBool(_T("General\\ReprocessAuto"), 999, bReprocessAuto); - RegistryLoadBool(_T("General\\SigSearch"), 999, bSigSearch); - RegistryLoadBool(_T("General\\DecScanImg"), 999, bDecodeScanImg); - RegistryLoadBool(_T("General\\DecScanImgAc"), 999, bDecodeScanImgAc); - - RegistryLoadBool(_T("General\\DumpScan"), 999, bOutputScanDump); - RegistryLoadBool(_T("General\\DumpDHTExpand"), 999, bOutputDHTexpand); - RegistryLoadBool(_T("General\\DecMaker"), 999, bDecodeMaker); - RegistryLoadBool(_T("General\\DumpHistoY"), 999, bDumpHistoY); -// RegistryLoadBool(_T("General\\DecScanClip"), 999, bStatClipEn); - RegistryLoadBool(_T("General\\DecScanHisto"), 999, bHistoEn); - - RegistryLoadBool(_T("General\\DbSubmitNet"), 999, bDbSubmitNet); - RegistryLoadBool(_T("General\\ExifHideUnk"), 999, bExifHideUnknown); - RegistryLoadBool(_T("General\\RelaxedParsing"), 999, bRelaxedParsing); - - RegistryLoadUint(_T("Report\\ErrMaxDecodeScan"), 999, nErrMaxDecodeScan); - - RegistryLoadStr( _T("General\\BatchLastInput"), _T(""), strBatchLastInput); - RegistryLoadStr( _T("General\\BatchLastOutput"), _T(""), strBatchLastOutput); - RegistryLoadStr( _T("General\\BatchExtensions"), _T(""), strBatchExtensions); - - RegistryLoadBool(_T("Coach\\ReprocessAuto"), 999, bCoachReprocessAuto); - RegistryLoadBool(_T("Coach\\DecodeIdct"), 999, bCoachDecodeIdct); - - // Deprecated Registry strings - // FIXME: Later on, decide if we should delete deprecated strings if found - // "General\\ScanImgDec" - // "General\\ScanImgDecDef" - // "General\\ScanPreviewDef" - // "General\\SigSearchAuto" -} - -// Write all configuration parameters to the registry -// - Skip write if no changes were made (!bDirty) -// -void CSnoopConfig::RegistryStore() -{ - // If no changes made, skip - if (!bDirty) { - return; - } - - RegistryStoreStr( _T("General\\UserDbPath"), strDbDir); - RegistryStoreBool( _T("General\\UpdateAuto"), bUpdateAuto); - RegistryStoreUint( _T("General\\UpdateAutoDays"), nUpdateAutoDays); - RegistryStoreStr( _T("General\\UpdateLastChk"), strUpdateLastChk); - RegistryStoreBool( _T("General\\EulaAccepted"), bEulaAccepted); - RegistryStoreBool( _T("General\\ReprocessAuto"), bReprocessAuto); - RegistryStoreBool( _T("General\\SigSearch"), bSigSearch); - RegistryStoreBool( _T("General\\DecScanImg"), bDecodeScanImg); - RegistryStoreBool( _T("General\\DecScanImgAc"), bDecodeScanImgAc); - - RegistryStoreBool( _T("General\\DumpScan"), bOutputScanDump); - RegistryStoreBool( _T("General\\DumpDHTExpand"), bOutputDHTexpand); - RegistryStoreBool( _T("General\\DecMaker"), bDecodeMaker); - RegistryStoreBool( _T("General\\DumpHistoY"), bDumpHistoY); - RegistryStoreBool( _T("General\\DecScanHisto"), bHistoEn); - - RegistryStoreBool( _T("General\\DbSubmitNet"), bDbSubmitNet); - RegistryStoreBool( _T("General\\ExifHideUnk"), bExifHideUnknown); - RegistryStoreBool( _T("General\\RelaxedParsing"), bRelaxedParsing); - - RegistryStoreUint( _T("Report\\ErrMaxDecodeScan"), nErrMaxDecodeScan); - - RegistryStoreStr( _T("General\\BatchLastInput"), strBatchLastInput); - RegistryStoreStr( _T("General\\BatchLastOutput"), strBatchLastOutput); - RegistryStoreStr( _T("General\\BatchExtensions"), strBatchExtensions); - - RegistryStoreBool( _T("Coach\\ReprocessAuto"), bCoachReprocessAuto); - RegistryStoreBool( _T("Coach\\DecodeIdct"), bCoachDecodeIdct); - - // Registry entries are no longer dirty - bDirty = false; - -} - - -// Load a string from the registry -// -// INPUT: -// - strKey Registry key to read -// - strDefault Default value (in case the key doesn't exist) -// -// OUTPUT: -// - String value from the registry key (or strDefault if not defined) -// -void CSnoopConfig::RegistryLoadStr(CString strKey,CString strDefault,CString &strSetting) -{ - CString strKeyPath = REG_KEY_PATH; - CString strKeyFull = strKeyPath + strKey; - CRegString reg(strKeyFull,strDefault,TRUE,HKEY_CURRENT_USER); - - // Try to load the registry entry - if (reg == strDefault) { - // None specified, so leave default from constructor - } else { - // Specified, so store in App Config struct - strSetting = reg; - } -} - -// Load a boolean from the registry -// -// INPUT: -// - strKey Registry key to read -// - nDefault Default value (in case the key doesn't exist) -// -// OUTPUT: -// - Boolean value from the registry key (or nDefault if not defined) -// -void CSnoopConfig::RegistryLoadBool(CString strKey,unsigned nDefault,bool &bSetting) -{ - CString strKeyPath = REG_KEY_PATH; - CString strKeyFull = strKeyPath + strKey; - CRegDWORD reg(strKeyFull,nDefault,TRUE,HKEY_CURRENT_USER); - - // Try to load the registry entry - if (reg == nDefault) { - // None specified, so leave default from constructor - } else { - // Specified, so store in App Config struct - bSetting = (reg>=1)?true:false; - } -} - -// Load an UINT32 from the registry -// -// INPUT: -// - strKey Registry key to read -// - nDefault Default value (in case the key doesn't exist) -// -// OUTPUT: -// - UINT32 value from the registry key (or nDefault if not defined) -// -void CSnoopConfig::RegistryLoadUint(CString strKey,unsigned nDefault,unsigned &nSetting) -{ - CString strKeyPath = REG_KEY_PATH; - CString strKeyFull = strKeyPath + strKey; - CRegDWORD reg(strKeyFull,nDefault,TRUE,HKEY_CURRENT_USER); - - // Try to load the registry entry - if (reg == nDefault) { - // None specified, so leave default from constructor - } else { - // Specified, so store in App Config struct - nSetting = reg; - } -} - -// Store an UINT32 to the registry -// -// INPUT: -// - strKey Registry key to write -// - nSetting Value to store at registry key -// -void CSnoopConfig::RegistryStoreUint(CString strKey,unsigned nSetting) -{ - CString strKeyPath = REG_KEY_PATH; - CString strKeyFull = strKeyPath + strKey; - CRegDWORD regWr(strKeyFull,999,TRUE,HKEY_CURRENT_USER); - regWr = nSetting; - CRegDWORD regRd(strKeyFull,999,TRUE,HKEY_CURRENT_USER); - ASSERT(regRd == nSetting); -} - -// Store a boolean to the registry -// -// INPUT: -// - strKey Registry key to write -// - bSetting Value to store at registry key -// -void CSnoopConfig::RegistryStoreBool(CString strKey,bool bSetting) -{ - RegistryStoreUint(strKey,(bSetting)?1:0); -} - -// Store a string to the registry -// -// INPUT: -// - strKey Registry key to write -// - strSetting Value to store at registry key -// -void CSnoopConfig::RegistryStoreStr(CString strKey,CString strSetting) -{ - CString strKeyPath = REG_KEY_PATH; - CString strKeyFull = strKeyPath + strKey; - CRegString regWr(strKeyFull,_T("???"),TRUE,HKEY_CURRENT_USER); - regWr = strSetting; - CRegString regRd(strKeyFull,_T("???"),TRUE,HKEY_CURRENT_USER); - ASSERT(regRd == strSetting); -} - - - -// Reset coach messages -void CSnoopConfig::CoachReset() -{ - // Enable all coach messages - bCoachReprocessAuto = true; - bCoachDecodeIdct = true; - - Dirty(); -} - -// Select a suitable working directory, create it if it doesn't already exist -CString CSnoopConfig::GetDefaultDbDir() -{ - TCHAR szUserProfile[MAX_PATH]; - TCHAR szFilePath[MAX_PATH]; - - - // Apparently, the SHGetFolderPath is not well supported in earlier - // versions of the OS, so we are only going to try it if we are - // running Win XP or later. - // See: http://support.microsoft.com/kb/310294 - // Older OS versions may require linking to shfolder.dll, which I decided - // not to implement yet. - - // Since I could not get SHGetFolderPath() to compile, even after including - // , I decided to revert to older version of the call: - // https://msdn2.microsoft.com/en-us/library/aa931257.aspx - - if (bIsWindowsNTorLater) { - // Get path for each computer, non-user specific and non-roaming data. - //if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_APPDATA, - // NULL, 0, szFilePath ) ) ) - if ( SHGetSpecialFolderPath( NULL, szFilePath, CSIDL_APPDATA, true )) - { - // Append product-specific path. - PathAppend( szFilePath, _T("\\JPEGsnoop") ); - - // Since the full path may not already exist, and CreateDirectory() only - // works on one level of hierarchy at a time, use a recursive function - // to do the job. - CreateDir(szFilePath); - } else { - // No error handling - AfxMessageBox(_T("Problem trying to locate suitable directory; please choose manually")); - - // As a default, start with EXE directory - wsprintf(szFilePath,GetExeDir()); - } - } else { - - // Apparently not a recent version of Windows, so we'll revert - // to some older methods at getting the directory - - ExpandEnvironmentStrings(_T("%userprofile%"),szUserProfile,sizeof(szUserProfile)/sizeof(*szUserProfile)); - - // NOTE: - // - In Win95/98 it is likely that the above will return the literal "%userprofile%" - // so in that case we don't want to create a directory -- use the exe dir instead - if (!_tcscmp(szUserProfile,_T("%userprofile%"))) { - wsprintf(szFilePath, _T("")); - // Since we can't locate the user profile directory from environment - // strings, we don't want to create any subdirectory. If we were to - // call CreateDir() with an empty string, we'd end up with a garbled - // folder name created! - - // So, for now, default to executable directory - wsprintf(szFilePath,GetExeDir()); - } else { - // FIXME - // Note that the following is not very good as it doesn't select - // a suitable directory for non-English systems. - wsprintf(szFilePath, _T("%s%s"), szUserProfile,_T("\\Application Data\\JPEGsnoop")); - - // Since the full path may not already exist, and CreateDirectory() only - // works on one level of hierarchy at a time, use a recursive function - // to do the job. - CreateDir(szFilePath); - } - } - return szFilePath; -} - -// Get the directory path of the JPEGsnoop executable -// - This is used as a default location for the user signature database -CString CSnoopConfig::GetExeDir() -{ - TCHAR szPath[1024]; - GetModuleFileName(AfxGetApp()->m_hInstance, szPath, sizeof(szPath)/sizeof(*szPath)); - - TCHAR *ptr = _tcsrchr(szPath, '\\'); - - if (ptr) - { - ptr[1] = '\0'; - } - - ASSERT(_tcslen(szPath) < sizeof(szPath)); - - return szPath; -} - -// Recursively create directories as needed to create full path -// TODO: Should replace this by SHCreateDirectoryEx() -void CSnoopConfig::CreateDir(LPTSTR Path) -{ - TCHAR DirName[256]; - TCHAR* p = Path; - TCHAR* q = DirName; - DirName[0] = '\0'; // Start as null-terminated - - while(*p) - { - if (('\\' == *p) || ('/' == *p)) - { - if (':' != *(p-1)) - { - CreateDirectory(DirName, NULL); - } - } - *q++ = *p++; - *q = '\0'; - } - CreateDirectory(DirName, NULL); -} - - - -// Create a new debug log if the control key is pressed during startup -// -// Note that we do not keep the log file open to help ensure that -// all debug entries are flushed to the file (in case of an -// an application crash). -// -bool CSnoopConfig::DebugLogCreate() -{ -#ifdef DEBUG_LOG_OUT - - if (strDebugLogFname == _T("")) { - return false; - } - - // Detect control keys - // - VK_CONTROL = Control key - // - VK_SHIFT = Shift - // - VK_MENU = Alt? - if (GetAsyncKeyState(VK_CONTROL)) { - AfxMessageBox(_T("Debug Log Enabled")); - bDebugLogEnable = true; - } else { - return true; - } - - ASSERT(fpDebugLog == NULL); - - try - { - // Open specified file - fpDebugLog = new CStdioFile(strDebugLogFname, CFile::modeCreate| CFile::modeWrite | CFile::typeText | CFile::shareDenyNone); - } - catch (CFileException* e) - { - TCHAR msg[MAX_BUF_EX_ERR_MSG]; - CString strError; - e->GetErrorMessage(msg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - strError.Format(_T("ERROR: Couldn't open debug log file for write [%s]: [%s]"), - (LPCTSTR)strDebugLogFname, (LPCTSTR)msg); - AfxMessageBox(strError); - fpDebugLog = NULL; - - return false; - } - - CString strLine; - strLine.Format(_T("JPEGsnoop version [%s]\r\n"),VERSION_STR); - fpDebugLog->WriteString(strLine); - fpDebugLog->WriteString(_T("-----\r\n")); - - // Close the file - if (fpDebugLog) { - fpDebugLog->Close(); - delete fpDebugLog; - fpDebugLog = NULL; - } - - // Extra code to record OS version - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - strLine.Format(_T("OS: PlatformId = %u"),osvi.dwPlatformId); - if (DEBUG_EN) DebugLogAdd(strLine); - strLine.Format(_T("OS: MajorVersion = %u"),osvi.dwMajorVersion); - if (DEBUG_EN) DebugLogAdd(strLine); - strLine.Format(_T("OS: MinorVersion = %u"),osvi.dwMinorVersion); - if (DEBUG_EN) DebugLogAdd(strLine); - strLine.Format(_T("OS: BuildNumber = %u"),osvi.dwBuildNumber); - if (DEBUG_EN) DebugLogAdd(strLine); - strLine.Format(_T("OS: OSVersionInfoSize = %u"),osvi.dwOSVersionInfoSize); - if (DEBUG_EN) DebugLogAdd(strLine); - if (DEBUG_EN) DebugLogAdd(_T("\n")); - -#endif - return true; -} - -// If the debug log has been enabled, append the string parameter -// to the log file. -// -// Note that we do not keep the log file open to help ensure that -// all debug entries are flushed to the file (in case of an -// an application crash). -// -bool CSnoopConfig::DebugLogAdd(CString strText) -{ -#ifdef DEBUG_LOG_OUT - - if (!bDebugLogEnable) { - return true; - } - - if (strDebugLogFname == _T("")) { - return false; - } - - ASSERT(fpDebugLog == NULL); - - try - { - // Open specified file but append - fpDebugLog = new CStdioFile(strDebugLogFname, CFile::modeCreate| CFile::modeWrite | CFile::typeText | CFile::shareDenyNone | - CFile::modeNoTruncate); - } - catch (CFileException* e) - { - TCHAR msg[MAX_BUF_EX_ERR_MSG]; - CString strError; - e->GetErrorMessage(msg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - strError.Format(_T("ERROR: Couldn't open debug log file for append [%s]: [%s]"), - (LPCTSTR)strDebugLogFname, (LPCTSTR)msg); - AfxMessageBox(strError); - fpDebugLog = NULL; - - return false; - } - - // Now seek to the end of the file - fpDebugLog->SeekToEnd(); - - CString strLine; - - // Get current time -/* - time_t sTime; - struct tm sNow; - unsigned nTmYear,nTmMon,nTmDay; - unsigned nTmHour,nTmMin,nTmSec; - localtime_s(&sNow,&sTime); - nTmYear = sNow.tm_year + 1900; - nTmMon = sNow.tm_mon + 1; - nTmDay = sNow.tm_mday; - nTmHour = sNow.tm_hour; - nTmMin = sNow.tm_min; - nTmSec = sNow.tm_sec; - - - // Generate log line - //strLine.Format(_T("[%4u/%2u/%2u %2u:%2u:%2u] %s\r\n"),nTmYear,nTmMon,nTmDay,nTmHour,nTmMin,nTmSec,strText); -*/ - strLine.Format(_T("%s\n"),strText); - fpDebugLog->WriteString(strLine); - - // Close the file - if (fpDebugLog) { - fpDebugLog->Close(); - delete fpDebugLog; - fpDebugLog = NULL; - } - -#endif - return true; -} \ No newline at end of file +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include + +#include "JfifDecode.h" +#include "JPEGsnoop.h" +//#include "JPEGsnoopCore.h" +#include "snoop.h" + +#include "SnoopConfig.h" + +// Define the defaults for the application configuration +CSnoopConfig::CSnoopConfig(CjfifDecode *pJfifDec) +{ + m_pJfifDec = pJfifDec; + + // Debug log + strDebugLogFname = ".\\JPEGsnoop-debug.log"; + fpDebugLog = NULL; + bDebugLogEnable = false; + + // Default to showing message dialogs + bInteractive = true; + + // Command-line modes + bGuiMode = true; + bCmdLineOpenEn = false; + strCmdLineOpenFname = ""; + bCmdLineOutputEn = false; // No output file specified + strCmdLineOutputFname = ""; + bCmdLineBatchEn = false; + strCmdLineBatchDirName = ""; + bCmdLineBatchRec = false; + bCmdLineExtractEn = false; + bCmdLineExtractDhtAvi = false; + bCmdLineBatchSrch = false; + bCmdLineDoneMsg = false; + + eCmdLineOffset = DEC_OFFSET_START; + nCmdLineOffsetPos = 0; + + bCmdLineHelp = false; + + nPosStart = 0; + + // -------------------------------- + // Registry settings + bDirty = false; // Have the registry options been dirtied? + bEulaAccepted = false; + bUpdateAuto = true; + nUpdateAutoDays = 14; // Check every 14 days + strUpdateLastChk = ""; + strDbDir = ""; + bReprocessAuto = false; + bDecodeScanImg = true; + bDecodeScanImgAc = false; // Coach message will be shown just in case + bSigSearch = true; + + bOutputScanDump = false; // Print snippet of scan data + bOutputDHTexpand = false; // Print expanded huffman tables + bDecodeMaker = false; + bDumpHistoY = false; + + // Difference in performance: 1dsmk2 image: + // Performance boost ~ 25% + bHistoEn = false; // Histogram & clipping stats enabled? + bStatClipEn = false; // UNUSED: Enable Scan Decode clip stats? + + bDbSubmitNet = true; // Default to submit new DB entries to web + + bExifHideUnknown = true; // Default to hiding unknown EXIF tags + bRelaxedParsing = false; // Normal parsing stops on bad marker + + nErrMaxDecodeScan = 20; + + strBatchLastInput = "C:\\"; // Default batch processing directory (input + strBatchLastOutput = "C:\\"; // Default batch processing directory (output + strBatchExtensions = ".jpg,.jpeg"; // Default batch extension list + + bDecodeColorConvert = true; // Perform color convert after scan decode + + // Reset coach message flags + CoachReset(); + + // Reset the current filename + strCurFname = ""; + + // -------------------------------- + + // Determine operating system + // Particularly for: WinHTTP functions +// OSVERSIONINFO osvi; + +// ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); +// osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + +// GetVersionEx(&osvi); + +// bIsWindowsNTorLater = (osvi.dwPlatformId >= VER_PLATFORM_WIN32_NT); + +// bIsWindowsXPorLater = +// ( (osvi.dwMajorVersion > 5) || +// ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1) )); + + /* + // Debug code to output the version info + QString strTmp; + strTmp.Format("OS Version: Platform=[%u] VerMajor=[%u] VerMinor=[%u] (>=NT:%s >=XP:%s)", + osvi.dwPlatformId,osvi.dwMajorVersion,osvi.dwMinorVersion, + (bIsWindowsNTorLater)?"Y":"N",(bIsWindowsXPorLater)?"Y":"N"); + AfxMessageBox(strTmp); + */ + qDebug() << "CSnoopConfig::CSnoopConfig End"; +} + +CSnoopConfig::~CSnoopConfig(void) +{ +} + +// This is generally called after app initializes and registry has just been loaded. +void CSnoopConfig::UseDefaults() +{ + // Assume all settings are to their default values + // But some need copying over +} + +// Update the flag to mark the configuration as dirty / modified +// - This is used later to indicate that a resave is required +// +void CSnoopConfig::Dirty(bool mode) +{ + bDirty = mode; +} + +// Fetch all configuration values from the registry +void CSnoopConfig::RegistryLoad() +{ + QSettings settings; + + QString regUserDbPath = settings.value("General\\UserDbPath", "").toString(); + + // Try to load the registry entry + if(regUserDbPath == "") + { + // None specified, so determine a suitable default +// strDbDir = GetDefaultDbDir(); + bDirty = true; + } + else + { + // Specified, so store in App Config struct + strDbDir = regUserDbPath; + } + + ////////////////// + + QString strCurDate = QDateTime::currentDateTime().toString("yyyymmdd"); + + QString regUpdateLastChk = settings.value("General\\UpdateLastChk", "").toString(); + + // Try to load the registry entry + if(regUpdateLastChk == "") + { + // None specified, so determine a suitable default + strUpdateLastChk = strCurDate; + bDirty = true; + } + else + { + // Specified, so store in App Config struct + strUpdateLastChk = regUpdateLastChk; + } + + bUpdateAuto = settings.value("General\\UpdateAuto", true).toBool(); + nUpdateAutoDays = settings.value("General\\UpdateAutoDays", 14).toInt(); + bEulaAccepted = settings.value("General\\EulaAccepted", false).toBool(); + bReprocessAuto = settings.value("General\\ReprocessAuto", false).toBool(); + bSigSearch = settings.value("General\\SigSearch", true).toBool(); + bDecodeScanImg = settings.value("General\\DecScanImg", false).toBool(); + bDecodeScanImgAc = settings.value("General\\DecScanImgAc", false).toBool(); + + bOutputScanDump = settings.value("General\\DumpScan", false).toBool(); + bOutputDHTexpand = settings.value("General\\DumpDHTExpand", false).toBool(); + bDecodeMaker = settings.value("General\\DecMaker", false).toBool(); + bDumpHistoY = settings.value("General\\DumpHistoY", false).toBool(); +// RegistryLoadBool("General\\DecScanClip"), 999, bStatClipEn; + bHistoEn = settings.value("General\\DecScanHisto", false).toBool(); + + bDbSubmitNet = settings.value("General\\DbSubmitNet", true).toBool(); + bExifHideUnknown = settings.value("General\\ExifHideUnk", true).toBool(); + bRelaxedParsing = settings.value("General\\RelaxedParsing", false).toBool(); + + nErrMaxDecodeScan = settings.value("General\\ErrMaxDecodeScan", 20).toInt(); + + strBatchLastInput = settings.value("General\\BatchLastInput", "").toString(); + strBatchLastOutput = settings.value("General\\BatchLastOutput", "").toString(); + strBatchExtensions = settings.value("General\\BatchExtensions", "").toString(); + + bCoachReprocessAuto = settings.value("Coach\\ReprocessAuto", false).toBool(); + bCoachDecodeIdct = settings.value("Coach\\DecodeIdct", false).toBool(); + + if(bHistoEn || bDumpHistoY || bDecodeScanImgAc) + { + docImageDirty(); + } + + printSettings(); + // Deprecated Registry strings + // FIXME: Later on, decide if we should delete deprecated strings if found + // "General\\ScanImgDec" + // "General\\ScanImgDecDef" + // "General\\ScanPreviewDef" + // "General\\SigSearchAuto" +} + +// Write all configuration parameters to the registry +// - Skip write if no changes were made (!bDirty) +// +void CSnoopConfig::RegistryStore() +{ + QSettings settings; + + // If no changes made, skip + if(bDirty) + { + qDebug() << "Saving Config"; + settings.setValue("General\\UserDbPath", strDbDir); + settings.setValue("General\\UpdateAuto", bUpdateAuto); + settings.setValue("General\\UpdateAutoDays", nUpdateAutoDays); + settings.setValue("General\\UpdateLastChk", strUpdateLastChk); + settings.setValue("General\\EulaAccepted", bEulaAccepted); + settings.setValue("General\\ReprocessAuto", bReprocessAuto); + settings.setValue("General\\SigSearch", bSigSearch); + settings.setValue("General\\DecScanImg", bDecodeScanImg); + settings.setValue("General\\DecScanImgAc", bDecodeScanImgAc); + + settings.setValue("General\\DumpScan", bOutputScanDump); + settings.setValue("General\\DumpDHTExpand", bOutputDHTexpand); + settings.setValue("General\\DecMaker", bDecodeMaker); + settings.setValue("General\\DumpHistoY", bDumpHistoY); + settings.setValue("General\\DecScanHisto", bHistoEn); + + settings.setValue("General\\DbSubmitNet", bDbSubmitNet); + settings.setValue("General\\ExifHideUnk", bExifHideUnknown); + settings.setValue("General\\RelaxedParsing", bRelaxedParsing); + + settings.setValue("Report\\ErrMaxDecodeScan", nErrMaxDecodeScan); + + settings.setValue("General\\BatchLastInput", strBatchLastInput); + settings.setValue("General\\BatchLastOutput", strBatchLastOutput); + settings.setValue("General\\BatchExtensions", strBatchExtensions); + + settings.setValue("Coach\\ReprocessAuto", bCoachReprocessAuto); + settings.setValue("Coach\\DecodeIdct", bCoachDecodeIdct); + + // Registry entries are no longer dirty + bDirty = false; + qDebug() << settings.status(); + } +} + +void CSnoopConfig::printSettings() +{ + qDebug() << "strDbDir" << strDbDir; + qDebug() << "bUpdateAuto" << bUpdateAuto; + qDebug() << "nUpdateAutoDays" << nUpdateAutoDays; + qDebug() << "strUpdateLastChk" << strUpdateLastChk; + qDebug() << "bEulaAccepted" << bEulaAccepted; + qDebug() << "bReprocessAuto" << bReprocessAuto; + qDebug() << "bSigSearch" << bSigSearch; + qDebug() << "bDecodeScanImg" << bDecodeScanImg; + qDebug() << "bDecodeScanImgAc" << bDecodeScanImgAc; + + qDebug() << "bOutputScanDump" << bOutputScanDump; + qDebug() << "bOutputDHTexpand" << bOutputDHTexpand; + qDebug() << "bDecodeMaker" << bDecodeMaker; + qDebug() << "bDumpHistoY" << bDumpHistoY; + qDebug() << "bHistoEn" << bHistoEn; + + qDebug() << "bDbSubmitNet" << bDbSubmitNet; + qDebug() << "bExifHideUnknown" << bExifHideUnknown; + qDebug() << "bRelaxedParsing" << bRelaxedParsing; + + qDebug() << "nErrMaxDecodeScan" << nErrMaxDecodeScan; + + qDebug() << "strBatchLastInput" << strBatchLastInput; + qDebug() << "strBatchLastOutput" << strBatchLastOutput; + qDebug() << "strBatchExtensions" << strBatchExtensions; + + qDebug() << "bCoachReprocessAuto" << bCoachReprocessAuto; + qDebug() << "bCoachDecodeIdct" << bCoachDecodeIdct; + +} +// Reset coach messages +void CSnoopConfig::CoachReset() +{ + // Enable all coach messages + bCoachReprocessAuto = true; + bCoachDecodeIdct = true; + + Dirty(); +} + +// Select a suitable working directory, create it if it doesn't already exist +QString CSnoopConfig::GetDefaultDbDir() +{ + +/* TCHAR szUserProfile[MAX_PATH]; + TCHAR szFilePath[MAX_PATH]; + + // Apparently, the SHGetFolderPath is not well supported in earlier + // versions of the OS, so we are only going to try it if we are + // running Win XP or later. + // See: http://support.microsoft.com/kb/310294 + // Older OS versions may require linking to shfolder.dll, which I decided + // not to implement yet. + + // Since I could not get SHGetFolderPath() to compile, even after including + // , I decided to revert to older version of the call: + // https://msdn2.microsoft.com/en-us/library/aa931257.aspx + + if (bIsWindowsNTorLater) { + // Get path for each computer, non-user specific and non-roaming data. + //if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_APPDATA, + // NULL, 0, szFilePath ) ) ) + if ( SHGetSpecialFolderPath( NULL, szFilePath, CSIDL_APPDATA, true )) + { + // Append product-specific path. + PathAppend( szFilePath, "\\JPEGsnoop") ; + + // Since the full path may not already exist, and CreateDirectory() only + // works on one level of hierarchy at a time, use a recursive function + // to do the job. + CreateDir(szFilePath); + } else { + // No error handling + AfxMessageBox("Problem trying to locate suitable directory; please choose manually"); + + // As a default, start with EXE directory + wsprintf(szFilePath,GetExeDir()); + } + } else { + + // Apparently not a recent version of Windows, so we'll revert + // to some older methods at getting the directory + + ExpandEnvironmentStrings("%userprofile%"),szUserProfile,sizeof(szUserProfile)/sizeof(*szUserProfile); + + // NOTE: + // - In Win95/98 it is likely that the above will return the literal "%userprofile%" + // so in that case we don't want to create a directory -- use the exe dir instead + if (!_tcscmp(szUserProfile,"%userprofile%")) { + wsprintf(szFilePath, ""); + // Since we can't locate the user profile directory from environment + // strings, we don't want to create any subdirectory. If we were to + // call CreateDir() with an empty string, we'd end up with a garbled + // folder name created! + + // So, for now, default to executable directory + wsprintf(szFilePath,GetExeDir()); + } else { + // FIXME + // Note that the following is not very good as it doesn't select + // a suitable directory for non-English systems. + wsprintf(szFilePath, "%s%s"), szUserProfile,_T("\\Application Data\\JPEGsnoop"); + + // Since the full path may not already exist, and CreateDirectory() only + // works on one level of hierarchy at a time, use a recursive function + // to do the job. + CreateDir(szFilePath); + } + } + return szFilePath; */ +} + +// Get the directory path of the JPEGsnoop executable +// - This is used as a default location for the user signature database +QString CSnoopConfig::GetExeDir() +{ + +/* TCHAR szPath[1024]; + GetModuleFileName(AfxGetApp()->m_hInstance, szPath, sizeof(szPath)/sizeof(*szPath)); + + TCHAR *ptr = _tcsrchr(szPath, '\\'); + + if (ptr) + { + ptr[1] = '\0'; + } + + ASSERT(_tcslen(szPath) < sizeof(szPath)); + + return szPath; */ +} + +// Recursively create directories as needed to create full path +// TODO: Should replace this by SHCreateDirectoryEx() +void CSnoopConfig::CreateDir(QString Path) +{ + +/* TCHAR DirName[256]; + TCHAR* p = Path; + TCHAR* q = DirName; + DirName[0] = '\0'; // Start as null-terminated + + while(*p) + { + if (('\\' == *p) || ('/' == *p)) + { + if (':' != *(p-1)) + { + CreateDirectory(DirName, NULL); + } + } + *q++ = *p++; + *q = '\0'; + } + CreateDirectory(DirName, NULL); */ +} + +// Create a new debug log if the control key is pressed during startup +// +// Note that we do not keep the log file open to help ensure that +// all debug entries are flushed to the file (in case of an +// an application crash). +// +bool CSnoopConfig::DebugLogCreate() +{ +#ifdef DEBUG_LOG_OUT + + if(strDebugLogFname == "") + { + return false; + } + + // Detect control keys + // - VK_CONTROL = Control key + // - VK_SHIFT = Shift + // - VK_MENU = Alt? + if(GetAsyncKeyState(VK_CONTROL)) + { + AfxMessageBox("Debug Log Enabled"); + bDebugLogEnable = true; + } + else + { + return true; + } + + ASSERT(fpDebugLog == NULL); + + try + { + // Open specified file + fpDebugLog = new CStdioFile(strDebugLogFname, CFile::modeCreate | CFile::modeWrite | CFile::typeText | CFile::shareDenyNone); + } + catch(CFileException * e) + { + TCHAR msg[MAX_BUF_EX_ERR_MSG]; + + QString strError; + + e->GetErrorMessage(msg, MAX_BUF_EX_ERR_MSG); + e->Delete(); + strError.Format("ERROR: Couldn't open debug log file for write [%s]: [%s]", (LPCTSTR) strDebugLogFname, (LPCTSTR) msg); + AfxMessageBox(strError); + fpDebugLog = NULL; + + return false; + } + + QString strLine; + + strLine.Format("JPEGsnoop version [%s]\r\n"), VERSION_STR; + fpDebugLog->WriteString(strLine); + fpDebugLog->WriteString("-----\r\n"); + + // Close the file + if(fpDebugLog) + { + fpDebugLog->Close(); + delete fpDebugLog; + + fpDebugLog = NULL; + } + + // Extra code to record OS version + OSVERSIONINFO osvi; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + strLine.Format("OS: PlatformId = %u"), osvi.dwPlatformId; + if(DEBUG_EN) + DebugLogAdd(strLine); + strLine.Format("OS: MajorVersion = %u"), osvi.dwMajorVersion; + if(DEBUG_EN) + DebugLogAdd(strLine); + strLine.Format("OS: MinorVersion = %u"), osvi.dwMinorVersion; + if(DEBUG_EN) + DebugLogAdd(strLine); + strLine.Format("OS: BuildNumber = %u"), osvi.dwBuildNumber; + if(DEBUG_EN) + DebugLogAdd(strLine); + strLine.Format("OS: OSVersionInfoSize = %u"), osvi.dwOSVersionInfoSize; + if(DEBUG_EN) + DebugLogAdd(strLine); + if(DEBUG_EN) + DebugLogAdd("\n"); + +#endif + return true; +} + +// If the debug log has been enabled, append the string parameter +// to the log file. +// +// Note that we do not keep the log file open to help ensure that +// all debug entries are flushed to the file (in case of an +// an application crash). +// +bool CSnoopConfig::DebugLogAdd(QString strText) +{ + qDebug() << strText; + +#ifdef DEBUG_LOG_OUT + + if(!bDebugLogEnable) + { + return true; + } + + if(strDebugLogFname == "") + { + return false; + } + + ASSERT(fpDebugLog == NULL); + + try + { + // Open specified file but append + fpDebugLog = new CStdioFile(strDebugLogFname, CFile::modeCreate | CFile::modeWrite | CFile::typeText | CFile::shareDenyNone | + CFile::modeNoTruncate); + } + catch(CFileException * e) + { + TCHAR msg[MAX_BUF_EX_ERR_MSG]; + + QString strError; + + e->GetErrorMessage(msg, MAX_BUF_EX_ERR_MSG); + e->Delete(); + strError.Format("ERROR: Couldn't open debug log file for append [%s]: [%s]", (LPCTSTR) strDebugLogFname, (LPCTSTR) msg); + AfxMessageBox(strError); + fpDebugLog = NULL; + + return false; + } + + // Now seek to the end of the file + fpDebugLog->SeekToEnd(); + + QString strLine; + + // Get current time + +/* + time_t sTime; + struct tm sNow; + unsigned nTmYear,nTmMon,nTmDay; + unsigned nTmHour,nTmMin,nTmSec; + localtime_s(&sNow,&sTime); + nTmYear = sNow.tm_year + 1900; + nTmMon = sNow.tm_mon + 1; + nTmDay = sNow.tm_mday; + nTmHour = sNow.tm_hour; + nTmMin = sNow.tm_min; + nTmSec = sNow.tm_sec; + + // Generate log line + //strLine.Format("[%4u/%2u/%2u %2u:%2u:%2u] %s\r\n"),nTmYear,nTmMon,nTmDay,nTmHour,nTmMin,nTmSec,strText; +*/ + strLine.Format("%s\n"), strText; + fpDebugLog->WriteString(strLine); + + // Close the file + if(fpDebugLog) + { + fpDebugLog->Close(); + delete fpDebugLog; + + fpDebugLog = NULL; + } + +#endif + return true; +} + +void CSnoopConfig::docImageDirty() +{ + m_pJfifDec->ImgSrcChanged(); +} + +void CSnoopConfig::onOptionsDhtexpand() +{ + if(bOutputDHTexpand) + { + bOutputDHTexpand = false; + } + else + { + bOutputDHTexpand = true; + } + + Dirty(); +// HandleAutoReprocess(); +} + +void CSnoopConfig::onOptionsMakernotes() +{ + if(bOutputDHTexpand) + { + bDecodeMaker = false; + } + else + { + bDecodeMaker = true; + } + + Dirty(); +// HandleAutoReprocess(); +} + +void CSnoopConfig::onOptionsHideuknownexiftags() +{ + if(bExifHideUnknown) + { + bExifHideUnknown = false; + } + else + { + bExifHideUnknown = true; + } + + Dirty(); + +// HandleAutoReprocess(); +} + +void CSnoopConfig::onOptionsSignaturesearch() +{ + if(bSigSearch) + { + bSigSearch = false; + } + else + { + bSigSearch = true; + } + + Dirty(); +// HandleAutoReprocess(); +} + +void CSnoopConfig::onOptionsRelaxedparsing() +{ + if(bRelaxedParsing) + { + bRelaxedParsing = false; + } + else + { + bRelaxedParsing = true; + } + + Dirty(); +// HandleAutoReprocess(); +} + +void CSnoopConfig::onScansegmentDecodeImage() +{ + if(bDecodeScanImg) + { + bDecodeScanImg = false; + } + else + { + bDecodeScanImg = true; + } + + Dirty(); +// HandleAutoReprocess(); +} + +void CSnoopConfig::onScansegmentNoidct() +{ + if(bDecodeScanImgAc) + { + bDecodeScanImgAc = false; + } + + qDebug() << "CSnoopConfig::onScansegmentNoidct()" << bDecodeScanImgAc; + Dirty(); + + docImageDirty(); +// HandleAutoReprocess(); +} + +void CSnoopConfig::onScansegmentFullidct() +{ + if(!bDecodeScanImgAc) + { + bDecodeScanImgAc = true; + } + + qDebug() << "CSnoopConfig::onScansegmentFullidct()" << bDecodeScanImgAc; + Dirty(); + + docImageDirty(); +// HandleAutoReprocess(); +} + +void CSnoopConfig::onScansegmentHistogram() +{ + if(bHistoEn) + { + bHistoEn = false; + } + else + { + bHistoEn = true; + } + + Dirty(); + + docImageDirty(); +// HandleAutoReprocess(); +} + +void CSnoopConfig::onScansegmentHistogramy() +{ + if(bDumpHistoY) + { + bDumpHistoY = false; + } + else + { + bDumpHistoY = true; + } + + Dirty(); + + docImageDirty(); +// HandleAutoReprocess(); +} + +void CSnoopConfig::onScansegmentDump() +{ + if(bOutputScanDump) + { + bOutputScanDump = false; + } + else + { + bOutputScanDump = true; + } + + Dirty(); + +// HandleAutoReprocess(); +} diff --git a/source/SnoopConfig.h b/source/SnoopConfig.h index 1cc7f3f..ae66580 100644 --- a/source/SnoopConfig.h +++ b/source/SnoopConfig.h @@ -1,144 +1,171 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Application configuration structures -// - Registry management -// - Note that the majority of this class is defined with public members -// -// ========================================================================== - -#include "snoop.h" // For DEBUG_LOG_OUT - -#pragma once - -class CSnoopConfig -{ -public: - CSnoopConfig(void); - ~CSnoopConfig(void); - - void UseDefaults(); - - void RegistryLoadStr(CString strKey,CString strDefault,CString &strSetting); - void RegistryLoadBool(CString strKey,unsigned nDefault,bool &bSetting); - void RegistryLoadUint(CString strKey,unsigned nDefault,unsigned &nSetting); - void RegistryStoreStr(CString strKey,CString strSetting); - void RegistryStoreBool(CString strKey,bool bSetting); - void RegistryStoreUint(CString strKey,unsigned nSetting); - - void RegistryLoad(); - void RegistryStore(); - void Dirty(bool mode=true); - - void CoachReset(); // Reset all coach messages - - CString GetDefaultDbDir(); // Public use by CSettingsDlg - -public: - // Debug Log - // - Used if DEBUG_LOG_OUT - bool DebugLogCreate(); - bool DebugLogAdd(CString strText); - -private: - CString GetExeDir(); - void CreateDir(LPTSTR Path); - - -public: - - // Interactive mode: shows message dialog box alerts - // In non-interactive mode we suppress most alert dialogs but still - // show them in certain circumstances: - // - They involve an interactive user function (eg. another dialog box) - // - They indicate a critical error - bool bInteractive; // Do we want user input (interactive mode)? (ie. show message boxes) - - bool bGuiMode; // Do we want to show the GUI? - bool bCmdLineOpenEn; // input file specified - CString strCmdLineOpenFname; // input filename - bool bCmdLineOutputEn; // output file specified? - CString strCmdLineOutputFname; // output filename - - bool bCmdLineBatchEn; // Do we run a batch job on a directory? - CString strCmdLineBatchDirName; // directory path for batch job - bool bCmdLineBatchRec; // recursive subdir batch operation? - - bool bCmdLineBatchSrch; // In batch process, perform search forward first? - - bool bCmdLineExtractEn; // Do we extract all JPEGs from file? - bool bCmdLineExtractDhtAvi; // Do we force MotionJPEG DHT? - - bool bCmdLineDoneMsg; // Indicate to user when command-line operations complete? - - teOffsetMode eCmdLineOffset; // Offset operating mode - unsigned long nCmdLineOffsetPos; // File offset for DEC_OFFSET_POS mode - - bool bCmdLineHelp; // Show command list - - unsigned nPosStart; // Starting decode file offset - - // Operating system - bool bIsWindowsNTorLater; - bool bIsWindowsXPorLater; - - // Registry Configuration options - bool bDirty; // Registry entry options dirtied? - bool bEulaAccepted; // Accepted the EULA? - bool bUpdateAuto; // Automatically check for updates - unsigned nUpdateAutoDays; // How many days between checks - CString strDbDir; // Directory for User DB - CString strUpdateLastChk; // When last checked for updates - bool bReprocessAuto; // Auto reprocess file when option change - bool bSigSearch; // Automatically search for comp signatures - bool bDecodeScanImg; // Scan image decode enabled - bool bDecodeScanImgAc; // When scan image decode, do full AC - bool bOutputScanDump; // Do we dump a portion of scan data? - bool bOutputDHTexpand; - bool bDecodeMaker; - bool bHistoEn; // Histogram calcs enabled? - bool bStatClipEn; // Enable scan decode clip stats? - bool bDumpHistoY; // Dump full Y DC Histogram - bool bDbSubmitNet; // Submit new entries to net? - bool bExifHideUnknown; // Hide unknown exif tags? - bool bRelaxedParsing; // Proceed despite bad marker / format? - - unsigned nErrMaxDecodeScan; // Max # errs to show in scan decode - - CString strBatchLastInput; // Last batch process input directory - CString strBatchLastOutput; // Last batch process output directory - CString strBatchExtensions; // Extension list for batch processing (eg. ".jpg,.jpeg") - - bool bCoachReprocessAuto; // Coach msg: Need to reprocess or change to auto - bool bCoachDecodeIdct; // Coach msg: Warn about slow AC decode / lowres DC - - // Extra config (not in registry) - bool bDecodeColorConvert; // Do we do color convert after scan decode? - - // Temporary status (not saved) - CString strCurFname; // Current filename (Debug use only) - - // Debug log - // - Used if DEBUG_LOG_OUT - bool bDebugLogEnable; - CString strDebugLogFname; - CStdioFile* fpDebugLog; - -}; +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - Application configuration structures +// - Registry management +// - Note that the majority of this class is defined with public members +// +// ========================================================================== + +#ifndef SNOOPCONFIG_H +#define SNOOPCONFIG_H + +#include "snoop.h" // For DEBUG_LOG_OUT + +#include +#include + +class CjfifDecode; + +class CSnoopConfig : public QObject +{ + Q_OBJECT + +public: + CSnoopConfig(CjfifDecode *pJfifDec); + ~CSnoopConfig(void); + + void UseDefaults(); + void printSettings(); + + void RegistryLoad(); + void RegistryStore(); + void Dirty(bool mode = true); + + void CoachReset(); // Reset all coach messages + + QString GetDefaultDbDir(); // Public use by CSettingsDlg + + QString dbPath() { return strDbDir; } + int32_t autoUpdateDays() { return nUpdateAutoDays; } + int32_t maxDecodeError() { return nErrMaxDecodeScan; } + bool swUpdateEnabled() { return bUpdateAuto; } + bool autoReprocess() { return bReprocessAuto; } + bool dbSubmitNet() { return bDbSubmitNet; } + + // Debug Log + // - Used if DEBUG_LOG_OUT + bool DebugLogCreate(); + bool DebugLogAdd(QString strText); + + // Interactive mode: shows message dialog box alerts + // In non-interactive mode we suppress most alert dialogs but still + // show them in certain circumstances: + // - They involve an interactive user function (eg. another dialog box) + // - They indicate a critical error + bool bInteractive; // Do we want user input (interactive mode)? (ie. show message boxes) + + bool bGuiMode; // Do we want to show the GUI? + bool bCmdLineOpenEn; // input file specified + QString strCmdLineOpenFname; // input filename + bool bCmdLineOutputEn; // output file specified? + QString strCmdLineOutputFname; // output filename + + bool bCmdLineBatchEn; // Do we run a batch job on a directory? + QString strCmdLineBatchDirName; // directory path for batch job + bool bCmdLineBatchRec; // recursive subdir batch operation? + + bool bCmdLineBatchSrch; // In batch process, perform search forward first? + + bool bCmdLineExtractEn; // Do we extract all JPEGs from file? + bool bCmdLineExtractDhtAvi; // Do we force MotionJPEG DHT? + + bool bCmdLineDoneMsg; // Indicate to user when command-line operations complete? + + teOffsetMode eCmdLineOffset; // Offset operating mode + unsigned long nCmdLineOffsetPos; // File offset for DEC_OFFSET_POS mode + + bool bCmdLineHelp; // Show command list + + unsigned nPosStart; // Starting decode file offset + + // Operating system + bool bIsWindowsNTorLater; + bool bIsWindowsXPorLater; + + // Registry Configuration options + QString strDbDir; // Directory for User DB + QString strUpdateLastChk; // When last checked for updates + QString strBatchLastInput; // Last batch process input directory + QString strBatchLastOutput; // Last batch process output directory + QString strBatchExtensions; // Extension list for batch processing (eg. ".jpg,.jpeg") + + + int nUpdateAutoDays; // How many days between checks + int nErrMaxDecodeScan; // Max # errs to show in scan decode + + bool bDirty; // Registry entry options dirtied? + bool bEulaAccepted; // Accepted the EULA? + bool bUpdateAuto; // Automatically check for updates + bool bReprocessAuto; // Auto reprocess file when option change + bool bSigSearch; // Automatically search for comp signatures + bool bDecodeScanImg; // Scan image decode enabled + bool bDecodeScanImgAc; // When scan image decode, do full AC + bool bOutputScanDump; // Do we dump a portion of scan data? + bool bOutputDHTexpand; + bool bDecodeMaker; + bool bHistoEn; // Histogram calcs enabled? + bool bStatClipEn; // Enable scan decode clip stats? + bool bDumpHistoY; // Dump full Y DC Histogram + bool bDbSubmitNet; // Submit new entries to net? + bool bExifHideUnknown; // Hide unknown exif tags? + bool bRelaxedParsing; // Proceed despite bad marker / format? + bool bCoachReprocessAuto; // Coach msg: Need to reprocess or change to auto + bool bCoachDecodeIdct; // Coach msg: Warn about slow AC decode / lowres DC + + // Extra config (not in registry) + bool bDecodeColorConvert; // Do we do color convert after scan decode? + + // Temporary status (not saved) + QString strCurFname; // Current filename (Debug use only) + + // Debug log + // - Used if DEBUG_LOG_OUT + bool bDebugLogEnable; + QString strDebugLogFname; + QTextStream *fpDebugLog; + +public slots: + void onOptionsDhtexpand(); + void onOptionsMakernotes(); + void onScansegmentDecodeImage(); + void onOptionsHideuknownexiftags(); + void onOptionsRelaxedparsing(); + void onOptionsSignaturesearch(); + void onScansegmentNoidct(); + void onScansegmentFullidct(); + void onScansegmentHistogram(); + void onScansegmentHistogramy(); + void onScansegmentDump(); + +private: + CSnoopConfig &operator = (const CSnoopConfig&); + CSnoopConfig(CSnoopConfig&); + + QString GetExeDir(); + void CreateDir(QString Path); + void docImageDirty(); + +// QSettings settings; + + CjfifDecode *m_pJfifDec; +}; + +#endif diff --git a/source/UrlString.h b/source/UrlString.h index ded8d89..57daef3 100644 --- a/source/UrlString.h +++ b/source/UrlString.h @@ -39,13 +39,13 @@ Description: H URL Encoder/Decoder class CUrlString { private: - CString m_csUnsafe; + QString m_csUnsafe; public: CUrlString(); virtual ~CUrlString() { }; - CString Encode(CString csDecoded); - CString Decode(CString csEncoded); + QString Encode(QString csDecoded); + QString Decode(QString csEncoded); }; #endif //__CURLSTRING_H_ diff --git a/source/WindowBuf.cpp b/source/WindowBuf.cpp index 1a01efc..b8d07b7 100644 --- a/source/WindowBuf.cpp +++ b/source/WindowBuf.cpp @@ -1,1007 +1,1214 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "stdafx.h" - -#include "WindowBuf.h" - -// Reset the main state -// -void CwindowBuf::Reset() -{ - // File handling - m_bBufOK = false; // Initialize the buffer to not loaded yet - m_pBufFile = NULL; // No file open yet - -} - -// Constructor for WindowBuf class -// - Allocates storage for the buffer -// - Resets state -// - Clears all buffer overlay bytes -// -CwindowBuf::CwindowBuf() -{ - m_pBuffer = new BYTE[MAX_BUF]; - if (!m_pBuffer) { - AfxMessageBox(_T("ERROR: Not enough memory for File Buffer")); - exit(1); - } - - m_pStatBar = NULL; - - Reset(); - - // Initialize all overlays as not defined. - // Only create space for them as required - m_nOverlayNum = 0; - m_nOverlayMax = 0; - for (unsigned nInd=0;nIndGetLength(); - if (m_nPosEof == 0) { - m_pBufFile = NULL; - AfxMessageBox(_T("ERROR: BufFileSet() File length zero")); - } -} - -// Called to mark the buffer as closed -// - Typically done when we've finished processing a file -// This avoids problems where we try to read a buffer -// that has already been terminated. -// -// POST: -// - m_pBufFile -// -void CwindowBuf::BufFileUnset() -{ - if (m_pBufFile) { - m_pBufFile = NULL; - } -} - - -// Search for a value in the buffer from a given starting position -// and direction, limited to a maximum search depth -// - Search value can be 8-bit, 16-bit or 32-bit -// - Update progress in lengthy searches -// -// INPUT: -// - nStartPos Starting byte offset for search -// - nSearchVal Value to search for (up to 32-bit unsigned) -// - nSearchLen Maximum number of bytes to search -// - bDirFwd TRUE for forward, FALSE for backwards -// -// PRE: -// - m_nPosEof -// -// OUTPUT: -// - nFoundPos Byte offset in buffer for start of search match -// -// RETURN: -// - Success in finding the value -// -bool CwindowBuf::BufSearch(unsigned long nStartPos, unsigned nSearchVal, unsigned nSearchLen, - bool bDirFwd, unsigned long &nFoundPos) -{ - // Save the current position - unsigned long nCurPos; - unsigned nCurVal; - CString strStatus; - time_t tmLast = clock(); - - nCurPos = nStartPos; - bool bDone = false; - bool bFound = false; - while (!bDone) { - - // Update progress in status bar - // - Note that we only check timer when step counter has - // reached a certain threshold. This limits the overhead - // associated with the timer comparison - if ( ((nCurPos%(16*1024))==0) && (m_pStatBar)) { - time_t tmNow = clock(); - if ((tmNow-tmLast) > (CLOCKS_PER_SEC / 8) ) { - tmLast = tmNow; - float fProgress = (nCurPos*100.0f)/m_nPosEof; - strStatus.Format(_T("Searching %3.f%% (%lu of %lu)..."),fProgress,nCurPos,m_nPosEof); - m_pStatBar->SetPaneText(0,strStatus); - } - } - - if (bDirFwd) { - nCurPos++; - if (nCurPos+(nSearchLen-1) >= m_nPosEof) { - bDone = true; - } - } else { - if (nCurPos > 0) { - nCurPos--; - } else { - bDone = true; - } - } - - if (nSearchLen == 4) { - nCurVal = (Buf(nCurPos+0)<<24) + (Buf(nCurPos+1)<<16) + (Buf(nCurPos+2)<<8) + Buf(nCurPos+3); - } else if (nSearchLen == 3) { - nCurVal = (Buf(nCurPos+0)<<16) + (Buf(nCurPos+1)<<8) + Buf(nCurPos+2); - } else if (nSearchLen == 2) { - nCurVal = (Buf(nCurPos+0)<<8) + Buf(nCurPos+1); - } else if (nSearchLen == 1) { - nCurVal = Buf(nCurPos+0); - } else { - AfxMessageBox(_T("ERROR: Unexpected nSearchLen")); - nCurVal = 0x0000; - } - if (nCurVal == nSearchVal) { - bFound = true; - bDone = true; - } - - } - - - nFoundPos = nCurPos; - return bFound; -} - -//SetStatusText - -// Establish local copy of status bar pointer -void CwindowBuf::SetStatusBar(CStatusBar* pStatBar) -{ - m_pStatBar = pStatBar; -} - -// Search for a variable-length byte string in the buffer from a given starting position -// and direction, limited to a maximum search depth -// - Search string is array of unsigned bytes -// - Update progress in lengthy searches -// -// INPUT: -// - nStartPos Starting byte offset for search -// - anSearchVal Byte array to search for -// - nSearchLen Maximum number of bytes to search -// - bDirFwd TRUE for forward, FALSE for backwards -// -// PRE: -// - m_nPosEof -// - m_pStatBar -// -// OUTPUT: -// - nFoundPos Byte offset in buffer for start of search match -// -// RETURN: -// - Success in finding the value -// -bool CwindowBuf::BufSearchX(unsigned long nStartPos, BYTE* anSearchVal, unsigned nSearchLen, - bool bDirFwd, unsigned long &nFoundPos) -{ - // Save the current position - unsigned long nCurPos; - unsigned nByteCur; - unsigned nByteSearch; - - unsigned long nCurPosOffset; - - unsigned long nMatchStartPos = 0; - //bool bMatchStart = false; - bool bMatchOn = false; - CString strStatus; - time_t tmLast = clock(); - - nCurPosOffset = 0; - nCurPos = nStartPos; - bool bDone = false; - bool bFound = false; // Matched entire search string - while (!bDone) { - - if (bDirFwd) { - nCurPos++; - if (nCurPos+(nSearchLen-1) >= m_nPosEof) { - bDone = true; - } - } else { - if (nCurPos > 0) { - nCurPos--; - } else { - bDone = true; - } - } - - // Update progress in status bar - // - Note that we only check timer when step counter has - // reached a certain threshold. This limits the overhead - // associated with the timer comparison - if ( ((nCurPos%(16*1024))==0) && (m_pStatBar)) { - time_t tmNow = clock(); - if ((tmNow-tmLast) > (CLOCKS_PER_SEC / 8) ) { - tmLast = tmNow; - float fProgress = (nCurPos*100.0f)/m_nPosEof; - strStatus.Format(_T("Searching %3.f%% (%lu of %lu)..."),fProgress,nCurPos,m_nPosEof); - m_pStatBar->SetPaneText(0,strStatus); - } - } - - nByteSearch = anSearchVal[nCurPosOffset]; - nByteCur = Buf(nCurPos); - if (nByteSearch == nByteCur) { - if (!bMatchOn) { - // Since we aren't in match mode, we are beginning a new - // sequence, so save the starting position in case we - // have to rewind - nMatchStartPos = nCurPos; - bMatchOn = true; - } - nCurPosOffset++; - } else { - if (bMatchOn) { - // Since we were in a sequence of matches, but ended early, - // we now need to reset our position to just after the start - // of the previous 1st match. - nCurPos = nMatchStartPos; - bMatchOn = false; - } - nCurPosOffset = 0; - } - if (nCurPosOffset >= nSearchLen) { - // We matched the entire length of our search string! - bFound = true; - bDone = true; - } - - } - - if (m_pStatBar) { - m_pStatBar->SetPaneText(0,_T("Done")); - } - - - if (bFound) { - nFoundPos = nMatchStartPos; - } - return bFound; - -} - - -// Ensure that the file offset parameter is captured in the current -// buffer cache. If not, reload a new cache around this offset. -// - Provide some limited cache prior to the desired address -// - Provide majority of cache after the desired address -// - The cache prior to the address facilitates reverse search performance -// -// INPUT: -// - nPosition File offset to ensure is available in new window -// PRE: -// - m_pBufFile -// - m_nPosEof -// -// POST: -// - m_bBufOK -// - m_nBufWinSize -// - m_nBufWinStart -// -void CwindowBuf::BufLoadWindow(unsigned long nPosition) -{ - - // We must not try to perform a seek command on a CFile that - // has already been closed, so we must check first. - - if (m_pBufFile) { - /* - CString strTmp; - strTmp.Format(_T("** BufLoadWindow @ 0x%08X"),nPosition); - log->AddLine(strTmp); - */ - - // Initialize to bad values - m_bBufOK = false; - m_nBufWinSize = 0; - m_nBufWinStart = 0; - - // For now, just read 128KB starting at current position - // Later on, we will need to do range checking and even start - // at a nPosition some distance before the "nPosition" to allow - // for some reverse seeking without refetching data. - - unsigned long nPositionAdj; - if (nPosition >= MAX_BUF_WINDOW_REV) { - nPositionAdj = nPosition - MAX_BUF_WINDOW_REV; - } else { - nPositionAdj = 0; - } - - // NOTE: - // Need to ensure that we don't try to read past the end of file. - // I have encountered some JPEGs that have Canon makernote - // fields with OffsetValue > 0xFFFF0000! Interpreting this as-is - // would cuase BufLoadWindow() to read past the end of file. - if (nPositionAdj >= m_nPosEof) { - - // ERROR! For now, just do this silently - // We're not going to throw up any errors unless we can - // limit the number that we'll display to the user! - // The current code will not reset the nPosition of the - // buffer, so every byte will try to reset it. - // FIXME - return; - } - - - unsigned long nVal; - nVal = (unsigned long)m_pBufFile->Seek(nPositionAdj,CFile::begin); - nVal = (unsigned long)m_pBufFile->Read(m_pBuffer,MAX_BUF_WINDOW); - if (nVal <= 0) { - // Failed to read anything! - // ERROR! - return; - } else { - // Read OK - // Recalculate bounds - m_bBufOK = true; - m_nBufWinStart = nPositionAdj; - m_nBufWinSize = nVal; - } - - } else { - AfxMessageBox(_T("ERROR: BufLoadWindow() and no file open")); - } -} - - -// Allocate a new buffer overlay into the array -// over overlays. Limits the number of overlays -// to NUM_OVERLAYS. -// - If the indexed overlay already exists, no changes are made -// - TODO: Replace with vector -// -// INPUT: -// - nInd Overlay index to allocate -// -// POST: -// - m_psOverlay[] -// -bool CwindowBuf::OverlayAlloc(unsigned nInd) -{ - if (nInd >= NUM_OVERLAYS) { - AfxMessageBox(_T("ERROR: Maximum number of overlays reached")); - return false; - - } else if (m_psOverlay[nInd]) { - // Already allocated, move on - return true; - - } else { - m_psOverlay[nInd] = new sOverlay(); - if (!m_psOverlay[nInd]) { - AfxMessageBox(_T("NOTE: Out of memory for extra file overlays")); - return false; - } else { - memset(m_psOverlay[nInd],0,sizeof(sOverlay)); - // FIXME: may not be necessary - m_psOverlay[nInd]->bEn = false; - m_psOverlay[nInd]->nStart = 0; - m_psOverlay[nInd]->nLen = 0; - - m_psOverlay[nInd]->nMcuX = 0; - m_psOverlay[nInd]->nMcuY = 0; - m_psOverlay[nInd]->nMcuLen = 0; - m_psOverlay[nInd]->nMcuLenIns = 0; - m_psOverlay[nInd]->nDcAdjustY = 0; - m_psOverlay[nInd]->nDcAdjustCb = 0; - m_psOverlay[nInd]->nDcAdjustCr = 0; - - // FIXME: Need to ensure that this is right - if (nInd+1 >= m_nOverlayMax) { - m_nOverlayMax = nInd+1; - } - //m_nOverlayMax++; - - return true; - } - } -} - - - -// Report out the list of overlays thave have been allocated -// -// PRE: -// - m_nOverlayNum -// - m_psOverlay[] -// -void CwindowBuf::ReportOverlays(CDocLog* pLog) -{ - CString strTmp; - - if (m_nOverlayNum>0) { - strTmp.Format(_T(" Buffer Overlays active: %u"),m_nOverlayNum); - pLog->AddLine(strTmp); - for (unsigned ind=0;indnMcuX,m_psOverlay[ind]->nMcuY,m_psOverlay[ind]->nMcuLen,m_psOverlay[ind]->nMcuLenIns, - m_psOverlay[ind]->nDcAdjustY,m_psOverlay[ind]->nDcAdjustCb,m_psOverlay[ind]->nDcAdjustCr, - m_psOverlay[ind]->nLen); - pLog->AddLine(strTmp); - } - } - pLog->AddLine(_T("")); - } -} - - -// Define the content of an overlay -// -// INPUT: -// - nOvrInd The overlay index to update/replace -// - pOverlay The byte array that defines the overlay content -// - nLen Byte length of the overlay -// - nBegin Starting byte offset for the overlay -// - nMcuX Additional info for this overlay -// - nMcuY Additional info for this overlay -// - nMcuLen Additional info for this overlay -// - nMcuLenIns Additional info for this overlay -// - nAdjY Additional info for this overlay -// - nAdjCb Additional info for this overlay -// - nAdjCr Additional info for this overlay -// -bool CwindowBuf::OverlayInstall(unsigned nOvrInd, BYTE* pOverlay,unsigned nLen,unsigned nBegin, - unsigned nMcuX,unsigned nMcuY,unsigned nMcuLen,unsigned nMcuLenIns, - int nAdjY,int nAdjCb,int nAdjCr) -{ - nOvrInd; // Unreferenced param - - // Ensure that the overlay is allocated, and allocate it - // if required. Fail out if we can't add (or run out of space) - if (!OverlayAlloc(m_nOverlayNum)) { - return false; - } - - if (nLen < MAX_OVERLAY) { - m_psOverlay[m_nOverlayNum]->bEn = true; - m_psOverlay[m_nOverlayNum]->nLen = nLen; - // Copy the overlay content, but clip to maximum size - // and pad if shorter - for (unsigned i=0;ianData[i] = (inStart = nBegin; - - // For reporting, save the extra data - m_psOverlay[m_nOverlayNum]->nMcuX = nMcuX; - m_psOverlay[m_nOverlayNum]->nMcuY = nMcuY; - m_psOverlay[m_nOverlayNum]->nMcuLen = nMcuLen; - m_psOverlay[m_nOverlayNum]->nMcuLenIns = nMcuLenIns; - m_psOverlay[m_nOverlayNum]->nDcAdjustY = nAdjY; - m_psOverlay[m_nOverlayNum]->nDcAdjustCb = nAdjCb; - m_psOverlay[m_nOverlayNum]->nDcAdjustCr = nAdjCr; - - m_nOverlayNum++; - } else { - AfxMessageBox(_T("ERROR: CwindowBuf:OverlayInstall() overlay too large")); - return false; - } - - return true; -} - -// Remove latest overlay entry -// -// POST: -// - m_nOverlayNum -// - m_psOverlay[] -// -void CwindowBuf::OverlayRemove() -{ - if (m_nOverlayNum<=0) { - return; - } - m_nOverlayNum--; - - // Note that we've already decremented the m_nOverlayNum - if (m_psOverlay[m_nOverlayNum]) { - // Don't need to delete the overlay struct as we might as well reuse it - m_psOverlay[m_nOverlayNum]->bEn = false; - //delete m_psOverlay[m_nOverlayNum]; - //m_psOverlay[m_nOverlayNum] = NULL; - } -} - -// Disable all buffer overlays -// -// POST: -// - m_nOverlayNum -// - m_psOverlay[] -// -void CwindowBuf::OverlayRemoveAll() -{ - m_nOverlayNum = 0; - for (unsigned nInd=0;nIndbEn = false; - } - } -} - -// Fetch the indexed buffer overlay -// -// INPUT: -// - nOvrInd The overlay index -// -// OUTPUT: -// - pOverlay A pointer to the indexed buffer -// - nLen Length of the overlay string -// - nBegin Starting file offset for the overlay -// -// RETURN: -// - Success if overlay index was allocated and enabled -// -bool CwindowBuf::OverlayGet(unsigned nOvrInd, BYTE* &pOverlay,unsigned &nLen,unsigned &nBegin) -{ - if ( (m_psOverlay[nOvrInd]) && (m_psOverlay[nOvrInd]->bEn) ) { - pOverlay = m_psOverlay[nOvrInd]->anData; - nLen = m_psOverlay[nOvrInd]->nLen; - nBegin = m_psOverlay[nOvrInd]->nStart; - return m_psOverlay[nOvrInd]->bEn; - } else { - return false; - } -} - -// Get the number of buffer overlays allocated -// -unsigned CwindowBuf::OverlayGetNum() -{ - return m_nOverlayNum; -} - -// Replaces the direct buffer access with a managed refillable window/cache. -// - Support for 1-byte access only -// - Support for overlays (optional) -// -// INPUT: -// - nOffset File offset to fetch from (via cache) -// - bClean Flag that indicates if overlays can be used -// If set to FALSE, then content from overlays that span -// the offset address will be returned instead of the file content -// -// RETURN: -// - Byte from the desired address -// -inline BYTE CwindowBuf::Buf(unsigned long nOffset,bool bClean) -{ - - // We are requesting address "nOffset" - // Our current window runs from "m_nBufWinStart...buf_win_end" (m_nBufWinSize) - // Therefore, our relative addr is nOffset-m_nBufWinStart - - long nWinRel; - - BYTE nCurVal = 0; - unsigned bInOvrWindow = false; - - if (!m_pBufFile) { - // FIXME: Open file or provide error - } - ASSERT(m_pBufFile); - - // Allow for overlay buffer capability (if not in "clean" mode) - if (!bClean) { - // Now handle any overlays - for (unsigned nInd=0;nIndbEn) { - if ((nOffset >= m_psOverlay[nInd]->nStart) && - (nOffset < m_psOverlay[nInd]->nStart + m_psOverlay[nInd]->nLen)) - { - nCurVal = m_psOverlay[nInd]->anData[nOffset-m_psOverlay[nInd]->nStart]; - bInOvrWindow = true; - } - } - } - } - if (bInOvrWindow) { - - // Before we return, make sure that the real buffer handles this region! - nWinRel = nOffset-m_nBufWinStart; - if ((nWinRel >= 0) && (nWinRel < (long)m_nBufWinSize)) { - } else { - // Address is outside of current window - BufLoadWindow(nOffset); - } - - return nCurVal; - } - } - - // Now that we've finished any overlays, proceed to actual cache content - - // Determine if the offset is within the current cache - // If not, reload a new cache around the desired address - nWinRel = nOffset-m_nBufWinStart; - if ((nWinRel >= 0) && (nWinRel < (long)m_nBufWinSize)) { - // Address is within current window - return m_pBuffer[nWinRel]; - } else { - // Address is outside of current window - BufLoadWindow(nOffset); - - // Now we assume that the address is in range - // m_nBufWinStart has now been updated - // TODO: check this - nWinRel = nOffset-m_nBufWinStart; - - // Now recheck the window - // TODO: Rewrite the following in a cleaner manner - if ((nWinRel >= 0) && (nWinRel < (long)m_nBufWinSize)) { - return m_pBuffer[nWinRel]; - } else { - // Still bad after refreshing window, so it must be bad addr - m_bBufOK = false; - // FIXME: Need to report error somehow - //log->AddLine(_T("ERROR: Overread buffer - file may be truncated"),9); - return 0; - } - } -} - -// Replaces the direct buffer access with a managed refillable window/cache. -// - Supports 1/2/4 byte fetch -// - No support for overlays -// -// INPUT: -// - nOffset File offset to fetch from (via cache) -// - nSz Size of word to fetch (1,2,4) -// - nByteSwap Flag to indicate if UINT16 or UINT32 should be byte-swapped -// -// RETURN: -// - 1/2/4 unsigned bytes from the desired address -// -unsigned CwindowBuf::BufX(unsigned long nOffset,unsigned nSz,bool nByteSwap) -{ - long nWinRel; - - ASSERT(m_pBufFile); - - nWinRel = nOffset-m_nBufWinStart; - if ((nWinRel >= 0) && (nWinRel+nSz < m_nBufWinSize)) { - // Address is within current window - if (!nByteSwap) { - if (nSz==4) { - return ( (m_pBuffer[nWinRel+0]<<24) + (m_pBuffer[nWinRel+1]<<16) + (m_pBuffer[nWinRel+2]<<8) + (m_pBuffer[nWinRel+3]) ); - } else if (nSz==2) { - return ( (m_pBuffer[nWinRel+0]<<8) + (m_pBuffer[nWinRel+1]) ); - } else if (nSz==1) { - return (m_pBuffer[nWinRel+0]); - } else { - AfxMessageBox(_T("ERROR: BufX() with bad size")); - return 0; - } - } else { - if (nSz==4) { - return ( (m_pBuffer[nWinRel+3]<<24) + (m_pBuffer[nWinRel+2]<<16) + (m_pBuffer[nWinRel+1]<<8) + (m_pBuffer[nWinRel+0]) ); - } else if (nSz==2) { - return ( (m_pBuffer[nWinRel+1]<<8) + (m_pBuffer[nWinRel+0]) ); - } else if (nSz==1) { - return (m_pBuffer[nWinRel+0]); - } else { - AfxMessageBox(_T("ERROR: BufX() with bad size")); - return 0; - } - } - - } else { - // Address is outside of current window - BufLoadWindow(nOffset); - - // Now we assume that the address is in range - // m_nBufWinStart has now been updated - // TODO: Check this - nWinRel = nOffset-m_nBufWinStart; - - // Now recheck the window - // TODO: Rewrite the following in a cleaner manner - if ((nWinRel >= 0) && (nWinRel+nSz < m_nBufWinSize)) { - if (!nByteSwap) { - if (nSz==4) { - return ( (m_pBuffer[nWinRel+0]<<24) + (m_pBuffer[nWinRel+1]<<16) + (m_pBuffer[nWinRel+2]<<8) + (m_pBuffer[nWinRel+3]) ); - } else if (nSz==2) { - return ( (m_pBuffer[nWinRel+0]<<8) + (m_pBuffer[nWinRel+1]) ); - } else if (nSz==1) { - return (m_pBuffer[nWinRel+0]); - } else { - AfxMessageBox(_T("ERROR: BufX() with bad size")); - return 0; - } - } else { - if (nSz==4) { - return ( (m_pBuffer[nWinRel+3]<<24) + (m_pBuffer[nWinRel+2]<<16) + (m_pBuffer[nWinRel+1]<<8) + (m_pBuffer[nWinRel+0]) ); - } else if (nSz==2) { - return ( (m_pBuffer[nWinRel+1]<<8) + (m_pBuffer[nWinRel+0]) ); - } else if (nSz==1) { - return (m_pBuffer[nWinRel+0]); - } else { - AfxMessageBox(_T("ERROR: BufX() with bad size")); - return 0; - } - } - } else { - // Still bad after refreshing window, so it must be bad addr - m_bBufOK = false; - // FIXME: Need to report error somehow - //log->AddLine(_T("ERROR: Overread buffer - file may be truncated"),9); - return 0; - } - } -} - -unsigned char CwindowBuf::BufRdAdv1(unsigned long &nOffset,bool bByteSwap) -{ - unsigned char nRet; - nRet = static_cast(BufX(nOffset,1,bByteSwap)); - nOffset += 1; - return nRet; -} - -unsigned short CwindowBuf::BufRdAdv2(unsigned long &nOffset,bool bByteSwap) -{ - unsigned short nRet; - nRet = static_cast(BufX(nOffset,2,bByteSwap)); - nOffset += 2; - return nRet; -} - -unsigned CwindowBuf::BufRdAdv4(unsigned long &nOffset,bool bByteSwap) -{ - unsigned nRet; - nRet = BufX(nOffset,4,bByteSwap); - nOffset += 4; - return nRet; -} - - - - -// Read a null-terminated string from the buffer/cache at the -// indicated file offset. -// - Does not affect the current file pointer nPosition -// - String length is limited by encountering either the NULL character -// of exceeding the maximum length of MAX_BUF_READ_STR -// -// INPUT: -// - nPosition File offset to start string fetch -// -// RETURN: -// - String fetched from file -// -CString CwindowBuf::BufReadStr(unsigned long nPosition) -{ - // Try to read a NULL-terminated string from file offset "nPosition" - // up to a maximum of MAX_BUF_READ_STR bytes. Result is max length MAX_BUF_READ_STR - CString strRd = _T(""); - unsigned char cRd; - bool bDone = false; - unsigned nIndex = 0; - - while (!bDone) - { - cRd = Buf(nPosition+nIndex); - // Only add if printable - if (isprint(cRd)) { - strRd += cRd; - } - nIndex++; - if (cRd == 0) { - bDone = true; - } else if (nIndex >= MAX_BUF_READ_STR) { - bDone = true; - // No need to null-terminate the string since we are using CString - } - } - return strRd; -} - -// Read a null-terminated 16-bit unicode string from the buffer/cache at the -// indicated file offset. -// - FIXME: Replace faked out unicode-to-ASCII conversion with real implementation -// - Does not affect the current file pointer nPosition -// - String length is limited by encountering either the NULL character -// of exceeding the maximum length of MAX_BUF_READ_STR -// - Reference: BUG: #1112 -// -// INPUT: -// - nPosition File offset to start string fetch -// -// RETURN: -// - String fetched from file -// -CString CwindowBuf::BufReadUniStr(unsigned long nPosition) -{ - // Try to read a NULL-terminated string from file offset "nPosition" - // up to a maximum of MAX_BUF_READ_STR bytes. Result is max length MAX_BUF_READ_STR - CString strRd; - unsigned char cRd; - bool bDone = false; - unsigned nIndex = 0; - - while (!bDone) - { - cRd = Buf(nPosition+nIndex); - - // Make sure it is a printable char! - // FIXME: No, we can't check for this as it will cause - // _tcslen() call in the calling function to get the wrong - // length as it isn't null-terminated. Skip for now. -// if (isprint(cRd)) { -// strRd += cRd; -// } else { -// strRd += _T("."); -// } - strRd += cRd; - - nIndex+=2; - if (cRd == 0) { - bDone = true; - } else if (nIndex >= (MAX_BUF_READ_STR*2)) { - bDone = true; - } - } - return strRd; -} - - -// Wrapper for ByteStr2Unicode that uses local Window Buffer -#define MAX_UNICODE_STRLEN 255 -CString CwindowBuf::BufReadUniStr2(unsigned long nPos, unsigned nBufLen) -{ - // Convert byte array into unicode string - // TODO: Replace with call to ByteStr2Unicode() - - bool bByteSwap = false; - CString strVal; - unsigned nStrLenTrunc; - BYTE nChVal; - BYTE anStrBuf[(MAX_UNICODE_STRLEN+1)*2]; - wchar_t acStrBuf[(MAX_UNICODE_STRLEN+1)]; - - // Start with length before any truncation - nStrLenTrunc = nBufLen; - - // Read unicode bytes into byte array - // Truncate the string, leaving room for terminator - if (nStrLenTrunc>MAX_UNICODE_STRLEN) { - nStrLenTrunc = MAX_UNICODE_STRLEN; - } - for (unsigned nInd=0;nInd 0) { - for (unsigned nInd=0;((!bDone)&&(nInd. +// + +#include +#include + +#include "WindowBuf.h" + +// Reset the main state +// +void CwindowBuf::Reset() +{ + // File handling + m_bBufOK = false; // Initialize the buffer to not loaded yet + m_pBufFile = NULL; // No file open yet +} + +// Constructor for WindowBuf class +// - Allocates storage for the buffer +// - Resets state +// - Clears all buffer overlay bytes +// +CwindowBuf::CwindowBuf() +{ + m_pBuffer = new unsigned char[MAX_BUF]; + + if(!m_pBuffer) + { + msgBox.setText("ERROR: Not enough memory for File Buffer"); + msgBox.exec(); + exit(1); + } + + m_pStatBar = NULL; + + Reset(); + + // Initialize all overlays as not defined. + // Only create space for them as required + m_nOverlayNum = 0; + m_nOverlayMax = 0; + + for(uint32_t nInd = 0; nInd < NUM_OVERLAYS; nInd++) + { + m_psOverlay[nInd] = NULL; + } +} + +// Destructor deallocates buffers and overlays +CwindowBuf::~CwindowBuf() +{ + if(m_pBuffer != NULL) + { + delete m_pBuffer; + + m_pBuffer = NULL; + m_bBufOK = false; + } + + // Clear up overlays + for(uint32_t nInd = 0; nInd < NUM_OVERLAYS; nInd++) + { + if(m_psOverlay[nInd]) + { + delete m_psOverlay[nInd]; + + m_psOverlay[nInd] = NULL; + } + } +} + +// Accessor for m_bBufOk +bool CwindowBuf::GetBufOk() +{ + return m_bBufOK; +} + +// Accessor for m_nPosEof +uint32_t CwindowBuf::GetPosEof() +{ + return m_nPosEof; +} + +// Retain a copy of the file pointer and fetch the file size +// +// POST: +// - m_pBufFile +// - m_nPosEof +// +void CwindowBuf::BufFileSet(QFile * inFile) +{ + Q_ASSERT(inFile); + + if(!inFile) + { + msgBox.setText("ERROR: BufFileSet() with NULL inFile"); + msgBox.exec(); + Q_ASSERT(false); + return; + } + + m_pBufFile = inFile; + m_nPosEof = m_pBufFile->size(); + + if(m_nPosEof == 0) + { + m_pBufFile = NULL; + msgBox.setText("ERROR: BufFileSet() File length zero"); + msgBox.exec(); + } +} + +// Called to mark the buffer as closed +// - Typically done when we've finished processing a file +// This avoids problems where we try to read a buffer +// that has already been terminated. +// +// POST: +// - m_pBufFile +// +void CwindowBuf::BufFileUnset() +{ + if(m_pBufFile) + { + m_pBufFile = NULL; + } +} + +// Search for a value in the buffer from a given starting position +// and direction, limited to a maximum search depth +// - Search value can be 8-bit, 16-bit or 32-bit +// - Update progress in lengthy searches +// +// INPUT: +// - nStartPos Starting byte offset for search +// - nSearchVal Value to search for (up to 32-bit unsigned) +// - nSearchLen Maximum number of bytes to search +// - bDirFwd TRUE for forward, FALSE for backwards +// +// PRE: +// - m_nPosEof +// +// OUTPUT: +// - nFoundPos Byte offset in buffer for start of search match +// +// RETURN: +// - Success in finding the value +// +bool CwindowBuf::BufSearch(uint32_t nStartPos, uint32_t nSearchVal, uint32_t nSearchLen, + bool bDirFwd, uint32_t &nFoundPos) +{ + // Save the current position + uint32_t nCurPos; + + uint32_t nCurVal; + + QString strStatus; + + time_t tmLast = clock(); + + nCurPos = nStartPos; + bool bDone = false; + + bool bFound = false; + + while(!bDone) + { + // Update progress in status bar + // - Note that we only check timer when step counter has + // reached a certain threshold. This limits the overhead + // associated with the timer comparison + if(((nCurPos % (16 * 1024)) == 0) && (m_pStatBar)) + { + time_t tmNow = clock(); + + if((tmNow - tmLast) > (CLOCKS_PER_SEC / 8)) + { + tmLast = tmNow; + float fProgress = (nCurPos * 100.0f) / m_nPosEof; + + strStatus = QString("Searching %3.f%% (%lu of %lu)...").arg(fProgress).arg(nCurPos).arg(m_nPosEof); + m_pStatBar->showMessage(strStatus); + } + } + + if(bDirFwd) + { + nCurPos++; + + if(nCurPos + (nSearchLen - 1) >= m_nPosEof) + { + bDone = true; + } + } + else + { + if(nCurPos > 0) + { + nCurPos--; + } + else + { + bDone = true; + } + } + + if(nSearchLen == 4) + { + nCurVal = (Buf(nCurPos + 0) << 24) + (Buf(nCurPos + 1) << 16) + (Buf(nCurPos + 2) << 8) + Buf(nCurPos + 3); + } + else if(nSearchLen == 3) + { + nCurVal = (Buf(nCurPos + 0) << 16) + (Buf(nCurPos + 1) << 8) + Buf(nCurPos + 2); + } + else if(nSearchLen == 2) + { + nCurVal = (Buf(nCurPos + 0) << 8) + Buf(nCurPos + 1); + } + else if(nSearchLen == 1) + { + nCurVal = Buf(nCurPos + 0); + } + else + { + msgBox.setText("ERROR: Unexpected nSearchLen"); + msgBox.exec(); + nCurVal = 0x0000; + } + + if(nCurVal == nSearchVal) + { + bFound = true; + bDone = true; + } + } + + nFoundPos = nCurPos; + return bFound; +} + +//SetStatusText + +// Establish local copy of status bar pointer +void CwindowBuf::SetStatusBar(QStatusBar * pStatBar) +{ + m_pStatBar = pStatBar; +} + +// Search for a variable-length byte string in the buffer from a given starting position +// and direction, limited to a maximum search depth +// - Search string is array of unsigned bytes +// - Update progress in lengthy searches +// +// INPUT: +// - nStartPos Starting byte offset for search +// - anSearchVal Byte array to search for +// - nSearchLen Maximum number of bytes to search +// - bDirFwd TRUE for forward, FALSE for backwards +// +// PRE: +// - m_nPosEof +// - m_pStatBar +// +// OUTPUT: +// - nFoundPos Byte offset in buffer for start of search match +// +// RETURN: +// - Success in finding the value +// +bool CwindowBuf::BufSearchX(uint32_t nStartPos, unsigned char *anSearchVal, uint32_t nSearchLen, + bool bDirFwd, uint32_t &nFoundPos) +{ + // Save the current position + uint32_t nCurPos; + + uint32_t nByteCur; + uint32_t nByteSearch; + + uint32_t nCurPosOffset; + uint32_t nMatchStartPos = 0; + + //bool bMatchStart = false; + bool bMatchOn = false; + + QString strStatus; + + time_t tmLast = clock(); + + nCurPosOffset = 0; + nCurPos = nStartPos; + bool bDone = false; + + bool bFound = false; // Matched entire search string + + while(!bDone) + { + + if(bDirFwd) + { + nCurPos++; + + if(nCurPos + (nSearchLen - 1) >= m_nPosEof) + { + bDone = true; + } + } + else + { + if(nCurPos > 0) + { + nCurPos--; + } + else + { + bDone = true; + } + } + + // Update progress in status bar + // - Note that we only check timer when step counter has + // reached a certain threshold. This limits the overhead + // associated with the timer comparison + if(((nCurPos % (16 * 1024)) == 0) && (m_pStatBar)) + { + time_t tmNow = clock(); + + if((tmNow - tmLast) > (CLOCKS_PER_SEC / 8)) + { + tmLast = tmNow; + float fProgress = (nCurPos * 100.0f) / m_nPosEof; + + strStatus = QString("Searching %3.f%% (%lu of %lu)...").arg(fProgress).arg(nCurPos).arg(m_nPosEof); + m_pStatBar->showMessage(strStatus); + } + } + + nByteSearch = anSearchVal[nCurPosOffset]; + nByteCur = Buf(nCurPos); + + if(nByteSearch == nByteCur) + { + if(!bMatchOn) + { + // Since we aren't in match mode, we are beginning a new + // sequence, so save the starting position in case we + // have to rewind + nMatchStartPos = nCurPos; + bMatchOn = true; + } + + nCurPosOffset++; + } + else + { + if(bMatchOn) + { + // Since we were in a sequence of matches, but ended early, + // we now need to reset our position to just after the start + // of the previous 1st match. + nCurPos = nMatchStartPos; + bMatchOn = false; + } + + nCurPosOffset = 0; + } + + if(nCurPosOffset >= nSearchLen) + { + // We matched the entire length of our search string! + bFound = true; + bDone = true; + } + } + + if(m_pStatBar) + { + m_pStatBar->showMessage("Done"); + } + + if(bFound) + { + nFoundPos = nMatchStartPos; + } + + return bFound; +} + +// Ensure that the file offset parameter is captured in the current +// buffer cache. If not, reload a new cache around this offset. +// - Provide some limited cache prior to the desired address +// - Provide majority of cache after the desired address +// - The cache prior to the address facilitates reverse search performance +// +// INPUT: +// - nPosition File offset to ensure is available in new window +// PRE: +// - m_pBufFile +// - m_nPosEof +// +// POST: +// - m_bBufOK +// - m_nBufWinSize +// - m_nBufWinStart +// +void CwindowBuf::BufLoadWindow(uint32_t nPosition) +{ + + // We must not try to perform a seek command on a CFile that + // has already been closed, so we must check first. + + if(m_pBufFile) + { + /* + QString strTmp; + strTmp = QString("** BufLoadWindow @ 0x%08X"),nPosition); + log->AddLine(strTmp); + */ + + // Initialize to bad values + m_bBufOK = false; + m_nBufWinSize = 0; + m_nBufWinStart = 0; + + // For now, just read 128KB starting at current position + // Later on, we will need to do range checking and even start + // at a nPosition some distance before the "nPosition" to allow + // for some reverse seeking without refetching data. + + uint32_t nPositionAdj; + + if(nPosition >= MAX_BUF_WINDOW_REV) + { + nPositionAdj = nPosition - MAX_BUF_WINDOW_REV; + } + else + { + nPositionAdj = 0; + } + + // NOTE: + // Need to ensure that we don't try to read past the end of file. + // I have encountered some JPEGs that have Canon makernote + // fields with OffsetValue > 0xFFFF0000! Interpreting this as-is + // would cuase BufLoadWindow() to read past the end of file. + if(nPositionAdj >= m_nPosEof) + { + + // ERROR! For now, just do this silently + // We're not going to throw up any errors unless we can + // limit the number that we'll display to the user! + // The current code will not reset the nPosition of the + // buffer, so every byte will try to reset it. + // FIXME + return; + } + + qint64 nVal; + + nVal = m_pBufFile->seek(nPositionAdj); + nVal = m_pBufFile->read(reinterpret_cast(m_pBuffer), MAX_BUF_WINDOW); + + if(nVal <= 0) + { + // Failed to read anything! + // ERROR! + return; + } + else + { + // Read OK + // Recalculate bounds + m_bBufOK = true; + m_nBufWinStart = nPositionAdj; + m_nBufWinSize = nVal; + } + } + else + { + msgBox.setText("ERROR: BufLoadWindow() and no file open"); + msgBox.exec(); + } +} + +// Allocate a new buffer overlay into the array +// over overlays. Limits the number of overlays +// to NUM_OVERLAYS. +// - If the indexed overlay already exists, no changes are made +// - TODO: Replace with vector +// +// INPUT: +// - nInd Overlay index to allocate +// +// POST: +// - m_psOverlay[] +// +bool CwindowBuf::OverlayAlloc(uint32_t nInd) +{ + if(nInd >= NUM_OVERLAYS) + { + msgBox.setText("ERROR: Maximum number of overlays reached"); + msgBox.exec(); + return false; + + } + else if(m_psOverlay[nInd]) + { + // Already allocated, move on + return true; + + } + else + { + m_psOverlay[nInd] = new sOverlay(); + + if(!m_psOverlay[nInd]) + { + msgBox.setText("NOTE: Out of memory for extra file overlays"); + msgBox.exec(); + return false; + } + else + { + memset(m_psOverlay[nInd], 0, sizeof(sOverlay)); + // FIXME: may not be necessary + m_psOverlay[nInd]->bEn = false; + m_psOverlay[nInd]->nStart = 0; + m_psOverlay[nInd]->nLen = 0; + + m_psOverlay[nInd]->nMcuX = 0; + m_psOverlay[nInd]->nMcuY = 0; + m_psOverlay[nInd]->nMcuLen = 0; + m_psOverlay[nInd]->nMcuLenIns = 0; + m_psOverlay[nInd]->nDcAdjustY = 0; + m_psOverlay[nInd]->nDcAdjustCb = 0; + m_psOverlay[nInd]->nDcAdjustCr = 0; + + // FIXME: Need to ensure that this is right + if(nInd + 1 >= m_nOverlayMax) + { + m_nOverlayMax = nInd + 1; + } + //m_nOverlayMax++; + + return true; + } + } +} + +// Report out the list of overlays thave have been allocated +// +// PRE: +// - m_nOverlayNum +// - m_psOverlay[] +// +void CwindowBuf::ReportOverlays(CDocLog *pLog) +{ + QString strTmp; + + if(m_nOverlayNum > 0) + { + strTmp = QString(" Buffer Overlays active: %1").arg(m_nOverlayNum); + pLog->AddLine(strTmp); + + for(uint32_t ind = 0; ind < m_nOverlayNum; ind++) + { + if(m_psOverlay[ind]) + { + strTmp = + QString(" %03u: MCU[%4u,%4u] MCU DelLen=[%2u] InsLen=[%2u] DC Offset YCC=[%5d,%5d,%5d] Overlay Byte Len=[%4u]"). + arg(ind).arg(m_psOverlay[ind]->nMcuX).arg(m_psOverlay[ind]->nMcuY).arg(m_psOverlay[ind]->nMcuLen).arg(m_psOverlay[ind]-> + nMcuLenIns). + arg(m_psOverlay[ind]->nDcAdjustY).arg(m_psOverlay[ind]->nDcAdjustCb).arg(m_psOverlay[ind]->nDcAdjustCr). + arg(m_psOverlay[ind]->nLen); + pLog->AddLine(strTmp); + } + } + + pLog->AddLine(""); + } +} + +// Define the content of an overlay +// +// INPUT: +// - nOvrInd The overlay index to update/replace +// - pOverlay The byte array that defines the overlay content +// - nLen Byte length of the overlay +// - nBegin Starting byte offset for the overlay +// - nMcuX Additional info for this overlay +// - nMcuY Additional info for this overlay +// - nMcuLen Additional info for this overlay +// - nMcuLenIns Additional info for this overlay +// - nAdjY Additional info for this overlay +// - nAdjCb Additional info for this overlay +// - nAdjCr Additional info for this overlay +// +bool CwindowBuf::OverlayInstall(uint32_t nOvrInd, unsigned char *pOverlay, uint32_t nLen, uint32_t nBegin, + uint32_t nMcuX, uint32_t nMcuY, uint32_t nMcuLen, uint32_t nMcuLenIns, + int nAdjY, int nAdjCb, int nAdjCr) +{ + nOvrInd; // Unreferenced param + + // Ensure that the overlay is allocated, and allocate it + // if required. Fail out if we can't add (or run out of space) + if(!OverlayAlloc(m_nOverlayNum)) + { + return false; + } + + if(nLen < MAX_OVERLAY) + { + m_psOverlay[m_nOverlayNum]->bEn = true; + m_psOverlay[m_nOverlayNum]->nLen = nLen; + + // Copy the overlay content, but clip to maximum size and pad if shorter + for(uint32_t i = 0; i < MAX_OVERLAY; i++) + { + m_psOverlay[m_nOverlayNum]->anData[i] = (i < nLen) ? pOverlay[i] : 0x00; + } + + m_psOverlay[m_nOverlayNum]->nStart = nBegin; + + // For reporting, save the extra data + m_psOverlay[m_nOverlayNum]->nMcuX = nMcuX; + m_psOverlay[m_nOverlayNum]->nMcuY = nMcuY; + m_psOverlay[m_nOverlayNum]->nMcuLen = nMcuLen; + m_psOverlay[m_nOverlayNum]->nMcuLenIns = nMcuLenIns; + m_psOverlay[m_nOverlayNum]->nDcAdjustY = nAdjY; + m_psOverlay[m_nOverlayNum]->nDcAdjustCb = nAdjCb; + m_psOverlay[m_nOverlayNum]->nDcAdjustCr = nAdjCr; + + m_nOverlayNum++; + } + else + { + msgBox.setText("ERROR: CwindowBuf:OverlayInstall() overlay too large"); + msgBox.exec(); + return false; + } + + return true; +} + +// Remove latest overlay entry +// +// POST: +// - m_nOverlayNum +// - m_psOverlay[] +// +void CwindowBuf::OverlayRemove() +{ + if(m_nOverlayNum <= 0) + { + return; + } + + m_nOverlayNum--; + + // Note that we've already decremented the m_nOverlayNum + if(m_psOverlay[m_nOverlayNum]) + { + // Don't need to delete the overlay struct as we might as well reuse it + m_psOverlay[m_nOverlayNum]->bEn = false; + //delete m_psOverlay[m_nOverlayNum]; + //m_psOverlay[m_nOverlayNum] = NULL; + } +} + +// Disable all buffer overlays +// +// POST: +// - m_nOverlayNum +// - m_psOverlay[] +// +void CwindowBuf::OverlayRemoveAll() +{ + m_nOverlayNum = 0; + + for(uint32_t nInd = 0; nInd < m_nOverlayMax; nInd++) + { + if(m_psOverlay[nInd]) + { + m_psOverlay[nInd]->bEn = false; + } + } +} + +// Fetch the indexed buffer overlay +// +// INPUT: +// - nOvrInd The overlay index +// +// OUTPUT: +// - pOverlay A pointer to the indexed buffer +// - nLen Length of the overlay string +// - nBegin Starting file offset for the overlay +// +// RETURN: +// - Success if overlay index was allocated and enabled +// +bool CwindowBuf::OverlayGet(uint32_t nOvrInd, unsigned char *&pOverlay, uint32_t &nLen, uint32_t &nBegin) +{ + if((m_psOverlay[nOvrInd]) && (m_psOverlay[nOvrInd]->bEn)) + { + pOverlay = m_psOverlay[nOvrInd]->anData; + nLen = m_psOverlay[nOvrInd]->nLen; + nBegin = m_psOverlay[nOvrInd]->nStart; + return m_psOverlay[nOvrInd]->bEn; + } + else + { + return false; + } +} + +// Get the number of buffer overlays allocated +// +uint32_t CwindowBuf::OverlayGetNum() +{ + return m_nOverlayNum; +} + +// Replaces the direct buffer access with a managed refillable window/cache. +// - Support for 1-byte access only +// - Support for overlays (optional) +// +// INPUT: +// - nOffset File offset to fetch from (via cache) +// - bClean Flag that indicates if overlays can be used +// If set to FALSE, then content from overlays that span +// the offset address will be returned instead of the file content +// +// RETURN: +// - Byte from the desired address +uint8_t CwindowBuf::Buf(uint32_t nOffset, bool bClean) +{ + // We are requesting address "nOffset" + // Our current window runs from "m_nBufWinStart...buf_win_end" (m_nBufWinSize) + // Therefore, our relative addr is nOffset-m_nBufWinStart + + long nWinRel; + + unsigned char nCurVal = 0; + + uint32_t bInOvrWindow = false; + + if(!m_pBufFile) + { + // FIXME: Open file or provide error + } + + Q_ASSERT(m_pBufFile); + + // Allow for overlay buffer capability (if not in "clean" mode) + if(!bClean) + { + // Now handle any overlays + for(uint32_t nInd = 0; nInd < m_nOverlayNum; nInd++) + { + if(m_psOverlay[nInd]) + { + if(m_psOverlay[nInd]->bEn) + { + if((nOffset >= m_psOverlay[nInd]->nStart) && (nOffset < m_psOverlay[nInd]->nStart + m_psOverlay[nInd]->nLen)) + { + nCurVal = m_psOverlay[nInd]->anData[nOffset - m_psOverlay[nInd]->nStart]; + bInOvrWindow = true; + } + } + } + } + + if(bInOvrWindow) + { + + // Before we return, make sure that the real buffer handles this region! + nWinRel = nOffset - m_nBufWinStart; + + if((nWinRel >= 0) && (nWinRel < (long) m_nBufWinSize)) + { + } + else + { + // Address is outside of current window + BufLoadWindow(nOffset); + } + + return nCurVal; + } + } + + // Now that we've finished any overlays, proceed to actual cache content + + // Determine if the offset is within the current cache + // If not, reload a new cache around the desired address + nWinRel = nOffset - m_nBufWinStart; + + if((nWinRel >= 0) && (nWinRel < (long) m_nBufWinSize)) + { + // Address is within current window + return m_pBuffer[nWinRel]; + } + else + { + // Address is outside of current window + BufLoadWindow(nOffset); + + // Now we assume that the address is in range + // m_nBufWinStart has now been updated + // TODO: check this + nWinRel = nOffset - m_nBufWinStart; + + // Now recheck the window + // TODO: Rewrite the following in a cleaner manner + if((nWinRel >= 0) && (nWinRel < (long) m_nBufWinSize)) + { + return m_pBuffer[nWinRel]; + } + else + { + // Still bad after refreshing window, so it must be bad addr + m_bBufOK = false; + // FIXME: Need to report error somehow + //log->AddLine("ERROR: Overread buffer - file may be truncated"),9); + return 0; + } + } +} + +// Replaces the direct buffer access with a managed refillable window/cache. +// - Supports 1/2/4 byte fetch +// - No support for overlays +// +// INPUT: +// - nOffset File offset to fetch from (via cache) +// - nSz Size of word to fetch (1,2,4) +// - nByteSwap Flag to indicate if UINT16 or UINT32 should be byte-swapped +// +// RETURN: +// - 1/2/4 unsigned bytes from the desired address +// +uint32_t CwindowBuf::BufX(uint32_t nOffset, uint32_t nSz, bool nByteSwap) +{ + long nWinRel; + + Q_ASSERT(m_pBufFile); + + nWinRel = nOffset - m_nBufWinStart; + if((nWinRel >= 0) && (nWinRel + nSz < m_nBufWinSize)) + { + // Address is within current window + if(!nByteSwap) + { + if(nSz == 4) + { + return ((m_pBuffer[nWinRel + 0] << 24) + (m_pBuffer[nWinRel + 1] << 16) + (m_pBuffer[nWinRel + 2] << 8) + + (m_pBuffer[nWinRel + 3])); + } + else if(nSz == 2) + { + return ((m_pBuffer[nWinRel + 0] << 8) + (m_pBuffer[nWinRel + 1])); + } + else if(nSz == 1) + { + return (m_pBuffer[nWinRel + 0]); + } + else + { + msgBox.setText("ERROR: BufX() with bad size"); + msgBox.exec(); + return 0; + } + } + else + { + if(nSz == 4) + { + return ((m_pBuffer[nWinRel + 3] << 24) + (m_pBuffer[nWinRel + 2] << 16) + (m_pBuffer[nWinRel + 1] << 8) + + (m_pBuffer[nWinRel + 0])); + } + else if(nSz == 2) + { + return ((m_pBuffer[nWinRel + 1] << 8) + (m_pBuffer[nWinRel + 0])); + } + else if(nSz == 1) + { + return (m_pBuffer[nWinRel + 0]); + } + else + { + msgBox.setText("ERROR: BufX() with bad size"); + msgBox.exec(); + return 0; + } + } + } + else + { + // Address is outside of current window + BufLoadWindow(nOffset); + + // Now we assume that the address is in range + // m_nBufWinStart has now been updated + // TODO: Check this + nWinRel = nOffset - m_nBufWinStart; + + // Now recheck the window + // TODO: Rewrite the following in a cleaner manner + if((nWinRel >= 0) && (nWinRel + nSz < m_nBufWinSize)) + { + if(!nByteSwap) + { + if(nSz == 4) + { + return ((m_pBuffer[nWinRel + 0] << 24) + (m_pBuffer[nWinRel + 1] << 16) + (m_pBuffer[nWinRel + 2] << 8) + + (m_pBuffer[nWinRel + 3])); + } + else if(nSz == 2) + { + return ((m_pBuffer[nWinRel + 0] << 8) + (m_pBuffer[nWinRel + 1])); + } + else if(nSz == 1) + { + return (m_pBuffer[nWinRel + 0]); + } + else + { + msgBox.setText("ERROR: BufX() with bad size"); + msgBox.exec(); + return 0; + } + } + else + { + if(nSz == 4) + { + return ((m_pBuffer[nWinRel + 3] << 24) + (m_pBuffer[nWinRel + 2] << 16) + (m_pBuffer[nWinRel + 1] << 8) + + (m_pBuffer[nWinRel + 0])); + } + else if(nSz == 2) + { + return ((m_pBuffer[nWinRel + 1] << 8) + (m_pBuffer[nWinRel + 0])); + } + else if(nSz == 1) + { + return (m_pBuffer[nWinRel + 0]); + } + else + { + msgBox.setText("ERROR: BufX() with bad size"); + msgBox.exec(); + return 0; + } + } + } + else + { + // Still bad after refreshing window, so it must be bad addr + m_bBufOK = false; + // FIXME: Need to report error somehow + //log->AddLine("ERROR: Overread buffer - file may be truncated"),9); + return 0; + } + } +} + +unsigned char CwindowBuf::BufRdAdv1(uint32_t &nOffset, bool bByteSwap) +{ + unsigned char nRet; + + nRet = static_cast < unsigned char >(BufX(nOffset, 1, bByteSwap)); + + nOffset += 1; + return nRet; +} + +uint16_t CwindowBuf::BufRdAdv2(uint32_t &nOffset, bool bByteSwap) +{ + uint16_t nRet; + + nRet = static_cast < uint16_t >(BufX(nOffset, 2, bByteSwap)); + + nOffset += 2; + return nRet; +} + +uint32_t CwindowBuf::BufRdAdv4(uint32_t &nOffset, bool bByteSwap) +{ + uint32_t nRet; + + nRet = BufX(nOffset, 4, bByteSwap); + nOffset += 4; + return nRet; +} + +// Read a null-terminated string from the buffer/cache at the +// indicated file offset. +// - Does not affect the current file pointer nPosition +// - String length is limited by encountering either the NULL character +// of exceeding the maximum length of MAX_BUF_READ_STR +// +// INPUT: +// - nPosition File offset to start string fetch +// +// RETURN: +// - String fetched from file +// +QString CwindowBuf::BufReadStr(uint32_t nPosition) +{ + // Try to read a NULL-terminated string from file offset "nPosition" + // up to a maximum of MAX_BUF_READ_STR bytes. Result is max length MAX_BUF_READ_STR + QString strRd = ""; + + unsigned char cRd; + + bool bDone = false; + + uint32_t nIndex = 0; + + while(!bDone) + { + cRd = Buf(nPosition + nIndex); + // Only add if printable + if(isprint(cRd)) + { + strRd += cRd; + } + nIndex++; + if(cRd == 0) + { + bDone = true; + } + else if(nIndex >= MAX_BUF_READ_STR) + { + bDone = true; + // No need to null-terminate the string since we are using QString + } + } + return strRd; +} + +// Read a null-terminated 16-bit unicode string from the buffer/cache at the +// indicated file offset. +// - FIXME: Replace faked out unicode-to-ASCII conversion with real implementation +// - Does not affect the current file pointer nPosition +// - String length is limited by encountering either the NULL character +// of exceeding the maximum length of MAX_BUF_READ_STR +// - Reference: BUG: #1112 +// +// INPUT: +// - nPosition File offset to start string fetch +// +// RETURN: +// - String fetched from file +// +QString CwindowBuf::BufReadUniStr(uint32_t nPosition) +{ + // Try to read a NULL-terminated string from file offset "nPosition" + // up to a maximum of MAX_BUF_READ_STR bytes. Result is max length MAX_BUF_READ_STR + QString strRd; + + unsigned char cRd; + + bool bDone = false; + + uint32_t nIndex = 0; + + while(!bDone) + { + cRd = Buf(nPosition + nIndex); + + // Make sure it is a printable char! + // FIXME: No, we can't check for this as it will cause + // _tcslen() call in the calling function to get the wrong + // length as it isn't null-terminated. Skip for now. +// if (isprint(cRd)) { +// strRd += cRd; +// } else { +// strRd += "."); +// } + strRd += cRd; + + nIndex += 2; + if(cRd == 0) + { + bDone = true; + } + else if(nIndex >= (MAX_BUF_READ_STR * 2)) + { + bDone = true; + } + } + return strRd; +} + +// Wrapper for ByteStr2Unicode that uses local Window Buffer +#define MAX_UNICODE_STRLEN 255 +QString CwindowBuf::BufReadUniStr2(uint32_t nPos, uint32_t nBufLen) +{ + // Convert byte array into unicode string + // TODO: Replace with call to ByteStr2Unicode() + + bool bByteSwap = false; + + QString strVal; + + uint32_t nStrLenTrunc; + + unsigned char nChVal; + + unsigned char anStrBuf[(MAX_UNICODE_STRLEN + 1) * 2]; + + wchar_t acStrBuf[(MAX_UNICODE_STRLEN + 1)]; + + // Start with length before any truncation + nStrLenTrunc = nBufLen; + + // Read unicode bytes into byte array + // Truncate the string, leaving room for terminator + if(nStrLenTrunc > MAX_UNICODE_STRLEN) + { + nStrLenTrunc = MAX_UNICODE_STRLEN; + } + + for(uint32_t nInd = 0; nInd < nStrLenTrunc; nInd++) + { + if(bByteSwap) + { + // Reverse the order of the bytes + nChVal = Buf(nPos + (nInd * 2) + 0); + anStrBuf[(nInd * 2) + 1] = nChVal; + nChVal = Buf(nPos + (nInd * 2) + 1); + anStrBuf[(nInd * 2) + 0] = nChVal; + } + else + { + // No byte reversal + nChVal = Buf(nPos + (nInd * 2) + 0); + anStrBuf[(nInd * 2) + 0] = nChVal; + nChVal = Buf(nPos + (nInd * 2) + 1); + anStrBuf[(nInd * 2) + 1] = nChVal; + } + } + + // Ensure it is terminated + anStrBuf[nStrLenTrunc * 2 + 0] = 0; + anStrBuf[nStrLenTrunc * 2 + 1] = 0; + // Copy into unicode string + // Ensure that it is terminated first! +// lstrcpyW(acStrBuf, (LPCWSTR) anStrBuf); + // Copy into QString + strVal = QString(reinterpret_cast(anStrBuf)); + + return strVal; +} + +// Read a string from the buffer/cache at the indicated file offset. +// - Does not affect the current file pointer nPosition +// - String length is limited by encountering either the NULL character +// of exceeding the maximum length parameter +// +// INPUT: +// - nPosition File offset to start string fetch +// - nLen Maximum number of bytes to fetch +// +// RETURN: +// - String fetched from file +// +QString CwindowBuf::BufReadStrn(uint32_t nPosition, uint32_t nLen) +{ + // Try to read a fixed-length string from file offset "nPosition" + // up to a maximum of "nLen" bytes. Result is length "nLen" + QString strRd = ""; + + unsigned char cRd; + + bool bDone = false; + + if(nLen > 0) + { + for(uint32_t nInd = 0; ((!bDone) && (nInd < nLen)); nInd++) + { + cRd = Buf(nPosition + nInd); + if(isprint(cRd)) + { + strRd += cRd; + } + if(cRd == char (0)) + { + bDone = true; + } + } + return strRd; + } + else + { + return ""; + } +} diff --git a/source/WindowBuf.h b/source/WindowBuf.h index f3a724b..a53a17f 100644 --- a/source/WindowBuf.h +++ b/source/WindowBuf.h @@ -1,128 +1,135 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Provides a cache for file access -// - Allows random access to a file but only issues new file I/O if -// the requested address is outside of the current cache window -// - Provides an overlay for temporary (local) buffer overwrites -// - Buffer search methods -// -// ========================================================================== - - -#pragma once - -#include "DocLog.h" - -// For now, we only ever use MAX_BUF_WINDOW bytes, even though we -// have allocated MAX_BUF bytes up front. I might change this -// later. We don't want the window size to be too large as it -// could have an impact on performance. -#define MAX_BUF 262144L -#define MAX_BUF_WINDOW 131072L -#define MAX_BUF_WINDOW_REV 16384L //1024L - -#define NUM_OVERLAYS 500 -#define MAX_OVERLAY 500 // 500 bytes - -#define NUM_HOLES 10 - -#define MAX_BUF_READ_STR 255 // Max number of bytes to fetch in BufReadStr() - -typedef struct { - bool bEn; // Enabled? -- not used currently - unsigned nStart; // File position - unsigned nLen; // MCU Length - BYTE anData[MAX_OVERLAY]; // Byte data - - // For reporting purposes: - unsigned nMcuX; // Starting MCU X - unsigned nMcuY; // Starting MCU Y - unsigned nMcuLen; // Number of MCUs deleted - unsigned nMcuLenIns; // Number of MCUs inserted - int nDcAdjustY; - int nDcAdjustCb; - int nDcAdjustCr; - -} sOverlay; - -class CwindowBuf -{ -public: - CwindowBuf(); - ~CwindowBuf(); - -public: - void SetStatusBar(CStatusBar* pStatBar); - - void BufLoadWindow(unsigned long nPosition); - void BufFileSet(CFile* inFile); - void BufFileUnset(); - BYTE Buf(unsigned long nOffset,bool bClean=false); - unsigned BufX(unsigned long nOffset,unsigned nSz,bool bByteSwap=false); - - unsigned char BufRdAdv1(unsigned long &nOffset,bool bByteSwap); - unsigned short BufRdAdv2(unsigned long &nOffset,bool bByteSwap); - unsigned BufRdAdv4(unsigned long &nOffset,bool bByteSwap); - - - CString BufReadStr(unsigned long nPosition); - CString BufReadUniStr(unsigned long nPosition); - CString BufReadUniStr2(unsigned long nPos, unsigned nBufLen); - CString BufReadStrn(unsigned long nPosition,unsigned nLen); - - bool BufSearch(unsigned long nStartPos, unsigned nSearchVal, unsigned nSearchLen, - bool bDirFwd, unsigned long &nFoundPos); - bool BufSearchX(unsigned long nStartPos, BYTE* anSearchVal, unsigned nSearchLen, - bool bDirFwd, unsigned long &nFoundPos); - - bool OverlayAlloc(unsigned nInd); - bool OverlayInstall(unsigned nOvrInd, BYTE* pOverlay,unsigned nLen,unsigned nBegin, - unsigned nMcuX,unsigned nMcuY,unsigned nMcuLen,unsigned nMcuLenIns, - int nAdjY,int nAdjCb,int nAdjCr); - void OverlayRemove(); - void OverlayRemoveAll(); - bool OverlayGet(unsigned nOvrInd, BYTE* &pOverlay,unsigned &nLen,unsigned &nBegin); - unsigned OverlayGetNum(); - void ReportOverlays(CDocLog* pLog); - - bool GetBufOk(); - unsigned long GetPosEof(); - -private: - void Reset(); - - -private: - BYTE* m_pBuffer; - CFile* m_pBufFile; - unsigned long m_nBufWinSize; - unsigned long m_nBufWinStart; - - unsigned m_nOverlayMax; // Number of overlays allocated (limited by mem) - unsigned m_nOverlayNum; - sOverlay* m_psOverlay[NUM_OVERLAYS]; - - CStatusBar* m_pStatBar; - - bool m_bBufOK; - unsigned long m_nPosEof; // Byte count at EOF - -}; +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - Provides a cache for file access +// - Allows random access to a file but only issues new file I/O if +// the requested address is outside of the current cache window +// - Provides an overlay for temporary (local) buffer overwrites +// - Buffer search methods +// +// ========================================================================== + +#ifndef WINDOWBUF_H +#define WINDOWBUF_H + +#include +#include +#include +#include + +#include "DocLog.h" + +class QPlainTextEdit; + +// For now, we only ever use MAX_BUF_WINDOW bytes, even though we +// have allocated MAX_BUF bytes up front. I might change this +// later. We don't want the window size to be too large as it +// could have an impact on performance. +#define MAX_BUF 262144L +#define MAX_BUF_WINDOW 131072L +#define MAX_BUF_WINDOW_REV 16384L //1024L + +#define NUM_OVERLAYS 500 +#define MAX_OVERLAY 500 // 500 bytes + +#define NUM_HOLES 10 + +#define MAX_BUF_READ_STR 255 // Max number of bytes to fetch in BufReadStr() + +typedef struct +{ + bool bEn; // Enabled? -- not used currently + uint32_t nStart; // File position + uint32_t nLen; // MCU Length + quint8 anData[MAX_OVERLAY]; // Byte data + + // For reporting purposes: + uint32_t nMcuX; // Starting MCU X + uint32_t nMcuY; // Starting MCU Y + uint32_t nMcuLen; // Number of MCUs deleted + uint32_t nMcuLenIns; // Number of MCUs inserted + int nDcAdjustY; + int nDcAdjustCb; + int nDcAdjustCr; +} sOverlay; + +class CwindowBuf +{ +public: + CwindowBuf(); + ~CwindowBuf(); + +public: + void SetStatusBar(QStatusBar *pStatBar); + + void BufLoadWindow(uint32_t nPosition); + void BufFileSet(QFile * inFile); + void BufFileUnset(); + uint8_t Buf(uint32_t nOffset, bool bClean = false); + uint32_t BufX(uint32_t nOffset, uint32_t nSz, bool bByteSwap = false); + + unsigned char BufRdAdv1(uint32_t &nOffset, bool bByteSwap); + uint16_t BufRdAdv2(uint32_t &nOffset, bool bByteSwap); + uint32_t BufRdAdv4(uint32_t &nOffset, bool bByteSwap); + + QString BufReadStr(uint32_t nPosition); + QString BufReadUniStr(uint32_t nPosition); + QString BufReadUniStr2(uint32_t nPos, uint32_t nBufLen); + QString BufReadStrn(uint32_t nPosition, uint32_t nLen); + + bool BufSearch(uint32_t nStartPos, uint32_t nSearchVal, uint32_t nSearchLen, bool bDirFwd, uint32_t &nFoundPos); + bool BufSearchX(uint32_t nStartPos, uint8_t * anSearchVal, uint32_t nSearchLen, bool bDirFwd, uint32_t &nFoundPos); + + bool OverlayAlloc(uint32_t nInd); + bool OverlayInstall(uint32_t nOvrInd, uint8_t *pOverlay, uint32_t nLen, uint32_t nBegin, + uint32_t nMcuX, uint32_t nMcuY, uint32_t nMcuLen, uint32_t nMcuLenIns, int nAdjY, int nAdjCb, int nAdjCr); + void OverlayRemove(); + void OverlayRemoveAll(); + bool OverlayGet(uint32_t nOvrInd, uint8_t *&pOverlay, uint32_t &nLen, uint32_t &nBegin); + uint32_t OverlayGetNum(); + void ReportOverlays(CDocLog *pLog); + + bool GetBufOk(); + uint32_t GetPosEof(); + +private: + void Reset(); + + CwindowBuf &operator = (const CwindowBuf&); + CwindowBuf(CwindowBuf&); + + unsigned char *m_pBuffer; + QFile *m_pBufFile; + uint32_t m_nBufWinSize; + uint32_t m_nBufWinStart; + + uint32_t m_nOverlayMax; // Number of overlays allocated (limited by mem) + uint32_t m_nOverlayNum; + sOverlay *m_psOverlay[NUM_OVERLAYS]; + + QStatusBar *m_pStatBar; + + QMessageBox msgBox; + + bool m_bBufOK; + quint64 m_nPosEof; // Byte count at EOF +}; + +#endif diff --git a/source/main.cpp b/source/main.cpp new file mode 100644 index 0000000..e440f49 --- /dev/null +++ b/source/main.cpp @@ -0,0 +1,36 @@ +#include +#include + +#include "DbSigs.h" +#include "DocLog.h" +#include "JPEGsnoop.h" +#include "JPEGsnoopCore.h" +#include "SnoopConfig.h" + +#include "mainwindow.h" + +CDocLog *glb_pDocLog; +CSnoopConfig* m_pAppConfig; +CDbSigs *m_pDbSigs; +CJPEGsnoopCore *pJPEGsnoopCore; + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QCoreApplication::setOrganizationName("ImpulseAdventure"); + QCoreApplication::setOrganizationDomain("www.impulseadventure.com"); + QCoreApplication::setApplicationName("JPEGsnoopQt"); + +// m_pAppConfig = new CSnoopConfig(); +// m_pAppConfig->UseDefaults(); + glb_pDocLog = new CDocLog(); + glb_pDocLog->Enable(); + m_pDbSigs = new CDbSigs(); +// pJPEGsnoopCore = new CJPEGsnoopCore(); +// m_pAppConfig->RegistryLoad(); + + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp new file mode 100644 index 0000000..336c7d2 --- /dev/null +++ b/source/mainwindow.cpp @@ -0,0 +1,685 @@ +#include + +#include "SnoopConfig.h" +#include "snoopconfigdialog.h" +#include "JPEGsnoop.h" +//#include "Viewer.h" +#include "JfifDecode.h" +#include "ImgDecode.h" +#include "WindowBuf.h" + +#include "mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent) +{ + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("MainWindow::MainWindow() Begin"); + + QWidget *widget = new QWidget; + setCentralWidget(widget); + setGeometry(100, 100, 800, 700); + + // Allocate the file window buffer + m_pWBuf = new CwindowBuf(); + + if(!m_pWBuf) + { + msgBox.setText("ERROR: Not enough memory for File Buffer"); + exit(1); + } + + // Allocate the JPEG decoder + m_pImgDec = new CimgDecode(glb_pDocLog, m_pWBuf, this); + + if(!m_pWBuf) + { + msgBox.setText("ERROR: Not enough memory for Image Decoder"); + exit(1); + } + + m_pJfifDec = new CjfifDecode(glb_pDocLog, m_pWBuf, m_pImgDec); + + if(!m_pWBuf) + { + msgBox.setText("ERROR: Not enough memory for JFIF Decoder"); + exit(1); + } + + m_pAppConfig = new CSnoopConfig(m_pJfifDec); + m_pAppConfig->RegistryLoad(); + + menuBar()->setNativeMenuBar(false); + + createActions(); + createMenus(); + +// QScrollArea *scrollArea = new QScrollArea(this); +// scrollArea->setWidget(m_pImgDec); +// scrollArea->setBackgroundRole(QPalette::Dark); +// scrollArea->setVisible(false); + + QSplitter *splitter = new QSplitter(Qt::Vertical); + doc = new QPlainTextEdit; + doc->setMaximumBlockCount(0); + QFont f; + f.setFamily("Courier"); + doc->setFont(f); + doc->appendPlainText(""); + +// v = new Q_Viewer(this); + splitter->addWidget(doc); + splitter->addWidget(m_pImgDec); +// splitter->addWidget(scrollArea); + setCentralWidget(splitter); + + m_StatusBar = statusBar(); + QLabel *st1 = new QLabel(" "); + st1->setAlignment(Qt::AlignHCenter); + st1->setMinimumSize(st1->sizeHint()); + + m_StatusBar->addPermanentWidget(st1); + st1->setText("1234"); + m_pJfifDec->SetStatusBar(m_StatusBar); + connect(m_pJfifDec, SIGNAL(updateStatus(QString, int)), m_StatusBar, SLOT(showMessage(QString,int))); + connect(m_pImgDec, SIGNAL(updateStatus(QString, int)), m_StatusBar, SLOT(showMessage(QString,int))); + + glb_pDocLog->setDoc(doc); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::createActions(void) +{ + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("MainWindow::createActions() Begin"); + +// newAct = new QAction(tr("&New"), this); +// newAct->setShortcuts(QKeySequence::New); +// newAct->setStatusTip(tr("Create a new file")); +// connect(newAct, &QAction::triggered, this, &MainWindow::newFile); + + openAct = new QAction(tr("&Open Image..."), this); + openAct->setShortcuts(QKeySequence::Open); +// openAct->setStatusTip(tr("Open an existing file")); + connect(openAct, &QAction::triggered, this, &MainWindow::open); + + saveLogAct = new QAction(tr("&Save Log..."), this); + saveLogAct->setShortcuts(QKeySequence::Save); + saveLogAct->setEnabled(false); +// saveAct->setStatusTip(tr("Save the document to disk")); + connect(saveLogAct, &QAction::triggered, this, &MainWindow::saveLog); + + reprocessAct = new QAction(tr("Reprocess File"), this); + reprocessAct->setShortcut(tr("Ctrl+R")); + reprocessAct->setEnabled(false); +// saveAct->setStatusTip(tr("Save the document to disk")); +// connect(saveAct, &QAction::triggered, this, &MainWindow::save); + + batchProcessAct = new QAction(tr("Batch Process..."), this); + OffsetAct = new QAction(tr("Offset"), this); + + printAct = new QAction(tr("&Print..."), this); + printAct->setShortcuts(QKeySequence::Print); +// printAct->setStatusTip(tr("Print the document")); +// connect(printAct, &QAction::triggered, this, &MainWindow::print); + + printPreviewAct = new QAction(tr("Print Preview"), this); +// printAct->setStatusTip(tr("Print the document")); +// connect(printAct, &QAction::triggered, this, &MainWindow::print); + + printSetupAct = new QAction(tr("Print Setup..."), this); +// printAct->setStatusTip(tr("Print the document")); +// connect(printAct, &QAction::triggered, this, &MainWindow::print); + + recentFileAct = new QAction(tr("Recent File"), this); + recentFileAct->setEnabled(false); + + exitAct = new QAction(tr("E&xit"), this); + exitAct->setShortcuts(QKeySequence::Quit); +// exitAct->setStatusTip(tr("Exit the application")); + connect(exitAct, &QAction::triggered, this, &MainWindow::Quit); + + undoAct = new QAction(tr("Undo"), this); + undoAct->setShortcuts(QKeySequence::Undo); + undoAct->setEnabled(false); + + copyAct = new QAction(tr("&Copy"), this); + copyAct->setShortcuts(QKeySequence::Copy); + copyAct->setEnabled(false); + + selectAllAct = new QAction(tr("Select All"), this); + selectAllAct->setShortcuts(QKeySequence::SelectAll); + selectAllAct->setEnabled(false); + + findAct = new QAction(tr("Find..."), this); + findAct->setShortcuts(QKeySequence::Find); + findAct->setEnabled(false); + + findNextAct = new QAction(tr("Find Next"), this); + findNextAct->setShortcuts(QKeySequence::FindNext); + findNextAct->setEnabled(false); + + adjustAct = new QAction(tr("Adjust..."), this); + adjustAct->setEnabled(false); + + // Image Channel + rgbAct = new QAction(tr("RGB"), this); + rgbAct->setShortcut(tr("Alt+1")); + rgbAct->setCheckable(true); + rgbAct->setChecked(true); + + yccAct = new QAction(tr("YCC"), this); + yccAct->setShortcut(tr("Alt+2")); + yccAct->setCheckable(true); + + rAct = new QAction(tr("R"), this); + rAct->setShortcut(tr("Alt+3")); + rAct->setCheckable(true); + + gAct = new QAction(tr("G"), this); + gAct->setShortcut(tr("Alt+4")); + gAct->setCheckable(true); + + bAct = new QAction(tr("B"), this); + bAct->setShortcut(tr("Alt+5")); + bAct->setCheckable(true); + + yAct = new QAction(tr("Y (Greyscale)"), this); + yAct->setShortcut(tr("Alt+6")); + yAct->setCheckable(true); + + cbAct = new QAction(tr("Cb"), this); + cbAct->setShortcut(tr("Alt+7")); + cbAct->setCheckable(true); + + crAct = new QAction(tr("Cr"), this); + crAct->setShortcut(tr("Alt+8")); + crAct->setCheckable(true); + + channelGroup = new QActionGroup(this); + channelGroup->addAction(rgbAct); + channelGroup->addAction(yccAct); + channelGroup->addAction(rAct); + channelGroup->addAction(gAct); + channelGroup->addAction(bAct); + channelGroup->addAction(yAct); + channelGroup->addAction(cbAct); + channelGroup->addAction(crAct); + + // Image Zoom + zoomInAct = new QAction(tr("Zoom In")); + zoomInAct->setShortcuts(QKeySequence::ZoomIn); + + zoomOutAct = new QAction(tr("Zoom Out")); + zoomOutAct->setShortcuts(QKeySequence::ZoomOut); + + zoom12_5Act = new QAction(tr("12.5%"), this); + zoom12_5Act->setCheckable(true); + zoom12_5Act->setChecked(true); + + zoom25Act = new QAction(tr("25%"), this); + zoom25Act->setCheckable(true); + + zoom50Act = new QAction(tr("50%"), this); + zoom50Act->setCheckable(true); + + zoom100Act = new QAction(tr("100%"), this); + zoom100Act->setCheckable(true); + + zoom150Act = new QAction(tr("150%"), this); + zoom150Act->setCheckable(true); + + zoom200Act = new QAction(tr("200%"), this); + zoom200Act->setCheckable(true); + + zoom300Act = new QAction(tr("300%"), this); + zoom300Act->setCheckable(true); + + zoom400Act = new QAction(tr("400%"), this); + zoom400Act->setCheckable(true); + + zoom500Act = new QAction(tr("500%"), this); + zoom500Act->setCheckable(true); + + zoomGroup = new QActionGroup(this); + zoomGroup->addAction(zoom12_5Act); + zoomGroup->addAction(zoom25Act); + zoomGroup->addAction(zoom50Act); + zoomGroup->addAction(zoom100Act); + zoomGroup->addAction(zoom150Act); + zoomGroup->addAction(zoom200Act); + zoomGroup->addAction(zoom300Act); + zoomGroup->addAction(zoom400Act); + zoomGroup->addAction(zoom500Act); + + mcuGridAct = new QAction(tr("MCU Grid"), this); + mcuGridAct->setShortcut(tr("Ctrl+G")); + + toolbarAct = new QAction(tr("&Toolbar"), this); + toolbarAct->setCheckable(true); + toolbarAct->setChecked(true); + + statusBarAct = new QAction(tr("&Status Bar"), this); + statusBarAct->setCheckable(true); + statusBarAct->setChecked(true); + + // Tools + imgSearchFwdAct = new QAction(tr("Image Search Fwd"), this); + imgSearchFwdAct->setShortcut(tr("Ctrl+2")); + imgSearchFwdAct->setEnabled(false); + + imgSearchRevAct = new QAction(tr("Image Search Rev"), this); + imgSearchRevAct->setShortcut(tr("Ctrl+1")); + imgSearchRevAct->setEnabled(false); + + lookupMcuOffAct = new QAction(tr("Lookup MCU Offset..."), this); + lookupMcuOffAct->setEnabled(false); + + fileOverlayAct = new QAction(tr("File Overlay..."), this); + fileOverlayAct->setEnabled(false); + + searchDqtAct = new QAction(tr("Search Executable for DQT..."), this); + + exportJpegAct = new QAction(tr("Export JPEG..."), this); + exportJpegAct->setEnabled(false); + + exportTiffAct = new QAction(tr("Export TIFF..."), this); + exportTiffAct->setEnabled(false); + + addToDbAct = new QAction(tr("Add Camera/SW to DB..."), this); + addToDbAct->setShortcut(tr("Alt+S")); + addToDbAct->setEnabled(false); + + manageLocalDbAct = new QAction(tr("Manage Local DB..."), this); + + // Options + dhtExpandAct = new QAction(tr("DHT Expand"), this); + dhtExpandAct->setCheckable(true); + dhtExpandAct->setChecked(m_pAppConfig->bOutputDHTexpand); + connect(dhtExpandAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onOptionsDhtexpand())); + + hideUnknownTagsAct = new QAction(tr("Hide Unknown EXIF Tags"), this); + hideUnknownTagsAct->setCheckable(true); + hideUnknownTagsAct->setChecked(m_pAppConfig->bExifHideUnknown); + connect(hideUnknownTagsAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onOptionsHideuknownexiftags())); + + makerNotesAct = new QAction(tr("Maker Notes"), this); + makerNotesAct->setCheckable(true); + hideUnknownTagsAct->setChecked(m_pAppConfig->bDecodeMaker); + connect(makerNotesAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onOptionsMakernotes())); + + sigSearchAct = new QAction(tr("Signature Search"), this); + sigSearchAct->setCheckable(true); + sigSearchAct->setChecked(m_pAppConfig->bSigSearch); + connect(sigSearchAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onOptionsSignaturesearch())); + + relaxedParseAct = new QAction(tr("Relaxed Parsing"), this); + relaxedParseAct->setCheckable(true); + relaxedParseAct->setChecked(m_pAppConfig->bRelaxedParsing); + connect(relaxedParseAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onOptionsRelaxedparsing())); + + configAct = new QAction(tr("Configuration..."), this); + connect(configAct, &QAction::triggered, this, &MainWindow::onConfig); + + checkUpdatesAct = new QAction(tr("Check for Updates..."), this); + + // Scan Segment menu + decodeImageAct = new QAction(tr("Decode Image"), this); + decodeImageAct->setCheckable(true); + decodeImageAct->setChecked(m_pAppConfig->bDecodeScanImg); + connect(decodeImageAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentDecodeImage())); + + fullIdtcAct = new QAction(tr("Full IDCT (AC+DC - slow)"), this);; + fullIdtcAct->setCheckable(true); + connect(fullIdtcAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentFullidct())); + + noIdtcAct = new QAction(tr("No IDCT (DC only - fast)"), this);; + noIdtcAct->setCheckable(true); + connect(noIdtcAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentNoidct())); + + qDebug() << "Action" << m_pAppConfig->bDecodeScanImgAc; + + if(m_pAppConfig->bDecodeScanImgAc) + { + fullIdtcAct->setChecked(true); + } + else + { + noIdtcAct->setChecked(true); + } + + idtGroup = new QActionGroup(this); + idtGroup->addAction(noIdtcAct); + idtGroup->addAction(fullIdtcAct); + + histogramRgbAct = new QAction(tr("Histogram RGB"), this);; + histogramRgbAct->setCheckable(true); + histogramRgbAct->setChecked(m_pAppConfig->bHistoEn); + connect(histogramRgbAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentHistogram())); + + histogramYAct = new QAction(tr("Histogram Y"), this);; + histogramYAct->setCheckable(true); + histogramYAct->setChecked(m_pAppConfig->bDumpHistoY); + connect(histogramYAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentHistogramy())); + + dumpAct = new QAction(tr("Dump"), this);; + dumpAct->setCheckable(true); + dumpAct->setChecked(m_pAppConfig->bOutputScanDump); + connect(dumpAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentDump())); + + detailedDecodeAct = new QAction(tr("Detailed Decode..."), this); + + // Help menu + aboutAct = new QAction(tr("&About JPEGsnoop...")); + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("MainWindow::createActions() End"); +} + +void MainWindow::createMenus(void) +{ + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("MainWindow::createMenus() Begin"); + + fileMenu = menuBar()->addMenu("&File"); + fileMenu->addAction(openAct); + fileMenu->addAction(saveLogAct); + fileMenu->addAction(reprocessAct); + fileMenu->addSeparator(); + fileMenu->addAction(OffsetAct); + fileMenu->addSeparator(); + fileMenu->addAction(printAct); + fileMenu->addAction(printPreviewAct); + fileMenu->addAction(printSetupAct); + fileMenu->addSeparator(); + fileMenu->addAction(recentFileAct); + fileMenu->addSeparator(); + fileMenu->addAction(exitAct); + + editMenu = menuBar()->addMenu("&Edit"); + editMenu->addAction(undoAct); + editMenu->addSeparator(); + editMenu->addAction(copyAct); + editMenu->addAction(selectAllAct); + editMenu->addSeparator(); + editMenu->addAction(findAct); + editMenu->addAction(findNextAct); + + viewMenu = menuBar()->addMenu("&View"); + imageChanMenu = viewMenu->addMenu(tr("Image Chan")); + imageZoomMenu = viewMenu->addMenu(tr("Image Zoom")); + overlayMenu = viewMenu->addMenu(tr("Overlays")); + viewMenu->addAction(adjustAct); + viewMenu->addSeparator(); + viewMenu->addAction(toolbarAct); + viewMenu->addAction(statusBarAct); + + imageChanMenu->addAction(rgbAct); + imageChanMenu->addAction(yccAct); + imageChanMenu->addSeparator(); + imageChanMenu->addAction(rAct); + imageChanMenu->addAction(gAct); + imageChanMenu->addAction(bAct); + imageChanMenu->addSeparator(); + imageChanMenu->addAction(yAct); + imageChanMenu->addAction(cbAct); + imageChanMenu->addAction(crAct); + + imageZoomMenu->addAction(zoomInAct); + imageZoomMenu->addAction(zoomOutAct); + imageZoomMenu->addSeparator(); + imageZoomMenu->addAction(zoom12_5Act); + imageZoomMenu->addAction(zoom25Act); + imageZoomMenu->addAction(zoom50Act); + imageZoomMenu->addAction(zoom100Act); + imageZoomMenu->addAction(zoom150Act); + imageZoomMenu->addAction(zoom200Act); + imageZoomMenu->addAction(zoom300Act); + imageZoomMenu->addAction(zoom400Act); + imageZoomMenu->addAction(zoom500Act); + + overlayMenu->addAction(mcuGridAct); + + toolsMenu = menuBar()->addMenu("&Tools"); + toolsMenu->addAction(imgSearchFwdAct); + toolsMenu->addAction(imgSearchRevAct); + toolsMenu->addSeparator(); + toolsMenu->addAction(lookupMcuOffAct); + toolsMenu->addAction(fileOverlayAct); + toolsMenu->addAction(searchDqtAct); + toolsMenu->addAction(exportJpegAct); + toolsMenu->addAction(exportTiffAct); + toolsMenu->addSeparator(); + toolsMenu->addAction(addToDbAct); + toolsMenu->addAction(manageLocalDbAct); + + optionsMenu = menuBar()->addMenu("&Options"); + optionsMenu->addAction(dhtExpandAct); + optionsMenu->addAction(hideUnknownTagsAct); + optionsMenu->addAction(makerNotesAct); + optionsMenu->addAction(sigSearchAct); + optionsMenu->addAction(relaxedParseAct); + optionsMenu->addSeparator(); + scanSegMenu = optionsMenu->addMenu(tr("Scan Segment")); + optionsMenu->addSeparator(); + optionsMenu->addAction(configAct); + optionsMenu->addAction(checkUpdatesAct); + + // Scan Segment menu + scanSegMenu->addAction(decodeImageAct); + scanSegMenu->addSeparator(); + scanSegMenu->addAction(fullIdtcAct); + scanSegMenu->addAction(noIdtcAct); + scanSegMenu->addSeparator(); + scanSegMenu->addAction(histogramRgbAct); + scanSegMenu->addAction(histogramYAct); + scanSegMenu->addSeparator(); + scanSegMenu->addAction(dumpAct); + scanSegMenu->addAction(detailedDecodeAct); + + // Help menu + helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addAction(aboutAct); +} + +void MainWindow::open() +{ + QFileDialog dialog(this); + + QStringList filters; + filters << "JPEG Image (*.jpg *.jpeg)" + << "Thumbnail (*.thm)" + << "QuickTime Movie (*.mov)" + << "Digital Negative (*.dng)" + << "RAW Image (*.crw *.cr2 *.nef *.orf *.pef)" + << "PDF Files (*.pdf)" + << "Photoshop Files (*.psd)" + << "All Files (*)"; + dialog.setNameFilters(filters); + dialog.setFileMode(QFileDialog::ExistingFile); + dialog.setOption(QFileDialog::ReadOnly); + dialog.setDirectory("/Users/bob/Downloads"); + + if(dialog.exec()) + { + QStringList files = dialog.selectedFiles(); + + m_currentFile = files.at(0); + + m_pFile = new QFile(m_currentFile); + + if(m_pFile->open(QIODevice::ReadOnly) == false) + { + QString strError; + + // Note: msg includes m_strPathName + strError = QString("ERROR: Couldn't open file: [%1]").arg(m_currentFile); + glb_pDocLog->AddLineErr(strError); + + if(m_pAppConfig->bInteractive) + { + msgBox.setText(strError); + msgBox.exec(); + } + + m_pFile = NULL; + } + else + { + // Set the file size variable + m_lFileSize = m_pFile->size(); + + // Don't attempt to load buffer with zero length file! + if(m_lFileSize > 0) + { + // Open up the buffer + m_pWBuf->BufFileSet(m_pFile); + m_pWBuf->BufLoadWindow(0); + + // Mark file as opened + m_bFileOpened = true; + + enableMenus(); + AnalyzeFileDo(); + AnalyzeClose(); + } + else + { + m_pFile->close(); + } + } + } +} + +void MainWindow::AnalyzeFileDo() +{ + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("MainWindow::AnalyzeFileDo() Start"); + + // Ensure file was already opened + Q_ASSERT(m_pFile); + Q_ASSERT(m_bFileOpened); + + // Reset the analyzed state in case this file is invalid (eg. zero length) + m_bFileAnalyzed = false; + + // Clear the document log + glb_pDocLog->Clear(); + + glb_pDocLog->AddLine(""); + glb_pDocLog->AddLine(QString("JPEGsnoop %1 by Calvin Hass").arg(QString(VERSION_STR))); + glb_pDocLog->AddLine(" http://www.impulseadventure.com/photo/"); + glb_pDocLog->AddLine(" -------------------------------------"); + glb_pDocLog->AddLine(""); + glb_pDocLog->AddLine(QString(" Filename: [%1]").arg(m_currentFile)); + glb_pDocLog->AddLine(QString(" Filesize: [%1] bytes").arg(m_lFileSize)); + glb_pDocLog->AddLine(""); + + // Perform the actual decoding + if(m_lFileSize > 0xFFFFFFFF) + { + glb_pDocLog->AddLineErr(QString("ERROR: File too large for this version of JPEGsnoop. [Size=0x%1]").arg(m_lFileSize)); + } + else if(m_lFileSize == 0) + { + glb_pDocLog->AddLineErr("ERROR: File length is zero, no decoding done."); + } + else + { + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeFileDo() Checkpoint 2"); + + m_pJfifDec->ProcessFile(m_pFile); + + // Now indicate that the file has been processed + m_bFileAnalyzed = true; + } +} + + +// Close the current file +// - Invalidate the buffer +// +// POST: +// - m_bFileOpened +// +void MainWindow::AnalyzeClose() +{ + // Indicate no file is currently opened + // Note that we don't clear m_bFileAnalyzed as the last + // decoder state is still available + m_bFileOpened = false; + + // Close the buffer window + m_pWBuf->BufFileUnset(); + + m_pFile->close(); +} + +void MainWindow::saveLog() +{ + QFileDialog dialog(this); + + QStringList filters; + filters << "Text File (*.txt)"; + + QFileInfo fileInfo(m_currentFile); + + dialog.setWindowModality(Qt::WindowModal); + dialog.setAcceptMode(QFileDialog::AcceptSave); + dialog.setNameFilters(filters); +// dialog.setDirectory("/Users/bob/Downloads"); + dialog.selectFile(fileInfo.absoluteFilePath() + "/" + fileInfo.baseName() + ".txt"); + + if (dialog.exec() != QDialog::Accepted) + return; + +// return saveFile(dialog.selectedFiles().first()); + QFile file(dialog.selectedFiles().first()); + + if (!file.open(QFile::WriteOnly | QFile::Text)) + { + QMessageBox::warning(this, tr("Application"), + tr("Cannot write file %1:\n%2.") + .arg(QDir::toNativeSeparators(dialog.selectedFiles().first()), + file.errorString())); + return; + } + + QTextStream out(&file); + out << doc->toPlainText(); + + file.close(); +} + +void MainWindow::enableMenus() +{ + saveLogAct->setEnabled(true); + reprocessAct->setEnabled(true); + selectAllAct->setEnabled(true); + findAct->setEnabled(true); + imgSearchFwdAct->setEnabled(true); + imgSearchRevAct->setEnabled(true); + lookupMcuOffAct->setEnabled(true); + fileOverlayAct->setEnabled(true); + searchDqtAct->setEnabled(true); + exportJpegAct->setEnabled(true); + exportTiffAct->setEnabled(true); + addToDbAct->setEnabled(true); + manageLocalDbAct->setEnabled(true); +} + +void MainWindow::onConfig() +{ + configDialog = new SnoopConfigDialog(); + configDialog->show(); +} + +void MainWindow::Quit() +{ + m_pAppConfig->RegistryStore(); + QApplication::quit(); +} diff --git a/source/mainwindow.h b/source/mainwindow.h new file mode 100644 index 0000000..6455ca8 --- /dev/null +++ b/source/mainwindow.h @@ -0,0 +1,164 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include +#include + +class SnoopConfigDialog; +//class Q_Viewer; +class CjfifDecode; +class CimgDecode; +class CwindowBuf; + + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + + QPlainTextEdit *doc; +// Q_Viewer *v; + +private slots: + void open(); + void saveLog(); + void onConfig(); + void Quit(); + +private: + MainWindow &operator = (const MainWindow&); + MainWindow(MainWindow&); + + void createActions(void); + void createMenus(void); + void enableMenus(); + void AnalyzeFileDo(); + void AnalyzeClose(); + + SnoopConfigDialog *configDialog; + + // Decoders and Buffers + CjfifDecode *m_pJfifDec; + CimgDecode *m_pImgDec; + CwindowBuf *m_pWBuf; + + QMenu *fileMenu; + QMenu *editMenu; + QMenu *viewMenu; + QMenu *imageChanMenu; + QMenu *imageZoomMenu; + QMenu *overlayMenu; + QMenu *toolsMenu; + QMenu *optionsMenu; + QMenu *scanSegMenu; + QMenu *helpMenu; + + // File menu + QAction *newAct; + QAction *openAct; + QAction *saveLogAct; + QAction *reprocessAct; + QAction *batchProcessAct; + QAction *OffsetAct; + QAction *printAct; + QAction *printPreviewAct; + QAction *printSetupAct; + QAction *recentFileAct; + QAction *exitAct; + + // Edit menu + QAction *undoAct; + QAction *copyAct; + QAction *selectAllAct; + QAction *findAct; + QAction *findNextAct; + + // View menu + QAction *adjustAct; + QAction *toolbarAct; + QAction *statusBarAct; + + // Image Chan menu + QAction *rgbAct; + QAction *yccAct; + QAction *rAct; + QAction *gAct; + QAction *bAct; + QAction *yAct; + QAction *cbAct; + QAction *crAct; + QActionGroup *channelGroup; + + // Image Zoom menu + QAction *zoomInAct; + QAction *zoomOutAct; + QAction *zoom12_5Act; + QAction *zoom25Act; + QAction *zoom50Act; + QAction *zoom100Act; + QAction *zoom150Act; + QAction *zoom200Act; + QAction *zoom300Act; + QAction *zoom400Act; + QAction *zoom500Act; + QActionGroup *zoomGroup; + + // Overlay menu + QAction *mcuGridAct; + + // Tools menu + QAction *imgSearchFwdAct; + QAction *imgSearchRevAct; + QAction *lookupMcuOffAct; + QAction *fileOverlayAct; + QAction *searchDqtAct; + QAction *exportJpegAct; + QAction *exportTiffAct; + QAction *addToDbAct; + QAction *manageLocalDbAct; + + // Options menu + QAction *dhtExpandAct; + QAction *hideUnknownTagsAct; + QAction *makerNotesAct; + QAction *sigSearchAct; + QAction *relaxedParseAct; + QAction *configAct; + QAction *checkUpdatesAct; + + // Scan Segment menu + QAction *decodeImageAct; + QAction *fullIdtcAct; + QAction *noIdtcAct; + QAction *histogramRgbAct; + QAction *histogramYAct; + QAction *dumpAct; + QAction *detailedDecodeAct; + QActionGroup *idtGroup; + + // Help menu + QAction *aboutAct; + + QStatusBar *m_StatusBar; + + QMessageBox msgBox; + + QString m_currentFile; + + // Input JPEG file + QFile *m_pFile; + qint64 m_lFileSize; + + bool m_bFileAnalyzed; // Have we opened and analyzed a file? + bool m_bFileOpened; // Is a file currently opened? + +}; + +#endif // MAINWINDOW_H diff --git a/source/q_decodedetaildlg.cpp b/source/q_decodedetaildlg.cpp new file mode 100644 index 0000000..8ae9e32 --- /dev/null +++ b/source/q_decodedetaildlg.cpp @@ -0,0 +1,28 @@ +#include "q_decodedetaildlg.h" +#include "ui_q_decodedetaildlg.h" + +Q_DecodeDetailDlg::Q_DecodeDetailDlg(QWidget *parent) : + QDialog(parent), ui(new Ui::Q_DecodeDetailDlg), m_nMcuX(0), m_nMcuY(0), m_nMcuLen(0), m_bEn(false) +{ + ui->setupUi(this); + + connect(this, SIGNAL(accepted()), this, SLOT(accept())); + connect(this, SIGNAL(rejected()), this, SLOT(reject())); + + ui->leMcuX->setText("1"); +} + +Q_DecodeDetailDlg::~Q_DecodeDetailDlg() +{ + delete ui; +} + +void Q_DecodeDetailDlg::accept() +{ + +} + +void Q_DecodeDetailDlg::reject() +{ + return; +} diff --git a/source/q_decodedetaildlg.h b/source/q_decodedetaildlg.h new file mode 100644 index 0000000..f36922b --- /dev/null +++ b/source/q_decodedetaildlg.h @@ -0,0 +1,36 @@ +#ifndef Q_DECODEDETAILDLG_H +#define Q_DECODEDETAILDLG_H + +#include + +namespace Ui { +class Q_DecodeDetailDlg; +} + +class Q_DecodeDetailDlg : public QDialog +{ + Q_OBJECT + +public: + explicit Q_DecodeDetailDlg(QWidget *parent = 0); + ~Q_DecodeDetailDlg(); + +private slots: + void accept(); + void reject(); + +private: + Ui::Q_DecodeDetailDlg *ui; + + uint32_t m_nMcuX; + uint32_t m_nMcuY; + uint32_t m_nMcuLen; + bool m_bEn; + + uint32_t m_nLoadMcuX; + uint32_t m_nLoadMcuY; + uint32_t m_nLoadMcuLen; + +}; + +#endif // Q_DECODEDETAILDLG_H diff --git a/source/q_decodedetaildlg.ui b/source/q_decodedetaildlg.ui new file mode 100644 index 0000000..c196b82 --- /dev/null +++ b/source/q_decodedetaildlg.ui @@ -0,0 +1,315 @@ + + + Q_DecodeDetailDlg + + + + 0 + 0 + 462 + 212 + + + + Detailed Scan Decode Options + + + true + + + + + 370 + 10 + 81 + 61 + + + + Qt::Vertical + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 10 + 10 + 301 + 61 + + + + QGroupBox { + border: 1px solid gray; + border-radius: 9px; + margin-top: 0.5em; +} + +QGroupBox::title { + subcontrol-origin: margin; + left: 10px; + padding: 0 3px 0 3px; +} + + + Starting MCU for Decode + + + true + + + + + 10 + 30 + 270 + 23 + + + + + + + + 0 + 0 + + + + MCU X = + + + leMcuX + + + + + + + + 61 + 0 + + + + + 30 + 21 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + MCU Y = + + + leMcuY + + + + + + + + 61 + 0 + + + + + 61 + 21 + + + + + + + + + + + 10 + 80 + 301 + 61 + + + + QGroupBox { + border: 1px solid gray; + border-radius: 9px; + margin-top: 0.5em; +} + +QGroupBox::title { + subcontrol-origin: margin; + left: 10px; + padding: 0 3px 0 3px; +} + + + Length of Decode + + + true + + + + + 10 + 30 + 132 + 23 + + + + + + + # MCUs = + + + leNumMcus + + + + + + + + 0 + 0 + + + + + 61 + 0 + + + + + 31 + 16777215 + + + + + + + + + + + 10 + 150 + 211 + 20 + + + + Enable detailed Scan Decode? + + + + + + 10 + 180 + 421 + 16 + + + + Detailed Scan Decode will be reported in the next decode operation + + + + + + 329 + 90 + 120 + 81 + + + + + + + Load X/Y/Len +from last 2 clicks: + + + + + + + Load Coords + + + + + + + + + + buttonBox + accepted() + Q_DecodeDetailDlg + accept() + + + 370 + 70 + + + 157 + 211 + + + + + buttonBox + rejected() + Q_DecodeDetailDlg + reject() + + + 396 + 70 + + + 286 + 211 + + + + + diff --git a/source/resource.h b/source/resource.h index 98a0fd9..9dfa5f9 100644 --- a/source/resource.h +++ b/source/resource.h @@ -1,204 +1,204 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by JPEGsnoop.rc -// -#define IDS_CAL_EXE_OPEN 1 -#define IDR_CNTR_INPLACE 6 -#define IDD_ABOUTBOX 100 -#define IDP_OLE_INIT_FAILED 100 -#define IDP_FAILED_TO_CREATE 102 -#define IDD_SETTINGSDLG 103 -#define IDD_TERMSDLG 104 -#define IDD_UPDATEAVAILDLG 105 -#define IDD_MODELESSDLG 106 -#define IDD_NOTEDLG 107 -#define IDD_DBMANAGEDLG 109 -#define IDD_EXPORTDLG 112 -#define IDD_DECODEDETAILDLG 113 -#define IDD_EXPORTTIFFDLG 116 -#define IDD_BATCHDLG 117 -#define IDR_MAINFRAME 128 -#define IDR_JPEGsnoopTYPE 129 -#define IDR_MAINFRAME_BAK 129 -#define IDD_DBSUBMITDLG 130 -#define IDR_TEST1TYPE 130 -#define IDD_OVERLAYBUFDLG 131 -#define IDR_TEST2TYPE 131 -#define IDD_LOOKUP 132 -#define IDR_MAINFRAME2 132 -#define IDD_OFFSETDLG 133 -#define IDR_MAINFRAME3 133 -#define IDR_MAINFRAME_AVI 134 -#define IDR_MAINFRAME_ALL 135 -#define ID_INDICATOR_YCC 136 -#define IDS_CAL_FILEOPEN 137 -#define IDS_CAL_FILESAVE 138 -#define ID_INDICATOR_MCU 139 -#define ID_INDICATOR_FILEPOS 140 -#define IDD_OPERATIONDLG 145 -#define IDC_DB_DIR 1000 -#define IDC_URL 1001 -#define IDC_DB_DIR_BROWSE 1001 -#define IDC_URL_DOC 1002 -#define IDC_UPDATE_CHK 1002 -#define IDC_VER_NUM 1003 -#define IDC_DB_DIR_DEFAULT 1003 -#define IDC_EULA 1004 -#define IDC_EULA_OK 1005 -#define IDC_UPDATE_AUTO 1006 -#define IDC_BASEH 1007 -#define IDC_BUTTON1 1007 -#define IDC_BASED 1008 -#define IDC_VER_CUR 1008 -#define IDC_OFFSETVAL 1009 -#define IDC_VER_LATEST 1009 -#define IDC_X 1010 -#define IDC_UPDATE_AUTO_STILL 1010 -#define IDC_Y 1011 -#define IDC_OFFSET 1012 -#define IDC_DATE_LATEST 1012 -#define IDC_BTN_CALC 1013 -#define IDC_COACH_OFF 1013 -#define IDC_RNGX 1014 -#define IDC_MSG 1014 -#define IDC_RNGY 1015 -#define IDC_COACH_RESET 1015 -#define IDC_REPROCESS_AUTO 1016 -#define IDC_UPDATE_CHK_DAYS 1017 -#define IDC_OVRPOS 1018 -#define IDC_OVRNEW 1019 -#define IDC_OVRCUR 1020 -#define IDC_LIST 1020 -#define IDC_OVR_LOAD 1021 -#define IDC_REMOVEALL 1022 -#define IDC_OVRCURBIN 1022 -#define IDC_OVRLEN 1023 -#define IDC_REMOVE 1023 -#define IDC_OVREN 1024 -#define IDC_QUAL 1025 -#define IDC_DBSUBMIT_NET 1025 -#define IDC_MAKE 1026 -#define IDC_MODEL 1027 -#define IDC_SIG 1028 -#define IDC_RPTERRMAX_SCANDECODE 1028 -#define IDC_SOFTWARE 1029 -#define IDC_APPLY 1029 -#define IDC_RADIO_CAM 1031 -#define IDC_RADIO_SW 1032 -#define IDC_USER_SOFTWARE 1033 -#define IDC_RADIO_UNKNOWN 1035 -#define IDC_NOTES 1036 -#define IDC_OVERLAY 1052 -#define IDC_DHTAVI 1053 -#define IDC_OFFSET_START 1054 -#define IDC_EDIT1 1071 -#define IDC_EDIT2 1072 -#define IDC_EDIT3 1073 -#define IDC_CHECK1 1074 -#define IDC_FORCE_EOI 1077 -#define IDC_FORCE_SOI 1078 -#define IDC_IGNORE_EOI 1081 -#define IDC_BTN_LOAD 1109 -#define IDC_EDIT_FNAME 1112 -#define IDC_RAD_RGB16 1113 -#define IDC_RAD_YCC8 1114 -#define IDC_RAD_RGB8 1115 -#define IDC_CHECK_SUBDIRS 1117 -#define IDC_EDIT_DIR 1118 -#define ID_BTN_ABORT 1119 -#define IDC_PROGRESS_BAR 1120 -#define IDC_STATIC_PROGRESS 1121 -#define IDC_EXT_ALL 1122 -#define IDC_CHECK_EXT_ALL 1123 -#define IDC_BTN_DIR_SRC_BROWSE 1126 -#define IDC_BTN_DIR_DST_BROWSE 1127 -#define IDC_EDIT_DIR_SRC 1128 -#define IDC_EDIT_DIR_DST 1129 -#define ID_CANCEL_EDIT_CNTR 32768 -#define ID_TOOLS_DECODE 32771 -#define ID_FILE_OFFSET 32772 -#define ID_TOOLS_SEARCHFORWARD 32773 -#define ID_TOOLS_SEARCHREVERSE 32774 -#define ID_TOOLS_LOOKUPMCUOFFSET 32775 -#define ID_TOOLS_FILEOVERLAY 32776 -#define ID_TOOLS_DECODESCANRANGE 32777 -#define ID_TOOLS_ADDCAMERATODB 32778 -#define ID_TOOLS_RESETLOCALDB 32779 -#define ID_OPTIONS_DHTEXPAND 32780 -#define ID_OPTIONS_MAKERNOTES 32781 -#define ID_OPTIONS_SCANDUMP 32782 -#define ID_OPTIONS_SCANPARSE 32783 -#define ID_OPTIONS_HISTOYDUMP 32784 -#define ID_FILE_REPROCESS 32788 -#define ID_FILE_OPENIMAGE 32789 -#define ID_FILE_SAVELOG 32790 -#define ID_OPTIONS_DECODESCAN 32795 -#define ID_OPTIONS_CONFIGURATION 32796 -#define ID_OPTIONS_CHECKFORUPDATES 32799 -#define ID_PREVIEW_RGB 32800 -#define ID_PREVIEW_YCC 32801 -#define ID_PREVIEW_R 32802 -#define ID_PREVIEW_G 32803 -#define ID_PREVIEW_B 32804 -#define ID_PREVIEW_Y 32805 -#define ID_PREVIEW_CB 32806 -#define ID_PREVIEW_CR 32807 -#define ID_PREVIEWZOOM_ZOOMIN 32808 -#define ID_PREVIEWZOOM_ZOOMOUT 32809 -#define ID_PREVIEWZOOM_100 32810 -#define ID_PREVIEWZOOM_150 32811 -#define ID_PREVIEWZOOM_200 32812 -#define ID_PREVIEWZOOM_300 32813 -#define ID_PREVIEWZOOM_400 32814 -#define ID_PREVIEWZOOM_800 32815 -#define ID_TOOLS_SEARCHEXECUTABLEFORDQT 32819 -#define ID_TOOLS_MANAGELOCALDB 32820 -#define ID_OPTIONS_SIGNATURESEARCH 32821 -#define ID_TOOLS_EXTRACTEMBEDDEDJPEG 32822 -#define ID_OPTIONS_DECODEAC 32824 -#define ID_OPTIONS_SCANSEGMENT 32825 -#define ID_SCANSEGMENT_DECODEIMAGE 32826 -#define ID_SCANSEGMENT_FULLIDCT 32827 -#define ID_SCANSEGMENT_HISTOGRAMY 32828 -#define ID_SCANSEGMENT_SCANDUMP 32829 -#define ID_SCANSEGMENT_DUMP 32830 -#define ID_Menu 32831 -#define ID_VIEW_ZOOM 32832 -#define ID_VIEW_IMAGEZOOM 32833 -#define ID_IMAGEZOOM_ZOOMIN 32834 -#define ID_IMAGEZOOM_ZOOMOUT 32835 -#define ID_IMAGEZOOM_12 32836 -#define ID_IMAGEZOOM_25 32837 -#define ID_IMAGEZOOM_50 32838 -#define ID_IMAGEZOOM_100 32839 -#define ID_IMAGEZOOM_150 32840 -#define ID_IMAGEZOOM_200 32841 -#define ID_IMAGEZOOM_300 32842 -#define ID_IMAGEZOOM_400 32843 -#define ID_IMAGEZOOM_800 32844 -#define ID_SCANSEGMENT_NOIDCT 32849 -#define ID_TOOLS_LOOKUPMCUOFFSET32850 32850 -#define ID_TOOLS_FILEOVERLAY32851 32851 -#define ID_VIEW_OVERLAYS 32854 -#define ID_OVERLAYS_MCUGRID 32855 -#define ID_DEV_DELMCU2 32858 -#define ID_VIEW_ADJUST 32859 -#define ID_TOOLS_EXPORTMODIFIEDJPEG 32860 -#define ID_TOOLS_DETAILEDSCANDECODE 32870 -#define ID_SCANSEGMENT_DETAILEDDECODE 32871 -#define ID_SCANSEGMENT_HISTOGRAM 32872 -#define ID_OPTIONS_HIDEUKNOWNEXIFTAGS 32883 -#define ID_TOOLS_EXPORTTIFF 32884 -#define ID_FILE_BATCHPROCESS 32885 -#define ID_OPTIONS_RELAXEDPARSING 32886 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 147 -#define _APS_NEXT_COMMAND_VALUE 32887 -#define _APS_NEXT_CONTROL_VALUE 1130 -#define _APS_NEXT_SYMED_VALUE 118 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by JPEGsnoop.rc +// +#define IDS_CAL_EXE_OPEN 1 +#define IDR_CNTR_INPLACE 6 +#define IDD_ABOUTBOX 100 +#define IDP_OLE_INIT_FAILED 100 +#define IDP_FAILED_TO_CREATE 102 +#define IDD_SETTINGSDLG 103 +#define IDD_TERMSDLG 104 +#define IDD_UPDATEAVAILDLG 105 +#define IDD_MODELESSDLG 106 +#define IDD_NOTEDLG 107 +#define IDD_DBMANAGEDLG 109 +#define IDD_EXPORTDLG 112 +#define IDD_DECODEDETAILDLG 113 +#define IDD_EXPORTTIFFDLG 116 +#define IDD_BATCHDLG 117 +#define IDR_MAINFRAME 128 +#define IDR_JPEGsnoopTYPE 129 +#define IDR_MAINFRAME_BAK 129 +#define IDD_DBSUBMITDLG 130 +#define IDR_TEST1TYPE 130 +#define IDD_OVERLAYBUFDLG 131 +#define IDR_TEST2TYPE 131 +#define IDD_LOOKUP 132 +#define IDR_MAINFRAME2 132 +#define IDD_OFFSETDLG 133 +#define IDR_MAINFRAME3 133 +#define IDR_MAINFRAME_AVI 134 +#define IDR_MAINFRAME_ALL 135 +#define ID_INDICATOR_YCC 136 +#define IDS_CAL_FILEOPEN 137 +#define IDS_CAL_FILESAVE 138 +#define ID_INDICATOR_MCU 139 +#define ID_INDICATOR_FILEPOS 140 +#define IDD_OPERATIONDLG 145 +#define IDC_DB_DIR 1000 +#define IDC_URL 1001 +#define IDC_DB_DIR_BROWSE 1001 +#define IDC_URL_DOC 1002 +#define IDC_UPDATE_CHK 1002 +#define IDC_VER_NUM 1003 +#define IDC_DB_DIR_DEFAULT 1003 +#define IDC_EULA 1004 +#define IDC_EULA_OK 1005 +#define IDC_UPDATE_AUTO 1006 +#define IDC_BASEH 1007 +#define IDC_BUTTON1 1007 +#define IDC_BASED 1008 +#define IDC_VER_CUR 1008 +#define IDC_OFFSETVAL 1009 +#define IDC_VER_LATEST 1009 +#define IDC_X 1010 +#define IDC_UPDATE_AUTO_STILL 1010 +#define IDC_Y 1011 +#define IDC_OFFSET 1012 +#define IDC_DATE_LATEST 1012 +#define IDC_BTN_CALC 1013 +#define IDC_COACH_OFF 1013 +#define IDC_RNGX 1014 +#define IDC_MSG 1014 +#define IDC_RNGY 1015 +#define IDC_COACH_RESET 1015 +#define IDC_REPROCESS_AUTO 1016 +#define IDC_UPDATE_CHK_DAYS 1017 +#define IDC_OVRPOS 1018 +#define IDC_OVRNEW 1019 +#define IDC_OVRCUR 1020 +#define IDC_LIST 1020 +#define IDC_OVR_LOAD 1021 +#define IDC_REMOVEALL 1022 +#define IDC_OVRCURBIN 1022 +#define IDC_OVRLEN 1023 +#define IDC_REMOVE 1023 +#define IDC_OVREN 1024 +#define IDC_QUAL 1025 +#define IDC_DBSUBMIT_NET 1025 +#define IDC_MAKE 1026 +#define IDC_MODEL 1027 +#define IDC_SIG 1028 +#define IDC_RPTERRMAX_SCANDECODE 1028 +#define IDC_SOFTWARE 1029 +#define IDC_APPLY 1029 +#define IDC_RADIO_CAM 1031 +#define IDC_RADIO_SW 1032 +#define IDC_USER_SOFTWARE 1033 +#define IDC_RADIO_UNKNOWN 1035 +#define IDC_NOTES 1036 +#define IDC_OVERLAY 1052 +#define IDC_DHTAVI 1053 +#define IDC_OFFSET_START 1054 +#define IDC_EDIT1 1071 +#define IDC_EDIT2 1072 +#define IDC_EDIT3 1073 +#define IDC_CHECK1 1074 +#define IDC_FORCE_EOI 1077 +#define IDC_FORCE_SOI 1078 +#define IDC_IGNORE_EOI 1081 +#define IDC_BTN_LOAD 1109 +#define IDC_EDIT_FNAME 1112 +#define IDC_RAD_RGB16 1113 +#define IDC_RAD_YCC8 1114 +#define IDC_RAD_RGB8 1115 +#define IDC_CHECK_SUBDIRS 1117 +#define IDC_EDIT_DIR 1118 +#define ID_BTN_ABORT 1119 +#define IDC_PROGRESS_BAR 1120 +#define IDC_STATIC_PROGRESS 1121 +#define IDC_EXT_ALL 1122 +#define IDC_CHECK_EXT_ALL 1123 +#define IDC_BTN_DIR_SRC_BROWSE 1126 +#define IDC_BTN_DIR_DST_BROWSE 1127 +#define IDC_EDIT_DIR_SRC 1128 +#define IDC_EDIT_DIR_DST 1129 +#define ID_CANCEL_EDIT_CNTR 32768 +#define ID_TOOLS_DECODE 32771 +#define ID_FILE_OFFSET 32772 +#define ID_TOOLS_SEARCHFORWARD 32773 +#define ID_TOOLS_SEARCHREVERSE 32774 +#define ID_TOOLS_LOOKUPMCUOFFSET 32775 +#define ID_TOOLS_FILEOVERLAY 32776 +#define ID_TOOLS_DECODESCANRANGE 32777 +#define ID_TOOLS_ADDCAMERATODB 32778 +#define ID_TOOLS_RESETLOCALDB 32779 +#define ID_OPTIONS_DHTEXPAND 32780 +#define ID_OPTIONS_MAKERNOTES 32781 +#define ID_OPTIONS_SCANDUMP 32782 +#define ID_OPTIONS_SCANPARSE 32783 +#define ID_OPTIONS_HISTOYDUMP 32784 +#define ID_FILE_REPROCESS 32788 +#define ID_FILE_OPENIMAGE 32789 +#define ID_FILE_SAVELOG 32790 +#define ID_OPTIONS_DECODESCAN 32795 +#define ID_OPTIONS_CONFIGURATION 32796 +#define ID_OPTIONS_CHECKFORUPDATES 32799 +#define ID_PREVIEW_RGB 32800 +#define ID_PREVIEW_YCC 32801 +#define ID_PREVIEW_R 32802 +#define ID_PREVIEW_G 32803 +#define ID_PREVIEW_B 32804 +#define ID_PREVIEW_Y 32805 +#define ID_PREVIEW_CB 32806 +#define ID_PREVIEW_CR 32807 +#define ID_PREVIEWZOOM_ZOOMIN 32808 +#define ID_PREVIEWZOOM_ZOOMOUT 32809 +#define ID_PREVIEWZOOM_100 32810 +#define ID_PREVIEWZOOM_150 32811 +#define ID_PREVIEWZOOM_200 32812 +#define ID_PREVIEWZOOM_300 32813 +#define ID_PREVIEWZOOM_400 32814 +#define ID_PREVIEWZOOM_800 32815 +#define ID_TOOLS_SEARCHEXECUTABLEFORDQT 32819 +#define ID_TOOLS_MANAGELOCALDB 32820 +#define ID_OPTIONS_SIGNATURESEARCH 32821 +#define ID_TOOLS_EXTRACTEMBEDDEDJPEG 32822 +#define ID_OPTIONS_DECODEAC 32824 +#define ID_OPTIONS_SCANSEGMENT 32825 +#define ID_SCANSEGMENT_DECODEIMAGE 32826 +#define ID_SCANSEGMENT_FULLIDCT 32827 +#define ID_SCANSEGMENT_HISTOGRAMY 32828 +#define ID_SCANSEGMENT_SCANDUMP 32829 +#define ID_SCANSEGMENT_DUMP 32830 +#define ID_Menu 32831 +#define ID_VIEW_ZOOM 32832 +#define ID_VIEW_IMAGEZOOM 32833 +#define ID_IMAGEZOOM_ZOOMIN 32834 +#define ID_IMAGEZOOM_ZOOMOUT 32835 +#define ID_IMAGEZOOM_12 32836 +#define ID_IMAGEZOOM_25 32837 +#define ID_IMAGEZOOM_50 32838 +#define ID_IMAGEZOOM_100 32839 +#define ID_IMAGEZOOM_150 32840 +#define ID_IMAGEZOOM_200 32841 +#define ID_IMAGEZOOM_300 32842 +#define ID_IMAGEZOOM_400 32843 +#define ID_IMAGEZOOM_800 32844 +#define ID_SCANSEGMENT_NOIDCT 32849 +#define ID_TOOLS_LOOKUPMCUOFFSET32850 32850 +#define ID_TOOLS_FILEOVERLAY32851 32851 +#define ID_VIEW_OVERLAYS 32854 +#define ID_OVERLAYS_MCUGRID 32855 +#define ID_DEV_DELMCU2 32858 +#define ID_VIEW_ADJUST 32859 +#define ID_TOOLS_EXPORTMODIFIEDJPEG 32860 +#define ID_TOOLS_DETAILEDSCANDECODE 32870 +#define ID_SCANSEGMENT_DETAILEDDECODE 32871 +#define ID_SCANSEGMENT_HISTOGRAM 32872 +#define ID_OPTIONS_HIDEUKNOWNEXIFTAGS 32883 +#define ID_TOOLS_EXPORTTIFF 32884 +#define ID_FILE_BATCHPROCESS 32885 +#define ID_OPTIONS_RELAXEDPARSING 32886 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 147 +#define _APS_NEXT_COMMAND_VALUE 32887 +#define _APS_NEXT_CONTROL_VALUE 1130 +#define _APS_NEXT_SYMED_VALUE 118 +#endif +#endif diff --git a/source/snoop.h b/source/snoop.h index 6e16b78..133fc49 100644 --- a/source/snoop.h +++ b/source/snoop.h @@ -1,177 +1,186 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - JPEGsnoop global definitions -// -// ========================================================================== - - -#pragma once - - -// Program Version / Release Number -// - Format: "X.Y.Z" - (full public release) -// - Format: "X.Y.Z (beta W)" - (beta release) -// - Note that when the version number is incremented, I need -// to also update the corresponding version numbers in the -// JPEGsnoop.rc resource under "Version.VS_VERSION_INFO". -#define VERSION_STR _T("1.8.0") - -// Version number for the database signatures -// - This version number has been provided in case I decide -// to change the database format. If a change to the format is -// required, then I can use this version number to help build a -// converter/import routine. -#define DB_SIG_VER 0x01 - -// Enable debug log? -//#define DEBUG_LOG_OUT -#define DEBUG_EN 0 - -//#define DEBUG_YCCK - -// Disable code that isn't fully implemented yet -//#define TODO - -// Enable Photoshop image/layer rendering -// TODO: Not fully implemented yet -#define PS_IMG_DEC_EN - -// User Local Database filename -#define DAT_FILE _T("JPEGsnoop_db.dat") - -// In QUICKLOG mode, we support batching up of writes to the -// RichEdit window, which greatly speeds up the output -// TODO: Might also use this for command-line nogui mode -#define QUICKLOG - -// Define the type of Internet support -// - WINHTTP is only supported in newer OS versions -#define WWW_WININET -//#define WWW_WINHTTP - -// The following DEFINEs are used in debugging and local batch operations -//#define DEBUG_SIG // Print debugging info for signature generation -//#define BATCH_DO_DBSUBMIT -//#define BATCH_DO_DBSUBMIT_ALL - - -// Internet access parameters -// - If the user has enabled sharing of the signature data with the online -// repository, then the following host and URLs are used. -// - The URLs that are used to indicate new release availability are also -// provided here. These pages have specific formatting that JPEGsnoop -// parses to identify if a newer version is available. -#define IA_HOST _T("www.impulseadventure.com") -#define IA_DB_SUBMIT_PAGE _T("/photo/jpeg-snoop-submit.php") -#define IA_UPDATES_CHK_PAGE _T("/photo/jpeg-snoop.html") -#define IA_UPDATES_DL_PAGE _T("http://www.impulseadventure.com/photo/jpeg-snoop.html#download") - -// Registry settings -#define REG_KEY_PATH _T("Software\\ImpulseAdventure\\JPEGsnoop\\") -#define REG_COMPANY_NAME _T("ImpulseAdventure") -#define REG_SW_NAME _T("JPEGsnoop") - -// Extra logging for debugging -#define DEBUG_LOG - -// For errors (eg. in exceptions), define message buffer length -#define MAX_BUF_EX_ERR_MSG 512 - -// Preview Modes -enum tePreviewMode { - PREVIEW_NONE=0, // Preview not calculated yet - PREVIEW_RGB, - PREVIEW_YCC, - PREVIEW_R, - PREVIEW_G, - PREVIEW_B, - PREVIEW_Y, - PREVIEW_CB, - PREVIEW_CR, -}; - -enum tePreviewZoom { - PRV_ZOOMBEGIN=0, - PRV_ZOOM_12, - PRV_ZOOM_25, - PRV_ZOOM_50, - PRV_ZOOM_100, - PRV_ZOOM_150, - PRV_ZOOM_200, - PRV_ZOOM_300, - PRV_ZOOM_400, - PRV_ZOOM_800, - PRV_ZOOMEND, -}; - -// DB Signature modes -enum teSource { - ENUM_SOURCE_UNSET=0, - ENUM_SOURCE_CAM, - ENUM_SOURCE_SW, - ENUM_SOURCE_UNSURE, -}; - -enum teMaker { - ENUM_MAKER_UNSET=0, - ENUM_MAKER_PRESENT, - ENUM_MAKER_NONE, -}; - -enum teEdited { - EDITED_UNSET=0, - EDITED_YES, - EDITED_NO, - EDITED_UNSURE, - EDITED_YESPROB, // Probably edited -}; - -enum teDbAdd { - DB_ADD_SUGGEST_UNSET=0, - DB_ADD_SUGGEST_CAM, - DB_ADD_SUGGEST_SW, -}; - -enum teEditor { - ENUM_EDITOR_UNSET=0, - ENUM_EDITOR_CAM, - ENUM_EDITOR_SW, - ENUM_EDITOR_UNSURE, -}; - -enum teLandscape { - ENUM_LANDSCAPE_UNSET=0, - ENUM_LANDSCAPE_YES, - ENUM_LANDSCAPE_NO, -}; - -enum teOffsetMode {DEC_OFFSET_START,DEC_OFFSET_SRCH1,DEC_OFFSET_SRCH2,DEC_OFFSET_POS}; - -// Define a few coach messages - -#define COACH_REPROCESS_AUTO _T("You have changed a processing option. To see these changes, ")\ - _T("you need to Reprocess the file or enable [Auto Reprocessing] in Configuration.") - -#define COACH_DECODE_IDCT_DC _T("Currently only decoding low-res view (DC-only). Full-resolution image decode ")\ - _T("can be enabled in [Options->Scan Segment->Full IDCT], but it is slower.") -#define COACH_DECODE_IDCT_AC _T("Currently decoding high-res view (AC+DC), which can be slow. For faster ")\ - _T("operation, low-resolution image decode can be enabled in [Options->Scan Segment->No IDCT].") - +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ========================================================================== +// CLASS DESCRIPTION: +// - JPEGsnoop global definitions +// +// ========================================================================== + +#pragma once + +// Program Version / Release Number +// - Format: "X.Y.Z" - (full public release) +// - Format: "X.Y.Z (beta W)" - (beta release) +// - Note that when the version number is incremented, I need +// to also update the corresponding version numbers in the +// JPEGsnoop.rc resource under "Version.VS_VERSION_INFO". +#define VERSION_STR "2.0.0 (alpha)" + +// Version number for the database signatures +// - This version number has been provided in case I decide +// to change the database format. If a change to the format is +// required, then I can use this version number to help build a +// converter/import routine. +#define DB_SIG_VER 0x01 + +// Enable debug log? +//#define DEBUG_LOG_OUT +#define DEBUG_EN 1 + +//#define DEBUG_YCCK + +// Disable code that isn't fully implemented yet +//#define TODO + +// Enable Photoshop image/layer rendering +// TODO: Not fully implemented yet +#define PS_IMG_DEC_EN + +// User Local Database filename +#define DAT_FILE "JPEGsnoop_db.dat" + +// In QUICKLOG mode, we support batching up of writes to the +// RichEdit window, which greatly speeds up the output +// TODO: Might also use this for command-line nogui mode +#define QUICKLOG + +// Define the type of Internet support +// - WINHTTP is only supported in newer OS versions +#define WWW_WININET +//#define WWW_WINHTTP + +// The following DEFINEs are used in debugging and local batch operations +//#define DEBUG_SIG // Print debugging info for signature generation +//#define BATCH_DO_DBSUBMIT +//#define BATCH_DO_DBSUBMIT_ALL + +// Internet access parameters +// - If the user has enabled sharing of the signature data with the online +// repository, then the following host and URLs are used. +// - The URLs that are used to indicate new release availability are also +// provided here. These pages have specific formatting that JPEGsnoop +// parses to identify if a newer version is available. +#define IA_HOST "www.impulseadventure.com" +#define IA_DB_SUBMIT_PAGE "/photo/jpeg-snoop-submit.php" +#define IA_UPDATES_CHK_PAGE "/photo/jpeg-snoop.html" +#define IA_UPDATES_DL_PAGE "http://www.impulseadventure.com/photo/jpeg-snoop.html#download" + +// Registry settings +#define REG_KEY_PATH "Software\\ImpulseAdventure\\JPEGsnoop\\" +#define REG_COMPANY_NAME "ImpulseAdventure" +#define REG_SW_NAME "JPEGsnoop" + +// Extra logging for debugging +#define DEBUG_LOG + +// For errors (eg. in exceptions), define message buffer length +#define MAX_BUF_EX_ERR_MSG 512 + +// Preview Modes +enum tePreviewMode +{ + PREVIEW_NONE = 0, // Preview not calculated yet + PREVIEW_RGB, + PREVIEW_YCC, + PREVIEW_R, + PREVIEW_G, + PREVIEW_B, + PREVIEW_Y, + PREVIEW_CB, + PREVIEW_CR, +}; + +enum tePreviewZoom +{ + PRV_ZOOMBEGIN = 0, + PRV_ZOOM_12, + PRV_ZOOM_25, + PRV_ZOOM_50, + PRV_ZOOM_100, + PRV_ZOOM_150, + PRV_ZOOM_200, + PRV_ZOOM_300, + PRV_ZOOM_400, + PRV_ZOOM_800, + PRV_ZOOMEND, +}; + +// DB Signature modes +enum teSource +{ + ENUM_SOURCE_UNSET = 0, + ENUM_SOURCE_CAM, + ENUM_SOURCE_SW, + ENUM_SOURCE_UNSURE, +}; + +enum teMaker +{ + ENUM_MAKER_UNSET = 0, + ENUM_MAKER_PRESENT, + ENUM_MAKER_NONE, +}; + +enum teEdited +{ + EDITED_UNSET = 0, + EDITED_YES, + EDITED_NO, + EDITED_UNSURE, + EDITED_YESPROB, // Probably edited +}; + +enum teDbAdd +{ + DB_ADD_SUGGEST_UNSET = 0, + DB_ADD_SUGGEST_CAM, + DB_ADD_SUGGEST_SW, +}; + +enum teEditor +{ + ENUM_EDITOR_UNSET = 0, + ENUM_EDITOR_CAM, + ENUM_EDITOR_SW, + ENUM_EDITOR_UNSURE, +}; + +enum teLandscape +{ + ENUM_LANDSCAPE_UNSET = 0, + ENUM_LANDSCAPE_YES, + ENUM_LANDSCAPE_NO, +}; + +enum teOffsetMode +{ + DEC_OFFSET_START, + DEC_OFFSET_SRCH1, + DEC_OFFSET_SRCH2, + DEC_OFFSET_POS +}; + +// Define a few coach messages + +#define COACH_REPROCESS_AUTO "You have changed a processing option. To see these changes, "\ + "you need to Reprocess the file or enable [Auto Reprocessing] in Configuration." +#define COACH_DECODE_IDCT_DC "Currently only decoding low-res view (DC-only). Full-resolution image decode "\ + "can be enabled in [Options->Scan Segment->Full IDCT], but it is slower." +#define COACH_DECODE_IDCT_AC _T("Currently decoding high-res view (AC+DC), which can be slow. For faster "\ + "operation, low-resolution image decode can be enabled in [Options->Scan Segment->No IDCT]." diff --git a/source/snoopconfigdialog.cpp b/source/snoopconfigdialog.cpp new file mode 100644 index 0000000..da4c4b4 --- /dev/null +++ b/source/snoopconfigdialog.cpp @@ -0,0 +1,62 @@ +#include "JPEGsnoop.h" + +#include "snoopconfigdialog.h" +#include "ui_snoopconfigdialog.h" + +SnoopConfigDialog::SnoopConfigDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::SnoopConfigDialog) +{ + ui->setupUi(this); + connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(onSave())); + connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(onCancel())); + + connect(ui->btnBrowse, SIGNAL(released()), this, SLOT(onBrowse())); + connect(ui->btnDefault, SIGNAL(released()), this, SLOT(onDefault())); + connect(ui->btnDefault, SIGNAL(released()), this, SLOT(onReset())); + + dbPath = m_pAppConfig->dbPath(); + ui->leDbPath->setText(dbPath); + + bAutoUpdate = m_pAppConfig->swUpdateEnabled(); + ui->cbAutoUpdate->setChecked(bAutoUpdate); + + autoUpdateDays = m_pAppConfig->autoUpdateDays(); + ui->leUpdateDays->setText(QString("%1").arg(autoUpdateDays)); + bAutoReprocess = m_pAppConfig->autoReprocess(); + ui->cbAutoReprocess->setChecked(bAutoReprocess); + bOnlineDb = m_pAppConfig->dbSubmitNet(); + ui->cbOblineDb->setChecked(bOnlineDb); + maxDecodeErrors = m_pAppConfig->maxDecodeError(); + ui->leMaxErrors->setText(QString("%1").arg(maxDecodeErrors)); +} + +SnoopConfigDialog::~SnoopConfigDialog() +{ + delete ui; +} + +void SnoopConfigDialog::onBrowse() +{ + +} + +void SnoopConfigDialog::onDefault() +{ + +} + +void SnoopConfigDialog::onReset() +{ + +} + +void SnoopConfigDialog::onSave() +{ + +} + +void SnoopConfigDialog::onCancel() +{ + close(); +} diff --git a/source/snoopconfigdialog.h b/source/snoopconfigdialog.h new file mode 100644 index 0000000..efc32cf --- /dev/null +++ b/source/snoopconfigdialog.h @@ -0,0 +1,41 @@ +#ifndef SNOOPCONFIGDIALOG_H +#define SNOOPCONFIGDIALOG_H + +#include + +namespace Ui { +class SnoopConfigDialog; +} + +class SnoopConfigDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SnoopConfigDialog(QWidget *parent = 0); + ~SnoopConfigDialog(); + +private slots: + void onBrowse(); + void onDefault(); + void onReset(); + void onSave(); + void onCancel(); + +private: + SnoopConfigDialog &operator = (const SnoopConfigDialog&); + SnoopConfigDialog(SnoopConfigDialog&); + + Ui::SnoopConfigDialog *ui; + + QString dbPath; + bool bAutoUpdate; + bool bAutoReprocess; + bool bOnlineDb; + + int32_t autoUpdateDays; + int32_t maxDecodeErrors; + +}; + +#endif // SNOOPCONFIGDIALOG_H diff --git a/source/snoopconfigdialog.ui b/source/snoopconfigdialog.ui new file mode 100644 index 0000000..ada1849 --- /dev/null +++ b/source/snoopconfigdialog.ui @@ -0,0 +1,409 @@ + + + SnoopConfigDialog + + + + 0 + 0 + 541 + 426 + + + + JPEGsnoop Confguration + + + true + + + + + 440 + 10 + 81 + 71 + + + + Qt::Vertical + + + QDialogButtonBox::Cancel|QDialogButtonBox::Save + + + + + + 20 + 10 + 402 + 406 + + + + + + + + 400 + 80 + + + + QGroupBox { + border: 1px solid gray; + border-radius: 9px; + margin-top: 0.5em; +} + +QGroupBox::title { + subcontrol-origin: margin; + left: 10px; + padding: 0 3px 0 3px; +} + + + Directory for User Database + + + true + + + + + 10 + 10 + 381 + 71 + + + + + + + + 320 + 20 + + + + + + + + + + Browse + + + + + + + Default + + + + + + + + + + + + + + 400 + 60 + + + + QGroupBox { + border: 1px solid gray; + border-radius: 9px; + margin-top: 0.5em; +} + +QGroupBox::title { + subcontrol-origin: margin; + left: 10px; + padding: 0 3px 0 3px; +} + + + Software Update + + + true + + + + + 10 + 20 + 381 + 31 + + + + + + + + 260 + 20 + + + + Automatically check for updates every + + + + + + + + 40 + 20 + + + + + + + + + 40 + 20 + + + + days + + + + + + + + + + + + 400 + 80 + + + + QGroupBox { + border: 1px solid gray; + border-radius: 9px; + margin-top: 0.5em; +} + +QGroupBox::title { + subcontrol-origin: margin; + left: 10px; + padding: 0 3px 0 3px; +} + + + Processing Options + + + true + + + + + 10 + 20 + 335 + 41 + + + + + + + Auto Reprocess files on change in Options (slower) + + + + + + + Submit signature to Online DB when User submit + + + + + + + + + + + + 400 + 60 + + + + + 16777215 + 60 + + + + QGroupBox { + border: 1px solid gray; + border-radius: 9px; + margin-top: 0.5em; +} + +QGroupBox::title { + subcontrol-origin: margin; + left: 10px; + padding: 0 3px 0 3px; +} + + + Report Settings + + + true + + + + + 10 + 20 + 325 + 31 + + + + + + + + 240 + 20 + + + + + 240 + 20 + + + + Max # errors to report in Scan Decode + + + + + + + + 40 + 20 + + + + + + + + + + + + + 400 + 60 + + + + + 16777215 + 60 + + + + QGroupBox { + border: 1px solid gray; + border-radius: 9px; + margin-top: 0.5em; +} + +QGroupBox::title { + subcontrol-origin: margin; + left: 10px; + padding: 0 3px 0 3px; +} + + + Help + + + true + + + + + 10 + 10 + 311 + 48 + + + + + 0 + + + + + + 230 + 20 + + + + Coach Messages can be re-enabled: + + + + + + + + 80 + 32 + + + + + 80 + 32 + + + + Reset + + + + + + + + + + + + + diff --git a/ui_q_decodedetaildlg.h b/ui_q_decodedetaildlg.h new file mode 100644 index 0000000..fe4a828 --- /dev/null +++ b/ui_q_decodedetaildlg.h @@ -0,0 +1,212 @@ +/******************************************************************************** +** Form generated from reading UI file 'q_decodedetaildlg.ui' +** +** Created by: Qt User Interface Compiler version 5.11.0 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_Q_DECODEDETAILDLG_H +#define UI_Q_DECODEDETAILDLG_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_Q_DecodeDetailDlg +{ +public: + QDialogButtonBox *buttonBox; + QGroupBox *groupBox; + QWidget *widget; + QHBoxLayout *horizontalLayout; + QLabel *label; + QLineEdit *leMcuX; + QSpacerItem *horizontalSpacer; + QLabel *label_2; + QLineEdit *leMcuY; + QGroupBox *groupBox_2; + QWidget *widget1; + QHBoxLayout *horizontalLayout_2; + QLabel *label_3; + QLineEdit *leNumMcus; + QCheckBox *cbEnableDec; + QLabel *label_4; + QWidget *widget2; + QVBoxLayout *verticalLayout; + QLabel *label_5; + QPushButton *pbLoadCoords; + + void setupUi(QDialog *Q_DecodeDetailDlg) + { + if (Q_DecodeDetailDlg->objectName().isEmpty()) + Q_DecodeDetailDlg->setObjectName(QStringLiteral("Q_DecodeDetailDlg")); + Q_DecodeDetailDlg->resize(462, 212); + Q_DecodeDetailDlg->setModal(true); + buttonBox = new QDialogButtonBox(Q_DecodeDetailDlg); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setGeometry(QRect(370, 10, 81, 61)); + buttonBox->setOrientation(Qt::Vertical); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + groupBox = new QGroupBox(Q_DecodeDetailDlg); + groupBox->setObjectName(QStringLiteral("groupBox")); + groupBox->setGeometry(QRect(10, 10, 301, 61)); + groupBox->setStyleSheet(QLatin1String("QGroupBox {\n" +" border: 1px solid gray;\n" +" border-radius: 9px;\n" +" margin-top: 0.5em;\n" +"}\n" +"\n" +"QGroupBox::title {\n" +" subcontrol-origin: margin;\n" +" left: 10px;\n" +" padding: 0 3px 0 3px;\n" +"}")); + groupBox->setFlat(true); + widget = new QWidget(groupBox); + widget->setObjectName(QStringLiteral("widget")); + widget->setGeometry(QRect(10, 30, 270, 23)); + horizontalLayout = new QHBoxLayout(widget); + horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + horizontalLayout->setContentsMargins(0, 0, 0, 0); + label = new QLabel(widget); + label->setObjectName(QStringLiteral("label")); + QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); + label->setSizePolicy(sizePolicy); + + horizontalLayout->addWidget(label); + + leMcuX = new QLineEdit(widget); + leMcuX->setObjectName(QStringLiteral("leMcuX")); + leMcuX->setMinimumSize(QSize(61, 0)); + leMcuX->setMaximumSize(QSize(30, 21)); + + horizontalLayout->addWidget(leMcuX); + + horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout->addItem(horizontalSpacer); + + label_2 = new QLabel(widget); + label_2->setObjectName(QStringLiteral("label_2")); + sizePolicy.setHeightForWidth(label_2->sizePolicy().hasHeightForWidth()); + label_2->setSizePolicy(sizePolicy); + + horizontalLayout->addWidget(label_2); + + leMcuY = new QLineEdit(widget); + leMcuY->setObjectName(QStringLiteral("leMcuY")); + leMcuY->setMinimumSize(QSize(61, 0)); + leMcuY->setMaximumSize(QSize(61, 21)); + + horizontalLayout->addWidget(leMcuY); + + groupBox_2 = new QGroupBox(Q_DecodeDetailDlg); + groupBox_2->setObjectName(QStringLiteral("groupBox_2")); + groupBox_2->setGeometry(QRect(10, 80, 301, 61)); + groupBox_2->setStyleSheet(QLatin1String("QGroupBox {\n" +" border: 1px solid gray;\n" +" border-radius: 9px;\n" +" margin-top: 0.5em;\n" +"}\n" +"\n" +"QGroupBox::title {\n" +" subcontrol-origin: margin;\n" +" left: 10px;\n" +" padding: 0 3px 0 3px;\n" +"}")); + groupBox_2->setFlat(true); + widget1 = new QWidget(groupBox_2); + widget1->setObjectName(QStringLiteral("widget1")); + widget1->setGeometry(QRect(10, 30, 132, 23)); + horizontalLayout_2 = new QHBoxLayout(widget1); + horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); + horizontalLayout_2->setContentsMargins(0, 0, 0, 0); + label_3 = new QLabel(widget1); + label_3->setObjectName(QStringLiteral("label_3")); + + horizontalLayout_2->addWidget(label_3); + + leNumMcus = new QLineEdit(widget1); + leNumMcus->setObjectName(QStringLiteral("leNumMcus")); + sizePolicy.setHeightForWidth(leNumMcus->sizePolicy().hasHeightForWidth()); + leNumMcus->setSizePolicy(sizePolicy); + leNumMcus->setMinimumSize(QSize(61, 0)); + leNumMcus->setMaximumSize(QSize(31, 16777215)); + + horizontalLayout_2->addWidget(leNumMcus); + + cbEnableDec = new QCheckBox(Q_DecodeDetailDlg); + cbEnableDec->setObjectName(QStringLiteral("cbEnableDec")); + cbEnableDec->setGeometry(QRect(10, 150, 211, 20)); + label_4 = new QLabel(Q_DecodeDetailDlg); + label_4->setObjectName(QStringLiteral("label_4")); + label_4->setGeometry(QRect(10, 180, 421, 16)); + widget2 = new QWidget(Q_DecodeDetailDlg); + widget2->setObjectName(QStringLiteral("widget2")); + widget2->setGeometry(QRect(329, 90, 120, 81)); + verticalLayout = new QVBoxLayout(widget2); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + verticalLayout->setContentsMargins(0, 0, 0, 0); + label_5 = new QLabel(widget2); + label_5->setObjectName(QStringLiteral("label_5")); + + verticalLayout->addWidget(label_5); + + pbLoadCoords = new QPushButton(widget2); + pbLoadCoords->setObjectName(QStringLiteral("pbLoadCoords")); + + verticalLayout->addWidget(pbLoadCoords); + +#ifndef QT_NO_SHORTCUT + label->setBuddy(leMcuX); + label_2->setBuddy(leMcuY); + label_3->setBuddy(leNumMcus); +#endif // QT_NO_SHORTCUT + + retranslateUi(Q_DecodeDetailDlg); + QObject::connect(buttonBox, SIGNAL(accepted()), Q_DecodeDetailDlg, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), Q_DecodeDetailDlg, SLOT(reject())); + + QMetaObject::connectSlotsByName(Q_DecodeDetailDlg); + } // setupUi + + void retranslateUi(QDialog *Q_DecodeDetailDlg) + { + Q_DecodeDetailDlg->setWindowTitle(QApplication::translate("Q_DecodeDetailDlg", "Detailed Scan Decode Options", nullptr)); + groupBox->setTitle(QApplication::translate("Q_DecodeDetailDlg", "Starting MCU for Decode", nullptr)); + label->setText(QApplication::translate("Q_DecodeDetailDlg", "MCU X =", nullptr)); + label_2->setText(QApplication::translate("Q_DecodeDetailDlg", "MCU Y =", nullptr)); + groupBox_2->setTitle(QApplication::translate("Q_DecodeDetailDlg", "Length of Decode", nullptr)); + label_3->setText(QApplication::translate("Q_DecodeDetailDlg", "# MCUs =", nullptr)); + cbEnableDec->setText(QApplication::translate("Q_DecodeDetailDlg", "Enable detailed Scan Decode?", nullptr)); + label_4->setText(QApplication::translate("Q_DecodeDetailDlg", "Detailed Scan Decode will be reported in the next decode operation", nullptr)); + label_5->setText(QApplication::translate("Q_DecodeDetailDlg", "Load X/Y/Len\n" +"from last 2 clicks:", nullptr)); + pbLoadCoords->setText(QApplication::translate("Q_DecodeDetailDlg", "Load Coords", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class Q_DecodeDetailDlg: public Ui_Q_DecodeDetailDlg {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_Q_DECODEDETAILDLG_H diff --git a/ui_snoopconfigdialog.h b/ui_snoopconfigdialog.h new file mode 100644 index 0000000..3671995 --- /dev/null +++ b/ui_snoopconfigdialog.h @@ -0,0 +1,309 @@ +/******************************************************************************** +** Form generated from reading UI file 'snoopconfigdialog.ui' +** +** Created by: Qt User Interface Compiler version 5.11.0 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_SNOOPCONFIGDIALOG_H +#define UI_SNOOPCONFIGDIALOG_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_SnoopConfigDialog +{ +public: + QDialogButtonBox *buttonBox; + QWidget *layoutWidget; + QVBoxLayout *verticalLayout_3; + QGroupBox *groupBox; + QWidget *layoutWidget1; + QHBoxLayout *horizontalLayout_2; + QLineEdit *leDbPath; + QVBoxLayout *verticalLayout; + QPushButton *btnBrowse; + QPushButton *btnDefault; + QGroupBox *groupBox_2; + QWidget *layoutWidget2; + QHBoxLayout *horizontalLayout; + QCheckBox *cbAutoUpdate; + QLineEdit *leUpdateDays; + QLabel *label_2; + QGroupBox *groupBox_3; + QWidget *layoutWidget3; + QVBoxLayout *verticalLayout_2; + QCheckBox *cbAutoReprocess; + QCheckBox *cbOblineDb; + QGroupBox *groupBox_4; + QWidget *layoutWidget4; + QHBoxLayout *horizontalLayout_3; + QLabel *label; + QLineEdit *leMaxErrors; + QGroupBox *groupBox_5; + QWidget *layoutWidget5; + QHBoxLayout *horizontalLayout_4; + QLabel *label_3; + QPushButton *btnReset; + + void setupUi(QDialog *SnoopConfigDialog) + { + if (SnoopConfigDialog->objectName().isEmpty()) + SnoopConfigDialog->setObjectName(QStringLiteral("SnoopConfigDialog")); + SnoopConfigDialog->resize(541, 426); + SnoopConfigDialog->setModal(true); + buttonBox = new QDialogButtonBox(SnoopConfigDialog); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setGeometry(QRect(440, 10, 81, 71)); + buttonBox->setOrientation(Qt::Vertical); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Save); + layoutWidget = new QWidget(SnoopConfigDialog); + layoutWidget->setObjectName(QStringLiteral("layoutWidget")); + layoutWidget->setGeometry(QRect(20, 10, 402, 406)); + verticalLayout_3 = new QVBoxLayout(layoutWidget); + verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3")); + verticalLayout_3->setContentsMargins(0, 0, 0, 0); + groupBox = new QGroupBox(layoutWidget); + groupBox->setObjectName(QStringLiteral("groupBox")); + groupBox->setMinimumSize(QSize(400, 80)); + groupBox->setStyleSheet(QLatin1String("QGroupBox {\n" +" border: 1px solid gray;\n" +" border-radius: 9px;\n" +" margin-top: 0.5em;\n" +"}\n" +"\n" +"QGroupBox::title {\n" +" subcontrol-origin: margin;\n" +" left: 10px;\n" +" padding: 0 3px 0 3px;\n" +"}")); + groupBox->setFlat(true); + layoutWidget1 = new QWidget(groupBox); + layoutWidget1->setObjectName(QStringLiteral("layoutWidget1")); + layoutWidget1->setGeometry(QRect(10, 10, 381, 71)); + horizontalLayout_2 = new QHBoxLayout(layoutWidget1); + horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); + horizontalLayout_2->setContentsMargins(0, 0, 0, 0); + leDbPath = new QLineEdit(layoutWidget1); + leDbPath->setObjectName(QStringLiteral("leDbPath")); + leDbPath->setMaximumSize(QSize(320, 20)); + + horizontalLayout_2->addWidget(leDbPath); + + verticalLayout = new QVBoxLayout(); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + btnBrowse = new QPushButton(layoutWidget1); + btnBrowse->setObjectName(QStringLiteral("btnBrowse")); + + verticalLayout->addWidget(btnBrowse); + + btnDefault = new QPushButton(layoutWidget1); + btnDefault->setObjectName(QStringLiteral("btnDefault")); + + verticalLayout->addWidget(btnDefault); + + + horizontalLayout_2->addLayout(verticalLayout); + + + verticalLayout_3->addWidget(groupBox); + + groupBox_2 = new QGroupBox(layoutWidget); + groupBox_2->setObjectName(QStringLiteral("groupBox_2")); + groupBox_2->setMinimumSize(QSize(400, 60)); + groupBox_2->setStyleSheet(QLatin1String("QGroupBox {\n" +" border: 1px solid gray;\n" +" border-radius: 9px;\n" +" margin-top: 0.5em;\n" +"}\n" +"\n" +"QGroupBox::title {\n" +" subcontrol-origin: margin;\n" +" left: 10px;\n" +" padding: 0 3px 0 3px;\n" +"}")); + groupBox_2->setFlat(true); + layoutWidget2 = new QWidget(groupBox_2); + layoutWidget2->setObjectName(QStringLiteral("layoutWidget2")); + layoutWidget2->setGeometry(QRect(10, 20, 381, 31)); + horizontalLayout = new QHBoxLayout(layoutWidget2); + horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + horizontalLayout->setContentsMargins(0, 0, 0, 0); + cbAutoUpdate = new QCheckBox(layoutWidget2); + cbAutoUpdate->setObjectName(QStringLiteral("cbAutoUpdate")); + cbAutoUpdate->setMaximumSize(QSize(260, 20)); + + horizontalLayout->addWidget(cbAutoUpdate); + + leUpdateDays = new QLineEdit(layoutWidget2); + leUpdateDays->setObjectName(QStringLiteral("leUpdateDays")); + leUpdateDays->setMaximumSize(QSize(40, 20)); + + horizontalLayout->addWidget(leUpdateDays); + + label_2 = new QLabel(layoutWidget2); + label_2->setObjectName(QStringLiteral("label_2")); + label_2->setMaximumSize(QSize(40, 20)); + + horizontalLayout->addWidget(label_2); + + + verticalLayout_3->addWidget(groupBox_2); + + groupBox_3 = new QGroupBox(layoutWidget); + groupBox_3->setObjectName(QStringLiteral("groupBox_3")); + groupBox_3->setMinimumSize(QSize(400, 80)); + groupBox_3->setStyleSheet(QLatin1String("QGroupBox {\n" +" border: 1px solid gray;\n" +" border-radius: 9px;\n" +" margin-top: 0.5em;\n" +"}\n" +"\n" +"QGroupBox::title {\n" +" subcontrol-origin: margin;\n" +" left: 10px;\n" +" padding: 0 3px 0 3px;\n" +"}")); + groupBox_3->setFlat(true); + layoutWidget3 = new QWidget(groupBox_3); + layoutWidget3->setObjectName(QStringLiteral("layoutWidget3")); + layoutWidget3->setGeometry(QRect(10, 20, 335, 41)); + verticalLayout_2 = new QVBoxLayout(layoutWidget3); + verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2")); + verticalLayout_2->setContentsMargins(0, 0, 0, 0); + cbAutoReprocess = new QCheckBox(layoutWidget3); + cbAutoReprocess->setObjectName(QStringLiteral("cbAutoReprocess")); + + verticalLayout_2->addWidget(cbAutoReprocess); + + cbOblineDb = new QCheckBox(layoutWidget3); + cbOblineDb->setObjectName(QStringLiteral("cbOblineDb")); + + verticalLayout_2->addWidget(cbOblineDb); + + + verticalLayout_3->addWidget(groupBox_3); + + groupBox_4 = new QGroupBox(layoutWidget); + groupBox_4->setObjectName(QStringLiteral("groupBox_4")); + groupBox_4->setMinimumSize(QSize(400, 60)); + groupBox_4->setMaximumSize(QSize(16777215, 60)); + groupBox_4->setStyleSheet(QLatin1String("QGroupBox {\n" +" border: 1px solid gray;\n" +" border-radius: 9px;\n" +" margin-top: 0.5em;\n" +"}\n" +"\n" +"QGroupBox::title {\n" +" subcontrol-origin: margin;\n" +" left: 10px;\n" +" padding: 0 3px 0 3px;\n" +"}")); + groupBox_4->setFlat(true); + layoutWidget4 = new QWidget(groupBox_4); + layoutWidget4->setObjectName(QStringLiteral("layoutWidget4")); + layoutWidget4->setGeometry(QRect(10, 20, 325, 31)); + horizontalLayout_3 = new QHBoxLayout(layoutWidget4); + horizontalLayout_3->setObjectName(QStringLiteral("horizontalLayout_3")); + horizontalLayout_3->setContentsMargins(0, 0, 0, 0); + label = new QLabel(layoutWidget4); + label->setObjectName(QStringLiteral("label")); + label->setMinimumSize(QSize(240, 20)); + label->setMaximumSize(QSize(240, 20)); + + horizontalLayout_3->addWidget(label); + + leMaxErrors = new QLineEdit(layoutWidget4); + leMaxErrors->setObjectName(QStringLiteral("leMaxErrors")); + leMaxErrors->setMaximumSize(QSize(40, 20)); + + horizontalLayout_3->addWidget(leMaxErrors); + + + verticalLayout_3->addWidget(groupBox_4); + + groupBox_5 = new QGroupBox(layoutWidget); + groupBox_5->setObjectName(QStringLiteral("groupBox_5")); + groupBox_5->setMinimumSize(QSize(400, 60)); + groupBox_5->setMaximumSize(QSize(16777215, 60)); + groupBox_5->setStyleSheet(QLatin1String("QGroupBox {\n" +" border: 1px solid gray;\n" +" border-radius: 9px;\n" +" margin-top: 0.5em;\n" +"}\n" +"\n" +"QGroupBox::title {\n" +" subcontrol-origin: margin;\n" +" left: 10px;\n" +" padding: 0 3px 0 3px;\n" +"}")); + groupBox_5->setFlat(true); + layoutWidget5 = new QWidget(groupBox_5); + layoutWidget5->setObjectName(QStringLiteral("layoutWidget5")); + layoutWidget5->setGeometry(QRect(10, 10, 311, 48)); + horizontalLayout_4 = new QHBoxLayout(layoutWidget5); + horizontalLayout_4->setObjectName(QStringLiteral("horizontalLayout_4")); + horizontalLayout_4->setContentsMargins(0, 0, 0, 0); + label_3 = new QLabel(layoutWidget5); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setMaximumSize(QSize(230, 20)); + + horizontalLayout_4->addWidget(label_3); + + btnReset = new QPushButton(layoutWidget5); + btnReset->setObjectName(QStringLiteral("btnReset")); + btnReset->setMinimumSize(QSize(80, 32)); + btnReset->setMaximumSize(QSize(80, 32)); + + horizontalLayout_4->addWidget(btnReset); + + + verticalLayout_3->addWidget(groupBox_5); + + + retranslateUi(SnoopConfigDialog); + + QMetaObject::connectSlotsByName(SnoopConfigDialog); + } // setupUi + + void retranslateUi(QDialog *SnoopConfigDialog) + { + SnoopConfigDialog->setWindowTitle(QApplication::translate("SnoopConfigDialog", "JPEGsnoop Confguration", nullptr)); + groupBox->setTitle(QApplication::translate("SnoopConfigDialog", "Directory for User Database", nullptr)); + btnBrowse->setText(QApplication::translate("SnoopConfigDialog", "Browse", nullptr)); + btnDefault->setText(QApplication::translate("SnoopConfigDialog", "Default", nullptr)); + groupBox_2->setTitle(QApplication::translate("SnoopConfigDialog", "Software Update", nullptr)); + cbAutoUpdate->setText(QApplication::translate("SnoopConfigDialog", "Automatically check for updates every ", nullptr)); + label_2->setText(QApplication::translate("SnoopConfigDialog", "days", nullptr)); + groupBox_3->setTitle(QApplication::translate("SnoopConfigDialog", "Processing Options", nullptr)); + cbAutoReprocess->setText(QApplication::translate("SnoopConfigDialog", "Auto Reprocess files on change in Options (slower)", nullptr)); + cbOblineDb->setText(QApplication::translate("SnoopConfigDialog", "Submit signature to Online DB when User submit", nullptr)); + groupBox_4->setTitle(QApplication::translate("SnoopConfigDialog", "Report Settings", nullptr)); + label->setText(QApplication::translate("SnoopConfigDialog", "Max # errors to report in Scan Decode", nullptr)); + groupBox_5->setTitle(QApplication::translate("SnoopConfigDialog", "Help", nullptr)); + label_3->setText(QApplication::translate("SnoopConfigDialog", "Coach Messages can be re-enabled:", nullptr)); + btnReset->setText(QApplication::translate("SnoopConfigDialog", "Reset", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class SnoopConfigDialog: public Ui_SnoopConfigDialog {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_SNOOPCONFIGDIALOG_H From 8e06955e45796873c58db712d35fd6c0f15adc19 Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Tue, 24 Jul 2018 22:50:05 -0700 Subject: [PATCH 02/14] Updated codebase from Bob Parker (archive 2018/07/23) - Also relocated source files into /source (via .pro) --- JPEGSnoop.qrc | 43 + JPEGSnoopQt.pro | 92 +- res/JPEGsnoop.manifest | 22 - res/JPEGsnoop.rc2 | 13 - res/JPEGsnoopDoc.ico | Bin 1078 -> 0 bytes res/Toolbar.bmp | Bin 1078 -> 0 bytes res/jpegsnoop-prog-icon1-novista.ico | Bin 25214 -> 0 bytes source/AboutDlg.cpp | 69 - source/AboutDlg.h | 51 - source/BatchDlg.cpp | 97 - source/BatchDlg.h | 60 - source/CntrItem.cpp | 63 - source/CntrItem.h | 57 - source/DbManageDlg.cpp | 153 - source/DbManageDlg.h | 72 - source/DbSigs.cpp | 192 +- source/DbSigs.h | 75 +- source/DbSubmitDlg.cpp | 94 - source/DbSubmitDlg.h | 58 - source/DecodeDetailDlg.cpp | 75 - source/DecodeDetailDlg.h | 57 - source/DecodeDicom.cpp | 1759 +++++------ source/DecodeDicom.h | 4 +- source/DecodeDicomTags.cpp | 3931 ------------------------- source/DecodePs.cpp | 413 +-- source/DecodePs.h | 34 +- source/Dib.cpp | 347 --- source/Dib.h | 125 - source/DocLog.cpp | 2 +- source/DocLog.h | 2 +- source/ExportDlg.cpp | 63 - source/ExportDlg.h | 54 - source/ExportTiffDlg.cpp | 66 - source/ExportTiffDlg.h | 52 - source/FileTiff.cpp | 539 ---- source/FileTiff.h | 93 - source/FolderDlg.cpp | 718 ++--- source/FolderDlg.h | 356 +-- source/General.cpp | 243 +- source/General.h | 30 +- source/HyperlinkStatic.cpp | 182 -- source/HyperlinkStatic.h | 99 - source/ImgDecode.cpp | 1564 +++++----- source/ImgDecode.h | 107 +- source/JPEGsnoop.cpp | 1729 ----------- source/JPEGsnoop.h | 136 - source/JPEGsnoop.rc | 1031 ------- source/JPEGsnoopCore.cpp | 1495 ---------- source/JPEGsnoopCore.h | 164 -- source/JPEGsnoopDoc.cpp | 2227 -------------- source/JPEGsnoopDoc.h | 175 -- source/JPEGsnoopView.cpp | 204 -- source/JPEGsnoopView.h | 79 - source/JPEGsnoopViewImg.cpp | 349 --- source/JPEGsnoopViewImg.h | 78 - source/JfifDecode.cpp | 739 +++-- source/JfifDecode.h | 43 +- source/LookupDlg.cpp | 117 - source/LookupDlg.h | 70 - source/MainFrm.cpp | 229 -- source/MainFrm.h | 84 - source/Md5.cpp | 2 +- source/Md5.h | 2 +- source/ModelessDlg.cpp | 61 - source/ModelessDlg.h | 56 - source/NoteDlg.cpp | 53 - source/NoteDlg.h | 51 - source/OffsetDlg.cpp | 187 -- source/OffsetDlg.h | 68 - source/OverlayBufDlg.cpp | 193 -- source/OverlayBufDlg.h | 77 - source/Registry.cpp | 647 ---- source/Registry.h | 706 ----- source/SettingsDlg.cpp | 155 - source/SettingsDlg.h | 60 - source/SnoopConfig.cpp | 172 +- source/SnoopConfig.h | 108 +- source/TermsDlg.cpp | 95 - source/TermsDlg.h | 56 - source/UpdateAvailDlg.cpp | 65 - source/UpdateAvailDlg.h | 54 - source/Viewer.cpp | 224 ++ source/Viewer.h | 51 + source/WindowBuf.cpp | 22 +- source/WindowBuf.h | 15 +- source/eula.cpp | 39 + source/eula.h | 27 + source/eula.ui | 134 + source/jpegsnoop.rc-1.5.2.japanese | 1079 ------- source/labelClick.cpp | 43 + source/labelClick.h | 30 + source/main.cpp | 19 - source/mainwindow.cpp | 420 ++- source/mainwindow.h | 45 +- mainwindow.ui => source/mainwindow.ui | 0 source/note.cpp | 20 + source/note.h | 23 + source/note.ui | 113 + source/resource.h | 204 -- source/snoop.h | 21 +- source/snoopconfigdialog.cpp | 23 +- source/snoopconfigdialog.h | 6 +- source/stdafx.cpp | 25 - source/stdafx.h | 63 - ui_q_decodedetaildlg.h | 212 -- ui_snoopconfigdialog.h | 309 -- 106 files changed, 4555 insertions(+), 22555 deletions(-) create mode 100644 JPEGSnoop.qrc delete mode 100644 res/JPEGsnoop.manifest delete mode 100644 res/JPEGsnoop.rc2 delete mode 100644 res/JPEGsnoopDoc.ico delete mode 100644 res/Toolbar.bmp delete mode 100644 res/jpegsnoop-prog-icon1-novista.ico delete mode 100644 source/AboutDlg.cpp delete mode 100644 source/AboutDlg.h delete mode 100644 source/BatchDlg.cpp delete mode 100644 source/BatchDlg.h delete mode 100644 source/CntrItem.cpp delete mode 100644 source/CntrItem.h delete mode 100644 source/DbManageDlg.cpp delete mode 100644 source/DbManageDlg.h delete mode 100644 source/DbSubmitDlg.cpp delete mode 100644 source/DbSubmitDlg.h delete mode 100644 source/DecodeDetailDlg.cpp delete mode 100644 source/DecodeDetailDlg.h delete mode 100644 source/DecodeDicomTags.cpp delete mode 100644 source/Dib.cpp delete mode 100644 source/Dib.h delete mode 100644 source/ExportDlg.cpp delete mode 100644 source/ExportDlg.h delete mode 100644 source/ExportTiffDlg.cpp delete mode 100644 source/ExportTiffDlg.h delete mode 100644 source/FileTiff.cpp delete mode 100644 source/FileTiff.h delete mode 100644 source/HyperlinkStatic.cpp delete mode 100644 source/HyperlinkStatic.h delete mode 100644 source/JPEGsnoop.cpp delete mode 100644 source/JPEGsnoop.h delete mode 100644 source/JPEGsnoop.rc delete mode 100644 source/JPEGsnoopCore.cpp delete mode 100644 source/JPEGsnoopCore.h delete mode 100644 source/JPEGsnoopDoc.cpp delete mode 100644 source/JPEGsnoopDoc.h delete mode 100644 source/JPEGsnoopView.cpp delete mode 100644 source/JPEGsnoopView.h delete mode 100644 source/JPEGsnoopViewImg.cpp delete mode 100644 source/JPEGsnoopViewImg.h delete mode 100644 source/LookupDlg.cpp delete mode 100644 source/LookupDlg.h delete mode 100644 source/MainFrm.cpp delete mode 100644 source/MainFrm.h delete mode 100644 source/ModelessDlg.cpp delete mode 100644 source/ModelessDlg.h delete mode 100644 source/NoteDlg.cpp delete mode 100644 source/NoteDlg.h delete mode 100644 source/OffsetDlg.cpp delete mode 100644 source/OffsetDlg.h delete mode 100644 source/OverlayBufDlg.cpp delete mode 100644 source/OverlayBufDlg.h delete mode 100644 source/Registry.cpp delete mode 100644 source/Registry.h delete mode 100644 source/SettingsDlg.cpp delete mode 100644 source/SettingsDlg.h delete mode 100644 source/TermsDlg.cpp delete mode 100644 source/TermsDlg.h delete mode 100644 source/UpdateAvailDlg.cpp delete mode 100644 source/UpdateAvailDlg.h create mode 100644 source/Viewer.cpp create mode 100644 source/Viewer.h create mode 100644 source/eula.cpp create mode 100644 source/eula.h create mode 100644 source/eula.ui delete mode 100644 source/jpegsnoop.rc-1.5.2.japanese create mode 100644 source/labelClick.cpp create mode 100644 source/labelClick.h rename mainwindow.ui => source/mainwindow.ui (100%) create mode 100644 source/note.cpp create mode 100644 source/note.h create mode 100644 source/note.ui delete mode 100644 source/resource.h delete mode 100644 source/stdafx.cpp delete mode 100644 source/stdafx.h delete mode 100644 ui_q_decodedetaildlg.h delete mode 100644 ui_snoopconfigdialog.h diff --git a/JPEGSnoop.qrc b/JPEGSnoop.qrc new file mode 100644 index 0000000..f1f552d --- /dev/null +++ b/JPEGSnoop.qrc @@ -0,0 +1,43 @@ + + + eula.txt + images/mac/editcopy.png + images/mac/editcut.png + images/mac/editpaste.png + images/mac/editredo.png + images/mac/editundo.png + images/mac/exportpdf.png + images/mac/filenew.png + images/mac/fileopen.png + images/mac/fileprint.png + images/mac/filesave.png + images/mac/textbold.png + images/mac/textcenter.png + images/mac/textitalic.png + images/mac/textjustify.png + images/mac/textleft.png + images/mac/textright.png + images/mac/textunder.png + images/mac/zoomin.png + images/mac/zoomout.png + images/win/editcopy.png + images/win/editcut.png + images/win/editpaste.png + images/win/editredo.png + images/win/editundo.png + images/win/exportpdf.png + images/win/filenew.png + images/win/fileopen.png + images/win/fileprint.png + images/win/filesave.png + images/win/textbold.png + images/win/textcenter.png + images/win/textitalic.png + images/win/textjustify.png + images/win/textleft.png + images/win/textright.png + images/win/textunder.png + images/win/zoomin.png + images/win/zoomout.png + + diff --git a/JPEGSnoopQt.pro b/JPEGSnoopQt.pro index e91dd98..a16cdc4 100644 --- a/JPEGSnoopQt.pro +++ b/JPEGSnoopQt.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui +QT += core gui printsupport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -25,12 +25,11 @@ QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtGui QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtWidgets } -QMAKE_CXXFLAGS += -fstrict-aliasing -Wextra -pedantic -Weffc++ -Wfloat-equal -Wswitch-default -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wdisabled-optimization -Wformat-nonliteral -Wformat-security -QMAKE_CXXFLAGS += -Wconversion -Wformat-nonliteral -Wformat-y2k -Wformat=2 -Wimport -Winit-self -Winline -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wold-style-cast -QMAKE_CXXFLAGS += -Wpacked -Wpointer-arith -Wredundant-decls -Wshadow -Wstack-protector -Wstrict-aliasing=2 -Wswitch-enum -Wunreachable-code -Wunused -Wvariadic-macros -Wwrite-strings - -#CAL! Added source directory -INCLUDEPATH += source +QMAKE_CXXFLAGS += -fstrict-aliasing -Wextra -pedantic -Weffc++ -Wfloat-equal -Wswitch-default -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment +QMAKE_CXXFLAGS += -Wdisabled-optimization -Wformat-nonliteral -Wformat-security -Wconversion -Wformat-nonliteral -Wformat-y2k -Wformat=2 -Wimport +QMAKE_CXXFLAGS += -Winit-self -Winline -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wold-style-cast +QMAKE_CXXFLAGS += -Wpacked -Wpointer-arith -Wredundant-decls -Wshadow -Wstack-protector -Wstrict-aliasing=2 -Wswitch-enum -Wunreachable-code +QMAKE_CXXFLAGS += -Wunused -Wvariadic-macros -Wwrite-strings # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings @@ -43,46 +42,47 @@ DEFINES += QT_DEPRECATED_WARNINGS # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 -SOURCES = \ - source/JfifDecode.cpp \ - source/DbSigs.cpp \ - source/DecodePs.cpp \ - source/DocLog.cpp \ - source/General.cpp \ - source/ImgDecode.cpp \ - source/JPEGsnoopCore.cpp \ - source/main.cpp \ - source/mainwindow.cpp \ - source/Md5.cpp \ - source/q_decodedetaildlg.cpp \ - source/SnoopConfig.cpp \ - source/snoopconfigdialog.cpp \ - source/WindowBuf.cpp -SOURCES += -SOURCES += - - -HEADERS = \ - source/JfifDecode.h \ - source/DbSigs.h \ - source/WindowBuf.h \ - source/snoopconfigdialog.h \ - source/SnoopConfig.h \ - source/snoop.h \ - source/q_decodedetaildlg.h \ - source/Md5.h \ - source/mainwindow.h \ - source/JPEGsnoopCore.h \ - source/JPEGsnoop.h \ - source/ImgDecode.h \ - source/General.h \ - source/DocLog.h \ - source/DecodePs.h \ - source/DecodeDicom.h -HEADERS += -HEADERS += +SOURCES = source/main.cpp \ + source/note.cpp \ + source/eula.cpp +SOURCES += source/DbSigs.cpp +SOURCES += source/DecodePs.cpp +SOURCES += source/DocLog.cpp +SOURCES += source/General.cpp +SOURCES += source/ImgDecode.cpp +SOURCES += source/JfifDecode.cpp +SOURCES += source/labelClick.cpp +SOURCES += source/Md5.cpp +SOURCES += source/SnoopConfig.cpp +SOURCES += source/WindowBuf.cpp +SOURCES += source/mainwindow.cpp +SOURCES += source/q_decodedetaildlg.cpp +SOURCES += source/snoopconfigdialog.cpp +SOURCES += source/Viewer.cpp +HEADERS = source/mainwindow.h \ + source/note.h \ + source/eula.h +HEADERS += source/DbSigs.h +HEADERS += source/DecodeDicom.h +HEADERS += source/DecodePs.h +HEADERS += source/DocLog.h +HEADERS += source/General.h +HEADERS += source/ImgDecode.h +HEADERS += source/JfifDecode.h +HEADERS += source/labelClick.h +HEADERS += source/Md5.h +HEADERS += source/SnoopConfig.h +HEADERS += source/WindowBuf.h +HEADERS += source/q_decodedetaildlg.h +HEADERS += source/snoop.h +HEADERS += source/snoopconfigdialog.h +HEADERS += source/Viewer.h FORMS += \ + source/snoopconfigdialog.ui \ source/q_decodedetaildlg.ui \ - source/snoopconfigdialog.ui + source/note.ui \ + source/eula.ui + +RESOURCES = JPEGSnoop.qrc diff --git a/res/JPEGsnoop.manifest b/res/JPEGsnoop.manifest deleted file mode 100644 index 132e7fb..0000000 --- a/res/JPEGsnoop.manifest +++ /dev/null @@ -1,22 +0,0 @@ - - - -JPEGsnoop image decoder and analysis - - - - - - diff --git a/res/JPEGsnoop.rc2 b/res/JPEGsnoop.rc2 deleted file mode 100644 index a70d446..0000000 --- a/res/JPEGsnoop.rc2 +++ /dev/null @@ -1,13 +0,0 @@ -// -// JPEGsnoop.RC2 - resources Microsoft Visual C++ does not edit directly -// - -#ifdef APSTUDIO_INVOKED -#error this file is not editable by Microsoft Visual C++ -#endif //APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// Add manually edited resources here... - -///////////////////////////////////////////////////////////////////////////// diff --git a/res/JPEGsnoopDoc.ico b/res/JPEGsnoopDoc.ico deleted file mode 100644 index 2a1f1ae6ef15e51df8c39bc028bbfb2171822ba5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1078 zcmcJNF;c@Y5JlGsgIpoERJdY%i*S@2!JS&si6f-)RXoFGDAfg5;z_dQBoi_)1DpI^ z{oS?KlD%25H@>BZ{KJV|_dD9_G1MV<{5a&-}7^W%4AM)k- zx&P*V(j}a@*Y~UhksXTAK!NRyiYN-8NMyKz<)2v9@tUao7A!g+SzkAcsHvdq6!0vQ z#-rA6>0BAr)4*u6Y57EdkamnXf Uh-a7VEuQ2KJb_2>o71HC3-%7w@Bjb+ diff --git a/res/Toolbar.bmp b/res/Toolbar.bmp deleted file mode 100644 index d501723c1ceb781cccf04bc42408a2bee6b0eab4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1078 zcmb_byK2Kg5WFD46)N-_DGd%mbvRHJ@+(`2Y#@z5De^h$T}Yp#;yM?~%&rw%!DZII z_s!1Ct^M-)Tn3AG^p9vgT8;J){9rDyxEsA+?t8wt)o$n@0`>@NK8bGHkdKdb4m#tglAgQo-)Js1!#;+~GSl z37z4Z<|(I?jV44Q_xOeQ!(IFmLY86pVjciLPfC9(?0)$t7hw7W^>>N<@a4LVKPMb~ ze5>=j|BL>!3lPen5hUo~ANKN`l7C&3 z%0PPq3XFRT-e1OO0*EKjOA>DIfd!JKE>l7s8ZOWoALnDl7bEaBMvn{Ll0`lMj_p*2 zeyj@cEB=w(f%+@Ig9SfK=ePQ9c)El>T>d0F2ei{lnHqPg}It<8 diff --git a/res/jpegsnoop-prog-icon1-novista.ico b/res/jpegsnoop-prog-icon1-novista.ico deleted file mode 100644 index 61893cf0631bfcfc2c3562d17e7850ed7064346e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25214 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 Byovw- diff --git a/source/AboutDlg.cpp b/source/AboutDlg.cpp deleted file mode 100644 index cad4ca8..0000000 --- a/source/AboutDlg.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "stdafx.h" -#include "jpegsnoop.h" -#include "AboutDlg.h" - - -CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) -, m_staticVerNum(_T("")) -{ -} - -void CAboutDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Control(pDX, IDC_URL, m_staticURL); - DDX_Control(pDX, IDC_URL_DOC, m_staticURLdoc); - DDX_Text(pDX, IDC_VER_NUM, m_staticVerNum); -} - -BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) -END_MESSAGE_MAP() - - - -// CjpegsnoopApp message handlers - - -BOOL CAboutDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - - // Dynamically change static text of version number - CString strTmp; - - strTmp.Format(_T("Version %s"),VERSION_STR); - m_staticVerNum.SetString(strTmp); - m_staticVerNum.Format(_T("Version %s"),VERSION_STR); - - UpdateData(FALSE); - - - // Update the URLs - m_staticURL.SetHyperlink(_T("http://www.impulseadventure.com/photo/")); - strTmp.Format(_T("http://www.impulseadventure.com/photo/jpeg-snoop.html?ver=%s"),VERSION_STR); - m_staticURLdoc.SetHyperlink(strTmp); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - diff --git a/source/AboutDlg.h b/source/AboutDlg.h deleted file mode 100644 index 670df79..0000000 --- a/source/AboutDlg.h +++ /dev/null @@ -1,51 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box providing basic about & version info -// -// ========================================================================== - -#pragma once -#include "afxwin.h" -#include "HyperlinkStatic.h" - -// CAboutDlg dialog used for App About - -class CAboutDlg : public CDialog -{ -public: - CAboutDlg(); - -// Dialog Data - enum { IDD = IDD_ABOUTBOX }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - -// Implementation -protected: - DECLARE_MESSAGE_MAP() -public: - virtual BOOL OnInitDialog(); - - CHyperlinkStatic m_staticURL; - CHyperlinkStatic m_staticURLdoc; - CString m_staticVerNum; -}; diff --git a/source/BatchDlg.cpp b/source/BatchDlg.cpp deleted file mode 100644 index 60f4eb3..0000000 --- a/source/BatchDlg.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// BatchDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "BatchDlg.h" - - -// CBatchDlg dialog - -IMPLEMENT_DYNAMIC(CBatchDlg, CDialog) -CBatchDlg::CBatchDlg(CWnd* pParent /*=NULL*/) - : CDialog(CBatchDlg::IDD, pParent) - , m_bProcessSubdir(FALSE) - , m_bExtractAll(FALSE) - , m_strDirSrc(_T("")) - , m_strDirDst(_T("")) -{ -} - -CBatchDlg::~CBatchDlg() -{ -} - -void CBatchDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Check(pDX, IDC_CHECK_SUBDIRS, m_bProcessSubdir); - DDX_Check(pDX, IDC_CHECK_EXT_ALL, m_bExtractAll); - DDX_Text(pDX, IDC_EDIT_DIR_SRC, m_strDirSrc); - DDX_Text(pDX, IDC_EDIT_DIR_DST, m_strDirDst); -} - - -BEGIN_MESSAGE_MAP(CBatchDlg, CDialog) - ON_BN_CLICKED(IDC_BTN_DIR_SRC_BROWSE, &CBatchDlg::OnBnClickedBtnDirSrcBrowse) - ON_BN_CLICKED(IDC_BTN_DIR_DST_BROWSE, &CBatchDlg::OnBnClickedBtnDirDstBrowse) -END_MESSAGE_MAP() - - -// CBatchDlg message handlers - - -void CBatchDlg::OnBnClickedBtnDirSrcBrowse() -{ - CFolderDialog myFolderDlg(NULL); - LPCITEMIDLIST myItemIdList; - CString strPath; - // Save fields first - UpdateData(true); - // Now request new path - myFolderDlg.SetStartPath(m_strDirSrc); - myItemIdList = myFolderDlg.BrowseForFolder(_T("Select input image folder"),0,0,false); - strPath = myFolderDlg.GetPathName(myItemIdList); - if (!strPath.IsEmpty()) { - m_strDirSrc = strPath; - // Also default the output log directory to same as input - m_strDirDst = strPath; - UpdateData(false); - } -} - - -void CBatchDlg::OnBnClickedBtnDirDstBrowse() -{ - CFolderDialog myFolderDlg(NULL); - LPCITEMIDLIST myItemIdList; - CString strPath; - // Save fields first - UpdateData(true); - // Now request new path - myFolderDlg.SetStartPath(m_strDirDst); - myItemIdList = myFolderDlg.BrowseForFolder(_T("Select output log folder"),0,0,false); - strPath = myFolderDlg.GetPathName(myItemIdList); - if (!strPath.IsEmpty()) { - m_strDirDst = strPath; - UpdateData(false); - } -} diff --git a/source/BatchDlg.h b/source/BatchDlg.h deleted file mode 100644 index 0bdd5c9..0000000 --- a/source/BatchDlg.h +++ /dev/null @@ -1,60 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box for Batch image processing -// -// ========================================================================== - - -#pragma once - - -// FIXME: -// For some reason, the IDD_BATCHDLG constant reports C2065 "undeclared identifier" -// So as a workaround, I am explicitly referencing "Resource.h" here -#include "Resource.h" - - -// CBatchDlg dialog - -class CBatchDlg : public CDialog -{ - DECLARE_DYNAMIC(CBatchDlg) - -public: - CBatchDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CBatchDlg(); - -// Dialog Data - enum { IDD = IDD_BATCHDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -public: - afx_msg void OnBnClickedBtnDirSrcBrowse(); - afx_msg void OnBnClickedBtnDirDstBrowse(); - - BOOL m_bProcessSubdir; - BOOL m_bExtractAll; - CString m_strDirSrc; - CString m_strDirDst; -}; diff --git a/source/CntrItem.cpp b/source/CntrItem.cpp deleted file mode 100644 index 466de74..0000000 --- a/source/CntrItem.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// CntrItem.cpp : implementation of the CJPEGsnoopCntrItem class -// - -#include "stdafx.h" -#include "JPEGsnoop.h" - -#include "JPEGsnoopDoc.h" -#include "JPEGsnoopView.h" -#include "CntrItem.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - - -// CJPEGsnoopCntrItem implementation - -IMPLEMENT_SERIAL(CJPEGsnoopCntrItem, CRichEditCntrItem, 0) - -CJPEGsnoopCntrItem::CJPEGsnoopCntrItem(REOBJECT* preo, CJPEGsnoopDoc* pContainer) - : CRichEditCntrItem(preo, pContainer) -{ - // TODO: add one-time construction code here -} - -CJPEGsnoopCntrItem::~CJPEGsnoopCntrItem() -{ - // TODO: add cleanup code here -} - - -// CJPEGsnoopCntrItem diagnostics - -#ifdef _DEBUG -void CJPEGsnoopCntrItem::AssertValid() const -{ - CRichEditCntrItem::AssertValid(); -} - -void CJPEGsnoopCntrItem::Dump(CDumpContext& dc) const -{ - CRichEditCntrItem::Dump(dc); -} -#endif - diff --git a/source/CntrItem.h b/source/CntrItem.h deleted file mode 100644 index d14322a..0000000 --- a/source/CntrItem.h +++ /dev/null @@ -1,57 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// CntrItem.h : interface of the CJPEGsnoopCntrItem class -// - -#pragma once - -class CJPEGsnoopDoc; -class CJPEGsnoopView; - -class CJPEGsnoopCntrItem : public CRichEditCntrItem -{ - DECLARE_SERIAL(CJPEGsnoopCntrItem) - -// Constructors -public: - CJPEGsnoopCntrItem(REOBJECT* preo = NULL, CJPEGsnoopDoc* pContainer = NULL); - // Note: pContainer is allowed to be NULL to enable IMPLEMENT_SERIALIZE - // IMPLEMENT_SERIALIZE requires the class have a constructor with - // zero arguments. Normally, OLE items are constructed with a - // non-NULL document pointer - -// Attributes -public: - CJPEGsnoopDoc* GetDocument() - { return reinterpret_cast(CRichEditCntrItem::GetDocument()); } - CJPEGsnoopView* GetActiveView() - { return reinterpret_cast(CRichEditCntrItem::GetActiveView()); } - - public: - protected: - -// Implementation -public: - ~CJPEGsnoopCntrItem(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif -}; - diff --git a/source/DbManageDlg.cpp b/source/DbManageDlg.cpp deleted file mode 100644 index 442ac89..0000000 --- a/source/DbManageDlg.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// DbManageDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "DbManageDlg.h" -#include ".\dbmanagedlg.h" - - -// CDbManageDlg dialog - -IMPLEMENT_DYNAMIC(CDbManageDlg, CDialog) -CDbManageDlg::CDbManageDlg(CWnd* pParent /*=NULL*/) - : CDialog(CDbManageDlg::IDD, pParent) -{ - m_asToInsert.SetSize(0,10); - m_anListBoxInd.SetSize(0,10); -} - -CDbManageDlg::~CDbManageDlg() -{ -} - -void CDbManageDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Control(pDX, IDC_LIST, m_ctlListBox); -} - -BOOL CDbManageDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - int lpiTabs[4]; - lpiTabs[0] = 150; - lpiTabs[1] = 250; - lpiTabs[2] = 300; - m_ctlListBox.SetTabStops(3,lpiTabs); - - // TODO: Add extra initialization here - // Transfer the pending list of - PopulateList(); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - - -BEGIN_MESSAGE_MAP(CDbManageDlg, CDialog) - ON_BN_CLICKED(IDC_REMOVE, OnBnClickedRemove) - ON_BN_CLICKED(IDC_REMOVEALL, OnBnClickedRemoveall) -END_MESSAGE_MAP() - - -// CDbManageDlg message handlers - -// Prepare a custom signature entry for addition into the dialog listbox -void CDbManageDlg::InsertEntry(unsigned ind,CString strMake, CString strModel, CString strQual, CString strSig) -{ - ind; // Unreferenced param - - CString strTmp; - strTmp.Format(_T("Make: [%s]\tModel: [%s]\tQual: [%s]"),(LPCTSTR)strMake,(LPCTSTR)strModel,(LPCTSTR)strQual); - m_asToInsert.Add(strTmp); -} - -// Copy entries from insert array to the listbox and record their position -void CDbManageDlg::PopulateList() -{ - CString strTmp; - - // Reset the current entry index list - m_anListBoxInd.RemoveAll(); - - // Now copy entries over - int nEntriesOrigMax = m_asToInsert.GetCount(); - int nListPos; - for (int nInd=0;nInd. -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box that allows user to manage the local signatures database -// - The caller will invoke InsertEntry() on all extra database signatures -// which can then be added to the listbox via PopulateList() during OnInitDialog(). -// - A sideband parallel array is used to record the original index positions -// of each entry in the listbox so that we can easily determine which entries -// have been deleted once the dialog has completed. -// - The parallel array can be queried after the dialog box has closed via GetRemainIndices() -// to return the list of custom signature indices that remain. This allows -// the master list to be trimmed down (ie. entries removed). -// ========================================================================== - - -#pragma once -#include "afxwin.h" - - -// CDbManageDlg dialog - -class CDbManageDlg : public CDialog -{ - DECLARE_DYNAMIC(CDbManageDlg) - -public: - CDbManageDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CDbManageDlg(); - -// Dialog Data - enum { IDD = IDD_DBMANAGEDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -public: - void InsertEntry(unsigned ind,CString strMake, CString strModel, CString strQual, CString strSig); - void PopulateList(); - void GetRemainIndices(CUIntArray& anRemain); - -private: - virtual BOOL OnInitDialog(); - afx_msg void OnBnClickedRemove(); - afx_msg void OnBnClickedRemoveall(); - -private: - CListBox m_ctlListBox; // Listbox representing custom signatures - CStringArray m_asToInsert; // Entries to be added to Listbox via PopulateList() - - CUIntArray m_anListBoxInd; // Index of entries currently in listBox (e.g 1,2,4,7,15) - - - -}; diff --git a/source/DbSigs.cpp b/source/DbSigs.cpp index afc6f27..be6694b 100644 --- a/source/DbSigs.cpp +++ b/source/DbSigs.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -16,13 +16,17 @@ // along with this program. If not, see . // +#include #include #include -#include "DbSigs.h" +#include "DocLog.h" #include "General.h" - +//#include "JPEGsnoop.h" #include "snoop.h" +#include "SnoopConfig.h" + +#include "DbSigs.h" #include "Signatures.inl" @@ -53,7 +57,7 @@ // - m_nXcomSwListNum // - m_strDbDir // -CDbSigs::CDbSigs() +CDbSigs::CDbSigs(CDocLog *pLog, CSnoopConfig *pAppConfig) : m_pDocLog(pLog), m_pAppConfig(pAppConfig) { // Count the built-in database bool bDone; @@ -65,20 +69,29 @@ CDbSigs::CDbSigs() while (!bDone) { -// if (!_tcscmp(m_sSigList[m_nSigListNum].strXMake,"*")) if (m_sSigList[m_nSigListNum].strXMake == "*") + { bDone = true; + } else + { m_nSigListNum++; + m_qSigList.append(m_sSigList[m_nSigListNum]); + } } + QFile sigFile(m_pAppConfig->dbPath() + "Signatures.dat"); + sigFile.open(QIODevice::WriteOnly); + QDataStream out(&sigFile); +// out << m_qSigList; + qDebug() << m_qSigList.count(); + // Count number of exceptions in Signatures.inl bDone = false; m_nExcMmNoMkrListNum = 0; while (!bDone) { -// if (!_tcscmp(m_sExcMmNoMkrList[m_nExcMmNoMkrListNum].strXMake,"*")) if (m_sExcMmNoMkrList[m_nExcMmNoMkrListNum].strXMake == "*") bDone = true; else @@ -90,14 +103,12 @@ CDbSigs::CDbSigs() while (!bDone) { -// if (!_tcscmp(m_sExcMmIsEditList[m_nExcMmIsEditListNum].strXMake,"*")) if (m_sExcMmIsEditList[m_nExcMmIsEditListNum].strXMake == "*") bDone = true; else m_nExcMmIsEditListNum++; } - bDone = false; m_nSwIjgListNum = 0; @@ -115,7 +126,6 @@ CDbSigs::CDbSigs() m_nSwIjgListNum = m_sSwIjgList.count(); - bDone = false; m_nXcomSwListNum = 0; @@ -157,38 +167,37 @@ void CDbSigs::SetFirstRun(bool bFirstRun) m_bFirstRun = bFirstRun; } -unsigned CDbSigs::GetNumSigsInternal() +int32_t CDbSigs::GetNumSigsInternal() { return m_nSigListNum; } -unsigned CDbSigs::GetNumSigsExtra() +int32_t CDbSigs::GetNumSigsExtra() { return m_nSigListExtraNum; } - // Read an unsigned integer (4B) from the buffer -bool CDbSigs::BufReadNum(uint8_t *pBuf,unsigned &nOut,unsigned,unsigned &nOffsetBytes) +bool CDbSigs::BufReadNum(uint8_t *pBuf,uint32_t &nOut,uint32_t,uint32_t &nOffsetBytes) { Q_ASSERT(pBuf); // TODO: check for buffer bounds - nOut = (unsigned)pBuf[nOffsetBytes]; - nOffsetBytes += sizeof(unsigned); + nOut = static_cast(pBuf[nOffsetBytes]); + nOffsetBytes += sizeof(uint32_t); return true; } // Write an unsigned integer (4B) to the buffer -bool CDbSigs::BufWriteNum(uint8_t *pBuf,unsigned nIn,unsigned,unsigned &nOffsetBytes) +bool CDbSigs::BufWriteNum(uint8_t *pBuf,uint32_t nIn,uint32_t,uint32_t &nOffsetBytes) { Q_ASSERT(pBuf); // TODO: check for buffer bounds uint8_t * pBufBase; - unsigned* pBufInt; + uint32_t* pBufInt; pBufBase = &pBuf[nOffsetBytes]; - pBufInt = (unsigned*)pBufBase; + pBufInt = reinterpret_cast(pBufBase); pBufInt[0] = nIn; - nOffsetBytes += sizeof(unsigned); + nOffsetBytes += sizeof(uint32_t); return true; } @@ -197,7 +206,7 @@ bool CDbSigs::BufWriteNum(uint8_t *pBuf,unsigned nIn,unsigned,unsigned &nOffsetB // Both 16-bit unicode and 8-bit SBCS encoding modes are supported (via bUni) // Offset parameter is incremented accordingly // Supports both newline and NULL for string termination -bool CDbSigs::BufReadStr(uint8_t *pBuf,QString &strOut,unsigned nMaxBytes,bool bUni,unsigned &nOffsetBytes) +bool CDbSigs::BufReadStr(uint8_t *pBuf,QString &strOut,uint32_t nMaxBytes,bool bUni,uint32_t &nOffsetBytes) { Q_ASSERT(pBuf); QString strOutTmp; @@ -205,13 +214,13 @@ bool CDbSigs::BufReadStr(uint8_t *pBuf,QString &strOut,unsigned nMaxBytes,bool b char chAsc; wchar_t chUni; - unsigned nCharSz = ((bUni)?sizeof(wchar_t):sizeof(char)); + uint32_t nCharSz = ((bUni)?sizeof(wchar_t):sizeof(char)); bDone = false; strOut = ""; // Ensure we don't overrun the buffer by calculating the last byte index required for each iteration. - for (unsigned nInd=nOffsetBytes; (!bDone) && (nInd + nCharSz - 1 < nMaxBytes); nInd += nCharSz) + for (uint32_t nInd=nOffsetBytes; (!bDone) && (nInd + nCharSz - 1 < nMaxBytes); nInd += nCharSz) { if (bUni) { @@ -254,24 +263,21 @@ bool CDbSigs::BufReadStr(uint8_t *pBuf,QString &strOut,unsigned nMaxBytes,bool b } // Return true if we managed to write entire string including terminator without overrunning nMaxBytes -bool CDbSigs::BufWriteStr(unsigned char *pBuf,QString strIn,unsigned nMaxBytes,bool bUni,unsigned &nOffsetBytes) +bool CDbSigs::BufWriteStr(unsigned char *pBuf,QString strIn,uint32_t nMaxBytes,bool bUni,uint32_t &nOffsetBytes) { - Q_ASSERT(pBuf); + Q_ASSERT(pBuf); - bool bRet = false; - char chAsc; - wchar_t chUni; - unsigned nCharSz = ((bUni)?sizeof(wchar_t):sizeof(char)); - unsigned char *pBufBase; - wchar_t *pBufUni; - unsigned char *pBufAsc; + bool bRet = false; + char chAsc; + wchar_t chUni; + uint32_t nCharSz = ((bUni)?sizeof(wchar_t):sizeof(char)); + unsigned char *pBufBase; + wchar_t *pBufUni; + unsigned char *pBufAsc; pBufBase = pBuf + nOffsetBytes; - pBufUni = (wchar_t *)pBufBase; - pBufAsc = pBufBase; - - // FIXME: Comment out the following until a cross-platform solution can be written - /* + pBufUni = (wchar_t *)pBufBase; + pBufAsc = pBufBase; #ifdef UNICODE // Create non-Unicode version of string @@ -285,32 +291,32 @@ bool CDbSigs::BufWriteStr(unsigned char *pBuf,QString strIn,unsigned nMaxBytes,b strIn.UnlockBuffer( ); #endif - unsigned nStrLen; - unsigned nChInd; - nStrLen = strIn.size(); - - for (nChInd=0;(nChIndm_qSigList; - unsigned m_nExcMmNoMkrListNum; + int32_t m_nExcMmNoMkrListNum; static const CompExcMm m_sExcMmNoMkrList[]; - unsigned m_nExcMmIsEditListNum; + int32_t m_nExcMmIsEditListNum; static const CompExcMm m_sExcMmIsEditList[]; - unsigned m_nSwIjgListNum; - - - unsigned m_nXcomSwListNum; + int32_t m_nSwIjgListNum; + int32_t m_nXcomSwListNum; QString m_strDbDir; // Database directory QStringList m_sXComSwList; diff --git a/source/DbSubmitDlg.cpp b/source/DbSubmitDlg.cpp deleted file mode 100644 index 849579d..0000000 --- a/source/DbSubmitDlg.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// DbSubmitDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "jpegsnoop.h" -#include "DbSubmitDlg.h" -#include ".\dbsubmitdlg.h" - - -// CDbSubmitDlg dialog - -IMPLEMENT_DYNAMIC(CDbSubmitDlg, CDialog) -CDbSubmitDlg::CDbSubmitDlg(CWnd* pParent /*=NULL*/) - : CDialog(CDbSubmitDlg::IDD, pParent) - , m_strSig(_T("")) - , m_strExifModel(_T("")) - , m_strExifSoftware(_T("")) - , m_strExifMake(_T("")) - , m_strQual(_T("")) - , m_strUserSoftware(_T("")) - , m_nSource(0) - , m_strNotes(_T("")) -{ -} - -CDbSubmitDlg::~CDbSubmitDlg() -{ -} - -void CDbSubmitDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Text(pDX, IDC_SIG, m_strSig); - DDX_Text(pDX, IDC_MODEL, m_strExifModel); - DDX_Text(pDX, IDC_SOFTWARE, m_strExifSoftware); - DDX_Text(pDX, IDC_MAKE, m_strExifMake); - DDX_Text(pDX, IDC_QUAL, m_strQual); - DDX_Text(pDX, IDC_USER_SOFTWARE, m_strUserSoftware); - DDX_Radio(pDX, IDC_RADIO_CAM, m_nSource); - DDX_Text(pDX, IDC_NOTES, m_strNotes); -} - - -BEGIN_MESSAGE_MAP(CDbSubmitDlg, CDialog) - ON_BN_CLICKED(IDOK, OnBnClickedOk) -END_MESSAGE_MAP() - - -// CDbSubmitDlg message handlers - -void CDbSubmitDlg::OnBnClickedOk() -{ - UpdateData(TRUE); - // If "Software" selected, then make sure title is filled in! - if (m_nSource == 1) { - if (m_strUserSoftware == _T("")) { - AfxMessageBox(_T("You indicated that this file is processed. Please enter software name.")); - return; - } - } else if (m_nSource == 0) { - // File is apparently "original from digicam" - if ((m_strExifMake == _T("???")) || (m_strExifModel == _T("???"))) { - // FIXME: - // Determine how to handle this scenario. User indicated that the file - // is "original from digicam" but there is no make / model metadata - // present. In some cases this could simply be an extracted frame - // from an AVI file (in which case the AVI container is indicated in the - // Extras field). - //AfxMessageBox("You indicated that this file is original, but Make/Model is unspecified."); - //return; - } - } - - // TODO: Add your control notification handler code here - OnOK(); -} diff --git a/source/DbSubmitDlg.h b/source/DbSubmitDlg.h deleted file mode 100644 index be43c2d..0000000 --- a/source/DbSubmitDlg.h +++ /dev/null @@ -1,58 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box that enables user to submit a new signature to the database -// -// ========================================================================== - - -#pragma once -#include "afxwin.h" - - -// CDbSubmitDlg dialog - -class CDbSubmitDlg : public CDialog -{ - DECLARE_DYNAMIC(CDbSubmitDlg) - -public: - CDbSubmitDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CDbSubmitDlg(); - -// Dialog Data - enum { IDD = IDD_DBSUBMITDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -public: - CString m_strSig; - CString m_strExifModel; - CString m_strExifSoftware; - CString m_strExifMake; - CString m_strQual; - CString m_strUserSoftware; - int m_nSource; - CString m_strNotes; - - afx_msg void OnBnClickedOk(); -}; diff --git a/source/DecodeDetailDlg.cpp b/source/DecodeDetailDlg.cpp deleted file mode 100644 index a6dceff..0000000 --- a/source/DecodeDetailDlg.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// DecodeDetailDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "DecodeDetailDlg.h" -#include ".\decodedetaildlg.h" - - -// CDecodeDetailDlg dialog - -IMPLEMENT_DYNAMIC(CDecodeDetailDlg, CDialog) -CDecodeDetailDlg::CDecodeDetailDlg(CWnd* pParent /*=NULL*/) - : CDialog(CDecodeDetailDlg::IDD, pParent) - , m_nMcuX(0) - , m_nMcuY(0) - , m_nMcuLen(0) - , m_bEn(FALSE) -{ - // Initialize the "load" values that come from - // the caller. This will generally be a coordinate - // that is passed in on the basis of a MCU click - // before opening the Detailed Decode dialog. - m_nLoadMcuX = 0; - m_nLoadMcuY = 0; - m_nLoadMcuLen = 0; -} - -CDecodeDetailDlg::~CDecodeDetailDlg() -{ -} - -void CDecodeDetailDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Text(pDX, IDC_EDIT1, m_nMcuX); - DDX_Text(pDX, IDC_EDIT2, m_nMcuY); - DDX_Text(pDX, IDC_EDIT3, m_nMcuLen); - DDX_Check(pDX, IDC_CHECK1, m_bEn); -} - - -BEGIN_MESSAGE_MAP(CDecodeDetailDlg, CDialog) - ON_BN_CLICKED(IDC_BTN_LOAD, OnBnClickedBtnLoad) -END_MESSAGE_MAP() - - -// CDecodeDetailDlg message handlers - -void CDecodeDetailDlg::OnBnClickedBtnLoad() -{ - m_nMcuX = m_nLoadMcuX; - m_nMcuY = m_nLoadMcuY; - m_nMcuLen = m_nLoadMcuLen; - m_bEn = true; - UpdateData(false); -} diff --git a/source/DecodeDetailDlg.h b/source/DecodeDetailDlg.h deleted file mode 100644 index 9bc3349..0000000 --- a/source/DecodeDetailDlg.h +++ /dev/null @@ -1,57 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box providing options for detailed scan segment decoding -// -// ========================================================================== - - -#pragma once - - -// CDecodeDetailDlg dialog - -class CDecodeDetailDlg : public CDialog -{ - DECLARE_DYNAMIC(CDecodeDetailDlg) - -public: - CDecodeDetailDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CDecodeDetailDlg(); - -// Dialog Data - enum { IDD = IDD_DECODEDETAILDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -public: - afx_msg void OnBnClickedBtnLoad(); - - UINT m_nMcuX; - UINT m_nMcuY; - UINT m_nMcuLen; - BOOL m_bEn; - - UINT m_nLoadMcuX; - UINT m_nLoadMcuY; - UINT m_nLoadMcuLen; -}; diff --git a/source/DecodeDicom.cpp b/source/DecodeDicom.cpp index a516a46..081bf9c 100644 --- a/source/DecodeDicom.cpp +++ b/source/DecodeDicom.cpp @@ -1,878 +1,881 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - - -#include "stdafx.h" - -#include "DecodeDicom.h" -#include "snoop.h" -#include "JPEGsnoop.h" // for m_pAppConfig get - -#include "WindowBuf.h" - -// Do we want to display extended DICOM tag info? -//#ifdef DICOM_TAG_EXTENDED - - -// Forward declarations -struct tsDicomTag asDicomTags[]; -struct tsDicomTagSpec asTagSpecial[]; - -CDecodeDicom::CDecodeDicom(CwindowBuf* pWBuf,CDocLog* pLog) -{ - // Save copies of class pointers - m_pWBuf = pWBuf; - m_pLog = pLog; - - // Ideally this would be passed by constructor, but simply access - // directly for now. - CJPEGsnoopApp* pApp; - pApp = (CJPEGsnoopApp*)AfxGetApp(); - m_pAppConfig = pApp->m_pAppConfig; - - Reset(); -} - -void CDecodeDicom::Reset() -{ - m_bDicom = false; - m_bJpegEncap = false; - m_bJpegEncapOffsetNext = false; -} - - -CDecodeDicom::~CDecodeDicom(void) -{ -} - - -// Provide a short-hand alias for the m_pWBuf buffer -// INPUT: -// - offset File offset to read from -// - bClean Forcibly disables any redirection to Fake DHT table -// -// POST: -// - m_pLog -// -// RETURN: -// - Byte from file -// -BYTE CDecodeDicom::Buf(unsigned long offset,bool bClean=false) -{ - return m_pWBuf->Buf(offset,bClean); -} - - - - -bool CDecodeDicom::GetTagHeader(unsigned long nPos,tsTagDetail &sTagDetail) -{ - unsigned nVR = 0; - CString strError; - unsigned nTagGroup; - unsigned nTagElement; - CString strTagName = _T(""); - - unsigned nLen = 0; - unsigned nOffset = 0; - CString strVR = _T(""); - - bool bTagOk = false; - CString strTag = _T(""); - - bool bVrExplicit; - bool bLen4B; - - bool bTagIsJpeg; - unsigned long nPosJpeg; - bool bTagIsOffsetHdr; - - // Find the tag - nTagGroup = m_pWBuf->BufX(nPos+0,2,true); - nTagElement = m_pWBuf->BufX(nPos+2,2,true); - - bool bFoundTag; - unsigned nFldInd = 0; - bFoundTag = FindTag(nTagGroup,nTagElement,nFldInd); - if (!bFoundTag) { - // Check for group length entry - // FIXME: - // Reference: Part 5, Section 7.2 - if (nTagElement == 0x0000) { - strTagName.Format(_T("Group Length (Group=%04X)"),nTagGroup); - bTagOk = true; - } else { - /* - strError.Format(_T("ERROR: Unknown Tag ID (%04X,%04X) @ 0x%08X"),nTagGroup,nTagElement,nPos); - m_pLog->AddLineErr(strError); - */ - strTagName.Format(_T("??? (%04X,%04X)"),nTagGroup,nTagElement); - bTagOk = false; - } - } else { - strTagName = asDicomTags[nFldInd].strTagName; - bTagOk = true; - } - - - // Check for zeros in place of VR. This might hint at implicit VR - // FIXME - if (m_pWBuf->BufX(nPos+4,2,true) == 0) { - //unsigned nBad=1; - } - strVR = m_pWBuf->BufReadStrn(nPos+4,2); - nVR = m_pWBuf->BufX(nPos+4,2,false); - - - // Value Representation (VR) - // Reference: Part 5, Section 6.2 - bVrExplicit = false; - bLen4B = false; - - switch (nVR) { - - // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" - case 'AE': - case 'AS': - case 'AT': - case 'CS': - case 'DA': - case 'DS': - case 'DT': - case 'FL': - case 'FD': - case 'IS': - case 'LO': - case 'LT': - //case 'OB': - //case 'OF': - //case 'OW': - case 'PN': - case 'SH': - case 'SL': - //case 'SQ': - case 'SS': - case 'ST': - case 'TM': - case 'UI': - case 'UL': - //case 'UN': - case 'US': - //case 'UT': - bVrExplicit = true; - bLen4B = false; - break; - - // Definition of VRs that have 4B length - // Reference (informal): http://cran.r-project.org/web/packages/oro.dicom/vignettes/dicom.pdf - // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" - case 'OB': - case 'OF': - case 'OW': - case 'SQ': - case 'UN': - bVrExplicit = true; - bLen4B = true; - break; - - // FIXME: - // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" - case 'UT': - bVrExplicit = true; - bLen4B = true; - break; - - default: - // FIXME: - // I have seen some documentation from others that say if VR is not - // known then it is implicit VR. However, this doesn't seem - // accurate to me since some implicit VRs could have length values - // that just happen to alias with a known VR code above! - bVrExplicit = false; - bLen4B = true; //FIXME - break; - } - - // Force some known implicit VRs to be handled this way - if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE000)) { bVrExplicit = false; bLen4B = true; } - if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE00D)) { bVrExplicit = false; bLen4B = true; } - if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE0DD)) { bVrExplicit = false; bLen4B = true; } - - - if (bVrExplicit) { - if (!bLen4B) { - // 2B length - nLen = m_pWBuf->BufX(nPos+6,2,true); - nOffset = 8; - } else { - // 4B length - // - Skip over 2B field (should be 0) - nLen = m_pWBuf->BufX(nPos+6,2,true); - ASSERT(nLen == 0); - nLen = m_pWBuf->BufX(nPos+8,4,true); - nOffset = 12; - } - } else { - // Implicit VR - strVR = _T("??"); - // 4B length - nLen = m_pWBuf->BufX(nPos+4,4,true); - nOffset = 8; - } - - - // Handle Items & Sequences (Image Fragment?) - bTagIsJpeg = false; - bTagIsOffsetHdr = false; - if (!m_bJpegEncap) { - // Not in a delimited sequence - // FIXME: Handle special case of sequence of fragments with offset table (7FE0,0010) - // Ref: Part 7, Section A.4, Table A.4-1 - if ((nTagGroup == 0x7FE0) && (nTagElement == 0x0010)) { - // Start of Pixel Data - if (nLen == 0xFFFFFFFF) { - // Undefined length. So expect encapsulated data with delimiter - // Expect we aren't already in encapsulated mode - ASSERT(m_bJpegEncap == false); - // Indicate we are now starting an encapsulation - m_bJpegEncap = true; - // Next tag should be offset header - m_bJpegEncapOffsetNext = true; - } else { - // FIXME: handle native type - ASSERT(false); - } - } - } else { - // We are in a sequence - if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE000)) { - // Is this an offset header? - if (m_bJpegEncapOffsetNext) { - ASSERT(nTagGroup == 0xFFFE); - ASSERT(nTagElement == 0xE000); - // Clear next flag since we've handled it - m_bJpegEncapOffsetNext = false; - // This is an offset header - bTagIsOffsetHdr = true; - } else { - // Not an offset header, so process it as embedded JPEG - bTagIsJpeg = true; - } - } else if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE0DD)) { - // Sequence delimiter - m_bJpegEncap = false; - } - } - - if (bTagIsJpeg) { - nPosJpeg = nPos+8; - } else { - // Indicate not a JPEG tag - nPosJpeg = 0; - } - - - -#ifdef DICOM_TAG_EXTENDED - // Extended tag info - if (bTagIsOffsetHdr) { - strTag.Format(_T("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X [OffsetHdr] %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName); - } else if (bTagIsJpeg) { - strTag.Format(_T("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X [JPEG] %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName); - } else { - strTag.Format(_T("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName); - } -#else - // Simple tag info - strTag.Format(_T("%s"),(LPCTSTR)strTagName); -#endif - - // Assign struct - sTagDetail.nTagGroup = nTagGroup; - sTagDetail.nTagElement = nTagElement; - sTagDetail.strVR = strVR; - sTagDetail.nLen = nLen; - sTagDetail.nOffset = nOffset; - - sTagDetail.bVrExplicit = bVrExplicit; - sTagDetail.bLen4B = bLen4B; - - sTagDetail.bTagOk = bTagOk; - sTagDetail.strTag = strTag; - //sTagDetail.bValOk = bValOk; - //sTagDetail.strVal = strDesc; - - sTagDetail.bTagIsJpeg = bTagIsJpeg; - sTagDetail.nPosJpeg = nPosJpeg; - //sTagDetail.bTagIsOffsetHdr = bTagIsOffsetHdr; - - return true; -} - -#if 0 -bool CDecodeDicom::DecodeTagHeader(unsigned long nPos,CString &strTag,CString &strVR,unsigned &nLen,unsigned &nOffset,unsigned long &nPosJpeg) -{ - unsigned nVR = 0; - CString strError; - unsigned nTagGroup; - unsigned nTagElement; - CString strTagName = _T(""); - - // Assign defaults - strTag = _T(""); - strVR = _T(""); - nLen = 0; - nOffset = 0; - - // Find the tag - nTagGroup = m_pWBuf->BufX(nPos+0,2,true); - nTagElement = m_pWBuf->BufX(nPos+2,2,true); - - bool bFoundTag; - unsigned nFldInd = 0; - bFoundTag = FindTag(nTagGroup,nTagElement,nFldInd); - - if (!bFoundTag) { - // Check for group length entry - // FIXME: - // Reference: Part 5, Section 7.2 - if (nTagElement == 0x0000) { - strTagName.Format(_T("Group Length (Group=%04X)"),nTagGroup); - } else { - strError.Format(_T("ERROR: Unknown Tag ID (%04X,%04X) @ 0x%08X"),nTagGroup,nTagElement,nPos); - m_pLog->AddLineErr(strError); - strTagName.Format(_T("??? (%04X,%04X)"),nTagGroup,nTagElement); - } - } else { - strTagName = asDicomTags[nFldInd].strTagName; - } - - - // Check for zeros in place of VR. This might hint at implicit VR - // FIXME - if (m_pWBuf->BufX(nPos+4,2,true) == 0) { - unsigned nBad=1; - } - strVR = m_pWBuf->BufReadStrn(nPos+4,2); - nVR = m_pWBuf->BufX(nPos+4,2,false); - - - // Value Representation (VR) - // Reference: Part 5, Section 6.2 - bool bVrExplicit = false; - bool bVrLen4B = false; - - switch (nVR) { - - // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" - case 'AE': - case 'AS': - case 'AT': - case 'CS': - case 'DA': - case 'DS': - case 'DT': - case 'FL': - case 'FD': - case 'IS': - case 'LO': - case 'LT': - //case 'OB': - //case 'OF': - //case 'OW': - case 'PN': - case 'SH': - case 'SL': - //case 'SQ': - case 'SS': - case 'ST': - case 'TM': - case 'UI': - case 'UL': - //case 'UN': - case 'US': - //case 'UT': - bVrExplicit = true; - bVrLen4B = false; - break; - - // Definition of VRs that have 4B length - // Reference (informal): http://cran.r-project.org/web/packages/oro.dicom/vignettes/dicom.pdf - // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" - case 'OB': - case 'OF': - case 'OW': - case 'SQ': - case 'UN': - bVrExplicit = true; - bVrLen4B = true; - break; - - // FIXME: - // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" - case 'UT': - bVrExplicit = true; - bVrLen4B = true; - break; - - default: - // FIXME: - // I have seen some documentation from others that say if VR is not - // known then it is implicit VR. However, this doesn't seem - // accurate to me since some implicit VRs could have length values - // that just happen to alias with a known VR code above! - bVrExplicit = false; - bVrLen4B = true; //FIXME - break; - } - - // Force some known implicit VRs to be handled this way - if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE000)) { bVrExplicit = false; bVrLen4B = true; } - if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE00D)) { bVrExplicit = false; bVrLen4B = true; } - if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE0DD)) { bVrExplicit = false; bVrLen4B = true; } - - - if (bVrExplicit) { - if (!bVrLen4B) { - // 2B length - nLen = m_pWBuf->BufX(nPos+6,2,true); - nOffset = 8; - } else { - // 4B length - // - Skip over 2B field (should be 0) - nLen = m_pWBuf->BufX(nPos+6,2,true); - ASSERT(nLen == 0); - nLen = m_pWBuf->BufX(nPos+8,4,true); - nOffset = 12; - } - } else { - // Implicit VR - strVR = _T("??"); - // 4B length - nLen = m_pWBuf->BufX(nPos+4,4,true); - nOffset = 8; - } - - - // Handle Items & Sequences (Image Fragment?) - bool bTagIsJpeg = false; - bool bTagIsOffsetHdr = false; - if (!m_bJpegEncap) { - // Not in a delimited sequence - // FIXME: Handle special case of sequence of fragments with offset table (7FE0,0010) - // Ref: Part 7, Section A.4, Table A.4-1 - if ((nTagGroup == 0x7FE0) && (nTagElement == 0x0010)) { - // Start of Pixel Data - if (nLen == 0xFFFFFFFF) { - // Undefined length. So expect encapsulated data with delimiter - // Expect we aren't already in encapsulated mode - ASSERT(m_bJpegEncap == false); - // Indicate we are now starting an encapsulation - m_bJpegEncap = true; - // Next tag should be offset header - m_bJpegEncapOffsetNext = true; - } else { - // FIXME: handle native type - ASSERT(false); - } - } - } else { - // We are in a sequence - if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE000)) { - // Is this an offset header? - if (m_bJpegEncapOffsetNext) { - ASSERT(nTagGroup == 0xFFFE); - ASSERT(nTagElement == 0xE000); - // Clear next flag since we've handled it - m_bJpegEncapOffsetNext = false; - // This is an offset header - bTagIsOffsetHdr = true; - } else { - // Not an offset header, so process it as embedded JPEG - bTagIsJpeg = true; - } - } else if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE0DD)) { - // Sequence delimiter - m_bJpegEncap = false; - } - } - - - -#ifdef DICOM_TAG_EXTENDED - // Extended tag info - if (bTagIsOffsetHdr) { - strTag.Format(_T("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X [OffsetHdr] %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName); - } else if (bTagIsJpeg) { - strTag.Format(_T("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X [JPEG] %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName); - } else { - strTag.Format(_T("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName); - } -#else - // Simple tag info - strTag.Format(_T("%s"),strTagName); -#endif - - if (bTagIsJpeg) { - nPosJpeg = nPos+8; - } else { - // Indicate not a JPEG tag - nPosJpeg = 0; - } - - return true; -} -#endif - -// Determine if the file is a DICOM -// If so, parse the headers. Generally want to start at start of file (nPos=0). -bool CDecodeDicom::DecodeDicom(unsigned long nPos,unsigned long nPosFileEnd,unsigned long &nPosJpeg) -{ - unsigned nLen; - unsigned nOffset; - CString strTag; - CString strSig; - CString strVR; - - - m_bDicom = false; - - - // Skip File Preamble - nPos += 128; - - // DICOM Prefix - strSig = m_pWBuf->BufReadStrn(nPos,4); - if (strSig == _T("DICM")) { - m_bDicom = true; - m_pLog->AddLine(_T("")); - m_pLog->AddLineHdr(_T("*** DICOM File Decoding ***")); - m_pLog->AddLine(_T("Decoding DICOM format...")); - m_pLog->AddLine(_T("")); - } else { - return false; - } - nPos+=4; - - bool bDone = false; - - // If we get here, then we have found the header signature - // FIXME: Handle proper termination! - if (nPos >= nPosFileEnd) { - bDone = true; - } - - //bool bFoundJpeg = false; - unsigned long nPosJpegFound = 0; - tsTagDetail sTagDetail; - while (!bDone) { - - sTagDetail.Reset(); - GetTagHeader(nPos,sTagDetail); - - // Fetch results - nLen = sTagDetail.nLen; - nPosJpegFound = sTagDetail.nPosJpeg; - strTag = sTagDetail.strTag; - strVR = sTagDetail.strVR; - nOffset = sTagDetail.nOffset; - - // Advance the file position - nPos += sTagDetail.nOffset; - - // Process the field - if (nLen == 0xFFFFFFFF) { - // Detect "invalid length" - // In these cases we are probably dependent upon delimiters - // so we don't have any real content in this tag. - // - // Example: E:\JPEG\JPEGsnoop Testcases\DICOM_samples\24-bit JPEG Lossy Color.dcm - // Offset: 0x508 - nLen = 0; - } - - if (nPosJpegFound != 0) { - // Only capture first image offset - if (nPosJpeg == 0) { - nPosJpeg = nPosJpegFound; - } - } - - - // See if this is an enumerated value - // If not, just report as hex for now - - // Now determine enum value - CString strValTrunc = _T(""); - CString strDesc = _T(""); - bool bIsEnum = false; - strValTrunc = m_pWBuf->BufReadStrn(nPos,200); - bIsEnum = LookupEnum(sTagDetail.nTagGroup,sTagDetail.nTagElement,strValTrunc,strDesc); - if (bIsEnum) { - ReportFldStrEnc(1,sTagDetail.strTag,strDesc,strValTrunc); - } else { - ReportFldHex(1,strTag,nPos,nLen); - } - - nPos += nLen; - - if (nPos >= nPosFileEnd) { - bDone = true; - } - - } // bDone - - - return true; - -} - -// Create indent string -// - Returns a sequence of spaces according to the indent level -CString CDecodeDicom::ParseIndent(unsigned nIndent) -{ - CString strIndent = _T(""); - for (unsigned nInd=0;nIndAddLine(strLine); -} - -// Display a formatted string field with encoded value -// - Report the value with the field name (strField) and current indent level (nIndent) -void CDecodeDicom::ReportFldStrEnc(unsigned nIndent,CString strField,CString strVal,CString strEncVal) -{ - CString strIndent; - CString strLine; - - strIndent = ParseIndent(nIndent); - strLine.Format(_T("%s%-50s = %s \"%s\""),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strEncVal,(LPCTSTR)strVal); - m_pLog->AddLine(strLine); -} - -// Locate a field ID in the constant Meta Tag array -// -// INPUT: -// - nTagGroup = Meta Tag (High) -// - nTagElement = Meta Tag (Low) -// OUTPUT: -// - nFldInd = Index into asDicomTags[] array -// RETURN: -// - Returns true if ID was found in array -// NOTE: -// - The constant struct array depends on DICOM_T_END as a terminator for the list -// -bool CDecodeDicom::FindTag(unsigned nTagGroup,unsigned nTagElement,unsigned &nFldInd) -{ - unsigned nInd=0; - bool bDone=false; - bool bFound=false; - while (!bDone) { - if (asDicomTags[nInd].eTagType == DICOM_T_END) { - bDone = true; - } else { - unsigned nFoundTagH = asDicomTags[nInd].nTagGroup; - unsigned nFoundTagL = asDicomTags[nInd].nTagElement; - if ((nTagGroup == nFoundTagH) && (nTagElement == nFoundTagL)) { - // Matched - bDone = true; - bFound = true; - } else { - nInd++; - } - - } - } - if (bFound) { - nFldInd = nInd; - } - return bFound; -} - - - -// -// Display a formatted hexadecimal field -// - Report the value with the field name (strField) and current indent level (nIndent) -// - Depending on the length of the buffer, either report the hex value in-line with -// the field name or else start a new row and begin a hex dump -// - Also report the ASCII representation alongside the hex dump -// -// INPUT: -// - nIndent = Current indent level for reporting -// - strField = Field name -// - nPosStart = Field byte array file position start -// - nLen = Field byte array length -// -void CDecodeDicom::ReportFldHex(unsigned nIndent,CString strField,unsigned long nPosStart,unsigned nLen) -{ - CString strIndent; - unsigned nByte; - CString strPrefix; - CString strByteHex; - CString strByteAsc; - CString strValHex; - CString strValAsc; - CString strLine; - - strIndent = ParseIndent(nIndent); - - if (nLen == 0) { - // Print out the header row, but no data will be shown - strLine.Format(_T("%s%-50s = "),(LPCTSTR)strIndent,(LPCTSTR)strField); - m_pLog->AddLine(strLine); - // Nothing to report, exit now - return; - } else if (nLen <= DC_HEX_MAX_INLINE) { - // Define prefix for row - strPrefix.Format(_T("%s%-50s = "),(LPCTSTR)strIndent,(LPCTSTR)strField); - } else { -#if 0 - // Print out header row - strLine.Format(_T("%s%-50s ="),(LPCTSTR)strIndent,(LPCTSTR)strField); - m_pLog->AddLine(strLine); - // Define prefix for next row - //strPrefix.Format(_T("%s"),(LPCTSTR)strIndent); - strPrefix.Format(_T("%s%-50s "),(LPCTSTR)strIndent,_T("")); -#else - // Define prefix for row - //FIXME: Only report field on first row - strPrefix.Format(_T("%s%-50s = "),(LPCTSTR)strIndent,(LPCTSTR)strField); -#endif - } - - - // Build up the hex string - // Limit to DC_HEX_TOTAL bytes - unsigned nRowOffset = 0; - bool bDone = false; - unsigned nLenClip; - nLenClip = min(nLen,DC_HEX_TOTAL); - strValHex = _T(""); - strValAsc = _T(""); - while (!bDone) { - // Have we reached the end of the data we wish to display? - if (nRowOffset>=nLenClip) { - bDone = true; - } else { - // Reset the cumulative hex/ascii value strings - strValHex = _T(""); - strValAsc = _T(""); - // Build the hex/ascii value strings - for (unsigned nInd=0;nIndBuf(nPosStart+nRowOffset+nInd); - strByteHex.Format(_T("%02X "),nByte); - // Only display printable characters - if (isprint(nByte)) { - strByteAsc.Format(_T("%c"),nByte); - } else { - strByteAsc = _T("."); - } - } else { - // Pad out to end of row - strByteHex.Format(_T(" ")); - strByteAsc = _T(" "); - } - // Build up the strings - strValHex += strByteHex; - strValAsc += strByteAsc; - } - - // Generate the line with Hex and ASCII representations - strLine.Format(_T("%s | 0x%s | %s"),(LPCTSTR)strPrefix,(LPCTSTR)strValHex,(LPCTSTR)strValAsc); - m_pLog->AddLine(strLine); - - // Now increment file offset - nRowOffset += DC_HEX_MAX_ROW; - } - } - - // If we had to clip the display length, then show ellipsis now - if (nLenClip < nLen) { - strLine.Format(_T("%s | ..."),(LPCTSTR)strPrefix); - m_pLog->AddLine(strLine); - } - - -} - -// Display a formatted enumerated type field -// - Look up enumerated constant (nVal) for the given field (eEnumField) -// - Report the value with the field name (strField) and current indent level (nIndent) -void CDecodeDicom::ReportFldEnum(unsigned nIndent,CString strField,unsigned nTagGroup,unsigned nTagElement,CString strVal) -{ - CString strIndent; - CString strDesc; - CString strLine; - bool bFound; - - strIndent = ParseIndent(nIndent); - - bFound = LookupEnum(nTagGroup,nTagElement,strVal,strDesc); - if (bFound) { - strLine.Format(_T("%s%-50s = %s"),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strDesc); - m_pLog->AddLine(strLine); - } else { - ASSERT(false); - } -} - -// Look up the enumerated constant (nVal) for the specified field (eEnumField) -// - Returns "" if the field wasn't found -bool CDecodeDicom::LookupEnum(unsigned nTagGroup,unsigned nTagElement,CString strVal,CString &strDesc) -{ - // Find the enum value - bool bFound = false; - bool bDone = false; - unsigned nEnumInd=0; - while (!bDone) { - if ( (asTagSpecial[nEnumInd].nTagGroup == nTagGroup) && (asTagSpecial[nEnumInd].nTagElement == nTagElement) ) { - if (asTagSpecial[nEnumInd].strVal == strVal) { - bDone = true; - bFound = true; - strDesc = asTagSpecial[nEnumInd].strDefinition; - } - } - if (asTagSpecial[nEnumInd].strVal == _T("")) { - bDone = true; - } - if (!bDone) { - nEnumInd++; - } - } - return bFound; -} - -// =============================================================================== -// CONSTANTS -// =============================================================================== - +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2017 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + + + +//#include "stdafx.h" + +#include + +#include "DecodeDicom.h" +#include "snoop.h" +#include "JPEGsnoop.h" // for m_pAppConfig get + +#include "WindowBuf.h" + + +// Do we want to display extended DICOM tag info? +//#ifdef DICOM_TAG_EXTENDED + + +// Forward declarations +extern struct tsDicomTag asDicomTags[]; +extern struct tsDicomTagSpec asTagSpecial[]; + +CDecodeDicom::CDecodeDicom(CwindowBuf* pWBuf,CDocLog* pLog) +{ + // Save copies of class pointers + m_pWBuf = pWBuf; + m_pLog = pLog; + + // Ideally this would be passed by constructor, but simply access + // directly for now. + CJPEGsnoopApp* pApp; +// pApp = (CJPEGsnoopApp*)AfxGetApp(); + m_pAppConfig = pApp->m_pAppConfig; + + Reset(); +} + +void CDecodeDicom::Reset() +{ + m_bDicom = false; + m_bJpegEncap = false; + m_bJpegEncapOffsetNext = false; +} + + +CDecodeDicom::~CDecodeDicom(void) +{ +} + + +// Provide a short-hand alias for the m_pWBuf buffer +// INPUT: +// - offset File offset to read from +// - bClean Forcibly disables any redirection to Fake DHT table +// +// POST: +// - m_pLog +// +// RETURN: +// - Byte from file +// +quint8 CDecodeDicom::Buf(unsigned long offset,bool bClean=false) +{ + return m_pWBuf->Buf(offset,bClean); +} + + + + +bool CDecodeDicom::GetTagHeader(unsigned long nPos,tsTagDetail &sTagDetail) +{ + unsigned nVR = 0; + QString strError; + quint32 nTagGroup; + quint32 nTagElement; + QString strTagName = ""; + + unsigned nLen = 0; + unsigned nOffset = 0; + QString strVR = ""; + + bool bTagOk = false; + QString strTag = ""; + + bool bVrExplicit; + bool bLen4B; + + bool bTagIsJpeg; + unsigned long nPosJpeg; + bool bTagIsOffsetHdr; + + // Find the tag + nTagGroup = m_pWBuf->BufX(nPos+0,2,true); + nTagElement = m_pWBuf->BufX(nPos+2,2,true); + + bool bFoundTag; + unsigned nFldInd = 0; + bFoundTag = FindTag(nTagGroup,nTagElement,nFldInd); + + if (!bFoundTag) { + // Check for group length entry + // FIXME: + // Reference: Part 5, Section 7.2 + if (nTagElement == 0x0000) { + strTagName.arg(nTagGroup, 4, 16, QChar('0')); // Format("Group Length (Group=%04X)"),nTagGroup; + bTagOk = true; + } else { + /* + strError.Format("ERROR: Unknown Tag ID (%04X,%04X) @ 0x%08X"),nTagGroup,nTagElement,nPos; + m_pLog->AddLineErr(strError); + */ + strTagName.arg(nTagGroup, 4, 16, QChar('0')).arg(nTagElement, 4, 16, QChar('0')); // .Format("??? (%04X,%04X)"),nTagGroup,nTagElement; + bTagOk = false; + } + } else { + strTagName = asDicomTags[nFldInd].strTagName; + bTagOk = true; + } + + + // Check for zeros in place of VR. This might hint at implicit VR + // FIXME + if (m_pWBuf->BufX(nPos+4,2,true) == 0) { + //unsigned nBad=1; + } + strVR = m_pWBuf->BufReadStrn(nPos+4,2); + nVR = m_pWBuf->BufX(nPos+4,2,false); + + + // Value Representation (VR) + // Reference: Part 5, Section 6.2 + bVrExplicit = false; + bLen4B = false; + + switch (nVR) { + + // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" + case 'AE': + case 'AS': + case 'AT': + case 'CS': + case 'DA': + case 'DS': + case 'DT': + case 'FL': + case 'FD': + case 'IS': + case 'LO': + case 'LT': + //case 'OB': + //case 'OF': + //case 'OW': + case 'PN': + case 'SH': + case 'SL': + //case 'SQ': + case 'SS': + case 'ST': + case 'TM': + case 'UI': + case 'UL': + //case 'UN': + case 'US': + //case 'UT': + bVrExplicit = true; + bLen4B = false; + break; + + // Definition of VRs that have 4B length + // Reference (informal): http://cran.r-project.org/web/packages/oro.dicom/vignettes/dicom.pdf + // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" + case 'OB': + case 'OF': + case 'OW': + case 'SQ': + case 'UN': + bVrExplicit = true; + bLen4B = true; + break; + + // FIXME: + // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" + case 'UT': + bVrExplicit = true; + bLen4B = true; + break; + + default: + // FIXME: + // I have seen some documentation from others that say if VR is not + // known then it is implicit VR. However, this doesn't seem + // accurate to me since some implicit VRs could have length values + // that just happen to alias with a known VR code above! + bVrExplicit = false; + bLen4B = true; //FIXME + break; + } + + // Force some known implicit VRs to be handled this way + if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE000)) { bVrExplicit = false; bLen4B = true; } + if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE00D)) { bVrExplicit = false; bLen4B = true; } + if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE0DD)) { bVrExplicit = false; bLen4B = true; } + + + if (bVrExplicit) { + if (!bLen4B) { + // 2B length + nLen = m_pWBuf->BufX(nPos+6,2,true); + nOffset = 8; + } else { + // 4B length + // - Skip over 2B field (should be 0) + nLen = m_pWBuf->BufX(nPos+6,2,true); + Q_ASSERT(nLen == 0); + nLen = m_pWBuf->BufX(nPos+8,4,true); + nOffset = 12; + } + } else { + // Implicit VR + strVR = "??"; + // 4B length + nLen = m_pWBuf->BufX(nPos+4,4,true); + nOffset = 8; + } + + + // Handle Items & Sequences (Image Fragment?) + bTagIsJpeg = false; + bTagIsOffsetHdr = false; + if (!m_bJpegEncap) { + // Not in a delimited sequence + // FIXME: Handle special case of sequence of fragments with offset table (7FE0,0010) + // Ref: Part 7, Section A.4, Table A.4-1 + if ((nTagGroup == 0x7FE0) && (nTagElement == 0x0010)) { + // Start of Pixel Data + if (nLen == 0xFFFFFFFF) { + // Undefined length. So expect encapsulated data with delimiter + // Expect we aren't already in encapsulated mode + Q_ASSERT(m_bJpegEncap == false); + // Indicate we are now starting an encapsulation + m_bJpegEncap = true; + // Next tag should be offset header + m_bJpegEncapOffsetNext = true; + } else { + // FIXME: handle native type + Q_ASSERT(false); + } + } + } else { + // We are in a sequence + if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE000)) { + // Is this an offset header? + if (m_bJpegEncapOffsetNext) { + Q_ASSERT(nTagGroup == 0xFFFE); + Q_ASSERT(nTagElement == 0xE000); + // Clear next flag since we've handled it + m_bJpegEncapOffsetNext = false; + // This is an offset header + bTagIsOffsetHdr = true; + } else { + // Not an offset header, so process it as embedded JPEG + bTagIsJpeg = true; + } + } else if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE0DD)) { + // Sequence delimiter + m_bJpegEncap = false; + } + } + + if (bTagIsJpeg) { + nPosJpeg = nPos+8; + } else { + // Indicate not a JPEG tag + nPosJpeg = 0; + } + + + +#ifdef DICOM_TAG_EXTENDED + // Extended tag info + if (bTagIsOffsetHdr) { + strTag.Format("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X [OffsetHdr] %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName; + } else if (bTagIsJpeg) { + strTag.Format("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X [JPEG] %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName; + } else { + strTag.Format("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName; + } +#else + // Simple tag info + strTag = strTagName; +#endif + + // Assign struct + sTagDetail.nTagGroup = nTagGroup; + sTagDetail.nTagElement = nTagElement; + sTagDetail.strVR = strVR; + sTagDetail.nLen = nLen; + sTagDetail.nOffset = nOffset; + + sTagDetail.bVrExplicit = bVrExplicit; + sTagDetail.bLen4B = bLen4B; + + sTagDetail.bTagOk = bTagOk; + sTagDetail.strTag = strTag; + //sTagDetail.bValOk = bValOk; + //sTagDetail.strVal = strDesc; + + sTagDetail.bTagIsJpeg = bTagIsJpeg; + sTagDetail.nPosJpeg = nPosJpeg; + //sTagDetail.bTagIsOffsetHdr = bTagIsOffsetHdr; + + return true; +} + +#if 0 +bool CDecodeDicom::DecodeTagHeader(unsigned long nPos,QString &strTag,QString &strVR,unsigned &nLen,unsigned &nOffset,unsigned long &nPosJpeg) +{ + unsigned nVR = 0; + QString strError; + unsigned nTagGroup; + unsigned nTagElement; + QString strTagName = ""; + + // Assign defaults + strTag = ""; + strVR = ""; + nLen = 0; + nOffset = 0; + + // Find the tag + nTagGroup = m_pWBuf->BufX(nPos+0,2,true); + nTagElement = m_pWBuf->BufX(nPos+2,2,true); + + bool bFoundTag; + unsigned nFldInd = 0; + bFoundTag = FindTag(nTagGroup,nTagElement,nFldInd); + + if (!bFoundTag) { + // Check for group length entry + // FIXME: + // Reference: Part 5, Section 7.2 + if (nTagElement == 0x0000) { + strTagName.Format("Group Length (Group=%04X)"),nTagGroup; + } else { + strError.Format("ERROR: Unknown Tag ID (%04X,%04X) @ 0x%08X"),nTagGroup,nTagElement,nPos; + m_pLog->AddLineErr(strError); + strTagName.Format("??? (%04X,%04X)"),nTagGroup,nTagElement; + } + } else { + strTagName = asDicomTags[nFldInd].strTagName; + } + + + // Check for zeros in place of VR. This might hint at implicit VR + // FIXME + if (m_pWBuf->BufX(nPos+4,2,true) == 0) { + unsigned nBad=1; + } + strVR = m_pWBuf->BufReadStrn(nPos+4,2); + nVR = m_pWBuf->BufX(nPos+4,2,false); + + + // Value Representation (VR) + // Reference: Part 5, Section 6.2 + bool bVrExplicit = false; + bool bVrLen4B = false; + + switch (nVR) { + + // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" + case 'AE': + case 'AS': + case 'AT': + case 'CS': + case 'DA': + case 'DS': + case 'DT': + case 'FL': + case 'FD': + case 'IS': + case 'LO': + case 'LT': + //case 'OB': + //case 'OF': + //case 'OW': + case 'PN': + case 'SH': + case 'SL': + //case 'SQ': + case 'SS': + case 'ST': + case 'TM': + case 'UI': + case 'UL': + //case 'UN': + case 'US': + //case 'UT': + bVrExplicit = true; + bVrLen4B = false; + break; + + // Definition of VRs that have 4B length + // Reference (informal): http://cran.r-project.org/web/packages/oro.dicom/vignettes/dicom.pdf + // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" + case 'OB': + case 'OF': + case 'OW': + case 'SQ': + case 'UN': + bVrExplicit = true; + bVrLen4B = true; + break; + + // FIXME: + // Ref: Part 5, Section 7.1.2 "Data Element Structure with Explicit VR" + case 'UT': + bVrExplicit = true; + bVrLen4B = true; + break; + + default: + // FIXME: + // I have seen some documentation from others that say if VR is not + // known then it is implicit VR. However, this doesn't seem + // accurate to me since some implicit VRs could have length values + // that just happen to alias with a known VR code above! + bVrExplicit = false; + bVrLen4B = true; //FIXME + break; + } + + // Force some known implicit VRs to be handled this way + if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE000)) { bVrExplicit = false; bVrLen4B = true; } + if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE00D)) { bVrExplicit = false; bVrLen4B = true; } + if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE0DD)) { bVrExplicit = false; bVrLen4B = true; } + + + if (bVrExplicit) { + if (!bVrLen4B) { + // 2B length + nLen = m_pWBuf->BufX(nPos+6,2,true); + nOffset = 8; + } else { + // 4B length + // - Skip over 2B field (should be 0) + nLen = m_pWBuf->BufX(nPos+6,2,true); + Q_ASSERT(nLen == 0); + nLen = m_pWBuf->BufX(nPos+8,4,true); + nOffset = 12; + } + } else { + // Implicit VR + strVR = "??"; + // 4B length + nLen = m_pWBuf->BufX(nPos+4,4,true); + nOffset = 8; + } + + + // Handle Items & Sequences (Image Fragment?) + bool bTagIsJpeg = false; + bool bTagIsOffsetHdr = false; + if (!m_bJpegEncap) { + // Not in a delimited sequence + // FIXME: Handle special case of sequence of fragments with offset table (7FE0,0010) + // Ref: Part 7, Section A.4, Table A.4-1 + if ((nTagGroup == 0x7FE0) && (nTagElement == 0x0010)) { + // Start of Pixel Data + if (nLen == 0xFFFFFFFF) { + // Undefined length. So expect encapsulated data with delimiter + // Expect we aren't already in encapsulated mode + Q_ASSERT(m_bJpegEncap == false); + // Indicate we are now starting an encapsulation + m_bJpegEncap = true; + // Next tag should be offset header + m_bJpegEncapOffsetNext = true; + } else { + // FIXME: handle native type + Q_ASSERT(false); + } + } + } else { + // We are in a sequence + if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE000)) { + // Is this an offset header? + if (m_bJpegEncapOffsetNext) { + Q_ASSERT(nTagGroup == 0xFFFE); + Q_ASSERT(nTagElement == 0xE000); + // Clear next flag since we've handled it + m_bJpegEncapOffsetNext = false; + // This is an offset header + bTagIsOffsetHdr = true; + } else { + // Not an offset header, so process it as embedded JPEG + bTagIsJpeg = true; + } + } else if ((nTagGroup == 0xFFFE) && (nTagElement == 0xE0DD)) { + // Sequence delimiter + m_bJpegEncap = false; + } + } + + + +#ifdef DICOM_TAG_EXTENDED + // Extended tag info + if (bTagIsOffsetHdr) { + strTag.Format("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X [OffsetHdr] %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName; + } else if (bTagIsJpeg) { + strTag.Format("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X [JPEG] %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName; + } else { + strTag.Format("@ 0x%08X (%04X,%04X) VR=[%2s] Len=0x%08X %s"),nPos,nTagGroup,nTagElement,strVR,nLen,strTagName; + } +#else + // Simple tag info + strTag.Format("%s"),strTagName; +#endif + + if (bTagIsJpeg) { + nPosJpeg = nPos+8; + } else { + // Indicate not a JPEG tag + nPosJpeg = 0; + } + + return true; +} +#endif + +// Determine if the file is a DICOM +// If so, parse the headers. Generally want to start at start of file (nPos=0). +bool CDecodeDicom::DecodeDicom(unsigned long nPos,unsigned long nPosFileEnd,unsigned long &nPosJpeg) +{ + unsigned nLen; + unsigned nOffset; + QString strTag; + QString strSig; + QString strVR; + + + m_bDicom = false; + + + // Skip File Preamble + nPos += 128; + + // DICOM Prefix + strSig = m_pWBuf->BufReadStrn(nPos,4); + if (strSig == "DICM") { + m_bDicom = true; + m_pLog->AddLine(""); + m_pLog->AddLineHdr("*** DICOM File Decoding ***"); + m_pLog->AddLine("Decoding DICOM format..."); + m_pLog->AddLine(""); + } else { + return false; + } + nPos+=4; + + bool bDone = false; + + // If we get here, then we have found the header signature + // FIXME: Handle proper termination! + if (nPos >= nPosFileEnd) { + bDone = true; + } + + //bool bFoundJpeg = false; + unsigned long nPosJpegFound = 0; + tsTagDetail sTagDetail; + while (!bDone) { + + sTagDetail.Reset(); + GetTagHeader(nPos,sTagDetail); + + // Fetch results + nLen = sTagDetail.nLen; + nPosJpegFound = sTagDetail.nPosJpeg; + strTag = sTagDetail.strTag; + strVR = sTagDetail.strVR; + nOffset = sTagDetail.nOffset; + + // Advance the file position + nPos += sTagDetail.nOffset; + + // Process the field + if (nLen == 0xFFFFFFFF) { + // Detect "invalid length" + // In these cases we are probably dependent upon delimiters + // so we don't have any real content in this tag. + // + // Example: E:\JPEG\JPEGsnoop Testcases\DICOM_samples\24-bit JPEG Lossy Color.dcm + // Offset: 0x508 + nLen = 0; + } + + if (nPosJpegFound != 0) { + // Only capture first image offset + if (nPosJpeg == 0) { + nPosJpeg = nPosJpegFound; + } + } + + + // See if this is an enumerated value + // If not, just report as hex for now + + // Now determine enum value + QString strValTrunc = ""; + QString strDesc = ""; + bool bIsEnum = false; + strValTrunc = m_pWBuf->BufReadStrn(nPos,200); + bIsEnum = LookupEnum(sTagDetail.nTagGroup,sTagDetail.nTagElement,strValTrunc,strDesc); + if (bIsEnum) { + ReportFldStrEnc(1,sTagDetail.strTag,strDesc,strValTrunc); + } else { + ReportFldHex(1,strTag,nPos,nLen); + } + + nPos += nLen; + + if (nPos >= nPosFileEnd) { + bDone = true; + } + + } // bDone + + + return true; + +} + +// Create indent string +// - Returns a sequence of spaces according to the indent level +QString CDecodeDicom::ParseIndent(unsigned nIndent) +{ + QString strIndent = ""; + for (unsigned nInd=0;nIndAddLine(strLine); +} + +// Display a formatted string field with encoded value +// - Report the value with the field name (strField) and current indent level (nIndent) +void CDecodeDicom::ReportFldStrEnc(unsigned nIndent,QString strField,QString strVal,QString strEncVal) +{ + QString strIndent; + QString strLine; + + strIndent = ParseIndent(nIndent); + strLine.arg(strIndent).arg(strField, -50).arg(strVal); //Format("%s%-50s = \"%s\""),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strVal; + m_pLog->AddLine(strLine); +} + +// Locate a field ID in the constant Meta Tag array +// +// INPUT: +// - nTagGroup = Meta Tag (High) +// - nTagElement = Meta Tag (Low) +// OUTPUT: +// - nFldInd = Index into asDicomTags[] array +// RETURN: +// - Returns true if ID was found in array +// NOTE: +// - The constant struct array depends on DICOM_T_END as a terminator for the list +// +bool CDecodeDicom::FindTag(unsigned nTagGroup,unsigned nTagElement,unsigned &nFldInd) +{ + unsigned nInd=0; + bool bDone=false; + bool bFound=false; + while (!bDone) { + if (asDicomTags[nInd].eTagType == DICOM_T_END) { + bDone = true; + } else { + unsigned nFoundTagH = asDicomTags[nInd].nTagGroup; + unsigned nFoundTagL = asDicomTags[nInd].nTagElement; + if ((nTagGroup == nFoundTagH) && (nTagElement == nFoundTagL)) { + // Matched + bDone = true; + bFound = true; + } else { + nInd++; + } + + } + } + if (bFound) { + nFldInd = nInd; + } + return bFound; +} + + + +// +// Display a formatted hexadecimal field +// - Report the value with the field name (strField) and current indent level (nIndent) +// - Depending on the length of the buffer, either report the hex value in-line with +// the field name or else start a new row and begin a hex dump +// - Also report the ASCII representation alongside the hex dump +// +// INPUT: +// - nIndent = Current indent level for reporting +// - strField = Field name +// - nPosStart = Field byte array file position start +// - nLen = Field byte array length +// +void CDecodeDicom::ReportFldHex(unsigned nIndent,QString strField,unsigned long nPosStart,unsigned nLen) +{ + QString strIndent; + unsigned nByte; + QString strPrefix; + QString strByteHex; + QString strByteAsc; + QString strValHex; + QString strValAsc; + QString strLine; + + strIndent = ParseIndent(nIndent); + + if (nLen == 0) { + // Print out the header row, but no data will be shown + strLine.arg(strIndent).arg(strField, -50); // ("%s%-50s = "),(LPCTSTR)strIndent,(LPCTSTR)strField; + m_pLog->AddLine(strLine); + // Nothing to report, exit now + return; + } else if (nLen <= DC_HEX_MAX_INLINE) { + // Define prefix for row + strPrefix.arg(strIndent).arg(strField, -50); // .Format("%s%-50s = "),(LPCTSTR)strIndent,(LPCTSTR)strField; + } else { +#if 0 + // Print out header row + strLine.Format("%s%-50s ="),(LPCTSTR)strIndent,(LPCTSTR)strField; + m_pLog->AddLine(strLine); + // Define prefix for next row + //strPrefix.Format("%s"),(LPCTSTR)strIndent; + strPrefix.Format("%s%-50s "),(LPCTSTR)strIndent,_T(""); +#else + // Define prefix for row + //FIXME: Only report field on first row + strPrefix.arg(strIndent).arg(strField, -50); //.Format("%s%-50s = "),(LPCTSTR)strIndent,(LPCTSTR)strField; +#endif + } + + + // Build up the hex string + // Limit to DC_HEX_TOTAL bytes + unsigned nRowOffset = 0; + bool bDone = false; + unsigned nLenClip; + nLenClip = qMin(nLen, unsigned(DC_HEX_TOTAL)); + strValHex = ""; + strValAsc = ""; + while (!bDone) { + // Have we reached the end of the data we wish to display? + if (nRowOffset>=nLenClip) { + bDone = true; + } else { + // Reset the cumulative hex/ascii value strings + strValHex = ""; + strValAsc = ""; + // Build the hex/ascii value strings + for (unsigned nInd=0;nIndBuf(nPosStart+nRowOffset+nInd); + strByteHex.arg(nByte, 2, 16, QChar('0')); // .Format("%02X "),nByte; + // Only display printable characters + if (isprint(nByte)) { + strByteAsc.arg(nByte); // .Format("%c"),nByte; + } else { + strByteAsc = "."; + } + } else { + // Pad out to end of row + strByteHex = " "; + strByteAsc = " "; + } + // Build up the strings + strValHex += strByteHex; + strValAsc += strByteAsc; + } + + // Generate the line with Hex and ASCII representations + strLine.arg(strPrefix, " | 0x", strValHex, " | ", strValAsc); // .Format("%s | 0x%s | %s"),(LPCTSTR)strPrefix,(LPCTSTR)strValHex,(LPCTSTR)strValAsc; + m_pLog->AddLine(strLine); + + // Now increment file offset + nRowOffset += DC_HEX_MAX_ROW; + } + } + + // If we had to clip the display length, then show ellipsis now + if (nLenClip < nLen) { + strLine.arg(strPrefix, " | ..."); // .Format("%s | ..."),(LPCTSTR)strPrefix; + m_pLog->AddLine(strLine); + } + + +} + +// Display a formatted enumerated type field +// - Look up enumerated constant (nVal) for the given field (eEnumField) +// - Report the value with the field name (strField) and current indent level (nIndent) +void CDecodeDicom::ReportFldEnum(unsigned nIndent,QString strField,unsigned nTagGroup,unsigned nTagElement,QString strVal) +{ + QString strIndent; + QString strDesc; + QString strLine; + bool bFound; + + strIndent = ParseIndent(nIndent); + + bFound = LookupEnum(nTagGroup,nTagElement,strVal,strDesc); + if (bFound) { + strLine.arg(strIndent).arg(strField, -50).arg(strDesc); // .Format("%s%-50s = %s"),(LPCTSTR)strIndent,(LPCTSTR)strField,(LPCTSTR)strDesc; + m_pLog->AddLine(strLine); + } else { + Q_ASSERT(false); + } +} + +// Look up the enumerated constant (nVal) for the specified field (eEnumField) +// - Returns "" if the field wasn't found +bool CDecodeDicom::LookupEnum(unsigned nTagGroup,unsigned nTagElement,QString strVal,QString &strDesc) +{ + // Find the enum value + bool bFound = false; + bool bDone = false; + unsigned nEnumInd=0; + while (!bDone) { + if ( (asTagSpecial[nEnumInd].nTagGroup == nTagGroup) && (asTagSpecial[nEnumInd].nTagElement == nTagElement) ) { + if (asTagSpecial[nEnumInd].strVal == strVal) { + bDone = true; + bFound = true; + strDesc = asTagSpecial[nEnumInd].strDefinition; + } + } + if (asTagSpecial[nEnumInd].strVal == "") { + bDone = true; + } + if (!bDone) { + nEnumInd++; + } + } + return bFound; +} + +// =============================================================================== +// CONSTANTS +// =============================================================================== diff --git a/source/DecodeDicom.h b/source/DecodeDicom.h index 9822092..026ba5f 100644 --- a/source/DecodeDicom.h +++ b/source/DecodeDicom.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -149,4 +149,4 @@ class CDecodeDicom bool m_bJpegEncapOffsetNext; }; -#endif +#endif \ No newline at end of file diff --git a/source/DecodeDicomTags.cpp b/source/DecodeDicomTags.cpp deleted file mode 100644 index 450ae69..0000000 --- a/source/DecodeDicomTags.cpp +++ /dev/null @@ -1,3931 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - -#include "stdafx.h" - -#include "DecodeDicom.h" - - -// =============================================================================== -// CONSTANTS -// =============================================================================== - - -// File Meta Elements -struct tsDicomTag asDicomTags[] = -{ -// Part 10, Section 7.1 -{ 0x0002,0x0000,DICOM_T_TYPE1, _T("File Meta Information Group Length") }, -{ 0x0002,0x0001,DICOM_T_TYPE1, _T("File Meta Information Version") }, -{ 0x0002,0x0002,DICOM_T_TYPE1, _T("Media Storage SOP Class UID") }, -{ 0x0002,0x0003,DICOM_T_TYPE1, _T("Media Storage SOP Instance UID") }, -{ 0x0002,0x0010,DICOM_T_TYPE1, _T("Transfer Syntax UID") }, -{ 0x0002,0x0012,DICOM_T_TYPE1, _T("Implementation Class UID") }, -{ 0x0002,0x0013,DICOM_T_TYPE3, _T("Implementation Version Name") }, -{ 0x0002,0x0016,DICOM_T_TYPE3, _T("Source Application Entity Title") }, -{ 0x0002,0x0100,DICOM_T_TYPE3, _T("Private Information Creator UID") }, -{ 0x0002,0x0102,DICOM_T_TYPE1C,_T("Private Information") }, - - // Part 6, Section 6 -{ 0x0008,0x0001,DICOM_T_UNK, _T("Length to End") }, -{ 0x0008,0x0005,DICOM_T_UNK, _T("Specific Character Set") }, -{ 0x0008,0x0006,DICOM_T_UNK, _T("Language Code Sequence") }, -{ 0x0008,0x0008,DICOM_T_UNK, _T("Image Type") }, -{ 0x0008,0x0010,DICOM_T_UNK, _T("Recognition Code") }, -{ 0x0008,0x0012,DICOM_T_UNK, _T("Instance Creation Date") }, -{ 0x0008,0x0013,DICOM_T_UNK, _T("Instance Creation Time") }, -{ 0x0008,0x0014,DICOM_T_UNK, _T("Instance Creator UID") }, -{ 0x0008,0x0015,DICOM_T_UNK, _T("Instance Coercion DateTime") }, -{ 0x0008,0x0016,DICOM_T_UNK, _T("SOP Class UID") }, -{ 0x0008,0x0018,DICOM_T_UNK, _T("SOP Instance UID") }, -{ 0x0008,0x001A,DICOM_T_UNK, _T("Related General SOP Class UID") }, -{ 0x0008,0x001B,DICOM_T_UNK, _T("Original Specialized SOP Class UID") }, -{ 0x0008,0x0020,DICOM_T_UNK, _T("Study Date") }, -{ 0x0008,0x0021,DICOM_T_UNK, _T("Series Date") }, -{ 0x0008,0x0022,DICOM_T_UNK, _T("Acquisition Date") }, -{ 0x0008,0x0023,DICOM_T_UNK, _T("Content Date") }, -{ 0x0008,0x0024,DICOM_T_UNK, _T("Overlay Date") }, -{ 0x0008,0x0025,DICOM_T_UNK, _T("Curve Date") }, -{ 0x0008,0x002A,DICOM_T_UNK, _T("Acquisition DateTime") }, -{ 0x0008,0x0030,DICOM_T_UNK, _T("Study Time") }, -{ 0x0008,0x0031,DICOM_T_UNK, _T("Series Time") }, -{ 0x0008,0x0032,DICOM_T_UNK, _T("Acquisition Time") }, -{ 0x0008,0x0033,DICOM_T_UNK, _T("Content Time") }, -{ 0x0008,0x0034,DICOM_T_UNK, _T("Overlay Time") }, -{ 0x0008,0x0035,DICOM_T_UNK, _T("Curve Time") }, -{ 0x0008,0x0040,DICOM_T_UNK, _T("Data Set Type") }, -{ 0x0008,0x0041,DICOM_T_UNK, _T("Data Set Subtype") }, -{ 0x0008,0x0042,DICOM_T_UNK, _T("Nuclear Medicine Series Type") }, -{ 0x0008,0x0050,DICOM_T_UNK, _T("Accession Number") }, -{ 0x0008,0x0051,DICOM_T_UNK, _T("Issuer of Accession Number Sequence") }, -{ 0x0008,0x0052,DICOM_T_UNK, _T("Query/Retrieve Level") }, -{ 0x0008,0x0053,DICOM_T_UNK, _T("Query/Retrieve View") }, -{ 0x0008,0x0054,DICOM_T_UNK, _T("Retrieve AE Title") }, -{ 0x0008,0x0056,DICOM_T_UNK, _T("Instance Availability") }, -{ 0x0008,0x0058,DICOM_T_UNK, _T("Failed SOP Instance UID List") }, -{ 0x0008,0x0060,DICOM_T_UNK, _T("Modality") }, -{ 0x0008,0x0061,DICOM_T_UNK, _T("Modalities in Study") }, -{ 0x0008,0x0062,DICOM_T_UNK, _T("SOP Classes in Study") }, -{ 0x0008,0x0064,DICOM_T_UNK, _T("Conversion Type") }, -{ 0x0008,0x0068,DICOM_T_UNK, _T("Presentation Intent Type") }, -{ 0x0008,0x0070,DICOM_T_UNK, _T("Manufacturer") }, -{ 0x0008,0x0080,DICOM_T_UNK, _T("Institution Name") }, -{ 0x0008,0x0081,DICOM_T_UNK, _T("Institution Address") }, -{ 0x0008,0x0082,DICOM_T_UNK, _T("Institution Code Sequence") }, -{ 0x0008,0x0090,DICOM_T_UNK, _T("Referring Physician's Name") }, -{ 0x0008,0x0092,DICOM_T_UNK, _T("Referring Physician's Address") }, -{ 0x0008,0x0094,DICOM_T_UNK, _T("Referring Physician's Telephone Numbers") }, -{ 0x0008,0x0096,DICOM_T_UNK, _T("Referring Physician Identification Sequence") }, -{ 0x0008,0x0100,DICOM_T_UNK, _T("Code Value") }, -{ 0x0008,0x0101,DICOM_T_UNK, _T("Extended Code Value") }, -{ 0x0008,0x0102,DICOM_T_UNK, _T("Coding Scheme Designator") }, -{ 0x0008,0x0103,DICOM_T_UNK, _T("Coding Scheme Version") }, -{ 0x0008,0x0104,DICOM_T_UNK, _T("Code Meaning") }, -{ 0x0008,0x0105,DICOM_T_UNK, _T("Mapping Resource") }, -{ 0x0008,0x0106,DICOM_T_UNK, _T("Context Group Version") }, -{ 0x0008,0x0107,DICOM_T_UNK, _T("Context Group Local Version") }, -{ 0x0008,0x0108,DICOM_T_UNK, _T("Extended Code Meaning") }, -{ 0x0008,0x010B,DICOM_T_UNK, _T("Context Group Extension Flag") }, -{ 0x0008,0x010C,DICOM_T_UNK, _T("Coding Scheme UID") }, -{ 0x0008,0x010D,DICOM_T_UNK, _T("Context Group Extension Creator UID") }, -{ 0x0008,0x010F,DICOM_T_UNK, _T("Context Identifier") }, -{ 0x0008,0x0110,DICOM_T_UNK, _T("Coding Scheme Identification Sequence") }, -{ 0x0008,0x0112,DICOM_T_UNK, _T("Coding Scheme Registry") }, -{ 0x0008,0x0114,DICOM_T_UNK, _T("Coding Scheme External ID") }, -{ 0x0008,0x0115,DICOM_T_UNK, _T("Coding Scheme Name") }, -{ 0x0008,0x0116,DICOM_T_UNK, _T("Coding Scheme Responsible Organization") }, -{ 0x0008,0x0117,DICOM_T_UNK, _T("Context UID") }, -{ 0x0008,0x0201,DICOM_T_UNK, _T("Timezone Offset From UTC") }, -{ 0x0008,0x1000,DICOM_T_UNK, _T("Network ID") }, -{ 0x0008,0x1010,DICOM_T_UNK, _T("Station Name") }, -{ 0x0008,0x1030,DICOM_T_UNK, _T("Study Description") }, -{ 0x0008,0x1032,DICOM_T_UNK, _T("Procedure Code Sequence") }, -{ 0x0008,0x103E,DICOM_T_UNK, _T("Series Description") }, -{ 0x0008,0x103F,DICOM_T_UNK, _T("Series Description Code Sequence") }, -{ 0x0008,0x1040,DICOM_T_UNK, _T("Institutional Department Name") }, -{ 0x0008,0x1048,DICOM_T_UNK, _T("Physician(s) of Record") }, -{ 0x0008,0x1049,DICOM_T_UNK, _T("Physician(s) of Record Identification Sequence") }, -{ 0x0008,0x1050,DICOM_T_UNK, _T("Performing Physician's Name") }, -{ 0x0008,0x1052,DICOM_T_UNK, _T("Performing Physician Identification Sequence") }, -{ 0x0008,0x1060,DICOM_T_UNK, _T("Name of Physician(s) Reading Study") }, -{ 0x0008,0x1062,DICOM_T_UNK, _T("Physician(s) Reading Study Identification Sequence") }, -{ 0x0008,0x1070,DICOM_T_UNK, _T("Operators' Name") }, -{ 0x0008,0x1072,DICOM_T_UNK, _T("Operator Identification Sequence") }, -{ 0x0008,0x1080,DICOM_T_UNK, _T("Admitting Diagnoses Description") }, -{ 0x0008,0x1084,DICOM_T_UNK, _T("Admitting Diagnoses Code Sequence") }, -{ 0x0008,0x1090,DICOM_T_UNK, _T("Manufacturer's Model Name") }, -{ 0x0008,0x1100,DICOM_T_UNK, _T("Referenced Results Sequence") }, -{ 0x0008,0x1110,DICOM_T_UNK, _T("Referenced Study Sequence") }, -{ 0x0008,0x1111,DICOM_T_UNK, _T("Referenced Performed Procedure Step Sequence") }, -{ 0x0008,0x1115,DICOM_T_UNK, _T("Referenced Series Sequence") }, -{ 0x0008,0x1120,DICOM_T_UNK, _T("Referenced Patient Sequence") }, -{ 0x0008,0x1125,DICOM_T_UNK, _T("Referenced Visit Sequence") }, -{ 0x0008,0x1130,DICOM_T_UNK, _T("Referenced Overlay Sequence") }, -{ 0x0008,0x1134,DICOM_T_UNK, _T("Referenced Stereometric Instance Sequence") }, -{ 0x0008,0x113A,DICOM_T_UNK, _T("Referenced Waveform Sequence") }, -{ 0x0008,0x1140,DICOM_T_UNK, _T("Referenced Image Sequence") }, -{ 0x0008,0x1145,DICOM_T_UNK, _T("Referenced Curve Sequence") }, -{ 0x0008,0x114A,DICOM_T_UNK, _T("Referenced Instance Sequence") }, -{ 0x0008,0x114B,DICOM_T_UNK, _T("Referenced Real World Value Mapping Instance Sequence") }, -{ 0x0008,0x1150,DICOM_T_UNK, _T("Referenced SOP Class UID") }, -{ 0x0008,0x1155,DICOM_T_UNK, _T("Referenced SOP Instance UID") }, -{ 0x0008,0x115A,DICOM_T_UNK, _T("SOP Classes Supported") }, -{ 0x0008,0x1160,DICOM_T_UNK, _T("Referenced Frame Number") }, -{ 0x0008,0x1161,DICOM_T_UNK, _T("Simple Frame List") }, -{ 0x0008,0x1162,DICOM_T_UNK, _T("Calculated Frame List") }, -{ 0x0008,0x1163,DICOM_T_UNK, _T("Time Range") }, -{ 0x0008,0x1164,DICOM_T_UNK, _T("Frame Extraction Sequence") }, -{ 0x0008,0x1167,DICOM_T_UNK, _T("Multi-frame Source SOP Instance UID") }, -{ 0x0008,0x1190,DICOM_T_UNK, _T("Retrieve URL") }, -{ 0x0008,0x1195,DICOM_T_UNK, _T("Transaction UID") }, -{ 0x0008,0x1196,DICOM_T_UNK, _T("Warning Reason") }, -{ 0x0008,0x1197,DICOM_T_UNK, _T("Failure Reason") }, -{ 0x0008,0x1198,DICOM_T_UNK, _T("Failed SOP Sequence") }, -{ 0x0008,0x1199,DICOM_T_UNK, _T("Referenced SOP Sequence") }, -{ 0x0008,0x1200,DICOM_T_UNK, _T("Studies Containing Other Referenced Instances Sequence") }, -{ 0x0008,0x1250,DICOM_T_UNK, _T("Related Series Sequence") }, -{ 0x0008,0x2110,DICOM_T_UNK, _T("Lossy Image Compression (Retired)") }, -{ 0x0008,0x2111,DICOM_T_UNK, _T("Derivation Description") }, -{ 0x0008,0x2112,DICOM_T_UNK, _T("Source Image Sequence") }, -{ 0x0008,0x2120,DICOM_T_UNK, _T("Stage Name") }, -{ 0x0008,0x2122,DICOM_T_UNK, _T("Stage Number") }, -{ 0x0008,0x2124,DICOM_T_UNK, _T("Number of Stages") }, -{ 0x0008,0x2127,DICOM_T_UNK, _T("View Name") }, -{ 0x0008,0x2128,DICOM_T_UNK, _T("View Number") }, -{ 0x0008,0x2129,DICOM_T_UNK, _T("Number of Event Timers") }, -{ 0x0008,0x212A,DICOM_T_UNK, _T("Number of Views in Stage") }, -{ 0x0008,0x2130,DICOM_T_UNK, _T("Event Elapsed Time(s)") }, -{ 0x0008,0x2132,DICOM_T_UNK, _T("Event Timer Name(s)") }, -{ 0x0008,0x2133,DICOM_T_UNK, _T("Event Timer Sequence") }, -{ 0x0008,0x2134,DICOM_T_UNK, _T("Event Time Offset") }, -{ 0x0008,0x2135,DICOM_T_UNK, _T("Event Code Sequence") }, -{ 0x0008,0x2142,DICOM_T_UNK, _T("Start Trim") }, -{ 0x0008,0x2143,DICOM_T_UNK, _T("Stop Trim") }, -{ 0x0008,0x2144,DICOM_T_UNK, _T("Recommended Display Frame Rate") }, -{ 0x0008,0x2200,DICOM_T_UNK, _T("Transducer Position") }, -{ 0x0008,0x2204,DICOM_T_UNK, _T("Transducer Orientation") }, -{ 0x0008,0x2208,DICOM_T_UNK, _T("Anatomic Structure") }, -{ 0x0008,0x2218,DICOM_T_UNK, _T("Anatomic Region Sequence") }, -{ 0x0008,0x2220,DICOM_T_UNK, _T("Anatomic Region Modifier Sequence") }, -{ 0x0008,0x2228,DICOM_T_UNK, _T("Primary Anatomic Structure Sequence") }, -{ 0x0008,0x2229,DICOM_T_UNK, _T("Anatomic Structure, Space or Region Sequence") }, -{ 0x0008,0x2230,DICOM_T_UNK, _T("Primary Anatomic Structure Modifier Sequence") }, -{ 0x0008,0x2240,DICOM_T_UNK, _T("Transducer Position Sequence") }, -{ 0x0008,0x2242,DICOM_T_UNK, _T("Transducer Position Modifier Sequence") }, -{ 0x0008,0x2244,DICOM_T_UNK, _T("Transducer Orientation Sequence") }, -{ 0x0008,0x2246,DICOM_T_UNK, _T("Transducer Orientation Modifier Sequence") }, -{ 0x0008,0x2251,DICOM_T_UNK, _T("Anatomic Structure Space Or Region Code Sequence (Trial)") }, -{ 0x0008,0x2253,DICOM_T_UNK, _T("Anatomic Portal Of Entrance Code Sequence (Trial)") }, -{ 0x0008,0x2255,DICOM_T_UNK, _T("Anatomic Approach Direction Code Sequence (Trial)") }, -{ 0x0008,0x2256,DICOM_T_UNK, _T("Anatomic Perspective Description (Trial)") }, -{ 0x0008,0x2257,DICOM_T_UNK, _T("Anatomic Perspective Code Sequence (Trial)") }, -{ 0x0008,0x2258,DICOM_T_UNK, _T("Anatomic Location Of Examining Instrument Description (Trial)") }, -{ 0x0008,0x2259,DICOM_T_UNK, _T("Anatomic Location Of Examining Instrument Code Sequence (Trial)") }, -{ 0x0008,0x225A,DICOM_T_UNK, _T("Anatomic Structure Space Or Region Modifier Code Sequence (Trial)") }, -{ 0x0008,0x225C,DICOM_T_UNK, _T("On Axis Background Anatomic Structure Code Sequence (Trial)") }, -{ 0x0008,0x3001,DICOM_T_UNK, _T("Alternate Representation Sequence") }, -{ 0x0008,0x3010,DICOM_T_UNK, _T("Irradiation Event UID") }, -{ 0x0008,0x3011,DICOM_T_UNK, _T("Source Irradiation Event Sequence") }, -{ 0x0008,0x3012,DICOM_T_UNK, _T("Radiopharmaceutical Administration Event UID") }, -{ 0x0008,0x4000,DICOM_T_UNK, _T("Identifying Comments") }, -{ 0x0008,0x9007,DICOM_T_UNK, _T("Frame Type") }, -{ 0x0008,0x9092,DICOM_T_UNK, _T("Referenced Image Evidence Sequence") }, -{ 0x0008,0x9121,DICOM_T_UNK, _T("Referenced Raw Data Sequence") }, -{ 0x0008,0x9123,DICOM_T_UNK, _T("Creator-Version UID") }, -{ 0x0008,0x9124,DICOM_T_UNK, _T("Derivation Image Sequence") }, -{ 0x0008,0x9154,DICOM_T_UNK, _T("Source Image Evidence Sequence") }, -{ 0x0008,0x9205,DICOM_T_UNK, _T("Pixel Presentation") }, -{ 0x0008,0x9206,DICOM_T_UNK, _T("Volumetric Properties") }, -{ 0x0008,0x9207,DICOM_T_UNK, _T("Volume Based Calculation Technique") }, -{ 0x0008,0x9208,DICOM_T_UNK, _T("Complex Image Component") }, -{ 0x0008,0x9209,DICOM_T_UNK, _T("Acquisition Contrast") }, -{ 0x0008,0x9215,DICOM_T_UNK, _T("Derivation Code Sequence") }, -{ 0x0008,0x9237,DICOM_T_UNK, _T("Referenced Presentation State Sequence") }, -{ 0x0008,0x9410,DICOM_T_UNK, _T("Referenced Other Plane Sequence") }, -{ 0x0008,0x9458,DICOM_T_UNK, _T("Frame Display Sequence") }, -{ 0x0008,0x9459,DICOM_T_UNK, _T("Recommended Display Frame Rate in Float") }, -{ 0x0008,0x9460,DICOM_T_UNK, _T("Skip Frame Range Flag") }, -{ 0x0010,0x0010,DICOM_T_UNK, _T("Patient's Name") }, -{ 0x0010,0x0020,DICOM_T_UNK, _T("Patient ID") }, -{ 0x0010,0x0021,DICOM_T_UNK, _T("Issuer of Patient ID") }, -{ 0x0010,0x0022,DICOM_T_UNK, _T("Type of Patient ID") }, -{ 0x0010,0x0024,DICOM_T_UNK, _T("Issuer of Patient ID Qualifiers Sequence") }, -{ 0x0010,0x0030,DICOM_T_UNK, _T("Patient's Birth Date") }, -{ 0x0010,0x0032,DICOM_T_UNK, _T("Patient's Birth Time") }, -{ 0x0010,0x0040,DICOM_T_UNK, _T("Patient's Sex") }, -{ 0x0010,0x0050,DICOM_T_UNK, _T("Patient's Insurance Plan Code Sequence") }, -{ 0x0010,0x0101,DICOM_T_UNK, _T("Patient's Primary Language Code Sequence") }, -{ 0x0010,0x0102,DICOM_T_UNK, _T("Patient's Primary Language Modifier Code Sequence") }, -{ 0x0010,0x0200,DICOM_T_UNK, _T("Quality Control Subject") }, -{ 0x0010,0x0201,DICOM_T_UNK, _T("Quality Control Subject Type Code Sequence") }, -{ 0x0010,0x1000,DICOM_T_UNK, _T("Other Patient IDs") }, -{ 0x0010,0x1001,DICOM_T_UNK, _T("Other Patient Names") }, -{ 0x0010,0x1002,DICOM_T_UNK, _T("Other Patient IDs Sequence") }, -{ 0x0010,0x1005,DICOM_T_UNK, _T("Patient's Birth Name") }, -{ 0x0010,0x1010,DICOM_T_UNK, _T("Patient's Age") }, -{ 0x0010,0x1020,DICOM_T_UNK, _T("Patient's Size") }, -{ 0x0010,0x1021,DICOM_T_UNK, _T("Patient's Size Code Sequence") }, -{ 0x0010,0x1030,DICOM_T_UNK, _T("Patient's Weight") }, -{ 0x0010,0x1040,DICOM_T_UNK, _T("Patient's Address") }, -{ 0x0010,0x1050,DICOM_T_UNK, _T("Insurance Plan Identification") }, -{ 0x0010,0x1060,DICOM_T_UNK, _T("Patient's Mother's Birth Name") }, -{ 0x0010,0x1080,DICOM_T_UNK, _T("Military Rank") }, -{ 0x0010,0x1081,DICOM_T_UNK, _T("Branch of Service") }, -{ 0x0010,0x1090,DICOM_T_UNK, _T("Medical Record Locator") }, -{ 0x0010,0x1100,DICOM_T_UNK, _T("Referenced Patient Photo Sequence") }, -{ 0x0010,0x2000,DICOM_T_UNK, _T("Medical Alerts") }, -{ 0x0010,0x2110,DICOM_T_UNK, _T("Allergies") }, -{ 0x0010,0x2150,DICOM_T_UNK, _T("Country of Residence") }, -{ 0x0010,0x2152,DICOM_T_UNK, _T("Region of Residence") }, -{ 0x0010,0x2154,DICOM_T_UNK, _T("Patient's Telephone Numbers") }, -{ 0x0010,0x2160,DICOM_T_UNK, _T("Ethnic Group") }, -{ 0x0010,0x2180,DICOM_T_UNK, _T("Occupation") }, -{ 0x0010,0x21A0,DICOM_T_UNK, _T("Smoking Status") }, -{ 0x0010,0x21B0,DICOM_T_UNK, _T("Additional Patient History") }, -{ 0x0010,0x21C0,DICOM_T_UNK, _T("Pregnancy Status") }, -{ 0x0010,0x21D0,DICOM_T_UNK, _T("Last Menstrual Date") }, -{ 0x0010,0x21F0,DICOM_T_UNK, _T("Patient's Religious Preference") }, -{ 0x0010,0x2201,DICOM_T_UNK, _T("Patient Species Description") }, -{ 0x0010,0x2202,DICOM_T_UNK, _T("Patient Species Code Sequence") }, -{ 0x0010,0x2203,DICOM_T_UNK, _T("Patient's Sex Neutered") }, -{ 0x0010,0x2210,DICOM_T_UNK, _T("Anatomical Orientation Type") }, -{ 0x0010,0x2292,DICOM_T_UNK, _T("Patient Breed Description") }, -{ 0x0010,0x2293,DICOM_T_UNK, _T("Patient Breed Code Sequence") }, -{ 0x0010,0x2294,DICOM_T_UNK, _T("Breed Registration Sequence") }, -{ 0x0010,0x2295,DICOM_T_UNK, _T("Breed Registration Number") }, -{ 0x0010,0x2296,DICOM_T_UNK, _T("Breed Registry Code Sequence") }, -{ 0x0010,0x2297,DICOM_T_UNK, _T("Responsible Person") }, -{ 0x0010,0x2298,DICOM_T_UNK, _T("Responsible Person Role") }, -{ 0x0010,0x2299,DICOM_T_UNK, _T("Responsible Organization") }, -{ 0x0010,0x4000,DICOM_T_UNK, _T("Patient Comments") }, -{ 0x0010,0x9431,DICOM_T_UNK, _T("Examined Body Thickness") }, -{ 0x0012,0x0010,DICOM_T_UNK, _T("Clinical Trial Sponsor Name") }, -{ 0x0012,0x0020,DICOM_T_UNK, _T("Clinical Trial Protocol ID") }, -{ 0x0012,0x0021,DICOM_T_UNK, _T("Clinical Trial Protocol Name") }, -{ 0x0012,0x0030,DICOM_T_UNK, _T("Clinical Trial Site ID") }, -{ 0x0012,0x0031,DICOM_T_UNK, _T("Clinical Trial Site Name") }, -{ 0x0012,0x0040,DICOM_T_UNK, _T("Clinical Trial Subject ID") }, -{ 0x0012,0x0042,DICOM_T_UNK, _T("Clinical Trial Subject Reading ID") }, -{ 0x0012,0x0050,DICOM_T_UNK, _T("Clinical Trial Time Point ID") }, -{ 0x0012,0x0051,DICOM_T_UNK, _T("Clinical Trial Time Point Description") }, -{ 0x0012,0x0060,DICOM_T_UNK, _T("Clinical Trial Coordinating Center Name") }, -{ 0x0012,0x0062,DICOM_T_UNK, _T("Patient Identity Removed") }, -{ 0x0012,0x0063,DICOM_T_UNK, _T("De-identification Method") }, -{ 0x0012,0x0064,DICOM_T_UNK, _T("De-identification Method Code Sequence") }, -{ 0x0012,0x0071,DICOM_T_UNK, _T("Clinical Trial Series ID") }, -{ 0x0012,0x0072,DICOM_T_UNK, _T("Clinical Trial Series Description") }, -{ 0x0012,0x0081,DICOM_T_UNK, _T("Clinical Trial Protocol Ethics Committee Name") }, -{ 0x0012,0x0082,DICOM_T_UNK, _T("Clinical Trial Protocol Ethics Committee Approval Number") }, -{ 0x0012,0x0083,DICOM_T_UNK, _T("Consent for Clinical Trial Use Sequence") }, -{ 0x0012,0x0084,DICOM_T_UNK, _T("Distribution Type") }, -{ 0x0012,0x0085,DICOM_T_UNK, _T("Consent for Distribution Flag") }, -{ 0x0014,0x0023,DICOM_T_UNK, _T("CAD File Format") }, -{ 0x0014,0x0024,DICOM_T_UNK, _T("Component Reference System") }, -{ 0x0014,0x0025,DICOM_T_UNK, _T("Component Manufacturing Procedure") }, -{ 0x0014,0x0028,DICOM_T_UNK, _T("Component Manufacturer") }, -{ 0x0014,0x0030,DICOM_T_UNK, _T("Material Thickness") }, -{ 0x0014,0x0032,DICOM_T_UNK, _T("Material Pipe Diameter") }, -{ 0x0014,0x0034,DICOM_T_UNK, _T("Material Isolation Diameter") }, -{ 0x0014,0x0042,DICOM_T_UNK, _T("Material Grade") }, -{ 0x0014,0x0044,DICOM_T_UNK, _T("Material Properties Description") }, -{ 0x0014,0x0045,DICOM_T_UNK, _T("Material Properties File Format (Retired)") }, -{ 0x0014,0x0046,DICOM_T_UNK, _T("Material Notes") }, -{ 0x0014,0x0050,DICOM_T_UNK, _T("Component Shape") }, -{ 0x0014,0x0052,DICOM_T_UNK, _T("Curvature Type") }, -{ 0x0014,0x0054,DICOM_T_UNK, _T("Outer Diameter") }, -{ 0x0014,0x0056,DICOM_T_UNK, _T("Inner Diameter") }, -{ 0x0014,0x1010,DICOM_T_UNK, _T("Actual Environmental Conditions") }, -{ 0x0014,0x1020,DICOM_T_UNK, _T("Expiry Date") }, -{ 0x0014,0x1040,DICOM_T_UNK, _T("Environmental Conditions") }, -{ 0x0014,0x2002,DICOM_T_UNK, _T("Evaluator Sequence") }, -{ 0x0014,0x2004,DICOM_T_UNK, _T("Evaluator Number") }, -{ 0x0014,0x2006,DICOM_T_UNK, _T("Evaluator Name") }, -{ 0x0014,0x2008,DICOM_T_UNK, _T("Evaluation Attempt") }, -{ 0x0014,0x2012,DICOM_T_UNK, _T("Indication Sequence") }, -{ 0x0014,0x2014,DICOM_T_UNK, _T("Indication Number") }, -{ 0x0014,0x2016,DICOM_T_UNK, _T("Indication Label") }, -{ 0x0014,0x2018,DICOM_T_UNK, _T("Indication Description") }, -{ 0x0014,0x201A,DICOM_T_UNK, _T("Indication Type") }, -{ 0x0014,0x201C,DICOM_T_UNK, _T("Indication Disposition") }, -{ 0x0014,0x201E,DICOM_T_UNK, _T("Indication ROI Sequence") }, -{ 0x0014,0x2030,DICOM_T_UNK, _T("Indication Physical Property Sequence") }, -{ 0x0014,0x2032,DICOM_T_UNK, _T("Property Label") }, -{ 0x0014,0x2202,DICOM_T_UNK, _T("Coordinate System Number of Axes") }, -{ 0x0014,0x2204,DICOM_T_UNK, _T("Coordinate System Axes Sequence") }, -{ 0x0014,0x2206,DICOM_T_UNK, _T("Coordinate System Axis Description") }, -{ 0x0014,0x2208,DICOM_T_UNK, _T("Coordinate System Data Set Mapping") }, -{ 0x0014,0x220A,DICOM_T_UNK, _T("Coordinate System Axis Number") }, -{ 0x0014,0x220C,DICOM_T_UNK, _T("Coordinate System Axis Type") }, -{ 0x0014,0x220E,DICOM_T_UNK, _T("Coordinate System Axis Units") }, -{ 0x0014,0x2210,DICOM_T_UNK, _T("Coordinate System Axis Values") }, -{ 0x0014,0x2220,DICOM_T_UNK, _T("Coordinate System Transform Sequence") }, -{ 0x0014,0x2222,DICOM_T_UNK, _T("Transform Description") }, -{ 0x0014,0x2224,DICOM_T_UNK, _T("Transform Number of Axes") }, -{ 0x0014,0x2226,DICOM_T_UNK, _T("Transform Order of Axes") }, -{ 0x0014,0x2228,DICOM_T_UNK, _T("Transformed Axis Units") }, -{ 0x0014,0x222A,DICOM_T_UNK, _T("Coordinate System Transform Rotation and Scale Matrix") }, -{ 0x0014,0x222C,DICOM_T_UNK, _T("Coordinate System Transform Translation Matrix") }, -{ 0x0014,0x3011,DICOM_T_UNK, _T("Internal Detector Frame Time") }, -{ 0x0014,0x3012,DICOM_T_UNK, _T("Number of Frames Integrated") }, -{ 0x0014,0x3020,DICOM_T_UNK, _T("Detector Temperature Sequence") }, -{ 0x0014,0x3022,DICOM_T_UNK, _T("Sensor Name") }, -{ 0x0014,0x3024,DICOM_T_UNK, _T("Horizontal Offset of Sensor") }, -{ 0x0014,0x3026,DICOM_T_UNK, _T("Vertical Offset of Sensor") }, -{ 0x0014,0x3028,DICOM_T_UNK, _T("Sensor Temperature") }, -{ 0x0014,0x3040,DICOM_T_UNK, _T("Dark Current Sequence") }, -{ 0x0014,0x3050,DICOM_T_UNK, _T("Dark Current Counts") }, -{ 0x0014,0x3060,DICOM_T_UNK, _T("Gain Correction Reference Sequence") }, -{ 0x0014,0x3070,DICOM_T_UNK, _T("Air Counts") }, -{ 0x0014,0x3071,DICOM_T_UNK, _T("KV Used in Gain Calibration") }, -{ 0x0014,0x3072,DICOM_T_UNK, _T("MA Used in Gain Calibration") }, -{ 0x0014,0x3073,DICOM_T_UNK, _T("Number of Frames Used for Integration") }, -{ 0x0014,0x3074,DICOM_T_UNK, _T("Filter Material Used in Gain Calibration") }, -{ 0x0014,0x3075,DICOM_T_UNK, _T("Filter Thickness Used in Gain Calibration") }, -{ 0x0014,0x3076,DICOM_T_UNK, _T("Date of Gain Calibration") }, -{ 0x0014,0x3077,DICOM_T_UNK, _T("Time of Gain Calibration") }, -{ 0x0014,0x3080,DICOM_T_UNK, _T("Bad Pixel Image") }, -{ 0x0014,0x3099,DICOM_T_UNK, _T("Calibration Notes") }, -{ 0x0014,0x4002,DICOM_T_UNK, _T("Pulser Equipment Sequence") }, -{ 0x0014,0x4004,DICOM_T_UNK, _T("Pulser Type") }, -{ 0x0014,0x4006,DICOM_T_UNK, _T("Pulser Notes") }, -{ 0x0014,0x4008,DICOM_T_UNK, _T("Receiver Equipment Sequence") }, -{ 0x0014,0x400A,DICOM_T_UNK, _T("Amplifier Type") }, -{ 0x0014,0x400C,DICOM_T_UNK, _T("Receiver Notes") }, -{ 0x0014,0x400E,DICOM_T_UNK, _T("Pre-Amplifier Equipment Sequence") }, -{ 0x0014,0x400F,DICOM_T_UNK, _T("Pre-Amplifier Notes") }, -{ 0x0014,0x4010,DICOM_T_UNK, _T("Transmit Transducer Sequence") }, -{ 0x0014,0x4011,DICOM_T_UNK, _T("Receive Transducer Sequence") }, -{ 0x0014,0x4012,DICOM_T_UNK, _T("Number of Elements") }, -{ 0x0014,0x4013,DICOM_T_UNK, _T("Element Shape") }, -{ 0x0014,0x4014,DICOM_T_UNK, _T("Element Dimension A") }, -{ 0x0014,0x4015,DICOM_T_UNK, _T("Element Dimension B") }, -{ 0x0014,0x4016,DICOM_T_UNK, _T("Element Pitch A") }, -{ 0x0014,0x4017,DICOM_T_UNK, _T("Measured Beam Dimension A") }, -{ 0x0014,0x4018,DICOM_T_UNK, _T("Measured Beam Dimension B") }, -{ 0x0014,0x4019,DICOM_T_UNK, _T("Location of Measured Beam Diameter") }, -{ 0x0014,0x401A,DICOM_T_UNK, _T("Nominal Frequency") }, -{ 0x0014,0x401B,DICOM_T_UNK, _T("Measured Center Frequency") }, -{ 0x0014,0x401C,DICOM_T_UNK, _T("Measured Bandwidth") }, -{ 0x0014,0x401D,DICOM_T_UNK, _T("Element Pitch B") }, -{ 0x0014,0x4020,DICOM_T_UNK, _T("Pulser Settings Sequence") }, -{ 0x0014,0x4022,DICOM_T_UNK, _T("Pulse Width") }, -{ 0x0014,0x4024,DICOM_T_UNK, _T("Excitation Frequency") }, -{ 0x0014,0x4026,DICOM_T_UNK, _T("Modulation Type") }, -{ 0x0014,0x4028,DICOM_T_UNK, _T("Damping") }, -{ 0x0014,0x4030,DICOM_T_UNK, _T("Receiver Settings Sequence") }, -{ 0x0014,0x4031,DICOM_T_UNK, _T("Acquired Soundpath Length") }, -{ 0x0014,0x4032,DICOM_T_UNK, _T("Acquisition Compression Type") }, -{ 0x0014,0x4033,DICOM_T_UNK, _T("Acquisition Sample Size") }, -{ 0x0014,0x4034,DICOM_T_UNK, _T("Rectifier Smoothing") }, -{ 0x0014,0x4035,DICOM_T_UNK, _T("DAC Sequence") }, -{ 0x0014,0x4036,DICOM_T_UNK, _T("DAC Type") }, -{ 0x0014,0x4038,DICOM_T_UNK, _T("DAC Gain Points") }, -{ 0x0014,0x403A,DICOM_T_UNK, _T("DAC Time Points") }, -{ 0x0014,0x403C,DICOM_T_UNK, _T("DAC Amplitude") }, -{ 0x0014,0x4040,DICOM_T_UNK, _T("Pre-Amplifier Settings Sequence") }, -{ 0x0014,0x4050,DICOM_T_UNK, _T("Transmit Transducer Settings Sequence") }, -{ 0x0014,0x4051,DICOM_T_UNK, _T("Receive Transducer Settings Sequence") }, -{ 0x0014,0x4052,DICOM_T_UNK, _T("Incident Angle") }, -{ 0x0014,0x4054,DICOM_T_UNK, _T("Coupling Technique") }, -{ 0x0014,0x4056,DICOM_T_UNK, _T("Coupling Medium") }, -{ 0x0014,0x4057,DICOM_T_UNK, _T("Coupling Velocity") }, -{ 0x0014,0x4058,DICOM_T_UNK, _T("Probe Center Location X") }, -{ 0x0014,0x4059,DICOM_T_UNK, _T("Probe Center Location Z") }, -{ 0x0014,0x405A,DICOM_T_UNK, _T("Sound Path Length") }, -{ 0x0014,0x405C,DICOM_T_UNK, _T("Delay Law Identifier") }, -{ 0x0014,0x4060,DICOM_T_UNK, _T("Gate Settings Sequence") }, -{ 0x0014,0x4062,DICOM_T_UNK, _T("Gate Threshold") }, -{ 0x0014,0x4064,DICOM_T_UNK, _T("Velocity of Sound") }, -{ 0x0014,0x4070,DICOM_T_UNK, _T("Calibration Settings Sequence") }, -{ 0x0014,0x4072,DICOM_T_UNK, _T("Calibration Procedure") }, -{ 0x0014,0x4074,DICOM_T_UNK, _T("Procedure Version") }, -{ 0x0014,0x4076,DICOM_T_UNK, _T("Procedure Creation Date") }, -{ 0x0014,0x4078,DICOM_T_UNK, _T("Procedure Expiration Date") }, -{ 0x0014,0x407A,DICOM_T_UNK, _T("Procedure Last Modified Date") }, -{ 0x0014,0x407C,DICOM_T_UNK, _T("Calibration Time") }, -{ 0x0014,0x407E,DICOM_T_UNK, _T("Calibration Date") }, -{ 0x0014,0x4080,DICOM_T_UNK, _T("Probe Drive Equipment Sequence") }, -{ 0x0014,0x4081,DICOM_T_UNK, _T("Drive Type") }, -{ 0x0014,0x4082,DICOM_T_UNK, _T("Probe Drive Notes") }, -{ 0x0014,0x4083,DICOM_T_UNK, _T("Drive Probe Sequence") }, -{ 0x0014,0x4084,DICOM_T_UNK, _T("Probe Inductance") }, -{ 0x0014,0x4085,DICOM_T_UNK, _T("Probe Resistance") }, -{ 0x0014,0x4086,DICOM_T_UNK, _T("Receive Probe Sequence") }, -{ 0x0014,0x4087,DICOM_T_UNK, _T("Probe Drive Settings Sequence") }, -{ 0x0014,0x4088,DICOM_T_UNK, _T("Bridge Resistors") }, -{ 0x0014,0x4089,DICOM_T_UNK, _T("Probe Orientation Angle") }, -{ 0x0014,0x408B,DICOM_T_UNK, _T("User Selected Gain Y") }, -{ 0x0014,0x408C,DICOM_T_UNK, _T("User Selected Phase") }, -{ 0x0014,0x408D,DICOM_T_UNK, _T("User Selected Offset X") }, -{ 0x0014,0x408E,DICOM_T_UNK, _T("User Selected Offset Y") }, -{ 0x0014,0x4091,DICOM_T_UNK, _T("Channel Settings Sequence") }, -{ 0x0014,0x4092,DICOM_T_UNK, _T("Channel Threshold") }, -{ 0x0014,0x409A,DICOM_T_UNK, _T("Scanner Settings Sequence") }, -{ 0x0014,0x409B,DICOM_T_UNK, _T("Scan Procedure") }, -{ 0x0014,0x409C,DICOM_T_UNK, _T("Translation Rate X") }, -{ 0x0014,0x409D,DICOM_T_UNK, _T("Translation Rate Y") }, -{ 0x0014,0x409F,DICOM_T_UNK, _T("Channel Overlap") }, -{ 0x0014,0x40A0,DICOM_T_UNK, _T("Image Quality Indicator Type") }, -{ 0x0014,0x40A1,DICOM_T_UNK, _T("Image Quality Indicator Material") }, -{ 0x0014,0x40A2,DICOM_T_UNK, _T("Image Quality Indicator Size") }, -{ 0x0014,0x5002,DICOM_T_UNK, _T("LINAC Energy") }, -{ 0x0014,0x5004,DICOM_T_UNK, _T("LINAC Output") }, -{ 0x0018,0x0010,DICOM_T_UNK, _T("Contrast/Bolus Agent") }, -{ 0x0018,0x0012,DICOM_T_UNK, _T("Contrast/Bolus Agent Sequence") }, -{ 0x0018,0x0013,DICOM_T_UNK, _T("Contrast/Bolus T1 Relaxivity") }, -{ 0x0018,0x0014,DICOM_T_UNK, _T("Contrast/Bolus Administration Route Sequence") }, -{ 0x0018,0x0015,DICOM_T_UNK, _T("Body Part Examined") }, -{ 0x0018,0x0020,DICOM_T_UNK, _T("Scanning Sequence") }, -{ 0x0018,0x0021,DICOM_T_UNK, _T("Sequence Variant") }, -{ 0x0018,0x0022,DICOM_T_UNK, _T("Scan Options") }, -{ 0x0018,0x0023,DICOM_T_UNK, _T("MR Acquisition Type") }, -{ 0x0018,0x0024,DICOM_T_UNK, _T("Sequence Name") }, -{ 0x0018,0x0025,DICOM_T_UNK, _T("Angio Flag") }, -{ 0x0018,0x0026,DICOM_T_UNK, _T("Intervention Drug Information Sequence") }, -{ 0x0018,0x0027,DICOM_T_UNK, _T("Intervention Drug Stop Time") }, -{ 0x0018,0x0028,DICOM_T_UNK, _T("Intervention Drug Dose") }, -{ 0x0018,0x0029,DICOM_T_UNK, _T("Intervention Drug Code Sequence") }, -{ 0x0018,0x002A,DICOM_T_UNK, _T("Additional Drug Sequence") }, -{ 0x0018,0x0030,DICOM_T_UNK, _T("Radionuclide") }, -{ 0x0018,0x0031,DICOM_T_UNK, _T("Radiopharmaceutical") }, -{ 0x0018,0x0032,DICOM_T_UNK, _T("Energy Window Centerline") }, -{ 0x0018,0x0033,DICOM_T_UNK, _T("Energy Window Total Width") }, -{ 0x0018,0x0034,DICOM_T_UNK, _T("Intervention Drug Name") }, -{ 0x0018,0x0035,DICOM_T_UNK, _T("Intervention Drug Start Time") }, -{ 0x0018,0x0036,DICOM_T_UNK, _T("Intervention Sequence") }, -{ 0x0018,0x0037,DICOM_T_UNK, _T("Therapy Type") }, -{ 0x0018,0x0038,DICOM_T_UNK, _T("Intervention Status") }, -{ 0x0018,0x0039,DICOM_T_UNK, _T("Therapy Description") }, -{ 0x0018,0x003A,DICOM_T_UNK, _T("Intervention Description") }, -{ 0x0018,0x0040,DICOM_T_UNK, _T("Cine Rate") }, -{ 0x0018,0x0042,DICOM_T_UNK, _T("Initial Cine Run State") }, -{ 0x0018,0x0050,DICOM_T_UNK, _T("Slice Thickness") }, -{ 0x0018,0x0060,DICOM_T_UNK, _T("KVP") }, -{ 0x0018,0x0070,DICOM_T_UNK, _T("Counts Accumulated") }, -{ 0x0018,0x0071,DICOM_T_UNK, _T("Acquisition Termination Condition") }, -{ 0x0018,0x0072,DICOM_T_UNK, _T("Effective Duration") }, -{ 0x0018,0x0073,DICOM_T_UNK, _T("Acquisition Start Condition") }, -{ 0x0018,0x0074,DICOM_T_UNK, _T("Acquisition Start Condition Data") }, -{ 0x0018,0x0075,DICOM_T_UNK, _T("Acquisition Termination Condition Data") }, -{ 0x0018,0x0080,DICOM_T_UNK, _T("Repetition Time") }, -{ 0x0018,0x0081,DICOM_T_UNK, _T("Echo Time") }, -{ 0x0018,0x0082,DICOM_T_UNK, _T("Inversion Time") }, -{ 0x0018,0x0083,DICOM_T_UNK, _T("Number of Averages") }, -{ 0x0018,0x0084,DICOM_T_UNK, _T("Imaging Frequency") }, -{ 0x0018,0x0085,DICOM_T_UNK, _T("Imaged Nucleus") }, -{ 0x0018,0x0086,DICOM_T_UNK, _T("Echo Number(s)") }, -{ 0x0018,0x0087,DICOM_T_UNK, _T("Magnetic Field Strength") }, -{ 0x0018,0x0088,DICOM_T_UNK, _T("Spacing Between Slices") }, -{ 0x0018,0x0089,DICOM_T_UNK, _T("Number of Phase Encoding Steps") }, -{ 0x0018,0x0090,DICOM_T_UNK, _T("Data Collection Diameter") }, -{ 0x0018,0x0091,DICOM_T_UNK, _T("Echo Train Length") }, -{ 0x0018,0x0093,DICOM_T_UNK, _T("Percent Sampling") }, -{ 0x0018,0x0094,DICOM_T_UNK, _T("Percent Phase Field of View") }, -{ 0x0018,0x0095,DICOM_T_UNK, _T("Pixel Bandwidth") }, -{ 0x0018,0x1000,DICOM_T_UNK, _T("Device Serial Number") }, -{ 0x0018,0x1002,DICOM_T_UNK, _T("Device UID") }, -{ 0x0018,0x1003,DICOM_T_UNK, _T("Device ID") }, -{ 0x0018,0x1004,DICOM_T_UNK, _T("Plate ID") }, -{ 0x0018,0x1005,DICOM_T_UNK, _T("Generator ID") }, -{ 0x0018,0x1006,DICOM_T_UNK, _T("Grid ID") }, -{ 0x0018,0x1007,DICOM_T_UNK, _T("Cassette ID") }, -{ 0x0018,0x1008,DICOM_T_UNK, _T("Gantry ID") }, -{ 0x0018,0x1010,DICOM_T_UNK, _T("Secondary Capture Device ID") }, -{ 0x0018,0x1011,DICOM_T_UNK, _T("Hardcopy Creation Device ID") }, -{ 0x0018,0x1012,DICOM_T_UNK, _T("Date of Secondary Capture") }, -{ 0x0018,0x1014,DICOM_T_UNK, _T("Time of Secondary Capture") }, -{ 0x0018,0x1016,DICOM_T_UNK, _T("Secondary Capture Device Manufacturer") }, -{ 0x0018,0x1017,DICOM_T_UNK, _T("Hardcopy Device Manufacturer") }, -{ 0x0018,0x1018,DICOM_T_UNK, _T("Secondary Capture Device Manufacturer's Model Name") }, -{ 0x0018,0x1019,DICOM_T_UNK, _T("Secondary Capture Device Software Versions") }, -{ 0x0018,0x101A,DICOM_T_UNK, _T("Hardcopy Device Software Version") }, -{ 0x0018,0x101B,DICOM_T_UNK, _T("Hardcopy Device Manufacturer's Model Name") }, -{ 0x0018,0x1020,DICOM_T_UNK, _T("Software Version(s)") }, -{ 0x0018,0x1022,DICOM_T_UNK, _T("Video Image Format Acquired") }, -{ 0x0018,0x1023,DICOM_T_UNK, _T("Digital Image Format Acquired") }, -{ 0x0018,0x1030,DICOM_T_UNK, _T("Protocol Name") }, -{ 0x0018,0x1040,DICOM_T_UNK, _T("Contrast/Bolus Route") }, -{ 0x0018,0x1041,DICOM_T_UNK, _T("Contrast/Bolus Volume") }, -{ 0x0018,0x1042,DICOM_T_UNK, _T("Contrast/Bolus Start Time") }, -{ 0x0018,0x1043,DICOM_T_UNK, _T("Contrast/Bolus Stop Time") }, -{ 0x0018,0x1044,DICOM_T_UNK, _T("Contrast/Bolus Total Dose") }, -{ 0x0018,0x1045,DICOM_T_UNK, _T("Syringe Counts") }, -{ 0x0018,0x1046,DICOM_T_UNK, _T("Contrast Flow Rate") }, -{ 0x0018,0x1047,DICOM_T_UNK, _T("Contrast Flow Duration") }, -{ 0x0018,0x1048,DICOM_T_UNK, _T("Contrast/Bolus Ingredient") }, -{ 0x0018,0x1049,DICOM_T_UNK, _T("Contrast/Bolus Ingredient Concentration") }, -{ 0x0018,0x1050,DICOM_T_UNK, _T("Spatial Resolution") }, -{ 0x0018,0x1060,DICOM_T_UNK, _T("Trigger Time") }, -{ 0x0018,0x1061,DICOM_T_UNK, _T("Trigger Source or Type") }, -{ 0x0018,0x1062,DICOM_T_UNK, _T("Nominal Interval") }, -{ 0x0018,0x1063,DICOM_T_UNK, _T("Frame Time") }, -{ 0x0018,0x1064,DICOM_T_UNK, _T("Cardiac Framing Type") }, -{ 0x0018,0x1065,DICOM_T_UNK, _T("Frame Time Vector") }, -{ 0x0018,0x1066,DICOM_T_UNK, _T("Frame Delay") }, -{ 0x0018,0x1067,DICOM_T_UNK, _T("Image Trigger Delay") }, -{ 0x0018,0x1068,DICOM_T_UNK, _T("Multiplex Group Time Offset") }, -{ 0x0018,0x1069,DICOM_T_UNK, _T("Trigger Time Offset") }, -{ 0x0018,0x106A,DICOM_T_UNK, _T("Synchronization Trigger") }, -{ 0x0018,0x106C,DICOM_T_UNK, _T("Synchronization Channel") }, -{ 0x0018,0x106E,DICOM_T_UNK, _T("Trigger Sample Position") }, -{ 0x0018,0x1070,DICOM_T_UNK, _T("Radiopharmaceutical Route") }, -{ 0x0018,0x1071,DICOM_T_UNK, _T("Radiopharmaceutical Volume") }, -{ 0x0018,0x1072,DICOM_T_UNK, _T("Radiopharmaceutical Start Time") }, -{ 0x0018,0x1073,DICOM_T_UNK, _T("Radiopharmaceutical Stop Time") }, -{ 0x0018,0x1074,DICOM_T_UNK, _T("Radionuclide Total Dose") }, -{ 0x0018,0x1075,DICOM_T_UNK, _T("Radionuclide Half Life") }, -{ 0x0018,0x1076,DICOM_T_UNK, _T("Radionuclide Positron Fraction") }, -{ 0x0018,0x1077,DICOM_T_UNK, _T("Radiopharmaceutical Specific Activity") }, -{ 0x0018,0x1078,DICOM_T_UNK, _T("Radiopharmaceutical Start DateTime") }, -{ 0x0018,0x1079,DICOM_T_UNK, _T("Radiopharmaceutical Stop DateTime") }, -{ 0x0018,0x1080,DICOM_T_UNK, _T("Beat Rejection Flag") }, -{ 0x0018,0x1081,DICOM_T_UNK, _T("Low R-R Value") }, -{ 0x0018,0x1082,DICOM_T_UNK, _T("High R-R Value") }, -{ 0x0018,0x1083,DICOM_T_UNK, _T("Intervals Acquired") }, -{ 0x0018,0x1084,DICOM_T_UNK, _T("Intervals Rejected") }, -{ 0x0018,0x1085,DICOM_T_UNK, _T("PVC Rejection") }, -{ 0x0018,0x1086,DICOM_T_UNK, _T("Skip Beats") }, -{ 0x0018,0x1088,DICOM_T_UNK, _T("Heart Rate") }, -{ 0x0018,0x1090,DICOM_T_UNK, _T("Cardiac Number of Images") }, -{ 0x0018,0x1094,DICOM_T_UNK, _T("Trigger Window") }, -{ 0x0018,0x1100,DICOM_T_UNK, _T("Reconstruction Diameter") }, -{ 0x0018,0x1110,DICOM_T_UNK, _T("Distance Source to Detector") }, -{ 0x0018,0x1111,DICOM_T_UNK, _T("Distance Source to Patient") }, -{ 0x0018,0x1114,DICOM_T_UNK, _T("Estimated Radiographic Magnification Factor") }, -{ 0x0018,0x1120,DICOM_T_UNK, _T("Gantry/Detector Tilt") }, -{ 0x0018,0x1121,DICOM_T_UNK, _T("Gantry/Detector Slew") }, -{ 0x0018,0x1130,DICOM_T_UNK, _T("Table Height") }, -{ 0x0018,0x1131,DICOM_T_UNK, _T("Table Traverse") }, -{ 0x0018,0x1134,DICOM_T_UNK, _T("Table Motion") }, -{ 0x0018,0x1135,DICOM_T_UNK, _T("Table Vertical Increment") }, -{ 0x0018,0x1136,DICOM_T_UNK, _T("Table Lateral Increment") }, -{ 0x0018,0x1137,DICOM_T_UNK, _T("Table Longitudinal Increment") }, -{ 0x0018,0x1138,DICOM_T_UNK, _T("Table Angle") }, -{ 0x0018,0x113A,DICOM_T_UNK, _T("Table Type") }, -{ 0x0018,0x1140,DICOM_T_UNK, _T("Rotation Direction") }, -{ 0x0018,0x1141,DICOM_T_UNK, _T("Angular Position") }, -{ 0x0018,0x1142,DICOM_T_UNK, _T("Radial Position") }, -{ 0x0018,0x1143,DICOM_T_UNK, _T("Scan Arc") }, -{ 0x0018,0x1144,DICOM_T_UNK, _T("Angular Step") }, -{ 0x0018,0x1145,DICOM_T_UNK, _T("Center of Rotation Offset") }, -{ 0x0018,0x1146,DICOM_T_UNK, _T("Rotation Offset") }, -{ 0x0018,0x1147,DICOM_T_UNK, _T("Field of View Shape") }, -{ 0x0018,0x1149,DICOM_T_UNK, _T("Field of View Dimension(s)") }, -{ 0x0018,0x1150,DICOM_T_UNK, _T("Exposure Time") }, -{ 0x0018,0x1151,DICOM_T_UNK, _T("X-Ray Tube Current") }, -{ 0x0018,0x1152,DICOM_T_UNK, _T("Exposure") }, -{ 0x0018,0x1153,DICOM_T_UNK, _T("Exposure in µAs") }, -{ 0x0018,0x1154,DICOM_T_UNK, _T("Average Pulse Width") }, -{ 0x0018,0x1155,DICOM_T_UNK, _T("Radiation Setting") }, -{ 0x0018,0x1156,DICOM_T_UNK, _T("Rectification Type") }, -{ 0x0018,0x115A,DICOM_T_UNK, _T("Radiation Mode") }, -{ 0x0018,0x115E,DICOM_T_UNK, _T("Image and Fluoroscopy Area Dose Product") }, -{ 0x0018,0x1160,DICOM_T_UNK, _T("Filter Type") }, -{ 0x0018,0x1161,DICOM_T_UNK, _T("Type of Filters") }, -{ 0x0018,0x1162,DICOM_T_UNK, _T("Intensifier Size") }, -{ 0x0018,0x1164,DICOM_T_UNK, _T("Imager Pixel Spacing") }, -{ 0x0018,0x1166,DICOM_T_UNK, _T("Grid") }, -{ 0x0018,0x1170,DICOM_T_UNK, _T("Generator Power") }, -{ 0x0018,0x1180,DICOM_T_UNK, _T("Collimator/grid Name") }, -{ 0x0018,0x1181,DICOM_T_UNK, _T("Collimator Type") }, -{ 0x0018,0x1182,DICOM_T_UNK, _T("Focal Distance") }, -{ 0x0018,0x1183,DICOM_T_UNK, _T("X Focus Center") }, -{ 0x0018,0x1184,DICOM_T_UNK, _T("Y Focus Center") }, -{ 0x0018,0x1190,DICOM_T_UNK, _T("Focal Spot(s)") }, -{ 0x0018,0x1191,DICOM_T_UNK, _T("Anode Target Material") }, -{ 0x0018,0x11A0,DICOM_T_UNK, _T("Body Part Thickness") }, -{ 0x0018,0x11A2,DICOM_T_UNK, _T("Compression Force") }, -{ 0x0018,0x11A4,DICOM_T_UNK, _T("Paddle Description") }, -{ 0x0018,0x1200,DICOM_T_UNK, _T("Date of Last Calibration") }, -{ 0x0018,0x1201,DICOM_T_UNK, _T("Time of Last Calibration") }, -{ 0x0018,0x1202,DICOM_T_UNK, _T("DateTime of Last Calibration") }, -{ 0x0018,0x1210,DICOM_T_UNK, _T("Convolution Kernel") }, -{ 0x0018,0x1240,DICOM_T_UNK, _T("Upper/Lower Pixel Values") }, -{ 0x0018,0x1242,DICOM_T_UNK, _T("Actual Frame Duration") }, -{ 0x0018,0x1243,DICOM_T_UNK, _T("Count Rate") }, -{ 0x0018,0x1244,DICOM_T_UNK, _T("Preferred Playback Sequencing") }, -{ 0x0018,0x1250,DICOM_T_UNK, _T("Receive Coil Name") }, -{ 0x0018,0x1251,DICOM_T_UNK, _T("Transmit Coil Name") }, -{ 0x0018,0x1260,DICOM_T_UNK, _T("Plate Type") }, -{ 0x0018,0x1261,DICOM_T_UNK, _T("Phosphor Type") }, -{ 0x0018,0x1300,DICOM_T_UNK, _T("Scan Velocity") }, -{ 0x0018,0x1301,DICOM_T_UNK, _T("Whole Body Technique") }, -{ 0x0018,0x1302,DICOM_T_UNK, _T("Scan Length") }, -{ 0x0018,0x1310,DICOM_T_UNK, _T("Acquisition Matrix") }, -{ 0x0018,0x1312,DICOM_T_UNK, _T("In-plane Phase Encoding Direction") }, -{ 0x0018,0x1314,DICOM_T_UNK, _T("Flip Angle") }, -{ 0x0018,0x1315,DICOM_T_UNK, _T("Variable Flip Angle Flag") }, -{ 0x0018,0x1316,DICOM_T_UNK, _T("SAR") }, -{ 0x0018,0x1318,DICOM_T_UNK, _T("dB/dt") }, -{ 0x0018,0x1400,DICOM_T_UNK, _T("Acquisition Device Processing Description") }, -{ 0x0018,0x1401,DICOM_T_UNK, _T("Acquisition Device Processing Code") }, -{ 0x0018,0x1402,DICOM_T_UNK, _T("Cassette Orientation") }, -{ 0x0018,0x1403,DICOM_T_UNK, _T("Cassette Size") }, -{ 0x0018,0x1404,DICOM_T_UNK, _T("Exposures on Plate") }, -{ 0x0018,0x1405,DICOM_T_UNK, _T("Relative X-Ray Exposure") }, -{ 0x0018,0x1411,DICOM_T_UNK, _T("Exposure Index") }, -{ 0x0018,0x1412,DICOM_T_UNK, _T("Target Exposure Index") }, -{ 0x0018,0x1413,DICOM_T_UNK, _T("Deviation Index") }, -{ 0x0018,0x1450,DICOM_T_UNK, _T("Column Angulation") }, -{ 0x0018,0x1460,DICOM_T_UNK, _T("Tomo Layer Height") }, -{ 0x0018,0x1470,DICOM_T_UNK, _T("Tomo Angle") }, -{ 0x0018,0x1480,DICOM_T_UNK, _T("Tomo Time") }, -{ 0x0018,0x1490,DICOM_T_UNK, _T("Tomo Type") }, -{ 0x0018,0x1491,DICOM_T_UNK, _T("Tomo Class") }, -{ 0x0018,0x1495,DICOM_T_UNK, _T("Number of Tomosynthesis Source Images") }, -{ 0x0018,0x1500,DICOM_T_UNK, _T("Positioner Motion") }, -{ 0x0018,0x1508,DICOM_T_UNK, _T("Positioner Type") }, -{ 0x0018,0x1510,DICOM_T_UNK, _T("Positioner Primary Angle") }, -{ 0x0018,0x1511,DICOM_T_UNK, _T("Positioner Secondary Angle") }, -{ 0x0018,0x1520,DICOM_T_UNK, _T("Positioner Primary Angle Increment") }, -{ 0x0018,0x1521,DICOM_T_UNK, _T("Positioner Secondary Angle Increment") }, -{ 0x0018,0x1530,DICOM_T_UNK, _T("Detector Primary Angle") }, -{ 0x0018,0x1531,DICOM_T_UNK, _T("Detector Secondary Angle") }, -{ 0x0018,0x1600,DICOM_T_UNK, _T("Shutter Shape") }, -{ 0x0018,0x1602,DICOM_T_UNK, _T("Shutter Left Vertical Edge") }, -{ 0x0018,0x1604,DICOM_T_UNK, _T("Shutter Right Vertical Edge") }, -{ 0x0018,0x1606,DICOM_T_UNK, _T("Shutter Upper Horizontal Edge") }, -{ 0x0018,0x1608,DICOM_T_UNK, _T("Shutter Lower Horizontal Edge") }, -{ 0x0018,0x1610,DICOM_T_UNK, _T("Center of Circular Shutter") }, -{ 0x0018,0x1612,DICOM_T_UNK, _T("Radius of Circular Shutter") }, -{ 0x0018,0x1620,DICOM_T_UNK, _T("Vertices of the Polygonal Shutter") }, -{ 0x0018,0x1622,DICOM_T_UNK, _T("Shutter Presentation Value") }, -{ 0x0018,0x1623,DICOM_T_UNK, _T("Shutter Overlay Group") }, -{ 0x0018,0x1624,DICOM_T_UNK, _T("Shutter Presentation Color CIELab Value") }, -{ 0x0018,0x1700,DICOM_T_UNK, _T("Collimator Shape") }, -{ 0x0018,0x1702,DICOM_T_UNK, _T("Collimator Left Vertical Edge") }, -{ 0x0018,0x1704,DICOM_T_UNK, _T("Collimator Right Vertical Edge") }, -{ 0x0018,0x1706,DICOM_T_UNK, _T("Collimator Upper Horizontal Edge") }, -{ 0x0018,0x1708,DICOM_T_UNK, _T("Collimator Lower Horizontal Edge") }, -{ 0x0018,0x1710,DICOM_T_UNK, _T("Center of Circular Collimator") }, -{ 0x0018,0x1712,DICOM_T_UNK, _T("Radius of Circular Collimator") }, -{ 0x0018,0x1720,DICOM_T_UNK, _T("Vertices of the Polygonal Collimator") }, -{ 0x0018,0x1800,DICOM_T_UNK, _T("Acquisition Time Synchronized") }, -{ 0x0018,0x1801,DICOM_T_UNK, _T("Time Source") }, -{ 0x0018,0x1802,DICOM_T_UNK, _T("Time Distribution Protocol") }, -{ 0x0018,0x1803,DICOM_T_UNK, _T("NTP Source Address") }, -{ 0x0018,0x2001,DICOM_T_UNK, _T("Page Number Vector") }, -{ 0x0018,0x2002,DICOM_T_UNK, _T("Frame Label Vector") }, -{ 0x0018,0x2003,DICOM_T_UNK, _T("Frame Primary Angle Vector") }, -{ 0x0018,0x2004,DICOM_T_UNK, _T("Frame Secondary Angle Vector") }, -{ 0x0018,0x2005,DICOM_T_UNK, _T("Slice Location Vector") }, -{ 0x0018,0x2006,DICOM_T_UNK, _T("Display Window Label Vector") }, -{ 0x0018,0x2010,DICOM_T_UNK, _T("Nominal Scanned Pixel Spacing") }, -{ 0x0018,0x2020,DICOM_T_UNK, _T("Digitizing Device Transport Direction") }, -{ 0x0018,0x2030,DICOM_T_UNK, _T("Rotation of Scanned Film") }, -{ 0x0018,0x2041,DICOM_T_UNK, _T("Biopsy Target Sequence") }, -{ 0x0018,0x2042,DICOM_T_UNK, _T("Target UID") }, -{ 0x0018,0x2043,DICOM_T_UNK, _T("Localizing Cursor Position") }, -{ 0x0018,0x2044,DICOM_T_UNK, _T("Calculated Target Position") }, -{ 0x0018,0x2045,DICOM_T_UNK, _T("Target Label") }, -{ 0x0018,0x2046,DICOM_T_UNK, _T("Displayed Z Value") }, -{ 0x0018,0x3100,DICOM_T_UNK, _T("IVUS Acquisition") }, -{ 0x0018,0x3101,DICOM_T_UNK, _T("IVUS Pullback Rate") }, -{ 0x0018,0x3102,DICOM_T_UNK, _T("IVUS Gated Rate") }, -{ 0x0018,0x3103,DICOM_T_UNK, _T("IVUS Pullback Start Frame Number") }, -{ 0x0018,0x3104,DICOM_T_UNK, _T("IVUS Pullback Stop Frame Number") }, -{ 0x0018,0x3105,DICOM_T_UNK, _T("Lesion Number") }, -{ 0x0018,0x4000,DICOM_T_UNK, _T("Acquisition Comments") }, -{ 0x0018,0x5000,DICOM_T_UNK, _T("Output Power") }, -{ 0x0018,0x5010,DICOM_T_UNK, _T("Transducer Data") }, -{ 0x0018,0x5012,DICOM_T_UNK, _T("Focus Depth") }, -{ 0x0018,0x5020,DICOM_T_UNK, _T("Processing Function") }, -{ 0x0018,0x5021,DICOM_T_UNK, _T("Postprocessing Function") }, -{ 0x0018,0x5022,DICOM_T_UNK, _T("Mechanical Index") }, -{ 0x0018,0x5024,DICOM_T_UNK, _T("Bone Thermal Index") }, -{ 0x0018,0x5026,DICOM_T_UNK, _T("Cranial Thermal Index") }, -{ 0x0018,0x5027,DICOM_T_UNK, _T("Soft Tissue Thermal Index") }, -{ 0x0018,0x5028,DICOM_T_UNK, _T("Soft Tissue-focus Thermal Index") }, -{ 0x0018,0x5029,DICOM_T_UNK, _T("Soft Tissue-surface Thermal Index") }, -{ 0x0018,0x5030,DICOM_T_UNK, _T("Dynamic Range") }, -{ 0x0018,0x5040,DICOM_T_UNK, _T("Total Gain") }, -{ 0x0018,0x5050,DICOM_T_UNK, _T("Depth of Scan Field") }, -{ 0x0018,0x5100,DICOM_T_UNK, _T("Patient Position") }, -{ 0x0018,0x5101,DICOM_T_UNK, _T("View Position") }, -{ 0x0018,0x5104,DICOM_T_UNK, _T("Projection Eponymous Name Code Sequence") }, -{ 0x0018,0x5210,DICOM_T_UNK, _T("Image Transformation Matrix") }, -{ 0x0018,0x5212,DICOM_T_UNK, _T("Image Translation Vector") }, -{ 0x0018,0x6000,DICOM_T_UNK, _T("Sensitivity") }, -{ 0x0018,0x6011,DICOM_T_UNK, _T("Sequence of Ultrasound Regions") }, -{ 0x0018,0x6012,DICOM_T_UNK, _T("Region Spatial Format") }, -{ 0x0018,0x6014,DICOM_T_UNK, _T("Region Data Type") }, -{ 0x0018,0x6016,DICOM_T_UNK, _T("Region Flags") }, -{ 0x0018,0x6018,DICOM_T_UNK, _T("Region Location Min X0") }, -{ 0x0018,0x601A,DICOM_T_UNK, _T("Region Location Min Y0") }, -{ 0x0018,0x601C,DICOM_T_UNK, _T("Region Location Max X1") }, -{ 0x0018,0x601E,DICOM_T_UNK, _T("Region Location Max Y1") }, -{ 0x0018,0x6020,DICOM_T_UNK, _T("Reference Pixel X0") }, -{ 0x0018,0x6022,DICOM_T_UNK, _T("Reference Pixel Y0") }, -{ 0x0018,0x6024,DICOM_T_UNK, _T("Physical Units X Direction") }, -{ 0x0018,0x6026,DICOM_T_UNK, _T("Physical Units Y Direction") }, -{ 0x0018,0x6028,DICOM_T_UNK, _T("Reference Pixel Physical Value X") }, -{ 0x0018,0x602A,DICOM_T_UNK, _T("Reference Pixel Physical Value Y") }, -{ 0x0018,0x602C,DICOM_T_UNK, _T("Physical Delta X") }, -{ 0x0018,0x602E,DICOM_T_UNK, _T("Physical Delta Y") }, -{ 0x0018,0x6030,DICOM_T_UNK, _T("Transducer Frequency") }, -{ 0x0018,0x6031,DICOM_T_UNK, _T("Transducer Type") }, -{ 0x0018,0x6032,DICOM_T_UNK, _T("Pulse Repetition Frequency") }, -{ 0x0018,0x6034,DICOM_T_UNK, _T("Doppler Correction Angle") }, -{ 0x0018,0x6036,DICOM_T_UNK, _T("Steering Angle") }, -{ 0x0018,0x6038,DICOM_T_UNK, _T("Doppler Sample Volume X Position (Retired)") }, -{ 0x0018,0x6039,DICOM_T_UNK, _T("Doppler Sample Volume X Position") }, -{ 0x0018,0x603A,DICOM_T_UNK, _T("Doppler Sample Volume Y Position (Retired)") }, -{ 0x0018,0x603B,DICOM_T_UNK, _T("Doppler Sample Volume Y Position") }, -{ 0x0018,0x603C,DICOM_T_UNK, _T("TM-Line Position X0 (Retired)") }, -{ 0x0018,0x603D,DICOM_T_UNK, _T("TM-Line Position X0") }, -{ 0x0018,0x603E,DICOM_T_UNK, _T("TM-Line Position Y0 (Retired)") }, -{ 0x0018,0x603F,DICOM_T_UNK, _T("TM-Line Position Y0") }, -{ 0x0018,0x6040,DICOM_T_UNK, _T("TM-Line Position X1 (Retired)") }, -{ 0x0018,0x6041,DICOM_T_UNK, _T("TM-Line Position X1") }, -{ 0x0018,0x6042,DICOM_T_UNK, _T("TM-Line Position Y1 (Retired)") }, -{ 0x0018,0x6043,DICOM_T_UNK, _T("TM-Line Position Y1") }, -{ 0x0018,0x6044,DICOM_T_UNK, _T("Pixel Component Organization") }, -{ 0x0018,0x6046,DICOM_T_UNK, _T("Pixel Component Mask") }, -{ 0x0018,0x6048,DICOM_T_UNK, _T("Pixel Component Range Start") }, -{ 0x0018,0x604A,DICOM_T_UNK, _T("Pixel Component Range Stop") }, -{ 0x0018,0x604C,DICOM_T_UNK, _T("Pixel Component Physical Units") }, -{ 0x0018,0x604E,DICOM_T_UNK, _T("Pixel Component Data Type") }, -{ 0x0018,0x6050,DICOM_T_UNK, _T("Number of Table Break Points") }, -{ 0x0018,0x6052,DICOM_T_UNK, _T("Table of X Break Points") }, -{ 0x0018,0x6054,DICOM_T_UNK, _T("Table of Y Break Points") }, -{ 0x0018,0x6056,DICOM_T_UNK, _T("Number of Table Entries") }, -{ 0x0018,0x6058,DICOM_T_UNK, _T("Table of Pixel Values") }, -{ 0x0018,0x605A,DICOM_T_UNK, _T("Table of Parameter Values") }, -{ 0x0018,0x6060,DICOM_T_UNK, _T("R Wave Time Vector") }, -{ 0x0018,0x7000,DICOM_T_UNK, _T("Detector Conditions Nominal Flag") }, -{ 0x0018,0x7001,DICOM_T_UNK, _T("Detector Temperature") }, -{ 0x0018,0x7004,DICOM_T_UNK, _T("Detector Type") }, -{ 0x0018,0x7005,DICOM_T_UNK, _T("Detector Configuration") }, -{ 0x0018,0x7006,DICOM_T_UNK, _T("Detector Description") }, -{ 0x0018,0x7008,DICOM_T_UNK, _T("Detector Mode") }, -{ 0x0018,0x700A,DICOM_T_UNK, _T("Detector ID") }, -{ 0x0018,0x700C,DICOM_T_UNK, _T("Date of Last Detector Calibration") }, -{ 0x0018,0x700E,DICOM_T_UNK, _T("Time of Last Detector Calibration") }, -{ 0x0018,0x7010,DICOM_T_UNK, _T("Exposures on Detector Since Last Calibration") }, -{ 0x0018,0x7011,DICOM_T_UNK, _T("Exposures on Detector Since Manufactured") }, -{ 0x0018,0x7012,DICOM_T_UNK, _T("Detector Time Since Last Exposure") }, -{ 0x0018,0x7014,DICOM_T_UNK, _T("Detector Active Time") }, -{ 0x0018,0x7016,DICOM_T_UNK, _T("Detector Activation Offset From Exposure") }, -{ 0x0018,0x701A,DICOM_T_UNK, _T("Detector Binning") }, -{ 0x0018,0x7020,DICOM_T_UNK, _T("Detector Element Physical Size") }, -{ 0x0018,0x7022,DICOM_T_UNK, _T("Detector Element Spacing") }, -{ 0x0018,0x7024,DICOM_T_UNK, _T("Detector Active Shape") }, -{ 0x0018,0x7026,DICOM_T_UNK, _T("Detector Active Dimension(s)") }, -{ 0x0018,0x7028,DICOM_T_UNK, _T("Detector Active Origin") }, -{ 0x0018,0x702A,DICOM_T_UNK, _T("Detector Manufacturer Name") }, -{ 0x0018,0x702B,DICOM_T_UNK, _T("Detector Manufacturer's Model Name") }, -{ 0x0018,0x7030,DICOM_T_UNK, _T("Field of View Origin") }, -{ 0x0018,0x7032,DICOM_T_UNK, _T("Field of View Rotation") }, -{ 0x0018,0x7034,DICOM_T_UNK, _T("Field of View Horizontal Flip") }, -{ 0x0018,0x7036,DICOM_T_UNK, _T("Pixel Data Area Origin Relative To FOV") }, -{ 0x0018,0x7038,DICOM_T_UNK, _T("Pixel Data Area Rotation Angle Relative To FOV") }, -{ 0x0018,0x7040,DICOM_T_UNK, _T("Grid Absorbing Material") }, -{ 0x0018,0x7041,DICOM_T_UNK, _T("Grid Spacing Material") }, -{ 0x0018,0x7042,DICOM_T_UNK, _T("Grid Thickness") }, -{ 0x0018,0x7044,DICOM_T_UNK, _T("Grid Pitch") }, -{ 0x0018,0x7046,DICOM_T_UNK, _T("Grid Aspect Ratio") }, -{ 0x0018,0x7048,DICOM_T_UNK, _T("Grid Period") }, -{ 0x0018,0x704C,DICOM_T_UNK, _T("Grid Focal Distance") }, -{ 0x0018,0x7050,DICOM_T_UNK, _T("Filter Material") }, -{ 0x0018,0x7052,DICOM_T_UNK, _T("Filter Thickness Minimum") }, -{ 0x0018,0x7054,DICOM_T_UNK, _T("Filter Thickness Maximum") }, -{ 0x0018,0x7056,DICOM_T_UNK, _T("Filter Beam Path Length Minimum") }, -{ 0x0018,0x7058,DICOM_T_UNK, _T("Filter Beam Path Length Maximum") }, -{ 0x0018,0x7060,DICOM_T_UNK, _T("Exposure Control Mode") }, -{ 0x0018,0x7062,DICOM_T_UNK, _T("Exposure Control Mode Description") }, -{ 0x0018,0x7064,DICOM_T_UNK, _T("Exposure Status") }, -{ 0x0018,0x7065,DICOM_T_UNK, _T("Phototimer Setting") }, -{ 0x0018,0x8150,DICOM_T_UNK, _T("Exposure Time in µS") }, -{ 0x0018,0x8151,DICOM_T_UNK, _T("X-Ray Tube Current in µA") }, -{ 0x0018,0x9004,DICOM_T_UNK, _T("Content Qualification") }, -{ 0x0018,0x9005,DICOM_T_UNK, _T("Pulse Sequence Name") }, -{ 0x0018,0x9006,DICOM_T_UNK, _T("MR Imaging Modifier Sequence") }, -{ 0x0018,0x9008,DICOM_T_UNK, _T("Echo Pulse Sequence") }, -{ 0x0018,0x9009,DICOM_T_UNK, _T("Inversion Recovery") }, -{ 0x0018,0x9010,DICOM_T_UNK, _T("Flow Compensation") }, -{ 0x0018,0x9011,DICOM_T_UNK, _T("Multiple Spin Echo") }, -{ 0x0018,0x9012,DICOM_T_UNK, _T("Multi-planar Excitation") }, -{ 0x0018,0x9014,DICOM_T_UNK, _T("Phase Contrast") }, -{ 0x0018,0x9015,DICOM_T_UNK, _T("Time of Flight Contrast") }, -{ 0x0018,0x9016,DICOM_T_UNK, _T("Spoiling") }, -{ 0x0018,0x9017,DICOM_T_UNK, _T("Steady State Pulse Sequence") }, -{ 0x0018,0x9018,DICOM_T_UNK, _T("Echo Planar Pulse Sequence") }, -{ 0x0018,0x9019,DICOM_T_UNK, _T("Tag Angle First Axis") }, -{ 0x0018,0x9020,DICOM_T_UNK, _T("Magnetization Transfer") }, -{ 0x0018,0x9021,DICOM_T_UNK, _T("T2 Preparation") }, -{ 0x0018,0x9022,DICOM_T_UNK, _T("Blood Signal Nulling") }, -{ 0x0018,0x9024,DICOM_T_UNK, _T("Saturation Recovery") }, -{ 0x0018,0x9025,DICOM_T_UNK, _T("Spectrally Selected Suppression") }, -{ 0x0018,0x9026,DICOM_T_UNK, _T("Spectrally Selected Excitation") }, -{ 0x0018,0x9027,DICOM_T_UNK, _T("Spatial Pre-saturation") }, -{ 0x0018,0x9028,DICOM_T_UNK, _T("Tagging") }, -{ 0x0018,0x9029,DICOM_T_UNK, _T("Oversampling Phase") }, -{ 0x0018,0x9030,DICOM_T_UNK, _T("Tag Spacing First Dimension") }, -{ 0x0018,0x9032,DICOM_T_UNK, _T("Geometry of k-Space Traversal") }, -{ 0x0018,0x9033,DICOM_T_UNK, _T("Segmented k-Space Traversal") }, -{ 0x0018,0x9034,DICOM_T_UNK, _T("Rectilinear Phase Encode Reordering") }, -{ 0x0018,0x9035,DICOM_T_UNK, _T("Tag Thickness") }, -{ 0x0018,0x9036,DICOM_T_UNK, _T("Partial Fourier Direction") }, -{ 0x0018,0x9037,DICOM_T_UNK, _T("Cardiac Synchronization Technique") }, -{ 0x0018,0x9041,DICOM_T_UNK, _T("Receive Coil Manufacturer Name") }, -{ 0x0018,0x9042,DICOM_T_UNK, _T("MR Receive Coil Sequence") }, -{ 0x0018,0x9043,DICOM_T_UNK, _T("Receive Coil Type") }, -{ 0x0018,0x9044,DICOM_T_UNK, _T("Quadrature Receive Coil") }, -{ 0x0018,0x9045,DICOM_T_UNK, _T("Multi-Coil Definition Sequence") }, -{ 0x0018,0x9046,DICOM_T_UNK, _T("Multi-Coil Configuration") }, -{ 0x0018,0x9047,DICOM_T_UNK, _T("Multi-Coil Element Name") }, -{ 0x0018,0x9048,DICOM_T_UNK, _T("Multi-Coil Element Used") }, -{ 0x0018,0x9049,DICOM_T_UNK, _T("MR Transmit Coil Sequence") }, -{ 0x0018,0x9050,DICOM_T_UNK, _T("Transmit Coil Manufacturer Name") }, -{ 0x0018,0x9051,DICOM_T_UNK, _T("Transmit Coil Type") }, -{ 0x0018,0x9052,DICOM_T_UNK, _T("Spectral Width") }, -{ 0x0018,0x9053,DICOM_T_UNK, _T("Chemical Shift Reference") }, -{ 0x0018,0x9054,DICOM_T_UNK, _T("Volume Localization Technique") }, -{ 0x0018,0x9058,DICOM_T_UNK, _T("MR Acquisition Frequency Encoding Steps") }, -{ 0x0018,0x9059,DICOM_T_UNK, _T("De-coupling") }, -{ 0x0018,0x9060,DICOM_T_UNK, _T("De-coupled Nucleus") }, -{ 0x0018,0x9061,DICOM_T_UNK, _T("De-coupling Frequency") }, -{ 0x0018,0x9062,DICOM_T_UNK, _T("De-coupling Method") }, -{ 0x0018,0x9063,DICOM_T_UNK, _T("De-coupling Chemical Shift Reference") }, -{ 0x0018,0x9064,DICOM_T_UNK, _T("k-space Filtering") }, -{ 0x0018,0x9065,DICOM_T_UNK, _T("Time Domain Filtering") }, -{ 0x0018,0x9066,DICOM_T_UNK, _T("Number of Zero Fills") }, -{ 0x0018,0x9067,DICOM_T_UNK, _T("Baseline Correction") }, -{ 0x0018,0x9069,DICOM_T_UNK, _T("Parallel Reduction Factor In-plane") }, -{ 0x0018,0x9070,DICOM_T_UNK, _T("Cardiac R-R Interval Specified") }, -{ 0x0018,0x9073,DICOM_T_UNK, _T("Acquisition Duration") }, -{ 0x0018,0x9074,DICOM_T_UNK, _T("Frame Acquisition DateTime") }, -{ 0x0018,0x9075,DICOM_T_UNK, _T("Diffusion Directionality") }, -{ 0x0018,0x9076,DICOM_T_UNK, _T("Diffusion Gradient Direction Sequence") }, -{ 0x0018,0x9077,DICOM_T_UNK, _T("Parallel Acquisition") }, -{ 0x0018,0x9078,DICOM_T_UNK, _T("Parallel Acquisition Technique") }, -{ 0x0018,0x9079,DICOM_T_UNK, _T("Inversion Times") }, -{ 0x0018,0x9080,DICOM_T_UNK, _T("Metabolite Map Description") }, -{ 0x0018,0x9081,DICOM_T_UNK, _T("Partial Fourier") }, -{ 0x0018,0x9082,DICOM_T_UNK, _T("Effective Echo Time") }, -{ 0x0018,0x9083,DICOM_T_UNK, _T("Metabolite Map Code Sequence") }, -{ 0x0018,0x9084,DICOM_T_UNK, _T("Chemical Shift Sequence") }, -{ 0x0018,0x9085,DICOM_T_UNK, _T("Cardiac Signal Source") }, -{ 0x0018,0x9087,DICOM_T_UNK, _T("Diffusion b-value") }, -{ 0x0018,0x9089,DICOM_T_UNK, _T("Diffusion Gradient Orientation") }, -{ 0x0018,0x9090,DICOM_T_UNK, _T("Velocity Encoding Direction") }, -{ 0x0018,0x9091,DICOM_T_UNK, _T("Velocity Encoding Minimum Value") }, -{ 0x0018,0x9092,DICOM_T_UNK, _T("Velocity Encoding Acquisition Sequence") }, -{ 0x0018,0x9093,DICOM_T_UNK, _T("Number of k-Space Trajectories") }, -{ 0x0018,0x9094,DICOM_T_UNK, _T("Coverage of k-Space") }, -{ 0x0018,0x9095,DICOM_T_UNK, _T("Spectroscopy Acquisition Phase Rows") }, -{ 0x0018,0x9096,DICOM_T_UNK, _T("Parallel Reduction Factor In-plane (Retired)") }, -{ 0x0018,0x9098,DICOM_T_UNK, _T("Transmitter Frequency") }, -{ 0x0018,0x9100,DICOM_T_UNK, _T("Resonant Nucleus") }, -{ 0x0018,0x9101,DICOM_T_UNK, _T("Frequency Correction") }, -{ 0x0018,0x9103,DICOM_T_UNK, _T("MR Spectroscopy FOV/Geometry Sequence") }, -{ 0x0018,0x9104,DICOM_T_UNK, _T("Slab Thickness") }, -{ 0x0018,0x9105,DICOM_T_UNK, _T("Slab Orientation") }, -{ 0x0018,0x9106,DICOM_T_UNK, _T("Mid Slab Position") }, -{ 0x0018,0x9107,DICOM_T_UNK, _T("MR Spatial Saturation Sequence") }, -{ 0x0018,0x9112,DICOM_T_UNK, _T("MR Timing and Related Parameters Sequence") }, -{ 0x0018,0x9114,DICOM_T_UNK, _T("MR Echo Sequence") }, -{ 0x0018,0x9115,DICOM_T_UNK, _T("MR Modifier Sequence") }, -{ 0x0018,0x9117,DICOM_T_UNK, _T("MR Diffusion Sequence") }, -{ 0x0018,0x9118,DICOM_T_UNK, _T("Cardiac Synchronization Sequence") }, -{ 0x0018,0x9119,DICOM_T_UNK, _T("MR Averages Sequence") }, -{ 0x0018,0x9125,DICOM_T_UNK, _T("MR FOV/Geometry Sequence") }, -{ 0x0018,0x9126,DICOM_T_UNK, _T("Volume Localization Sequence") }, -{ 0x0018,0x9127,DICOM_T_UNK, _T("Spectroscopy Acquisition Data Columns") }, -{ 0x0018,0x9147,DICOM_T_UNK, _T("Diffusion Anisotropy Type") }, -{ 0x0018,0x9151,DICOM_T_UNK, _T("Frame Reference DateTime") }, -{ 0x0018,0x9152,DICOM_T_UNK, _T("MR Metabolite Map Sequence") }, -{ 0x0018,0x9155,DICOM_T_UNK, _T("Parallel Reduction Factor out-of-plane") }, -{ 0x0018,0x9159,DICOM_T_UNK, _T("Spectroscopy Acquisition Out-of-plane Phase Steps") }, -{ 0x0018,0x9166,DICOM_T_UNK, _T("Bulk Motion Status") }, -{ 0x0018,0x9168,DICOM_T_UNK, _T("Parallel Reduction Factor Second In-plane") }, -{ 0x0018,0x9169,DICOM_T_UNK, _T("Cardiac Beat Rejection Technique") }, -{ 0x0018,0x9170,DICOM_T_UNK, _T("Respiratory Motion Compensation Technique") }, -{ 0x0018,0x9171,DICOM_T_UNK, _T("Respiratory Signal Source") }, -{ 0x0018,0x9172,DICOM_T_UNK, _T("Bulk Motion Compensation Technique") }, -{ 0x0018,0x9173,DICOM_T_UNK, _T("Bulk Motion Signal Source") }, -{ 0x0018,0x9174,DICOM_T_UNK, _T("Applicable Safety Standard Agency") }, -{ 0x0018,0x9175,DICOM_T_UNK, _T("Applicable Safety Standard Description") }, -{ 0x0018,0x9176,DICOM_T_UNK, _T("Operating Mode Sequence") }, -{ 0x0018,0x9177,DICOM_T_UNK, _T("Operating Mode Type") }, -{ 0x0018,0x9178,DICOM_T_UNK, _T("Operating Mode") }, -{ 0x0018,0x9179,DICOM_T_UNK, _T("Specific Absorption Rate Definition") }, -{ 0x0018,0x9180,DICOM_T_UNK, _T("Gradient Output Type") }, -{ 0x0018,0x9181,DICOM_T_UNK, _T("Specific Absorption Rate Value") }, -{ 0x0018,0x9182,DICOM_T_UNK, _T("Gradient Output") }, -{ 0x0018,0x9183,DICOM_T_UNK, _T("Flow Compensation Direction") }, -{ 0x0018,0x9184,DICOM_T_UNK, _T("Tagging Delay") }, -{ 0x0018,0x9185,DICOM_T_UNK, _T("Respiratory Motion Compensation Technique Description") }, -{ 0x0018,0x9186,DICOM_T_UNK, _T("Respiratory Signal Source ID") }, -{ 0x0018,0x9195,DICOM_T_UNK, _T("Chemical Shift Minimum Integration Limit in Hz") }, -{ 0x0018,0x9196,DICOM_T_UNK, _T("Chemical Shift Maximum Integration Limit in Hz") }, -{ 0x0018,0x9197,DICOM_T_UNK, _T("MR Velocity Encoding Sequence") }, -{ 0x0018,0x9198,DICOM_T_UNK, _T("First Order Phase Correction") }, -{ 0x0018,0x9199,DICOM_T_UNK, _T("Water Referenced Phase Correction") }, -{ 0x0018,0x9200,DICOM_T_UNK, _T("MR Spectroscopy Acquisition Type") }, -{ 0x0018,0x9214,DICOM_T_UNK, _T("Respiratory Cycle Position") }, -{ 0x0018,0x9217,DICOM_T_UNK, _T("Velocity Encoding Maximum Value") }, -{ 0x0018,0x9218,DICOM_T_UNK, _T("Tag Spacing Second Dimension") }, -{ 0x0018,0x9219,DICOM_T_UNK, _T("Tag Angle Second Axis") }, -{ 0x0018,0x9220,DICOM_T_UNK, _T("Frame Acquisition Duration") }, -{ 0x0018,0x9226,DICOM_T_UNK, _T("MR Image Frame Type Sequence") }, -{ 0x0018,0x9227,DICOM_T_UNK, _T("MR Spectroscopy Frame Type Sequence") }, -{ 0x0018,0x9231,DICOM_T_UNK, _T("MR Acquisition Phase Encoding Steps in-plane") }, -{ 0x0018,0x9232,DICOM_T_UNK, _T("MR Acquisition Phase Encoding Steps out-of-plane") }, -{ 0x0018,0x9234,DICOM_T_UNK, _T("Spectroscopy Acquisition Phase Columns") }, -{ 0x0018,0x9236,DICOM_T_UNK, _T("Cardiac Cycle Position") }, -{ 0x0018,0x9239,DICOM_T_UNK, _T("Specific Absorption Rate Sequence") }, -{ 0x0018,0x9240,DICOM_T_UNK, _T("RF Echo Train Length") }, -{ 0x0018,0x9241,DICOM_T_UNK, _T("Gradient Echo Train Length") }, -{ 0x0018,0x9250,DICOM_T_UNK, _T("Arterial Spin Labeling Contrast") }, -{ 0x0018,0x9251,DICOM_T_UNK, _T("MR Arterial Spin Labeling Sequence") }, -{ 0x0018,0x9252,DICOM_T_UNK, _T("ASL Technique Description") }, -{ 0x0018,0x9253,DICOM_T_UNK, _T("ASL Slab Number") }, -{ 0x0018,0x9254,DICOM_T_UNK, _T("ASL Slab Thickness") }, -{ 0x0018,0x9255,DICOM_T_UNK, _T("ASL Slab Orientation") }, -{ 0x0018,0x9256,DICOM_T_UNK, _T("ASL Mid Slab Position") }, -{ 0x0018,0x9257,DICOM_T_UNK, _T("ASL Context") }, -{ 0x0018,0x9258,DICOM_T_UNK, _T("ASL Pulse Train Duration") }, -{ 0x0018,0x9259,DICOM_T_UNK, _T("ASL Crusher Flag") }, -{ 0x0018,0x925A,DICOM_T_UNK, _T("ASL Crusher Flow Limit") }, -{ 0x0018,0x925B,DICOM_T_UNK, _T("ASL Crusher Description") }, -{ 0x0018,0x925C,DICOM_T_UNK, _T("ASL Bolus Cut-off Flag") }, -{ 0x0018,0x925D,DICOM_T_UNK, _T("ASL Bolus Cut-off Timing Sequence") }, -{ 0x0018,0x925E,DICOM_T_UNK, _T("ASL Bolus Cut-off Technique") }, -{ 0x0018,0x925F,DICOM_T_UNK, _T("ASL Bolus Cut-off Delay Time") }, -{ 0x0018,0x9260,DICOM_T_UNK, _T("ASL Slab Sequence") }, -{ 0x0018,0x9295,DICOM_T_UNK, _T("Chemical Shift Minimum Integration Limit in ppm") }, -{ 0x0018,0x9296,DICOM_T_UNK, _T("Chemical Shift Maximum Integration Limit in ppm") }, -{ 0x0018,0x9297,DICOM_T_UNK, _T("Water Reference Acquisition") }, -{ 0x0018,0x9298,DICOM_T_UNK, _T("Echo Peak Position") }, -{ 0x0018,0x9301,DICOM_T_UNK, _T("CT Acquisition Type Sequence") }, -{ 0x0018,0x9302,DICOM_T_UNK, _T("Acquisition Type") }, -{ 0x0018,0x9303,DICOM_T_UNK, _T("Tube Angle") }, -{ 0x0018,0x9304,DICOM_T_UNK, _T("CT Acquisition Details Sequence") }, -{ 0x0018,0x9305,DICOM_T_UNK, _T("Revolution Time") }, -{ 0x0018,0x9306,DICOM_T_UNK, _T("Single Collimation Width") }, -{ 0x0018,0x9307,DICOM_T_UNK, _T("Total Collimation Width") }, -{ 0x0018,0x9308,DICOM_T_UNK, _T("CT Table Dynamics Sequence") }, -{ 0x0018,0x9309,DICOM_T_UNK, _T("Table Speed") }, -{ 0x0018,0x9310,DICOM_T_UNK, _T("Table Feed per Rotation") }, -{ 0x0018,0x9311,DICOM_T_UNK, _T("Spiral Pitch Factor") }, -{ 0x0018,0x9312,DICOM_T_UNK, _T("CT Geometry Sequence") }, -{ 0x0018,0x9313,DICOM_T_UNK, _T("Data Collection Center (Patient)") }, -{ 0x0018,0x9314,DICOM_T_UNK, _T("CT Reconstruction Sequence") }, -{ 0x0018,0x9315,DICOM_T_UNK, _T("Reconstruction Algorithm") }, -{ 0x0018,0x9316,DICOM_T_UNK, _T("Convolution Kernel Group") }, -{ 0x0018,0x9317,DICOM_T_UNK, _T("Reconstruction Field of View") }, -{ 0x0018,0x9318,DICOM_T_UNK, _T("Reconstruction Target Center (Patient)") }, -{ 0x0018,0x9319,DICOM_T_UNK, _T("Reconstruction Angle") }, -{ 0x0018,0x9320,DICOM_T_UNK, _T("Image Filter") }, -{ 0x0018,0x9321,DICOM_T_UNK, _T("CT Exposure Sequence") }, -{ 0x0018,0x9322,DICOM_T_UNK, _T("Reconstruction Pixel Spacing") }, -{ 0x0018,0x9323,DICOM_T_UNK, _T("Exposure Modulation Type") }, -{ 0x0018,0x9324,DICOM_T_UNK, _T("Estimated Dose Saving") }, -{ 0x0018,0x9325,DICOM_T_UNK, _T("CT X-Ray Details Sequence") }, -{ 0x0018,0x9326,DICOM_T_UNK, _T("CT Position Sequence") }, -{ 0x0018,0x9327,DICOM_T_UNK, _T("Table Position") }, -{ 0x0018,0x9328,DICOM_T_UNK, _T("Exposure Time in ms") }, -{ 0x0018,0x9329,DICOM_T_UNK, _T("CT Image Frame Type Sequence") }, -{ 0x0018,0x9330,DICOM_T_UNK, _T("X-Ray Tube Current in mA") }, -{ 0x0018,0x9332,DICOM_T_UNK, _T("Exposure in mAs") }, -{ 0x0018,0x9333,DICOM_T_UNK, _T("Constant Volume Flag") }, -{ 0x0018,0x9334,DICOM_T_UNK, _T("Fluoroscopy Flag") }, -{ 0x0018,0x9335,DICOM_T_UNK, _T("Distance Source to Data Collection Center") }, -{ 0x0018,0x9337,DICOM_T_UNK, _T("Contrast/Bolus Agent Number") }, -{ 0x0018,0x9338,DICOM_T_UNK, _T("Contrast/Bolus Ingredient Code Sequence") }, -{ 0x0018,0x9340,DICOM_T_UNK, _T("Contrast Administration Profile Sequence") }, -{ 0x0018,0x9341,DICOM_T_UNK, _T("Contrast/Bolus Usage Sequence") }, -{ 0x0018,0x9342,DICOM_T_UNK, _T("Contrast/Bolus Agent Administered") }, -{ 0x0018,0x9343,DICOM_T_UNK, _T("Contrast/Bolus Agent Detected") }, -{ 0x0018,0x9344,DICOM_T_UNK, _T("Contrast/Bolus Agent Phase") }, -{ 0x0018,0x9345,DICOM_T_UNK, _T("CTDIvol") }, -{ 0x0018,0x9346,DICOM_T_UNK, _T("CTDI Phantom Type Code Sequence") }, -{ 0x0018,0x9351,DICOM_T_UNK, _T("Calcium Scoring Mass Factor Patient") }, -{ 0x0018,0x9352,DICOM_T_UNK, _T("Calcium Scoring Mass Factor Device") }, -{ 0x0018,0x9353,DICOM_T_UNK, _T("Energy Weighting Factor") }, -{ 0x0018,0x9360,DICOM_T_UNK, _T("CT Additional X-Ray Source Sequence") }, -{ 0x0018,0x9401,DICOM_T_UNK, _T("Projection Pixel Calibration Sequence") }, -{ 0x0018,0x9402,DICOM_T_UNK, _T("Distance Source to Isocenter") }, -{ 0x0018,0x9403,DICOM_T_UNK, _T("Distance Object to Table Top") }, -{ 0x0018,0x9404,DICOM_T_UNK, _T("Object Pixel Spacing in Center of Beam") }, -{ 0x0018,0x9405,DICOM_T_UNK, _T("Positioner Position Sequence") }, -{ 0x0018,0x9406,DICOM_T_UNK, _T("Table Position Sequence") }, -{ 0x0018,0x9407,DICOM_T_UNK, _T("Collimator Shape Sequence") }, -{ 0x0018,0x9410,DICOM_T_UNK, _T("Planes in Acquisition") }, -{ 0x0018,0x9412,DICOM_T_UNK, _T("XA/XRF Frame Characteristics Sequence") }, -{ 0x0018,0x9417,DICOM_T_UNK, _T("Frame Acquisition Sequence") }, -{ 0x0018,0x9420,DICOM_T_UNK, _T("X-Ray Receptor Type") }, -{ 0x0018,0x9423,DICOM_T_UNK, _T("Acquisition Protocol Name") }, -{ 0x0018,0x9424,DICOM_T_UNK, _T("Acquisition Protocol Description") }, -{ 0x0018,0x9425,DICOM_T_UNK, _T("Contrast/Bolus Ingredient Opaque") }, -{ 0x0018,0x9426,DICOM_T_UNK, _T("Distance Receptor Plane to Detector Housing") }, -{ 0x0018,0x9427,DICOM_T_UNK, _T("Intensifier Active Shape") }, -{ 0x0018,0x9428,DICOM_T_UNK, _T("Intensifier Active Dimension(s)") }, -{ 0x0018,0x9429,DICOM_T_UNK, _T("Physical Detector Size") }, -{ 0x0018,0x9430,DICOM_T_UNK, _T("Position of Isocenter Projection") }, -{ 0x0018,0x9432,DICOM_T_UNK, _T("Field of View Sequence") }, -{ 0x0018,0x9433,DICOM_T_UNK, _T("Field of View Description") }, -{ 0x0018,0x9434,DICOM_T_UNK, _T("Exposure Control Sensing Regions Sequence") }, -{ 0x0018,0x9435,DICOM_T_UNK, _T("Exposure Control Sensing Region Shape") }, -{ 0x0018,0x9436,DICOM_T_UNK, _T("Exposure Control Sensing Region Left Vertical Edge") }, -{ 0x0018,0x9437,DICOM_T_UNK, _T("Exposure Control Sensing Region Right Vertical Edge") }, -{ 0x0018,0x9438,DICOM_T_UNK, _T("Exposure Control Sensing Region Upper Horizontal Edge") }, -{ 0x0018,0x9439,DICOM_T_UNK, _T("Exposure Control Sensing Region Lower Horizontal Edge") }, -{ 0x0018,0x9440,DICOM_T_UNK, _T("Center of Circular Exposure Control Sensing Region") }, -{ 0x0018,0x9441,DICOM_T_UNK, _T("Radius of Circular Exposure Control Sensing Region") }, -{ 0x0018,0x9442,DICOM_T_UNK, _T("Vertices of the Polygonal Exposure Control Sensing Region") }, -{ 0x0018,0x9445,DICOM_T_UNK, _T("") }, -{ 0x0018,0x9447,DICOM_T_UNK, _T("Column Angulation (Patient)") }, -{ 0x0018,0x9449,DICOM_T_UNK, _T("Beam Angle") }, -{ 0x0018,0x9451,DICOM_T_UNK, _T("Frame Detector Parameters Sequence") }, -{ 0x0018,0x9452,DICOM_T_UNK, _T("Calculated Anatomy Thickness") }, -{ 0x0018,0x9455,DICOM_T_UNK, _T("Calibration Sequence") }, -{ 0x0018,0x9456,DICOM_T_UNK, _T("Object Thickness Sequence") }, -{ 0x0018,0x9457,DICOM_T_UNK, _T("Plane Identification") }, -{ 0x0018,0x9461,DICOM_T_UNK, _T("Field of View Dimension(s) in Float") }, -{ 0x0018,0x9462,DICOM_T_UNK, _T("Isocenter Reference System Sequence") }, -{ 0x0018,0x9463,DICOM_T_UNK, _T("Positioner Isocenter Primary Angle") }, -{ 0x0018,0x9464,DICOM_T_UNK, _T("Positioner Isocenter Secondary Angle") }, -{ 0x0018,0x9465,DICOM_T_UNK, _T("Positioner Isocenter Detector Rotation Angle") }, -{ 0x0018,0x9466,DICOM_T_UNK, _T("Table X Position to Isocenter") }, -{ 0x0018,0x9467,DICOM_T_UNK, _T("Table Y Position to Isocenter") }, -{ 0x0018,0x9468,DICOM_T_UNK, _T("Table Z Position to Isocenter") }, -{ 0x0018,0x9469,DICOM_T_UNK, _T("Table Horizontal Rotation Angle") }, -{ 0x0018,0x9470,DICOM_T_UNK, _T("Table Head Tilt Angle") }, -{ 0x0018,0x9471,DICOM_T_UNK, _T("Table Cradle Tilt Angle") }, -{ 0x0018,0x9472,DICOM_T_UNK, _T("Frame Display Shutter Sequence") }, -{ 0x0018,0x9473,DICOM_T_UNK, _T("Acquired Image Area Dose Product") }, -{ 0x0018,0x9474,DICOM_T_UNK, _T("C-arm Positioner Tabletop Relationship") }, -{ 0x0018,0x9476,DICOM_T_UNK, _T("X-Ray Geometry Sequence") }, -{ 0x0018,0x9477,DICOM_T_UNK, _T("Irradiation Event Identification Sequence") }, -{ 0x0018,0x9504,DICOM_T_UNK, _T("X-Ray 3D Frame Type Sequence") }, -{ 0x0018,0x9506,DICOM_T_UNK, _T("Contributing Sources Sequence") }, -{ 0x0018,0x9507,DICOM_T_UNK, _T("X-Ray 3D Acquisition Sequence") }, -{ 0x0018,0x9508,DICOM_T_UNK, _T("Primary Positioner Scan Arc") }, -{ 0x0018,0x9509,DICOM_T_UNK, _T("Secondary Positioner Scan Arc") }, -{ 0x0018,0x9510,DICOM_T_UNK, _T("Primary Positioner Scan Start Angle") }, -{ 0x0018,0x9511,DICOM_T_UNK, _T("Secondary Positioner Scan Start Angle") }, -{ 0x0018,0x9514,DICOM_T_UNK, _T("Primary Positioner Increment") }, -{ 0x0018,0x9515,DICOM_T_UNK, _T("Secondary Positioner Increment") }, -{ 0x0018,0x9516,DICOM_T_UNK, _T("Start Acquisition DateTime") }, -{ 0x0018,0x9517,DICOM_T_UNK, _T("End Acquisition DateTime") }, -{ 0x0018,0x9518,DICOM_T_UNK, _T("Primary Positioner Increment Sign") }, -{ 0x0018,0x9519,DICOM_T_UNK, _T("Secondary Positioner Increment Sign") }, -{ 0x0018,0x9524,DICOM_T_UNK, _T("Application Name") }, -{ 0x0018,0x9525,DICOM_T_UNK, _T("Application Version") }, -{ 0x0018,0x9526,DICOM_T_UNK, _T("Application Manufacturer") }, -{ 0x0018,0x9527,DICOM_T_UNK, _T("Algorithm Type") }, -{ 0x0018,0x9528,DICOM_T_UNK, _T("Algorithm Description") }, -{ 0x0018,0x9530,DICOM_T_UNK, _T("X-Ray 3D Reconstruction Sequence") }, -{ 0x0018,0x9531,DICOM_T_UNK, _T("Reconstruction Description") }, -{ 0x0018,0x9538,DICOM_T_UNK, _T("Per Projection Acquisition Sequence") }, -{ 0x0018,0x9541,DICOM_T_UNK, _T("Detector Position Sequence") }, -{ 0x0018,0x9542,DICOM_T_UNK, _T("X-Ray Acquisition Dose Sequence") }, -{ 0x0018,0x9543,DICOM_T_UNK, _T("X-Ray Source Isocenter Primary Angle") }, -{ 0x0018,0x9544,DICOM_T_UNK, _T("X-Ray Source Isocenter Secondary Angle") }, -{ 0x0018,0x9545,DICOM_T_UNK, _T("Breast Support Isocenter Primary Angle") }, -{ 0x0018,0x9546,DICOM_T_UNK, _T("Breast Support Isocenter Secondary Angle") }, -{ 0x0018,0x9547,DICOM_T_UNK, _T("Breast Support X Position to Isocenter") }, -{ 0x0018,0x9548,DICOM_T_UNK, _T("Breast Support Y Position to Isocenter") }, -{ 0x0018,0x9549,DICOM_T_UNK, _T("Breast Support Z Position to Isocenter") }, -{ 0x0018,0x9550,DICOM_T_UNK, _T("Detector Isocenter Primary Angle") }, -{ 0x0018,0x9551,DICOM_T_UNK, _T("Detector Isocenter Secondary Angle") }, -{ 0x0018,0x9552,DICOM_T_UNK, _T("Detector X Position to Isocenter") }, -{ 0x0018,0x9553,DICOM_T_UNK, _T("Detector Y Position to Isocenter") }, -{ 0x0018,0x9554,DICOM_T_UNK, _T("Detector Z Position to Isocenter") }, -{ 0x0018,0x9555,DICOM_T_UNK, _T("X-Ray Grid Sequence") }, -{ 0x0018,0x9556,DICOM_T_UNK, _T("X-Ray Filter Sequence") }, -{ 0x0018,0x9557,DICOM_T_UNK, _T("Detector Active Area TLHC Position") }, -{ 0x0018,0x9558,DICOM_T_UNK, _T("Detector Active Area Orientation") }, -{ 0x0018,0x9559,DICOM_T_UNK, _T("Positioner Primary Angle Direction") }, -{ 0x0018,0x9601,DICOM_T_UNK, _T("Diffusion b-matrix Sequence") }, -{ 0x0018,0x9602,DICOM_T_UNK, _T("Diffusion b-value XX") }, -{ 0x0018,0x9603,DICOM_T_UNK, _T("Diffusion b-value XY") }, -{ 0x0018,0x9604,DICOM_T_UNK, _T("Diffusion b-value XZ") }, -{ 0x0018,0x9605,DICOM_T_UNK, _T("Diffusion b-value YY") }, -{ 0x0018,0x9606,DICOM_T_UNK, _T("Diffusion b-value YZ") }, -{ 0x0018,0x9607,DICOM_T_UNK, _T("Diffusion b-value ZZ") }, -{ 0x0018,0x9701,DICOM_T_UNK, _T("Decay Correction DateTime") }, -{ 0x0018,0x9715,DICOM_T_UNK, _T("Start Density Threshold") }, -{ 0x0018,0x9716,DICOM_T_UNK, _T("Start Relative Density Difference Threshold") }, -{ 0x0018,0x9717,DICOM_T_UNK, _T("Start Cardiac Trigger Count Threshold") }, -{ 0x0018,0x9718,DICOM_T_UNK, _T("Start Respiratory Trigger Count Threshold") }, -{ 0x0018,0x9719,DICOM_T_UNK, _T("Termination Counts Threshold") }, -{ 0x0018,0x9720,DICOM_T_UNK, _T("Termination Density Threshold") }, -{ 0x0018,0x9721,DICOM_T_UNK, _T("Termination Relative Density Threshold") }, -{ 0x0018,0x9722,DICOM_T_UNK, _T("Termination Time Threshold") }, -{ 0x0018,0x9723,DICOM_T_UNK, _T("Termination Cardiac Trigger Count Threshold") }, -{ 0x0018,0x9724,DICOM_T_UNK, _T("Termination Respiratory Trigger Count Threshold") }, -{ 0x0018,0x9725,DICOM_T_UNK, _T("Detector Geometry") }, -{ 0x0018,0x9726,DICOM_T_UNK, _T("Transverse Detector Separation") }, -{ 0x0018,0x9727,DICOM_T_UNK, _T("Axial Detector Dimension") }, -{ 0x0018,0x9729,DICOM_T_UNK, _T("Radiopharmaceutical Agent Number") }, -{ 0x0018,0x9732,DICOM_T_UNK, _T("PET Frame Acquisition Sequence") }, -{ 0x0018,0x9733,DICOM_T_UNK, _T("PET Detector Motion Details Sequence") }, -{ 0x0018,0x9734,DICOM_T_UNK, _T("PET Table Dynamics Sequence") }, -{ 0x0018,0x9735,DICOM_T_UNK, _T("PET Position Sequence") }, -{ 0x0018,0x9736,DICOM_T_UNK, _T("PET Frame Correction Factors Sequence") }, -{ 0x0018,0x9737,DICOM_T_UNK, _T("Radiopharmaceutical Usage Sequence") }, -{ 0x0018,0x9738,DICOM_T_UNK, _T("Attenuation Correction Source") }, -{ 0x0018,0x9739,DICOM_T_UNK, _T("Number of Iterations") }, -{ 0x0018,0x9740,DICOM_T_UNK, _T("Number of Subsets") }, -{ 0x0018,0x9749,DICOM_T_UNK, _T("PET Reconstruction Sequence") }, -{ 0x0018,0x9751,DICOM_T_UNK, _T("PET Frame Type Sequence") }, -{ 0x0018,0x9755,DICOM_T_UNK, _T("Time of Flight Information Used") }, -{ 0x0018,0x9756,DICOM_T_UNK, _T("Reconstruction Type") }, -{ 0x0018,0x9758,DICOM_T_UNK, _T("Decay Corrected") }, -{ 0x0018,0x9759,DICOM_T_UNK, _T("Attenuation Corrected") }, -{ 0x0018,0x9760,DICOM_T_UNK, _T("Scatter Corrected") }, -{ 0x0018,0x9761,DICOM_T_UNK, _T("Dead Time Corrected") }, -{ 0x0018,0x9762,DICOM_T_UNK, _T("Gantry Motion Corrected") }, -{ 0x0018,0x9763,DICOM_T_UNK, _T("Patient Motion Corrected") }, -{ 0x0018,0x9764,DICOM_T_UNK, _T("Count Loss Normalization Corrected") }, -{ 0x0018,0x9765,DICOM_T_UNK, _T("Randoms Corrected") }, -{ 0x0018,0x9766,DICOM_T_UNK, _T("Non-uniform Radial Sampling Corrected") }, -{ 0x0018,0x9767,DICOM_T_UNK, _T("Sensitivity Calibrated") }, -{ 0x0018,0x9768,DICOM_T_UNK, _T("Detector Normalization Correction") }, -{ 0x0018,0x9769,DICOM_T_UNK, _T("Iterative Reconstruction Method") }, -{ 0x0018,0x9770,DICOM_T_UNK, _T("Attenuation Correction Temporal Relationship") }, -{ 0x0018,0x9771,DICOM_T_UNK, _T("Patient Physiological State Sequence") }, -{ 0x0018,0x9772,DICOM_T_UNK, _T("Patient Physiological State Code Sequence") }, -{ 0x0018,0x9801,DICOM_T_UNK, _T("Depth(s) of Focus") }, -{ 0x0018,0x9803,DICOM_T_UNK, _T("Excluded Intervals Sequence") }, -{ 0x0018,0x9804,DICOM_T_UNK, _T("Exclusion Start DateTime") }, -{ 0x0018,0x9805,DICOM_T_UNK, _T("Exclusion Duration") }, -{ 0x0018,0x9806,DICOM_T_UNK, _T("US Image Description Sequence") }, -{ 0x0018,0x9807,DICOM_T_UNK, _T("Image Data Type Sequence") }, -{ 0x0018,0x9808,DICOM_T_UNK, _T("Data Type") }, -{ 0x0018,0x9809,DICOM_T_UNK, _T("Transducer Scan Pattern Code Sequence") }, -{ 0x0018,0x980B,DICOM_T_UNK, _T("Aliased Data Type") }, -{ 0x0018,0x980C,DICOM_T_UNK, _T("Position Measuring Device Used") }, -{ 0x0018,0x980D,DICOM_T_UNK, _T("Transducer Geometry Code Sequence") }, -{ 0x0018,0x980E,DICOM_T_UNK, _T("Transducer Beam Steering Code Sequence") }, -{ 0x0018,0x980F,DICOM_T_UNK, _T("Transducer Application Code Sequence") }, -{ 0x0018,0x9810,DICOM_T_UNK, _T("Zero Velocity Pixel Value") }, -{ 0x0018,0xA001,DICOM_T_UNK, _T("Contributing Equipment Sequence") }, -{ 0x0018,0xA002,DICOM_T_UNK, _T("Contribution DateTime") }, -{ 0x0018,0xA003,DICOM_T_UNK, _T("Contribution Description") }, -{ 0x0020,0x000D,DICOM_T_UNK, _T("Study Instance UID") }, -{ 0x0020,0x000E,DICOM_T_UNK, _T("Series Instance UID") }, -{ 0x0020,0x0010,DICOM_T_UNK, _T("Study ID") }, -{ 0x0020,0x0011,DICOM_T_UNK, _T("Series Number") }, -{ 0x0020,0x0012,DICOM_T_UNK, _T("Acquisition Number") }, -{ 0x0020,0x0013,DICOM_T_UNK, _T("Instance Number") }, -{ 0x0020,0x0014,DICOM_T_UNK, _T("Isotope Number") }, -{ 0x0020,0x0015,DICOM_T_UNK, _T("Phase Number") }, -{ 0x0020,0x0016,DICOM_T_UNK, _T("Interval Number") }, -{ 0x0020,0x0017,DICOM_T_UNK, _T("Time Slot Number") }, -{ 0x0020,0x0018,DICOM_T_UNK, _T("Angle Number") }, -{ 0x0020,0x0019,DICOM_T_UNK, _T("Item Number") }, -{ 0x0020,0x0020,DICOM_T_UNK, _T("Patient Orientation") }, -{ 0x0020,0x0022,DICOM_T_UNK, _T("Overlay Number") }, -{ 0x0020,0x0024,DICOM_T_UNK, _T("Curve Number") }, -{ 0x0020,0x0026,DICOM_T_UNK, _T("LUT Number") }, -{ 0x0020,0x0030,DICOM_T_UNK, _T("Image Position") }, -{ 0x0020,0x0032,DICOM_T_UNK, _T("Image Position (Patient)") }, -{ 0x0020,0x0035,DICOM_T_UNK, _T("Image Orientation") }, -{ 0x0020,0x0037,DICOM_T_UNK, _T("Image Orientation (Patient)") }, -{ 0x0020,0x0050,DICOM_T_UNK, _T("Location") }, -{ 0x0020,0x0052,DICOM_T_UNK, _T("Frame of Reference UID") }, -{ 0x0020,0x0060,DICOM_T_UNK, _T("Laterality") }, -{ 0x0020,0x0062,DICOM_T_UNK, _T("Image Laterality") }, -{ 0x0020,0x0070,DICOM_T_UNK, _T("Image Geometry Type") }, -{ 0x0020,0x0080,DICOM_T_UNK, _T("Masking Image") }, -{ 0x0020,0x00AA,DICOM_T_UNK, _T("Report Number") }, -{ 0x0020,0x0100,DICOM_T_UNK, _T("Temporal Position Identifier") }, -{ 0x0020,0x0105,DICOM_T_UNK, _T("Number of Temporal Positions") }, -{ 0x0020,0x0110,DICOM_T_UNK, _T("Temporal Resolution") }, -{ 0x0020,0x0200,DICOM_T_UNK, _T("Synchronization Frame of Reference UID") }, -{ 0x0020,0x0242,DICOM_T_UNK, _T("SOP Instance UID of Concatenation Source") }, -{ 0x0020,0x1000,DICOM_T_UNK, _T("Series in Study") }, -{ 0x0020,0x1001,DICOM_T_UNK, _T("Acquisitions in Series") }, -{ 0x0020,0x1002,DICOM_T_UNK, _T("Images in Acquisition") }, -{ 0x0020,0x1003,DICOM_T_UNK, _T("Images in Series") }, -{ 0x0020,0x1004,DICOM_T_UNK, _T("Acquisitions in Study") }, -{ 0x0020,0x1005,DICOM_T_UNK, _T("Images in Study") }, -{ 0x0020,0x1020,DICOM_T_UNK, _T("Reference") }, -{ 0x0020,0x1040,DICOM_T_UNK, _T("Position Reference Indicator") }, -{ 0x0020,0x1041,DICOM_T_UNK, _T("Slice Location") }, -{ 0x0020,0x1070,DICOM_T_UNK, _T("Other Study Numbers") }, -{ 0x0020,0x1200,DICOM_T_UNK, _T("Number of Patient Related Studies") }, -{ 0x0020,0x1202,DICOM_T_UNK, _T("Number of Patient Related Series") }, -{ 0x0020,0x1204,DICOM_T_UNK, _T("Number of Patient Related Instances") }, -{ 0x0020,0x1206,DICOM_T_UNK, _T("Number of Study Related Series") }, -{ 0x0020,0x1208,DICOM_T_UNK, _T("Number of Study Related Instances") }, -{ 0x0020,0x1209,DICOM_T_UNK, _T("Number of Series Related Instances") }, -/* -{ 0x0020,0x31xx,DICOM_T_UNK, _T("Source Image IDs") }, -*/ -{ 0x0020,0x3401,DICOM_T_UNK, _T("Modifying Device ID") }, -{ 0x0020,0x3402,DICOM_T_UNK, _T("Modified Image ID") }, -{ 0x0020,0x3403,DICOM_T_UNK, _T("Modified Image Date") }, -{ 0x0020,0x3404,DICOM_T_UNK, _T("Modifying Device Manufacturer") }, -{ 0x0020,0x3405,DICOM_T_UNK, _T("Modified Image Time") }, -{ 0x0020,0x3406,DICOM_T_UNK, _T("Modified Image Description") }, -{ 0x0020,0x4000,DICOM_T_UNK, _T("Image Comments") }, -{ 0x0020,0x5000,DICOM_T_UNK, _T("Original Image Identification") }, -{ 0x0020,0x5002,DICOM_T_UNK, _T("Original Image Identification Nomenclature") }, -{ 0x0020,0x9056,DICOM_T_UNK, _T("Stack ID") }, -{ 0x0020,0x9057,DICOM_T_UNK, _T("In-Stack Position Number") }, -{ 0x0020,0x9071,DICOM_T_UNK, _T("Frame Anatomy Sequence") }, -{ 0x0020,0x9072,DICOM_T_UNK, _T("Frame Laterality") }, -{ 0x0020,0x9111,DICOM_T_UNK, _T("Frame Content Sequence") }, -{ 0x0020,0x9113,DICOM_T_UNK, _T("Plane Position Sequence") }, -{ 0x0020,0x9116,DICOM_T_UNK, _T("Plane Orientation Sequence") }, -{ 0x0020,0x9128,DICOM_T_UNK, _T("Temporal Position Index") }, -{ 0x0020,0x9153,DICOM_T_UNK, _T("Nominal Cardiac Trigger Delay Time") }, -{ 0x0020,0x9154,DICOM_T_UNK, _T("Nominal Cardiac Trigger Time Prior To R-Peak") }, -{ 0x0020,0x9155,DICOM_T_UNK, _T("Actual Cardiac Trigger Time Prior To R-Peak") }, -{ 0x0020,0x9156,DICOM_T_UNK, _T("Frame Acquisition Number") }, -{ 0x0020,0x9157,DICOM_T_UNK, _T("Dimension Index Values") }, -{ 0x0020,0x9158,DICOM_T_UNK, _T("Frame Comments") }, -{ 0x0020,0x9161,DICOM_T_UNK, _T("Concatenation UID") }, -{ 0x0020,0x9162,DICOM_T_UNK, _T("In-concatenation Number") }, -{ 0x0020,0x9163,DICOM_T_UNK, _T("In-concatenation Total Number") }, -{ 0x0020,0x9164,DICOM_T_UNK, _T("Dimension Organization UID") }, -{ 0x0020,0x9165,DICOM_T_UNK, _T("Dimension Index Pointer") }, -{ 0x0020,0x9167,DICOM_T_UNK, _T("Functional Group Pointer") }, -{ 0x0020,0x9170,DICOM_T_UNK, _T("Unassigned Shared Converted Attributes Sequence") }, -{ 0x0020,0x9171,DICOM_T_UNK, _T("Unassigned Per-Frame Converted Attributes Sequence") }, -{ 0x0020,0x9172,DICOM_T_UNK, _T("Conversion Source Attributes Sequence") }, -{ 0x0020,0x9213,DICOM_T_UNK, _T("Dimension Index Private Creator") }, -{ 0x0020,0x9221,DICOM_T_UNK, _T("Dimension Organization Sequence") }, -{ 0x0020,0x9222,DICOM_T_UNK, _T("Dimension Index Sequence") }, -{ 0x0020,0x9228,DICOM_T_UNK, _T("Concatenation Frame Offset Number") }, -{ 0x0020,0x9238,DICOM_T_UNK, _T("Functional Group Private Creator") }, -{ 0x0020,0x9241,DICOM_T_UNK, _T("Nominal Percentage of Cardiac Phase") }, -{ 0x0020,0x9245,DICOM_T_UNK, _T("Nominal Percentage of Respiratory Phase") }, -{ 0x0020,0x9246,DICOM_T_UNK, _T("Starting Respiratory Amplitude") }, -{ 0x0020,0x9247,DICOM_T_UNK, _T("Starting Respiratory Phase") }, -{ 0x0020,0x9248,DICOM_T_UNK, _T("Ending Respiratory Amplitude") }, -{ 0x0020,0x9249,DICOM_T_UNK, _T("Ending Respiratory Phase") }, -{ 0x0020,0x9250,DICOM_T_UNK, _T("Respiratory Trigger Type") }, -{ 0x0020,0x9251,DICOM_T_UNK, _T("R-R Interval Time Nominal") }, -{ 0x0020,0x9252,DICOM_T_UNK, _T("Actual Cardiac Trigger Delay Time") }, -{ 0x0020,0x9253,DICOM_T_UNK, _T("Respiratory Synchronization Sequence") }, -{ 0x0020,0x9254,DICOM_T_UNK, _T("Respiratory Interval Time") }, -{ 0x0020,0x9255,DICOM_T_UNK, _T("Nominal Respiratory Trigger Delay Time") }, -{ 0x0020,0x9256,DICOM_T_UNK, _T("Respiratory Trigger Delay Threshold") }, -{ 0x0020,0x9257,DICOM_T_UNK, _T("Actual Respiratory Trigger Delay Time") }, -{ 0x0020,0x9301,DICOM_T_UNK, _T("Image Position (Volume)") }, -{ 0x0020,0x9302,DICOM_T_UNK, _T("Image Orientation (Volume)") }, -{ 0x0020,0x9307,DICOM_T_UNK, _T("Ultrasound Acquisition Geometry") }, -{ 0x0020,0x9308,DICOM_T_UNK, _T("Apex Position") }, -{ 0x0020,0x9309,DICOM_T_UNK, _T("Volume to Transducer Mapping Matrix") }, -{ 0x0020,0x930A,DICOM_T_UNK, _T("Volume to Table Mapping Matrix") }, -{ 0x0020,0x930B,DICOM_T_UNK, _T("Volume to Transducer Relationship") }, -{ 0x0020,0x930C,DICOM_T_UNK, _T("Patient Frame of Reference Source") }, -{ 0x0020,0x930D,DICOM_T_UNK, _T("Temporal Position Time Offset") }, -{ 0x0020,0x930E,DICOM_T_UNK, _T("Plane Position (Volume) Sequence") }, -{ 0x0020,0x930F,DICOM_T_UNK, _T("Plane Orientation (Volume) Sequence") }, -{ 0x0020,0x9310,DICOM_T_UNK, _T("Temporal Position Sequence") }, -{ 0x0020,0x9311,DICOM_T_UNK, _T("Dimension Organization Type") }, -{ 0x0020,0x9312,DICOM_T_UNK, _T("Volume Frame of Reference UID") }, -{ 0x0020,0x9313,DICOM_T_UNK, _T("Table Frame of Reference UID") }, -{ 0x0020,0x9421,DICOM_T_UNK, _T("Dimension Description Label") }, -{ 0x0020,0x9450,DICOM_T_UNK, _T("Patient Orientation in Frame Sequence") }, -{ 0x0020,0x9453,DICOM_T_UNK, _T("Frame Label") }, -{ 0x0020,0x9518,DICOM_T_UNK, _T("Acquisition Index") }, -{ 0x0020,0x9529,DICOM_T_UNK, _T("Contributing SOP Instances Reference Sequence") }, -{ 0x0020,0x9536,DICOM_T_UNK, _T("Reconstruction Index") }, -{ 0x0022,0x0001,DICOM_T_UNK, _T("Light Path Filter Pass-Through Wavelength") }, -{ 0x0022,0x0002,DICOM_T_UNK, _T("Light Path Filter Pass Band") }, -{ 0x0022,0x0003,DICOM_T_UNK, _T("Image Path Filter Pass-Through Wavelength") }, -{ 0x0022,0x0004,DICOM_T_UNK, _T("Image Path Filter Pass Band") }, -{ 0x0022,0x0005,DICOM_T_UNK, _T("Patient Eye Movement Commanded") }, -{ 0x0022,0x0006,DICOM_T_UNK, _T("Patient Eye Movement Command Code Sequence") }, -{ 0x0022,0x0007,DICOM_T_UNK, _T("Spherical Lens Power") }, -{ 0x0022,0x0008,DICOM_T_UNK, _T("Cylinder Lens Power") }, -{ 0x0022,0x0009,DICOM_T_UNK, _T("Cylinder Axis") }, -{ 0x0022,0x000A,DICOM_T_UNK, _T("Emmetropic Magnification") }, -{ 0x0022,0x000B,DICOM_T_UNK, _T("Intra Ocular Pressure") }, -{ 0x0022,0x000C,DICOM_T_UNK, _T("Horizontal Field of View") }, -{ 0x0022,0x000D,DICOM_T_UNK, _T("Pupil Dilated") }, -{ 0x0022,0x000E,DICOM_T_UNK, _T("Degree of Dilation") }, -{ 0x0022,0x0010,DICOM_T_UNK, _T("Stereo Baseline Angle") }, -{ 0x0022,0x0011,DICOM_T_UNK, _T("Stereo Baseline Displacement") }, -{ 0x0022,0x0012,DICOM_T_UNK, _T("Stereo Horizontal Pixel Offset") }, -{ 0x0022,0x0013,DICOM_T_UNK, _T("Stereo Vertical Pixel Offset") }, -{ 0x0022,0x0014,DICOM_T_UNK, _T("Stereo Rotation") }, -{ 0x0022,0x0015,DICOM_T_UNK, _T("Acquisition Device Type Code Sequence") }, -{ 0x0022,0x0016,DICOM_T_UNK, _T("Illumination Type Code Sequence") }, -{ 0x0022,0x0017,DICOM_T_UNK, _T("Light Path Filter Type Stack Code Sequence") }, -{ 0x0022,0x0018,DICOM_T_UNK, _T("Image Path Filter Type Stack Code Sequence") }, -{ 0x0022,0x0019,DICOM_T_UNK, _T("Lenses Code Sequence") }, -{ 0x0022,0x001A,DICOM_T_UNK, _T("Channel Description Code Sequence") }, -{ 0x0022,0x001B,DICOM_T_UNK, _T("Refractive State Sequence") }, -{ 0x0022,0x001C,DICOM_T_UNK, _T("Mydriatic Agent Code Sequence") }, -{ 0x0022,0x001D,DICOM_T_UNK, _T("Relative Image Position Code Sequence") }, -{ 0x0022,0x001E,DICOM_T_UNK, _T("Camera Angle of View") }, -{ 0x0022,0x0020,DICOM_T_UNK, _T("Stereo Pairs Sequence") }, -{ 0x0022,0x0021,DICOM_T_UNK, _T("Left Image Sequence") }, -{ 0x0022,0x0022,DICOM_T_UNK, _T("Right Image Sequence") }, -{ 0x0022,0x0030,DICOM_T_UNK, _T("Axial Length of the Eye") }, -{ 0x0022,0x0031,DICOM_T_UNK, _T("Ophthalmic Frame Location Sequence") }, -{ 0x0022,0x0032,DICOM_T_UNK, _T("Reference Coordinates") }, -{ 0x0022,0x0035,DICOM_T_UNK, _T("Depth Spatial Resolution") }, -{ 0x0022,0x0036,DICOM_T_UNK, _T("Maximum Depth Distortion") }, -{ 0x0022,0x0037,DICOM_T_UNK, _T("Along-scan Spatial Resolution") }, -{ 0x0022,0x0038,DICOM_T_UNK, _T("Maximum Along-scan Distortion") }, -{ 0x0022,0x0039,DICOM_T_UNK, _T("Ophthalmic Image Orientation") }, -{ 0x0022,0x0041,DICOM_T_UNK, _T("Depth of Transverse Image") }, -{ 0x0022,0x0042,DICOM_T_UNK, _T("Mydriatic Agent Concentration Units Sequence") }, -{ 0x0022,0x0048,DICOM_T_UNK, _T("Across-scan Spatial Resolution") }, -{ 0x0022,0x0049,DICOM_T_UNK, _T("Maximum Across-scan Distortion") }, -{ 0x0022,0x004E,DICOM_T_UNK, _T("Mydriatic Agent Concentration") }, -{ 0x0022,0x0055,DICOM_T_UNK, _T("Illumination Wave Length") }, -{ 0x0022,0x0056,DICOM_T_UNK, _T("Illumination Power") }, -{ 0x0022,0x0057,DICOM_T_UNK, _T("Illumination Bandwidth") }, -{ 0x0022,0x0058,DICOM_T_UNK, _T("Mydriatic Agent Sequence") }, -{ 0x0022,0x1007,DICOM_T_UNK, _T("Ophthalmic Axial Measurements Right Eye Sequence") }, -{ 0x0022,0x1008,DICOM_T_UNK, _T("Ophthalmic Axial Measurements Left Eye Sequence") }, -{ 0x0022,0x1009,DICOM_T_UNK, _T("Ophthalmic Axial Measurements Device Type") }, -{ 0x0022,0x1010,DICOM_T_UNK, _T("Ophthalmic Axial Length Measurements Type") }, -{ 0x0022,0x1012,DICOM_T_UNK, _T("Ophthalmic Axial Length Sequence") }, -{ 0x0022,0x1019,DICOM_T_UNK, _T("Ophthalmic Axial Length") }, -{ 0x0022,0x1024,DICOM_T_UNK, _T("Lens Status Code Sequence") }, -{ 0x0022,0x1025,DICOM_T_UNK, _T("Vitreous Status Code Sequence") }, -{ 0x0022,0x1028,DICOM_T_UNK, _T("IOL Formula Code Sequence") }, -{ 0x0022,0x1029,DICOM_T_UNK, _T("IOL Formula Detail") }, -{ 0x0022,0x1033,DICOM_T_UNK, _T("Keratometer Index") }, -{ 0x0022,0x1035,DICOM_T_UNK, _T("Source of Ophthalmic Axial Length Code Sequence") }, -{ 0x0022,0x1037,DICOM_T_UNK, _T("Target Refraction") }, -{ 0x0022,0x1039,DICOM_T_UNK, _T("Refractive Procedure Occurred") }, -{ 0x0022,0x1040,DICOM_T_UNK, _T("Refractive Surgery Type Code Sequence") }, -{ 0x0022,0x1044,DICOM_T_UNK, _T("Ophthalmic Ultrasound Method Code Sequence") }, -{ 0x0022,0x1050,DICOM_T_UNK, _T("Ophthalmic Axial Length Measurements Sequence") }, -{ 0x0022,0x1053,DICOM_T_UNK, _T("IOL Power") }, -{ 0x0022,0x1054,DICOM_T_UNK, _T("Predicted Refractive Error") }, -{ 0x0022,0x1059,DICOM_T_UNK, _T("Ophthalmic Axial Length Velocity") }, -{ 0x0022,0x1065,DICOM_T_UNK, _T("Lens Status Description") }, -{ 0x0022,0x1066,DICOM_T_UNK, _T("Vitreous Status Description") }, -{ 0x0022,0x1090,DICOM_T_UNK, _T("IOL Power Sequence") }, -{ 0x0022,0x1092,DICOM_T_UNK, _T("Lens Constant Sequence") }, -{ 0x0022,0x1093,DICOM_T_UNK, _T("IOL Manufacturer") }, -{ 0x0022,0x1094,DICOM_T_UNK, _T("Lens Constant Description") }, -{ 0x0022,0x1095,DICOM_T_UNK, _T("Implant Name") }, -{ 0x0022,0x1096,DICOM_T_UNK, _T("Keratometry Measurement Type Code Sequence") }, -{ 0x0022,0x1097,DICOM_T_UNK, _T("Implant Part Number") }, -{ 0x0022,0x1100,DICOM_T_UNK, _T("Referenced Ophthalmic Axial Measurements Sequence") }, -{ 0x0022,0x1101,DICOM_T_UNK, _T("Ophthalmic Axial Length Measurements Segment Name Code Sequence") }, -{ 0x0022,0x1103,DICOM_T_UNK, _T("Refractive Error Before Refractive Surgery Code Sequence") }, -{ 0x0022,0x1121,DICOM_T_UNK, _T("IOL Power For Exact Emmetropia") }, -{ 0x0022,0x1122,DICOM_T_UNK, _T("IOL Power For Exact Target Refraction") }, -{ 0x0022,0x1125,DICOM_T_UNK, _T("Anterior Chamber Depth Definition Code Sequence") }, -{ 0x0022,0x1127,DICOM_T_UNK, _T("Lens Thickness Sequence") }, -{ 0x0022,0x1128,DICOM_T_UNK, _T("Anterior Chamber Depth Sequence") }, -{ 0x0022,0x1130,DICOM_T_UNK, _T("Lens Thickness") }, -{ 0x0022,0x1131,DICOM_T_UNK, _T("Anterior Chamber Depth") }, -{ 0x0022,0x1132,DICOM_T_UNK, _T("Source of Lens Thickness Data Code Sequence") }, -{ 0x0022,0x1133,DICOM_T_UNK, _T("Source of Anterior Chamber Depth Data Code Sequence") }, -{ 0x0022,0x1134,DICOM_T_UNK, _T("Source of Refractive Measurements Sequence") }, -{ 0x0022,0x1135,DICOM_T_UNK, _T("Source of Refractive Measurements Code Sequence") }, -{ 0x0022,0x1140,DICOM_T_UNK, _T("Ophthalmic Axial Length Measurement Modified") }, -{ 0x0022,0x1150,DICOM_T_UNK, _T("Ophthalmic Axial Length Data Source Code Sequence") }, -{ 0x0022,0x1153,DICOM_T_UNK, _T("Ophthalmic Axial Length Acquisition Method Code Sequence") }, -{ 0x0022,0x1155,DICOM_T_UNK, _T("Signal to Noise Ratio") }, -{ 0x0022,0x1159,DICOM_T_UNK, _T("Ophthalmic Axial Length Data Source Description") }, -{ 0x0022,0x1210,DICOM_T_UNK, _T("Ophthalmic Axial Length Measurements Total Length Sequence") }, -{ 0x0022,0x1211,DICOM_T_UNK, _T("Ophthalmic Axial Length Measurements Segmental Length Sequence") }, -{ 0x0022,0x1212,DICOM_T_UNK, _T("Ophthalmic Axial Length Measurements Length Summation Sequence") }, -{ 0x0022,0x1220,DICOM_T_UNK, _T("Ultrasound Ophthalmic Axial Length Measurements Sequence") }, -{ 0x0022,0x1225,DICOM_T_UNK, _T("Optical Ophthalmic Axial Length Measurements Sequence") }, -{ 0x0022,0x1230,DICOM_T_UNK, _T("Ultrasound Selected Ophthalmic Axial Length Sequence") }, -{ 0x0022,0x1250,DICOM_T_UNK, _T("Ophthalmic Axial Length Selection Method Code Sequence") }, -{ 0x0022,0x1255,DICOM_T_UNK, _T("Optical Selected Ophthalmic Axial Length Sequence") }, -{ 0x0022,0x1257,DICOM_T_UNK, _T("Selected Segmental Ophthalmic Axial Length Sequence") }, -{ 0x0022,0x1260,DICOM_T_UNK, _T("Selected Total Ophthalmic Axial Length Sequence") }, -{ 0x0022,0x1262,DICOM_T_UNK, _T("Ophthalmic Axial Length Quality Metric Sequence") }, -{ 0x0022,0x1265,DICOM_T_UNK, _T("Ophthalmic Axial Length Quality Metric Type Code Sequence") }, -{ 0x0022,0x1273,DICOM_T_UNK, _T("Ophthalmic Axial Length Quality Metric Type Description") }, -{ 0x0022,0x1300,DICOM_T_UNK, _T("Intraocular Lens Calculations Right Eye Sequence") }, -{ 0x0022,0x1310,DICOM_T_UNK, _T("Intraocular Lens Calculations Left Eye Sequence") }, -{ 0x0022,0x1330,DICOM_T_UNK, _T("Referenced Ophthalmic Axial Length Measurement QC Image Sequence") }, -{ 0x0022,0x1415,DICOM_T_UNK, _T("Ophthalmic Mapping Device Type") }, -{ 0x0022,0x1420,DICOM_T_UNK, _T("Acquisition Method Code Sequence") }, -{ 0x0022,0x1423,DICOM_T_UNK, _T("Acquisition Method Algorithm Sequence") }, -{ 0x0022,0x1436,DICOM_T_UNK, _T("Ophthalmic Thickness Map Type Code Sequence") }, -{ 0x0022,0x1443,DICOM_T_UNK, _T("Ophthalmic Thickness Mapping Normals Sequence") }, -{ 0x0022,0x1445,DICOM_T_UNK, _T("Retinal Thickness Definition Code Sequence") }, -{ 0x0022,0x1450,DICOM_T_UNK, _T("Pixel Value Mapping to Coded Concept Sequence") }, -{ 0x0022,0x1452,DICOM_T_UNK, _T("Mapped Pixel Value") }, -{ 0x0022,0x1454,DICOM_T_UNK, _T("Pixel Value Mapping Explanation") }, -{ 0x0022,0x1458,DICOM_T_UNK, _T("Ophthalmic Thickness Map Quality Threshold Sequence") }, -{ 0x0022,0x1460,DICOM_T_UNK, _T("Ophthalmic Thickness Map Threshold Quality Rating") }, -{ 0x0022,0x1463,DICOM_T_UNK, _T("Anatomic Structure Reference Point") }, -{ 0x0022,0x1465,DICOM_T_UNK, _T("Registration to Localizer Sequence") }, -{ 0x0022,0x1466,DICOM_T_UNK, _T("Registered Localizer Units") }, -{ 0x0022,0x1467,DICOM_T_UNK, _T("Registered Localizer Top Left Hand Corner") }, -{ 0x0022,0x1468,DICOM_T_UNK, _T("Registered Localizer Bottom Right Hand Corner") }, -{ 0x0022,0x1470,DICOM_T_UNK, _T("Ophthalmic Thickness Map Quality Rating Sequence") }, -{ 0x0022,0x1472,DICOM_T_UNK, _T("Relevant OPT Attributes Sequence") }, -{ 0x0024,0x0010,DICOM_T_UNK, _T("Visual Field Horizontal Extent") }, -{ 0x0024,0x0011,DICOM_T_UNK, _T("Visual Field Vertical Extent") }, -{ 0x0024,0x0012,DICOM_T_UNK, _T("Visual Field Shape") }, -{ 0x0024,0x0016,DICOM_T_UNK, _T("Screening Test Mode Code Sequence") }, -{ 0x0024,0x0018,DICOM_T_UNK, _T("Maximum Stimulus Luminance") }, -{ 0x0024,0x0020,DICOM_T_UNK, _T("Background Luminance") }, -{ 0x0024,0x0021,DICOM_T_UNK, _T("Stimulus Color Code Sequence") }, -{ 0x0024,0x0024,DICOM_T_UNK, _T("Background Illumination Color Code Sequence") }, -{ 0x0024,0x0025,DICOM_T_UNK, _T("Stimulus Area") }, -{ 0x0024,0x0028,DICOM_T_UNK, _T("Stimulus Presentation Time") }, -{ 0x0024,0x0032,DICOM_T_UNK, _T("Fixation Sequence") }, -{ 0x0024,0x0033,DICOM_T_UNK, _T("Fixation Monitoring Code Sequence") }, -{ 0x0024,0x0034,DICOM_T_UNK, _T("Visual Field Catch Trial Sequence") }, -{ 0x0024,0x0035,DICOM_T_UNK, _T("Fixation Checked Quantity") }, -{ 0x0024,0x0036,DICOM_T_UNK, _T("Patient Not Properly Fixated Quantity") }, -{ 0x0024,0x0037,DICOM_T_UNK, _T("Presented Visual Stimuli Data Flag") }, -{ 0x0024,0x0038,DICOM_T_UNK, _T("Number of Visual Stimuli") }, -{ 0x0024,0x0039,DICOM_T_UNK, _T("Excessive Fixation Losses Data Flag") }, -{ 0x0024,0x0040,DICOM_T_UNK, _T("Excessive Fixation Losses") }, -{ 0x0024,0x0042,DICOM_T_UNK, _T("Stimuli Retesting Quantity") }, -{ 0x0024,0x0044,DICOM_T_UNK, _T("Comments on Patient's Performance of Visual Field") }, -{ 0x0024,0x0045,DICOM_T_UNK, _T("False Negatives Estimate Flag") }, -{ 0x0024,0x0046,DICOM_T_UNK, _T("False Negatives Estimate") }, -{ 0x0024,0x0048,DICOM_T_UNK, _T("Negative Catch Trials Quantity") }, -{ 0x0024,0x0050,DICOM_T_UNK, _T("False Negatives Quantity") }, -{ 0x0024,0x0051,DICOM_T_UNK, _T("Excessive False Negatives Data Flag") }, -{ 0x0024,0x0052,DICOM_T_UNK, _T("Excessive False Negatives") }, -{ 0x0024,0x0053,DICOM_T_UNK, _T("False Positives Estimate Flag") }, -{ 0x0024,0x0054,DICOM_T_UNK, _T("False Positives Estimate") }, -{ 0x0024,0x0055,DICOM_T_UNK, _T("Catch Trials Data Flag") }, -{ 0x0024,0x0056,DICOM_T_UNK, _T("Positive Catch Trials Quantity") }, -{ 0x0024,0x0057,DICOM_T_UNK, _T("Test Point Normals Data Flag") }, -{ 0x0024,0x0058,DICOM_T_UNK, _T("Test Point Normals Sequence") }, -{ 0x0024,0x0059,DICOM_T_UNK, _T("Global Deviation Probability Normals Flag") }, -{ 0x0024,0x0060,DICOM_T_UNK, _T("False Positives Quantity") }, -{ 0x0024,0x0061,DICOM_T_UNK, _T("Excessive False Positives Data Flag") }, -{ 0x0024,0x0062,DICOM_T_UNK, _T("Excessive False Positives") }, -{ 0x0024,0x0063,DICOM_T_UNK, _T("Visual Field Test Normals Flag") }, -{ 0x0024,0x0064,DICOM_T_UNK, _T("Results Normals Sequence") }, -{ 0x0024,0x0065,DICOM_T_UNK, _T("Age Corrected Sensitivity Deviation Algorithm Sequence") }, -{ 0x0024,0x0066,DICOM_T_UNK, _T("Global Deviation From Normal") }, -{ 0x0024,0x0067,DICOM_T_UNK, _T("Generalized Defect Sensitivity Deviation Algorithm Sequence") }, -{ 0x0024,0x0068,DICOM_T_UNK, _T("Localized Deviation From Normal") }, -{ 0x0024,0x0069,DICOM_T_UNK, _T("Patient Reliability Indicator") }, -{ 0x0024,0x0070,DICOM_T_UNK, _T("Visual Field Mean Sensitivity") }, -{ 0x0024,0x0071,DICOM_T_UNK, _T("Global Deviation Probability") }, -{ 0x0024,0x0072,DICOM_T_UNK, _T("Local Deviation Probability Normals Flag") }, -{ 0x0024,0x0073,DICOM_T_UNK, _T("Localized Deviation Probability") }, -{ 0x0024,0x0074,DICOM_T_UNK, _T("Short Term Fluctuation Calculated") }, -{ 0x0024,0x0075,DICOM_T_UNK, _T("Short Term Fluctuation") }, -{ 0x0024,0x0076,DICOM_T_UNK, _T("Short Term Fluctuation Probability Calculated") }, -{ 0x0024,0x0077,DICOM_T_UNK, _T("Short Term Fluctuation Probability") }, -{ 0x0024,0x0078,DICOM_T_UNK, _T("Corrected Localized Deviation From Normal Calculated") }, -{ 0x0024,0x0079,DICOM_T_UNK, _T("Corrected Localized Deviation From Normal") }, -{ 0x0024,0x0080,DICOM_T_UNK, _T("Corrected Localized Deviation From Normal Probability Calculated") }, -{ 0x0024,0x0081,DICOM_T_UNK, _T("Corrected Localized Deviation From Normal Probability") }, -{ 0x0024,0x0083,DICOM_T_UNK, _T("Global Deviation Probability Sequence") }, -{ 0x0024,0x0085,DICOM_T_UNK, _T("Localized Deviation Probability Sequence") }, -{ 0x0024,0x0086,DICOM_T_UNK, _T("Foveal Sensitivity Measured") }, -{ 0x0024,0x0087,DICOM_T_UNK, _T("Foveal Sensitivity") }, -{ 0x0024,0x0088,DICOM_T_UNK, _T("Visual Field Test Duration") }, -{ 0x0024,0x0089,DICOM_T_UNK, _T("Visual Field Test Point Sequence") }, -{ 0x0024,0x0090,DICOM_T_UNK, _T("Visual Field Test Point X-Coordinate") }, -{ 0x0024,0x0091,DICOM_T_UNK, _T("Visual Field Test Point Y-Coordinate") }, -{ 0x0024,0x0092,DICOM_T_UNK, _T("Age Corrected Sensitivity Deviation Value") }, -{ 0x0024,0x0093,DICOM_T_UNK, _T("Stimulus Results") }, -{ 0x0024,0x0094,DICOM_T_UNK, _T("Sensitivity Value") }, -{ 0x0024,0x0095,DICOM_T_UNK, _T("Retest Stimulus Seen") }, -{ 0x0024,0x0096,DICOM_T_UNK, _T("Retest Sensitivity Value") }, -{ 0x0024,0x0097,DICOM_T_UNK, _T("Visual Field Test Point Normals Sequence") }, -{ 0x0024,0x0098,DICOM_T_UNK, _T("Quantified Defect") }, -{ 0x0024,0x0100,DICOM_T_UNK, _T("Age Corrected Sensitivity Deviation Probability Value") }, -{ 0x0024,0x0102,DICOM_T_UNK, _T("Generalized Defect Corrected Sensitivity Deviation Flag") }, -{ 0x0024,0x0103,DICOM_T_UNK, _T("Generalized Defect Corrected Sensitivity Deviation Value") }, -{ 0x0024,0x0104,DICOM_T_UNK, _T("Generalized Defect Corrected Sensitivity Deviation Probability Value") }, -{ 0x0024,0x0105,DICOM_T_UNK, _T("Minimum Sensitivity Value") }, -{ 0x0024,0x0106,DICOM_T_UNK, _T("Blind Spot Localized") }, -{ 0x0024,0x0107,DICOM_T_UNK, _T("Blind Spot X-Coordinate") }, -{ 0x0024,0x0108,DICOM_T_UNK, _T("Blind Spot Y-Coordinate") }, -{ 0x0024,0x0110,DICOM_T_UNK, _T("Visual Acuity Measurement Sequence") }, -{ 0x0024,0x0112,DICOM_T_UNK, _T("Refractive Parameters Used on Patient Sequence") }, -{ 0x0024,0x0113,DICOM_T_UNK, _T("Measurement Laterality") }, -{ 0x0024,0x0114,DICOM_T_UNK, _T("Ophthalmic Patient Clinical Information Left Eye Sequence") }, -{ 0x0024,0x0115,DICOM_T_UNK, _T("Ophthalmic Patient Clinical Information Right Eye Sequence") }, -{ 0x0024,0x0117,DICOM_T_UNK, _T("Foveal Point Normative Data Flag") }, -{ 0x0024,0x0118,DICOM_T_UNK, _T("Foveal Point Probability Value") }, -{ 0x0024,0x0120,DICOM_T_UNK, _T("Screening Baseline Measured") }, -{ 0x0024,0x0122,DICOM_T_UNK, _T("Screening Baseline Measured Sequence") }, -{ 0x0024,0x0124,DICOM_T_UNK, _T("Screening Baseline Type") }, -{ 0x0024,0x0126,DICOM_T_UNK, _T("Screening Baseline Value") }, -{ 0x0024,0x0202,DICOM_T_UNK, _T("Algorithm Source") }, -{ 0x0024,0x0306,DICOM_T_UNK, _T("Data Set Name") }, -{ 0x0024,0x0307,DICOM_T_UNK, _T("Data Set Version") }, -{ 0x0024,0x0308,DICOM_T_UNK, _T("Data Set Source") }, -{ 0x0024,0x0309,DICOM_T_UNK, _T("Data Set Description") }, -{ 0x0024,0x0317,DICOM_T_UNK, _T("Visual Field Test Reliability Global Index Sequence") }, -{ 0x0024,0x0320,DICOM_T_UNK, _T("Visual Field Global Results Index Sequence") }, -{ 0x0024,0x0325,DICOM_T_UNK, _T("Data Observation Sequence") }, -{ 0x0024,0x0338,DICOM_T_UNK, _T("Index Normals Flag") }, -{ 0x0024,0x0341,DICOM_T_UNK, _T("Index Probability") }, -{ 0x0024,0x0344,DICOM_T_UNK, _T("Index Probability Sequence") }, -{ 0x0028,0x0002,DICOM_T_UNK, _T("Samples per Pixel") }, -{ 0x0028,0x0003,DICOM_T_UNK, _T("Samples per Pixel Used") }, -{ 0x0028,0x0004,DICOM_T_UNK, _T("Photometric Interpretation") }, -{ 0x0028,0x0005,DICOM_T_UNK, _T("Image Dimensions") }, -{ 0x0028,0x0006,DICOM_T_UNK, _T("Planar Configuration") }, -{ 0x0028,0x0008,DICOM_T_UNK, _T("Number of Frames") }, -{ 0x0028,0x0009,DICOM_T_UNK, _T("Frame Increment Pointer") }, -{ 0x0028,0x000A,DICOM_T_UNK, _T("Frame Dimension Pointer") }, -{ 0x0028,0x0010,DICOM_T_UNK, _T("Rows") }, -{ 0x0028,0x0011,DICOM_T_UNK, _T("Columns") }, -{ 0x0028,0x0012,DICOM_T_UNK, _T("Planes") }, -{ 0x0028,0x0014,DICOM_T_UNK, _T("Ultrasound Color Data Present") }, -{ 0x0028,0x0020,DICOM_T_UNK, _T("") }, -{ 0x0028,0x0030,DICOM_T_UNK, _T("Pixel Spacing") }, -{ 0x0028,0x0031,DICOM_T_UNK, _T("Zoom Factor") }, -{ 0x0028,0x0032,DICOM_T_UNK, _T("Zoom Center") }, -{ 0x0028,0x0034,DICOM_T_UNK, _T("Pixel Aspect Ratio") }, -{ 0x0028,0x0040,DICOM_T_UNK, _T("Image Format") }, -{ 0x0028,0x0050,DICOM_T_UNK, _T("Manipulated Image") }, -{ 0x0028,0x0051,DICOM_T_UNK, _T("Corrected Image") }, -{ 0x0028,0x005F,DICOM_T_UNK, _T("Compression Recognition Code") }, -{ 0x0028,0x0060,DICOM_T_UNK, _T("Compression Code") }, -{ 0x0028,0x0061,DICOM_T_UNK, _T("Compression Originator") }, -{ 0x0028,0x0062,DICOM_T_UNK, _T("Compression Label") }, -{ 0x0028,0x0063,DICOM_T_UNK, _T("Compression Description") }, -{ 0x0028,0x0065,DICOM_T_UNK, _T("Compression Sequence") }, -{ 0x0028,0x0066,DICOM_T_UNK, _T("Compression Step Pointers") }, -{ 0x0028,0x0068,DICOM_T_UNK, _T("Repeat Interval") }, -{ 0x0028,0x0069,DICOM_T_UNK, _T("Bits Grouped") }, -{ 0x0028,0x0070,DICOM_T_UNK, _T("Perimeter Table") }, -{ 0x0028,0x0071,DICOM_T_UNK, _T("Perimeter Value") }, -{ 0x0028,0x0080,DICOM_T_UNK, _T("Predictor Rows") }, -{ 0x0028,0x0081,DICOM_T_UNK, _T("Predictor Columns") }, -{ 0x0028,0x0082,DICOM_T_UNK, _T("Predictor Constants") }, -{ 0x0028,0x0090,DICOM_T_UNK, _T("Blocked Pixels") }, -{ 0x0028,0x0091,DICOM_T_UNK, _T("Block Rows") }, -{ 0x0028,0x0092,DICOM_T_UNK, _T("Block Columns") }, -{ 0x0028,0x0093,DICOM_T_UNK, _T("Row Overlap") }, -{ 0x0028,0x0094,DICOM_T_UNK, _T("Column Overlap") }, -{ 0x0028,0x0100,DICOM_T_UNK, _T("Bits Allocated") }, -{ 0x0028,0x0101,DICOM_T_UNK, _T("Bits Stored") }, -{ 0x0028,0x0102,DICOM_T_UNK, _T("High Bit") }, -{ 0x0028,0x0103,DICOM_T_UNK, _T("Pixel Representation") }, -{ 0x0028,0x0104,DICOM_T_UNK, _T("Smallest Valid Pixel Value") }, -{ 0x0028,0x0105,DICOM_T_UNK, _T("Largest Valid Pixel Value") }, -{ 0x0028,0x0106,DICOM_T_UNK, _T("Smallest Image Pixel Value") }, -{ 0x0028,0x0107,DICOM_T_UNK, _T("Largest Image Pixel Value") }, -{ 0x0028,0x0108,DICOM_T_UNK, _T("Smallest Pixel Value in Series") }, -{ 0x0028,0x0109,DICOM_T_UNK, _T("Largest Pixel Value in Series") }, -{ 0x0028,0x0110,DICOM_T_UNK, _T("Smallest Image Pixel Value in Plane") }, -{ 0x0028,0x0111,DICOM_T_UNK, _T("Largest Image Pixel Value in Plane") }, -{ 0x0028,0x0120,DICOM_T_UNK, _T("Pixel Padding Value") }, -{ 0x0028,0x0121,DICOM_T_UNK, _T("Pixel Padding Range Limit") }, -{ 0x0028,0x0200,DICOM_T_UNK, _T("Image Location") }, -{ 0x0028,0x0300,DICOM_T_UNK, _T("Quality Control Image") }, -{ 0x0028,0x0301,DICOM_T_UNK, _T("Burned In Annotation") }, -{ 0x0028,0x0302,DICOM_T_UNK, _T("Recognizable Visual Features") }, -{ 0x0028,0x0303,DICOM_T_UNK, _T("Longitudinal Temporal Information Modified") }, -{ 0x0028,0x0304,DICOM_T_UNK, _T("Referenced Color Palette Instance UID") }, -{ 0x0028,0x0400,DICOM_T_UNK, _T("Transform Label") }, -{ 0x0028,0x0401,DICOM_T_UNK, _T("Transform Version Number") }, -{ 0x0028,0x0402,DICOM_T_UNK, _T("Number of Transform Steps") }, -{ 0x0028,0x0403,DICOM_T_UNK, _T("Sequence of Compressed Data") }, -{ 0x0028,0x0404,DICOM_T_UNK, _T("Details of Coefficients") }, -/* -{ 0x0028,0x04x0,DICOM_T_UNK, _T("Rows For Nth Order Coefficients") }, -{ 0x0028,0x04x1,DICOM_T_UNK, _T("Columns For Nth Order Coefficients") }, -{ 0x0028,0x04x2,DICOM_T_UNK, _T("Coefficient Coding") }, -{ 0x0028,0x04x3,DICOM_T_UNK, _T("Coefficient Coding Pointers") }, -*/ -{ 0x0028,0x0700,DICOM_T_UNK, _T("DCT Label") }, -{ 0x0028,0x0701,DICOM_T_UNK, _T("Data Block Description") }, -{ 0x0028,0x0702,DICOM_T_UNK, _T("Data Block") }, -{ 0x0028,0x0710,DICOM_T_UNK, _T("Normalization Factor Format") }, -{ 0x0028,0x0720,DICOM_T_UNK, _T("Zonal Map Number Format") }, -{ 0x0028,0x0721,DICOM_T_UNK, _T("Zonal Map Location") }, -{ 0x0028,0x0722,DICOM_T_UNK, _T("Zonal Map Format") }, -{ 0x0028,0x0730,DICOM_T_UNK, _T("Adaptive Map Format") }, -{ 0x0028,0x0740,DICOM_T_UNK, _T("Code Number Format") }, -/* -{ 0x0028,0x08x0,DICOM_T_UNK, _T("Code Label") }, -{ 0x0028,0x08x2,DICOM_T_UNK, _T("Number of Tables") }, -{ 0x0028,0x08x3,DICOM_T_UNK, _T("Code Table Location") }, -{ 0x0028,0x08x4,DICOM_T_UNK, _T("Bits For Code Word") }, -{ 0x0028,0x08x8,DICOM_T_UNK, _T("Image Data Location") }, -*/ -{ 0x0028,0x0A02,DICOM_T_UNK, _T("Pixel Spacing Calibration Type") }, -{ 0x0028,0x0A04,DICOM_T_UNK, _T("Pixel Spacing Calibration Description") }, -{ 0x0028,0x1040,DICOM_T_UNK, _T("Pixel Intensity Relationship") }, -{ 0x0028,0x1041,DICOM_T_UNK, _T("Pixel Intensity Relationship Sign") }, -{ 0x0028,0x1050,DICOM_T_UNK, _T("Window Center") }, -{ 0x0028,0x1051,DICOM_T_UNK, _T("Window Width") }, -{ 0x0028,0x1052,DICOM_T_UNK, _T("Rescale Intercept") }, -{ 0x0028,0x1053,DICOM_T_UNK, _T("Rescale Slope") }, -{ 0x0028,0x1054,DICOM_T_UNK, _T("Rescale Type") }, -{ 0x0028,0x1055,DICOM_T_UNK, _T("Window Center & Width Explanation") }, -{ 0x0028,0x1056,DICOM_T_UNK, _T("VOI LUT Function") }, -{ 0x0028,0x1080,DICOM_T_UNK, _T("Gray Scale") }, -{ 0x0028,0x1090,DICOM_T_UNK, _T("Recommended Viewing Mode") }, -{ 0x0028,0x1100,DICOM_T_UNK, _T("Gray Lookup Table Descriptor") }, -{ 0x0028,0x1101,DICOM_T_UNK, _T("Red Palette Color Lookup Table Descriptor") }, -{ 0x0028,0x1102,DICOM_T_UNK, _T("Green Palette Color Lookup Table Descriptor") }, -{ 0x0028,0x1103,DICOM_T_UNK, _T("Blue Palette Color Lookup Table Descriptor") }, -{ 0x0028,0x1104,DICOM_T_UNK, _T("Alpha Palette Color Lookup Table Descriptor") }, -{ 0x0028,0x1111,DICOM_T_UNK, _T("Large Red Palette Color Lookup Table Descriptor") }, -{ 0x0028,0x1112,DICOM_T_UNK, _T("Large Green Palette Color Lookup Table Descriptor") }, -{ 0x0028,0x1113,DICOM_T_UNK, _T("Large Blue Palette Color Lookup Table Descriptor") }, -{ 0x0028,0x1199,DICOM_T_UNK, _T("Palette Color Lookup Table UID") }, -{ 0x0028,0x1200,DICOM_T_UNK, _T("Gray Lookup Table Data") }, -{ 0x0028,0x1201,DICOM_T_UNK, _T("Red Palette Color Lookup Table Data") }, -{ 0x0028,0x1202,DICOM_T_UNK, _T("Green Palette Color Lookup Table Data") }, -{ 0x0028,0x1203,DICOM_T_UNK, _T("Blue Palette Color Lookup Table Data") }, -{ 0x0028,0x1204,DICOM_T_UNK, _T("Alpha Palette Color Lookup Table Data") }, -{ 0x0028,0x1211,DICOM_T_UNK, _T("Large Red Palette Color Lookup Table Data") }, -{ 0x0028,0x1212,DICOM_T_UNK, _T("Large Green Palette Color Lookup Table Data") }, -{ 0x0028,0x1213,DICOM_T_UNK, _T("Large Blue Palette Color Lookup Table Data") }, -{ 0x0028,0x1214,DICOM_T_UNK, _T("Large Palette Color Lookup Table UID") }, -{ 0x0028,0x1221,DICOM_T_UNK, _T("Segmented Red Palette Color Lookup Table Data") }, -{ 0x0028,0x1222,DICOM_T_UNK, _T("Segmented Green Palette Color Lookup Table Data") }, -{ 0x0028,0x1223,DICOM_T_UNK, _T("Segmented Blue Palette Color Lookup Table Data") }, -{ 0x0028,0x1300,DICOM_T_UNK, _T("Breast Implant Present") }, -{ 0x0028,0x1350,DICOM_T_UNK, _T("Partial View") }, -{ 0x0028,0x1351,DICOM_T_UNK, _T("Partial View Description") }, -{ 0x0028,0x1352,DICOM_T_UNK, _T("Partial View Code Sequence") }, -{ 0x0028,0x135A,DICOM_T_UNK, _T("Spatial Locations Preserved") }, -{ 0x0028,0x1401,DICOM_T_UNK, _T("Data Frame Assignment Sequence") }, -{ 0x0028,0x1402,DICOM_T_UNK, _T("Data Path Assignment") }, -{ 0x0028,0x1403,DICOM_T_UNK, _T("Bits Mapped to Color Lookup Table") }, -{ 0x0028,0x1404,DICOM_T_UNK, _T("Blending LUT 1 Sequence") }, -{ 0x0028,0x1405,DICOM_T_UNK, _T("Blending LUT 1 Transfer Function") }, -{ 0x0028,0x1406,DICOM_T_UNK, _T("Blending Weight Constant") }, -{ 0x0028,0x1407,DICOM_T_UNK, _T("Blending Lookup Table Descriptor") }, -{ 0x0028,0x1408,DICOM_T_UNK, _T("Blending Lookup Table Data") }, -{ 0x0028,0x140B,DICOM_T_UNK, _T("Enhanced Palette Color Lookup Table Sequence") }, -{ 0x0028,0x140C,DICOM_T_UNK, _T("Blending LUT 2 Sequence") }, -{ 0x0028,0x140D,DICOM_T_UNK, _T("Blending LUT 2 Transfer Function") }, -{ 0x0028,0x140E,DICOM_T_UNK, _T("Data Path ID") }, -{ 0x0028,0x140F,DICOM_T_UNK, _T("RGB LUT Transfer Function") }, -{ 0x0028,0x1410,DICOM_T_UNK, _T("Alpha LUT Transfer Function") }, -{ 0x0028,0x2000,DICOM_T_UNK, _T("ICC Profile") }, -{ 0x0028,0x2110,DICOM_T_UNK, _T("Lossy Image Compression") }, -{ 0x0028,0x2112,DICOM_T_UNK, _T("Lossy Image Compression Ratio") }, -{ 0x0028,0x2114,DICOM_T_UNK, _T("Lossy Image Compression Method") }, -{ 0x0028,0x3000,DICOM_T_UNK, _T("Modality LUT Sequence") }, -{ 0x0028,0x3002,DICOM_T_UNK, _T("LUT Descriptor") }, -{ 0x0028,0x3003,DICOM_T_UNK, _T("LUT Explanation") }, -{ 0x0028,0x3004,DICOM_T_UNK, _T("Modality LUT Type") }, -{ 0x0028,0x3006,DICOM_T_UNK, _T("LUT Data") }, -{ 0x0028,0x3010,DICOM_T_UNK, _T("VOI LUT Sequence") }, -{ 0x0028,0x3110,DICOM_T_UNK, _T("Softcopy VOI LUT Sequence") }, -{ 0x0028,0x4000,DICOM_T_UNK, _T("Image Presentation Comments") }, -{ 0x0028,0x5000,DICOM_T_UNK, _T("Bi-Plane Acquisition Sequence") }, -{ 0x0028,0x6010,DICOM_T_UNK, _T("Representative Frame Number") }, -{ 0x0028,0x6020,DICOM_T_UNK, _T("Frame Numbers of Interest (FOI)") }, -{ 0x0028,0x6022,DICOM_T_UNK, _T("Frame of Interest Description") }, -{ 0x0028,0x6023,DICOM_T_UNK, _T("Frame of Interest Type") }, -{ 0x0028,0x6030,DICOM_T_UNK, _T("Mask Pointer(s)") }, -{ 0x0028,0x6040,DICOM_T_UNK, _T("R Wave Pointer") }, -{ 0x0028,0x6100,DICOM_T_UNK, _T("Mask Subtraction Sequence") }, -{ 0x0028,0x6101,DICOM_T_UNK, _T("Mask Operation") }, -{ 0x0028,0x6102,DICOM_T_UNK, _T("Applicable Frame Range") }, -{ 0x0028,0x6110,DICOM_T_UNK, _T("Mask Frame Numbers") }, -{ 0x0028,0x6112,DICOM_T_UNK, _T("Contrast Frame Averaging") }, -{ 0x0028,0x6114,DICOM_T_UNK, _T("Mask Sub-pixel Shift") }, -{ 0x0028,0x6120,DICOM_T_UNK, _T("TID Offset") }, -{ 0x0028,0x6190,DICOM_T_UNK, _T("Mask Operation Explanation") }, -{ 0x0028,0x7000,DICOM_T_UNK, _T("Equipment Administrator Sequence") }, -{ 0x0028,0x7001,DICOM_T_UNK, _T("Number of Display Subsystems") }, -{ 0x0028,0x7002,DICOM_T_UNK, _T("Current Configuration ID") }, -{ 0x0028,0x7003,DICOM_T_UNK, _T("Display Subsystem ID") }, -{ 0x0028,0x7004,DICOM_T_UNK, _T("Display Subsystem Name") }, -{ 0x0028,0x7005,DICOM_T_UNK, _T("Display Subsystem Description") }, -{ 0x0028,0x7006,DICOM_T_UNK, _T("System Status") }, -{ 0x0028,0x7007,DICOM_T_UNK, _T("System Status Comment") }, -{ 0x0028,0x7008,DICOM_T_UNK, _T("Target Luminance Characteristics Sequence") }, -{ 0x0028,0x7009,DICOM_T_UNK, _T("Luminance Characteristics ID") }, -{ 0x0028,0x700A,DICOM_T_UNK, _T("Display Subsystem Configuration Sequence") }, -{ 0x0028,0x700B,DICOM_T_UNK, _T("Configuration ID") }, -{ 0x0028,0x700C,DICOM_T_UNK, _T("Configuration Name") }, -{ 0x0028,0x700D,DICOM_T_UNK, _T("Configuration Description") }, -{ 0x0028,0x700E,DICOM_T_UNK, _T("Referenced Target Luminance Characteristics ID") }, -{ 0x0028,0x700F,DICOM_T_UNK, _T("QA Results Sequence") }, -{ 0x0028,0x7010,DICOM_T_UNK, _T("Display Subsystem QA Results Sequence") }, -{ 0x0028,0x7011,DICOM_T_UNK, _T("Configuration QA Results Sequence") }, -{ 0x0028,0x7012,DICOM_T_UNK, _T("Measurement Equipment Sequence") }, -{ 0x0028,0x7013,DICOM_T_UNK, _T("Measurement Functions") }, -{ 0x0028,0x7014,DICOM_T_UNK, _T("Measurement Equipment Type") }, -{ 0x0028,0x7015,DICOM_T_UNK, _T("Visual Evaluation Result Sequence") }, -{ 0x0028,0x7016,DICOM_T_UNK, _T("Display Calibration Result Sequence") }, -{ 0x0028,0x7017,DICOM_T_UNK, _T("DDL Value") }, -{ 0x0028,0x7018,DICOM_T_UNK, _T("CIExy White Point") }, -{ 0x0028,0x7019,DICOM_T_UNK, _T("Display Function Type") }, -{ 0x0028,0x701A,DICOM_T_UNK, _T("Gamma Value") }, -{ 0x0028,0x701B,DICOM_T_UNK, _T("Number of Luminance Points") }, -{ 0x0028,0x701C,DICOM_T_UNK, _T("Luminance Response Sequence") }, -{ 0x0028,0x701D,DICOM_T_UNK, _T("Target Minimum Luminance") }, -{ 0x0028,0x701E,DICOM_T_UNK, _T("Target Maximum Luminance") }, -{ 0x0028,0x701F,DICOM_T_UNK, _T("Luminance Value") }, -{ 0x0028,0x7020,DICOM_T_UNK, _T("Luminance Response Description") }, -{ 0x0028,0x7021,DICOM_T_UNK, _T("White Point Flag") }, -{ 0x0028,0x7022,DICOM_T_UNK, _T("Display Device Type Code Sequence") }, -{ 0x0028,0x7023,DICOM_T_UNK, _T("Display Subsystem Sequence") }, -{ 0x0028,0x7024,DICOM_T_UNK, _T("Luminance Result Sequence") }, -{ 0x0028,0x7025,DICOM_T_UNK, _T("Ambient Light Value Source") }, -{ 0x0028,0x7026,DICOM_T_UNK, _T("Measured Characteristics") }, -{ 0x0028,0x7027,DICOM_T_UNK, _T("Luminance Uniformity Result Sequence") }, -{ 0x0028,0x7028,DICOM_T_UNK, _T("Visual Evaluation Test Sequence") }, -{ 0x0028,0x7029,DICOM_T_UNK, _T("Test Result") }, -{ 0x0028,0x702A,DICOM_T_UNK, _T("Test Result Comment") }, -{ 0x0028,0x702B,DICOM_T_UNK, _T("Test Image Validation") }, -{ 0x0028,0x702C,DICOM_T_UNK, _T("Test Pattern Code Sequence") }, -{ 0x0028,0x702D,DICOM_T_UNK, _T("Measurement Pattern Code Sequence") }, -{ 0x0028,0x702E,DICOM_T_UNK, _T("Visual Evaluation Method Code Sequence") }, -{ 0x0028,0x7FE0,DICOM_T_UNK, _T("Pixel Data Provider URL") }, -{ 0x0028,0x9001,DICOM_T_UNK, _T("Data Point Rows") }, -{ 0x0028,0x9002,DICOM_T_UNK, _T("Data Point Columns") }, -{ 0x0028,0x9003,DICOM_T_UNK, _T("Signal Domain Columns") }, -{ 0x0028,0x9099,DICOM_T_UNK, _T("Largest Monochrome Pixel Value") }, -{ 0x0028,0x9108,DICOM_T_UNK, _T("Data Representation") }, -{ 0x0028,0x9110,DICOM_T_UNK, _T("Pixel Measures Sequence") }, -{ 0x0028,0x9132,DICOM_T_UNK, _T("Frame VOI LUT Sequence") }, -{ 0x0028,0x9145,DICOM_T_UNK, _T("Pixel Value Transformation Sequence") }, -{ 0x0028,0x9235,DICOM_T_UNK, _T("Signal Domain Rows") }, -{ 0x0028,0x9411,DICOM_T_UNK, _T("Display Filter Percentage") }, -{ 0x0028,0x9415,DICOM_T_UNK, _T("Frame Pixel Shift Sequence") }, -{ 0x0028,0x9416,DICOM_T_UNK, _T("Subtraction Item ID") }, -{ 0x0028,0x9422,DICOM_T_UNK, _T("Pixel Intensity Relationship LUT Sequence") }, -{ 0x0028,0x9443,DICOM_T_UNK, _T("Frame Pixel Data Properties Sequence") }, -{ 0x0028,0x9444,DICOM_T_UNK, _T("Geometrical Properties") }, -{ 0x0028,0x9445,DICOM_T_UNK, _T("Geometric Maximum Distortion") }, -{ 0x0028,0x9446,DICOM_T_UNK, _T("Image Processing Applied") }, -{ 0x0028,0x9454,DICOM_T_UNK, _T("Mask Selection Mode") }, -{ 0x0028,0x9474,DICOM_T_UNK, _T("LUT Function") }, -{ 0x0028,0x9478,DICOM_T_UNK, _T("Mask Visibility Percentage") }, -{ 0x0028,0x9501,DICOM_T_UNK, _T("Pixel Shift Sequence") }, -{ 0x0028,0x9502,DICOM_T_UNK, _T("Region Pixel Shift Sequence") }, -{ 0x0028,0x9503,DICOM_T_UNK, _T("Vertices of the Region") }, -{ 0x0028,0x9505,DICOM_T_UNK, _T("Multi-frame Presentation Sequence") }, -{ 0x0028,0x9506,DICOM_T_UNK, _T("Pixel Shift Frame Range") }, -{ 0x0028,0x9507,DICOM_T_UNK, _T("LUT Frame Range") }, -{ 0x0028,0x9520,DICOM_T_UNK, _T("Image to Equipment Mapping Matrix") }, -{ 0x0028,0x9537,DICOM_T_UNK, _T("Equipment Coordinate System Identification") }, -{ 0x0032,0x000A,DICOM_T_UNK, _T("Study Status ID") }, -{ 0x0032,0x000C,DICOM_T_UNK, _T("Study Priority ID") }, -{ 0x0032,0x0012,DICOM_T_UNK, _T("Study ID Issuer") }, -{ 0x0032,0x0032,DICOM_T_UNK, _T("Study Verified Date") }, -{ 0x0032,0x0033,DICOM_T_UNK, _T("Study Verified Time") }, -{ 0x0032,0x0034,DICOM_T_UNK, _T("Study Read Date") }, -{ 0x0032,0x0035,DICOM_T_UNK, _T("Study Read Time") }, -{ 0x0032,0x1000,DICOM_T_UNK, _T("Scheduled Study Start Date") }, -{ 0x0032,0x1001,DICOM_T_UNK, _T("Scheduled Study Start Time") }, -{ 0x0032,0x1010,DICOM_T_UNK, _T("Scheduled Study Stop Date") }, -{ 0x0032,0x1011,DICOM_T_UNK, _T("Scheduled Study Stop Time") }, -{ 0x0032,0x1020,DICOM_T_UNK, _T("Scheduled Study Location") }, -{ 0x0032,0x1021,DICOM_T_UNK, _T("Scheduled Study Location AE Title") }, -{ 0x0032,0x1030,DICOM_T_UNK, _T("Reason for Study") }, -{ 0x0032,0x1031,DICOM_T_UNK, _T("Requesting Physician Identification Sequence") }, -{ 0x0032,0x1032,DICOM_T_UNK, _T("Requesting Physician") }, -{ 0x0032,0x1033,DICOM_T_UNK, _T("Requesting Service") }, -{ 0x0032,0x1034,DICOM_T_UNK, _T("Requesting Service Code Sequence") }, -{ 0x0032,0x1040,DICOM_T_UNK, _T("Study Arrival Date") }, -{ 0x0032,0x1041,DICOM_T_UNK, _T("Study Arrival Time") }, -{ 0x0032,0x1050,DICOM_T_UNK, _T("Study Completion Date") }, -{ 0x0032,0x1051,DICOM_T_UNK, _T("Study Completion Time") }, -{ 0x0032,0x1055,DICOM_T_UNK, _T("Study Component Status ID") }, -{ 0x0032,0x1060,DICOM_T_UNK, _T("Requested Procedure Description") }, -{ 0x0032,0x1064,DICOM_T_UNK, _T("Requested Procedure Code Sequence") }, -{ 0x0032,0x1070,DICOM_T_UNK, _T("Requested Contrast Agent") }, -{ 0x0032,0x4000,DICOM_T_UNK, _T("Study Comments") }, -{ 0x0038,0x0004,DICOM_T_UNK, _T("Referenced Patient Alias Sequence") }, -{ 0x0038,0x0008,DICOM_T_UNK, _T("Visit Status ID") }, -{ 0x0038,0x0010,DICOM_T_UNK, _T("Admission ID") }, -{ 0x0038,0x0011,DICOM_T_UNK, _T("Issuer of Admission ID") }, -{ 0x0038,0x0014,DICOM_T_UNK, _T("Issuer of Admission ID Sequence") }, -{ 0x0038,0x0016,DICOM_T_UNK, _T("Route of Admissions") }, -{ 0x0038,0x001A,DICOM_T_UNK, _T("Scheduled Admission Date") }, -{ 0x0038,0x001B,DICOM_T_UNK, _T("Scheduled Admission Time") }, -{ 0x0038,0x001C,DICOM_T_UNK, _T("Scheduled Discharge Date") }, -{ 0x0038,0x001D,DICOM_T_UNK, _T("Scheduled Discharge Time") }, -{ 0x0038,0x001E,DICOM_T_UNK, _T("Scheduled Patient Institution Residence") }, -{ 0x0038,0x0020,DICOM_T_UNK, _T("Admitting Date") }, -{ 0x0038,0x0021,DICOM_T_UNK, _T("Admitting Time") }, -{ 0x0038,0x0030,DICOM_T_UNK, _T("Discharge Date") }, -{ 0x0038,0x0032,DICOM_T_UNK, _T("Discharge Time") }, -{ 0x0038,0x0040,DICOM_T_UNK, _T("Discharge Diagnosis Description") }, -{ 0x0038,0x0044,DICOM_T_UNK, _T("Discharge Diagnosis Code Sequence") }, -{ 0x0038,0x0050,DICOM_T_UNK, _T("Special Needs") }, -{ 0x0038,0x0060,DICOM_T_UNK, _T("Service Episode ID") }, -{ 0x0038,0x0061,DICOM_T_UNK, _T("Issuer of Service Episode ID") }, -{ 0x0038,0x0062,DICOM_T_UNK, _T("Service Episode Description") }, -{ 0x0038,0x0064,DICOM_T_UNK, _T("Issuer of Service Episode ID Sequence") }, -{ 0x0038,0x0100,DICOM_T_UNK, _T("Pertinent Documents Sequence") }, -{ 0x0038,0x0300,DICOM_T_UNK, _T("Current Patient Location") }, -{ 0x0038,0x0400,DICOM_T_UNK, _T("Patient's Institution Residence") }, -{ 0x0038,0x0500,DICOM_T_UNK, _T("Patient State") }, -{ 0x0038,0x0502,DICOM_T_UNK, _T("Patient Clinical Trial Participation Sequence") }, -{ 0x0038,0x4000,DICOM_T_UNK, _T("Visit Comments") }, -{ 0x003A,0x0004,DICOM_T_UNK, _T("Waveform Originality") }, -{ 0x003A,0x0005,DICOM_T_UNK, _T("Number of Waveform Channels") }, -{ 0x003A,0x0010,DICOM_T_UNK, _T("Number of Waveform Samples") }, -{ 0x003A,0x001A,DICOM_T_UNK, _T("Sampling Frequency") }, -{ 0x003A,0x0020,DICOM_T_UNK, _T("Multiplex Group Label") }, -{ 0x003A,0x0200,DICOM_T_UNK, _T("Channel Definition Sequence") }, -{ 0x003A,0x0202,DICOM_T_UNK, _T("Waveform Channel Number") }, -{ 0x003A,0x0203,DICOM_T_UNK, _T("Channel Label") }, -{ 0x003A,0x0205,DICOM_T_UNK, _T("Channel Status") }, -{ 0x003A,0x0208,DICOM_T_UNK, _T("Channel Source Sequence") }, -{ 0x003A,0x0209,DICOM_T_UNK, _T("Channel Source Modifiers Sequence") }, -{ 0x003A,0x020A,DICOM_T_UNK, _T("Source Waveform Sequence") }, -{ 0x003A,0x020C,DICOM_T_UNK, _T("Channel Derivation Description") }, -{ 0x003A,0x0210,DICOM_T_UNK, _T("Channel Sensitivity") }, -{ 0x003A,0x0211,DICOM_T_UNK, _T("Channel Sensitivity Units Sequence") }, -{ 0x003A,0x0212,DICOM_T_UNK, _T("Channel Sensitivity Correction Factor") }, -{ 0x003A,0x0213,DICOM_T_UNK, _T("Channel Baseline") }, -{ 0x003A,0x0214,DICOM_T_UNK, _T("Channel Time Skew") }, -{ 0x003A,0x0215,DICOM_T_UNK, _T("Channel Sample Skew") }, -{ 0x003A,0x0218,DICOM_T_UNK, _T("Channel Offset") }, -{ 0x003A,0x021A,DICOM_T_UNK, _T("Waveform Bits Stored") }, -{ 0x003A,0x0220,DICOM_T_UNK, _T("Filter Low Frequency") }, -{ 0x003A,0x0221,DICOM_T_UNK, _T("Filter High Frequency") }, -{ 0x003A,0x0222,DICOM_T_UNK, _T("Notch Filter Frequency") }, -{ 0x003A,0x0223,DICOM_T_UNK, _T("Notch Filter Bandwidth") }, -{ 0x003A,0x0230,DICOM_T_UNK, _T("Waveform Data Display Scale") }, -{ 0x003A,0x0231,DICOM_T_UNK, _T("Waveform Display Background CIELab Value") }, -{ 0x003A,0x0240,DICOM_T_UNK, _T("Waveform Presentation Group Sequence") }, -{ 0x003A,0x0241,DICOM_T_UNK, _T("Presentation Group Number") }, -{ 0x003A,0x0242,DICOM_T_UNK, _T("Channel Display Sequence") }, -{ 0x003A,0x0244,DICOM_T_UNK, _T("Channel Recommended Display CIELab Value") }, -{ 0x003A,0x0245,DICOM_T_UNK, _T("Channel Position") }, -{ 0x003A,0x0246,DICOM_T_UNK, _T("Display Shading Flag") }, -{ 0x003A,0x0247,DICOM_T_UNK, _T("Fractional Channel Display Scale") }, -{ 0x003A,0x0248,DICOM_T_UNK, _T("Absolute Channel Display Scale") }, -{ 0x003A,0x0300,DICOM_T_UNK, _T("Multiplexed Audio Channels Description Code Sequence") }, -{ 0x003A,0x0301,DICOM_T_UNK, _T("Channel Identification Code") }, -{ 0x003A,0x0302,DICOM_T_UNK, _T("Channel Mode") }, -{ 0x0040,0x0001,DICOM_T_UNK, _T("Scheduled Station AE Title") }, -{ 0x0040,0x0002,DICOM_T_UNK, _T("Scheduled Procedure Step Start Date") }, -{ 0x0040,0x0003,DICOM_T_UNK, _T("Scheduled Procedure Step Start Time") }, -{ 0x0040,0x0004,DICOM_T_UNK, _T("Scheduled Procedure Step End Date") }, -{ 0x0040,0x0005,DICOM_T_UNK, _T("Scheduled Procedure Step End Time") }, -{ 0x0040,0x0006,DICOM_T_UNK, _T("Scheduled Performing Physician's Name") }, -{ 0x0040,0x0007,DICOM_T_UNK, _T("Scheduled Procedure Step Description") }, -{ 0x0040,0x0008,DICOM_T_UNK, _T("Scheduled Protocol Code Sequence") }, -{ 0x0040,0x0009,DICOM_T_UNK, _T("Scheduled Procedure Step ID") }, -{ 0x0040,0x000A,DICOM_T_UNK, _T("Stage Code Sequence") }, -{ 0x0040,0x000B,DICOM_T_UNK, _T("Scheduled Performing Physician Identification Sequence") }, -{ 0x0040,0x0010,DICOM_T_UNK, _T("Scheduled Station Name") }, -{ 0x0040,0x0011,DICOM_T_UNK, _T("Scheduled Procedure Step Location") }, -{ 0x0040,0x0012,DICOM_T_UNK, _T("Pre-Medication") }, -{ 0x0040,0x0020,DICOM_T_UNK, _T("Scheduled Procedure Step Status") }, -{ 0x0040,0x0026,DICOM_T_UNK, _T("Order Placer Identifier Sequence") }, -{ 0x0040,0x0027,DICOM_T_UNK, _T("Order Filler Identifier Sequence") }, -{ 0x0040,0x0031,DICOM_T_UNK, _T("Local Namespace Entity ID") }, -{ 0x0040,0x0032,DICOM_T_UNK, _T("Universal Entity ID") }, -{ 0x0040,0x0033,DICOM_T_UNK, _T("Universal Entity ID Type") }, -{ 0x0040,0x0035,DICOM_T_UNK, _T("Identifier Type Code") }, -{ 0x0040,0x0036,DICOM_T_UNK, _T("Assigning Facility Sequence") }, -{ 0x0040,0x0039,DICOM_T_UNK, _T("Assigning Jurisdiction Code Sequence") }, -{ 0x0040,0x003A,DICOM_T_UNK, _T("Assigning Agency or Department Code Sequence") }, -{ 0x0040,0x0100,DICOM_T_UNK, _T("Scheduled Procedure Step Sequence") }, -{ 0x0040,0x0220,DICOM_T_UNK, _T("Referenced Non-Image Composite SOP Instance Sequence") }, -{ 0x0040,0x0241,DICOM_T_UNK, _T("Performed Station AE Title") }, -{ 0x0040,0x0242,DICOM_T_UNK, _T("Performed Station Name") }, -{ 0x0040,0x0243,DICOM_T_UNK, _T("Performed Location") }, -{ 0x0040,0x0244,DICOM_T_UNK, _T("Performed Procedure Step Start Date") }, -{ 0x0040,0x0245,DICOM_T_UNK, _T("Performed Procedure Step Start Time") }, -{ 0x0040,0x0250,DICOM_T_UNK, _T("Performed Procedure Step End Date") }, -{ 0x0040,0x0251,DICOM_T_UNK, _T("Performed Procedure Step End Time") }, -{ 0x0040,0x0252,DICOM_T_UNK, _T("Performed Procedure Step Status") }, -{ 0x0040,0x0253,DICOM_T_UNK, _T("Performed Procedure Step ID") }, -{ 0x0040,0x0254,DICOM_T_UNK, _T("Performed Procedure Step Description") }, -{ 0x0040,0x0255,DICOM_T_UNK, _T("Performed Procedure Type Description") }, -{ 0x0040,0x0260,DICOM_T_UNK, _T("Performed Protocol Code Sequence") }, -{ 0x0040,0x0261,DICOM_T_UNK, _T("Performed Protocol Type") }, -{ 0x0040,0x0270,DICOM_T_UNK, _T("Scheduled Step Attributes Sequence") }, -{ 0x0040,0x0275,DICOM_T_UNK, _T("Request Attributes Sequence") }, -{ 0x0040,0x0280,DICOM_T_UNK, _T("Comments on the Performed Procedure Step") }, -{ 0x0040,0x0281,DICOM_T_UNK, _T("Performed Procedure Step Discontinuation Reason Code Sequence") }, -{ 0x0040,0x0293,DICOM_T_UNK, _T("Quantity Sequence") }, -{ 0x0040,0x0294,DICOM_T_UNK, _T("Quantity") }, -{ 0x0040,0x0295,DICOM_T_UNK, _T("Measuring Units Sequence") }, -{ 0x0040,0x0296,DICOM_T_UNK, _T("Billing Item Sequence") }, -{ 0x0040,0x0300,DICOM_T_UNK, _T("Total Time of Fluoroscopy") }, -{ 0x0040,0x0301,DICOM_T_UNK, _T("Total Number of Exposures") }, -{ 0x0040,0x0302,DICOM_T_UNK, _T("Entrance Dose") }, -{ 0x0040,0x0303,DICOM_T_UNK, _T("Exposed Area") }, -{ 0x0040,0x0306,DICOM_T_UNK, _T("Distance Source to Entrance") }, -{ 0x0040,0x0307,DICOM_T_UNK, _T("Distance Source to Support") }, -{ 0x0040,0x030E,DICOM_T_UNK, _T("Exposure Dose Sequence") }, -{ 0x0040,0x0310,DICOM_T_UNK, _T("Comments on Radiation Dose") }, -{ 0x0040,0x0312,DICOM_T_UNK, _T("X-Ray Output") }, -{ 0x0040,0x0314,DICOM_T_UNK, _T("Half Value Layer") }, -{ 0x0040,0x0316,DICOM_T_UNK, _T("Organ Dose") }, -{ 0x0040,0x0318,DICOM_T_UNK, _T("Organ Exposed") }, -{ 0x0040,0x0320,DICOM_T_UNK, _T("Billing Procedure Step Sequence") }, -{ 0x0040,0x0321,DICOM_T_UNK, _T("Film Consumption Sequence") }, -{ 0x0040,0x0324,DICOM_T_UNK, _T("Billing Supplies and Devices Sequence") }, -{ 0x0040,0x0330,DICOM_T_UNK, _T("Referenced Procedure Step Sequence") }, -{ 0x0040,0x0340,DICOM_T_UNK, _T("Performed Series Sequence") }, -{ 0x0040,0x0400,DICOM_T_UNK, _T("Comments on the Scheduled Procedure Step") }, -{ 0x0040,0x0440,DICOM_T_UNK, _T("Protocol Context Sequence") }, -{ 0x0040,0x0441,DICOM_T_UNK, _T("Content Item Modifier Sequence") }, -{ 0x0040,0x0500,DICOM_T_UNK, _T("Scheduled Specimen Sequence") }, -{ 0x0040,0x050A,DICOM_T_UNK, _T("Specimen Accession Number") }, -{ 0x0040,0x0512,DICOM_T_UNK, _T("Container Identifier") }, -{ 0x0040,0x0513,DICOM_T_UNK, _T("Issuer of the Container Identifier Sequence") }, -{ 0x0040,0x0515,DICOM_T_UNK, _T("Alternate Container Identifier Sequence") }, -{ 0x0040,0x0518,DICOM_T_UNK, _T("Container Type Code Sequence") }, -{ 0x0040,0x051A,DICOM_T_UNK, _T("Container Description") }, -{ 0x0040,0x0520,DICOM_T_UNK, _T("Container Component Sequence") }, -{ 0x0040,0x0550,DICOM_T_UNK, _T("Specimen Sequence") }, -{ 0x0040,0x0551,DICOM_T_UNK, _T("Specimen Identifier") }, -{ 0x0040,0x0552,DICOM_T_UNK, _T("Specimen Description Sequence (Trial)") }, -{ 0x0040,0x0553,DICOM_T_UNK, _T("Specimen Description (Trial)") }, -{ 0x0040,0x0554,DICOM_T_UNK, _T("Specimen UID") }, -{ 0x0040,0x0555,DICOM_T_UNK, _T("Acquisition Context Sequence") }, -{ 0x0040,0x0556,DICOM_T_UNK, _T("Acquisition Context Description") }, -{ 0x0040,0x059A,DICOM_T_UNK, _T("Specimen Type Code Sequence") }, -{ 0x0040,0x0560,DICOM_T_UNK, _T("Specimen Description Sequence") }, -{ 0x0040,0x0562,DICOM_T_UNK, _T("Issuer of the Specimen Identifier Sequence") }, -{ 0x0040,0x0600,DICOM_T_UNK, _T("Specimen Short Description") }, -{ 0x0040,0x0602,DICOM_T_UNK, _T("Specimen Detailed Description") }, -{ 0x0040,0x0610,DICOM_T_UNK, _T("Specimen Preparation Sequence") }, -{ 0x0040,0x0612,DICOM_T_UNK, _T("Specimen Preparation Step Content Item Sequence") }, -{ 0x0040,0x0620,DICOM_T_UNK, _T("Specimen Localization Content Item Sequence") }, -{ 0x0040,0x06FA,DICOM_T_UNK, _T("Slide Identifier") }, -{ 0x0040,0x071A,DICOM_T_UNK, _T("Image Center Point Coordinates Sequence") }, -{ 0x0040,0x072A,DICOM_T_UNK, _T("X Offset in Slide Coordinate System") }, -{ 0x0040,0x073A,DICOM_T_UNK, _T("Y Offset in Slide Coordinate System") }, -{ 0x0040,0x074A,DICOM_T_UNK, _T("Z Offset in Slide Coordinate System") }, -{ 0x0040,0x08D8,DICOM_T_UNK, _T("Pixel Spacing Sequence") }, -{ 0x0040,0x08DA,DICOM_T_UNK, _T("Coordinate System Axis Code Sequence") }, -{ 0x0040,0x08EA,DICOM_T_UNK, _T("Measurement Units Code Sequence") }, -{ 0x0040,0x09F8,DICOM_T_UNK, _T("Vital Stain Code Sequence (Trial)") }, -{ 0x0040,0x1001,DICOM_T_UNK, _T("Requested Procedure ID") }, -{ 0x0040,0x1002,DICOM_T_UNK, _T("Reason for the Requested Procedure") }, -{ 0x0040,0x1003,DICOM_T_UNK, _T("Requested Procedure Priority") }, -{ 0x0040,0x1004,DICOM_T_UNK, _T("Patient Transport Arrangements") }, -{ 0x0040,0x1005,DICOM_T_UNK, _T("Requested Procedure Location") }, -{ 0x0040,0x1006,DICOM_T_UNK, _T("Placer Order Number / Procedure") }, -{ 0x0040,0x1007,DICOM_T_UNK, _T("Filler Order Number / Procedure") }, -{ 0x0040,0x1008,DICOM_T_UNK, _T("Confidentiality Code") }, -{ 0x0040,0x1009,DICOM_T_UNK, _T("Reporting Priority") }, -{ 0x0040,0x100A,DICOM_T_UNK, _T("Reason for Requested Procedure Code Sequence") }, -{ 0x0040,0x1010,DICOM_T_UNK, _T("Names of Intended Recipients of Results") }, -{ 0x0040,0x1011,DICOM_T_UNK, _T("Intended Recipients of Results Identification Sequence") }, -{ 0x0040,0x1012,DICOM_T_UNK, _T("Reason For Performed Procedure Code Sequence") }, -{ 0x0040,0x1060,DICOM_T_UNK, _T("Requested Procedure Description (Trial)") }, -{ 0x0040,0x1101,DICOM_T_UNK, _T("Person Identification Code Sequence") }, -{ 0x0040,0x1102,DICOM_T_UNK, _T("Person's Address") }, -{ 0x0040,0x1103,DICOM_T_UNK, _T("Person's Telephone Numbers") }, -{ 0x0040,0x1400,DICOM_T_UNK, _T("Requested Procedure Comments") }, -{ 0x0040,0x2001,DICOM_T_UNK, _T("Reason for the Imaging Service Request") }, -{ 0x0040,0x2004,DICOM_T_UNK, _T("Issue Date of Imaging Service Request") }, -{ 0x0040,0x2005,DICOM_T_UNK, _T("Issue Time of Imaging Service Request") }, -{ 0x0040,0x2006,DICOM_T_UNK, _T("Placer Order Number / Imaging Service Request (Retired)") }, -{ 0x0040,0x2007,DICOM_T_UNK, _T("Filler Order Number / Imaging Service Request (Retired)") }, -{ 0x0040,0x2008,DICOM_T_UNK, _T("Order Entered By") }, -{ 0x0040,0x2009,DICOM_T_UNK, _T("Order Enterer's Location") }, -{ 0x0040,0x2010,DICOM_T_UNK, _T("Order Callback Phone Number") }, -{ 0x0040,0x2016,DICOM_T_UNK, _T("Placer Order Number / Imaging Service Request") }, -{ 0x0040,0x2017,DICOM_T_UNK, _T("Filler Order Number / Imaging Service Request") }, -{ 0x0040,0x2400,DICOM_T_UNK, _T("Imaging Service Request Comments") }, -{ 0x0040,0x3001,DICOM_T_UNK, _T("Confidentiality Constraint on Patient Data Description") }, -{ 0x0040,0x4001,DICOM_T_UNK, _T("General Purpose Scheduled Procedure Step Status") }, -{ 0x0040,0x4002,DICOM_T_UNK, _T("General Purpose Performed Procedure Step Status") }, -{ 0x0040,0x4003,DICOM_T_UNK, _T("General Purpose Scheduled Procedure Step Priority") }, -{ 0x0040,0x4004,DICOM_T_UNK, _T("Scheduled Processing Applications Code Sequence") }, -{ 0x0040,0x4005,DICOM_T_UNK, _T("Scheduled Procedure Step Start DateTime") }, -{ 0x0040,0x4006,DICOM_T_UNK, _T("Multiple Copies Flag") }, -{ 0x0040,0x4007,DICOM_T_UNK, _T("Performed Processing Applications Code Sequence") }, -{ 0x0040,0x4009,DICOM_T_UNK, _T("Human Performer Code Sequence") }, -{ 0x0040,0x4010,DICOM_T_UNK, _T("Scheduled Procedure Step Modification DateTime") }, -{ 0x0040,0x4011,DICOM_T_UNK, _T("Expected Completion DateTime") }, -{ 0x0040,0x4015,DICOM_T_UNK, _T("Resulting General Purpose Performed Procedure Steps Sequence") }, -{ 0x0040,0x4016,DICOM_T_UNK, _T("Referenced General Purpose Scheduled Procedure Step Sequence") }, -{ 0x0040,0x4018,DICOM_T_UNK, _T("Scheduled Workitem Code Sequence") }, -{ 0x0040,0x4019,DICOM_T_UNK, _T("Performed Workitem Code Sequence") }, -{ 0x0040,0x4020,DICOM_T_UNK, _T("Input Availability Flag") }, -{ 0x0040,0x4021,DICOM_T_UNK, _T("Input Information Sequence") }, -{ 0x0040,0x4022,DICOM_T_UNK, _T("Relevant Information Sequence") }, -{ 0x0040,0x4023,DICOM_T_UNK, _T("Referenced General Purpose Scheduled Procedure Step Transaction UID") }, -{ 0x0040,0x4025,DICOM_T_UNK, _T("Scheduled Station Name Code Sequence") }, -{ 0x0040,0x4026,DICOM_T_UNK, _T("Scheduled Station Class Code Sequence") }, -{ 0x0040,0x4027,DICOM_T_UNK, _T("Scheduled Station Geographic Location Code Sequence") }, -{ 0x0040,0x4028,DICOM_T_UNK, _T("Performed Station Name Code Sequence") }, -{ 0x0040,0x4029,DICOM_T_UNK, _T("Performed Station Class Code Sequence") }, -{ 0x0040,0x4030,DICOM_T_UNK, _T("Performed Station Geographic Location Code Sequence") }, -{ 0x0040,0x4031,DICOM_T_UNK, _T("Requested Subsequent Workitem Code Sequence") }, -{ 0x0040,0x4032,DICOM_T_UNK, _T("Non-DICOM Output Code Sequence") }, -{ 0x0040,0x4033,DICOM_T_UNK, _T("Output Information Sequence") }, -{ 0x0040,0x4034,DICOM_T_UNK, _T("Scheduled Human Performers Sequence") }, -{ 0x0040,0x4035,DICOM_T_UNK, _T("Actual Human Performers Sequence") }, -{ 0x0040,0x4036,DICOM_T_UNK, _T("Human Performer's Organization") }, -{ 0x0040,0x4037,DICOM_T_UNK, _T("Human Performer's Name") }, -{ 0x0040,0x4040,DICOM_T_UNK, _T("Raw Data Handling") }, -{ 0x0040,0x4041,DICOM_T_UNK, _T("Input Readiness State") }, -{ 0x0040,0x4050,DICOM_T_UNK, _T("Performed Procedure Step Start DateTime") }, -{ 0x0040,0x4051,DICOM_T_UNK, _T("Performed Procedure Step End DateTime") }, -{ 0x0040,0x4052,DICOM_T_UNK, _T("Procedure Step Cancellation DateTime") }, -{ 0x0040,0x8302,DICOM_T_UNK, _T("Entrance Dose in mGy") }, -{ 0x0040,0x9094,DICOM_T_UNK, _T("Referenced Image Real World Value Mapping Sequence") }, -{ 0x0040,0x9096,DICOM_T_UNK, _T("Real World Value Mapping Sequence") }, -{ 0x0040,0x9098,DICOM_T_UNK, _T("Pixel Value Mapping Code Sequence") }, -{ 0x0040,0x9210,DICOM_T_UNK, _T("LUT Label") }, -{ 0x0040,0x9211,DICOM_T_UNK, _T("Real World Value Last Value Mapped") }, -{ 0x0040,0x9212,DICOM_T_UNK, _T("Real World Value LUT Data") }, -{ 0x0040,0x9216,DICOM_T_UNK, _T("Real World Value First Value Mapped") }, -{ 0x0040,0x9224,DICOM_T_UNK, _T("Real World Value Intercept") }, -{ 0x0040,0x9225,DICOM_T_UNK, _T("Real World Value Slope") }, -{ 0x0040,0xA007,DICOM_T_UNK, _T("Findings Flag (Trial)") }, -{ 0x0040,0xA010,DICOM_T_UNK, _T("Relationship Type") }, -{ 0x0040,0xA020,DICOM_T_UNK, _T("Findings Sequence (Trial)") }, -{ 0x0040,0xA021,DICOM_T_UNK, _T("Findings Group UID (Trial)") }, -{ 0x0040,0xA022,DICOM_T_UNK, _T("Referenced Findings Group UID (Trial)") }, -{ 0x0040,0xA023,DICOM_T_UNK, _T("Findings Group Recording Date (Trial)") }, -{ 0x0040,0xA024,DICOM_T_UNK, _T("Findings Group Recording Time (Trial)") }, -{ 0x0040,0xA026,DICOM_T_UNK, _T("Findings Source Category Code Sequence (Trial)") }, -{ 0x0040,0xA027,DICOM_T_UNK, _T("Verifying Organization") }, -{ 0x0040,0xA028,DICOM_T_UNK, _T("Documenting Organization Identifier Code Sequence (Trial)") }, -{ 0x0040,0xA030,DICOM_T_UNK, _T("Verification DateTime") }, -{ 0x0040,0xA032,DICOM_T_UNK, _T("Observation DateTime") }, -{ 0x0040,0xA040,DICOM_T_UNK, _T("Value Type") }, -{ 0x0040,0xA043,DICOM_T_UNK, _T("Concept Name Code Sequence") }, -{ 0x0040,0xA047,DICOM_T_UNK, _T("Measurement Precision Description (Trial)") }, -{ 0x0040,0xA050,DICOM_T_UNK, _T("Continuity Of Content") }, -{ 0x0040,0xA057,DICOM_T_UNK, _T("Urgency or Priority Alerts (Trial)") }, -{ 0x0040,0xA060,DICOM_T_UNK, _T("Sequencing Indicator (Trial)") }, -{ 0x0040,0xA066,DICOM_T_UNK, _T("Document Identifier Code Sequence (Trial)") }, -{ 0x0040,0xA067,DICOM_T_UNK, _T("Document Author (Trial)") }, -{ 0x0040,0xA068,DICOM_T_UNK, _T("Document Author Identifier Code Sequence (Trial)") }, -{ 0x0040,0xA070,DICOM_T_UNK, _T("Identifier Code Sequence (Trial)") }, -{ 0x0040,0xA073,DICOM_T_UNK, _T("Verifying Observer Sequence") }, -{ 0x0040,0xA074,DICOM_T_UNK, _T("Object Binary Identifier (Trial)") }, -{ 0x0040,0xA075,DICOM_T_UNK, _T("Verifying Observer Name") }, -{ 0x0040,0xA076,DICOM_T_UNK, _T("Documenting Observer Identifier Code Sequence (Trial)") }, -{ 0x0040,0xA078,DICOM_T_UNK, _T("Author Observer Sequence") }, -{ 0x0040,0xA07A,DICOM_T_UNK, _T("Participant Sequence") }, -{ 0x0040,0xA07C,DICOM_T_UNK, _T("Custodial Organization Sequence") }, -{ 0x0040,0xA080,DICOM_T_UNK, _T("Participation Type") }, -{ 0x0040,0xA082,DICOM_T_UNK, _T("Participation DateTime") }, -{ 0x0040,0xA084,DICOM_T_UNK, _T("Observer Type") }, -{ 0x0040,0xA085,DICOM_T_UNK, _T("Procedure Identifier Code Sequence (Trial)") }, -{ 0x0040,0xA088,DICOM_T_UNK, _T("Verifying Observer Identification Code Sequence") }, -{ 0x0040,0xA089,DICOM_T_UNK, _T("Object Directory Binary Identifier (Trial)") }, -{ 0x0040,0xA090,DICOM_T_UNK, _T("Equivalent CDA Document Sequence") }, -{ 0x0040,0xA0B0,DICOM_T_UNK, _T("Referenced Waveform Channels") }, -{ 0x0040,0xA110,DICOM_T_UNK, _T("Date of Document or Verbal Transaction (Trial)") }, -{ 0x0040,0xA112,DICOM_T_UNK, _T("Time of Document Creation or Verbal Transaction (Trial)") }, -{ 0x0040,0xA120,DICOM_T_UNK, _T("DateTime") }, -{ 0x0040,0xA121,DICOM_T_UNK, _T("Date") }, -{ 0x0040,0xA122,DICOM_T_UNK, _T("Time") }, -{ 0x0040,0xA123,DICOM_T_UNK, _T("Person Name") }, -{ 0x0040,0xA124,DICOM_T_UNK, _T("UID") }, -{ 0x0040,0xA125,DICOM_T_UNK, _T("Report Status ID (Trial)") }, -{ 0x0040,0xA130,DICOM_T_UNK, _T("Temporal Range Type") }, -{ 0x0040,0xA132,DICOM_T_UNK, _T("Referenced Sample Positions") }, -{ 0x0040,0xA136,DICOM_T_UNK, _T("Referenced Frame Numbers") }, -{ 0x0040,0xA138,DICOM_T_UNK, _T("Referenced Time Offsets") }, -{ 0x0040,0xA13A,DICOM_T_UNK, _T("Referenced DateTime") }, -{ 0x0040,0xA160,DICOM_T_UNK, _T("Text Value") }, -{ 0x0040,0xA161,DICOM_T_UNK, _T("Floating Point Value") }, -{ 0x0040,0xA162,DICOM_T_UNK, _T("Rational Numerator Value") }, -{ 0x0040,0xA163,DICOM_T_UNK, _T("Rational Denominator Value") }, -{ 0x0040,0xA167,DICOM_T_UNK, _T("Observation Category Code Sequence (Trial)") }, -{ 0x0040,0xA168,DICOM_T_UNK, _T("Concept Code Sequence") }, -{ 0x0040,0xA16A,DICOM_T_UNK, _T("Bibliographic Citation (Trial)") }, -{ 0x0040,0xA170,DICOM_T_UNK, _T("Purpose of Reference Code Sequence") }, -{ 0x0040,0xA171,DICOM_T_UNK, _T("Observation UID") }, -{ 0x0040,0xA172,DICOM_T_UNK, _T("Referenced Observation UID (Trial)") }, -{ 0x0040,0xA173,DICOM_T_UNK, _T("Referenced Observation Class (Trial)") }, -{ 0x0040,0xA174,DICOM_T_UNK, _T("Referenced Object Observation Class (Trial)") }, -{ 0x0040,0xA180,DICOM_T_UNK, _T("Annotation Group Number") }, -{ 0x0040,0xA192,DICOM_T_UNK, _T("Observation Date (Trial)") }, -{ 0x0040,0xA193,DICOM_T_UNK, _T("Observation Time (Trial)") }, -{ 0x0040,0xA194,DICOM_T_UNK, _T("Measurement Automation (Trial)") }, -{ 0x0040,0xA195,DICOM_T_UNK, _T("Modifier Code Sequence") }, -{ 0x0040,0xA224,DICOM_T_UNK, _T("Identification Description (Trial)") }, -{ 0x0040,0xA290,DICOM_T_UNK, _T("Coordinates Set Geometric Type (Trial)") }, -{ 0x0040,0xA296,DICOM_T_UNK, _T("Algorithm Code Sequence (Trial)") }, -{ 0x0040,0xA297,DICOM_T_UNK, _T("Algorithm Description (Trial)") }, -{ 0x0040,0xA29A,DICOM_T_UNK, _T("Pixel Coordinates Set (Trial)") }, -{ 0x0040,0xA300,DICOM_T_UNK, _T("Measured Value Sequence") }, -{ 0x0040,0xA301,DICOM_T_UNK, _T("Numeric Value Qualifier Code Sequence") }, -{ 0x0040,0xA307,DICOM_T_UNK, _T("Current Observer (Trial)") }, -{ 0x0040,0xA30A,DICOM_T_UNK, _T("Numeric Value") }, -{ 0x0040,0xA313,DICOM_T_UNK, _T("Referenced Accession Sequence (Trial)") }, -{ 0x0040,0xA33A,DICOM_T_UNK, _T("Report Status Comment (Trial)") }, -{ 0x0040,0xA340,DICOM_T_UNK, _T("Procedure Context Sequence (Trial)") }, -{ 0x0040,0xA352,DICOM_T_UNK, _T("Verbal Source (Trial)") }, -{ 0x0040,0xA353,DICOM_T_UNK, _T("Address (Trial)") }, -{ 0x0040,0xA354,DICOM_T_UNK, _T("Telephone Number (Trial)") }, -{ 0x0040,0xA358,DICOM_T_UNK, _T("Verbal Source Identifier Code Sequence (Trial)") }, -{ 0x0040,0xA360,DICOM_T_UNK, _T("Predecessor Documents Sequence") }, -{ 0x0040,0xA370,DICOM_T_UNK, _T("Referenced Request Sequence") }, -{ 0x0040,0xA372,DICOM_T_UNK, _T("Performed Procedure Code Sequence") }, -{ 0x0040,0xA375,DICOM_T_UNK, _T("Current Requested Procedure Evidence Sequence") }, -{ 0x0040,0xA380,DICOM_T_UNK, _T("Report Detail Sequence (Trial)") }, -{ 0x0040,0xA385,DICOM_T_UNK, _T("Pertinent Other Evidence Sequence") }, -{ 0x0040,0xA390,DICOM_T_UNK, _T("HL7 Structured Document Reference Sequence") }, -{ 0x0040,0xA402,DICOM_T_UNK, _T("Observation Subject UID (Trial)") }, -{ 0x0040,0xA403,DICOM_T_UNK, _T("Observation Subject Class (Trial)") }, -{ 0x0040,0xA404,DICOM_T_UNK, _T("Observation Subject Type Code Sequence (Trial)") }, -{ 0x0040,0xA491,DICOM_T_UNK, _T("Completion Flag") }, -{ 0x0040,0xA492,DICOM_T_UNK, _T("Completion Flag Description") }, -{ 0x0040,0xA493,DICOM_T_UNK, _T("Verification Flag") }, -{ 0x0040,0xA494,DICOM_T_UNK, _T("Archive Requested") }, -{ 0x0040,0xA496,DICOM_T_UNK, _T("Preliminary Flag") }, -{ 0x0040,0xA504,DICOM_T_UNK, _T("Content Template Sequence") }, -{ 0x0040,0xA525,DICOM_T_UNK, _T("Identical Documents Sequence") }, -{ 0x0040,0xA600,DICOM_T_UNK, _T("Observation Subject Context Flag (Trial)") }, -{ 0x0040,0xA601,DICOM_T_UNK, _T("Observer Context Flag (Trial)") }, -{ 0x0040,0xA603,DICOM_T_UNK, _T("Procedure Context Flag (Trial)") }, -{ 0x0040,0xA730,DICOM_T_UNK, _T("Content Sequence") }, -{ 0x0040,0xA731,DICOM_T_UNK, _T("Relationship Sequence (Trial)") }, -{ 0x0040,0xA732,DICOM_T_UNK, _T("Relationship Type Code Sequence (Trial)") }, -{ 0x0040,0xA744,DICOM_T_UNK, _T("Language Code Sequence (Trial)") }, -{ 0x0040,0xA992,DICOM_T_UNK, _T("Uniform Resource Locator (Trial)") }, -{ 0x0040,0xB020,DICOM_T_UNK, _T("Waveform Annotation Sequence") }, -{ 0x0040,0xDB00,DICOM_T_UNK, _T("Template Identifier") }, -{ 0x0040,0xDB06,DICOM_T_UNK, _T("Template Version") }, -{ 0x0040,0xDB07,DICOM_T_UNK, _T("Template Local Version") }, -{ 0x0040,0xDB0B,DICOM_T_UNK, _T("Template Extension Flag") }, -{ 0x0040,0xDB0C,DICOM_T_UNK, _T("Template Extension Organization UID") }, -{ 0x0040,0xDB0D,DICOM_T_UNK, _T("Template Extension Creator UID") }, -{ 0x0040,0xDB73,DICOM_T_UNK, _T("Referenced Content Item Identifier") }, -{ 0x0040,0xE001,DICOM_T_UNK, _T("HL7 Instance Identifier") }, -{ 0x0040,0xE004,DICOM_T_UNK, _T("HL7 Document Effective Time") }, -{ 0x0040,0xE006,DICOM_T_UNK, _T("HL7 Document Type Code Sequence") }, -{ 0x0040,0xE008,DICOM_T_UNK, _T("Document Class Code Sequence") }, -{ 0x0040,0xE010,DICOM_T_UNK, _T("Retrieve URI") }, -{ 0x0040,0xE011,DICOM_T_UNK, _T("Retrieve Location UID") }, -{ 0x0040,0xE020,DICOM_T_UNK, _T("Type of Instances") }, -{ 0x0040,0xE021,DICOM_T_UNK, _T("DICOM Retrieval Sequence") }, -{ 0x0040,0xE022,DICOM_T_UNK, _T("DICOM Media Retrieval Sequence") }, -{ 0x0040,0xE023,DICOM_T_UNK, _T("WADO Retrieval Sequence") }, -{ 0x0040,0xE024,DICOM_T_UNK, _T("XDS Retrieval Sequence") }, -{ 0x0040,0xE030,DICOM_T_UNK, _T("Repository Unique ID") }, -{ 0x0040,0xE031,DICOM_T_UNK, _T("Home Community ID") }, -{ 0x0042,0x0010,DICOM_T_UNK, _T("Document Title") }, -{ 0x0042,0x0011,DICOM_T_UNK, _T("Encapsulated Document") }, -{ 0x0042,0x0012,DICOM_T_UNK, _T("MIME Type of Encapsulated Document") }, -{ 0x0042,0x0013,DICOM_T_UNK, _T("Source Instance Sequence") }, -{ 0x0042,0x0014,DICOM_T_UNK, _T("List of MIME Types") }, -{ 0x0044,0x0001,DICOM_T_UNK, _T("Product Package Identifier") }, -{ 0x0044,0x0002,DICOM_T_UNK, _T("Substance Administration Approval") }, -{ 0x0044,0x0003,DICOM_T_UNK, _T("Approval Status Further Description") }, -{ 0x0044,0x0004,DICOM_T_UNK, _T("Approval Status DateTime") }, -{ 0x0044,0x0007,DICOM_T_UNK, _T("Product Type Code Sequence") }, -{ 0x0044,0x0008,DICOM_T_UNK, _T("Product Name") }, -{ 0x0044,0x0009,DICOM_T_UNK, _T("Product Description") }, -{ 0x0044,0x000A,DICOM_T_UNK, _T("Product Lot Identifier") }, -{ 0x0044,0x000B,DICOM_T_UNK, _T("Product Expiration DateTime") }, -{ 0x0044,0x0010,DICOM_T_UNK, _T("Substance Administration DateTime") }, -{ 0x0044,0x0011,DICOM_T_UNK, _T("Substance Administration Notes") }, -{ 0x0044,0x0012,DICOM_T_UNK, _T("Substance Administration Device ID") }, -{ 0x0044,0x0013,DICOM_T_UNK, _T("Product Parameter Sequence") }, -{ 0x0044,0x0019,DICOM_T_UNK, _T("Substance Administration Parameter Sequence") }, -{ 0x0046,0x0012,DICOM_T_UNK, _T("Lens Description") }, -{ 0x0046,0x0014,DICOM_T_UNK, _T("Right Lens Sequence") }, -{ 0x0046,0x0015,DICOM_T_UNK, _T("Left Lens Sequence") }, -{ 0x0046,0x0016,DICOM_T_UNK, _T("Unspecified Laterality Lens Sequence") }, -{ 0x0046,0x0018,DICOM_T_UNK, _T("Cylinder Sequence") }, -{ 0x0046,0x0028,DICOM_T_UNK, _T("Prism Sequence") }, -{ 0x0046,0x0030,DICOM_T_UNK, _T("Horizontal Prism Power") }, -{ 0x0046,0x0032,DICOM_T_UNK, _T("Horizontal Prism Base") }, -{ 0x0046,0x0034,DICOM_T_UNK, _T("Vertical Prism Power") }, -{ 0x0046,0x0036,DICOM_T_UNK, _T("Vertical Prism Base") }, -{ 0x0046,0x0038,DICOM_T_UNK, _T("Lens Segment Type") }, -{ 0x0046,0x0040,DICOM_T_UNK, _T("Optical Transmittance") }, -{ 0x0046,0x0042,DICOM_T_UNK, _T("Channel Width") }, -{ 0x0046,0x0044,DICOM_T_UNK, _T("Pupil Size") }, -{ 0x0046,0x0046,DICOM_T_UNK, _T("Corneal Size") }, -{ 0x0046,0x0050,DICOM_T_UNK, _T("Autorefraction Right Eye Sequence") }, -{ 0x0046,0x0052,DICOM_T_UNK, _T("Autorefraction Left Eye Sequence") }, -{ 0x0046,0x0060,DICOM_T_UNK, _T("Distance Pupillary Distance") }, -{ 0x0046,0x0062,DICOM_T_UNK, _T("Near Pupillary Distance") }, -{ 0x0046,0x0063,DICOM_T_UNK, _T("Intermediate Pupillary Distance") }, -{ 0x0046,0x0064,DICOM_T_UNK, _T("Other Pupillary Distance") }, -{ 0x0046,0x0070,DICOM_T_UNK, _T("Keratometry Right Eye Sequence") }, -{ 0x0046,0x0071,DICOM_T_UNK, _T("Keratometry Left Eye Sequence") }, -{ 0x0046,0x0074,DICOM_T_UNK, _T("Steep Keratometric Axis Sequence") }, -{ 0x0046,0x0075,DICOM_T_UNK, _T("Radius of Curvature") }, -{ 0x0046,0x0076,DICOM_T_UNK, _T("Keratometric Power") }, -{ 0x0046,0x0077,DICOM_T_UNK, _T("Keratometric Axis") }, -{ 0x0046,0x0080,DICOM_T_UNK, _T("Flat Keratometric Axis Sequence") }, -{ 0x0046,0x0092,DICOM_T_UNK, _T("Background Color") }, -{ 0x0046,0x0094,DICOM_T_UNK, _T("Optotype") }, -{ 0x0046,0x0095,DICOM_T_UNK, _T("Optotype Presentation") }, -{ 0x0046,0x0097,DICOM_T_UNK, _T("Subjective Refraction Right Eye Sequence") }, -{ 0x0046,0x0098,DICOM_T_UNK, _T("Subjective Refraction Left Eye Sequence") }, -{ 0x0046,0x0100,DICOM_T_UNK, _T("Add Near Sequence") }, -{ 0x0046,0x0101,DICOM_T_UNK, _T("Add Intermediate Sequence") }, -{ 0x0046,0x0102,DICOM_T_UNK, _T("Add Other Sequence") }, -{ 0x0046,0x0104,DICOM_T_UNK, _T("Add Power") }, -{ 0x0046,0x0106,DICOM_T_UNK, _T("Viewing Distance") }, -{ 0x0046,0x0121,DICOM_T_UNK, _T("Visual Acuity Type Code Sequence") }, -{ 0x0046,0x0122,DICOM_T_UNK, _T("Visual Acuity Right Eye Sequence") }, -{ 0x0046,0x0123,DICOM_T_UNK, _T("Visual Acuity Left Eye Sequence") }, -{ 0x0046,0x0124,DICOM_T_UNK, _T("Visual Acuity Both Eyes Open Sequence") }, -{ 0x0046,0x0125,DICOM_T_UNK, _T("Viewing Distance Type") }, -{ 0x0046,0x0135,DICOM_T_UNK, _T("Visual Acuity Modifiers") }, -{ 0x0046,0x0137,DICOM_T_UNK, _T("Decimal Visual Acuity") }, -{ 0x0046,0x0139,DICOM_T_UNK, _T("Optotype Detailed Definition") }, -{ 0x0046,0x0145,DICOM_T_UNK, _T("Referenced Refractive Measurements Sequence") }, -{ 0x0046,0x0146,DICOM_T_UNK, _T("Sphere Power") }, -{ 0x0046,0x0147,DICOM_T_UNK, _T("Cylinder Power") }, -{ 0x0046,0x0201,DICOM_T_UNK, _T("Corneal Topography Surface") }, -{ 0x0046,0x0202,DICOM_T_UNK, _T("Corneal Vertex Location") }, -{ 0x0046,0x0203,DICOM_T_UNK, _T("Pupil Centroid X-Coordinate") }, -{ 0x0046,0x0204,DICOM_T_UNK, _T("Pupil Centroid Y-Coordinate") }, -{ 0x0046,0x0205,DICOM_T_UNK, _T("Equivalent Pupil Radius") }, -{ 0x0046,0x0207,DICOM_T_UNK, _T("Corneal Topography Map Type Code Sequence") }, -{ 0x0046,0x0208,DICOM_T_UNK, _T("Vertices of the Outline of Pupil") }, -{ 0x0046,0x0210,DICOM_T_UNK, _T("Corneal Topography Mapping Normals Sequence") }, -{ 0x0046,0x0211,DICOM_T_UNK, _T("Maximum Corneal Curvature Sequence") }, -{ 0x0046,0x0212,DICOM_T_UNK, _T("Maximum Corneal Curvature") }, -{ 0x0046,0x0213,DICOM_T_UNK, _T("Maximum Corneal Curvature Location") }, -{ 0x0046,0x0215,DICOM_T_UNK, _T("Minimum Keratometric Sequence") }, -{ 0x0046,0x0218,DICOM_T_UNK, _T("Simulated Keratometric Cylinder Sequence") }, -{ 0x0046,0x0220,DICOM_T_UNK, _T("Average Corneal Power") }, -{ 0x0046,0x0224,DICOM_T_UNK, _T("Corneal I-S Value") }, -{ 0x0046,0x0227,DICOM_T_UNK, _T("Analyzed Area") }, -{ 0x0046,0x0230,DICOM_T_UNK, _T("Surface Regularity Index") }, -{ 0x0046,0x0232,DICOM_T_UNK, _T("Surface Asymmetry Index") }, -{ 0x0046,0x0234,DICOM_T_UNK, _T("Corneal Eccentricity Index") }, -{ 0x0046,0x0236,DICOM_T_UNK, _T("Keratoconus Prediction Index") }, -{ 0x0046,0x0238,DICOM_T_UNK, _T("Decimal Potential Visual Acuity") }, -{ 0x0046,0x0242,DICOM_T_UNK, _T("Corneal Topography Map Quality Evaluation") }, -{ 0x0046,0x0244,DICOM_T_UNK, _T("Source Image Corneal Processed Data Sequence") }, -{ 0x0046,0x0247,DICOM_T_UNK, _T("Corneal Point Location") }, -{ 0x0046,0x0248,DICOM_T_UNK, _T("Corneal Point Estimated") }, -{ 0x0046,0x0249,DICOM_T_UNK, _T("Axial Power") }, -{ 0x0046,0x0250,DICOM_T_UNK, _T("Tangential Power") }, -{ 0x0046,0x0251,DICOM_T_UNK, _T("Refractive Power") }, -{ 0x0046,0x0252,DICOM_T_UNK, _T("Relative Elevation") }, -{ 0x0046,0x0253,DICOM_T_UNK, _T("Corneal Wavefront") }, -{ 0x0048,0x0001,DICOM_T_UNK, _T("Imaged Volume Width") }, -{ 0x0048,0x0002,DICOM_T_UNK, _T("Imaged Volume Height") }, -{ 0x0048,0x0003,DICOM_T_UNK, _T("Imaged Volume Depth") }, -{ 0x0048,0x0006,DICOM_T_UNK, _T("Total Pixel Matrix Columns") }, -{ 0x0048,0x0007,DICOM_T_UNK, _T("Total Pixel Matrix Rows") }, -{ 0x0048,0x0008,DICOM_T_UNK, _T("Total Pixel Matrix Origin Sequence") }, -{ 0x0048,0x0010,DICOM_T_UNK, _T("Specimen Label in Image") }, -{ 0x0048,0x0011,DICOM_T_UNK, _T("Focus Method") }, -{ 0x0048,0x0012,DICOM_T_UNK, _T("Extended Depth of Field") }, -{ 0x0048,0x0013,DICOM_T_UNK, _T("Number of Focal Planes") }, -{ 0x0048,0x0014,DICOM_T_UNK, _T("Distance Between Focal Planes") }, -{ 0x0048,0x0015,DICOM_T_UNK, _T("Recommended Absent Pixel CIELab Value") }, -{ 0x0048,0x0100,DICOM_T_UNK, _T("Illuminator Type Code Sequence") }, -{ 0x0048,0x0102,DICOM_T_UNK, _T("Image Orientation (Slide)") }, -{ 0x0048,0x0105,DICOM_T_UNK, _T("Optical Path Sequence") }, -{ 0x0048,0x0106,DICOM_T_UNK, _T("Optical Path Identifier") }, -{ 0x0048,0x0107,DICOM_T_UNK, _T("Optical Path Description") }, -{ 0x0048,0x0108,DICOM_T_UNK, _T("Illumination Color Code Sequence") }, -{ 0x0048,0x0110,DICOM_T_UNK, _T("Specimen Reference Sequence") }, -{ 0x0048,0x0111,DICOM_T_UNK, _T("Condenser Lens Power") }, -{ 0x0048,0x0112,DICOM_T_UNK, _T("Objective Lens Power") }, -{ 0x0048,0x0113,DICOM_T_UNK, _T("Objective Lens Numerical Aperture") }, -{ 0x0048,0x0120,DICOM_T_UNK, _T("Palette Color Lookup Table Sequence") }, -{ 0x0048,0x0200,DICOM_T_UNK, _T("Referenced Image Navigation Sequence") }, -{ 0x0048,0x0201,DICOM_T_UNK, _T("Top Left Hand Corner of Localizer Area") }, -{ 0x0048,0x0202,DICOM_T_UNK, _T("Bottom Right Hand Corner of Localizer Area") }, -{ 0x0048,0x0207,DICOM_T_UNK, _T("Optical Path Identification Sequence") }, -{ 0x0048,0x021A,DICOM_T_UNK, _T("Plane Position (Slide) Sequence") }, -{ 0x0048,0x021E,DICOM_T_UNK, _T("Column Position In Total Image Pixel Matrix") }, -{ 0x0048,0x021F,DICOM_T_UNK, _T("Row Position In Total Image Pixel Matrix") }, -{ 0x0048,0x0301,DICOM_T_UNK, _T("Pixel Origin Interpretation") }, -{ 0x0050,0x0004,DICOM_T_UNK, _T("Calibration Image") }, -{ 0x0050,0x0010,DICOM_T_UNK, _T("Device Sequence") }, -{ 0x0050,0x0012,DICOM_T_UNK, _T("Container Component Type Code Sequence") }, -{ 0x0050,0x0013,DICOM_T_UNK, _T("Container Component Thickness") }, -{ 0x0050,0x0014,DICOM_T_UNK, _T("Device Length") }, -{ 0x0050,0x0015,DICOM_T_UNK, _T("Container Component Width") }, -{ 0x0050,0x0016,DICOM_T_UNK, _T("Device Diameter") }, -{ 0x0050,0x0017,DICOM_T_UNK, _T("Device Diameter Units") }, -{ 0x0050,0x0018,DICOM_T_UNK, _T("Device Volume") }, -{ 0x0050,0x0019,DICOM_T_UNK, _T("Inter-Marker Distance") }, -{ 0x0050,0x001A,DICOM_T_UNK, _T("Container Component Material") }, -{ 0x0050,0x001B,DICOM_T_UNK, _T("Container Component ID") }, -{ 0x0050,0x001C,DICOM_T_UNK, _T("Container Component Length") }, -{ 0x0050,0x001D,DICOM_T_UNK, _T("Container Component Diameter") }, -{ 0x0050,0x001E,DICOM_T_UNK, _T("Container Component Description") }, -{ 0x0050,0x0020,DICOM_T_UNK, _T("Device Description") }, -{ 0x0052,0x0001,DICOM_T_UNK, _T("Contrast/Bolus Ingredient Percent by Volume") }, -{ 0x0052,0x0002,DICOM_T_UNK, _T("OCT Focal Distance") }, -{ 0x0052,0x0003,DICOM_T_UNK, _T("Beam Spot Size") }, -{ 0x0052,0x0004,DICOM_T_UNK, _T("Effective Refractive Index") }, -{ 0x0052,0x0006,DICOM_T_UNK, _T("OCT Acquisition Domain") }, -{ 0x0052,0x0007,DICOM_T_UNK, _T("OCT Optical Center Wavelength") }, -{ 0x0052,0x0008,DICOM_T_UNK, _T("Axial Resolution") }, -{ 0x0052,0x0009,DICOM_T_UNK, _T("Ranging Depth") }, -{ 0x0052,0x0011,DICOM_T_UNK, _T("A-line Rate") }, -{ 0x0052,0x0012,DICOM_T_UNK, _T("A-lines Per Frame") }, -{ 0x0052,0x0013,DICOM_T_UNK, _T("Catheter Rotational Rate") }, -{ 0x0052,0x0014,DICOM_T_UNK, _T("A-line Pixel Spacing") }, -{ 0x0052,0x0016,DICOM_T_UNK, _T("Mode of Percutaneous Access Sequence") }, -{ 0x0052,0x0025,DICOM_T_UNK, _T("Intravascular OCT Frame Type Sequence") }, -{ 0x0052,0x0026,DICOM_T_UNK, _T("OCT Z Offset Applied") }, -{ 0x0052,0x0027,DICOM_T_UNK, _T("Intravascular Frame Content Sequence") }, -{ 0x0052,0x0028,DICOM_T_UNK, _T("Intravascular Longitudinal Distance") }, -{ 0x0052,0x0029,DICOM_T_UNK, _T("Intravascular OCT Frame Content Sequence") }, -{ 0x0052,0x0030,DICOM_T_UNK, _T("OCT Z Offset Correction") }, -{ 0x0052,0x0031,DICOM_T_UNK, _T("Catheter Direction of Rotation") }, -{ 0x0052,0x0033,DICOM_T_UNK, _T("Seam Line Location") }, -{ 0x0052,0x0034,DICOM_T_UNK, _T("First A-line Location") }, -{ 0x0052,0x0036,DICOM_T_UNK, _T("Seam Line Index") }, -{ 0x0052,0x0038,DICOM_T_UNK, _T("Number of Padded A-lines") }, -{ 0x0052,0x0039,DICOM_T_UNK, _T("Interpolation Type") }, -{ 0x0052,0x003A,DICOM_T_UNK, _T("Refractive Index Applied") }, -{ 0x0054,0x0010,DICOM_T_UNK, _T("Energy Window Vector") }, -{ 0x0054,0x0011,DICOM_T_UNK, _T("Number of Energy Windows") }, -{ 0x0054,0x0012,DICOM_T_UNK, _T("Energy Window Information Sequence") }, -{ 0x0054,0x0013,DICOM_T_UNK, _T("Energy Window Range Sequence") }, -{ 0x0054,0x0014,DICOM_T_UNK, _T("Energy Window Lower Limit") }, -{ 0x0054,0x0015,DICOM_T_UNK, _T("Energy Window Upper Limit") }, -{ 0x0054,0x0016,DICOM_T_UNK, _T("Radiopharmaceutical Information Sequence") }, -{ 0x0054,0x0017,DICOM_T_UNK, _T("Residual Syringe Counts") }, -{ 0x0054,0x0018,DICOM_T_UNK, _T("Energy Window Name") }, -{ 0x0054,0x0020,DICOM_T_UNK, _T("Detector Vector") }, -{ 0x0054,0x0021,DICOM_T_UNK, _T("Number of Detectors") }, -{ 0x0054,0x0022,DICOM_T_UNK, _T("Detector Information Sequence") }, -{ 0x0054,0x0030,DICOM_T_UNK, _T("Phase Vector") }, -{ 0x0054,0x0031,DICOM_T_UNK, _T("Number of Phases") }, -{ 0x0054,0x0032,DICOM_T_UNK, _T("Phase Information Sequence") }, -{ 0x0054,0x0033,DICOM_T_UNK, _T("Number of Frames in Phase") }, -{ 0x0054,0x0036,DICOM_T_UNK, _T("Phase Delay") }, -{ 0x0054,0x0038,DICOM_T_UNK, _T("Pause Between Frames") }, -{ 0x0054,0x0039,DICOM_T_UNK, _T("Phase Description") }, -{ 0x0054,0x0050,DICOM_T_UNK, _T("Rotation Vector") }, -{ 0x0054,0x0051,DICOM_T_UNK, _T("Number of Rotations") }, -{ 0x0054,0x0052,DICOM_T_UNK, _T("Rotation Information Sequence") }, -{ 0x0054,0x0053,DICOM_T_UNK, _T("Number of Frames in Rotation") }, -{ 0x0054,0x0060,DICOM_T_UNK, _T("R-R Interval Vector") }, -{ 0x0054,0x0061,DICOM_T_UNK, _T("Number of R-R Intervals") }, -{ 0x0054,0x0062,DICOM_T_UNK, _T("Gated Information Sequence") }, -{ 0x0054,0x0063,DICOM_T_UNK, _T("Data Information Sequence") }, -{ 0x0054,0x0070,DICOM_T_UNK, _T("Time Slot Vector") }, -{ 0x0054,0x0071,DICOM_T_UNK, _T("Number of Time Slots") }, -{ 0x0054,0x0072,DICOM_T_UNK, _T("Time Slot Information Sequence") }, -{ 0x0054,0x0073,DICOM_T_UNK, _T("Time Slot Time") }, -{ 0x0054,0x0080,DICOM_T_UNK, _T("Slice Vector") }, -{ 0x0054,0x0081,DICOM_T_UNK, _T("Number of Slices") }, -{ 0x0054,0x0090,DICOM_T_UNK, _T("Angular View Vector") }, -{ 0x0054,0x0100,DICOM_T_UNK, _T("Time Slice Vector") }, -{ 0x0054,0x0101,DICOM_T_UNK, _T("Number of Time Slices") }, -{ 0x0054,0x0200,DICOM_T_UNK, _T("Start Angle") }, -{ 0x0054,0x0202,DICOM_T_UNK, _T("Type of Detector Motion") }, -{ 0x0054,0x0210,DICOM_T_UNK, _T("Trigger Vector") }, -{ 0x0054,0x0211,DICOM_T_UNK, _T("Number of Triggers in Phase") }, -{ 0x0054,0x0220,DICOM_T_UNK, _T("View Code Sequence") }, -{ 0x0054,0x0222,DICOM_T_UNK, _T("View Modifier Code Sequence") }, -{ 0x0054,0x0300,DICOM_T_UNK, _T("Radionuclide Code Sequence") }, -{ 0x0054,0x0302,DICOM_T_UNK, _T("Administration Route Code Sequence") }, -{ 0x0054,0x0304,DICOM_T_UNK, _T("Radiopharmaceutical Code Sequence") }, -{ 0x0054,0x0306,DICOM_T_UNK, _T("Calibration Data Sequence") }, -{ 0x0054,0x0308,DICOM_T_UNK, _T("Energy Window Number") }, -{ 0x0054,0x0400,DICOM_T_UNK, _T("Image ID") }, -{ 0x0054,0x0410,DICOM_T_UNK, _T("Patient Orientation Code Sequence") }, -{ 0x0054,0x0412,DICOM_T_UNK, _T("Patient Orientation Modifier Code Sequence") }, -{ 0x0054,0x0414,DICOM_T_UNK, _T("Patient Gantry Relationship Code Sequence") }, -{ 0x0054,0x0500,DICOM_T_UNK, _T("Slice Progression Direction") }, -{ 0x0054,0x0501,DICOM_T_UNK, _T("Scan Progression Direction") }, -{ 0x0054,0x1000,DICOM_T_UNK, _T("Series Type") }, -{ 0x0054,0x1001,DICOM_T_UNK, _T("Units") }, -{ 0x0054,0x1002,DICOM_T_UNK, _T("Counts Source") }, -{ 0x0054,0x1004,DICOM_T_UNK, _T("Reprojection Method") }, -{ 0x0054,0x1006,DICOM_T_UNK, _T("SUV Type") }, -{ 0x0054,0x1100,DICOM_T_UNK, _T("Randoms Correction Method") }, -{ 0x0054,0x1101,DICOM_T_UNK, _T("Attenuation Correction Method") }, -{ 0x0054,0x1102,DICOM_T_UNK, _T("Decay Correction") }, -{ 0x0054,0x1103,DICOM_T_UNK, _T("Reconstruction Method") }, -{ 0x0054,0x1104,DICOM_T_UNK, _T("Detector Lines of Response Used") }, -{ 0x0054,0x1105,DICOM_T_UNK, _T("Scatter Correction Method") }, -{ 0x0054,0x1200,DICOM_T_UNK, _T("Axial Acceptance") }, -{ 0x0054,0x1201,DICOM_T_UNK, _T("Axial Mash") }, -{ 0x0054,0x1202,DICOM_T_UNK, _T("Transverse Mash") }, -{ 0x0054,0x1203,DICOM_T_UNK, _T("Detector Element Size") }, -{ 0x0054,0x1210,DICOM_T_UNK, _T("Coincidence Window Width") }, -{ 0x0054,0x1220,DICOM_T_UNK, _T("Secondary Counts Type") }, -{ 0x0054,0x1300,DICOM_T_UNK, _T("Frame Reference Time") }, -{ 0x0054,0x1310,DICOM_T_UNK, _T("Primary (Prompts) Counts Accumulated") }, -{ 0x0054,0x1311,DICOM_T_UNK, _T("Secondary Counts Accumulated") }, -{ 0x0054,0x1320,DICOM_T_UNK, _T("Slice Sensitivity Factor") }, -{ 0x0054,0x1321,DICOM_T_UNK, _T("Decay Factor") }, -{ 0x0054,0x1322,DICOM_T_UNK, _T("Dose Calibration Factor") }, -{ 0x0054,0x1323,DICOM_T_UNK, _T("Scatter Fraction Factor") }, -{ 0x0054,0x1324,DICOM_T_UNK, _T("Dead Time Factor") }, -{ 0x0054,0x1330,DICOM_T_UNK, _T("Image Index") }, -{ 0x0054,0x1400,DICOM_T_UNK, _T("Counts Included") }, -{ 0x0054,0x1401,DICOM_T_UNK, _T("Dead Time Correction Flag") }, -{ 0x0060,0x3000,DICOM_T_UNK, _T("Histogram Sequence") }, -{ 0x0060,0x3002,DICOM_T_UNK, _T("Histogram Number of Bins") }, -{ 0x0060,0x3004,DICOM_T_UNK, _T("Histogram First Bin Value") }, -{ 0x0060,0x3006,DICOM_T_UNK, _T("Histogram Last Bin Value") }, -{ 0x0060,0x3008,DICOM_T_UNK, _T("Histogram Bin Width") }, -{ 0x0060,0x3010,DICOM_T_UNK, _T("Histogram Explanation") }, -{ 0x0060,0x3020,DICOM_T_UNK, _T("Histogram Data") }, -{ 0x0062,0x0001,DICOM_T_UNK, _T("Segmentation Type") }, -{ 0x0062,0x0002,DICOM_T_UNK, _T("Segment Sequence") }, -{ 0x0062,0x0003,DICOM_T_UNK, _T("Segmented Property Category Code Sequence") }, -{ 0x0062,0x0004,DICOM_T_UNK, _T("Segment Number") }, -{ 0x0062,0x0005,DICOM_T_UNK, _T("Segment Label") }, -{ 0x0062,0x0006,DICOM_T_UNK, _T("Segment Description") }, -{ 0x0062,0x0008,DICOM_T_UNK, _T("Segment Algorithm Type") }, -{ 0x0062,0x0009,DICOM_T_UNK, _T("Segment Algorithm Name") }, -{ 0x0062,0x000A,DICOM_T_UNK, _T("Segment Identification Sequence") }, -{ 0x0062,0x000B,DICOM_T_UNK, _T("Referenced Segment Number") }, -{ 0x0062,0x000C,DICOM_T_UNK, _T("Recommended Display Grayscale Value") }, -{ 0x0062,0x000D,DICOM_T_UNK, _T("Recommended Display CIELab Value") }, -{ 0x0062,0x000E,DICOM_T_UNK, _T("Maximum Fractional Value") }, -{ 0x0062,0x000F,DICOM_T_UNK, _T("Segmented Property Type Code Sequence") }, -{ 0x0062,0x0010,DICOM_T_UNK, _T("Segmentation Fractional Type") }, -{ 0x0062,0x0011,DICOM_T_UNK, _T("Segmented Property Type Modifier Code Sequence") }, -{ 0x0062,0x0012,DICOM_T_UNK, _T("Used Segments Sequence") }, -{ 0x0064,0x0002,DICOM_T_UNK, _T("Deformable Registration Sequence") }, -{ 0x0064,0x0003,DICOM_T_UNK, _T("Source Frame of Reference UID") }, -{ 0x0064,0x0005,DICOM_T_UNK, _T("Deformable Registration Grid Sequence") }, -{ 0x0064,0x0007,DICOM_T_UNK, _T("Grid Dimensions") }, -{ 0x0064,0x0008,DICOM_T_UNK, _T("Grid Resolution") }, -{ 0x0064,0x0009,DICOM_T_UNK, _T("Vector Grid Data") }, -{ 0x0064,0x000F,DICOM_T_UNK, _T("Pre Deformation Matrix Registration Sequence") }, -{ 0x0064,0x0010,DICOM_T_UNK, _T("Post Deformation Matrix Registration Sequence") }, -{ 0x0066,0x0001,DICOM_T_UNK, _T("Number of Surfaces") }, -{ 0x0066,0x0002,DICOM_T_UNK, _T("Surface Sequence") }, -{ 0x0066,0x0003,DICOM_T_UNK, _T("Surface Number") }, -{ 0x0066,0x0004,DICOM_T_UNK, _T("Surface Comments") }, -{ 0x0066,0x0009,DICOM_T_UNK, _T("Surface Processing") }, -{ 0x0066,0x000A,DICOM_T_UNK, _T("Surface Processing Ratio") }, -{ 0x0066,0x000B,DICOM_T_UNK, _T("Surface Processing Description") }, -{ 0x0066,0x000C,DICOM_T_UNK, _T("Recommended Presentation Opacity") }, -{ 0x0066,0x000D,DICOM_T_UNK, _T("Recommended Presentation Type") }, -{ 0x0066,0x000E,DICOM_T_UNK, _T("Finite Volume") }, -{ 0x0066,0x0010,DICOM_T_UNK, _T("Manifold") }, -{ 0x0066,0x0011,DICOM_T_UNK, _T("Surface Points Sequence") }, -{ 0x0066,0x0012,DICOM_T_UNK, _T("Surface Points Normals Sequence") }, -{ 0x0066,0x0013,DICOM_T_UNK, _T("Surface Mesh Primitives Sequence") }, -{ 0x0066,0x0015,DICOM_T_UNK, _T("Number of Surface Points") }, -{ 0x0066,0x0016,DICOM_T_UNK, _T("Point Coordinates Data") }, -{ 0x0066,0x0017,DICOM_T_UNK, _T("Point Position Accuracy") }, -{ 0x0066,0x0018,DICOM_T_UNK, _T("Mean Point Distance") }, -{ 0x0066,0x0019,DICOM_T_UNK, _T("Maximum Point Distance") }, -{ 0x0066,0x001A,DICOM_T_UNK, _T("Points Bounding Box Coordinates") }, -{ 0x0066,0x001B,DICOM_T_UNK, _T("Axis of Rotation") }, -{ 0x0066,0x001C,DICOM_T_UNK, _T("Center of Rotation") }, -{ 0x0066,0x001E,DICOM_T_UNK, _T("Number of Vectors") }, -{ 0x0066,0x001F,DICOM_T_UNK, _T("Vector Dimensionality") }, -{ 0x0066,0x0020,DICOM_T_UNK, _T("Vector Accuracy") }, -{ 0x0066,0x0021,DICOM_T_UNK, _T("Vector Coordinate Data") }, -{ 0x0066,0x0023,DICOM_T_UNK, _T("Triangle Point Index List") }, -{ 0x0066,0x0024,DICOM_T_UNK, _T("Edge Point Index List") }, -{ 0x0066,0x0025,DICOM_T_UNK, _T("Vertex Point Index List") }, -{ 0x0066,0x0026,DICOM_T_UNK, _T("Triangle Strip Sequence") }, -{ 0x0066,0x0027,DICOM_T_UNK, _T("Triangle Fan Sequence") }, -{ 0x0066,0x0028,DICOM_T_UNK, _T("Line Sequence") }, -{ 0x0066,0x0029,DICOM_T_UNK, _T("Primitive Point Index List") }, -{ 0x0066,0x002A,DICOM_T_UNK, _T("Surface Count") }, -{ 0x0066,0x002B,DICOM_T_UNK, _T("Referenced Surface Sequence") }, -{ 0x0066,0x002C,DICOM_T_UNK, _T("Referenced Surface Number") }, -{ 0x0066,0x002D,DICOM_T_UNK, _T("Segment Surface Generation Algorithm Identification Sequence") }, -{ 0x0066,0x002E,DICOM_T_UNK, _T("Segment Surface Source Instance Sequence") }, -{ 0x0066,0x002F,DICOM_T_UNK, _T("Algorithm Family Code Sequence") }, -{ 0x0066,0x0030,DICOM_T_UNK, _T("Algorithm Name Code Sequence") }, -{ 0x0066,0x0031,DICOM_T_UNK, _T("Algorithm Version") }, -{ 0x0066,0x0032,DICOM_T_UNK, _T("Algorithm Parameters") }, -{ 0x0066,0x0034,DICOM_T_UNK, _T("Facet Sequence") }, -{ 0x0066,0x0035,DICOM_T_UNK, _T("Surface Processing Algorithm Identification Sequence") }, -{ 0x0066,0x0036,DICOM_T_UNK, _T("Algorithm Name") }, -{ 0x0066,0x0037,DICOM_T_UNK, _T("Recommended Point Radius") }, -{ 0x0066,0x0038,DICOM_T_UNK, _T("Recommended Line Thickness") }, -{ 0x0066,0x0040,DICOM_T_UNK, _T("Long Primitive Point Index List") }, -{ 0x0066,0x0041,DICOM_T_UNK, _T("Long Triangle Point Index List") }, -{ 0x0066,0x0042,DICOM_T_UNK, _T("Long Edge Point Index List") }, -{ 0x0066,0x0043,DICOM_T_UNK, _T("Long Vertex Point Index List") }, -{ 0x0068,0x6210,DICOM_T_UNK, _T("Implant Size") }, -{ 0x0068,0x6221,DICOM_T_UNK, _T("Implant Template Version") }, -{ 0x0068,0x6222,DICOM_T_UNK, _T("Replaced Implant Template Sequence") }, -{ 0x0068,0x6223,DICOM_T_UNK, _T("Implant Type") }, -{ 0x0068,0x6224,DICOM_T_UNK, _T("Derivation Implant Template Sequence") }, -{ 0x0068,0x6225,DICOM_T_UNK, _T("Original Implant Template Sequence") }, -{ 0x0068,0x6226,DICOM_T_UNK, _T("Effective DateTime") }, -{ 0x0068,0x6230,DICOM_T_UNK, _T("Implant Target Anatomy Sequence") }, -{ 0x0068,0x6260,DICOM_T_UNK, _T("Information From Manufacturer Sequence") }, -{ 0x0068,0x6265,DICOM_T_UNK, _T("Notification From Manufacturer Sequence") }, -{ 0x0068,0x6270,DICOM_T_UNK, _T("Information Issue DateTime") }, -{ 0x0068,0x6280,DICOM_T_UNK, _T("Information Summary") }, -{ 0x0068,0x62A0,DICOM_T_UNK, _T("Implant Regulatory Disapproval Code Sequence") }, -{ 0x0068,0x62A5,DICOM_T_UNK, _T("Overall Template Spatial Tolerance") }, -{ 0x0068,0x62C0,DICOM_T_UNK, _T("HPGL Document Sequence") }, -{ 0x0068,0x62D0,DICOM_T_UNK, _T("HPGL Document ID") }, -{ 0x0068,0x62D5,DICOM_T_UNK, _T("HPGL Document Label") }, -{ 0x0068,0x62E0,DICOM_T_UNK, _T("View Orientation Code Sequence") }, -{ 0x0068,0x62F0,DICOM_T_UNK, _T("View Orientation Modifier") }, -{ 0x0068,0x62F2,DICOM_T_UNK, _T("HPGL Document Scaling") }, -{ 0x0068,0x6300,DICOM_T_UNK, _T("HPGL Document") }, -{ 0x0068,0x6310,DICOM_T_UNK, _T("HPGL Contour Pen Number") }, -{ 0x0068,0x6320,DICOM_T_UNK, _T("HPGL Pen Sequence") }, -{ 0x0068,0x6330,DICOM_T_UNK, _T("HPGL Pen Number") }, -{ 0x0068,0x6340,DICOM_T_UNK, _T("HPGL Pen Label") }, -{ 0x0068,0x6345,DICOM_T_UNK, _T("HPGL Pen Description") }, -{ 0x0068,0x6346,DICOM_T_UNK, _T("Recommended Rotation Point") }, -{ 0x0068,0x6347,DICOM_T_UNK, _T("Bounding Rectangle") }, -{ 0x0068,0x6350,DICOM_T_UNK, _T("Implant Template 3D Model Surface Number") }, -{ 0x0068,0x6360,DICOM_T_UNK, _T("Surface Model Description Sequence") }, -{ 0x0068,0x6380,DICOM_T_UNK, _T("Surface Model Label") }, -{ 0x0068,0x6390,DICOM_T_UNK, _T("Surface Model Scaling Factor") }, -{ 0x0068,0x63A0,DICOM_T_UNK, _T("Materials Code Sequence") }, -{ 0x0068,0x63A4,DICOM_T_UNK, _T("Coating Materials Code Sequence") }, -{ 0x0068,0x63A8,DICOM_T_UNK, _T("Implant Type Code Sequence") }, -{ 0x0068,0x63AC,DICOM_T_UNK, _T("Fixation Method Code Sequence") }, -{ 0x0068,0x63B0,DICOM_T_UNK, _T("Mating Feature Sets Sequence") }, -{ 0x0068,0x63C0,DICOM_T_UNK, _T("Mating Feature Set ID") }, -{ 0x0068,0x63D0,DICOM_T_UNK, _T("Mating Feature Set Label") }, -{ 0x0068,0x63E0,DICOM_T_UNK, _T("Mating Feature Sequence") }, -{ 0x0068,0x63F0,DICOM_T_UNK, _T("Mating Feature ID") }, -{ 0x0068,0x6400,DICOM_T_UNK, _T("Mating Feature Degree of Freedom Sequence") }, -{ 0x0068,0x6410,DICOM_T_UNK, _T("Degree of Freedom ID") }, -{ 0x0068,0x6420,DICOM_T_UNK, _T("Degree of Freedom Type") }, -{ 0x0068,0x6430,DICOM_T_UNK, _T("2D Mating Feature Coordinates Sequence") }, -{ 0x0068,0x6440,DICOM_T_UNK, _T("Referenced HPGL Document ID") }, -{ 0x0068,0x6450,DICOM_T_UNK, _T("2D Mating Point") }, -{ 0x0068,0x6460,DICOM_T_UNK, _T("2D Mating Axes") }, -{ 0x0068,0x6470,DICOM_T_UNK, _T("2D Degree of Freedom Sequence") }, -{ 0x0068,0x6490,DICOM_T_UNK, _T("3D Degree of Freedom Axis") }, -{ 0x0068,0x64A0,DICOM_T_UNK, _T("Range of Freedom") }, -{ 0x0068,0x64C0,DICOM_T_UNK, _T("3D Mating Point") }, -{ 0x0068,0x64D0,DICOM_T_UNK, _T("3D Mating Axes") }, -{ 0x0068,0x64F0,DICOM_T_UNK, _T("2D Degree of Freedom Axis") }, -{ 0x0068,0x6500,DICOM_T_UNK, _T("Planning Landmark Point Sequence") }, -{ 0x0068,0x6510,DICOM_T_UNK, _T("Planning Landmark Line Sequence") }, -{ 0x0068,0x6520,DICOM_T_UNK, _T("Planning Landmark Plane Sequence") }, -{ 0x0068,0x6530,DICOM_T_UNK, _T("Planning Landmark ID") }, -{ 0x0068,0x6540,DICOM_T_UNK, _T("Planning Landmark Description") }, -{ 0x0068,0x6545,DICOM_T_UNK, _T("Planning Landmark Identification Code Sequence") }, -{ 0x0068,0x6550,DICOM_T_UNK, _T("2D Point Coordinates Sequence") }, -{ 0x0068,0x6560,DICOM_T_UNK, _T("2D Point Coordinates") }, -{ 0x0068,0x6590,DICOM_T_UNK, _T("3D Point Coordinates") }, -{ 0x0068,0x65A0,DICOM_T_UNK, _T("2D Line Coordinates Sequence") }, -{ 0x0068,0x65B0,DICOM_T_UNK, _T("2D Line Coordinates") }, -{ 0x0068,0x65D0,DICOM_T_UNK, _T("3D Line Coordinates") }, -{ 0x0068,0x65E0,DICOM_T_UNK, _T("2D Plane Coordinates Sequence") }, -{ 0x0068,0x65F0,DICOM_T_UNK, _T("2D Plane Intersection") }, -{ 0x0068,0x6610,DICOM_T_UNK, _T("3D Plane Origin") }, -{ 0x0068,0x6620,DICOM_T_UNK, _T("3D Plane Normal") }, -{ 0x0070,0x0001,DICOM_T_UNK, _T("Graphic Annotation Sequence") }, -{ 0x0070,0x0002,DICOM_T_UNK, _T("Graphic Layer") }, -{ 0x0070,0x0003,DICOM_T_UNK, _T("Bounding Box Annotation Units") }, -{ 0x0070,0x0004,DICOM_T_UNK, _T("Anchor Point Annotation Units") }, -{ 0x0070,0x0005,DICOM_T_UNK, _T("Graphic Annotation Units") }, -{ 0x0070,0x0006,DICOM_T_UNK, _T("Unformatted Text Value") }, -{ 0x0070,0x0008,DICOM_T_UNK, _T("Text Object Sequence") }, -{ 0x0070,0x0009,DICOM_T_UNK, _T("Graphic Object Sequence") }, -{ 0x0070,0x0010,DICOM_T_UNK, _T("Bounding Box Top Left Hand Corner") }, -{ 0x0070,0x0011,DICOM_T_UNK, _T("Bounding Box Bottom Right Hand Corner") }, -{ 0x0070,0x0012,DICOM_T_UNK, _T("Bounding Box Text Horizontal Justification") }, -{ 0x0070,0x0014,DICOM_T_UNK, _T("Anchor Point") }, -{ 0x0070,0x0015,DICOM_T_UNK, _T("Anchor Point Visibility") }, -{ 0x0070,0x0020,DICOM_T_UNK, _T("Graphic Dimensions") }, -{ 0x0070,0x0021,DICOM_T_UNK, _T("Number of Graphic Points") }, -{ 0x0070,0x0022,DICOM_T_UNK, _T("Graphic Data") }, -{ 0x0070,0x0023,DICOM_T_UNK, _T("Graphic Type") }, -{ 0x0070,0x0024,DICOM_T_UNK, _T("Graphic Filled") }, -{ 0x0070,0x0040,DICOM_T_UNK, _T("Image Rotation (Retired)") }, -{ 0x0070,0x0041,DICOM_T_UNK, _T("Image Horizontal Flip") }, -{ 0x0070,0x0042,DICOM_T_UNK, _T("Image Rotation") }, -{ 0x0070,0x0050,DICOM_T_UNK, _T("Displayed Area Top Left Hand Corner (Trial)") }, -{ 0x0070,0x0051,DICOM_T_UNK, _T("Displayed Area Bottom Right Hand Corner (Trial)") }, -{ 0x0070,0x0052,DICOM_T_UNK, _T("Displayed Area Top Left Hand Corner") }, -{ 0x0070,0x0053,DICOM_T_UNK, _T("Displayed Area Bottom Right Hand Corner") }, -{ 0x0070,0x005A,DICOM_T_UNK, _T("Displayed Area Selection Sequence") }, -{ 0x0070,0x0060,DICOM_T_UNK, _T("Graphic Layer Sequence") }, -{ 0x0070,0x0062,DICOM_T_UNK, _T("Graphic Layer Order") }, -{ 0x0070,0x0066,DICOM_T_UNK, _T("Graphic Layer Recommended Display Grayscale Value") }, -{ 0x0070,0x0067,DICOM_T_UNK, _T("Graphic Layer Recommended Display RGB Value") }, -{ 0x0070,0x0068,DICOM_T_UNK, _T("Graphic Layer Description") }, -{ 0x0070,0x0080,DICOM_T_UNK, _T("Content Label") }, -{ 0x0070,0x0081,DICOM_T_UNK, _T("Content Description") }, -{ 0x0070,0x0082,DICOM_T_UNK, _T("Presentation Creation Date") }, -{ 0x0070,0x0083,DICOM_T_UNK, _T("Presentation Creation Time") }, -{ 0x0070,0x0084,DICOM_T_UNK, _T("Content Creator's Name") }, -{ 0x0070,0x0086,DICOM_T_UNK, _T("Content Creator's Identification Code Sequence") }, -{ 0x0070,0x0087,DICOM_T_UNK, _T("Alternate Content Description Sequence") }, -{ 0x0070,0x0100,DICOM_T_UNK, _T("Presentation Size Mode") }, -{ 0x0070,0x0101,DICOM_T_UNK, _T("Presentation Pixel Spacing") }, -{ 0x0070,0x0102,DICOM_T_UNK, _T("Presentation Pixel Aspect Ratio") }, -{ 0x0070,0x0103,DICOM_T_UNK, _T("Presentation Pixel Magnification Ratio") }, -{ 0x0070,0x0207,DICOM_T_UNK, _T("Graphic Group Label") }, -{ 0x0070,0x0208,DICOM_T_UNK, _T("Graphic Group Description") }, -{ 0x0070,0x0209,DICOM_T_UNK, _T("Compound Graphic Sequence") }, -{ 0x0070,0x0226,DICOM_T_UNK, _T("Compound Graphic Instance ID") }, -{ 0x0070,0x0227,DICOM_T_UNK, _T("Font Name") }, -{ 0x0070,0x0228,DICOM_T_UNK, _T("Font Name Type") }, -{ 0x0070,0x0229,DICOM_T_UNK, _T("CSS Font Name") }, -{ 0x0070,0x0230,DICOM_T_UNK, _T("Rotation Angle") }, -{ 0x0070,0x0231,DICOM_T_UNK, _T("Text Style Sequence") }, -{ 0x0070,0x0232,DICOM_T_UNK, _T("Line Style Sequence") }, -{ 0x0070,0x0233,DICOM_T_UNK, _T("Fill Style Sequence") }, -{ 0x0070,0x0234,DICOM_T_UNK, _T("Graphic Group Sequence") }, -{ 0x0070,0x0241,DICOM_T_UNK, _T("Text Color CIELab Value") }, -{ 0x0070,0x0242,DICOM_T_UNK, _T("Horizontal Alignment") }, -{ 0x0070,0x0243,DICOM_T_UNK, _T("Vertical Alignment") }, -{ 0x0070,0x0244,DICOM_T_UNK, _T("Shadow Style") }, -{ 0x0070,0x0245,DICOM_T_UNK, _T("Shadow Offset X") }, -{ 0x0070,0x0246,DICOM_T_UNK, _T("Shadow Offset Y") }, -{ 0x0070,0x0247,DICOM_T_UNK, _T("Shadow Color CIELab Value") }, -{ 0x0070,0x0248,DICOM_T_UNK, _T("Underlined") }, -{ 0x0070,0x0249,DICOM_T_UNK, _T("Bold") }, -{ 0x0070,0x0250,DICOM_T_UNK, _T("Italic") }, -{ 0x0070,0x0251,DICOM_T_UNK, _T("Pattern On Color CIELab Value") }, -{ 0x0070,0x0252,DICOM_T_UNK, _T("Pattern Off Color CIELab Value") }, -{ 0x0070,0x0253,DICOM_T_UNK, _T("Line Thickness") }, -{ 0x0070,0x0254,DICOM_T_UNK, _T("Line Dashing Style") }, -{ 0x0070,0x0255,DICOM_T_UNK, _T("Line Pattern") }, -{ 0x0070,0x0256,DICOM_T_UNK, _T("Fill Pattern") }, -{ 0x0070,0x0257,DICOM_T_UNK, _T("Fill Mode") }, -{ 0x0070,0x0258,DICOM_T_UNK, _T("Shadow Opacity") }, -{ 0x0070,0x0261,DICOM_T_UNK, _T("Gap Length") }, -{ 0x0070,0x0262,DICOM_T_UNK, _T("Diameter of Visibility") }, -{ 0x0070,0x0273,DICOM_T_UNK, _T("Rotation Point") }, -{ 0x0070,0x0274,DICOM_T_UNK, _T("Tick Alignment") }, -{ 0x0070,0x0278,DICOM_T_UNK, _T("Show Tick Label") }, -{ 0x0070,0x0279,DICOM_T_UNK, _T("Tick Label Alignment") }, -{ 0x0070,0x0282,DICOM_T_UNK, _T("Compound Graphic Units") }, -{ 0x0070,0x0284,DICOM_T_UNK, _T("Pattern On Opacity") }, -{ 0x0070,0x0285,DICOM_T_UNK, _T("Pattern Off Opacity") }, -{ 0x0070,0x0287,DICOM_T_UNK, _T("Major Ticks Sequence") }, -{ 0x0070,0x0288,DICOM_T_UNK, _T("Tick Position") }, -{ 0x0070,0x0289,DICOM_T_UNK, _T("Tick Label") }, -{ 0x0070,0x0294,DICOM_T_UNK, _T("Compound Graphic Type") }, -{ 0x0070,0x0295,DICOM_T_UNK, _T("Graphic Group ID") }, -{ 0x0070,0x0306,DICOM_T_UNK, _T("Shape Type") }, -{ 0x0070,0x0308,DICOM_T_UNK, _T("Registration Sequence") }, -{ 0x0070,0x0309,DICOM_T_UNK, _T("Matrix Registration Sequence") }, -{ 0x0070,0x030A,DICOM_T_UNK, _T("Matrix Sequence") }, -{ 0x0070,0x030C,DICOM_T_UNK, _T("Frame of Reference Transformation Matrix Type") }, -{ 0x0070,0x030D,DICOM_T_UNK, _T("Registration Type Code Sequence") }, -{ 0x0070,0x030F,DICOM_T_UNK, _T("Fiducial Description") }, -{ 0x0070,0x0310,DICOM_T_UNK, _T("Fiducial Identifier") }, -{ 0x0070,0x0311,DICOM_T_UNK, _T("Fiducial Identifier Code Sequence") }, -{ 0x0070,0x0312,DICOM_T_UNK, _T("Contour Uncertainty Radius") }, -{ 0x0070,0x0314,DICOM_T_UNK, _T("Used Fiducials Sequence") }, -{ 0x0070,0x0318,DICOM_T_UNK, _T("Graphic Coordinates Data Sequence") }, -{ 0x0070,0x031A,DICOM_T_UNK, _T("Fiducial UID") }, -{ 0x0070,0x031C,DICOM_T_UNK, _T("Fiducial Set Sequence") }, -{ 0x0070,0x031E,DICOM_T_UNK, _T("Fiducial Sequence") }, -{ 0x0070,0x0401,DICOM_T_UNK, _T("Graphic Layer Recommended Display CIELab Value") }, -{ 0x0070,0x0402,DICOM_T_UNK, _T("Blending Sequence") }, -{ 0x0070,0x0403,DICOM_T_UNK, _T("Relative Opacity") }, -{ 0x0070,0x0404,DICOM_T_UNK, _T("Referenced Spatial Registration Sequence") }, -{ 0x0070,0x0405,DICOM_T_UNK, _T("Blending Position") }, -{ 0x0072,0x0002,DICOM_T_UNK, _T("Hanging Protocol Name") }, -{ 0x0072,0x0004,DICOM_T_UNK, _T("Hanging Protocol Description") }, -{ 0x0072,0x0006,DICOM_T_UNK, _T("Hanging Protocol Level") }, -{ 0x0072,0x0008,DICOM_T_UNK, _T("Hanging Protocol Creator") }, -{ 0x0072,0x000A,DICOM_T_UNK, _T("Hanging Protocol Creation DateTime") }, -{ 0x0072,0x000C,DICOM_T_UNK, _T("Hanging Protocol Definition Sequence") }, -{ 0x0072,0x000E,DICOM_T_UNK, _T("Hanging Protocol User Identification Code Sequence") }, -{ 0x0072,0x0010,DICOM_T_UNK, _T("Hanging Protocol User Group Name") }, -{ 0x0072,0x0012,DICOM_T_UNK, _T("Source Hanging Protocol Sequence") }, -{ 0x0072,0x0014,DICOM_T_UNK, _T("Number of Priors Referenced") }, -{ 0x0072,0x0020,DICOM_T_UNK, _T("Image Sets Sequence") }, -{ 0x0072,0x0022,DICOM_T_UNK, _T("Image Set Selector Sequence") }, -{ 0x0072,0x0024,DICOM_T_UNK, _T("Image Set Selector Usage Flag") }, -{ 0x0072,0x0026,DICOM_T_UNK, _T("Selector Attribute") }, -{ 0x0072,0x0028,DICOM_T_UNK, _T("Selector Value Number") }, -{ 0x0072,0x0030,DICOM_T_UNK, _T("Time Based Image Sets Sequence") }, -{ 0x0072,0x0032,DICOM_T_UNK, _T("Image Set Number") }, -{ 0x0072,0x0034,DICOM_T_UNK, _T("Image Set Selector Category") }, -{ 0x0072,0x0038,DICOM_T_UNK, _T("Relative Time") }, -{ 0x0072,0x003A,DICOM_T_UNK, _T("Relative Time Units") }, -{ 0x0072,0x003C,DICOM_T_UNK, _T("Abstract Prior Value") }, -{ 0x0072,0x003E,DICOM_T_UNK, _T("Abstract Prior Code Sequence") }, -{ 0x0072,0x0040,DICOM_T_UNK, _T("Image Set Label") }, -{ 0x0072,0x0050,DICOM_T_UNK, _T("Selector Attribute VR") }, -{ 0x0072,0x0052,DICOM_T_UNK, _T("Selector Sequence Pointer") }, -{ 0x0072,0x0054,DICOM_T_UNK, _T("Selector Sequence Pointer Private Creator") }, -{ 0x0072,0x0056,DICOM_T_UNK, _T("Selector Attribute Private Creator") }, -{ 0x0072,0x0060,DICOM_T_UNK, _T("Selector AT Value") }, -{ 0x0072,0x0062,DICOM_T_UNK, _T("Selector CS Value") }, -{ 0x0072,0x0064,DICOM_T_UNK, _T("Selector IS Value") }, -{ 0x0072,0x0066,DICOM_T_UNK, _T("Selector LO Value") }, -{ 0x0072,0x0068,DICOM_T_UNK, _T("Selector LT Value") }, -{ 0x0072,0x006A,DICOM_T_UNK, _T("Selector PN Value") }, -{ 0x0072,0x006C,DICOM_T_UNK, _T("Selector SH Value") }, -{ 0x0072,0x006E,DICOM_T_UNK, _T("Selector ST Value") }, -{ 0x0072,0x0070,DICOM_T_UNK, _T("Selector UT Value") }, -{ 0x0072,0x0072,DICOM_T_UNK, _T("Selector DS Value") }, -{ 0x0072,0x0074,DICOM_T_UNK, _T("Selector FD Value") }, -{ 0x0072,0x0076,DICOM_T_UNK, _T("Selector FL Value") }, -{ 0x0072,0x0078,DICOM_T_UNK, _T("Selector UL Value") }, -{ 0x0072,0x007A,DICOM_T_UNK, _T("Selector US Value") }, -{ 0x0072,0x007C,DICOM_T_UNK, _T("Selector SL Value") }, -{ 0x0072,0x007E,DICOM_T_UNK, _T("Selector SS Value") }, -{ 0x0072,0x0080,DICOM_T_UNK, _T("Selector Code Sequence Value") }, -{ 0x0072,0x0100,DICOM_T_UNK, _T("Number of Screens") }, -{ 0x0072,0x0102,DICOM_T_UNK, _T("Nominal Screen Definition Sequence") }, -{ 0x0072,0x0104,DICOM_T_UNK, _T("Number of Vertical Pixels") }, -{ 0x0072,0x0106,DICOM_T_UNK, _T("Number of Horizontal Pixels") }, -{ 0x0072,0x0108,DICOM_T_UNK, _T("Display Environment Spatial Position") }, -{ 0x0072,0x010A,DICOM_T_UNK, _T("Screen Minimum Grayscale Bit Depth") }, -{ 0x0072,0x010C,DICOM_T_UNK, _T("Screen Minimum Color Bit Depth") }, -{ 0x0072,0x010E,DICOM_T_UNK, _T("Application Maximum Repaint Time") }, -{ 0x0072,0x0200,DICOM_T_UNK, _T("Display Sets Sequence") }, -{ 0x0072,0x0202,DICOM_T_UNK, _T("Display Set Number") }, -{ 0x0072,0x0203,DICOM_T_UNK, _T("Display Set Label") }, -{ 0x0072,0x0204,DICOM_T_UNK, _T("Display Set Presentation Group") }, -{ 0x0072,0x0206,DICOM_T_UNK, _T("Display Set Presentation Group Description") }, -{ 0x0072,0x0208,DICOM_T_UNK, _T("Partial Data Display Handling") }, -{ 0x0072,0x0210,DICOM_T_UNK, _T("Synchronized Scrolling Sequence") }, -{ 0x0072,0x0212,DICOM_T_UNK, _T("Display Set Scrolling Group") }, -{ 0x0072,0x0214,DICOM_T_UNK, _T("Navigation Indicator Sequence") }, -{ 0x0072,0x0216,DICOM_T_UNK, _T("Navigation Display Set") }, -{ 0x0072,0x0218,DICOM_T_UNK, _T("Reference Display Sets") }, -{ 0x0072,0x0300,DICOM_T_UNK, _T("Image Boxes Sequence") }, -{ 0x0072,0x0302,DICOM_T_UNK, _T("Image Box Number") }, -{ 0x0072,0x0304,DICOM_T_UNK, _T("Image Box Layout Type") }, -{ 0x0072,0x0306,DICOM_T_UNK, _T("Image Box Tile Horizontal Dimension") }, -{ 0x0072,0x0308,DICOM_T_UNK, _T("Image Box Tile Vertical Dimension") }, -{ 0x0072,0x0310,DICOM_T_UNK, _T("Image Box Scroll Direction") }, -{ 0x0072,0x0312,DICOM_T_UNK, _T("Image Box Small Scroll Type") }, -{ 0x0072,0x0314,DICOM_T_UNK, _T("Image Box Small Scroll Amount") }, -{ 0x0072,0x0316,DICOM_T_UNK, _T("Image Box Large Scroll Type") }, -{ 0x0072,0x0318,DICOM_T_UNK, _T("Image Box Large Scroll Amount") }, -{ 0x0072,0x0320,DICOM_T_UNK, _T("Image Box Overlap Priority") }, -{ 0x0072,0x0330,DICOM_T_UNK, _T("Cine Relative to Real-Time") }, -{ 0x0072,0x0400,DICOM_T_UNK, _T("Filter Operations Sequence") }, -{ 0x0072,0x0402,DICOM_T_UNK, _T("Filter-by Category") }, -{ 0x0072,0x0404,DICOM_T_UNK, _T("Filter-by Attribute Presence") }, -{ 0x0072,0x0406,DICOM_T_UNK, _T("Filter-by Operator") }, -{ 0x0072,0x0420,DICOM_T_UNK, _T("Structured Display Background CIELab Value") }, -{ 0x0072,0x0421,DICOM_T_UNK, _T("Empty Image Box CIELab Value") }, -{ 0x0072,0x0422,DICOM_T_UNK, _T("Structured Display Image Box Sequence") }, -{ 0x0072,0x0424,DICOM_T_UNK, _T("Structured Display Text Box Sequence") }, -{ 0x0072,0x0427,DICOM_T_UNK, _T("Referenced First Frame Sequence") }, -{ 0x0072,0x0430,DICOM_T_UNK, _T("Image Box Synchronization Sequence") }, -{ 0x0072,0x0432,DICOM_T_UNK, _T("Synchronized Image Box List") }, -{ 0x0072,0x0434,DICOM_T_UNK, _T("Type of Synchronization") }, -{ 0x0072,0x0500,DICOM_T_UNK, _T("Blending Operation Type") }, -{ 0x0072,0x0510,DICOM_T_UNK, _T("Reformatting Operation Type") }, -{ 0x0072,0x0512,DICOM_T_UNK, _T("Reformatting Thickness") }, -{ 0x0072,0x0514,DICOM_T_UNK, _T("Reformatting Interval") }, -{ 0x0072,0x0516,DICOM_T_UNK, _T("Reformatting Operation Initial View Direction") }, -{ 0x0072,0x0520,DICOM_T_UNK, _T("3D Rendering Type") }, -{ 0x0072,0x0600,DICOM_T_UNK, _T("Sorting Operations Sequence") }, -{ 0x0072,0x0602,DICOM_T_UNK, _T("Sort-by Category") }, -{ 0x0072,0x0604,DICOM_T_UNK, _T("Sorting Direction") }, -{ 0x0072,0x0700,DICOM_T_UNK, _T("Display Set Patient Orientation") }, -{ 0x0072,0x0702,DICOM_T_UNK, _T("VOI Type") }, -{ 0x0072,0x0704,DICOM_T_UNK, _T("Pseudo-Color Type") }, -{ 0x0072,0x0705,DICOM_T_UNK, _T("Pseudo-Color Palette Instance Reference Sequence") }, -{ 0x0072,0x0706,DICOM_T_UNK, _T("Show Grayscale Inverted") }, -{ 0x0072,0x0710,DICOM_T_UNK, _T("Show Image True Size Flag") }, -{ 0x0072,0x0712,DICOM_T_UNK, _T("Show Graphic Annotation Flag") }, -{ 0x0072,0x0714,DICOM_T_UNK, _T("Show Patient Demographics Flag") }, -{ 0x0072,0x0716,DICOM_T_UNK, _T("Show Acquisition Techniques Flag") }, -{ 0x0072,0x0717,DICOM_T_UNK, _T("Display Set Horizontal Justification") }, -{ 0x0072,0x0718,DICOM_T_UNK, _T("Display Set Vertical Justification") }, -{ 0x0074,0x0120,DICOM_T_UNK, _T("Continuation Start Meterset") }, -{ 0x0074,0x0121,DICOM_T_UNK, _T("Continuation End Meterset") }, -{ 0x0074,0x1000,DICOM_T_UNK, _T("Procedure Step State") }, -{ 0x0074,0x1002,DICOM_T_UNK, _T("Procedure Step Progress Information Sequence") }, -{ 0x0074,0x1004,DICOM_T_UNK, _T("Procedure Step Progress") }, -{ 0x0074,0x1006,DICOM_T_UNK, _T("Procedure Step Progress Description") }, -{ 0x0074,0x1008,DICOM_T_UNK, _T("Procedure Step Communications URI Sequence") }, -{ 0x0074,0x100A,DICOM_T_UNK, _T("Contact URI") }, -{ 0x0074,0x100C,DICOM_T_UNK, _T("Contact Display Name") }, -{ 0x0074,0x100E,DICOM_T_UNK, _T("Procedure Step Discontinuation Reason Code Sequence") }, -{ 0x0074,0x1020,DICOM_T_UNK, _T("Beam Task Sequence") }, -{ 0x0074,0x1022,DICOM_T_UNK, _T("Beam Task Type") }, -{ 0x0074,0x1024,DICOM_T_UNK, _T("Beam Order Index (Trial)") }, -{ 0x0074,0x1025,DICOM_T_UNK, _T("Autosequence Flag") }, -{ 0x0074,0x1026,DICOM_T_UNK, _T("Table Top Vertical Adjusted Position") }, -{ 0x0074,0x1027,DICOM_T_UNK, _T("Table Top Longitudinal Adjusted Position") }, -{ 0x0074,0x1028,DICOM_T_UNK, _T("Table Top Lateral Adjusted Position") }, -{ 0x0074,0x102A,DICOM_T_UNK, _T("Patient Support Adjusted Angle") }, -{ 0x0074,0x102B,DICOM_T_UNK, _T("Table Top Eccentric Adjusted Angle") }, -{ 0x0074,0x102C,DICOM_T_UNK, _T("Table Top Pitch Adjusted Angle") }, -{ 0x0074,0x102D,DICOM_T_UNK, _T("Table Top Roll Adjusted Angle") }, -{ 0x0074,0x1030,DICOM_T_UNK, _T("Delivery Verification Image Sequence") }, -{ 0x0074,0x1032,DICOM_T_UNK, _T("Verification Image Timing") }, -{ 0x0074,0x1034,DICOM_T_UNK, _T("Double Exposure Flag") }, -{ 0x0074,0x1036,DICOM_T_UNK, _T("Double Exposure Ordering") }, -{ 0x0074,0x1038,DICOM_T_UNK, _T("Double Exposure Meterset (Trial)") }, -{ 0x0074,0x103A,DICOM_T_UNK, _T("Double Exposure Field Delta (Trial)") }, -{ 0x0074,0x1040,DICOM_T_UNK, _T("Related Reference RT Image Sequence") }, -{ 0x0074,0x1042,DICOM_T_UNK, _T("General Machine Verification Sequence") }, -{ 0x0074,0x1044,DICOM_T_UNK, _T("Conventional Machine Verification Sequence") }, -{ 0x0074,0x1046,DICOM_T_UNK, _T("Ion Machine Verification Sequence") }, -{ 0x0074,0x1048,DICOM_T_UNK, _T("Failed Attributes Sequence") }, -{ 0x0074,0x104A,DICOM_T_UNK, _T("Overridden Attributes Sequence") }, -{ 0x0074,0x104C,DICOM_T_UNK, _T("Conventional Control Point Verification Sequence") }, -{ 0x0074,0x104E,DICOM_T_UNK, _T("Ion Control Point Verification Sequence") }, -{ 0x0074,0x1050,DICOM_T_UNK, _T("Attribute Occurrence Sequence") }, -{ 0x0074,0x1052,DICOM_T_UNK, _T("Attribute Occurrence Pointer") }, -{ 0x0074,0x1054,DICOM_T_UNK, _T("Attribute Item Selector") }, -{ 0x0074,0x1056,DICOM_T_UNK, _T("Attribute Occurrence Private Creator") }, -{ 0x0074,0x1057,DICOM_T_UNK, _T("Selector Sequence Pointer Items") }, -{ 0x0074,0x1200,DICOM_T_UNK, _T("Scheduled Procedure Step Priority") }, -{ 0x0074,0x1202,DICOM_T_UNK, _T("Worklist Label") }, -{ 0x0074,0x1204,DICOM_T_UNK, _T("Procedure Step Label") }, -{ 0x0074,0x1210,DICOM_T_UNK, _T("Scheduled Processing Parameters Sequence") }, -{ 0x0074,0x1212,DICOM_T_UNK, _T("Performed Processing Parameters Sequence") }, -{ 0x0074,0x1216,DICOM_T_UNK, _T("Unified Procedure Step Performed Procedure Sequence") }, -{ 0x0074,0x1220,DICOM_T_UNK, _T("Related Procedure Step Sequence") }, -{ 0x0074,0x1222,DICOM_T_UNK, _T("Procedure Step Relationship Type") }, -{ 0x0074,0x1224,DICOM_T_UNK, _T("Replaced Procedure Step Sequence") }, -{ 0x0074,0x1230,DICOM_T_UNK, _T("Deletion Lock") }, -{ 0x0074,0x1234,DICOM_T_UNK, _T("Receiving AE") }, -{ 0x0074,0x1236,DICOM_T_UNK, _T("Requesting AE") }, -{ 0x0074,0x1238,DICOM_T_UNK, _T("Reason for Cancellation") }, -{ 0x0074,0x1242,DICOM_T_UNK, _T("SCP Status") }, -{ 0x0074,0x1244,DICOM_T_UNK, _T("Subscription List Status") }, -{ 0x0074,0x1246,DICOM_T_UNK, _T("Unified Procedure Step List Status") }, -{ 0x0074,0x1324,DICOM_T_UNK, _T("Beam Order Index") }, -{ 0x0074,0x1338,DICOM_T_UNK, _T("Double Exposure Meterset") }, -{ 0x0074,0x133A,DICOM_T_UNK, _T("Double Exposure Field Delta") }, -{ 0x0076,0x0001,DICOM_T_UNK, _T("Implant Assembly Template Name") }, -{ 0x0076,0x0003,DICOM_T_UNK, _T("Implant Assembly Template Issuer") }, -{ 0x0076,0x0006,DICOM_T_UNK, _T("Implant Assembly Template Version") }, -{ 0x0076,0x0008,DICOM_T_UNK, _T("Replaced Implant Assembly Template Sequence") }, -{ 0x0076,0x000A,DICOM_T_UNK, _T("Implant Assembly Template Type") }, -{ 0x0076,0x000C,DICOM_T_UNK, _T("Original Implant Assembly Template Sequence") }, -{ 0x0076,0x000E,DICOM_T_UNK, _T("Derivation Implant Assembly Template Sequence") }, -{ 0x0076,0x0010,DICOM_T_UNK, _T("Implant Assembly Template Target Anatomy Sequence") }, -{ 0x0076,0x0020,DICOM_T_UNK, _T("Procedure Type Code Sequence") }, -{ 0x0076,0x0030,DICOM_T_UNK, _T("Surgical Technique") }, -{ 0x0076,0x0032,DICOM_T_UNK, _T("Component Types Sequence") }, -{ 0x0076,0x0034,DICOM_T_UNK, _T("Component Type Code Sequence") }, -{ 0x0076,0x0036,DICOM_T_UNK, _T("Exclusive Component Type") }, -{ 0x0076,0x0038,DICOM_T_UNK, _T("Mandatory Component Type") }, -{ 0x0076,0x0040,DICOM_T_UNK, _T("Component Sequence") }, -{ 0x0076,0x0055,DICOM_T_UNK, _T("Component ID") }, -{ 0x0076,0x0060,DICOM_T_UNK, _T("Component Assembly Sequence") }, -{ 0x0076,0x0070,DICOM_T_UNK, _T("Component 1 Referenced ID") }, -{ 0x0076,0x0080,DICOM_T_UNK, _T("Component 1 Referenced Mating Feature Set ID") }, -{ 0x0076,0x0090,DICOM_T_UNK, _T("Component 1 Referenced Mating Feature ID") }, -{ 0x0076,0x00A0,DICOM_T_UNK, _T("Component 2 Referenced ID") }, -{ 0x0076,0x00B0,DICOM_T_UNK, _T("Component 2 Referenced Mating Feature Set ID") }, -{ 0x0076,0x00C0,DICOM_T_UNK, _T("Component 2 Referenced Mating Feature ID") }, -{ 0x0078,0x0001,DICOM_T_UNK, _T("Implant Template Group Name") }, -{ 0x0078,0x0010,DICOM_T_UNK, _T("Implant Template Group Description") }, -{ 0x0078,0x0020,DICOM_T_UNK, _T("Implant Template Group Issuer") }, -{ 0x0078,0x0024,DICOM_T_UNK, _T("Implant Template Group Version") }, -{ 0x0078,0x0026,DICOM_T_UNK, _T("Replaced Implant Template Group Sequence") }, -{ 0x0078,0x0028,DICOM_T_UNK, _T("Implant Template Group Target Anatomy Sequence") }, -{ 0x0078,0x002A,DICOM_T_UNK, _T("Implant Template Group Members Sequence") }, -{ 0x0078,0x002E,DICOM_T_UNK, _T("Implant Template Group Member ID") }, -{ 0x0078,0x0050,DICOM_T_UNK, _T("3D Implant Template Group Member Matching Point") }, -{ 0x0078,0x0060,DICOM_T_UNK, _T("3D Implant Template Group Member Matching Axes") }, -{ 0x0078,0x0070,DICOM_T_UNK, _T("Implant Template Group Member Matching 2D Coordinates Sequence") }, -{ 0x0078,0x0090,DICOM_T_UNK, _T("2D Implant Template Group Member Matching Point") }, -{ 0x0078,0x00A0,DICOM_T_UNK, _T("2D Implant Template Group Member Matching Axes") }, -{ 0x0078,0x00B0,DICOM_T_UNK, _T("Implant Template Group Variation Dimension Sequence") }, -{ 0x0078,0x00B2,DICOM_T_UNK, _T("Implant Template Group Variation Dimension Name") }, -{ 0x0078,0x00B4,DICOM_T_UNK, _T("Implant Template Group Variation Dimension Rank Sequence") }, -{ 0x0078,0x00B6,DICOM_T_UNK, _T("Referenced Implant Template Group Member ID") }, -{ 0x0078,0x00B8,DICOM_T_UNK, _T("Implant Template Group Variation Dimension Rank") }, -{ 0x0080,0x0001,DICOM_T_UNK, _T("Surface Scan Acquisition Type Code Sequence") }, -{ 0x0080,0x0002,DICOM_T_UNK, _T("Surface Scan Mode Code Sequence") }, -{ 0x0080,0x0003,DICOM_T_UNK, _T("Registration Method Code Sequence") }, -{ 0x0080,0x0004,DICOM_T_UNK, _T("Shot Duration Time") }, -{ 0x0080,0x0005,DICOM_T_UNK, _T("Shot Offset Time") }, -{ 0x0080,0x0006,DICOM_T_UNK, _T("Surface Point Presentation Value Data") }, -{ 0x0080,0x0007,DICOM_T_UNK, _T("Surface Point Color CIELab Value Data") }, -{ 0x0080,0x0008,DICOM_T_UNK, _T("UV Mapping Sequence") }, -{ 0x0080,0x0009,DICOM_T_UNK, _T("Texture Label") }, -{ 0x0080,0x0010,DICOM_T_UNK, _T("U Value Data") }, -{ 0x0080,0x0011,DICOM_T_UNK, _T("V Value Data") }, -{ 0x0080,0x0012,DICOM_T_UNK, _T("Referenced Texture Sequence") }, -{ 0x0080,0x0013,DICOM_T_UNK, _T("Referenced Surface Data Sequence") }, -{ 0x0088,0x0130,DICOM_T_UNK, _T("Storage Media File-set ID") }, -{ 0x0088,0x0140,DICOM_T_UNK, _T("Storage Media File-set UID") }, -{ 0x0088,0x0200,DICOM_T_UNK, _T("Icon Image Sequence") }, -{ 0x0088,0x0904,DICOM_T_UNK, _T("Topic Title") }, -{ 0x0088,0x0906,DICOM_T_UNK, _T("Topic Subject") }, -{ 0x0088,0x0910,DICOM_T_UNK, _T("Topic Author") }, -{ 0x0088,0x0912,DICOM_T_UNK, _T("Topic Keywords") }, -{ 0x0100,0x0410,DICOM_T_UNK, _T("SOP Instance Status") }, -{ 0x0100,0x0420,DICOM_T_UNK, _T("SOP Authorization DateTime") }, -{ 0x0100,0x0424,DICOM_T_UNK, _T("SOP Authorization Comment") }, -{ 0x0100,0x0426,DICOM_T_UNK, _T("Authorization Equipment Certification Number") }, -{ 0x0400,0x0005,DICOM_T_UNK, _T("MAC ID Number") }, -{ 0x0400,0x0010,DICOM_T_UNK, _T("MAC Calculation Transfer Syntax UID") }, -{ 0x0400,0x0015,DICOM_T_UNK, _T("MAC Algorithm") }, -{ 0x0400,0x0020,DICOM_T_UNK, _T("Data Elements Signed") }, -{ 0x0400,0x0100,DICOM_T_UNK, _T("Digital Signature UID") }, -{ 0x0400,0x0105,DICOM_T_UNK, _T("Digital Signature DateTime") }, -{ 0x0400,0x0110,DICOM_T_UNK, _T("Certificate Type") }, -{ 0x0400,0x0115,DICOM_T_UNK, _T("Certificate of Signer") }, -{ 0x0400,0x0120,DICOM_T_UNK, _T("Signature") }, -{ 0x0400,0x0305,DICOM_T_UNK, _T("Certified Timestamp Type") }, -{ 0x0400,0x0310,DICOM_T_UNK, _T("Certified Timestamp") }, -{ 0x0400,0x0401,DICOM_T_UNK, _T("Digital Signature Purpose Code Sequence") }, -{ 0x0400,0x0402,DICOM_T_UNK, _T("Referenced Digital Signature Sequence") }, -{ 0x0400,0x0403,DICOM_T_UNK, _T("Referenced SOP Instance MAC Sequence") }, -{ 0x0400,0x0404,DICOM_T_UNK, _T("MAC") }, -{ 0x0400,0x0500,DICOM_T_UNK, _T("Encrypted Attributes Sequence") }, -{ 0x0400,0x0510,DICOM_T_UNK, _T("Encrypted Content Transfer Syntax UID") }, -{ 0x0400,0x0520,DICOM_T_UNK, _T("Encrypted Content") }, -{ 0x0400,0x0550,DICOM_T_UNK, _T("Modified Attributes Sequence") }, -{ 0x0400,0x0561,DICOM_T_UNK, _T("Original Attributes Sequence") }, -{ 0x0400,0x0562,DICOM_T_UNK, _T("Attribute Modification DateTime") }, -{ 0x0400,0x0563,DICOM_T_UNK, _T("Modifying System") }, -{ 0x0400,0x0564,DICOM_T_UNK, _T("Source of Previous Values") }, -{ 0x0400,0x0565,DICOM_T_UNK, _T("Reason for the Attribute Modification") }, -/* -{ 0x1000,0xxxx0,DICOM_T_UNK, _T("Escape Triplet") }, -{ 0x1000,0xxxx1,DICOM_T_UNK, _T("Run Length Triplet") }, -{ 0x1000,0xxxx2,DICOM_T_UNK, _T("Huffman Table Size") }, -{ 0x1000,0xxxx3,DICOM_T_UNK, _T("Huffman Table Triplet") }, -{ 0x1000,0xxxx4,DICOM_T_UNK, _T("Shift Table Size") }, -{ 0x1000,0xxxx5,DICOM_T_UNK, _T("Shift Table Triplet") }, -{ 0x1010,0xxxxx,DICOM_T_UNK, _T("Zonal Map") }, -*/ -{ 0x2000,0x0010,DICOM_T_UNK, _T("Number of Copies") }, -{ 0x2000,0x001E,DICOM_T_UNK, _T("Printer Configuration Sequence") }, -{ 0x2000,0x0020,DICOM_T_UNK, _T("Print Priority") }, -{ 0x2000,0x0030,DICOM_T_UNK, _T("Medium Type") }, -{ 0x2000,0x0040,DICOM_T_UNK, _T("Film Destination") }, -{ 0x2000,0x0050,DICOM_T_UNK, _T("Film Session Label") }, -{ 0x2000,0x0060,DICOM_T_UNK, _T("Memory Allocation") }, -{ 0x2000,0x0061,DICOM_T_UNK, _T("Maximum Memory Allocation") }, -{ 0x2000,0x0062,DICOM_T_UNK, _T("Color Image Printing Flag") }, -{ 0x2000,0x0063,DICOM_T_UNK, _T("Collation Flag") }, -{ 0x2000,0x0065,DICOM_T_UNK, _T("Annotation Flag") }, -{ 0x2000,0x0067,DICOM_T_UNK, _T("Image Overlay Flag") }, -{ 0x2000,0x0069,DICOM_T_UNK, _T("Presentation LUT Flag") }, -{ 0x2000,0x006A,DICOM_T_UNK, _T("Image Box Presentation LUT Flag") }, -{ 0x2000,0x00A0,DICOM_T_UNK, _T("Memory Bit Depth") }, -{ 0x2000,0x00A1,DICOM_T_UNK, _T("Printing Bit Depth") }, -{ 0x2000,0x00A2,DICOM_T_UNK, _T("Media Installed Sequence") }, -{ 0x2000,0x00A4,DICOM_T_UNK, _T("Other Media Available Sequence") }, -{ 0x2000,0x00A8,DICOM_T_UNK, _T("Supported Image Display Formats Sequence") }, -{ 0x2000,0x0500,DICOM_T_UNK, _T("Referenced Film Box Sequence") }, -{ 0x2000,0x0510,DICOM_T_UNK, _T("Referenced Stored Print Sequence") }, -{ 0x2010,0x0010,DICOM_T_UNK, _T("Image Display Format") }, -{ 0x2010,0x0030,DICOM_T_UNK, _T("Annotation Display Format ID") }, -{ 0x2010,0x0040,DICOM_T_UNK, _T("Film Orientation") }, -{ 0x2010,0x0050,DICOM_T_UNK, _T("Film Size ID") }, -{ 0x2010,0x0052,DICOM_T_UNK, _T("Printer Resolution ID") }, -{ 0x2010,0x0054,DICOM_T_UNK, _T("Default Printer Resolution ID") }, -{ 0x2010,0x0060,DICOM_T_UNK, _T("Magnification Type") }, -{ 0x2010,0x0080,DICOM_T_UNK, _T("Smoothing Type") }, -{ 0x2010,0x00A6,DICOM_T_UNK, _T("Default Magnification Type") }, -{ 0x2010,0x00A7,DICOM_T_UNK, _T("Other Magnification Types Available") }, -{ 0x2010,0x00A8,DICOM_T_UNK, _T("Default Smoothing Type") }, -{ 0x2010,0x00A9,DICOM_T_UNK, _T("Other Smoothing Types Available") }, -{ 0x2010,0x0100,DICOM_T_UNK, _T("Border Density") }, -{ 0x2010,0x0110,DICOM_T_UNK, _T("Empty Image Density") }, -{ 0x2010,0x0120,DICOM_T_UNK, _T("Min Density") }, -{ 0x2010,0x0130,DICOM_T_UNK, _T("Max Density") }, -{ 0x2010,0x0140,DICOM_T_UNK, _T("Trim") }, -{ 0x2010,0x0150,DICOM_T_UNK, _T("Configuration Information") }, -{ 0x2010,0x0152,DICOM_T_UNK, _T("Configuration Information Description") }, -{ 0x2010,0x0154,DICOM_T_UNK, _T("Maximum Collated Films") }, -{ 0x2010,0x015E,DICOM_T_UNK, _T("Illumination") }, -{ 0x2010,0x0160,DICOM_T_UNK, _T("Reflected Ambient Light") }, -{ 0x2010,0x0376,DICOM_T_UNK, _T("Printer Pixel Spacing") }, -{ 0x2010,0x0500,DICOM_T_UNK, _T("Referenced Film Session Sequence") }, -{ 0x2010,0x0510,DICOM_T_UNK, _T("Referenced Image Box Sequence") }, -{ 0x2010,0x0520,DICOM_T_UNK, _T("Referenced Basic Annotation Box Sequence") }, -{ 0x2020,0x0010,DICOM_T_UNK, _T("Image Box Position") }, -{ 0x2020,0x0020,DICOM_T_UNK, _T("Polarity") }, -{ 0x2020,0x0030,DICOM_T_UNK, _T("Requested Image Size") }, -{ 0x2020,0x0040,DICOM_T_UNK, _T("Requested Decimate/Crop Behavior") }, -{ 0x2020,0x0050,DICOM_T_UNK, _T("Requested Resolution ID") }, -{ 0x2020,0x00A0,DICOM_T_UNK, _T("Requested Image Size Flag") }, -{ 0x2020,0x00A2,DICOM_T_UNK, _T("Decimate/Crop Result") }, -{ 0x2020,0x0110,DICOM_T_UNK, _T("Basic Grayscale Image Sequence") }, -{ 0x2020,0x0111,DICOM_T_UNK, _T("Basic Color Image Sequence") }, -{ 0x2020,0x0130,DICOM_T_UNK, _T("Referenced Image Overlay Box Sequence") }, -{ 0x2020,0x0140,DICOM_T_UNK, _T("Referenced VOI LUT Box Sequence") }, -{ 0x2030,0x0010,DICOM_T_UNK, _T("Annotation Position") }, -{ 0x2030,0x0020,DICOM_T_UNK, _T("Text String") }, -{ 0x2040,0x0010,DICOM_T_UNK, _T("Referenced Overlay Plane Sequence") }, -{ 0x2040,0x0011,DICOM_T_UNK, _T("Referenced Overlay Plane Groups") }, -{ 0x2040,0x0020,DICOM_T_UNK, _T("Overlay Pixel Data Sequence") }, -{ 0x2040,0x0060,DICOM_T_UNK, _T("Overlay Magnification Type") }, -{ 0x2040,0x0070,DICOM_T_UNK, _T("Overlay Smoothing Type") }, -{ 0x2040,0x0072,DICOM_T_UNK, _T("Overlay or Image Magnification") }, -{ 0x2040,0x0074,DICOM_T_UNK, _T("Magnify to Number of Columns") }, -{ 0x2040,0x0080,DICOM_T_UNK, _T("Overlay Foreground Density") }, -{ 0x2040,0x0082,DICOM_T_UNK, _T("Overlay Background Density") }, -{ 0x2040,0x0090,DICOM_T_UNK, _T("Overlay Mode") }, -{ 0x2040,0x0100,DICOM_T_UNK, _T("Threshold Density") }, -{ 0x2040,0x0500,DICOM_T_UNK, _T("Referenced Image Box Sequence (Retired)") }, -{ 0x2050,0x0010,DICOM_T_UNK, _T("Presentation LUT Sequence") }, -{ 0x2050,0x0020,DICOM_T_UNK, _T("Presentation LUT Shape") }, -{ 0x2050,0x0500,DICOM_T_UNK, _T("Referenced Presentation LUT Sequence") }, -{ 0x2100,0x0010,DICOM_T_UNK, _T("Print Job ID") }, -{ 0x2100,0x0020,DICOM_T_UNK, _T("Execution Status") }, -{ 0x2100,0x0030,DICOM_T_UNK, _T("Execution Status Info") }, -{ 0x2100,0x0040,DICOM_T_UNK, _T("Creation Date") }, -{ 0x2100,0x0050,DICOM_T_UNK, _T("Creation Time") }, -{ 0x2100,0x0070,DICOM_T_UNK, _T("Originator") }, -{ 0x2100,0x0140,DICOM_T_UNK, _T("Destination AE") }, -{ 0x2100,0x0160,DICOM_T_UNK, _T("Owner ID") }, -{ 0x2100,0x0170,DICOM_T_UNK, _T("Number of Films") }, -{ 0x2100,0x0500,DICOM_T_UNK, _T("Referenced Print Job Sequence (Pull Stored Print)") }, -{ 0x2110,0x0010,DICOM_T_UNK, _T("Printer Status") }, -{ 0x2110,0x0020,DICOM_T_UNK, _T("Printer Status Info") }, -{ 0x2110,0x0030,DICOM_T_UNK, _T("Printer Name") }, -{ 0x2110,0x0099,DICOM_T_UNK, _T("Print Queue ID") }, -{ 0x2120,0x0010,DICOM_T_UNK, _T("Queue Status") }, -{ 0x2120,0x0050,DICOM_T_UNK, _T("Print Job Description Sequence") }, -{ 0x2120,0x0070,DICOM_T_UNK, _T("Referenced Print Job Sequence") }, -{ 0x2130,0x0010,DICOM_T_UNK, _T("Print Management Capabilities Sequence") }, -{ 0x2130,0x0015,DICOM_T_UNK, _T("Printer Characteristics Sequence") }, -{ 0x2130,0x0030,DICOM_T_UNK, _T("Film Box Content Sequence") }, -{ 0x2130,0x0040,DICOM_T_UNK, _T("Image Box Content Sequence") }, -{ 0x2130,0x0050,DICOM_T_UNK, _T("Annotation Content Sequence") }, -{ 0x2130,0x0060,DICOM_T_UNK, _T("Image Overlay Box Content Sequence") }, -{ 0x2130,0x0080,DICOM_T_UNK, _T("Presentation LUT Content Sequence") }, -{ 0x2130,0x00A0,DICOM_T_UNK, _T("Proposed Study Sequence") }, -{ 0x2130,0x00C0,DICOM_T_UNK, _T("Original Image Sequence") }, -{ 0x2200,0x0001,DICOM_T_UNK, _T("Label Using Information Extracted From Instances") }, -{ 0x2200,0x0002,DICOM_T_UNK, _T("Label Text") }, -{ 0x2200,0x0003,DICOM_T_UNK, _T("Label Style Selection") }, -{ 0x2200,0x0004,DICOM_T_UNK, _T("Media Disposition") }, -{ 0x2200,0x0005,DICOM_T_UNK, _T("Barcode Value") }, -{ 0x2200,0x0006,DICOM_T_UNK, _T("Barcode Symbology") }, -{ 0x2200,0x0007,DICOM_T_UNK, _T("Allow Media Splitting") }, -{ 0x2200,0x0008,DICOM_T_UNK, _T("Include Non-DICOM Objects") }, -{ 0x2200,0x0009,DICOM_T_UNK, _T("Include Display Application") }, -{ 0x2200,0x000A,DICOM_T_UNK, _T("Preserve Composite Instances After Media Creation") }, -{ 0x2200,0x000B,DICOM_T_UNK, _T("Total Number of Pieces of Media Created") }, -{ 0x2200,0x000C,DICOM_T_UNK, _T("Requested Media Application Profile") }, -{ 0x2200,0x000D,DICOM_T_UNK, _T("Referenced Storage Media Sequence") }, -{ 0x2200,0x000E,DICOM_T_UNK, _T("Failure Attributes") }, -{ 0x2200,0x000F,DICOM_T_UNK, _T("Allow Lossy Compression") }, -{ 0x2200,0x0020,DICOM_T_UNK, _T("Request Priority") }, -{ 0x3002,0x0002,DICOM_T_UNK, _T("RT Image Label") }, -{ 0x3002,0x0003,DICOM_T_UNK, _T("RT Image Name") }, -{ 0x3002,0x0004,DICOM_T_UNK, _T("RT Image Description") }, -{ 0x3002,0x000A,DICOM_T_UNK, _T("Reported Values Origin") }, -{ 0x3002,0x000C,DICOM_T_UNK, _T("RT Image Plane") }, -{ 0x3002,0x000D,DICOM_T_UNK, _T("X-Ray Image Receptor Translation") }, -{ 0x3002,0x000E,DICOM_T_UNK, _T("X-Ray Image Receptor Angle") }, -{ 0x3002,0x0010,DICOM_T_UNK, _T("RT Image Orientation") }, -{ 0x3002,0x0011,DICOM_T_UNK, _T("Image Plane Pixel Spacing") }, -{ 0x3002,0x0012,DICOM_T_UNK, _T("RT Image Position") }, -{ 0x3002,0x0020,DICOM_T_UNK, _T("Radiation Machine Name") }, -{ 0x3002,0x0022,DICOM_T_UNK, _T("Radiation Machine SAD") }, -{ 0x3002,0x0024,DICOM_T_UNK, _T("Radiation Machine SSD") }, -{ 0x3002,0x0026,DICOM_T_UNK, _T("RT Image SID") }, -{ 0x3002,0x0028,DICOM_T_UNK, _T("Source to Reference Object Distance") }, -{ 0x3002,0x0029,DICOM_T_UNK, _T("Fraction Number") }, -{ 0x3002,0x0030,DICOM_T_UNK, _T("Exposure Sequence") }, -{ 0x3002,0x0032,DICOM_T_UNK, _T("Meterset Exposure") }, -{ 0x3002,0x0034,DICOM_T_UNK, _T("Diaphragm Position") }, -{ 0x3002,0x0040,DICOM_T_UNK, _T("Fluence Map Sequence") }, -{ 0x3002,0x0041,DICOM_T_UNK, _T("Fluence Data Source") }, -{ 0x3002,0x0042,DICOM_T_UNK, _T("Fluence Data Scale") }, -{ 0x3002,0x0050,DICOM_T_UNK, _T("Primary Fluence Mode Sequence") }, -{ 0x3002,0x0051,DICOM_T_UNK, _T("Fluence Mode") }, -{ 0x3002,0x0052,DICOM_T_UNK, _T("Fluence Mode ID") }, -{ 0x3004,0x0001,DICOM_T_UNK, _T("DVH Type") }, -{ 0x3004,0x0002,DICOM_T_UNK, _T("Dose Units") }, -{ 0x3004,0x0004,DICOM_T_UNK, _T("Dose Type") }, -{ 0x3004,0x0005,DICOM_T_UNK, _T("Spatial Transform of Dose") }, -{ 0x3004,0x0006,DICOM_T_UNK, _T("Dose Comment") }, -{ 0x3004,0x0008,DICOM_T_UNK, _T("Normalization Point") }, -{ 0x3004,0x000A,DICOM_T_UNK, _T("Dose Summation Type") }, -{ 0x3004,0x000C,DICOM_T_UNK, _T("Grid Frame Offset Vector") }, -{ 0x3004,0x000E,DICOM_T_UNK, _T("Dose Grid Scaling") }, -{ 0x3004,0x0010,DICOM_T_UNK, _T("RT Dose ROI Sequence") }, -{ 0x3004,0x0012,DICOM_T_UNK, _T("Dose Value") }, -{ 0x3004,0x0014,DICOM_T_UNK, _T("Tissue Heterogeneity Correction") }, -{ 0x3004,0x0040,DICOM_T_UNK, _T("DVH Normalization Point") }, -{ 0x3004,0x0042,DICOM_T_UNK, _T("DVH Normalization Dose Value") }, -{ 0x3004,0x0050,DICOM_T_UNK, _T("DVH Sequence") }, -{ 0x3004,0x0052,DICOM_T_UNK, _T("DVH Dose Scaling") }, -{ 0x3004,0x0054,DICOM_T_UNK, _T("DVH Volume Units") }, -{ 0x3004,0x0056,DICOM_T_UNK, _T("DVH Number of Bins") }, -{ 0x3004,0x0058,DICOM_T_UNK, _T("DVH Data") }, -{ 0x3004,0x0060,DICOM_T_UNK, _T("DVH Referenced ROI Sequence") }, -{ 0x3004,0x0062,DICOM_T_UNK, _T("DVH ROI Contribution Type") }, -{ 0x3004,0x0070,DICOM_T_UNK, _T("DVH Minimum Dose") }, -{ 0x3004,0x0072,DICOM_T_UNK, _T("DVH Maximum Dose") }, -{ 0x3004,0x0074,DICOM_T_UNK, _T("DVH Mean Dose") }, -{ 0x3006,0x0002,DICOM_T_UNK, _T("Structure Set Label") }, -{ 0x3006,0x0004,DICOM_T_UNK, _T("Structure Set Name") }, -{ 0x3006,0x0006,DICOM_T_UNK, _T("Structure Set Description") }, -{ 0x3006,0x0008,DICOM_T_UNK, _T("Structure Set Date") }, -{ 0x3006,0x0009,DICOM_T_UNK, _T("Structure Set Time") }, -{ 0x3006,0x0010,DICOM_T_UNK, _T("Referenced Frame of Reference Sequence") }, -{ 0x3006,0x0012,DICOM_T_UNK, _T("RT Referenced Study Sequence") }, -{ 0x3006,0x0014,DICOM_T_UNK, _T("RT Referenced Series Sequence") }, -{ 0x3006,0x0016,DICOM_T_UNK, _T("Contour Image Sequence") }, -{ 0x3006,0x0018,DICOM_T_UNK, _T("Predecessor Structure Set Sequence") }, -{ 0x3006,0x0020,DICOM_T_UNK, _T("Structure Set ROI Sequence") }, -{ 0x3006,0x0022,DICOM_T_UNK, _T("ROI Number") }, -{ 0x3006,0x0024,DICOM_T_UNK, _T("Referenced Frame of Reference UID") }, -{ 0x3006,0x0026,DICOM_T_UNK, _T("ROI Name") }, -{ 0x3006,0x0028,DICOM_T_UNK, _T("ROI Description") }, -{ 0x3006,0x002A,DICOM_T_UNK, _T("ROI Display Color") }, -{ 0x3006,0x002C,DICOM_T_UNK, _T("ROI Volume") }, -{ 0x3006,0x0030,DICOM_T_UNK, _T("RT Related ROI Sequence") }, -{ 0x3006,0x0033,DICOM_T_UNK, _T("RT ROI Relationship") }, -{ 0x3006,0x0036,DICOM_T_UNK, _T("ROI Generation Algorithm") }, -{ 0x3006,0x0038,DICOM_T_UNK, _T("ROI Generation Description") }, -{ 0x3006,0x0039,DICOM_T_UNK, _T("ROI Contour Sequence") }, -{ 0x3006,0x0040,DICOM_T_UNK, _T("Contour Sequence") }, -{ 0x3006,0x0042,DICOM_T_UNK, _T("Contour Geometric Type") }, -{ 0x3006,0x0044,DICOM_T_UNK, _T("Contour Slab Thickness") }, -{ 0x3006,0x0045,DICOM_T_UNK, _T("Contour Offset Vector") }, -{ 0x3006,0x0046,DICOM_T_UNK, _T("Number of Contour Points") }, -{ 0x3006,0x0048,DICOM_T_UNK, _T("Contour Number") }, -{ 0x3006,0x0049,DICOM_T_UNK, _T("Attached Contours") }, -{ 0x3006,0x0050,DICOM_T_UNK, _T("Contour Data") }, -{ 0x3006,0x0080,DICOM_T_UNK, _T("RT ROI Observations Sequence") }, -{ 0x3006,0x0082,DICOM_T_UNK, _T("Observation Number") }, -{ 0x3006,0x0084,DICOM_T_UNK, _T("Referenced ROI Number") }, -{ 0x3006,0x0085,DICOM_T_UNK, _T("ROI Observation Label") }, -{ 0x3006,0x0086,DICOM_T_UNK, _T("RT ROI Identification Code Sequence") }, -{ 0x3006,0x0088,DICOM_T_UNK, _T("ROI Observation Description") }, -{ 0x3006,0x00A0,DICOM_T_UNK, _T("Related RT ROI Observations Sequence") }, -{ 0x3006,0x00A4,DICOM_T_UNK, _T("RT ROI Interpreted Type") }, -{ 0x3006,0x00A6,DICOM_T_UNK, _T("ROI Interpreter") }, -{ 0x3006,0x00B0,DICOM_T_UNK, _T("ROI Physical Properties Sequence") }, -{ 0x3006,0x00B2,DICOM_T_UNK, _T("ROI Physical Property") }, -{ 0x3006,0x00B4,DICOM_T_UNK, _T("ROI Physical Property Value") }, -{ 0x3006,0x00B6,DICOM_T_UNK, _T("ROI Elemental Composition Sequence") }, -{ 0x3006,0x00B7,DICOM_T_UNK, _T("ROI Elemental Composition Atomic Number") }, -{ 0x3006,0x00B8,DICOM_T_UNK, _T("ROI Elemental Composition Atomic Mass Fraction") }, -{ 0x3006,0x00B9,DICOM_T_UNK, _T("Additional RT ROI Identification Code Sequence") }, -{ 0x3006,0x00C0,DICOM_T_UNK, _T("Frame of Reference Relationship Sequence") }, -{ 0x3006,0x00C2,DICOM_T_UNK, _T("Related Frame of Reference UID") }, -{ 0x3006,0x00C4,DICOM_T_UNK, _T("Frame of Reference Transformation Type") }, -{ 0x3006,0x00C6,DICOM_T_UNK, _T("Frame of Reference Transformation Matrix") }, -{ 0x3006,0x00C8,DICOM_T_UNK, _T("Frame of Reference Transformation Comment") }, -{ 0x3008,0x0010,DICOM_T_UNK, _T("Measured Dose Reference Sequence") }, -{ 0x3008,0x0012,DICOM_T_UNK, _T("Measured Dose Description") }, -{ 0x3008,0x0014,DICOM_T_UNK, _T("Measured Dose Type") }, -{ 0x3008,0x0016,DICOM_T_UNK, _T("Measured Dose Value") }, -{ 0x3008,0x0020,DICOM_T_UNK, _T("Treatment Session Beam Sequence") }, -{ 0x3008,0x0021,DICOM_T_UNK, _T("Treatment Session Ion Beam Sequence") }, -{ 0x3008,0x0022,DICOM_T_UNK, _T("Current Fraction Number") }, -{ 0x3008,0x0024,DICOM_T_UNK, _T("Treatment Control Point Date") }, -{ 0x3008,0x0025,DICOM_T_UNK, _T("Treatment Control Point Time") }, -{ 0x3008,0x002A,DICOM_T_UNK, _T("Treatment Termination Status") }, -{ 0x3008,0x002B,DICOM_T_UNK, _T("Treatment Termination Code") }, -{ 0x3008,0x002C,DICOM_T_UNK, _T("Treatment Verification Status") }, -{ 0x3008,0x0030,DICOM_T_UNK, _T("Referenced Treatment Record Sequence") }, -{ 0x3008,0x0032,DICOM_T_UNK, _T("Specified Primary Meterset") }, -{ 0x3008,0x0033,DICOM_T_UNK, _T("Specified Secondary Meterset") }, -{ 0x3008,0x0036,DICOM_T_UNK, _T("Delivered Primary Meterset") }, -{ 0x3008,0x0037,DICOM_T_UNK, _T("Delivered Secondary Meterset") }, -{ 0x3008,0x003A,DICOM_T_UNK, _T("Specified Treatment Time") }, -{ 0x3008,0x003B,DICOM_T_UNK, _T("Delivered Treatment Time") }, -{ 0x3008,0x0040,DICOM_T_UNK, _T("Control Point Delivery Sequence") }, -{ 0x3008,0x0041,DICOM_T_UNK, _T("Ion Control Point Delivery Sequence") }, -{ 0x3008,0x0042,DICOM_T_UNK, _T("Specified Meterset") }, -{ 0x3008,0x0044,DICOM_T_UNK, _T("Delivered Meterset") }, -{ 0x3008,0x0045,DICOM_T_UNK, _T("Meterset Rate Set") }, -{ 0x3008,0x0046,DICOM_T_UNK, _T("Meterset Rate Delivered") }, -{ 0x3008,0x0047,DICOM_T_UNK, _T("Scan Spot Metersets Delivered") }, -{ 0x3008,0x0048,DICOM_T_UNK, _T("Dose Rate Delivered") }, -{ 0x3008,0x0050,DICOM_T_UNK, _T("Treatment Summary Calculated Dose Reference Sequence") }, -{ 0x3008,0x0052,DICOM_T_UNK, _T("Cumulative Dose to Dose Reference") }, -{ 0x3008,0x0054,DICOM_T_UNK, _T("First Treatment Date") }, -{ 0x3008,0x0056,DICOM_T_UNK, _T("Most Recent Treatment Date") }, -{ 0x3008,0x005A,DICOM_T_UNK, _T("Number of Fractions Delivered") }, -{ 0x3008,0x0060,DICOM_T_UNK, _T("Override Sequence") }, -{ 0x3008,0x0061,DICOM_T_UNK, _T("Parameter Sequence Pointer") }, -{ 0x3008,0x0062,DICOM_T_UNK, _T("Override Parameter Pointer") }, -{ 0x3008,0x0063,DICOM_T_UNK, _T("Parameter Item Index") }, -{ 0x3008,0x0064,DICOM_T_UNK, _T("Measured Dose Reference Number") }, -{ 0x3008,0x0065,DICOM_T_UNK, _T("Parameter Pointer") }, -{ 0x3008,0x0066,DICOM_T_UNK, _T("Override Reason") }, -{ 0x3008,0x0068,DICOM_T_UNK, _T("Corrected Parameter Sequence") }, -{ 0x3008,0x006A,DICOM_T_UNK, _T("Correction Value") }, -{ 0x3008,0x0070,DICOM_T_UNK, _T("Calculated Dose Reference Sequence") }, -{ 0x3008,0x0072,DICOM_T_UNK, _T("Calculated Dose Reference Number") }, -{ 0x3008,0x0074,DICOM_T_UNK, _T("Calculated Dose Reference Description") }, -{ 0x3008,0x0076,DICOM_T_UNK, _T("Calculated Dose Reference Dose Value") }, -{ 0x3008,0x0078,DICOM_T_UNK, _T("Start Meterset") }, -{ 0x3008,0x007A,DICOM_T_UNK, _T("End Meterset") }, -{ 0x3008,0x0080,DICOM_T_UNK, _T("Referenced Measured Dose Reference Sequence") }, -{ 0x3008,0x0082,DICOM_T_UNK, _T("Referenced Measured Dose Reference Number") }, -{ 0x3008,0x0090,DICOM_T_UNK, _T("Referenced Calculated Dose Reference Sequence") }, -{ 0x3008,0x0092,DICOM_T_UNK, _T("Referenced Calculated Dose Reference Number") }, -{ 0x3008,0x00A0,DICOM_T_UNK, _T("Beam Limiting Device Leaf Pairs Sequence") }, -{ 0x3008,0x00B0,DICOM_T_UNK, _T("Recorded Wedge Sequence") }, -{ 0x3008,0x00C0,DICOM_T_UNK, _T("Recorded Compensator Sequence") }, -{ 0x3008,0x00D0,DICOM_T_UNK, _T("Recorded Block Sequence") }, -{ 0x3008,0x00E0,DICOM_T_UNK, _T("Treatment Summary Measured Dose Reference Sequence") }, -{ 0x3008,0x00F0,DICOM_T_UNK, _T("Recorded Snout Sequence") }, -{ 0x3008,0x00F2,DICOM_T_UNK, _T("Recorded Range Shifter Sequence") }, -{ 0x3008,0x00F4,DICOM_T_UNK, _T("Recorded Lateral Spreading Device Sequence") }, -{ 0x3008,0x00F6,DICOM_T_UNK, _T("Recorded Range Modulator Sequence") }, -{ 0x3008,0x0100,DICOM_T_UNK, _T("Recorded Source Sequence") }, -{ 0x3008,0x0105,DICOM_T_UNK, _T("Source Serial Number") }, -{ 0x3008,0x0110,DICOM_T_UNK, _T("Treatment Session Application Setup Sequence") }, -{ 0x3008,0x0116,DICOM_T_UNK, _T("Application Setup Check") }, -{ 0x3008,0x0120,DICOM_T_UNK, _T("Recorded Brachy Accessory Device Sequence") }, -{ 0x3008,0x0122,DICOM_T_UNK, _T("Referenced Brachy Accessory Device Number") }, -{ 0x3008,0x0130,DICOM_T_UNK, _T("Recorded Channel Sequence") }, -{ 0x3008,0x0132,DICOM_T_UNK, _T("Specified Channel Total Time") }, -{ 0x3008,0x0134,DICOM_T_UNK, _T("Delivered Channel Total Time") }, -{ 0x3008,0x0136,DICOM_T_UNK, _T("Specified Number of Pulses") }, -{ 0x3008,0x0138,DICOM_T_UNK, _T("Delivered Number of Pulses") }, -{ 0x3008,0x013A,DICOM_T_UNK, _T("Specified Pulse Repetition Interval") }, -{ 0x3008,0x013C,DICOM_T_UNK, _T("Delivered Pulse Repetition Interval") }, -{ 0x3008,0x0140,DICOM_T_UNK, _T("Recorded Source Applicator Sequence") }, -{ 0x3008,0x0142,DICOM_T_UNK, _T("Referenced Source Applicator Number") }, -{ 0x3008,0x0150,DICOM_T_UNK, _T("Recorded Channel Shield Sequence") }, -{ 0x3008,0x0152,DICOM_T_UNK, _T("Referenced Channel Shield Number") }, -{ 0x3008,0x0160,DICOM_T_UNK, _T("Brachy Control Point Delivered Sequence") }, -{ 0x3008,0x0162,DICOM_T_UNK, _T("Safe Position Exit Date") }, -{ 0x3008,0x0164,DICOM_T_UNK, _T("Safe Position Exit Time") }, -{ 0x3008,0x0166,DICOM_T_UNK, _T("Safe Position Return Date") }, -{ 0x3008,0x0168,DICOM_T_UNK, _T("Safe Position Return Time") }, -{ 0x3008,0x0171,DICOM_T_UNK, _T("Pulse Specific Brachy Control Point Delivered Sequence") }, -{ 0x3008,0x0172,DICOM_T_UNK, _T("Pulse Number") }, -{ 0x3008,0x0173,DICOM_T_UNK, _T("Brachy Pulse Control Point Delivered Sequence") }, -{ 0x3008,0x0200,DICOM_T_UNK, _T("Current Treatment Status") }, -{ 0x3008,0x0202,DICOM_T_UNK, _T("Treatment Status Comment") }, -{ 0x3008,0x0220,DICOM_T_UNK, _T("Fraction Group Summary Sequence") }, -{ 0x3008,0x0223,DICOM_T_UNK, _T("Referenced Fraction Number") }, -{ 0x3008,0x0224,DICOM_T_UNK, _T("Fraction Group Type") }, -{ 0x3008,0x0230,DICOM_T_UNK, _T("Beam Stopper Position") }, -{ 0x3008,0x0240,DICOM_T_UNK, _T("Fraction Status Summary Sequence") }, -{ 0x3008,0x0250,DICOM_T_UNK, _T("Treatment Date") }, -{ 0x3008,0x0251,DICOM_T_UNK, _T("Treatment Time") }, -{ 0x300A,0x0002,DICOM_T_UNK, _T("RT Plan Label") }, -{ 0x300A,0x0003,DICOM_T_UNK, _T("RT Plan Name") }, -{ 0x300A,0x0004,DICOM_T_UNK, _T("RT Plan Description") }, -{ 0x300A,0x0006,DICOM_T_UNK, _T("RT Plan Date") }, -{ 0x300A,0x0007,DICOM_T_UNK, _T("RT Plan Time") }, -{ 0x300A,0x0009,DICOM_T_UNK, _T("Treatment Protocols") }, -{ 0x300A,0x000A,DICOM_T_UNK, _T("Plan Intent") }, -{ 0x300A,0x000B,DICOM_T_UNK, _T("Treatment Sites") }, -{ 0x300A,0x000C,DICOM_T_UNK, _T("RT Plan Geometry") }, -{ 0x300A,0x000E,DICOM_T_UNK, _T("Prescription Description") }, -{ 0x300A,0x0010,DICOM_T_UNK, _T("Dose Reference Sequence") }, -{ 0x300A,0x0012,DICOM_T_UNK, _T("Dose Reference Number") }, -{ 0x300A,0x0013,DICOM_T_UNK, _T("Dose Reference UID") }, -{ 0x300A,0x0014,DICOM_T_UNK, _T("Dose Reference Structure Type") }, -{ 0x300A,0x0015,DICOM_T_UNK, _T("Nominal Beam Energy Unit") }, -{ 0x300A,0x0016,DICOM_T_UNK, _T("Dose Reference Description") }, -{ 0x300A,0x0018,DICOM_T_UNK, _T("Dose Reference Point Coordinates") }, -{ 0x300A,0x001A,DICOM_T_UNK, _T("Nominal Prior Dose") }, -{ 0x300A,0x0020,DICOM_T_UNK, _T("Dose Reference Type") }, -{ 0x300A,0x0021,DICOM_T_UNK, _T("Constraint Weight") }, -{ 0x300A,0x0022,DICOM_T_UNK, _T("Delivery Warning Dose") }, -{ 0x300A,0x0023,DICOM_T_UNK, _T("Delivery Maximum Dose") }, -{ 0x300A,0x0025,DICOM_T_UNK, _T("Target Minimum Dose") }, -{ 0x300A,0x0026,DICOM_T_UNK, _T("Target Prescription Dose") }, -{ 0x300A,0x0027,DICOM_T_UNK, _T("Target Maximum Dose") }, -{ 0x300A,0x0028,DICOM_T_UNK, _T("Target Underdose Volume Fraction") }, -{ 0x300A,0x002A,DICOM_T_UNK, _T("Organ at Risk Full-volume Dose") }, -{ 0x300A,0x002B,DICOM_T_UNK, _T("Organ at Risk Limit Dose") }, -{ 0x300A,0x002C,DICOM_T_UNK, _T("Organ at Risk Maximum Dose") }, -{ 0x300A,0x002D,DICOM_T_UNK, _T("Organ at Risk Overdose Volume Fraction") }, -{ 0x300A,0x0040,DICOM_T_UNK, _T("Tolerance Table Sequence") }, -{ 0x300A,0x0042,DICOM_T_UNK, _T("Tolerance Table Number") }, -{ 0x300A,0x0043,DICOM_T_UNK, _T("Tolerance Table Label") }, -{ 0x300A,0x0044,DICOM_T_UNK, _T("Gantry Angle Tolerance") }, -{ 0x300A,0x0046,DICOM_T_UNK, _T("Beam Limiting Device Angle Tolerance") }, -{ 0x300A,0x0048,DICOM_T_UNK, _T("Beam Limiting Device Tolerance Sequence") }, -{ 0x300A,0x004A,DICOM_T_UNK, _T("Beam Limiting Device Position Tolerance") }, -{ 0x300A,0x004B,DICOM_T_UNK, _T("Snout Position Tolerance") }, -{ 0x300A,0x004C,DICOM_T_UNK, _T("Patient Support Angle Tolerance") }, -{ 0x300A,0x004E,DICOM_T_UNK, _T("Table Top Eccentric Angle Tolerance") }, -{ 0x300A,0x004F,DICOM_T_UNK, _T("Table Top Pitch Angle Tolerance") }, -{ 0x300A,0x0050,DICOM_T_UNK, _T("Table Top Roll Angle Tolerance") }, -{ 0x300A,0x0051,DICOM_T_UNK, _T("Table Top Vertical Position Tolerance") }, -{ 0x300A,0x0052,DICOM_T_UNK, _T("Table Top Longitudinal Position Tolerance") }, -{ 0x300A,0x0053,DICOM_T_UNK, _T("Table Top Lateral Position Tolerance") }, -{ 0x300A,0x0055,DICOM_T_UNK, _T("RT Plan Relationship") }, -{ 0x300A,0x0070,DICOM_T_UNK, _T("Fraction Group Sequence") }, -{ 0x300A,0x0071,DICOM_T_UNK, _T("Fraction Group Number") }, -{ 0x300A,0x0072,DICOM_T_UNK, _T("Fraction Group Description") }, -{ 0x300A,0x0078,DICOM_T_UNK, _T("Number of Fractions Planned") }, -{ 0x300A,0x0079,DICOM_T_UNK, _T("Number of Fraction Pattern Digits Per Day") }, -{ 0x300A,0x007A,DICOM_T_UNK, _T("Repeat Fraction Cycle Length") }, -{ 0x300A,0x007B,DICOM_T_UNK, _T("Fraction Pattern") }, -{ 0x300A,0x0080,DICOM_T_UNK, _T("Number of Beams") }, -{ 0x300A,0x0082,DICOM_T_UNK, _T("Beam Dose Specification Point") }, -{ 0x300A,0x0084,DICOM_T_UNK, _T("Beam Dose") }, -{ 0x300A,0x0086,DICOM_T_UNK, _T("Beam Meterset") }, -{ 0x300A,0x0088,DICOM_T_UNK, _T("Beam Dose Point Depth") }, -{ 0x300A,0x0089,DICOM_T_UNK, _T("Beam Dose Point Equivalent Depth") }, -{ 0x300A,0x008A,DICOM_T_UNK, _T("Beam Dose Point SSD") }, -{ 0x300A,0x008B,DICOM_T_UNK, _T("Beam Dose Meaning") }, -{ 0x300A,0x008C,DICOM_T_UNK, _T("Beam Dose Verification Control Point Sequence") }, -{ 0x300A,0x008D,DICOM_T_UNK, _T("Average Beam Dose Point Depth") }, -{ 0x300A,0x008E,DICOM_T_UNK, _T("Average Beam Dose Point Equivalent Depth") }, -{ 0x300A,0x008F,DICOM_T_UNK, _T("Average Beam Dose Point SSD") }, -{ 0x300A,0x00A0,DICOM_T_UNK, _T("Number of Brachy Application Setups") }, -{ 0x300A,0x00A2,DICOM_T_UNK, _T("Brachy Application Setup Dose Specification Point") }, -{ 0x300A,0x00A4,DICOM_T_UNK, _T("Brachy Application Setup Dose") }, -{ 0x300A,0x00B0,DICOM_T_UNK, _T("Beam Sequence") }, -{ 0x300A,0x00B2,DICOM_T_UNK, _T("Treatment Machine Name") }, -{ 0x300A,0x00B3,DICOM_T_UNK, _T("Primary Dosimeter Unit") }, -{ 0x300A,0x00B4,DICOM_T_UNK, _T("Source-Axis Distance") }, -{ 0x300A,0x00B6,DICOM_T_UNK, _T("Beam Limiting Device Sequence") }, -{ 0x300A,0x00B8,DICOM_T_UNK, _T("RT Beam Limiting Device Type") }, -{ 0x300A,0x00BA,DICOM_T_UNK, _T("Source to Beam Limiting Device Distance") }, -{ 0x300A,0x00BB,DICOM_T_UNK, _T("Isocenter to Beam Limiting Device Distance") }, -{ 0x300A,0x00BC,DICOM_T_UNK, _T("Number of Leaf/Jaw Pairs") }, -{ 0x300A,0x00BE,DICOM_T_UNK, _T("Leaf Position Boundaries") }, -{ 0x300A,0x00C0,DICOM_T_UNK, _T("Beam Number") }, -{ 0x300A,0x00C2,DICOM_T_UNK, _T("Beam Name") }, -{ 0x300A,0x00C3,DICOM_T_UNK, _T("Beam Description") }, -{ 0x300A,0x00C4,DICOM_T_UNK, _T("Beam Type") }, -{ 0x300A,0x00C5,DICOM_T_UNK, _T("Beam Delivery Duration Limit") }, -{ 0x300A,0x00C6,DICOM_T_UNK, _T("Radiation Type") }, -{ 0x300A,0x00C7,DICOM_T_UNK, _T("High-Dose Technique Type") }, -{ 0x300A,0x00C8,DICOM_T_UNK, _T("Reference Image Number") }, -{ 0x300A,0x00CA,DICOM_T_UNK, _T("Planned Verification Image Sequence") }, -{ 0x300A,0x00CC,DICOM_T_UNK, _T("Imaging Device-Specific Acquisition Parameters") }, -{ 0x300A,0x00CE,DICOM_T_UNK, _T("Treatment Delivery Type") }, -{ 0x300A,0x00D0,DICOM_T_UNK, _T("Number of Wedges") }, -{ 0x300A,0x00D1,DICOM_T_UNK, _T("Wedge Sequence") }, -{ 0x300A,0x00D2,DICOM_T_UNK, _T("Wedge Number") }, -{ 0x300A,0x00D3,DICOM_T_UNK, _T("Wedge Type") }, -{ 0x300A,0x00D4,DICOM_T_UNK, _T("Wedge ID") }, -{ 0x300A,0x00D5,DICOM_T_UNK, _T("Wedge Angle") }, -{ 0x300A,0x00D6,DICOM_T_UNK, _T("Wedge Factor") }, -{ 0x300A,0x00D7,DICOM_T_UNK, _T("Total Wedge Tray Water-Equivalent Thickness") }, -{ 0x300A,0x00D8,DICOM_T_UNK, _T("Wedge Orientation") }, -{ 0x300A,0x00D9,DICOM_T_UNK, _T("Isocenter to Wedge Tray Distance") }, -{ 0x300A,0x00DA,DICOM_T_UNK, _T("Source to Wedge Tray Distance") }, -{ 0x300A,0x00DB,DICOM_T_UNK, _T("Wedge Thin Edge Position") }, -{ 0x300A,0x00DC,DICOM_T_UNK, _T("Bolus ID") }, -{ 0x300A,0x00DD,DICOM_T_UNK, _T("Bolus Description") }, -{ 0x300A,0x00E0,DICOM_T_UNK, _T("Number of Compensators") }, -{ 0x300A,0x00E1,DICOM_T_UNK, _T("Material ID") }, -{ 0x300A,0x00E2,DICOM_T_UNK, _T("Total Compensator Tray Factor") }, -{ 0x300A,0x00E3,DICOM_T_UNK, _T("Compensator Sequence") }, -{ 0x300A,0x00E4,DICOM_T_UNK, _T("Compensator Number") }, -{ 0x300A,0x00E5,DICOM_T_UNK, _T("Compensator ID") }, -{ 0x300A,0x00E6,DICOM_T_UNK, _T("Source to Compensator Tray Distance") }, -{ 0x300A,0x00E7,DICOM_T_UNK, _T("Compensator Rows") }, -{ 0x300A,0x00E8,DICOM_T_UNK, _T("Compensator Columns") }, -{ 0x300A,0x00E9,DICOM_T_UNK, _T("Compensator Pixel Spacing") }, -{ 0x300A,0x00EA,DICOM_T_UNK, _T("Compensator Position") }, -{ 0x300A,0x00EB,DICOM_T_UNK, _T("Compensator Transmission Data") }, -{ 0x300A,0x00EC,DICOM_T_UNK, _T("Compensator Thickness Data") }, -{ 0x300A,0x00ED,DICOM_T_UNK, _T("Number of Boli") }, -{ 0x300A,0x00EE,DICOM_T_UNK, _T("Compensator Type") }, -{ 0x300A,0x00EF,DICOM_T_UNK, _T("Compensator Tray ID") }, -{ 0x300A,0x00F0,DICOM_T_UNK, _T("Number of Blocks") }, -{ 0x300A,0x00F2,DICOM_T_UNK, _T("Total Block Tray Factor") }, -{ 0x300A,0x00F3,DICOM_T_UNK, _T("Total Block Tray Water-Equivalent Thickness") }, -{ 0x300A,0x00F4,DICOM_T_UNK, _T("Block Sequence") }, -{ 0x300A,0x00F5,DICOM_T_UNK, _T("Block Tray ID") }, -{ 0x300A,0x00F6,DICOM_T_UNK, _T("Source to Block Tray Distance") }, -{ 0x300A,0x00F7,DICOM_T_UNK, _T("Isocenter to Block Tray Distance") }, -{ 0x300A,0x00F8,DICOM_T_UNK, _T("Block Type") }, -{ 0x300A,0x00F9,DICOM_T_UNK, _T("Accessory Code") }, -{ 0x300A,0x00FA,DICOM_T_UNK, _T("Block Divergence") }, -{ 0x300A,0x00FB,DICOM_T_UNK, _T("Block Mounting Position") }, -{ 0x300A,0x00FC,DICOM_T_UNK, _T("Block Number") }, -{ 0x300A,0x00FE,DICOM_T_UNK, _T("Block Name") }, -{ 0x300A,0x0100,DICOM_T_UNK, _T("Block Thickness") }, -{ 0x300A,0x0102,DICOM_T_UNK, _T("Block Transmission") }, -{ 0x300A,0x0104,DICOM_T_UNK, _T("Block Number of Points") }, -{ 0x300A,0x0106,DICOM_T_UNK, _T("Block Data") }, -{ 0x300A,0x0107,DICOM_T_UNK, _T("Applicator Sequence") }, -{ 0x300A,0x0108,DICOM_T_UNK, _T("Applicator ID") }, -{ 0x300A,0x0109,DICOM_T_UNK, _T("Applicator Type") }, -{ 0x300A,0x010A,DICOM_T_UNK, _T("Applicator Description") }, -{ 0x300A,0x010C,DICOM_T_UNK, _T("Cumulative Dose Reference Coefficient") }, -{ 0x300A,0x010E,DICOM_T_UNK, _T("Final Cumulative Meterset Weight") }, -{ 0x300A,0x0110,DICOM_T_UNK, _T("Number of Control Points") }, -{ 0x300A,0x0111,DICOM_T_UNK, _T("Control Point Sequence") }, -{ 0x300A,0x0112,DICOM_T_UNK, _T("Control Point Index") }, -{ 0x300A,0x0114,DICOM_T_UNK, _T("Nominal Beam Energy") }, -{ 0x300A,0x0115,DICOM_T_UNK, _T("Dose Rate Set") }, -{ 0x300A,0x0116,DICOM_T_UNK, _T("Wedge Position Sequence") }, -{ 0x300A,0x0118,DICOM_T_UNK, _T("Wedge Position") }, -{ 0x300A,0x011A,DICOM_T_UNK, _T("Beam Limiting Device Position Sequence") }, -{ 0x300A,0x011C,DICOM_T_UNK, _T("Leaf/Jaw Positions") }, -{ 0x300A,0x011E,DICOM_T_UNK, _T("Gantry Angle") }, -{ 0x300A,0x011F,DICOM_T_UNK, _T("Gantry Rotation Direction") }, -{ 0x300A,0x0120,DICOM_T_UNK, _T("Beam Limiting Device Angle") }, -{ 0x300A,0x0121,DICOM_T_UNK, _T("Beam Limiting Device Rotation Direction") }, -{ 0x300A,0x0122,DICOM_T_UNK, _T("Patient Support Angle") }, -{ 0x300A,0x0123,DICOM_T_UNK, _T("Patient Support Rotation Direction") }, -{ 0x300A,0x0124,DICOM_T_UNK, _T("Table Top Eccentric Axis Distance") }, -{ 0x300A,0x0125,DICOM_T_UNK, _T("Table Top Eccentric Angle") }, -{ 0x300A,0x0126,DICOM_T_UNK, _T("Table Top Eccentric Rotation Direction") }, -{ 0x300A,0x0128,DICOM_T_UNK, _T("Table Top Vertical Position") }, -{ 0x300A,0x0129,DICOM_T_UNK, _T("Table Top Longitudinal Position") }, -{ 0x300A,0x012A,DICOM_T_UNK, _T("Table Top Lateral Position") }, -{ 0x300A,0x012C,DICOM_T_UNK, _T("Isocenter Position") }, -{ 0x300A,0x012E,DICOM_T_UNK, _T("Surface Entry Point") }, -{ 0x300A,0x0130,DICOM_T_UNK, _T("Source to Surface Distance") }, -{ 0x300A,0x0134,DICOM_T_UNK, _T("Cumulative Meterset Weight") }, -{ 0x300A,0x0140,DICOM_T_UNK, _T("Table Top Pitch Angle") }, -{ 0x300A,0x0142,DICOM_T_UNK, _T("Table Top Pitch Rotation Direction") }, -{ 0x300A,0x0144,DICOM_T_UNK, _T("Table Top Roll Angle") }, -{ 0x300A,0x0146,DICOM_T_UNK, _T("Table Top Roll Rotation Direction") }, -{ 0x300A,0x0148,DICOM_T_UNK, _T("Head Fixation Angle") }, -{ 0x300A,0x014A,DICOM_T_UNK, _T("Gantry Pitch Angle") }, -{ 0x300A,0x014C,DICOM_T_UNK, _T("Gantry Pitch Rotation Direction") }, -{ 0x300A,0x014E,DICOM_T_UNK, _T("Gantry Pitch Angle Tolerance") }, -{ 0x300A,0x0180,DICOM_T_UNK, _T("Patient Setup Sequence") }, -{ 0x300A,0x0182,DICOM_T_UNK, _T("Patient Setup Number") }, -{ 0x300A,0x0183,DICOM_T_UNK, _T("Patient Setup Label") }, -{ 0x300A,0x0184,DICOM_T_UNK, _T("Patient Additional Position") }, -{ 0x300A,0x0190,DICOM_T_UNK, _T("Fixation Device Sequence") }, -{ 0x300A,0x0192,DICOM_T_UNK, _T("Fixation Device Type") }, -{ 0x300A,0x0194,DICOM_T_UNK, _T("Fixation Device Label") }, -{ 0x300A,0x0196,DICOM_T_UNK, _T("Fixation Device Description") }, -{ 0x300A,0x0198,DICOM_T_UNK, _T("Fixation Device Position") }, -{ 0x300A,0x0199,DICOM_T_UNK, _T("Fixation Device Pitch Angle") }, -{ 0x300A,0x019A,DICOM_T_UNK, _T("Fixation Device Roll Angle") }, -{ 0x300A,0x01A0,DICOM_T_UNK, _T("Shielding Device Sequence") }, -{ 0x300A,0x01A2,DICOM_T_UNK, _T("Shielding Device Type") }, -{ 0x300A,0x01A4,DICOM_T_UNK, _T("Shielding Device Label") }, -{ 0x300A,0x01A6,DICOM_T_UNK, _T("Shielding Device Description") }, -{ 0x300A,0x01A8,DICOM_T_UNK, _T("Shielding Device Position") }, -{ 0x300A,0x01B0,DICOM_T_UNK, _T("Setup Technique") }, -{ 0x300A,0x01B2,DICOM_T_UNK, _T("Setup Technique Description") }, -{ 0x300A,0x01B4,DICOM_T_UNK, _T("Setup Device Sequence") }, -{ 0x300A,0x01B6,DICOM_T_UNK, _T("Setup Device Type") }, -{ 0x300A,0x01B8,DICOM_T_UNK, _T("Setup Device Label") }, -{ 0x300A,0x01BA,DICOM_T_UNK, _T("Setup Device Description") }, -{ 0x300A,0x01BC,DICOM_T_UNK, _T("Setup Device Parameter") }, -{ 0x300A,0x01D0,DICOM_T_UNK, _T("Setup Reference Description") }, -{ 0x300A,0x01D2,DICOM_T_UNK, _T("Table Top Vertical Setup Displacement") }, -{ 0x300A,0x01D4,DICOM_T_UNK, _T("Table Top Longitudinal Setup Displacement") }, -{ 0x300A,0x01D6,DICOM_T_UNK, _T("Table Top Lateral Setup Displacement") }, -{ 0x300A,0x0200,DICOM_T_UNK, _T("Brachy Treatment Technique") }, -{ 0x300A,0x0202,DICOM_T_UNK, _T("Brachy Treatment Type") }, -{ 0x300A,0x0206,DICOM_T_UNK, _T("Treatment Machine Sequence") }, -{ 0x300A,0x0210,DICOM_T_UNK, _T("Source Sequence") }, -{ 0x300A,0x0212,DICOM_T_UNK, _T("Source Number") }, -{ 0x300A,0x0214,DICOM_T_UNK, _T("Source Type") }, -{ 0x300A,0x0216,DICOM_T_UNK, _T("Source Manufacturer") }, -{ 0x300A,0x0218,DICOM_T_UNK, _T("Active Source Diameter") }, -{ 0x300A,0x021A,DICOM_T_UNK, _T("Active Source Length") }, -{ 0x300A,0x021B,DICOM_T_UNK, _T("Source Model ID") }, -{ 0x300A,0x021C,DICOM_T_UNK, _T("Source Description") }, -{ 0x300A,0x0222,DICOM_T_UNK, _T("Source Encapsulation Nominal Thickness") }, -{ 0x300A,0x0224,DICOM_T_UNK, _T("Source Encapsulation Nominal Transmission") }, -{ 0x300A,0x0226,DICOM_T_UNK, _T("Source Isotope Name") }, -{ 0x300A,0x0228,DICOM_T_UNK, _T("Source Isotope Half Life") }, -{ 0x300A,0x0229,DICOM_T_UNK, _T("Source Strength Units") }, -{ 0x300A,0x022A,DICOM_T_UNK, _T("Reference Air Kerma Rate") }, -{ 0x300A,0x022B,DICOM_T_UNK, _T("Source Strength") }, -{ 0x300A,0x022C,DICOM_T_UNK, _T("Source Strength Reference Date") }, -{ 0x300A,0x022E,DICOM_T_UNK, _T("Source Strength Reference Time") }, -{ 0x300A,0x0230,DICOM_T_UNK, _T("Application Setup Sequence") }, -{ 0x300A,0x0232,DICOM_T_UNK, _T("Application Setup Type") }, -{ 0x300A,0x0234,DICOM_T_UNK, _T("Application Setup Number") }, -{ 0x300A,0x0236,DICOM_T_UNK, _T("Application Setup Name") }, -{ 0x300A,0x0238,DICOM_T_UNK, _T("Application Setup Manufacturer") }, -{ 0x300A,0x0240,DICOM_T_UNK, _T("Template Number") }, -{ 0x300A,0x0242,DICOM_T_UNK, _T("Template Type") }, -{ 0x300A,0x0244,DICOM_T_UNK, _T("Template Name") }, -{ 0x300A,0x0250,DICOM_T_UNK, _T("Total Reference Air Kerma") }, -{ 0x300A,0x0260,DICOM_T_UNK, _T("Brachy Accessory Device Sequence") }, -{ 0x300A,0x0262,DICOM_T_UNK, _T("Brachy Accessory Device Number") }, -{ 0x300A,0x0263,DICOM_T_UNK, _T("Brachy Accessory Device ID") }, -{ 0x300A,0x0264,DICOM_T_UNK, _T("Brachy Accessory Device Type") }, -{ 0x300A,0x0266,DICOM_T_UNK, _T("Brachy Accessory Device Name") }, -{ 0x300A,0x026A,DICOM_T_UNK, _T("Brachy Accessory Device Nominal Thickness") }, -{ 0x300A,0x026C,DICOM_T_UNK, _T("Brachy Accessory Device Nominal Transmission") }, -{ 0x300A,0x0280,DICOM_T_UNK, _T("Channel Sequence") }, -{ 0x300A,0x0282,DICOM_T_UNK, _T("Channel Number") }, -{ 0x300A,0x0284,DICOM_T_UNK, _T("Channel Length") }, -{ 0x300A,0x0286,DICOM_T_UNK, _T("Channel Total Time") }, -{ 0x300A,0x0288,DICOM_T_UNK, _T("Source Movement Type") }, -{ 0x300A,0x028A,DICOM_T_UNK, _T("Number of Pulses") }, -{ 0x300A,0x028C,DICOM_T_UNK, _T("Pulse Repetition Interval") }, -{ 0x300A,0x0290,DICOM_T_UNK, _T("Source Applicator Number") }, -{ 0x300A,0x0291,DICOM_T_UNK, _T("Source Applicator ID") }, -{ 0x300A,0x0292,DICOM_T_UNK, _T("Source Applicator Type") }, -{ 0x300A,0x0294,DICOM_T_UNK, _T("Source Applicator Name") }, -{ 0x300A,0x0296,DICOM_T_UNK, _T("Source Applicator Length") }, -{ 0x300A,0x0298,DICOM_T_UNK, _T("Source Applicator Manufacturer") }, -{ 0x300A,0x029C,DICOM_T_UNK, _T("Source Applicator Wall Nominal Thickness") }, -{ 0x300A,0x029E,DICOM_T_UNK, _T("Source Applicator Wall Nominal Transmission") }, -{ 0x300A,0x02A0,DICOM_T_UNK, _T("Source Applicator Step Size") }, -{ 0x300A,0x02A2,DICOM_T_UNK, _T("Transfer Tube Number") }, -{ 0x300A,0x02A4,DICOM_T_UNK, _T("Transfer Tube Length") }, -{ 0x300A,0x02B0,DICOM_T_UNK, _T("Channel Shield Sequence") }, -{ 0x300A,0x02B2,DICOM_T_UNK, _T("Channel Shield Number") }, -{ 0x300A,0x02B3,DICOM_T_UNK, _T("Channel Shield ID") }, -{ 0x300A,0x02B4,DICOM_T_UNK, _T("Channel Shield Name") }, -{ 0x300A,0x02B8,DICOM_T_UNK, _T("Channel Shield Nominal Thickness") }, -{ 0x300A,0x02BA,DICOM_T_UNK, _T("Channel Shield Nominal Transmission") }, -{ 0x300A,0x02C8,DICOM_T_UNK, _T("Final Cumulative Time Weight") }, -{ 0x300A,0x02D0,DICOM_T_UNK, _T("Brachy Control Point Sequence") }, -{ 0x300A,0x02D2,DICOM_T_UNK, _T("Control Point Relative Position") }, -{ 0x300A,0x02D4,DICOM_T_UNK, _T("Control Point 3D Position") }, -{ 0x300A,0x02D6,DICOM_T_UNK, _T("Cumulative Time Weight") }, -{ 0x300A,0x02E0,DICOM_T_UNK, _T("Compensator Divergence") }, -{ 0x300A,0x02E1,DICOM_T_UNK, _T("Compensator Mounting Position") }, -{ 0x300A,0x02E2,DICOM_T_UNK, _T("Source to Compensator Distance") }, -{ 0x300A,0x02E3,DICOM_T_UNK, _T("Total Compensator Tray Water-Equivalent Thickness") }, -{ 0x300A,0x02E4,DICOM_T_UNK, _T("Isocenter to Compensator Tray Distance") }, -{ 0x300A,0x02E5,DICOM_T_UNK, _T("Compensator Column Offset") }, -{ 0x300A,0x02E6,DICOM_T_UNK, _T("Isocenter to Compensator Distances") }, -{ 0x300A,0x02E7,DICOM_T_UNK, _T("Compensator Relative Stopping Power Ratio") }, -{ 0x300A,0x02E8,DICOM_T_UNK, _T("Compensator Milling Tool Diameter") }, -{ 0x300A,0x02EA,DICOM_T_UNK, _T("Ion Range Compensator Sequence") }, -{ 0x300A,0x02EB,DICOM_T_UNK, _T("Compensator Description") }, -{ 0x300A,0x0302,DICOM_T_UNK, _T("Radiation Mass Number") }, -{ 0x300A,0x0304,DICOM_T_UNK, _T("Radiation Atomic Number") }, -{ 0x300A,0x0306,DICOM_T_UNK, _T("Radiation Charge State") }, -{ 0x300A,0x0308,DICOM_T_UNK, _T("Scan Mode") }, -{ 0x300A,0x030A,DICOM_T_UNK, _T("Virtual Source-Axis Distances") }, -{ 0x300A,0x030C,DICOM_T_UNK, _T("Snout Sequence") }, -{ 0x300A,0x030D,DICOM_T_UNK, _T("Snout Position") }, -{ 0x300A,0x030F,DICOM_T_UNK, _T("Snout ID") }, -{ 0x300A,0x0312,DICOM_T_UNK, _T("Number of Range Shifters") }, -{ 0x300A,0x0314,DICOM_T_UNK, _T("Range Shifter Sequence") }, -{ 0x300A,0x0316,DICOM_T_UNK, _T("Range Shifter Number") }, -{ 0x300A,0x0318,DICOM_T_UNK, _T("Range Shifter ID") }, -{ 0x300A,0x0320,DICOM_T_UNK, _T("Range Shifter Type") }, -{ 0x300A,0x0322,DICOM_T_UNK, _T("Range Shifter Description") }, -{ 0x300A,0x0330,DICOM_T_UNK, _T("Number of Lateral Spreading Devices") }, -{ 0x300A,0x0332,DICOM_T_UNK, _T("Lateral Spreading Device Sequence") }, -{ 0x300A,0x0334,DICOM_T_UNK, _T("Lateral Spreading Device Number") }, -{ 0x300A,0x0336,DICOM_T_UNK, _T("Lateral Spreading Device ID") }, -{ 0x300A,0x0338,DICOM_T_UNK, _T("Lateral Spreading Device Type") }, -{ 0x300A,0x033A,DICOM_T_UNK, _T("Lateral Spreading Device Description") }, -{ 0x300A,0x033C,DICOM_T_UNK, _T("Lateral Spreading Device Water Equivalent Thickness") }, -{ 0x300A,0x0340,DICOM_T_UNK, _T("Number of Range Modulators") }, -{ 0x300A,0x0342,DICOM_T_UNK, _T("Range Modulator Sequence") }, -{ 0x300A,0x0344,DICOM_T_UNK, _T("Range Modulator Number") }, -{ 0x300A,0x0346,DICOM_T_UNK, _T("Range Modulator ID") }, -{ 0x300A,0x0348,DICOM_T_UNK, _T("Range Modulator Type") }, -{ 0x300A,0x034A,DICOM_T_UNK, _T("Range Modulator Description") }, -{ 0x300A,0x034C,DICOM_T_UNK, _T("Beam Current Modulation ID") }, -{ 0x300A,0x0350,DICOM_T_UNK, _T("Patient Support Type") }, -{ 0x300A,0x0352,DICOM_T_UNK, _T("Patient Support ID") }, -{ 0x300A,0x0354,DICOM_T_UNK, _T("Patient Support Accessory Code") }, -{ 0x300A,0x0356,DICOM_T_UNK, _T("Fixation Light Azimuthal Angle") }, -{ 0x300A,0x0358,DICOM_T_UNK, _T("Fixation Light Polar Angle") }, -{ 0x300A,0x035A,DICOM_T_UNK, _T("Meterset Rate") }, -{ 0x300A,0x0360,DICOM_T_UNK, _T("Range Shifter Settings Sequence") }, -{ 0x300A,0x0362,DICOM_T_UNK, _T("Range Shifter Setting") }, -{ 0x300A,0x0364,DICOM_T_UNK, _T("Isocenter to Range Shifter Distance") }, -{ 0x300A,0x0366,DICOM_T_UNK, _T("Range Shifter Water Equivalent Thickness") }, -{ 0x300A,0x0370,DICOM_T_UNK, _T("Lateral Spreading Device Settings Sequence") }, -{ 0x300A,0x0372,DICOM_T_UNK, _T("Lateral Spreading Device Setting") }, -{ 0x300A,0x0374,DICOM_T_UNK, _T("Isocenter to Lateral Spreading Device Distance") }, -{ 0x300A,0x0380,DICOM_T_UNK, _T("Range Modulator Settings Sequence") }, -{ 0x300A,0x0382,DICOM_T_UNK, _T("Range Modulator Gating Start Value") }, -{ 0x300A,0x0384,DICOM_T_UNK, _T("Range Modulator Gating Stop Value") }, -{ 0x300A,0x0386,DICOM_T_UNK, _T("Range Modulator Gating Start Water Equivalent Thickness") }, -{ 0x300A,0x0388,DICOM_T_UNK, _T("Range Modulator Gating Stop Water Equivalent Thickness") }, -{ 0x300A,0x038A,DICOM_T_UNK, _T("Isocenter to Range Modulator Distance") }, -{ 0x300A,0x0390,DICOM_T_UNK, _T("Scan Spot Tune ID") }, -{ 0x300A,0x0392,DICOM_T_UNK, _T("Number of Scan Spot Positions") }, -{ 0x300A,0x0394,DICOM_T_UNK, _T("Scan Spot Position Map") }, -{ 0x300A,0x0396,DICOM_T_UNK, _T("Scan Spot Meterset Weights") }, -{ 0x300A,0x0398,DICOM_T_UNK, _T("Scanning Spot Size") }, -{ 0x300A,0x039A,DICOM_T_UNK, _T("Number of Paintings") }, -{ 0x300A,0x03A0,DICOM_T_UNK, _T("Ion Tolerance Table Sequence") }, -{ 0x300A,0x03A2,DICOM_T_UNK, _T("Ion Beam Sequence") }, -{ 0x300A,0x03A4,DICOM_T_UNK, _T("Ion Beam Limiting Device Sequence") }, -{ 0x300A,0x03A6,DICOM_T_UNK, _T("Ion Block Sequence") }, -{ 0x300A,0x03A8,DICOM_T_UNK, _T("Ion Control Point Sequence") }, -{ 0x300A,0x03AA,DICOM_T_UNK, _T("Ion Wedge Sequence") }, -{ 0x300A,0x03AC,DICOM_T_UNK, _T("Ion Wedge Position Sequence") }, -{ 0x300A,0x0401,DICOM_T_UNK, _T("Referenced Setup Image Sequence") }, -{ 0x300A,0x0402,DICOM_T_UNK, _T("Setup Image Comment") }, -{ 0x300A,0x0410,DICOM_T_UNK, _T("Motion Synchronization Sequence") }, -{ 0x300A,0x0412,DICOM_T_UNK, _T("Control Point Orientation") }, -{ 0x300A,0x0420,DICOM_T_UNK, _T("General Accessory Sequence") }, -{ 0x300A,0x0421,DICOM_T_UNK, _T("General Accessory ID") }, -{ 0x300A,0x0422,DICOM_T_UNK, _T("General Accessory Description") }, -{ 0x300A,0x0423,DICOM_T_UNK, _T("General Accessory Type") }, -{ 0x300A,0x0424,DICOM_T_UNK, _T("General Accessory Number") }, -{ 0x300A,0x0425,DICOM_T_UNK, _T("Source to General Accessory Distance") }, -{ 0x300A,0x0431,DICOM_T_UNK, _T("Applicator Geometry Sequence") }, -{ 0x300A,0x0432,DICOM_T_UNK, _T("Applicator Aperture Shape") }, -{ 0x300A,0x0433,DICOM_T_UNK, _T("Applicator Opening") }, -{ 0x300A,0x0434,DICOM_T_UNK, _T("Applicator Opening X") }, -{ 0x300A,0x0435,DICOM_T_UNK, _T("Applicator Opening Y") }, -{ 0x300A,0x0436,DICOM_T_UNK, _T("Source to Applicator Mounting Position Distance") }, -{ 0x300C,0x0002,DICOM_T_UNK, _T("Referenced RT Plan Sequence") }, -{ 0x300C,0x0004,DICOM_T_UNK, _T("Referenced Beam Sequence") }, -{ 0x300C,0x0006,DICOM_T_UNK, _T("Referenced Beam Number") }, -{ 0x300C,0x0007,DICOM_T_UNK, _T("Referenced Reference Image Number") }, -{ 0x300C,0x0008,DICOM_T_UNK, _T("Start Cumulative Meterset Weight") }, -{ 0x300C,0x0009,DICOM_T_UNK, _T("End Cumulative Meterset Weight") }, -{ 0x300C,0x000A,DICOM_T_UNK, _T("Referenced Brachy Application Setup Sequence") }, -{ 0x300C,0x000C,DICOM_T_UNK, _T("Referenced Brachy Application Setup Number") }, -{ 0x300C,0x000E,DICOM_T_UNK, _T("Referenced Source Number") }, -{ 0x300C,0x0020,DICOM_T_UNK, _T("Referenced Fraction Group Sequence") }, -{ 0x300C,0x0022,DICOM_T_UNK, _T("Referenced Fraction Group Number") }, -{ 0x300C,0x0040,DICOM_T_UNK, _T("Referenced Verification Image Sequence") }, -{ 0x300C,0x0042,DICOM_T_UNK, _T("Referenced Reference Image Sequence") }, -{ 0x300C,0x0050,DICOM_T_UNK, _T("Referenced Dose Reference Sequence") }, -{ 0x300C,0x0051,DICOM_T_UNK, _T("Referenced Dose Reference Number") }, -{ 0x300C,0x0055,DICOM_T_UNK, _T("Brachy Referenced Dose Reference Sequence") }, -{ 0x300C,0x0060,DICOM_T_UNK, _T("Referenced Structure Set Sequence") }, -{ 0x300C,0x006A,DICOM_T_UNK, _T("Referenced Patient Setup Number") }, -{ 0x300C,0x0080,DICOM_T_UNK, _T("Referenced Dose Sequence") }, -{ 0x300C,0x00A0,DICOM_T_UNK, _T("Referenced Tolerance Table Number") }, -{ 0x300C,0x00B0,DICOM_T_UNK, _T("Referenced Bolus Sequence") }, -{ 0x300C,0x00C0,DICOM_T_UNK, _T("Referenced Wedge Number") }, -{ 0x300C,0x00D0,DICOM_T_UNK, _T("Referenced Compensator Number") }, -{ 0x300C,0x00E0,DICOM_T_UNK, _T("Referenced Block Number") }, -{ 0x300C,0x00F0,DICOM_T_UNK, _T("Referenced Control Point Index") }, -{ 0x300C,0x00F2,DICOM_T_UNK, _T("Referenced Control Point Sequence") }, -{ 0x300C,0x00F4,DICOM_T_UNK, _T("Referenced Start Control Point Index") }, -{ 0x300C,0x00F6,DICOM_T_UNK, _T("Referenced Stop Control Point Index") }, -{ 0x300C,0x0100,DICOM_T_UNK, _T("Referenced Range Shifter Number") }, -{ 0x300C,0x0102,DICOM_T_UNK, _T("Referenced Lateral Spreading Device Number") }, -{ 0x300C,0x0104,DICOM_T_UNK, _T("Referenced Range Modulator Number") }, -{ 0x300E,0x0002,DICOM_T_UNK, _T("Approval Status") }, -{ 0x300E,0x0004,DICOM_T_UNK, _T("Review Date") }, -{ 0x300E,0x0005,DICOM_T_UNK, _T("Review Time") }, -{ 0x300E,0x0008,DICOM_T_UNK, _T("Reviewer Name") }, -{ 0x4000,0x0010,DICOM_T_UNK, _T("Arbitrary") }, -{ 0x4000,0x4000,DICOM_T_UNK, _T("Text Comments") }, -{ 0x4008,0x0040,DICOM_T_UNK, _T("Results ID") }, -{ 0x4008,0x0042,DICOM_T_UNK, _T("Results ID Issuer") }, -{ 0x4008,0x0050,DICOM_T_UNK, _T("Referenced Interpretation Sequence") }, -{ 0x4008,0x00FF,DICOM_T_UNK, _T("Report Production Status (Trial)") }, -{ 0x4008,0x0100,DICOM_T_UNK, _T("Interpretation Recorded Date") }, -{ 0x4008,0x0101,DICOM_T_UNK, _T("Interpretation Recorded Time") }, -{ 0x4008,0x0102,DICOM_T_UNK, _T("Interpretation Recorder") }, -{ 0x4008,0x0103,DICOM_T_UNK, _T("Reference to Recorded Sound") }, -{ 0x4008,0x0108,DICOM_T_UNK, _T("Interpretation Transcription Date") }, -{ 0x4008,0x0109,DICOM_T_UNK, _T("Interpretation Transcription Time") }, -{ 0x4008,0x010A,DICOM_T_UNK, _T("Interpretation Transcriber") }, -{ 0x4008,0x010B,DICOM_T_UNK, _T("Interpretation Text") }, -{ 0x4008,0x010C,DICOM_T_UNK, _T("Interpretation Author") }, -{ 0x4008,0x0111,DICOM_T_UNK, _T("Interpretation Approver Sequence") }, -{ 0x4008,0x0112,DICOM_T_UNK, _T("Interpretation Approval Date") }, -{ 0x4008,0x0113,DICOM_T_UNK, _T("Interpretation Approval Time") }, -{ 0x4008,0x0114,DICOM_T_UNK, _T("Physician Approving Interpretation") }, -{ 0x4008,0x0115,DICOM_T_UNK, _T("Interpretation Diagnosis Description") }, -{ 0x4008,0x0117,DICOM_T_UNK, _T("Interpretation Diagnosis Code Sequence") }, -{ 0x4008,0x0118,DICOM_T_UNK, _T("Results Distribution List Sequence") }, -{ 0x4008,0x0119,DICOM_T_UNK, _T("Distribution Name") }, -{ 0x4008,0x011A,DICOM_T_UNK, _T("Distribution Address") }, -{ 0x4008,0x0200,DICOM_T_UNK, _T("Interpretation ID") }, -{ 0x4008,0x0202,DICOM_T_UNK, _T("Interpretation ID Issuer") }, -{ 0x4008,0x0210,DICOM_T_UNK, _T("Interpretation Type ID") }, -{ 0x4008,0x0212,DICOM_T_UNK, _T("Interpretation Status ID") }, -{ 0x4008,0x0300,DICOM_T_UNK, _T("Impressions") }, -{ 0x4008,0x4000,DICOM_T_UNK, _T("Results Comments") }, -{ 0x4010,0x0001,DICOM_T_UNK, _T("Low Energy Detectors") }, -{ 0x4010,0x0002,DICOM_T_UNK, _T("High Energy Detectors") }, -{ 0x4010,0x0004,DICOM_T_UNK, _T("Detector Geometry Sequence") }, -{ 0x4010,0x1001,DICOM_T_UNK, _T("Threat ROI Voxel Sequence") }, -{ 0x4010,0x1004,DICOM_T_UNK, _T("Threat ROI Base") }, -{ 0x4010,0x1005,DICOM_T_UNK, _T("Threat ROI Extents") }, -{ 0x4010,0x1006,DICOM_T_UNK, _T("Threat ROI Bitmap") }, -{ 0x4010,0x1007,DICOM_T_UNK, _T("Route Segment ID") }, -{ 0x4010,0x1008,DICOM_T_UNK, _T("Gantry Type") }, -{ 0x4010,0x1009,DICOM_T_UNK, _T("OOI Owner Type") }, -{ 0x4010,0x100A,DICOM_T_UNK, _T("Route Segment Sequence") }, -{ 0x4010,0x1010,DICOM_T_UNK, _T("Potential Threat Object ID") }, -{ 0x4010,0x1011,DICOM_T_UNK, _T("Threat Sequence") }, -{ 0x4010,0x1012,DICOM_T_UNK, _T("Threat Category") }, -{ 0x4010,0x1013,DICOM_T_UNK, _T("Threat Category Description") }, -{ 0x4010,0x1014,DICOM_T_UNK, _T("ATD Ability Assessment") }, -{ 0x4010,0x1015,DICOM_T_UNK, _T("ATD Assessment Flag") }, -{ 0x4010,0x1016,DICOM_T_UNK, _T("ATD Assessment Probability") }, -{ 0x4010,0x1017,DICOM_T_UNK, _T("Mass") }, -{ 0x4010,0x1018,DICOM_T_UNK, _T("Density") }, -{ 0x4010,0x1019,DICOM_T_UNK, _T("Z Effective") }, -{ 0x4010,0x101A,DICOM_T_UNK, _T("Boarding Pass ID") }, -{ 0x4010,0x101B,DICOM_T_UNK, _T("Center of Mass") }, -{ 0x4010,0x101C,DICOM_T_UNK, _T("Center of PTO") }, -{ 0x4010,0x101D,DICOM_T_UNK, _T("Bounding Polygon") }, -{ 0x4010,0x101E,DICOM_T_UNK, _T("Route Segment Start Location ID") }, -{ 0x4010,0x101F,DICOM_T_UNK, _T("Route Segment End Location ID") }, -{ 0x4010,0x1020,DICOM_T_UNK, _T("Route Segment Location ID Type") }, -{ 0x4010,0x1021,DICOM_T_UNK, _T("Abort Reason") }, -{ 0x4010,0x1023,DICOM_T_UNK, _T("Volume of PTO") }, -{ 0x4010,0x1024,DICOM_T_UNK, _T("Abort Flag") }, -{ 0x4010,0x1025,DICOM_T_UNK, _T("Route Segment Start Time") }, -{ 0x4010,0x1026,DICOM_T_UNK, _T("Route Segment End Time") }, -{ 0x4010,0x1027,DICOM_T_UNK, _T("TDR Type") }, -{ 0x4010,0x1028,DICOM_T_UNK, _T("International Route Segment") }, -{ 0x4010,0x1029,DICOM_T_UNK, _T("Threat Detection Algorithm and Version") }, -{ 0x4010,0x102A,DICOM_T_UNK, _T("Assigned Location") }, -{ 0x4010,0x102B,DICOM_T_UNK, _T("Alarm Decision Time") }, -{ 0x4010,0x1031,DICOM_T_UNK, _T("Alarm Decision") }, -{ 0x4010,0x1033,DICOM_T_UNK, _T("Number of Total Objects") }, -{ 0x4010,0x1034,DICOM_T_UNK, _T("Number of Alarm Objects") }, -{ 0x4010,0x1037,DICOM_T_UNK, _T("PTO Representation Sequence") }, -{ 0x4010,0x1038,DICOM_T_UNK, _T("ATD Assessment Sequence") }, -{ 0x4010,0x1039,DICOM_T_UNK, _T("TIP Type") }, -{ 0x4010,0x103A,DICOM_T_UNK, _T("DICOS Version") }, -{ 0x4010,0x1041,DICOM_T_UNK, _T("OOI Owner Creation Time") }, -{ 0x4010,0x1042,DICOM_T_UNK, _T("OOI Type") }, -{ 0x4010,0x1043,DICOM_T_UNK, _T("OOI Size") }, -{ 0x4010,0x1044,DICOM_T_UNK, _T("Acquisition Status") }, -{ 0x4010,0x1045,DICOM_T_UNK, _T("Basis Materials Code Sequence") }, -{ 0x4010,0x1046,DICOM_T_UNK, _T("Phantom Type") }, -{ 0x4010,0x1047,DICOM_T_UNK, _T("OOI Owner Sequence") }, -{ 0x4010,0x1048,DICOM_T_UNK, _T("Scan Type") }, -{ 0x4010,0x1051,DICOM_T_UNK, _T("Itinerary ID") }, -{ 0x4010,0x1052,DICOM_T_UNK, _T("Itinerary ID Type") }, -{ 0x4010,0x1053,DICOM_T_UNK, _T("Itinerary ID Assigning Authority") }, -{ 0x4010,0x1054,DICOM_T_UNK, _T("Route ID") }, -{ 0x4010,0x1055,DICOM_T_UNK, _T("Route ID Assigning Authority") }, -{ 0x4010,0x1056,DICOM_T_UNK, _T("Inbound Arrival Type") }, -{ 0x4010,0x1058,DICOM_T_UNK, _T("Carrier ID") }, -{ 0x4010,0x1059,DICOM_T_UNK, _T("Carrier ID Assigning Authority") }, -{ 0x4010,0x1060,DICOM_T_UNK, _T("Source Orientation") }, -{ 0x4010,0x1061,DICOM_T_UNK, _T("Source Position") }, -{ 0x4010,0x1062,DICOM_T_UNK, _T("Belt Height") }, -{ 0x4010,0x1064,DICOM_T_UNK, _T("Algorithm Routing Code Sequence") }, -{ 0x4010,0x1067,DICOM_T_UNK, _T("Transport Classification") }, -{ 0x4010,0x1068,DICOM_T_UNK, _T("OOI Type Descriptor") }, -{ 0x4010,0x1069,DICOM_T_UNK, _T("Total Processing Time") }, -{ 0x4010,0x106C,DICOM_T_UNK, _T("Detector Calibration Data") }, -{ 0x4010,0x106D,DICOM_T_UNK, _T("Additional Screening Performed") }, -{ 0x4010,0x106E,DICOM_T_UNK, _T("Additional Inspection Selection Criteria") }, -{ 0x4010,0x106F,DICOM_T_UNK, _T("Additional Inspection Method Sequence") }, -{ 0x4010,0x1070,DICOM_T_UNK, _T("AIT Device Type") }, -{ 0x4010,0x1071,DICOM_T_UNK, _T("QR Measurements Sequence") }, -{ 0x4010,0x1072,DICOM_T_UNK, _T("Target Material Sequence") }, -{ 0x4010,0x1073,DICOM_T_UNK, _T("SNR Threshold") }, -{ 0x4010,0x1075,DICOM_T_UNK, _T("Image Scale Representation") }, -{ 0x4010,0x1076,DICOM_T_UNK, _T("Referenced PTO Sequence") }, -{ 0x4010,0x1077,DICOM_T_UNK, _T("Referenced TDR Instance Sequence") }, -{ 0x4010,0x1078,DICOM_T_UNK, _T("PTO Location Description") }, -{ 0x4010,0x1079,DICOM_T_UNK, _T("Anomaly Locator Indicator Sequence") }, -{ 0x4010,0x107A,DICOM_T_UNK, _T("Anomaly Locator Indicator") }, -{ 0x4010,0x107B,DICOM_T_UNK, _T("PTO Region Sequence") }, -{ 0x4010,0x107C,DICOM_T_UNK, _T("Inspection Selection Criteria") }, -{ 0x4010,0x107D,DICOM_T_UNK, _T("Secondary Inspection Method Sequence") }, -{ 0x4010,0x107E,DICOM_T_UNK, _T("PRCS to RCS Orientation") }, -{ 0x4FFE,0x0001,DICOM_T_UNK, _T("MAC Parameters Sequence") }, -/* -{ 0x50xx,0x0005,DICOM_T_UNK, _T("Curve Dimensions") }, -{ 0x50xx,0x0010,DICOM_T_UNK, _T("Number of Points") }, -{ 0x50xx,0x0020,DICOM_T_UNK, _T("Type of Data") }, -{ 0x50xx,0x0022,DICOM_T_UNK, _T("Curve Description") }, -{ 0x50xx,0x0030,DICOM_T_UNK, _T("Axis Units") }, -{ 0x50xx,0x0040,DICOM_T_UNK, _T("Axis Labels") }, -{ 0x50xx,0x0103,DICOM_T_UNK, _T("Data Value Representation") }, -{ 0x50xx,0x0104,DICOM_T_UNK, _T("Minimum Coordinate Value") }, -{ 0x50xx,0x0105,DICOM_T_UNK, _T("Maximum Coordinate Value") }, -{ 0x50xx,0x0106,DICOM_T_UNK, _T("Curve Range") }, -{ 0x50xx,0x0110,DICOM_T_UNK, _T("Curve Data Descriptor") }, -{ 0x50xx,0x0112,DICOM_T_UNK, _T("Coordinate Start Value") }, -{ 0x50xx,0x0114,DICOM_T_UNK, _T("Coordinate Step Value") }, -{ 0x50xx,0x1001,DICOM_T_UNK, _T("Curve Activation Layer") }, -{ 0x50xx,0x2000,DICOM_T_UNK, _T("Audio Type") }, -{ 0x50xx,0x2002,DICOM_T_UNK, _T("Audio Sample Format") }, -{ 0x50xx,0x2004,DICOM_T_UNK, _T("Number of Channels") }, -{ 0x50xx,0x2006,DICOM_T_UNK, _T("Number of Samples") }, -{ 0x50xx,0x2008,DICOM_T_UNK, _T("Sample Rate") }, -{ 0x50xx,0x200A,DICOM_T_UNK, _T("Total Time") }, -{ 0x50xx,0x200C,DICOM_T_UNK, _T("Audio Sample Data") }, -{ 0x50xx,0x200E,DICOM_T_UNK, _T("Audio Comments") }, -{ 0x50xx,0x2500,DICOM_T_UNK, _T("Curve Label") }, -{ 0x50xx,0x2600,DICOM_T_UNK, _T("Curve Referenced Overlay Sequence") }, -{ 0x50xx,0x2610,DICOM_T_UNK, _T("Curve Referenced Overlay Group") }, -{ 0x50xx,0x3000,DICOM_T_UNK, _T("Curve Data") }, -*/ -{ 0x5200,0x9229,DICOM_T_UNK, _T("Shared Functional Groups Sequence") }, -{ 0x5200,0x9230,DICOM_T_UNK, _T("Per-frame Functional Groups Sequence") }, -{ 0x5400,0x0100,DICOM_T_UNK, _T("Waveform Sequence") }, -{ 0x5400,0x0110,DICOM_T_UNK, _T("Channel Minimum Value") }, -{ 0x5400,0x0112,DICOM_T_UNK, _T("Channel Maximum Value") }, -{ 0x5400,0x1004,DICOM_T_UNK, _T("Waveform Bits Allocated") }, -{ 0x5400,0x1006,DICOM_T_UNK, _T("Waveform Sample Interpretation") }, -{ 0x5400,0x100A,DICOM_T_UNK, _T("Waveform Padding Value") }, -{ 0x5400,0x1010,DICOM_T_UNK, _T("Waveform Data") }, -{ 0x5600,0x0010,DICOM_T_UNK, _T("First Order Phase Correction Angle") }, -{ 0x5600,0x0020,DICOM_T_UNK, _T("Spectroscopy Data") }, -/* -{ 0x60xx,0x0010,DICOM_T_UNK, _T("Overlay Rows") }, -{ 0x60xx,0x0011,DICOM_T_UNK, _T("Overlay Columns") }, -{ 0x60xx,0x0012,DICOM_T_UNK, _T("Overlay Planes") }, -{ 0x60xx,0x0015,DICOM_T_UNK, _T("Number of Frames in Overlay") }, -{ 0x60xx,0x0022,DICOM_T_UNK, _T("Overlay Description") }, -{ 0x60xx,0x0040,DICOM_T_UNK, _T("Overlay Type") }, -{ 0x60xx,0x0045,DICOM_T_UNK, _T("Overlay Subtype") }, -{ 0x60xx,0x0050,DICOM_T_UNK, _T("Overlay Origin") }, -{ 0x60xx,0x0051,DICOM_T_UNK, _T("Image Frame Origin") }, -{ 0x60xx,0x0052,DICOM_T_UNK, _T("Overlay Plane Origin") }, -{ 0x60xx,0x0060,DICOM_T_UNK, _T("Overlay Compression Code") }, -{ 0x60xx,0x0061,DICOM_T_UNK, _T("Overlay Compression Originator") }, -{ 0x60xx,0x0062,DICOM_T_UNK, _T("Overlay Compression Label") }, -{ 0x60xx,0x0063,DICOM_T_UNK, _T("Overlay Compression Description") }, -{ 0x60xx,0x0066,DICOM_T_UNK, _T("Overlay Compression Step Pointers") }, -{ 0x60xx,0x0068,DICOM_T_UNK, _T("Overlay Repeat Interval") }, -{ 0x60xx,0x0069,DICOM_T_UNK, _T("Overlay Bits Grouped") }, -{ 0x60xx,0x0100,DICOM_T_UNK, _T("Overlay Bits Allocated") }, -{ 0x60xx,0x0102,DICOM_T_UNK, _T("Overlay Bit Position") }, -{ 0x60xx,0x0110,DICOM_T_UNK, _T("Overlay Format") }, -{ 0x60xx,0x0200,DICOM_T_UNK, _T("Overlay Location") }, -{ 0x60xx,0x0800,DICOM_T_UNK, _T("Overlay Code Label") }, -{ 0x60xx,0x0802,DICOM_T_UNK, _T("Overlay Number of Tables") }, -{ 0x60xx,0x0803,DICOM_T_UNK, _T("Overlay Code Table Location") }, -{ 0x60xx,0x0804,DICOM_T_UNK, _T("Overlay Bits For Code Word") }, -{ 0x60xx,0x1001,DICOM_T_UNK, _T("Overlay Activation Layer") }, -{ 0x60xx,0x1100,DICOM_T_UNK, _T("Overlay Descriptor - Gray") }, -{ 0x60xx,0x1101,DICOM_T_UNK, _T("Overlay Descriptor - Red") }, -{ 0x60xx,0x1102,DICOM_T_UNK, _T("Overlay Descriptor - Green") }, -{ 0x60xx,0x1103,DICOM_T_UNK, _T("Overlay Descriptor - Blue") }, -{ 0x60xx,0x1200,DICOM_T_UNK, _T("Overlays - Gray") }, -{ 0x60xx,0x1201,DICOM_T_UNK, _T("Overlays - Red") }, -{ 0x60xx,0x1202,DICOM_T_UNK, _T("Overlays - Green") }, -{ 0x60xx,0x1203,DICOM_T_UNK, _T("Overlays - Blue") }, -{ 0x60xx,0x1301,DICOM_T_UNK, _T("ROI Area") }, -{ 0x60xx,0x1302,DICOM_T_UNK, _T("ROI Mean") }, -{ 0x60xx,0x1303,DICOM_T_UNK, _T("ROI Standard Deviation") }, -{ 0x60xx,0x1500,DICOM_T_UNK, _T("Overlay Label") }, -{ 0x60xx,0x3000,DICOM_T_UNK, _T("Overlay Data") }, -{ 0x60xx,0x4000,DICOM_T_UNK, _T("Overlay Comments") }, -*/ - -// Pixel data has special decoding. Sometimes see "undefined length" -// (4B length = 0xFFFFFFFF) -// Reference: Part 5, Section A.4 -// Undefined length in Part 5, Section 7.1.1 -{ 0x7FE0,0x0010,DICOM_T_UNK, _T("Pixel Data") }, - -{ 0x7FE0,0x0020,DICOM_T_UNK, _T("Coefficients SDVN") }, -{ 0x7FE0,0x0030,DICOM_T_UNK, _T("Coefficients SDHN") }, -{ 0x7FE0,0x0040,DICOM_T_UNK, _T("Coefficients SDDN") }, -/* -{ 0x7Fxx,0x0010,DICOM_T_UNK, _T("Variable Pixel Data") }, -{ 0x7Fxx,0x0011,DICOM_T_UNK, _T("Variable Next Data Group") }, -{ 0x7Fxx,0x0020,DICOM_T_UNK, _T("Variable Coefficients SDVN") }, -{ 0x7Fxx,0x0030,DICOM_T_UNK, _T("Variable Coefficients SDHN") }, -{ 0x7Fxx,0x0040,DICOM_T_UNK, _T("Variable Coefficients SDDN") }, -*/ -{ 0xFFFA,0xFFFA,DICOM_T_UNK, _T("Digital Signatures Sequence") }, -{ 0xFFFC,0xFFFC,DICOM_T_UNK, _T("Data Set Trailing Padding") }, - -// For these 3 items, Part 6, Section 6 indicates: -// The VR for these Data Elements do not exist. See PS 3.5 for explanation. -// Part 5, Section 7.5 -{ 0xFFFE,0xE000,DICOM_T_UNK, _T("Item") }, -{ 0xFFFE,0xE00D,DICOM_T_UNK, _T("Item Delimitation Item") }, -{ 0xFFFE,0xE0DD,DICOM_T_UNK, _T("Sequence Delimitation Item") }, - -}; - - -struct tsDicomTagSpec asTagSpecial[] = -{ - // Backround details in: - // - Part 5, Section 10 - // - Part 5, Section A.4.1 - // - Part 5, Section F.1 - - // Part 6, Section A - { 0x0002, 0x0010, _T("1.2.840.10008.1.2"), _T("Implicit VR Little Endian") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.1"), _T("Explicit VR Little Endian") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.1.99"), _T("Deflated Explicit VR Little Endian") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.2"), _T("Explicit VR Big Endian") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.50"), _T("JPEG Baseline (Process 1)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.51"), _T("JPEG Extended (Process 2 & 4)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.52"), _T("JPEG Extended (Process 3 & 5) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.53"), _T("JPEG Spectral Selection, Non- Hierarchical (Process 6 & 8) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.54"), _T("JPEG Spectral Selection, Non- Hierarchical (Process 7 & 9) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.55"), _T("JPEG Full Progression, Non- Hierarchical (Process 10 & 12) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.56"), _T("JPEG Full Progression, Non- Hierarchical (Process 11 & 13) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.57"), _T("JPEG Lossless, Non-Hierarchical (Process 14)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.58"), _T("JPEG Lossless, Non-Hierarchical (Process 15) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.59"), _T("JPEG Extended, Hierarchical (Process 16 & 18) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.60"), _T("JPEG Extended, Hierarchical (Process 17 & 19) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.61"), _T("JPEG Spectral Selection, Hierarchical (Process 20 & 22) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.62"), _T("JPEG Spectral Selection, Hierarchical (Process 21 & 23) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.63"), _T("JPEG Full Progression, Hierarchical (Process 24 & 26) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.64"), _T("JPEG Full Progression, Hierarchical (Process 25 & 27) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.65"), _T("JPEG Lossless, Hierarchical (Process 28) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.66"), _T("JPEG Lossless, Hierarchical (Process 29) (Retired)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.70"), _T("JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.80"), _T("JPEG-LS Lossless Image Compression") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.81"), _T("JPEG-LS Lossy (Near-Lossless) Image Compression") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.90"), _T("JPEG 2000 Image Compression (Lossless Only)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.91"), _T("JPEG 2000 Image Compression") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.92"), _T("JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.93"), _T("JPEG 2000 Part 2 Multi-component Image Compression") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.94"), _T("JPIP Referenced") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.95"), _T("JPIP Referenced Deflate") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.100"), _T("MPEG2 Main Profile @ Main Level") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.101"), _T("MPEG2 Main Profile @ High Level") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.102"), _T("MPEG-4 AVC/H.264 High Profile / Level 4.1") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.4.103"), _T("MPEG-4 AVC/H.264 BDcompatible High Profile / Level 4.1") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.5"), _T("RLE Lossless") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.6.1"), _T("RFC 2557 MIME encapsulation") }, - { 0x0002, 0x0010, _T("1.2.840.10008.1.2.6.2"), _T("XML Encoding") }, - - { 0x0000, 0x0000, _T(""), _T("END OF LIST") }, - -}; - diff --git a/source/DecodePs.cpp b/source/DecodePs.cpp index c6bafe6..bdea2f9 100644 --- a/source/DecodePs.cpp +++ b/source/DecodePs.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -22,7 +22,8 @@ #include "DecodePs.h" #include "snoop.h" -#include "JPEGsnoop.h" // for m_pAppConfig get +//#include "JPEGsnoop.h" // for m_pAppConfig get +#include "SnoopConfig.h" #include "WindowBuf.h" @@ -267,12 +268,8 @@ struct tsBimEnum asBimEnums[] = { {BIM_T_ENUM_END, 0, "???"}, }; -CDecodePs::CDecodePs(CwindowBuf * pWBuf, CDocLog * pLog) +CDecodePs::CDecodePs(CwindowBuf *pWBuf, CDocLog *pLog, CSnoopConfig *pAppConfig) : m_pWBuf(pWBuf), m_pLog(pLog), m_pAppConfig(pAppConfig) { - // Save copies of class pointers - m_pWBuf = pWBuf; - m_pLog = pLog; - // HACK // Only select a single layer to decode into the DIB // FIXME: Need to allow user control over this setting @@ -280,13 +277,6 @@ CDecodePs::CDecodePs(CwindowBuf * pWBuf, CDocLog * pLog) m_nDisplayLayerInd = 0; m_bDisplayImage = true; - // Ideally this would be passed by constructor, but simply access - // directly for now. - CJPEGsnoopApp *pApp; - -//@@ pApp = (CJPEGsnoopApp*)AfxGetApp(); -//@@ m_pAppConfig = pApp->m_pAppConfig; - Reset(); } @@ -313,26 +303,26 @@ CDecodePs::~CDecodePs(void) // RETURN: // - Byte from file // -BYTE CDecodePs::Buf(uint32_t offset, bool bClean = false) +uint8_t CDecodePs::Buf(uint32_t offset, bool bClean = false) { return m_pWBuf->Buf(offset, bClean); } // Determine if the file is a Photoshop PSD // If so, parse the headers. Generally want to start at start of file (nPos=0). -bool CDecodePs::DecodePsd(uint32_t nPos, CDIB * pDibTemp, uint32_t &nWidth, uint32_t &nHeight) +bool CDecodePs::DecodePsd(uint32_t nPos, QImage * pDibTemp, int32_t &nWidth, int32_t &nHeight) { QString strTmp; + QString strSig; m_bPsd = false; - QString strSig; - uint32_t nVer; strSig = m_pWBuf->BufReadStrn(nPos, 4); nPos += 4; nVer = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + if((strSig == "8BPS") && (nVer == 1)) { m_bPsd = true; @@ -358,11 +348,13 @@ bool CDecodePs::DecodePsd(uint32_t nPos, CDIB * pDibTemp, uint32_t &nWidth, uint nHeight = sImageInfo.nImageHeight; PhotoshopParseColorModeSection(nPos, 3); + if(bDecOk) bDecOk &= PhotoshopParseImageResourcesSection(nPos, 3); if(bDecOk) bDecOk &= PhotoshopParseLayerMaskInfo(nPos, 3, pDibTemp); + if(bDecOk) { unsigned char *pDibBits = NULL; @@ -386,24 +378,24 @@ bool CDecodePs::DecodePsd(uint32_t nPos, CDIB * pDibTemp, uint32_t &nWidth, uint // Fetch the actual pixel array //@@ pDibBits = (unsigned char *) (pDibTemp->GetDIBBitArray()); } + + pDibTemp = new QImage(nWidth, nHeight, QImage::Format_RGB32); } #endif bDecOk &= PhotoshopParseImageData(nPos, 3, &sImageInfo, pDibBits); PhotoshopParseReportFldOffset(3, "Image data decode complete:", nPos); } + PhotoshopParseReportNote(3, ""); - if(bDecOk) - { - } - else + if(!bDecOk) { m_pLog->AddLineErr("ERROR: There was a problem during decode. Aborting."); return false; } - return true; + return true; } // Locate a field ID in the constant 8BIM / Image Resource array @@ -422,7 +414,6 @@ bool CDecodePs::FindBimRecord(uint32_t nBimId, uint32_t &nFldInd) uint32_t nInd = 0; bool bDone = false; - bool bFound = false; while(!bDone) @@ -454,13 +445,14 @@ bool CDecodePs::FindBimRecord(uint32_t nBimId, uint32_t &nFldInd) { nInd++; } - } } + if(bFound) { nFldInd = nInd; } + return bFound; } @@ -476,7 +468,6 @@ bool CDecodePs::LookupIptcField(uint32_t nRecord, uint32_t nDataSet, uint32_t &n uint32_t nInd = 0; bool bDone = false; - bool bFound = false; while(!bDone) @@ -498,10 +489,12 @@ bool CDecodePs::LookupIptcField(uint32_t nRecord, uint32_t nDataSet, uint32_t &n } } } + if(bFound) { nFldInd = nInd; } + return bFound; } @@ -520,13 +513,10 @@ QString CDecodePs::DecodeIptcValue(teIptcType eIptcType, uint32_t nFldCnt, uint3 { //uint32_t nFldInd = 0; uint32_t nInd; - uint32_t nVal; QString strField = ""; - QString strByte = ""; - QString strVal = ""; switch (eIptcType) @@ -539,29 +529,38 @@ QString CDecodePs::DecodeIptcValue(teIptcType eIptcType, uint32_t nFldCnt, uint3 nPos += nFldCnt; strVal = QString("%1").arg(nVal); break; + case IPTC_T_HEX: strVal = "["; + for(nInd = 0; nInd < nFldCnt; nInd++) { strByte = QString("0x%1 ").arg(Buf(nPos++), 2, 16, QChar('0')); strVal += strByte; } + strVal += "]"; break; + case IPTC_T_STR: strVal = "\""; + for(nInd = 0; nInd < nFldCnt; nInd++) { strByte = QString("%1").arg(Buf(nPos++)); strVal += strByte; } + strVal += "\""; break; + case IPTC_T_UNK: strVal = "???"; + default: break; } + return strVal; } @@ -571,15 +570,10 @@ QString CDecodePs::DecodeIptcValue(teIptcType eIptcType, uint32_t nFldCnt, uint3 void CDecodePs::DecodeIptc(uint32_t &nPos, uint32_t nLen, uint32_t nIndent) { QString strIndent; - QString strTmp; - QString strIptcTypeName; - QString strIptcField; - QString strIptcVal; - QString strByte; uint32_t nPosStart; @@ -591,11 +585,13 @@ void CDecodePs::DecodeIptc(uint32_t &nPos, uint32_t nLen, uint32_t nIndent) strIndent = PhotoshopParseIndent(nIndent); nPosStart = nPos; bDone = true; + if(nPos <= nPosStart + nLen) { // TODO: Should probably check to see if we have at least 5 bytes? bDone = false; } + while(!bDone) { nTagMarker = Buf(nPos + 0); @@ -622,10 +618,11 @@ void CDecodePs::DecodeIptc(uint32_t &nPos, uint32_t nLen, uint32_t nIndent) } strIptcVal = DecodeIptcValue(eIptcType, nDataFieldCnt, nPos); - strTmp = - QString("%1IPTC [%03u:%03u] %4 = %5").arg(strIndent).arg(nRecordNumber, 3, 10, QChar('0')).arg(nDataSetNumber, 3, 10, - QChar('0')). - arg(strIptcField).arg(strIptcVal); + strTmp = QString("IPTC [%1:%2] %3 = %4").arg(strIndent) + .arg(nRecordNumber, 3, 10, QChar('0')) + .arg(nDataSetNumber, 3, 10, QChar('0')) + .arg(strIptcField) + .arg(strIptcVal); m_pLog->AddLine(strTmp); nPos += nDataFieldCnt; } @@ -635,17 +632,18 @@ void CDecodePs::DecodeIptc(uint32_t &nPos, uint32_t nLen, uint32_t nIndent) // I have seen at least one JPEG file that had an IPTC block with all zeros. // In this example, the TagMarker check for 0x1C would fail. // Since we don't know how to parse it, abort now. - strTmp = - QString("ERROR: Unknown IPTC TagMarker [0x%02X] @ 0x%08X. Skipping parsing.").arg(nTagMarker, 2, 16, - QChar('0')).arg(nPos - 5, 8, 16, - QChar('0')); + strTmp = QString("ERROR: Unknown IPTC TagMarker [0x%1] @ 0x%2. Skipping parsing.") + .arg(nTagMarker, 2, 16, QChar('0')) + .arg(nPos - 5, 8, 16, QChar('0')); m_pLog->AddLineErr(strTmp); #ifdef DEBUG_LOG QString strDebug; - strDebug = - QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", -10).arg(strTmp); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n") + .arg(m_pAppConfig->strCurFname, -100) + .arg("PsDecode", -10) + .arg(strTmp); qDebug() << (strDebug); #endif @@ -673,6 +671,7 @@ QString CDecodePs::PhotoshopParseIndent(uint32_t nIndent) { strIndent += " "; } + return strIndent; } @@ -687,6 +686,7 @@ QString CDecodePs::PhotoshopParseGetLStrAsc(uint32_t &nPos) QString strVal = ""; nStrLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); + if(nStrLen != 0) { strVal = m_pWBuf->BufReadStrn(nPos, nStrLen); @@ -695,9 +695,14 @@ QString CDecodePs::PhotoshopParseGetLStrAsc(uint32_t &nPos) else { // 4 byte string - strVal = QString("%1%2%3%4").arg(Buf(nPos + 0)).arg(Buf(nPos + 1)).arg(Buf(nPos + 2)).arg(Buf(nPos + 3)); + strVal = QString("%1%2%3%4") + .arg(Buf(nPos + 0)) + .arg(Buf(nPos + 1)) + .arg(Buf(nPos + 2)) + .arg(Buf(nPos + 3)); nPos += 4; } + return strVal; } @@ -716,7 +721,7 @@ QString CDecodePs::PhotoshopParseGetBimLStrUni(uint32_t nPos, uint32_t &nPosOffs char anStrBuf[(PS_MAX_UNICODE_STRLEN + 1) * 2]; - wchar_t acStrBuf[(PS_MAX_UNICODE_STRLEN + 1)]; +// wchar_t acStrBuf[(PS_MAX_UNICODE_STRLEN + 1)]; char nChVal; @@ -736,6 +741,7 @@ QString CDecodePs::PhotoshopParseGetBimLStrUni(uint32_t nPos, uint32_t &nPosOffs { nStrLenTrunc = PS_MAX_UNICODE_STRLEN; } + for(uint32_t nInd = 0; nInd < nStrLenTrunc; nInd++) { // Reverse the order of the bytes @@ -744,6 +750,7 @@ QString CDecodePs::PhotoshopParseGetBimLStrUni(uint32_t nPos, uint32_t &nPosOffs nChVal = Buf(nPos + nPosOffset + (nInd * 2) + 1); anStrBuf[(nInd * 2) + 0] = nChVal; } + // TODO: Replace with call to ByteStr2Unicode() // Ensure it is terminated anStrBuf[nStrLenTrunc * 2 + 0] = 0; @@ -754,6 +761,7 @@ QString CDecodePs::PhotoshopParseGetBimLStrUni(uint32_t nPos, uint32_t &nPosOffs // Copy into QString strVal = QString(anStrBuf); } + // Update the file position offset nPosOffset += nStrLenActual * 2; // Return @@ -765,11 +773,12 @@ QString CDecodePs::PhotoshopParseGetBimLStrUni(uint32_t nPos, uint32_t &nPosOffs void CDecodePs::PhotoshopParseReportNote(uint32_t nIndent, QString strNote) { QString strIndent; - QString strLine; strIndent = PhotoshopParseIndent(nIndent); - strLine = QString("%1%2").arg(strIndent).arg(strNote, -50); + strLine = QString("%1%2") + .arg(strIndent) + .arg(strNote, -50); m_pLog->AddLine(strLine); } @@ -778,14 +787,15 @@ void CDecodePs::PhotoshopParseReportNote(uint32_t nIndent, QString strNote) void CDecodePs::PhotoshopParseReportFldNum(uint32_t nIndent, QString strField, uint32_t nVal, QString strUnits) { QString strIndent; - QString strVal; - QString strLine; strIndent = PhotoshopParseIndent(nIndent); strVal = QString("%1").arg(nVal); - strLine = QString("%1%2 = %3 %4").arg(strIndent).arg(strField, -50).arg(strVal).arg(strUnits); + strLine = QString("%1%2 = %3 %4") + .arg(strIndent) + .arg(strField, -50) + .arg(strVal).arg(strUnits); m_pLog->AddLine(strLine); } @@ -794,14 +804,15 @@ void CDecodePs::PhotoshopParseReportFldNum(uint32_t nIndent, QString strField, u void CDecodePs::PhotoshopParseReportFldBool(uint32_t nIndent, QString strField, uint32_t nVal) { QString strIndent; - QString strVal; - QString strLine; strIndent = PhotoshopParseIndent(nIndent); strVal = (nVal != 0) ? "true" : "false"; - strLine = QString("%1%2 = %3").arg(strIndent).arg(strField, -50).arg(strVal); + strLine = QString("%1%2 = %3") + .arg(strIndent) + .arg(strField, -50) + .arg(strVal); m_pLog->AddLine(strLine); } @@ -821,21 +832,15 @@ void CDecodePs::PhotoshopParseReportFldBool(uint32_t nIndent, QString strField, void CDecodePs::PhotoshopParseReportFldHex(uint32_t nIndent, QString strField, uint32_t nPosStart, uint32_t nLen) { QString strIndent; - - uint32_t nByte; - QString strPrefix; - QString strByteHex; - QString strByteAsc; - QString strValHex; - QString strValAsc; - QString strLine; + int32_t nByte; + strIndent = PhotoshopParseIndent(nIndent); if(nLen == 0) @@ -871,6 +876,7 @@ void CDecodePs::PhotoshopParseReportFldHex(uint32_t nIndent, QString strField, u nLenClip = qMin(nLen, PS_HEX_TOTAL); strValHex = ""; strValAsc = ""; + while(!bDone) { // Have we reached the end of the data we wish to display? @@ -883,6 +889,7 @@ void CDecodePs::PhotoshopParseReportFldHex(uint32_t nIndent, QString strField, u // Reset the cumulative hex/ascii value strings strValHex = ""; strValAsc = ""; + // Build the hex/ascii value strings for(uint32_t nInd = 0; nInd < PS_HEX_MAX_ROW; nInd++) { @@ -890,6 +897,7 @@ void CDecodePs::PhotoshopParseReportFldHex(uint32_t nIndent, QString strField, u { nByte = m_pWBuf->Buf(nPosStart + nRowOffset + nInd); strByteHex = QString("%1 ").arg(nByte, 2, 16, QChar('0')); + // Only display printable characters if(isprint(nByte)) { @@ -906,6 +914,7 @@ void CDecodePs::PhotoshopParseReportFldHex(uint32_t nIndent, QString strField, u strByteHex = QString(" "); strByteAsc = " "; } + // Build up the strings strValHex += strByteHex; strValAsc += strByteAsc; @@ -932,27 +941,25 @@ void CDecodePs::PhotoshopParseReportFldHex(uint32_t nIndent, QString strField, u QString CDecodePs::PhotoshopDispHexWord(uint32_t nVal) { QString strValHex; - QString strValAsc; - - uint32_t nByte; - QString strByteHex; - QString strByteAsc; - QString strLine; + uint32_t nByte; + // Reset the cumulative hex/ascii value strings strValHex = ""; strValAsc = ""; + // Build the hex/ascii value strings for(uint32_t nInd = 0; nInd <= 3; nInd++) { nByte = (nVal & 0xFF000000) >> 24; nVal <<= 8; - strByteHex = QString("%02X ").arg(nByte, 2, 16, QChar('0')); + strByteHex = QString("%1 ").arg(nByte, 2, 16, QChar('0')); + // Only display printable characters if(isprint(nByte)) { @@ -998,10 +1005,12 @@ QString CDecodePs::PhotoshopParseLookupEnum(teBimEnumField eEnumField, uint32_t strVal = asBimEnums[nEnumInd].strVal; } } + if(asBimEnums[nEnumInd].eBimEnum == BIM_T_ENUM_END) { bDone = true; } + if(!bDone) { nEnumInd++; @@ -1024,9 +1033,7 @@ QString CDecodePs::PhotoshopParseLookupEnum(teBimEnumField eEnumField, uint32_t void CDecodePs::PhotoshopParseReportFldEnum(uint32_t nIndent, QString strField, teBimEnumField eEnumField, uint32_t nVal) { QString strIndent; - QString strVal; - QString strLine; strIndent = PhotoshopParseIndent(nIndent); @@ -1042,17 +1049,19 @@ void CDecodePs::PhotoshopParseReportFldEnum(uint32_t nIndent, QString strField, void CDecodePs::PhotoshopParseReportFldFixPt(uint32_t nIndent, QString strField, uint32_t nVal, QString strUnits) { QString strIndent; - QString strVal; - QString strLine; - float fVal; + double fVal; - fVal = (nVal / (float) 65536.0); + fVal = (static_cast(nVal) / 65536.0); strIndent = PhotoshopParseIndent(nIndent); strVal = QString("%1").arg(fVal); - strLine = QString("%1%2 = %3 %4").arg(strIndent).arg(strField, -50).arg(strVal).arg(strUnits); + strLine = QString("%1%2 = %3 %4") + .arg(strIndent) + .arg(strField, -50) + .arg(strVal) + .arg(strUnits); m_pLog->AddLine(strLine); } @@ -1062,9 +1071,7 @@ void CDecodePs::PhotoshopParseReportFldFixPt(uint32_t nIndent, QString strField, void CDecodePs::PhotoshopParseReportFldFloatPt(uint32_t nIndent, QString strField, uint32_t nVal, QString strUnits) { QString strIndent; - QString strVal; - QString strLine; float fVal; @@ -1074,35 +1081,35 @@ void CDecodePs::PhotoshopParseReportFldFloatPt(uint32_t nIndent, QString strFiel // indicate how floating points are stored. union tUnionTmp { - BYTE nVal[4]; + uint8_t nVal[4]; float fVal; }; tUnionTmp myUnion; // NOTE: Empirically determined the byte order for double representation - myUnion.nVal[3] = static_cast < BYTE > ((nVal & 0xFF000000) >> 24); - myUnion.nVal[2] = static_cast < BYTE > ((nVal & 0x00FF0000) >> 16); - myUnion.nVal[1] = static_cast < BYTE > ((nVal & 0x0000FF00) >> 8); - myUnion.nVal[0] = static_cast < BYTE > ((nVal & 0x000000FF) >> 0); + myUnion.nVal[3] = static_cast ((nVal & 0xFF000000) >> 24); + myUnion.nVal[2] = static_cast ((nVal & 0x00FF0000) >> 16); + myUnion.nVal[1] = static_cast ((nVal & 0x0000FF00) >> 8); + myUnion.nVal[0] = static_cast ((nVal & 0x000000FF) >> 0); fVal = myUnion.fVal; strIndent = PhotoshopParseIndent(nIndent); - strVal = QString("%1").arg(fVal,0,'f',5); - strLine = QString("%1%2 = %3 %4").arg(strIndent).arg(strField, -50).arg(strVal).arg(strUnits); + strVal = QString("%1").arg(fVal, 0, 'f', 5); + strLine = QString("%1%2 = %3 %4") + .arg(strIndent) + .arg(strField, -50) + .arg(strVal).arg(strUnits); m_pLog->AddLine(strLine); } // Display a formatted double-precision floating-point field // - Convert two 32-bit unsigned integers into Photoshop double-precision floating point // - Report the value with the field name (strField) and current indent level (nIndent) -void CDecodePs::PhotoshopParseReportFldDoublePt(uint32_t nIndent, QString strField, uint32_t nVal1, uint32_t nVal2, - QString strUnits) +void CDecodePs::PhotoshopParseReportFldDoublePt(uint32_t nIndent, QString strField, uint32_t nVal1, uint32_t nVal2, QString strUnits) { QString strIndent; - QString strVal; - QString strLine; double dVal; @@ -1112,26 +1119,30 @@ void CDecodePs::PhotoshopParseReportFldDoublePt(uint32_t nIndent, QString strFie // indicate how double points are stored. union tUnionTmp { - BYTE nVal[8]; + uint8_t nVal[8]; double dVal; }; tUnionTmp myUnion; // NOTE: Empirically determined the byte order for double representation - myUnion.nVal[7] = static_cast < BYTE > ((nVal1 & 0xFF000000) >> 24); - myUnion.nVal[6] = static_cast < BYTE > ((nVal1 & 0x00FF0000) >> 16); - myUnion.nVal[5] = static_cast < BYTE > ((nVal1 & 0x0000FF00) >> 8); - myUnion.nVal[4] = static_cast < BYTE > ((nVal1 & 0x000000FF) >> 0); - myUnion.nVal[3] = static_cast < BYTE > ((nVal2 & 0xFF000000) >> 24); - myUnion.nVal[2] = static_cast < BYTE > ((nVal2 & 0x00FF0000) >> 16); - myUnion.nVal[1] = static_cast < BYTE > ((nVal2 & 0x0000FF00) >> 8); - myUnion.nVal[0] = static_cast < BYTE > ((nVal2 & 0x000000FF) >> 0); + myUnion.nVal[7] = static_cast ((nVal1 & 0xFF000000) >> 24); + myUnion.nVal[6] = static_cast ((nVal1 & 0x00FF0000) >> 16); + myUnion.nVal[5] = static_cast ((nVal1 & 0x0000FF00) >> 8); + myUnion.nVal[4] = static_cast ((nVal1 & 0x000000FF) >> 0); + myUnion.nVal[3] = static_cast ((nVal2 & 0xFF000000) >> 24); + myUnion.nVal[2] = static_cast ((nVal2 & 0x00FF0000) >> 16); + myUnion.nVal[1] = static_cast ((nVal2 & 0x0000FF00) >> 8); + myUnion.nVal[0] = static_cast ((nVal2 & 0x000000FF) >> 0); dVal = myUnion.dVal; strIndent = PhotoshopParseIndent(nIndent); - strVal = QString("%1").arg(dVal,0,'f',5); - strLine = QString("%1%2 = %3 %4").arg(strIndent).arg(strField, -50).arg(strVal).arg(strUnits); + strVal = QString("%1").arg(dVal, 0, 'f', 5); + strLine = QString("%1%2 = %3 %4") + .arg(strIndent) + .arg(strField, -50) + .arg(strVal) + .arg(strUnits); m_pLog->AddLine(strLine); } @@ -1140,7 +1151,6 @@ void CDecodePs::PhotoshopParseReportFldDoublePt(uint32_t nIndent, QString strFie void CDecodePs::PhotoshopParseReportFldStr(uint32_t nIndent, QString strField, QString strVal) { QString strIndent; - QString strLine; strIndent = PhotoshopParseIndent(nIndent); @@ -1153,7 +1163,6 @@ void CDecodePs::PhotoshopParseReportFldStr(uint32_t nIndent, QString strField, Q void CDecodePs::PhotoshopParseReportFldOffset(uint32_t nIndent, QString strField, uint32_t nOffset) { QString strIndent; - QString strLine; strIndent = PhotoshopParseIndent(nIndent); @@ -1412,6 +1421,7 @@ void CDecodePs::PhotoshopParseGridGuides(uint32_t &nPos, uint32_t nIndent) if(nNumGuides > 0) PhotoshopParseReportNote(nIndent, "-----"); + for(uint32_t nInd = 0; nInd < nNumGuides; nInd++) { strVal = QString("Guide #%1:").arg(nInd); @@ -1422,6 +1432,7 @@ void CDecodePs::PhotoshopParseGridGuides(uint32_t &nPos, uint32_t nIndent) nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); PhotoshopParseReportFldEnum(nIndent + 1, "Direction", BIM_T_ENUM_GRID_GUIDE_DIR, nVal); } + if(nNumGuides > 0) PhotoshopParseReportNote(nIndent, "-----"); } @@ -1496,7 +1507,7 @@ void CDecodePs::PhotoshopParseLayerGroupInfo(uint32_t &nPos, uint32_t nIndent, u for(uint32_t nInd = 0; nInd < nNumLayers; nInd++) { - strVal = QString("Layer #%:").arg(nInd); + strVal = QString("Layer #%1:").arg(nInd); PhotoshopParseReportNote(nIndent, strVal); nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); PhotoshopParseReportFldNum(nIndent + 1, "Layer Group", nVal, ""); @@ -1551,6 +1562,7 @@ void CDecodePs::PhotoshopParseLayerSelectId(uint32_t &nPos, uint32_t nIndent) uint32_t nNumLayer = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); PhotoshopParseReportFldNum(nIndent, "Num selected", nNumLayer, ""); + for(uint32_t nInd = 0; nInd < nNumLayer; nInd++) { nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); @@ -1621,6 +1633,7 @@ void CDecodePs::PhotoshopParseColorModeSection(uint32_t &nPos, uint32_t nIndent) uint32_t nColModeLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); PhotoshopParseReportFldNum(nIndent, "Length", nColModeLen, ""); + if(nColModeLen != 0) { PhotoshopParseReportFldOffset(nIndent, "Color data", nPos); @@ -1640,7 +1653,7 @@ void CDecodePs::PhotoshopParseColorModeSection(uint32_t &nPos, uint32_t nIndent) // OUTPUT: // - nPos = File position after reading the block // -bool CDecodePs::PhotoshopParseLayerMaskInfo(uint32_t &nPos, uint32_t nIndent, CDIB * pDibTemp) +bool CDecodePs::PhotoshopParseLayerMaskInfo(uint32_t &nPos, uint32_t nIndent, QImage *pDibTemp) { QString strVal; @@ -1650,12 +1663,11 @@ bool CDecodePs::PhotoshopParseLayerMaskInfo(uint32_t &nPos, uint32_t nIndent, CD nIndent++; uint32_t nLayerMaskLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); - uint32_t nPosStart = nPos; - uint32_t nPosEnd = nPosStart + nLayerMaskLen; PhotoshopParseReportFldNum(nIndent, "Length", nLayerMaskLen, ""); + if(nLayerMaskLen == 0) { return true; @@ -1664,8 +1676,10 @@ bool CDecodePs::PhotoshopParseLayerMaskInfo(uint32_t &nPos, uint32_t nIndent, CD { if(bDecOk) bDecOk &= PhotoshopParseLayerInfo(nPos, nIndent, pDibTemp); + if(bDecOk) bDecOk &= PhotoshopParseGlobalLayerMaskInfo(nPos, nIndent); + if(bDecOk) { //while ((bDecOk) && (nPos < nPosEnd)) { @@ -1694,7 +1708,7 @@ bool CDecodePs::PhotoshopParseLayerMaskInfo(uint32_t &nPos, uint32_t nIndent, CD // OUTPUT: // - nPos = File position after reading the block // -bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * pDibTemp) +bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, QImage * pDibTemp) { QString strVal; @@ -1706,6 +1720,7 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * uint32_t nLayerLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); PhotoshopParseReportFldNum(nIndent, "Length", nLayerLen, ""); + if(nLayerLen == 0) { return bDecOk; @@ -1725,12 +1740,12 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * // first alpha channel contains the transparency data for the merged result. // Therefore, we'll treat it as signed short and take absolute value uint16_t nLayerCountU = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); - - signed short nLayerCountS = (signed short) nLayerCountU; + int16_t nLayerCountS = static_cast(nLayerCountU); uint32_t nLayerCount = abs(nLayerCountS); PhotoshopParseReportFldNum(nIndent, "Layer count", nLayerCount, ""); + if(nLayerCountU & 0x8000) { PhotoshopParseReportNote(nIndent, "First alpha channel contains transparency for merged result"); @@ -1750,6 +1765,7 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * strTmp = QString("Layer #%1").arg(nLayerInd); PhotoshopParseReportFldOffset(nIndent, strTmp, nPos); + if(bDecOk) bDecOk &= PhotoshopParseLayerRecord(nPos, nIndent, &sLayerAllInfo.psLayers[nLayerInd]); } @@ -1758,13 +1774,9 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * QString strLine; uint32_t nNumChans; - uint32_t nWidth; - uint32_t nHeight; - uint32_t nPosLastLayer = 0; - uint32_t nPosLastChan = 0; for(uint32_t nLayerInd = 0; (bDecOk) && (nLayerInd < nLayerCount); nLayerInd++) @@ -1798,16 +1810,19 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * #endif nPosLastLayer = nPos; + for(uint32_t nChanInd = 0; (bDecOk) && (nChanInd < nNumChans); nChanInd++) { nPosLastChan = nPos; - strLine = - QString("Layer %1/%2, Channel %3/%4").arg(nLayerInd + 1, 3).arg(nLayerCount, 3).arg(nChanInd + 1, 2).arg(nNumChans, 2); + strLine = QString("Layer %1/%2, Channel %3/%4") + .arg(nLayerInd + 1, 3) + .arg(nLayerCount, 3) + .arg(nChanInd + 1, 2).arg(nNumChans, 2); //m_pLog->AddLine(strLine); PhotoshopParseReportNote(nIndent + 1, strLine); + if(bDecOk) { - // Fetch the channel ID to determine what RGB channel to map to // - Layer 0 (background): 0->R, 1->G, 2->B // - Layer n (other): 65535->A, 0->R, 1->G, 2->B @@ -1821,21 +1836,21 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * bDecOk &= PhotoshopParseChannelImageData(nPos, nIndent + 1, nWidth, nHeight, nChanID, pDibBits); } - strLine = - QString("CurPos @ 0x%1, bDecOk=%2, LastLayer @ 0x%3, LastChan @ 0x%4").arg(nPos, 8, 16, - QChar('0')).arg(bDecOk).arg(nPosLastLayer, 8, - 16, - QChar('0')). - arg(nPosLastChan, 8, 16, QChar('0')); + + strLine = QString("CurPos @ 0x%1, bDecOk=%2, LastLayer @ 0x%3, LastChan @ 0x%4") + .arg(nPos, 8, 16, QChar('0')) + .arg(bDecOk).arg(nPosLastLayer, 8, 16, QChar('0')) + .arg(nPosLastChan, 8, 16, QChar('0')); //m_pLog->AddLine(strLine); //PhotoshopParseReportNote(nIndent+1,strLine); } } // Pad out to specified length - signed nPad; + int32_t nPad; nPad = nPosStart + nLayerLen - nPos; + if(nPad > 0) { nPos += nPad; @@ -1847,6 +1862,7 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * for(uint32_t nLayerInd = 0; (nLayerInd < sLayerAllInfo.nNumLayers); nLayerInd++) { nNumChans = sLayerAllInfo.psLayers[nLayerInd].nNumChans; + for(uint32_t nChanInd = 0; (bDecOk) && (nChanInd < nNumChans); nChanInd++) { delete[]sLayerAllInfo.psLayers[nLayerInd].pnChanLen; @@ -1855,6 +1871,7 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * sLayerAllInfo.psLayers[nLayerInd].pnChanID = NULL; } } + delete[]sLayerAllInfo.psLayers; sLayerAllInfo.psLayers = NULL; } @@ -1924,6 +1941,7 @@ bool CDecodePs::PhotoshopParseLayerRecord(uint32_t &nPos, uint32_t nIndent, tsLa pLayerInfo->pnChanID[nChanInd] = nChanID; pLayerInfo->pnChanLen[nChanInd] = nChanDataLen; } + QString strBlendModeSig = m_pWBuf->BufReadStrn(nPos, 4); nPos += 4; @@ -1943,6 +1961,7 @@ bool CDecodePs::PhotoshopParseLayerRecord(uint32_t &nPos, uint32_t nIndent, tsLa if(bDecOk) bDecOk &= PhotoshopParseLayerMask(nPos, nIndent); + if(bDecOk) bDecOk &= PhotoshopParseLayerBlendingRanges(nPos, nIndent); @@ -1994,7 +2013,6 @@ bool CDecodePs::PhotoshopParseLayerMask(uint32_t &nPos, uint32_t nIndent) } uint32_t nRectA1, nRectA2, nRectA3, nRectA4; - uint32_t nRectB1, nRectB2, nRectB3, nRectB4; nRectA1 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); @@ -2022,17 +2040,20 @@ bool CDecodePs::PhotoshopParseLayerMask(uint32_t &nPos, uint32_t nIndent) // User mask density, 1 byte nTmp = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); } + if(nMaskParams & (1 << 1)) { // User mask feather, 8 bytes, double nTmp = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); nTmp = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); } + if(nMaskParams & (1 << 2)) { // Vector mask density, 1 byte nTmp = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); } + if(nMaskParams & (1 << 3)) { // Vector mask feather, 8 bytes, double @@ -2047,7 +2068,6 @@ bool CDecodePs::PhotoshopParseLayerMask(uint32_t &nPos, uint32_t nIndent) nRectB2 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); nRectB3 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); nRectB4 = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); - } return bDecOk; @@ -2087,6 +2107,7 @@ bool CDecodePs::PhotoshopParseLayerBlendingRanges(uint32_t &nPos, uint32_t nInde m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); // unsigned nSrcRng m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); // unsigned nDstRng } + return bDecOk; } @@ -2115,6 +2136,7 @@ bool CDecodePs::PhotoshopParseChannelImageData(uint32_t &nPos, uint32_t nIndent, { return true; } + // Read the line lengths into an array // - LOOP [nHeight] // - 16-bit: row length @@ -2124,6 +2146,7 @@ bool CDecodePs::PhotoshopParseChannelImageData(uint32_t &nPos, uint32_t nIndent, anRowLen = new uint32_t[nHeight]; Q_ASSERT(anRowLen); + for(uint32_t nRow = 0; nRow < nHeight; nRow++) { anRowLen[nRow] = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); @@ -2133,7 +2156,6 @@ bool CDecodePs::PhotoshopParseChannelImageData(uint32_t &nPos, uint32_t nIndent, for(uint32_t nRow = 0; (bDecOk) && (nRow < nHeight); nRow++) { uint32_t nRowLen = anRowLen[nRow]; - bDecOk = PhotoshopDecodeRowRle(nPos, nWidth, nHeight, nRow, nRowLen, nChan, pDibBits); } //nRow @@ -2143,7 +2165,6 @@ bool CDecodePs::PhotoshopParseChannelImageData(uint32_t &nPos, uint32_t nIndent, delete[]anRowLen; anRowLen = NULL; } - } else if(nCompressionMethod == 0) { @@ -2152,11 +2173,11 @@ bool CDecodePs::PhotoshopParseChannelImageData(uint32_t &nPos, uint32_t nIndent, { return true; } + for(uint32_t nRow = 0; (bDecOk) && (nRow < nHeight); nRow++) { bDecOk = PhotoshopDecodeRowUncomp(nPos, nWidth, nHeight, nRow, nChan, pDibBits); } - } else { @@ -2187,10 +2208,11 @@ bool CDecodePs::PhotoshopDecodeRowUncomp(uint32_t &nPos, uint32_t nWidth, uint32 if(pDibBits) { nRowActual = nHeight - nRow - 1; // Need to flip vertical for DIB - nPixByte = (nRowActual * nWidth + nCol) * sizeof(RGBQUAD); + nPixByte = (nRowActual * nWidth + nCol) * sizeof(QRgb); // Assign the RGB pixel map pDibBits[nPixByte + 3] = 0; + if(nChanID == 0) { pDibBits[nPixByte + 2] = nVal; @@ -2208,7 +2230,6 @@ bool CDecodePs::PhotoshopDecodeRowUncomp(uint32_t &nPos, uint32_t nWidth, uint32 } } // pDibBits #endif - } // nCol return bDecOk; @@ -2219,37 +2240,31 @@ bool CDecodePs::PhotoshopDecodeRowRle(uint32_t &nPos, uint32_t nWidth, uint32_t { bool bDecOk = true; - unsigned char nRleRun; - - signed char nRleRunS; - - uint32_t nRleRunCnt; + char nRleRunS; + unsigned char nRleRun; unsigned char nRleVal; + uint32_t nRleRunCnt; uint32_t nRowOffsetComp; // Row offset (compressed size) - uint32_t nRowOffsetDecomp; // Row offset (decompressed size) - uint32_t nRowOffsetDecompLast; - uint32_t nRowActual; - uint32_t nPixByte; // Decompress the row data nRowOffsetComp = 0; nRowOffsetDecomp = 0; nRowOffsetDecompLast = 0; + while((bDecOk) && (nRowOffsetComp < nRowLen)) { - // Save the position in the row before decompressing // the current RLE encoded entry nRowOffsetDecompLast = nRowOffsetDecomp; nRleRun = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); - nRleRunS = (signed char) (nRleRun); + nRleRunS = static_cast(nRleRun); nRowOffsetComp++; if(nRleRunS < 0) @@ -2264,12 +2279,14 @@ bool CDecodePs::PhotoshopDecodeRowRle(uint32_t &nPos, uint32_t nWidth, uint32_t if(pDibBits) { nRowActual = nHeight - nRow - 1; // Need to flip vertical for DIB + for(uint32_t nRunInd = 0; nRunInd < nRleRunCnt; nRunInd++) { - nPixByte = (nRowActual * nWidth + nRowOffsetDecompLast + nRunInd) * sizeof(RGBQUAD); + nPixByte = (nRowActual * nWidth + nRowOffsetDecompLast + nRunInd) * sizeof(QRgb); // Assign the RGB pixel map pDibBits[nPixByte + 3] = 0; + if(nChanID == 0) { pDibBits[nPixByte + 2] = nRleVal; @@ -2288,13 +2305,12 @@ bool CDecodePs::PhotoshopDecodeRowRle(uint32_t &nPos, uint32_t nWidth, uint32_t } // nRunInd } // pDibBits #endif - } else { - // Copy the next bytes as-is nRleRunCnt = 1 + nRleRunS; + for(uint32_t nRunInd = 0; nRunInd < nRleRunCnt; nRunInd++) { nRleVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); @@ -2305,10 +2321,11 @@ bool CDecodePs::PhotoshopDecodeRowRle(uint32_t &nPos, uint32_t nWidth, uint32_t if(pDibBits) { nRowActual = nHeight - nRow - 1; // Need to flip vertical for DIB - nPixByte = (nRowActual * nWidth + nRowOffsetDecompLast + nRunInd) * sizeof(RGBQUAD); + nPixByte = (nRowActual * nWidth + nRowOffsetDecompLast + nRunInd) * sizeof(QRgb); // Assign the RGB pixel map pDibBits[nPixByte + 3] = 0; + if(nChanID == 0) { pDibBits[nPixByte + 2] = nRleVal; @@ -2329,7 +2346,6 @@ bool CDecodePs::PhotoshopDecodeRowRle(uint32_t &nPos, uint32_t nWidth, uint32_t } // nRunInd } // nRleRunS - } // nRowOffsetComp // Now that we've finished the row, compare the decompressed size @@ -2366,9 +2382,7 @@ bool CDecodePs::PhotoshopParseImageData(uint32_t &nPos, uint32_t nIndent, tsImag //---- uint32_t nWidth = psImageInfo->nImageWidth; - uint32_t nHeight = psImageInfo->nImageHeight; - uint32_t nNumChans = psImageInfo->nNumChans; //---- @@ -2398,6 +2412,7 @@ bool CDecodePs::PhotoshopParseImageData(uint32_t &nPos, uint32_t nIndent, tsImag anRowLen = new uint32_t[nNumChans * nHeight]; Q_ASSERT(anRowLen); + for(uint32_t nRow = 0; nRow < (nNumChans * nHeight); nRow++) { anRowLen[nRow] = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); @@ -2420,7 +2435,6 @@ bool CDecodePs::PhotoshopParseImageData(uint32_t &nPos, uint32_t nIndent, tsImag delete[]anRowLen; anRowLen = NULL; } - } else if(nCompressionMethod == 0) { @@ -2434,6 +2448,7 @@ bool CDecodePs::PhotoshopParseImageData(uint32_t &nPos, uint32_t nIndent, tsImag { return true; } + for(uint32_t nChan = 0; nChan < nNumChans; nChan++) { for(uint32_t nRow = 0; (bDecOk) && (nRow < nHeight); nRow++) @@ -2441,7 +2456,6 @@ bool CDecodePs::PhotoshopParseImageData(uint32_t &nPos, uint32_t nIndent, tsImag bDecOk = PhotoshopDecodeRowUncomp(nPos, nWidth, nHeight, nRow, nChan, pDibBits); } //nRow } //nChan - } else { @@ -2451,7 +2465,6 @@ bool CDecodePs::PhotoshopParseImageData(uint32_t &nPos, uint32_t nIndent, tsImag } return bDecOk; - } // Parse the Photoshop IRB Global layer mask info @@ -2721,7 +2734,10 @@ bool CDecodePs::PhotoshopParseImageResourceBlock(uint32_t &nPos, uint32_t nInden QString strDebug; strDebug = - QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", -10).arg(strError); + QString("## File=[%1] Block=[%2] Error=[%3]\n") + .arg(m_pAppConfig->strCurFname, -100) + .arg("PsDecode", -10) + .arg(strError); qDebug() << (strDebug); #else Q_ASSERT(false); @@ -2731,7 +2747,6 @@ bool CDecodePs::PhotoshopParseImageResourceBlock(uint32_t &nPos, uint32_t nInden } uint32_t nBimId = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); - uint32_t nResNameLen = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); QString strResName = m_pWBuf->BufReadStrn(nPos, nResNameLen); @@ -2743,12 +2758,11 @@ bool CDecodePs::PhotoshopParseImageResourceBlock(uint32_t &nPos, uint32_t nInden { nPos += 1; } + uint32_t nBimLen = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); QString strTmp; - QString strBimName; - QString strByte; // Lookup 8BIM defined name @@ -2765,12 +2779,11 @@ bool CDecodePs::PhotoshopParseImageResourceBlock(uint32_t &nPos, uint32_t nInden strBimDefName = asBimRecords[nFldInd].strRecordName; } - strTmp = - QString("8BIM: [0x%1] Name=\"%2\" Len=[0x%3] DefinedName=\"%4\"").arg(nBimId, 4, 16, QChar('0')).arg(strBimName).arg(nBimLen, - 4, 16, - QChar - ('0')). - arg(strBimDefName); + strTmp = QString("8BIM: [0x%1] Name=\"%2\" Len=[0x%3] DefinedName=\"%4\"") + .arg(nBimId, 4, 16, QChar('0')) + .arg(strBimName) + .arg(nBimLen, 4, 16, QChar('0')) + .arg(strBimDefName); PhotoshopParseReportNote(nIndent, strTmp); nIndent++; @@ -2779,11 +2792,9 @@ bool CDecodePs::PhotoshopParseImageResourceBlock(uint32_t &nPos, uint32_t nInden { // If length is zero, then skip this block PhotoshopParseReportNote(nIndent, "Length is zero. Skipping."); - } else if(bBimKnown) { - // Save the file pointer uint32_t nPosSaved; @@ -2900,21 +2911,23 @@ bool CDecodePs::PhotoshopParseImageResourceBlock(uint32_t &nPos, uint32_t nInden if(nPos > nPosEnd + 1) { // Length mismatch detected: we read too much (versus length) - strTmp = - QString - ("ERROR: Parsing exceeded expected length. Stopping decode. BIM=[%s], CurPos=[0x%08X], ExpPosEnd=[0x%08X], ExpLen=[%u]"). - arg(strBimDefName).arg(nPos, 8, 16, QChar('0')).arg(nPosEnd + 1, 8, 16, QChar('0')).arg(nBimLen); + strTmp = QString("ERROR: Parsing exceeded expected length. Stopping decode. BIM=[%1], CurPos=[0x%2], ExpPosEnd=[0x%3], ExpLen=[%4]") + .arg(strBimDefName) + .arg(nPos, 8, 16, QChar('0')) + .arg(nPosEnd + 1, 8, 16, QChar('0')) + .arg(nBimLen); m_pLog->AddLineErr(strTmp); #ifdef DEBUG_LOG QString strDebug; - strDebug = - QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", -10).arg(strTmp); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n") + .arg(m_pAppConfig->strCurFname, -100) + .arg("PsDecode", -10) + .arg(strTmp); qDebug() << (strDebug); #else Q_ASSERT(false); #endif - // TODO: Add interactive error message here // Now we should roll-back the file position to the position indicated @@ -2928,15 +2941,18 @@ bool CDecodePs::PhotoshopParseImageResourceBlock(uint32_t &nPos, uint32_t nInden // Length mismatch detected: we read too little (versus length) // This is generally an indication that either I haven't accurately captured the // specific block parsing format or else the specification is loose. - strTmp = - QString("WARNING: Parsing offset length mismatch. Current pos=[0x%1], expected end pos=[0x%2], expect length=[%3]"). - arg(nPos, 8, 16, QChar('0')).arg(nPosEnd + 1, 8, 16, QChar('0')).arg(nBimLen); + strTmp = QString("WARNING: Parsing offset length mismatch. Current pos=[0x%1], expected end pos=[0x%2], expect length=[%3]") + .arg(nPos, 8, 16, QChar('0')) + .arg(nPosEnd + 1, 8, 16, QChar('0')) + .arg(nBimLen); m_pLog->AddLineWarn(strTmp); #ifdef DEBUG_LOG QString strDebug; - strDebug = - QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", -10).arg(strTmp); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n") + .arg(m_pAppConfig->strCurFname, -100) + .arg("PsDecode", -10) + .arg(strTmp); qDebug() << (strDebug); #endif return false; @@ -3009,7 +3025,6 @@ void CDecodePs::PhotoshopParseSliceHeader(uint32_t &nPos, uint32_t nIndent, uint } if(nNumSlices > 0) PhotoshopParseReportNote(nIndent, "-----"); - } else if((nSliceVer == 7) || (nSliceVer == 8)) { @@ -3017,7 +3032,6 @@ void CDecodePs::PhotoshopParseSliceHeader(uint32_t &nPos, uint32_t nIndent, uint PhotoshopParseReportFldNum(nIndent, "Descriptor version", nVal, ""); PhotoshopParseDescriptor(nPos, nIndent); } - } // Parse the Photoshop IRB Slice Resource @@ -3049,11 +3063,13 @@ void CDecodePs::PhotoshopParseSliceResource(uint32_t &nPos, uint32_t nIndent, ui uint32_t nOrigin = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); PhotoshopParseReportFldNum(nIndent, "Origin", nOrigin, ""); + if(nOrigin == 1) { nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); PhotoshopParseReportFldNum(nIndent, "Associated Layer ID", nVal, ""); } + strVal = PhotoshopParseGetBimLStrUni(nPos, nPosOffset); nPos += nPosOffset; PhotoshopParseReportFldStr(nIndent, "Name", strVal); @@ -3106,7 +3122,6 @@ void CDecodePs::PhotoshopParseSliceResource(uint32_t &nPos, uint32_t nIndent, ui // after reading the descriptor version?) if(nPos <= nPosEnd) { - nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); PhotoshopParseReportFldNum(nIndent, "Descriptor version", nVal, ""); @@ -3128,10 +3143,8 @@ void CDecodePs::PhotoshopParseSliceResource(uint32_t &nPos, uint32_t nIndent, ui // NOTE: // - This IRB is private, so reverse-engineered and may not be per spec // -void CDecodePs::PhotoshopParseJpegQuality(uint32_t &nPos, uint32_t nIndent, uint32_t nPosEnd) +void CDecodePs::PhotoshopParseJpegQuality(uint32_t &nPos, uint32_t nIndent, uint32_t) { - nPosEnd; // Unreferenced param - uint32_t nVal; QString strVal; @@ -3141,6 +3154,7 @@ void CDecodePs::PhotoshopParseJpegQuality(uint32_t &nPos, uint32_t nIndent, uint // Save As Quality // Index 0: Quality level nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + switch (nVal) { case 0xFFFD: @@ -3183,6 +3197,7 @@ void CDecodePs::PhotoshopParseJpegQuality(uint32_t &nPos, uint32_t nIndent, uint m_nQualitySaveAs = 0; break; } + if(m_nQualitySaveAs != 0) { PhotoshopParseReportFldNum(nIndent, "Photoshop Save As Quality", m_nQualitySaveAs, ""); @@ -3194,6 +3209,7 @@ void CDecodePs::PhotoshopParseJpegQuality(uint32_t &nPos, uint32_t nIndent, uint // Index 1: Format nSaveFormat = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + switch (nSaveFormat) { case 0x0000: @@ -3209,11 +3225,13 @@ void CDecodePs::PhotoshopParseJpegQuality(uint32_t &nPos, uint32_t nIndent, uint strVal = "???"; break; } + PhotoshopParseReportFldStr(nIndent, "Photoshop Save Format", strVal); // Index 2: Progressive Scans // - Only meaningful if Progressive mode nVal = m_pWBuf->BufRdAdv2(nPos, PS_BSWAP); + switch (nVal) { case 0x0001: @@ -3229,12 +3247,12 @@ void CDecodePs::PhotoshopParseJpegQuality(uint32_t &nPos, uint32_t nIndent, uint strVal = "???"; break; } + PhotoshopParseReportFldStr(nIndent, "Photoshop Save Progressive Scans", strVal); // Not sure what this byte is for nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); PhotoshopParseReportFldNum(nIndent, "???", nVal, ""); - } // Decode the OSType field and invoke the appropriate IRB parsing handler @@ -3305,21 +3323,19 @@ void CDecodePs::PhotoshopParseHandleOsType(QString strOsType, uint32_t &nPos, ui } else { - #ifdef DEBUG_LOG QString strError; - QString strDebug; strError = QString("ERROR: Unsupported OSType [%1]").arg(strOsType); - strDebug = - QString("## File=[%-100s] Block=[%-10s] Error=[%s]\n").arg(m_pAppConfig->strCurFname, -100).arg("PsDecode", - -10).arg(strError); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n") + .arg(m_pAppConfig->strCurFname, -100) + .arg("PsDecode", -10) + .arg(strError); qDebug() << (strDebug); #else Q_ASSERT(false); #endif - } } @@ -3352,6 +3368,7 @@ void CDecodePs::PhotoshopParseDescriptor(uint32_t &nPos, uint32_t nIndent) if(nDescNumItems > 0) PhotoshopParseReportNote(nIndent, "-----"); + for(uint32_t nDescInd = 0; nDescInd < nDescNumItems; nDescInd++) { QString strDescInd; @@ -3364,12 +3381,17 @@ void CDecodePs::PhotoshopParseDescriptor(uint32_t &nPos, uint32_t nIndent) QString strOsType; - strOsType = QString("%1%2%3%4").arg(Buf(nPos + 0)).arg(Buf(nPos + 1)).arg(Buf(nPos + 2)).arg(Buf(nPos + 3)); + strOsType = QString("%1%2%3%4") + .arg(Buf(nPos + 0)) + .arg(Buf(nPos + 1)) + .arg(Buf(nPos + 2)) + .arg(Buf(nPos + 3)); nPos += 4; PhotoshopParseReportFldStr(nIndent + 1, "OSType key", strOsType); PhotoshopParseHandleOsType(strOsType, nPos, nIndent + 1); } + if(nDescNumItems > 0) PhotoshopParseReportNote(nIndent, "-----"); } @@ -3384,7 +3406,6 @@ void CDecodePs::PhotoshopParseDescriptor(uint32_t &nPos, uint32_t nIndent) void CDecodePs::PhotoshopParseList(uint32_t &nPos, uint32_t nIndent) { QString strVal; - QString strLine; uint32_t nNumItems = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); @@ -3393,6 +3414,7 @@ void CDecodePs::PhotoshopParseList(uint32_t &nPos, uint32_t nIndent) if(nNumItems > 0) PhotoshopParseReportNote(nIndent, "-----"); + for(uint32_t nItemInd = 0; nItemInd < nNumItems; nItemInd++) { QString strItemInd; @@ -3402,12 +3424,17 @@ void CDecodePs::PhotoshopParseList(uint32_t &nPos, uint32_t nIndent) QString strOsType; - strOsType = QString("%1%2%3%4").arg(Buf(nPos + 0)).arg(Buf(nPos + 1)).arg(Buf(nPos + 2)).arg(Buf(nPos + 3)); + strOsType = QString("%1%2%3%4") + .arg(Buf(nPos + 0)) + .arg(Buf(nPos + 1)) + .arg(Buf(nPos + 2)) + .arg(Buf(nPos + 3)); nPos += 4; PhotoshopParseReportFldStr(nIndent + 1, "OSType key", strVal); PhotoshopParseHandleOsType(strOsType, nPos, nIndent + 1); } + if(nNumItems > 0) PhotoshopParseReportNote(nIndent, "-----"); } @@ -3424,7 +3451,6 @@ void CDecodePs::PhotoshopParseInteger(uint32_t &nPos, uint32_t nIndent) uint32_t nVal; QString strVal; - QString strLine; nVal = m_pWBuf->BufRdAdv4(nPos, PS_BSWAP); @@ -3443,7 +3469,6 @@ void CDecodePs::PhotoshopParseBool(uint32_t &nPos, uint32_t nIndent) uint32_t nVal; QString strVal; - QString strLine; nVal = m_pWBuf->BufRdAdv1(nPos, PS_BSWAP); @@ -3460,7 +3485,6 @@ void CDecodePs::PhotoshopParseBool(uint32_t &nPos, uint32_t nIndent) void CDecodePs::PhotoshopParseEnum(uint32_t &nPos, uint32_t nIndent) { QString strVal; - QString strLine; strVal = PhotoshopParseGetLStrAsc(nPos); @@ -3468,7 +3492,6 @@ void CDecodePs::PhotoshopParseEnum(uint32_t &nPos, uint32_t nIndent) strVal = PhotoshopParseGetLStrAsc(nPos); PhotoshopParseReportFldStr(nIndent, "Enum", strVal); - } // Parse the Photoshop IRB Unicode String diff --git a/source/DecodePs.h b/source/DecodePs.h index 030fcbb..0bbfb09 100644 --- a/source/DecodePs.h +++ b/source/DecodePs.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -27,10 +27,10 @@ #define DECODEPS_H #include "WindowBuf.h" -#include "snoop.h" -#include "SnoopConfig.h" +//#include "snoop.h" -#include "Dib.h" +class CDocLog; +class CSnoopConfig; // // Structure used for each IPTC field @@ -154,14 +154,22 @@ struct tsImageInfo class CDecodePs { public: - CDecodePs(CwindowBuf * pWBuf, CDocLog * pLog); + CDecodePs(CwindowBuf *pWBuf, CDocLog * pLog, CSnoopConfig *pAppConfig); ~CDecodePs(void); void Reset(); - bool DecodePsd(uint32_t nPos, CDIB * pDibTemp, uint32_t &nWidth, uint32_t &nHeight); + bool DecodePsd(uint32_t nPos, QImage * pDibTemp, int32_t &nWidth, int32_t &nHeight); bool PhotoshopParseImageResourceBlock(uint32_t &nPos, uint32_t nIndent); + bool m_bPsd; + uint32_t m_nQualitySaveAs; + uint32_t m_nQualitySaveForWeb; + + bool m_bDisplayLayer; + uint32_t m_nDisplayLayerInd; + bool m_bDisplayImage; + private: CDecodePs &operator = (const CDecodePs&); CDecodePs(CDecodePs&); @@ -209,8 +217,8 @@ class CDecodePs void PhotoshopParseLayerSelectId(uint32_t &nPos, uint32_t nIndent); void PhotoshopParseJpegQuality(uint32_t &nPos, uint32_t nIndent, uint32_t nPosEnd); - bool PhotoshopParseLayerMaskInfo(uint32_t &nPos, uint32_t nIndent, CDIB * pDibTemp); - bool PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, CDIB * pDibTemp); + bool PhotoshopParseLayerMaskInfo(uint32_t &nPos, uint32_t nIndent, QImage * pDibTemp); + bool PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, QImage * pDibTemp); bool PhotoshopParseLayerRecord(uint32_t &nPos, uint32_t nIndent, tsLayerInfo * psLayerInfo); bool PhotoshopParseLayerMask(uint32_t &nPos, uint32_t nIndent); bool PhotoshopParseLayerBlendingRanges(uint32_t &nPos, uint32_t nIndent); @@ -238,7 +246,6 @@ class CDecodePs quint8 Buf(uint32_t offset, bool bClean); -private: // Configuration CSnoopConfig * m_pAppConfig; @@ -247,15 +254,6 @@ class CDecodePs CDocLog *m_pLog; bool m_bAbort; // Abort continued decode? - -public: - bool m_bPsd; - uint32_t m_nQualitySaveAs; - uint32_t m_nQualitySaveForWeb; - - bool m_bDisplayLayer; - uint32_t m_nDisplayLayerInd; - bool m_bDisplayImage; }; #endif diff --git a/source/Dib.cpp b/source/Dib.cpp deleted file mode 100644 index 7102a60..0000000 --- a/source/Dib.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code was loosely based on an example CDIB class that appears in the following book: -// -// Title: Visual C++ 6 Unleashed -// Authors: Mickey Williams and David Bennett -// Publisher: Sams (July 24, 2000) -// ISBN-10: 0672312417 -// ISBN-13: 978-0672312410 -// ==================================================================================================== - -#include "stdafx.h" -#include "dib.h" - - - -CDIB::CDIB() : m_pDIB(NULL) -{ -} - -CDIB::~CDIB() -{ - if (m_pDIB) delete m_pDIB; -} - -void CDIB::Kill() -{ - if (m_pDIB) { - delete m_pDIB; - m_pDIB = FALSE; - } -} - -bool CDIB::CreateDIB(DWORD dwWidth,DWORD dwHeight,unsigned short nBits) -{ - if (m_pDIB) return FALSE; - const DWORD dwcBihSize = sizeof(BITMAPINFOHEADER); - - // Calculate the memory required for the DIB - - // Note that we don't actually use the color table (so 1*QUAD is not actually used) - // Extra +4 is just in case we're not aligned to word boundary - DWORD dwSize = dwcBihSize + - 1 * sizeof(RGBQUAD) + - ( (dwWidth * dwHeight) * sizeof(RGBQUAD) ) + - 4; - - - m_pDIB = (LPBITMAPINFO)new BYTE[dwSize]; - if (!m_pDIB) return FALSE; - - //CAL! Added - // Erase the DIB - memset(m_pDIB,0x00,dwSize); - - m_pDIB->bmiHeader.biSize = dwcBihSize; - m_pDIB->bmiHeader.biWidth = dwWidth; - m_pDIB->bmiHeader.biHeight = dwHeight; - m_pDIB->bmiHeader.biBitCount = nBits; - m_pDIB->bmiHeader.biPlanes = 1; - m_pDIB->bmiHeader.biCompression = BI_RGB; - m_pDIB->bmiHeader.biXPelsPerMeter = 1000; - m_pDIB->bmiHeader.biYPelsPerMeter = 1000; - m_pDIB->bmiHeader.biClrUsed = 0; - m_pDIB->bmiHeader.biClrImportant = 0; - - InitializeColors(); - return TRUE; -} - - -void CDIB::InitializeColors() -{ - if (!m_pDIB) return; - // This just initializes all colors to black - - LPRGBQUAD lpColors = m_pDIB->bmiColors; - - for(int i=0;ibmiHeader.biBitCount > 8) { - return 0; - } else { - return (2>>m_pDIB->bmiHeader.biBitCount); - } -} - -void* CDIB::GetDIBBitArray() const -{ - if (!m_pDIB) return FALSE; - - unsigned char* ptr; - ptr = (unsigned char*)m_pDIB; - ptr += m_pDIB->bmiHeader.biSize; - ptr += GetDIBCols() * sizeof(RGBQUAD); - return (void*)ptr; - -} - -bool CDIB::CreateDIBFromBitmap(CDC* pDC) -{ - if (!pDC) return FALSE; - HDC hDC = pDC->GetSafeHdc(); - - BITMAP bimapInfo; - m_bmBitmap.GetBitmap(&bimapInfo); - if (!CreateDIB(bimapInfo.bmWidth,bimapInfo.bmHeight, - bimapInfo.bmBitsPixel)) return FALSE; - - LPRGBQUAD lpColors = m_pDIB->bmiColors; - - - SetDIBColorTable(hDC,0,GetDIBCols(),lpColors); - - // This implicitly assumes that the source bitmap - // is at the 1 pixel per mm resolution - bool bSuccess = (GetDIBits(hDC,(HBITMAP)m_bmBitmap, - 0,bimapInfo.bmHeight,GetDIBBitArray(), - m_pDIB,DIB_RGB_COLORS) > 0); - return bSuccess; -} - -bool CDIB::CopyDIB(CDC* pDestDC,int x,int y,float scale) -{ - if (!m_pDIB || !pDestDC) return FALSE; - int nOldMapMode = pDestDC->SetMapMode(MM_TEXT); - - // NOTE: The following line was added to make the down-sampling - // (zoom < 100%) look much better. Otherwise, the display doesn't look nice. - SetStretchBltMode(pDestDC->GetSafeHdc(),COLORONCOLOR); - - bool bOK = StretchDIBits(pDestDC->GetSafeHdc(), - x,y, - (unsigned)(m_pDIB->bmiHeader.biWidth * scale), // Dest Width - (unsigned)(m_pDIB->bmiHeader.biHeight * scale), // Dest Height - 0,0, - m_pDIB->bmiHeader.biWidth, // Source Width - m_pDIB->bmiHeader.biHeight, // Source Height - GetDIBBitArray(),m_pDIB,DIB_RGB_COLORS,SRCCOPY) > 0; - - pDestDC->SetMapMode(nOldMapMode); - return bOK; -} - -bool CDIB::CopyDibDblBuf(CDC* pDestDC, int x, int y,CRect* rectClient, float scale) -{ - HDC hdcMem; - HBITMAP hbmMem; - HANDLE hOld; - - int win_width = rectClient->Width(); - int win_height = rectClient->Height(); - - - // Create an off-screen DC for double-buffering - hdcMem = CreateCompatibleDC(pDestDC->GetSafeHdc()); - hbmMem = CreateCompatibleBitmap(pDestDC->GetSafeHdc(), win_width, win_height); - hOld = SelectObject(hdcMem, hbmMem); - - // Draw into hdcMem - - bool bOK = StretchDIBits(hdcMem, //hdcMem->GetSafeHdc(), - x,y, - (unsigned)(m_pDIB->bmiHeader.biWidth * scale), // Dest Width - (unsigned)(m_pDIB->bmiHeader.biHeight * scale), // Dest Height - 0,0, - m_pDIB->bmiHeader.biWidth, // Source Width - m_pDIB->bmiHeader.biHeight, // Source Height - GetDIBBitArray(),m_pDIB,DIB_RGB_COLORS,SRCCOPY) > 0; - - // Transfer the off-screen DC to the screen - BitBlt(pDestDC->GetSafeHdc(), 0, 0, win_width, win_height, hdcMem, 0, 0, SRCCOPY); - - // Free-up the off-screen DC - SelectObject(hdcMem, hOld); - DeleteObject(hbmMem); - DeleteDC (hdcMem); - - return bOK; - -} - - -bool CDIB::CopyDibPart(CDC* pDestDC,CRect rectImg,CRect* rectClient, float scale) -{ - scale; // Unreferenced param - - if (!m_pDIB || !pDestDC) return FALSE; - - int nDstW; - int nDstH; - int nDstX; - int nDstY; - int nSrcX; - int nSrcY; - int nSrcW; - int nSrcH; - CRect rectSrc; - CRect rectInter; - - // Determine boundaries of region to copy - rectInter.IntersectRect(rectClient,rectImg); - - // Now determine what original source rect this corresponds to - rectSrc = rectInter; - rectSrc.OffsetRect(-rectImg.left,-rectImg.top); - nSrcX = rectSrc.left; - nSrcY = rectSrc.top; - nSrcW = rectInter.Width(); - nSrcH = rectInter.Height(); - nDstX = rectInter.left;// - rectClient->left; - nDstY = rectInter.top;// - rectClient->top; - nDstW = rectInter.Width(); - nDstH = rectInter.Height(); - - int nOldMapMode = pDestDC->SetMapMode(MM_TEXT); - - // NOTE: Original code would have used StretchDIBits() here - // but it doesn't appear to work correctly. See workaround at: - // http://wiki.allegro.cc/StretchDIBits - - nSrcX = rectInter.left; - nSrcY = rectInter.top; - nSrcW = rectClient->Width(); - nSrcH = rectClient->Height(); - - nDstX = rectInter.left; - nDstY = rectInter.top; - nDstW = rectClient->Width(); - nDstH = rectClient->Height(); - - int nBmpH; - int nStDstX; - int nStDstY; - int nStDstW; - int nStDstH; - int nStSrcX; - int nStSrcY; - int nStSrcW; - int nStSrcH; - - nBmpH = rectImg.Height(); - - nStDstX = nDstX; - nStDstY = nDstH + nDstY - 1; - nStDstW = nDstW; - nStDstH = -nDstH; - - nStSrcX = nSrcX; - nStSrcY = nBmpH - nSrcY + 1; - nStSrcW = nSrcW; - nStSrcH = -nSrcH; - - - bool bOK = StretchDIBits(pDestDC->GetSafeHdc(), - nStDstX,nStDstY, // Dest X,Y - nStDstW, // Dest Width - nStDstH, // Dest Height - nStSrcX,nStSrcY, // Source X,Y - nStSrcW, // Source Width - nStSrcH, // Source Height - GetDIBBitArray(),m_pDIB,DIB_RGB_COLORS,SRCCOPY) > 0; - - pDestDC->SetMapMode(nOldMapMode); - return bOK; -} - - - -// Attempt to create a double-buffer so that we can do our -// own resize function as the StretchDIBits() looks terrible -// for downsampling! -// -// NOTE: the following is currently unused as it led to strange -// redraw issues, likely due to client rect boundaries -bool CDIB::CopyDIBsmall(CDC* pDestDC,int x,int y,float scale) -{ - if (!m_pDIB || !pDestDC) return FALSE; - - // -------------- - CDC dcm; - CRect rc; - pDestDC->GetWindow()->GetClientRect(rc); - //GetClientRect(rc); - dcm.CreateCompatibleDC(pDestDC); - CBitmap bmt; - bmt.CreateCompatibleBitmap(pDestDC,rc.Width(),rc.Height()); - CBitmap *pBitmapOld = dcm.SelectObject(&bmt); - - dcm.Rectangle(rc);// make the work of the OnEraseBkgnd function - - // DRAWING start - int nOldMapMode = dcm.SetMapMode(MM_TEXT); - bool bOK = StretchDIBits(dcm.GetSafeHdc(), - x,y, - (unsigned)(m_pDIB->bmiHeader.biWidth * scale), // Dest Width - (unsigned)(m_pDIB->bmiHeader.biHeight * scale), // Dest Height - 0,0, - m_pDIB->bmiHeader.biWidth, // Source Width - m_pDIB->bmiHeader.biHeight, // Source Height - GetDIBBitArray(),m_pDIB,DIB_RGB_COLORS,SRCCOPY) > 0; - - dcm.SetMapMode(nOldMapMode); - // DRAWING end - - // Copy over - BitBlt(pDestDC->m_hDC,0,0,rc.Width(),rc.Height(),dcm.m_hDC,0,0,SRCCOPY); - - dcm.SelectObject(pBitmapOld); - // drop other objects from the dc context memory - if there are. - - return bOK; -} - diff --git a/source/Dib.h b/source/Dib.h deleted file mode 100644 index f904465..0000000 --- a/source/Dib.h +++ /dev/null @@ -1,125 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code was loosely based on an example CDIB class that appears in the following book: -// -// Title: Visual C++ 6 Unleashed -// Authors: Mickey Williams and David Bennett -// Publisher: Sams (July 24, 2000) -// ISBN-10: 0672312417 -// ISBN-13: 978-0672312410 -// ==================================================================================================== - -#ifndef DIB_H -#define DIB_H - -#include -#include -#include - -// TODO: Note that this file (Dib) will likely be removed soon -#include - -#define BI_RGB 0 - -// TODO: Confirm appropriate mapping (LONG & DWORD) -typedef long LONG; -typedef unsigned char BYTE; -typedef unsigned long DWORD; -typedef unsigned short WORD; - -// TODO: Remove the following as already defined in windows.h -#if 0 - -typedef struct tagBITMAPFILEHEADER -{ - WORD bfType; // 2 /* Magic identifier */ - DWORD bfSize; // 4 /* File size in bytes */ - WORD bfReserved1; // 2 - WORD bfReserved2; // 2 - DWORD bfOffBits; // 4 /* Offset to image data, bytes */ -} __attribute__((packed)) BITMAPFILEHEADER; - -typedef struct tagBITMAPINFOHEADER -{ - DWORD biSize; // 4 /* Header size in bytes */ - LONG biWidth; // 4 /* Width of image */ - LONG biHeight; // 4 /* Height of image */ - WORD biPlanes; // 2 /* Number of colour planes */ - WORD biBitCount; // 2 /* Bits per pixel */ - DWORD biCompression; // 4 /* Compression type */ - DWORD biSizeImage; // 4 /* Image size in bytes */ - LONG biXPelsPerMeter; // 4 - LONG biYPelsPerMeter; // 4 /* Pixels per meter */ - DWORD biClrUsed; // 4 /* Number of colours */ - DWORD biClrImportant; // 4 /* Important colours */ -} BITMAPINFOHEADER; - -typedef struct tagRGBQUAD -{ - unsigned char rgbBlue; - unsigned char rgbGreen; - unsigned char rgbRed; - unsigned char rgbReserved; -} RGBQUAD, *LPRGBQUAD; - -typedef struct tagBITMAPINFO -{ - BITMAPINFOHEADER bmiHeader; - RGBQUAD bmiColors[1]; -} BITMAPINFO, *LPBITMAPINFO; - -#endif // - -typedef struct -{ - BYTE b; - BYTE g; - BYTE r; -} RGB_data; // RGB TYPE, plz also make sure the order - -class CDIB : public QObject -{ -public: - CDIB(); - virtual ~CDIB(); - - void Kill(); - bool CreateDIB(quint32 dwWidth,quint32 dwHeight,unsigned short nBits); -// bool CreateDIBFromBitmap(CDC* pDC); - void InitializeColors(); - int GetDIBCols() const; - void* GetDIBBitArray() const; -// bool CopyDIB(CDC* pDestDC,int x,int y,float scale=1); -// bool CopyDibDblBuf(CDC* pDestDC, int x, int y,QRect* rectClient, float scale); -// bool CopyDIBsmall(CDC* pDestDC,int x,int y,float scale=1); -// bool CopyDibPart(CDC* pDestDC,QRect rectImg,QRect* rectClient, float scale); - - QBitmap m_bmBitmap; - -private: - CDIB &operator = (const CDIB&); - CDIB(CDIB&); - - LPBITMAPINFO m_pDIB; -}; - -#endif diff --git a/source/DocLog.cpp b/source/DocLog.cpp index 41ad41b..f81f3fb 100644 --- a/source/DocLog.cpp +++ b/source/DocLog.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/DocLog.h b/source/DocLog.h index 1d3b5ee..a8a7d78 100644 --- a/source/DocLog.h +++ b/source/DocLog.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/ExportDlg.cpp b/source/ExportDlg.cpp deleted file mode 100644 index 307213e..0000000 --- a/source/ExportDlg.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ExportDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "ExportDlg.h" -#include ".\exportdlg.h" - - -// CExportDlg dialog - -IMPLEMENT_DYNAMIC(CExportDlg, CDialog) -CExportDlg::CExportDlg(CWnd* pParent /*=NULL*/) - : CDialog(CExportDlg::IDD, pParent) - , m_bOverlayEn(FALSE) - , m_bDhtAviInsert(FALSE) - , m_strOffsetStart(_T("")) - , m_bForceEoi(FALSE) - , m_bIgnoreEoi(FALSE) - , m_bForceSoi(FALSE) - , m_bExtractAllEn(FALSE) -{ -} - -CExportDlg::~CExportDlg() -{ -} - -void CExportDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Check(pDX, IDC_OVERLAY, m_bOverlayEn); - DDX_Check(pDX, IDC_DHTAVI, m_bDhtAviInsert); - DDX_Text(pDX, IDC_OFFSET_START, m_strOffsetStart); - DDX_Check(pDX, IDC_FORCE_EOI, m_bForceEoi); - DDX_Check(pDX, IDC_IGNORE_EOI, m_bIgnoreEoi); - DDX_Check(pDX, IDC_FORCE_SOI, m_bForceSoi); - DDX_Check(pDX, IDC_EXT_ALL, m_bExtractAllEn); -} - - -BEGIN_MESSAGE_MAP(CExportDlg, CDialog) -END_MESSAGE_MAP() - - diff --git a/source/ExportDlg.h b/source/ExportDlg.h deleted file mode 100644 index c71d49c..0000000 --- a/source/ExportDlg.h +++ /dev/null @@ -1,54 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box providing options for exporting to JPEG -// -// ========================================================================== - - -#pragma once - - -// CExportDlg dialog - -class CExportDlg : public CDialog -{ - DECLARE_DYNAMIC(CExportDlg) - -public: - CExportDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CExportDlg(); - -// Dialog Data - enum { IDD = IDD_EXPORTDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -public: - BOOL m_bOverlayEn; - BOOL m_bDhtAviInsert; - CString m_strOffsetStart; - BOOL m_bForceEoi; - BOOL m_bIgnoreEoi; - BOOL m_bForceSoi; - BOOL m_bExtractAllEn; -}; diff --git a/source/ExportTiffDlg.cpp b/source/ExportTiffDlg.cpp deleted file mode 100644 index 689d8cb..0000000 --- a/source/ExportTiffDlg.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ExportTiffDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "ExportTiffDlg.h" -#include ".\exporttiffdlg.h" - - -// CExportTiffDlg dialog - -IMPLEMENT_DYNAMIC(CExportTiffDlg, CDialog) -CExportTiffDlg::CExportTiffDlg(CWnd* pParent /*=NULL*/) - : CDialog(CExportTiffDlg::IDD, pParent) - , m_nCtlFmt(0) - , m_sFname(_T("")) -{ -} - -CExportTiffDlg::~CExportTiffDlg() -{ -} - -void CExportTiffDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Radio(pDX, IDC_RAD_RGB8, m_nCtlFmt); - DDX_Text(pDX, IDC_EDIT_FNAME, m_sFname); -} - - -BEGIN_MESSAGE_MAP(CExportTiffDlg, CDialog) -END_MESSAGE_MAP() - - -// CExportTiffDlg message handlers - -BOOL CExportTiffDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - m_nCtlFmt = 0; - UpdateData(false); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} diff --git a/source/ExportTiffDlg.h b/source/ExportTiffDlg.h deleted file mode 100644 index 1a0eec0..0000000 --- a/source/ExportTiffDlg.h +++ /dev/null @@ -1,52 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box providing options for exporting to TIFF -// -// ========================================================================== - - -#pragma once -#include "afxwin.h" - - -// CExportTiffDlg dialog - -class CExportTiffDlg : public CDialog -{ - DECLARE_DYNAMIC(CExportTiffDlg) - -public: - CExportTiffDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CExportTiffDlg(); - -// Dialog Data - enum { IDD = IDD_EXPORTTIFFDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -public: - virtual BOOL OnInitDialog(); - - int m_nCtlFmt; - CString m_sFname; -}; diff --git a/source/FileTiff.cpp b/source/FileTiff.cpp deleted file mode 100644 index fa41386..0000000 --- a/source/FileTiff.cpp +++ /dev/null @@ -1,539 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "stdafx.h" - -#include "FileTiff.h" - - -FileTiff::FileTiff() -{ - m_pFileOutput = NULL; - m_nPtrIfdExtra = 0; - m_nPtrImg = 0; - m_nPos = 0; - m_pIfdExtraBuf = NULL; -} - -FileTiff::~FileTiff() -{ - if (m_pFileOutput) { - delete m_pFileOutput; - m_pFileOutput = NULL; - } - if (m_pIfdExtraBuf) { - delete m_pIfdExtraBuf; - m_pIfdExtraBuf = NULL; - } -} - -void FileTiff::WriteVal8(BYTE nVal) -{ - if (!m_bPreCalc) { - m_pFileOutput->Write(&nVal,1); - } - m_nPos += 1; -} -void FileTiff::WriteIfdExtraBuf8(BYTE nVal) -{ - if (!m_bPreCalc) { - ASSERT (m_pIfdExtraBuf); - m_pIfdExtraBuf[m_nIfdExtraLen+0] = nVal; - } - m_nIfdExtraLen += 1; - -} - -void FileTiff::WriteVal16(unsigned short nVal) -{ - if (!m_bPreCalc) { - BYTE nTmp[2]; - nTmp[0] = (nVal & 0xFF00) >> 8; - nTmp[1] = (nVal & 0x00FF) >> 0; - m_pFileOutput->Write(&(nTmp[0]),1); - m_pFileOutput->Write(&(nTmp[1]),1); - } - m_nPos += 2; -} -void FileTiff::WriteIfdExtraBuf16(unsigned short nVal) -{ - if (!m_bPreCalc) { - BYTE nTmp[2]; - nTmp[0] = (nVal & 0xFF00) >> 8; - nTmp[1] = (nVal & 0x00FF) >> 0; - ASSERT (m_pIfdExtraBuf); - m_pIfdExtraBuf[m_nIfdExtraLen+0] = nTmp[0]; - m_pIfdExtraBuf[m_nIfdExtraLen+1] = nTmp[1]; - } - m_nIfdExtraLen += 2; -} - - -void FileTiff::WriteVal32(unsigned int nVal) -{ - if (!m_bPreCalc) { - BYTE nTmp[4]; - nTmp[0] = static_cast((nVal & 0xFF000000) >> 24); - nTmp[1] = static_cast((nVal & 0x00FF0000) >> 16); - nTmp[2] = static_cast((nVal & 0x0000FF00) >> 8); - nTmp[3] = static_cast((nVal & 0x000000FF) >> 0); - m_pFileOutput->Write(&(nTmp[0]),1); - m_pFileOutput->Write(&(nTmp[1]),1); - m_pFileOutput->Write(&(nTmp[2]),1); - m_pFileOutput->Write(&(nTmp[3]),1); - } - m_nPos += 4; -} -void FileTiff::WriteIfdExtraBuf32(unsigned int nVal) -{ - if (!m_bPreCalc) { - BYTE nTmp[4]; - nTmp[0] = static_cast((nVal & 0xFF000000) >> 24); - nTmp[1] = static_cast((nVal & 0x00FF0000) >> 16); - nTmp[2] = static_cast((nVal & 0x0000FF00) >> 8); - nTmp[3] = static_cast((nVal & 0x000000FF) >> 0); - ASSERT (m_pIfdExtraBuf); - m_pIfdExtraBuf[m_nIfdExtraLen+0] = nTmp[0]; - m_pIfdExtraBuf[m_nIfdExtraLen+1] = nTmp[1]; - m_pIfdExtraBuf[m_nIfdExtraLen+2] = nTmp[2]; - m_pIfdExtraBuf[m_nIfdExtraLen+3] = nTmp[3]; - } - m_nIfdExtraLen += 4; -} - - -void FileTiff::WriteIfdEntrySingle(unsigned short nTag,unsigned short nType,unsigned nValOffset) -{ - unsigned nNum; - - nNum = 1; - WriteVal16(nTag); - WriteVal16(nType); - WriteVal32(nNum); - switch (nType) { - case TIFF_TYPE_BYTE: - WriteVal8(static_cast(nValOffset)); - WriteVal8(0x00); - WriteVal16(0x0000); - break; - case TIFF_TYPE_ASCII: - // The value of the Count part of an ASCII field entry includes the NUL - // Therefore, it is not valid for a "Single" entry. - ASSERT(false); - break; - case TIFF_TYPE_SHORT: - WriteVal16(static_cast(nValOffset)); - WriteVal16(0x0000); - break; - case TIFF_TYPE_LONG: - WriteVal32(nValOffset); - break; - default: - ASSERT(false); - break; - } - m_nNumIfd++; -} - -/* -Types -The field types and their sizes are: -1 = BYTE 8-bit unsigned integer. -2 = ASCII 8-bit byte that contains a 7-bit ASCII code; the last byte -must be NUL (binary zero). -3 = SHORT 16-bit (2-byte) unsigned integer. -4 = LONG 32-bit (4-byte) unsigned integer. -5 = RATIONAL Two LONGs: the first represents the numerator of a -fraction; the second, the denominator. -The value of the Count part of an ASCII field entry includes the NUL. If padding -is necessary, the Count does not include the pad byte. Note that there is no initial -“count byte” as in Pascal-style strings. -*/ - -unsigned FileTiff::GetTypeLen(unsigned nType) -{ - unsigned nLen=0; - switch(nType) { - case TIFF_TYPE_BYTE: - case TIFF_TYPE_ASCII: - nLen = 1; - break; - case TIFF_TYPE_SHORT: - nLen = 2; - break; - case TIFF_TYPE_LONG: - nLen = 4; - break; - case TIFF_TYPE_RATIONAL: - // We set it to be 4 here instead of 8 - // because nNumVals is 2x nNumVals - nLen = 4; - break; - default: - ASSERT(false); - break; - } - return nLen; -} - -// Use this if we are using external reference -void FileTiff::WriteIfdEntryMult(unsigned short nTag,unsigned short nType,unsigned nNumVals,unsigned* nVals) -{ - // Calculate total length so we can determine if the - // values fit inside a DWORD - unsigned nTotalLen; - bool bInExtra=false; - nTotalLen = nNumVals * GetTypeLen(nType); - if (nTotalLen > 4) { bInExtra = true; } - - WriteVal16(nTag); - WriteVal16(nType); - WriteVal32((nType!=TIFF_TYPE_RATIONAL)?nNumVals:nNumVals/2); - if (bInExtra) { - WriteVal32(m_nPtrIfdExtra+m_nIfdExtraLen); - } - - // Increment the number of IFD entries - m_nNumIfd++; - - - // Now start writing to IfdExtraBuf - unsigned nVal; - BYTE nVal1; - unsigned short nVal2; - - - for (unsigned nInd=0;nInd(nVal & 0xFF); - nVal2 = static_cast(nVal & 0xFFFF); - switch (nType) { - case TIFF_TYPE_BYTE: - if (bInExtra) { - WriteIfdExtraBuf8(nVal1); - } else { - WriteVal8(nVal1); - } - break; - case TIFF_TYPE_ASCII: - if (bInExtra) { - WriteIfdExtraBuf8(nVal1); - } else { - WriteVal8(nVal1); - } - break; - case TIFF_TYPE_SHORT: - if (bInExtra) { - WriteIfdExtraBuf16(nVal2); - } else { - WriteVal16(nVal2); - } - break; - case TIFF_TYPE_LONG: - if (bInExtra) { - WriteIfdExtraBuf32(nVal); - } else { - WriteVal32(nVal); - } - break; - case TIFF_TYPE_RATIONAL: - // Expect two longs in array, so this gets - // called twice per rational - if (bInExtra) { - WriteIfdExtraBuf32(nVal); - } else { - WriteVal32(nVal); - } - break; - default: - ASSERT(false); - break; - } - } - - // Do we need to pad? - if ((!bInExtra) && (nTotalLen < 4)) { - // Need to pad out with NULLs - for (unsigned nPad=0;nPad<(4-nTotalLen);nPad++) { - WriteVal8(0x00); - } - } - - -} - - -void FileTiff::WriteIfd(unsigned nSizeX,unsigned nSizeY,bool bModeYcc,bool bMode16b) -{ - ASSERT(m_pFileOutput); - - unsigned anVals[16]; - - bool bPreCalcSaved; - - unsigned short nFinalNumIfd; - unsigned nFinalIfdExtraLen; - unsigned nFinalPtrIfdStart; - unsigned nFinalPtrIfdExtra; - unsigned nFinalPtrIfdEnd; - - - // Save the PreCalc mode - bPreCalcSaved = m_bPreCalc; - - // Save the position of the start of IFD - - m_nPtrIfdExtra = 0; - m_nIfdExtraLen = 0; - - ASSERT(m_pIfdExtraBuf==NULL); - - nFinalNumIfd = 0; - nFinalPtrIfdStart = m_nPos; - nFinalPtrIfdExtra = 0; - nFinalPtrIfdEnd = 0; - nFinalIfdExtraLen = 0; - - for (unsigned nPass=0;nPass<2;nPass++) { - - m_bPreCalc = (nPass == 0)?true:false; - - m_nPos = nFinalPtrIfdStart; - - m_nNumIfd = 0; - m_nIfdExtraLen = 0; // Number of bytes used in IfdExtra Buf - - // The following WriteIfdEntry calls will use "m_nPtrIfdExtra" - // when any reference needs to be made. In PreCalc pass, these - // will all be invalid as "m_nPtrIfdExtraStart" has not been - // calculated until we finished the pass. In real pass, we - // have calculated the "m_nPtrIfdExtraStart" and set up the - // "m_nPtrIfdExtra" to begin there. - if (!m_bPreCalc) { - m_nPtrIfdExtra = nFinalPtrIfdExtra; - - // Allocate the IfdExtra buffer now that - // we know how large it will be - m_pIfdExtraBuf = new BYTE[nFinalIfdExtraLen]; - ASSERT(m_pIfdExtraBuf); - } - // Number of Dir Entries - WriteVal16(nFinalNumIfd); - - WriteIfdEntrySingle(TIFF_TAG_IMG_WIDTH,TIFF_TYPE_SHORT,nSizeX); - WriteIfdEntrySingle(TIFF_TAG_IMG_HEIGHT,TIFF_TYPE_SHORT,nSizeY); - anVals[0] = (bMode16b)?16:8; - anVals[1] = (bMode16b)?16:8; - anVals[2] = (bMode16b)?16:8; - WriteIfdEntryMult(TIFF_TAG_BITS_PER_SAMP,TIFF_TYPE_SHORT,3,anVals); - WriteIfdEntrySingle(TIFF_TAG_COMPRESSION,TIFF_TYPE_SHORT,1); - unsigned nValPhotomInterp = (bModeYcc)?6:2; - WriteIfdEntrySingle(TIFF_TAG_PHOTOM_INTERP,TIFF_TYPE_SHORT,nValPhotomInterp); - - WriteIfdEntrySingle(TIFF_TAG_STRIP_OFFSETS,TIFF_TYPE_SHORT,m_nPtrImg); //? - WriteIfdEntrySingle(TIFF_TAG_ORIENTATION,TIFF_TYPE_SHORT,1); - WriteIfdEntrySingle(TIFF_TAG_SAMP_PER_PIX,TIFF_TYPE_SHORT,3); - WriteIfdEntrySingle(TIFF_TAG_ROWS_PER_STRIP,TIFF_TYPE_SHORT,nSizeY); - unsigned nBytePerPix = (bMode16b)?6:3; - WriteIfdEntrySingle(TIFF_TAG_STRIP_BYTE_COUNTS,TIFF_TYPE_LONG,nSizeY*nSizeX*nBytePerPix); - - anVals[0] = 72; anVals[1] = 1; // 72 DPI - WriteIfdEntryMult(TIFF_TAG_X_RESOLUTION,TIFF_TYPE_RATIONAL,2,anVals); - WriteIfdEntryMult(TIFF_TAG_Y_RESOLUTION,TIFF_TYPE_RATIONAL,2,anVals); - WriteIfdEntrySingle(TIFF_TAG_PLANAR_CONFIG,TIFF_TYPE_SHORT,1); - WriteIfdEntrySingle(TIFF_TAG_RESOLUTION_UNIT,TIFF_TYPE_SHORT,2); // Inches - - - if (bModeYcc) { - // Add the extra tags required - anVals[0] = 299; anVals[1] = 1000; - anVals[2] = 587; anVals[3] = 1000; - anVals[4] = 114; anVals[5] = 1000; - WriteIfdEntryMult(TIFF_TAG_YCC_COEFFS,TIFF_TYPE_RATIONAL,6,anVals); - anVals[0] = 1; - anVals[1] = 1; - WriteIfdEntryMult(TIFF_TAG_YCC_SUBSAMP,TIFF_TYPE_SHORT,2,anVals); - WriteIfdEntrySingle(TIFF_TAG_POSITIONING,TIFF_TYPE_SHORT,1); - } - - // For YCC 8b: [0/1, 255/1,128/1, 255/1, 128/1, 255/1] - if (!bModeYcc) { - anVals[0] = 0x00; anVals[1] = 1; // R - Black - anVals[2] = 0xFF; anVals[3] = 1; // R - White - anVals[4] = 0x00; anVals[5] = 1; // G - Black - anVals[6] = 0xFF; anVals[7] = 1; // G - White - anVals[8] = 0x00; anVals[9] = 1; // B - Black - anVals[10] = 0xFF; anVals[11] = 1; // B - White - } else { - anVals[0] = 0x00; anVals[1] = 1; // Y - Black - anVals[2] = 0xFF; anVals[3] = 1; // Y - White - anVals[4] = 0x00; anVals[5] = 1; // Cb - Black - anVals[6] = 0xFF; anVals[7] = 1; // Cb - White - anVals[8] = 0x00; anVals[9] = 1; // Cr - Black - anVals[10] = 0xFF; anVals[11] = 1; // Cr - White - } - WriteIfdEntryMult(TIFF_TAG_REF_BLACK_WHITE,TIFF_TYPE_RATIONAL,12,anVals); - - // End of IFD - WriteVal32(0x00000000); - - // Save the pointer to the start of extra IFD region - nFinalPtrIfdExtra = m_nPos; - - // Save the count of # IFD entries - nFinalNumIfd = m_nNumIfd; - - nFinalIfdExtraLen = m_nIfdExtraLen; - - // Now write out IFD Extra buffer - if (m_nIfdExtraLen > 0) { - if (!m_bPreCalc) { - ASSERT(m_pIfdExtraBuf); - } - - for (unsigned nBufInd=0;nBufInd(pBitmap); - pBitmap16 = reinterpret_cast(pBitmap); - - - ASSERT(sFnameOut != _T("")); - - try - { - // Open specified file - // Added in shareDenyNone as this apparently helps resolve some people's troubles - // with an error showing: Couldn't open file "Sharing Violation" - m_pFileOutput = new CFile(sFnameOut, CFile::modeCreate| CFile::modeWrite | CFile::typeBinary | CFile::shareDenyNone); - } - catch (CFileException* e) - { - TCHAR msg[MAX_BUF_EX_ERR_MSG]; - CString strError; - e->GetErrorMessage(msg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - strError.Format(_T("ERROR: Couldn't open file for write [%s]: [%s]"), - (LPCTSTR)sFnameOut, msg); - AfxMessageBox(strError); - m_pFileOutput = NULL; - - return; - - } - - unsigned nIfdPtr; - - m_bPreCalc = false; - m_nPos = 0; - - // This will get updated after pass 1 of WriteIfd() - m_nPtrImg = 0; - - // TIFF Header - WriteVal32(0x4D4D002A); - - // IFD Directory Ptr, place at start of file - nIfdPtr = 8; - WriteVal32(nIfdPtr); - - // IFD - WriteIfd(nSizeX,nSizeY,bModeYcc,bMode16b); - - // Skip to start of image - unsigned nPad; - nPad = m_nPtrImg - m_nPos; - for (unsigned nInd=0;nIndWrite(pBitmap8,nSizeX*nSizeY*3*1); - m_nPos += nSizeX*nSizeY*3*1; - } else { - m_pFileOutput->Write(pBitmap16,nSizeX*nSizeY*3*2); - m_nPos += nSizeX*nSizeY*3*2; - } - - } - - - // If no image was loaded, then output a placeholder gradient image - if (!pBitmap) { - for (unsigned nIndY=0;nIndY(nIndX*32+nIndY*16)); // R - WriteVal8(0x20 + static_cast(nIndX*16+nIndY*16)); // G - WriteVal8(0x80 + static_cast(nIndX*8 +nIndY*16)); // B - } else { - WriteVal16(0x00 + static_cast(nIndX*32+nIndY*16)); // R - WriteVal16(0x20 + static_cast(nIndX*16+nIndY*16)); // G - WriteVal16(0x80 + static_cast(nIndX*8 +nIndY*16)); // B - } - } - } - } - - - - - m_pFileOutput->Close(); - - - // Clean up - // Don't really need to delete m_pFileOutput - if (m_pFileOutput) { - delete m_pFileOutput; - m_pFileOutput = NULL; - } -} \ No newline at end of file diff --git a/source/FileTiff.h b/source/FileTiff.h deleted file mode 100644 index b299d1e..0000000 --- a/source/FileTiff.h +++ /dev/null @@ -1,93 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - TIFF file export routines -// -// ========================================================================== - - -#pragma once - -#include "snoop.h" - -#define TIFF_TYPE_BYTE 0x00 -#define TIFF_TYPE_ASCII 0x01 -#define TIFF_TYPE_SHORT 0x03 -#define TIFF_TYPE_LONG 0x04 -#define TIFF_TYPE_RATIONAL 0x05 - - -#define TIFF_TAG_IMG_WIDTH 0x0100 -#define TIFF_TAG_IMG_HEIGHT 0x0101 -#define TIFF_TAG_BITS_PER_SAMP 0x0102 -#define TIFF_TAG_COMPRESSION 0x0103 -#define TIFF_TAG_PHOTOM_INTERP 0x0106 -#define TIFF_TAG_STRIP_OFFSETS 0x0111 -#define TIFF_TAG_ORIENTATION 0x0112 -#define TIFF_TAG_SAMP_PER_PIX 0x0115 -#define TIFF_TAG_ROWS_PER_STRIP 0x0116 -#define TIFF_TAG_STRIP_BYTE_COUNTS 0x0117 -#define TIFF_TAG_X_RESOLUTION 0x011A -#define TIFF_TAG_Y_RESOLUTION 0x011B -#define TIFF_TAG_PLANAR_CONFIG 0x011C -#define TIFF_TAG_RESOLUTION_UNIT 0x0128 - -// For YCC Images -#define TIFF_TAG_YCC_COEFFS 0x0211 -#define TIFF_TAG_YCC_SUBSAMP 0x0212 -#define TIFF_TAG_POSITIONING 0x0213 -#define TIFF_TAG_REF_BLACK_WHITE 0x0214 - - - -class FileTiff -{ - -public: - FileTiff(); - ~FileTiff(); - - void WriteFile(CString sFnameOut,bool bModeYcc,bool bMode16b,void* pBitmap,unsigned nSizeX,unsigned nSizeY); - void WriteIfd(unsigned nSizeX,unsigned nSizeY,bool bModeYcc,bool bMode16b); - void WriteIfdEntrySingle(unsigned short nTag,unsigned short nType,unsigned nValOffset); - void WriteIfdEntryMult(unsigned short nTag,unsigned short nType,unsigned nNumVals,unsigned* nVals); - - unsigned GetTypeLen(unsigned nType); - - void WriteVal8(BYTE nVal); - void WriteVal16(unsigned short nVal); - void WriteVal32(unsigned int nVal); - void WriteIfdExtraBuf8(BYTE nVal); - void WriteIfdExtraBuf16(unsigned short nVal); - void WriteIfdExtraBuf32(unsigned int nVal); - -private: - CFile* m_pFileOutput; - - unsigned m_nPtrIfdExtra; - unsigned m_nPtrImg; - unsigned m_nPos; - - bool m_bPreCalc; - unsigned short m_nNumIfd; - BYTE* m_pIfdExtraBuf; - unsigned m_nIfdExtraLen; - -}; diff --git a/source/FolderDlg.cpp b/source/FolderDlg.cpp index 8ef566c..2ffb697 100644 --- a/source/FolderDlg.cpp +++ b/source/FolderDlg.cpp @@ -1,360 +1,360 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code is based on an example CFolderDialog class that appears in MSDN: -// -// Title: CFolderDialog (C++ at Work: Counting MDI Children, Browsing for Folders) -// Authors: Paul DiLascia -// URL: http://msdn.microsoft.com/en-us/magazine/cc163789.aspx -// Date: Jun 2005 -// ==================================================================================================== - - - -////////////////////////////////////////////////////////////////// -// MSDN Magazine -- June 2005 -// If this code works, it was written by Paul DiLascia. -// If not, I don't know who wrote it. -// Compiles with Visual Studio .NET 2003 (V7.1) on Windows XP. Tab size=3. -// -#include "stdafx.h" -#include "FolderDlg.h" -#include - -// You must link shlwapi.lib for StrRetToBuf -#pragma comment(lib, "shlwapi.lib") - -//CAL! Commented out the following to avoid issues with DEBUG_INTERFACE_NAME -#if 0 //CAL! -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -BOOL CFolderDialog::bTRACE=0; // controls tracing - -////////////////// -// For deugging: names of interfaces easier to read than GUIDs! -// -DEBUG_BEGIN_INTERFACE_NAMES() - DEBUG_INTERFACE_NAME(IFolderFilterSite) - DEBUG_INTERFACE_NAME(IFolderFilter) -DEBUG_END_INTERFACE_NAMES(); - -#endif - -IMPLEMENT_DYNAMIC(CFolderDialog, CCmdTarget); - -////////////////// -// ctor: initialize most stuff to NULL -// -CFolderDialog::CFolderDialog(CWnd* pWnd) -{ - pWnd; // Unreferenced param - - //CAL! Modified the following to allow us to call this - // routine without a parent window defined. This - // is a temporary workaround so that I can call - // CFolderDialog() from the JPEGsnoopDoc class. - -//CAL! ASSERT(pWnd); - memset(&m_brinfo,0,sizeof(m_brinfo)); -//CAL! m_brinfo.hwndOwner=pWnd->m_hWnd; // use parent window - m_bFilter = FALSE; // default: no filtering - SHGetDesktopFolder(&m_shfRoot); // get root IShellFolder - - //CAL! Add support for start path - m_strStartPath = ""; -} - -////////////////// -// dtor: detach browser window before it's destroyed! -// -CFolderDialog::~CFolderDialog() -{ -} - -////////////////// -// Browse for folder. Args are same as for SHBrowseForFolder, but with extra -// bFilter that tells whether to do custom filtering. Note this requires -// BIF_NEWDIALOGSTYLE, which is inconsistent with some other flags--be -// careful! -// -LPCITEMIDLIST CFolderDialog::BrowseForFolder(LPCTSTR title, UINT flags, - LPCITEMIDLIST root, BOOL bFilter) -{ - //BFTRACE(_T("CFolderDialog::BrowseForFolder\n")); - TCHAR* buf = m_sDisplayName.GetBuffer(MAX_PATH); - m_brinfo.pidlRoot = root; - m_brinfo.pszDisplayName = buf; - m_brinfo.lpszTitle = title; - m_brinfo.ulFlags = flags; - m_brinfo.lpfn = CallbackProc; - m_brinfo.lParam = (LPARAM)this; - - // filtering only supported for new-style dialogs - m_bFilter = bFilter; - ASSERT(!bFilter||(m_brinfo.ulFlags & BIF_NEWDIALOGSTYLE)); - - LPCITEMIDLIST pidl = SHBrowseForFolder(&m_brinfo); // do it - m_sDisplayName.ReleaseBuffer(); - - return pidl; -} - -////////////////// -// Handy function to get the string pathname from pidl. -// -CString CFolderDialog::GetPathName(LPCITEMIDLIST pidl) -{ - CString path; - TCHAR* buf = path.GetBuffer(MAX_PATH); - SHGetPathFromIDList(pidl, buf); - path.ReleaseBuffer(); - return path; -} - -//CAL! Added -void CFolderDialog::SetStartPath(CString strPath) -{ - m_strStartPath = strPath; -} - -////////////////// -// Handy function to get the display name from pidl. -// -CString CFolderDialog::GetDisplayNameOf(IShellFolder* psf, LPCITEMIDLIST pidl, - DWORD uFlags) -{ - CString dn; - STRRET strret; // special struct for GetDisplayNameOf - strret.uType = STRRET_CSTR; // get as CSTR - if (SUCCEEDED(psf->GetDisplayNameOf(pidl, uFlags, &strret))) { - StrRetToBuf(&strret, pidl, dn.GetBuffer(MAX_PATH), MAX_PATH); - dn.ReleaseBuffer(); - } - return dn; -} - -////////////////// -// Free PIDL using shell's IMalloc -// -void CFolderDialog::FreePIDL(LPCITEMIDLIST pidl) -{ - CComQIPtr iMalloc; // shell's IMalloc - HRESULT hr = SHGetMalloc(&iMalloc); - ASSERT(SUCCEEDED(hr)); - iMalloc->Free((void*)pidl); -} - -////////////////// -// Internal callback proc used for SHBrowseForFolder passes control to -// appropriate virtual function after attaching browser window. -// -int CALLBACK CFolderDialog::CallbackProc(HWND hwnd, - UINT msg, LPARAM lp, LPARAM lpData) -{ - CFolderDialog* pDlg = (CFolderDialog*)lpData; - ASSERT(pDlg); - if (pDlg->m_hWnd!=hwnd) { - if (pDlg->m_hWnd) - pDlg->UnsubclassWindow(); - pDlg->SubclassWindow(hwnd); - } - return pDlg->OnMessage(msg, lp); -} - -////////////////// -// Handle notification from browser window: parse args and pass to specific -// virtual handler function. -// -int CFolderDialog::OnMessage(UINT msg, LPARAM lp) -{ - switch (msg) { - case BFFM_INITIALIZED: - OnInitialized(); - //CAL! - // Add support for initial start directory - if (!m_strStartPath.IsEmpty()) { - LPARAM lpStartPath; - lpStartPath = (LPARAM)(m_strStartPath.GetBuffer(1)); - m_strStartPath.ReleaseBuffer(); - ::SendMessage(this->m_hWnd,BFFM_SETSELECTION,TRUE,lpStartPath); - } - //CAL! - return 0; - case BFFM_IUNKNOWN: - OnIUnknown((IUnknown*)lp); - return 0; - case BFFM_SELCHANGED: - OnSelChanged((LPCITEMIDLIST)lp); - return 0; - case BFFM_VALIDATEFAILED: - return OnValidateFailed((LPCTSTR)lp); - default: - TRACE(_T("***Warning: unknown message %d in CFolderDialog::OnMessage\n")); - } - return 0; -} - -///////////////// -// Browser window initialized. -// -void CFolderDialog::OnInitialized() -{ - //BFTRACE(_T("CFolderDialog::OnInitialized\n")); -} - -///////////////// -// Browser is notifying me with its IUnknown: use it to set filter if -// requested. Note this can be called with punk=NULL when shutting down! -// -void CFolderDialog::OnIUnknown(IUnknown* punk) -{ - //BFTRACE(_T("CFolderDialog::OnIUnknown: %p\n"), punk); - if (punk && m_bFilter) { - CComQIPtr iffs; - VERIFY(SUCCEEDED(punk->QueryInterface(IID_IFolderFilterSite, (void**)&iffs))); - iffs->SetFilter((IFolderFilter*)&m_xFolderFilter); - // smart pointer automatically Releases iffs, - // no longer needed once you call SetFilter - } -} - -////////////////// -// User selected a different folder. -// -void CFolderDialog::OnSelChanged(LPCITEMIDLIST pidl) -{ - pidl; // Unrefernced param - //BFTRACE(_T("CFolderDialog::OnSelChanged: %s\n"), - // GetDisplayNameOf(m_shfRoot, pidl, SHGDN_FORPARSING)); -} - -////////////////// -// User attempted to enter a name in the edit box that isn't a folder. -// -BOOL CFolderDialog::OnValidateFailed(LPCTSTR lpsz) -{ - lpsz; // Unreferenced param - //BFTRACE(_T("CFolderDialog::OnValidateFailed: %s\n"), lpsz); - return TRUE; // don't close dialog. -} - -////////////////// -// Used for custom filtering. You must override to specify filter flags. -// -HRESULT CFolderDialog::OnGetEnumFlags( - IShellFolder* psf, // this folder's IShellFolder - LPCITEMIDLIST pidlFolder, // folder's PIDL - DWORD *pgrfFlags) // [out] return flags you want to allow -{ - psf; // Unreferenced param - pidlFolder; // Unreferenced param - pgrfFlags; // Unreferenced param - //BFTRACE(_T("CFolderDialog::OnGetEnumFlags(%p): %s\n"), - // psf, GetPathName(pidlFolder)); - return S_OK; -} - -////////////////// -// Used for custom filtering. You must override to filter items. -// -HRESULT CFolderDialog::OnShouldShow( - IShellFolder* psf, // This folder's IShellFolder - LPCITEMIDLIST pidlFolder, // PIDL for folder containing item - LPCITEMIDLIST pidlItem) // PIDL for item -{ - psf; // Unreferenced param - pidlFolder; // Unreferenced param - pidlItem; // Unreferenced param - //BFTRACE(_T("CFolderDialog::OnShouldShow(%p): %s: %s\n"), psf, - // GetDisplayNameOf(psf,pidlFolder,SHGDN_NORMAL), - // GetDisplayNameOf(psf,pidlItem,SHGDN_NORMAL)); - return S_OK; -} - -//////////////// Standard MFC IUnknown -- nested classes call these //////////////// - -STDMETHODIMP_(ULONG) CFolderDialog::AddRef() -{ - //BFTRACE(_T("CFolderDialog(%p)::AddRef\n"),this); - return ExternalAddRef(); -} - -STDMETHODIMP_(ULONG) CFolderDialog::Release() -{ - //BFTRACE(_T("CFolderDialog(%p)::Release\n"), this); - return ExternalRelease(); -} - -STDMETHODIMP CFolderDialog::QueryInterface(REFIID iid, LPVOID* ppvRet) -{ - if (ppvRet==NULL) - return E_INVALIDARG; - //BFTRACE(_T("CFolderDialog(%p)::QueryInterface(%s)\n"),this,_TR(iid)); - HRESULT hr = ExternalQueryInterface(&iid, ppvRet); - //BFTRACE(_T(">CFolderDialog::QueryInterface returns %s, *ppv=%p\n"),_TR(hr),*ppvRet); - return hr; -} - -//////////////////////////////// IFolderFilter //////////////////////////////// -// -// Implementation passes control to parent class CFolderDialog (pThis) -// -BEGIN_INTERFACE_MAP(CFolderDialog, CCmdTarget) - INTERFACE_PART(CFolderDialog, IID_IFolderFilter, FolderFilter) -END_INTERFACE_MAP() - -STDMETHODIMP_(ULONG) CFolderDialog::XFolderFilter::AddRef() -{ - METHOD_PROLOGUE(CFolderDialog, FolderFilter); - return pThis->AddRef(); -} - -STDMETHODIMP_(ULONG) CFolderDialog::XFolderFilter::Release() -{ - METHOD_PROLOGUE(CFolderDialog, FolderFilter); - return pThis->Release(); -} - -STDMETHODIMP CFolderDialog::XFolderFilter::QueryInterface(REFIID iid, LPVOID* ppv) -{ - METHOD_PROLOGUE(CFolderDialog, FolderFilter); - return pThis->QueryInterface(iid, ppv); -} - -// Note: pHwnd is always NULL here as far as I can tell. -STDMETHODIMP CFolderDialog::XFolderFilter::GetEnumFlags(IShellFolder* psf, - LPCITEMIDLIST pidlFolder, HWND *pHwnd, DWORD *pgrfFlags) -{ - pHwnd; // Unreferenced param - METHOD_PROLOGUE(CFolderDialog, FolderFilter); - return pThis->OnGetEnumFlags(psf, pidlFolder, pgrfFlags); -} - -STDMETHODIMP CFolderDialog::XFolderFilter::ShouldShow(IShellFolder* psf, - LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlItem) -{ - METHOD_PROLOGUE(CFolderDialog, FolderFilter); - return pThis->OnShouldShow(psf, pidlFolder, pidlItem); +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2017 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + + +// ==================================================================================================== +// SOURCE CODE ACKNOWLEDGEMENT +// ==================================================================================================== +// The following code is based on an example CFolderDialog class that appears in MSDN: +// +// Title: CFolderDialog (C++ at Work: Counting MDI Children, Browsing for Folders) +// Authors: Paul DiLascia +// URL: http://msdn.microsoft.com/en-us/magazine/cc163789.aspx +// Date: Jun 2005 +// ==================================================================================================== + + + +////////////////////////////////////////////////////////////////// +// MSDN Magazine -- June 2005 +// If this code works, it was written by Paul DiLascia. +// If not, I don't know who wrote it. +// Compiles with Visual Studio .NET 2003 (V7.1) on Windows XP. Tab size=3. +// +#include "stdafx.h" +#include "FolderDlg.h" +#include + +// You must link shlwapi.lib for StrRetToBuf +#pragma comment(lib, "shlwapi.lib") + +//CAL! Commented out the following to avoid issues with DEBUG_INTERFACE_NAME +#if 0 //CAL! +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +BOOL CFolderDialog::bTRACE=0; // controls tracing + +////////////////// +// For deugging: names of interfaces easier to read than GUIDs! +// +DEBUG_BEGIN_INTERFACE_NAMES() + DEBUG_INTERFACE_NAME(IFolderFilterSite) + DEBUG_INTERFACE_NAME(IFolderFilter) +DEBUG_END_INTERFACE_NAMES(); + +#endif + +IMPLEMENT_DYNAMIC(CFolderDialog, CCmdTarget); + +////////////////// +// ctor: initialize most stuff to NULL +// +CFolderDialog::CFolderDialog(CWnd* pWnd) +{ + pWnd; // Unreferenced param + + //CAL! Modified the following to allow us to call this + // routine without a parent window defined. This + // is a temporary workaround so that I can call + // CFolderDialog() from the JPEGsnoopDoc class. + +//CAL! ASSERT(pWnd); + memset(&m_brinfo,0,sizeof(m_brinfo)); +//CAL! m_brinfo.hwndOwner=pWnd->m_hWnd; // use parent window + m_bFilter = FALSE; // default: no filtering + SHGetDesktopFolder(&m_shfRoot); // get root IShellFolder + + //CAL! Add support for start path + m_strStartPath = ""; +} + +////////////////// +// dtor: detach browser window before it's destroyed! +// +CFolderDialog::~CFolderDialog() +{ +} + +////////////////// +// Browse for folder. Args are same as for SHBrowseForFolder, but with extra +// bFilter that tells whether to do custom filtering. Note this requires +// BIF_NEWDIALOGSTYLE, which is inconsistent with some other flags--be +// careful! +// +LPCITEMIDLIST CFolderDialog::BrowseForFolder(LPCTSTR title, UINT flags, + LPCITEMIDLIST root, BOOL bFilter) +{ + //BFTRACE(_T("CFolderDialog::BrowseForFolder\n")); + TCHAR* buf = m_sDisplayName.GetBuffer(MAX_PATH); + m_brinfo.pidlRoot = root; + m_brinfo.pszDisplayName = buf; + m_brinfo.lpszTitle = title; + m_brinfo.ulFlags = flags; + m_brinfo.lpfn = CallbackProc; + m_brinfo.lParam = (LPARAM)this; + + // filtering only supported for new-style dialogs + m_bFilter = bFilter; + ASSERT(!bFilter||(m_brinfo.ulFlags & BIF_NEWDIALOGSTYLE)); + + LPCITEMIDLIST pidl = SHBrowseForFolder(&m_brinfo); // do it + m_sDisplayName.ReleaseBuffer(); + + return pidl; +} + +////////////////// +// Handy function to get the string pathname from pidl. +// +CString CFolderDialog::GetPathName(LPCITEMIDLIST pidl) +{ + CString path; + TCHAR* buf = path.GetBuffer(MAX_PATH); + SHGetPathFromIDList(pidl, buf); + path.ReleaseBuffer(); + return path; +} + +//CAL! Added +void CFolderDialog::SetStartPath(CString strPath) +{ + m_strStartPath = strPath; +} + +////////////////// +// Handy function to get the display name from pidl. +// +CString CFolderDialog::GetDisplayNameOf(IShellFolder* psf, LPCITEMIDLIST pidl, + DWORD uFlags) +{ + CString dn; + STRRET strret; // special struct for GetDisplayNameOf + strret.uType = STRRET_CSTR; // get as CSTR + if (SUCCEEDED(psf->GetDisplayNameOf(pidl, uFlags, &strret))) { + StrRetToBuf(&strret, pidl, dn.GetBuffer(MAX_PATH), MAX_PATH); + dn.ReleaseBuffer(); + } + return dn; +} + +////////////////// +// Free PIDL using shell's IMalloc +// +void CFolderDialog::FreePIDL(LPCITEMIDLIST pidl) +{ + CComQIPtr iMalloc; // shell's IMalloc + HRESULT hr = SHGetMalloc(&iMalloc); + ASSERT(SUCCEEDED(hr)); + iMalloc->Free((void*)pidl); +} + +////////////////// +// Internal callback proc used for SHBrowseForFolder passes control to +// appropriate virtual function after attaching browser window. +// +int CALLBACK CFolderDialog::CallbackProc(HWND hwnd, + UINT msg, LPARAM lp, LPARAM lpData) +{ + CFolderDialog* pDlg = (CFolderDialog*)lpData; + ASSERT(pDlg); + if (pDlg->m_hWnd!=hwnd) { + if (pDlg->m_hWnd) + pDlg->UnsubclassWindow(); + pDlg->SubclassWindow(hwnd); + } + return pDlg->OnMessage(msg, lp); +} + +////////////////// +// Handle notification from browser window: parse args and pass to specific +// virtual handler function. +// +int CFolderDialog::OnMessage(UINT msg, LPARAM lp) +{ + switch (msg) { + case BFFM_INITIALIZED: + OnInitialized(); + //CAL! + // Add support for initial start directory + if (!m_strStartPath.IsEmpty()) { + LPARAM lpStartPath; + lpStartPath = (LPARAM)(m_strStartPath.GetBuffer(1)); + m_strStartPath.ReleaseBuffer(); + ::SendMessage(this->m_hWnd,BFFM_SETSELECTION,TRUE,lpStartPath); + } + //CAL! + return 0; + case BFFM_IUNKNOWN: + OnIUnknown((IUnknown*)lp); + return 0; + case BFFM_SELCHANGED: + OnSelChanged((LPCITEMIDLIST)lp); + return 0; + case BFFM_VALIDATEFAILED: + return OnValidateFailed((LPCTSTR)lp); + default: + TRACE(_T("***Warning: unknown message %d in CFolderDialog::OnMessage\n")); + } + return 0; +} + +///////////////// +// Browser window initialized. +// +void CFolderDialog::OnInitialized() +{ + //BFTRACE(_T("CFolderDialog::OnInitialized\n")); +} + +///////////////// +// Browser is notifying me with its IUnknown: use it to set filter if +// requested. Note this can be called with punk=NULL when shutting down! +// +void CFolderDialog::OnIUnknown(IUnknown* punk) +{ + //BFTRACE(_T("CFolderDialog::OnIUnknown: %p\n"), punk); + if (punk && m_bFilter) { + CComQIPtr iffs; + VERIFY(SUCCEEDED(punk->QueryInterface(IID_IFolderFilterSite, (void**)&iffs))); + iffs->SetFilter((IFolderFilter*)&m_xFolderFilter); + // smart pointer automatically Releases iffs, + // no longer needed once you call SetFilter + } +} + +////////////////// +// User selected a different folder. +// +void CFolderDialog::OnSelChanged(LPCITEMIDLIST pidl) +{ + pidl; // Unrefernced param + //BFTRACE(_T("CFolderDialog::OnSelChanged: %s\n"), + // GetDisplayNameOf(m_shfRoot, pidl, SHGDN_FORPARSING)); +} + +////////////////// +// User attempted to enter a name in the edit box that isn't a folder. +// +BOOL CFolderDialog::OnValidateFailed(LPCTSTR lpsz) +{ + lpsz; // Unreferenced param + //BFTRACE(_T("CFolderDialog::OnValidateFailed: %s\n"), lpsz); + return TRUE; // don't close dialog. +} + +////////////////// +// Used for custom filtering. You must override to specify filter flags. +// +HRESULT CFolderDialog::OnGetEnumFlags( + IShellFolder* psf, // this folder's IShellFolder + LPCITEMIDLIST pidlFolder, // folder's PIDL + DWORD *pgrfFlags) // [out] return flags you want to allow +{ + psf; // Unreferenced param + pidlFolder; // Unreferenced param + pgrfFlags; // Unreferenced param + //BFTRACE(_T("CFolderDialog::OnGetEnumFlags(%p): %s\n"), + // psf, GetPathName(pidlFolder)); + return S_OK; +} + +////////////////// +// Used for custom filtering. You must override to filter items. +// +HRESULT CFolderDialog::OnShouldShow( + IShellFolder* psf, // This folder's IShellFolder + LPCITEMIDLIST pidlFolder, // PIDL for folder containing item + LPCITEMIDLIST pidlItem) // PIDL for item +{ + psf; // Unreferenced param + pidlFolder; // Unreferenced param + pidlItem; // Unreferenced param + //BFTRACE(_T("CFolderDialog::OnShouldShow(%p): %s: %s\n"), psf, + // GetDisplayNameOf(psf,pidlFolder,SHGDN_NORMAL), + // GetDisplayNameOf(psf,pidlItem,SHGDN_NORMAL)); + return S_OK; +} + +//////////////// Standard MFC IUnknown -- nested classes call these //////////////// + +STDMETHODIMP_(ULONG) CFolderDialog::AddRef() +{ + //BFTRACE(_T("CFolderDialog(%p)::AddRef\n"),this); + return ExternalAddRef(); +} + +STDMETHODIMP_(ULONG) CFolderDialog::Release() +{ + //BFTRACE(_T("CFolderDialog(%p)::Release\n"), this); + return ExternalRelease(); +} + +STDMETHODIMP CFolderDialog::QueryInterface(REFIID iid, LPVOID* ppvRet) +{ + if (ppvRet==NULL) + return E_INVALIDARG; + //BFTRACE(_T("CFolderDialog(%p)::QueryInterface(%s)\n"),this,_TR(iid)); + HRESULT hr = ExternalQueryInterface(&iid, ppvRet); + //BFTRACE(_T(">CFolderDialog::QueryInterface returns %s, *ppv=%p\n"),_TR(hr),*ppvRet); + return hr; +} + +//////////////////////////////// IFolderFilter //////////////////////////////// +// +// Implementation passes control to parent class CFolderDialog (pThis) +// +BEGIN_INTERFACE_MAP(CFolderDialog, CCmdTarget) + INTERFACE_PART(CFolderDialog, IID_IFolderFilter, FolderFilter) +END_INTERFACE_MAP() + +STDMETHODIMP_(ULONG) CFolderDialog::XFolderFilter::AddRef() +{ + METHOD_PROLOGUE(CFolderDialog, FolderFilter); + return pThis->AddRef(); +} + +STDMETHODIMP_(ULONG) CFolderDialog::XFolderFilter::Release() +{ + METHOD_PROLOGUE(CFolderDialog, FolderFilter); + return pThis->Release(); +} + +STDMETHODIMP CFolderDialog::XFolderFilter::QueryInterface(REFIID iid, LPVOID* ppv) +{ + METHOD_PROLOGUE(CFolderDialog, FolderFilter); + return pThis->QueryInterface(iid, ppv); +} + +// Note: pHwnd is always NULL here as far as I can tell. +STDMETHODIMP CFolderDialog::XFolderFilter::GetEnumFlags(IShellFolder* psf, + LPCITEMIDLIST pidlFolder, HWND *pHwnd, DWORD *pgrfFlags) +{ + pHwnd; // Unreferenced param + METHOD_PROLOGUE(CFolderDialog, FolderFilter); + return pThis->OnGetEnumFlags(psf, pidlFolder, pgrfFlags); +} + +STDMETHODIMP CFolderDialog::XFolderFilter::ShouldShow(IShellFolder* psf, + LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlItem) +{ + METHOD_PROLOGUE(CFolderDialog, FolderFilter); + return pThis->OnShouldShow(psf, pidlFolder, pidlItem); } \ No newline at end of file diff --git a/source/FolderDlg.h b/source/FolderDlg.h index aff392c..af1038b 100644 --- a/source/FolderDlg.h +++ b/source/FolderDlg.h @@ -1,178 +1,178 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code is based on an example CFolderDialog class that appears in MSDN: -// -// Title: CFolderDialog (C++ at Work: Counting MDI Children, Browsing for Folders) -// Authors: Paul DiLascia -// URL: http://msdn.microsoft.com/en-us/magazine/cc163789.aspx -// Date: Jun 2005 -// ==================================================================================================== - - -//////////////////////////////////////////////////////////////// -// MSDN Magazine -- June 2005 -// If this code works, it was written by Paul DiLascia. -// If not, I don't know who wrote it. -// Compiles with Visual Studio .NET 2003 (V7.1) on Windows XP. Tab size=3. -// -#pragma once -//#include "debug.h" // debugging tools - -////////////////// -// BRTRACEFN is like TRACEFN but only does anything if -// CFolderDialog::bTRACE is on. See Debug.h. -// -#ifdef _DEBUG -#define BFTRACE \ - if (CFolderDialog::bTRACE) \ - TRACE -#else -#define BFTRACE -#endif - -////////////////// -// Class to encapsulate SHBrowseForFolder. To use, instantiate in your app -// and call BrowseForFolder, which returns a PIDL. You can call GetPathName -// to get the path name from the PIDL. For example: -// -// CFolderDialog dlg(this); -// LPCITEMIDLIST pidl = dlg.BrowseForFolder(...); -// CString path = dlg.GetPathName(pidl); -// -// You can also derive your own class from CFolderDialog to override virtual -// message handler functions like OnInitialized and OnSelChanged to do stuff -// when various things happen. This replaces the callback mechanism for -// SHBrowseForFolder. You call various wrapper functions from your hanlers to -// send messages to the browser window. For example: -// -// int CMyFolderDialog::OnInitialized() -// { -// CFolderDialog::OnInitialized(); -// SetStatusText(_T("Nice day, isn't it?")); -// SetOKText(L"Choose Me!"); -// return 0; -// } -// -// You can set CFolderDialog::bTRACE=TRUE to turn on debugging TRACE -// diagnostics to help you understand what's going on. -// -class CFolderDialog : public CWnd { -public: - static BOOL bTRACE; // controls tracing - - CFolderDialog(CWnd* pWnd); - ~CFolderDialog(); - - LPCITEMIDLIST BrowseForFolder(LPCTSTR title, UINT flags, - LPCITEMIDLIST pidRoot=NULL, BOOL bFilter=FALSE); - - CString GetDisplayName() { return m_sDisplayName; } - - // helpers - static CString GetPathName(LPCITEMIDLIST pidl); - static CString GetDisplayNameOf(IShellFolder* psf, LPCITEMIDLIST pidl, DWORD uFlags); - static void FreePIDL(LPCITEMIDLIST pidl); - - void SetStartPath(CString strPath); //CAL! -private: - CString m_strStartPath; //CAL! - -protected: - BROWSEINFO m_brinfo; // internal structure for SHBrowseForFolder - CString m_sDisplayName; // display name of folder chosen - BOOL m_bFilter; // do custom filtering? - CComQIPtr m_shfRoot; // handy to have root folder - - static int CALLBACK CallbackProc(HWND hwnd, UINT msg, LPARAM lp, LPARAM lpData); - - virtual int OnMessage(UINT msg, LPARAM lp); // internal catch-all - - // Virtual message handlers: override these instead of using callback - virtual void OnInitialized(); - virtual void OnIUnknown(IUnknown* punk); - virtual void OnSelChanged(LPCITEMIDLIST pidl); - virtual BOOL OnValidateFailed(LPCTSTR lpsz); - - // Wrapper functions for folder dialog messages--call these only from - // virtual handler functions above! - - // Enable or disable the OK button - void EnableOK(BOOL bEnable) { - SendMessage(BFFM_ENABLEOK,0,bEnable); - } - - // The Microsoft documentation is wrong for this: text in LPARAM, not WPARAM! - void SetOKText(LPCWSTR lpText) { - SendMessage(BFFM_SETOKTEXT,0,(LPARAM)lpText); - } - - // Set selected item from string or PIDL. - // The documentation says lpText must be Unicode, but it can be LPCTSTR. - void SetSelection(LPCTSTR lpText) { - SendMessage(BFFM_SETSELECTION,TRUE,(LPARAM)lpText); - } - void SetSelection(LPCITEMIDLIST pidl) { - SendMessage(BFFM_SETSELECTION,FALSE,(LPARAM)pidl); - } - - // Expand item from string or PIDL - void SetExpanded(LPCWSTR lpText) { - SendMessage(BFFM_SETEXPANDED,TRUE,(LPARAM)lpText); - } - void SetExpanded(LPCITEMIDLIST pidl) { - SendMessage(BFFM_SETEXPANDED,FALSE,(LPARAM)pidl); - } - - // Set status window text - void SetStatusText(LPCTSTR pText) { - SendMessage(BFFM_SETSTATUSTEXT,0,(LPARAM)pText); - } - - // Override for custom filtering. You must call BrowseForFolder with bFilter=TRUE. - virtual HRESULT OnGetEnumFlags(IShellFolder* psf, - LPCITEMIDLIST pidlFolder, - DWORD *pgrfFlags); - virtual HRESULT OnShouldShow(IShellFolder* psf, - LPCITEMIDLIST pidlFolder, - LPCITEMIDLIST pidlItem); - - // COM interfaces. The only one currently is IFolderFilter - DECLARE_INTERFACE_MAP() - - // IUnknown--all nested interfaces call these - STDMETHOD_(ULONG, AddRef)(); - STDMETHOD_(ULONG, Release)(); - STDMETHOD(QueryInterface)(REFIID iid, LPVOID* ppvObj); - - // COM interface IFolderFilter, used to do custom filtering - BEGIN_INTERFACE_PART(FolderFilter, IFolderFilter) - STDMETHOD(GetEnumFlags) (IShellFolder* psf, - LPCITEMIDLIST pidlFolder, - HWND *pHwnd, - DWORD *pgrfFlags); - STDMETHOD(ShouldShow) (IShellFolder* psf, - LPCITEMIDLIST pidlFolder, - LPCITEMIDLIST pidlItem); - END_INTERFACE_PART(FolderFilter) - - DECLARE_DYNAMIC(CFolderDialog) -}; \ No newline at end of file +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2017 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +// ==================================================================================================== +// SOURCE CODE ACKNOWLEDGEMENT +// ==================================================================================================== +// The following code is based on an example CFolderDialog class that appears in MSDN: +// +// Title: CFolderDialog (C++ at Work: Counting MDI Children, Browsing for Folders) +// Authors: Paul DiLascia +// URL: http://msdn.microsoft.com/en-us/magazine/cc163789.aspx +// Date: Jun 2005 +// ==================================================================================================== + + +//////////////////////////////////////////////////////////////// +// MSDN Magazine -- June 2005 +// If this code works, it was written by Paul DiLascia. +// If not, I don't know who wrote it. +// Compiles with Visual Studio .NET 2003 (V7.1) on Windows XP. Tab size=3. +// +#pragma once +//#include "debug.h" // debugging tools + +////////////////// +// BRTRACEFN is like TRACEFN but only does anything if +// CFolderDialog::bTRACE is on. See Debug.h. +// +#ifdef _DEBUG +#define BFTRACE \ + if (CFolderDialog::bTRACE) \ + TRACE +#else +#define BFTRACE +#endif + +////////////////// +// Class to encapsulate SHBrowseForFolder. To use, instantiate in your app +// and call BrowseForFolder, which returns a PIDL. You can call GetPathName +// to get the path name from the PIDL. For example: +// +// CFolderDialog dlg(this); +// LPCITEMIDLIST pidl = dlg.BrowseForFolder(...); +// CString path = dlg.GetPathName(pidl); +// +// You can also derive your own class from CFolderDialog to override virtual +// message handler functions like OnInitialized and OnSelChanged to do stuff +// when various things happen. This replaces the callback mechanism for +// SHBrowseForFolder. You call various wrapper functions from your hanlers to +// send messages to the browser window. For example: +// +// int CMyFolderDialog::OnInitialized() +// { +// CFolderDialog::OnInitialized(); +// SetStatusText(_T("Nice day, isn't it?")); +// SetOKText(L"Choose Me!"); +// return 0; +// } +// +// You can set CFolderDialog::bTRACE=TRUE to turn on debugging TRACE +// diagnostics to help you understand what's going on. +// +class CFolderDialog : public CWnd { +public: + static bool bTRACE; // controls tracing + + CFolderDialog(CWnd* pWnd); + ~CFolderDialog(); + + LPCITEMIDLIST BrowseForFolder(LPCTSTR title, UINT flags, + LPCITEMIDLIST pidRoot=NULL, bool bFilter=FALSE); + + CString GetDisplayName() { return m_sDisplayName; } + + // helpers + static CString GetPathName(LPCITEMIDLIST pidl); + static CString GetDisplayNameOf(IShellFolder* psf, LPCITEMIDLIST pidl, DWORD uFlags); + static void FreePIDL(LPCITEMIDLIST pidl); + + void SetStartPath(CString strPath); //CAL! +private: + CString m_strStartPath; //CAL! + +protected: + BROWSEINFO m_brinfo; // internal structure for SHBrowseForFolder + CString m_sDisplayName; // display name of folder chosen + bool m_bFilter; // do custom filtering? + CComQIPtr m_shfRoot; // handy to have root folder + + static int CALLBACK CallbackProc(HWND hwnd, UINT msg, LPARAM lp, LPARAM lpData); + + virtual int OnMessage(UINT msg, LPARAM lp); // internal catch-all + + // Virtual message handlers: override these instead of using callback + virtual void OnInitialized(); + virtual void OnIUnknown(IUnknown* punk); + virtual void OnSelChanged(LPCITEMIDLIST pidl); + virtual bool OnValidateFailed(LPCTSTR lpsz); + + // Wrapper functions for folder dialog messages--call these only from + // virtual handler functions above! + + // Enable or disable the OK button + void EnableOK(bool bEnable) { + SendMessage(BFFM_ENABLEOK,0,bEnable); + } + + // The Microsoft documentation is wrong for this: text in LPARAM, not WPARAM! + void SetOKText(LPCWSTR lpText) { + SendMessage(BFFM_SETOKTEXT,0,(LPARAM)lpText); + } + + // Set selected item from string or PIDL. + // The documentation says lpText must be Unicode, but it can be LPCTSTR. + void SetSelection(LPCTSTR lpText) { + SendMessage(BFFM_SETSELECTION,TRUE,(LPARAM)lpText); + } + void SetSelection(LPCITEMIDLIST pidl) { + SendMessage(BFFM_SETSELECTION,FALSE,(LPARAM)pidl); + } + + // Expand item from string or PIDL + void SetExpanded(LPCWSTR lpText) { + SendMessage(BFFM_SETEXPANDED,TRUE,(LPARAM)lpText); + } + void SetExpanded(LPCITEMIDLIST pidl) { + SendMessage(BFFM_SETEXPANDED,FALSE,(LPARAM)pidl); + } + + // Set status window text + void SetStatusText(LPCTSTR pText) { + SendMessage(BFFM_SETSTATUSTEXT,0,(LPARAM)pText); + } + + // Override for custom filtering. You must call BrowseForFolder with bFilter=TRUE. + virtual HRESULT OnGetEnumFlags(IShellFolder* psf, + LPCITEMIDLIST pidlFolder, + DWORD *pgrfFlags); + virtual HRESULT OnShouldShow(IShellFolder* psf, + LPCITEMIDLIST pidlFolder, + LPCITEMIDLIST pidlItem); + + // COM interfaces. The only one currently is IFolderFilter + DECLARE_INTERFACE_MAP() + + // IUnknown--all nested interfaces call these + STDMETHOD_(ULONG, AddRef)(); + STDMETHOD_(ULONG, Release)(); + STDMETHOD(QueryInterface)(REFIID iid, LPVOID* ppvObj); + + // COM interface IFolderFilter, used to do custom filtering + BEGIN_INTERFACE_PART(FolderFilter, IFolderFilter) + STDMETHOD(GetEnumFlags) (IShellFolder* psf, + LPCITEMIDLIST pidlFolder, + HWND *pHwnd, + DWORD *pgrfFlags); + STDMETHOD(ShouldShow) (IShellFolder* psf, + LPCITEMIDLIST pidlFolder, + LPCITEMIDLIST pidlItem); + END_INTERFACE_PART(FolderFilter) + + DECLARE_DYNAMIC(CFolderDialog) +}; diff --git a/source/General.cpp b/source/General.cpp index e802d22..32da729 100644 --- a/source/General.cpp +++ b/source/General.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -21,87 +21,97 @@ // --------------------------------------- #include -QString Dec2Bin(unsigned nVal,unsigned nLen,bool bSpace) +QString Dec2Bin(uint32_t nVal, uint32_t nLen, bool bSpace) { - unsigned nBit; - QString strBin = ""; + uint32_t nBit; - for (int nInd=nLen-1;nInd>=0;nInd--) - { - nBit = ( nVal & (1 << nInd) ) >> nInd; - strBin += (nBit==1)?"1":"0"; + QString strBin = ""; - if ( ((nInd % 8) == 0) && (nInd != 0) ) + for(int32_t nInd = nLen - 1; nInd >= 0; nInd--) + { + nBit = (nVal & (1 << nInd)) >> nInd; + strBin += (nBit == 1) ? "1" : "0"; + + if(((nInd % 8) == 0) && (nInd != 0)) { - if (bSpace) + if(bSpace) { strBin += " "; - } - } - } + } + } + } - return strBin; + return strBin; } // Perform byteswap which is used to create packed image array // before write-out of 16b values to disk -unsigned short Swap16(unsigned short nVal) +uint16_t Swap16(uint16_t nVal) { - quint8 nValHi,nValLo; - nValHi = static_cast((nVal & 0xFF00)>>8); - nValLo = static_cast((nVal & 0x00FF)); - return (nValLo<<8) + nValHi; + uint8_t nValHi, nValLo; + + nValHi = static_cast((nVal & 0xFF00) >> 8); + nValLo = static_cast((nVal & 0x00FF)); + return (nValLo << 8) + nValHi; } // Simple helper routine to test whether an indexed bit is set -bool TestBit(unsigned nVal,unsigned nBit) +bool TestBit(uint32_t nVal, uint32_t nBit) { - unsigned nTmp; - nTmp = (nVal & (1<>24); - c2 = char((nVal & 0x00FF0000)>>16); - c1 = char((nVal & 0x0000FF00)>>8); - c0 = char(nVal & 0x000000FF); - c3 = (c3 == 0)?'.':c3; - c2 = (c2 == 0)?'.':c2; - c1 = (c1 == 0)?'.':c1; - c0 = (c0 == 0)?'.':c0; -// strTmp.Format(_T("'%c%c%c%c' (0x%08X)"), c3,c2,c1,c0,nVal); - strTmp = QString("'%1%2%3%4' (%5)").arg(c3).arg(c2).arg(c1).arg(c0).arg(nVal, 8, 16, QChar('0')); - return strTmp; + + char c3, c2, c1, c0; + + c3 = char ((nVal & 0xFF000000) >> 24); + c2 = char ((nVal & 0x00FF0000) >> 16); + c1 = char ((nVal & 0x0000FF00) >> 8); + c0 = char (nVal & 0x000000FF); + + c3 = (c3 == 0) ? '.' : c3; + c2 = (c2 == 0) ? '.' : c2; + c1 = (c1 == 0) ? '.' : c1; + c0 = (c0 == 0) ? '.' : c0; + strTmp = QString("'%1%2%3%4' (%5)") + .arg(c3) + .arg(c2) + .arg(c1) + .arg(c0) + .arg(nVal, 8, 16, QChar('0')); + return strTmp; } // Convert between unsigned int and a dotted-byte notation -QString Uint2DotByte(unsigned nVal) +QString Uint2DotByte(uint32_t nVal) { QString strTmp; - strTmp = QString("'%1%2%3%4' (%5)") - .arg(nVal & 0xFF000000>>24) - .arg(nVal & 0x00FF0000>>16) - .arg(nVal & 0x0000FF00>>8) + + strTmp = QString("'%1.%2.%3.%4' (%5)") + .arg(nVal & 0xFF000000 >> 24) + .arg(nVal & 0x00FF0000 >> 16) + .arg(nVal & 0x0000FF00 >> 8) .arg(nVal & 0x000000FF) .arg(nVal, 8, 16, QChar('0')); -/* strTmp.Format(_T("'%u.%u.%u.%u' (0x%08X)"), - ((nVal & 0xFF000000)>>24), - ((nVal & 0x00FF0000)>>16), - ((nVal & 0x0000FF00)>>8), - (nVal & 0x000000FF), - nVal);*/ - return strTmp; + + return strTmp; } /* @@ -165,36 +175,35 @@ QString ByteStr2Unicode(BYTE* pBuf, unsigned nBufLen) } */ -bool Str2Uint32(QString strVal,unsigned nBase,unsigned &nVal) +bool Str2Uint32(QString strVal, uint32_t nBase, uint32_t & nVal) { - // Convert to unsigned 32b -// strVal.MakeUpper(); + // Convert to unsigned 32b +// strVal.MakeUpper(); bool Ok; - if (nBase == 16) + if(nBase == 16) { - // Hex - if (strVal.startsWith("0X")) + // Hex + if(strVal.startsWith("0X")) { - strVal = strVal.mid(2,20); - } + strVal = strVal.mid(2, 20); + } nVal = strVal.toUInt(&Ok, 16); } - else if (nBase == 10) + else if(nBase == 10) { - // Dec - nVal = strVal.toUInt(&Ok, 10); + // Dec + nVal = strVal.toUInt(&Ok, 10); } else { - return false; - } + return false; + } return Ok; } - /* // UNUSED // Convert a unicode string to ASCII and write into a buffer @@ -217,13 +226,11 @@ bool Uni2AscBuf(PBYTE pBuf,QString strIn,unsigned nMaxBytes,unsigned &nOffsetByt #endif // UNICODE - unsigned nStrLen; unsigned nChInd; nStrLen = strIn.GetLength(); for (nChInd=0;(nChInd // General Global Functions -QString Dec2Bin(unsigned nVal,unsigned nLen,bool bSpace=true); -unsigned short Swap16(unsigned short nVal); -QString Uint2Chars(unsigned nVal); -QString Uint2DotByte(unsigned nVal); -bool TestBit(unsigned nVal,unsigned nBit); -//QString ByteStr2Unicode(quint8* pBuf, unsigned nBufLen); -bool Str2Uint32(QString strVal,unsigned nBase,unsigned &nVal); - -//bool Uni2AscBuf(quint8* pBuf,QString strIn,unsigned nMaxBytes,unsigned &nOffsetBytes); +QString Dec2Bin(uint32_t nVal, uint32_t nLen, bool bSpace = true); +uint16_t Swap16(uint16_t nVal); +QString Uint2Chars(uint32_t nVal); +QString Uint2DotByte(uint32_t nVal); +bool TestBit(uint32_t nVal, uint32_t nBit); +//QString ByteStr2Unicode(quint8* pBuf, uint32_t nBufLen); +bool Str2Uint32(QString strVal, uint32_t nBase, uint32_t & nVal); +//bool Uni2AscBuf(quint8* pBuf,QString strIn,uint32_t nMaxBytes,uint32_t &nOffsetBytes); // General Global Constants -extern const unsigned glb_anZigZag[64]; -extern const unsigned glb_anUnZigZag[64]; - -extern const unsigned glb_anQuantRotate[64]; -extern const unsigned glb_anStdQuantLum[64]; -extern const unsigned glb_anStdQuantChr[64]; +extern const uint32_t glb_anZigZag[64]; +extern const uint32_t glb_anUnZigZag[64]; +extern const uint32_t glb_anQuantRotate[64]; +extern const uint32_t glb_anStdQuantLum[64]; +extern const uint32_t glb_anStdQuantChr[64]; #endif diff --git a/source/HyperlinkStatic.cpp b/source/HyperlinkStatic.cpp deleted file mode 100644 index 29c3d72..0000000 --- a/source/HyperlinkStatic.cpp +++ /dev/null @@ -1,182 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code is derived from the following project on CodeGuru: -// -// Title: HyperlinkStatic -// Author: Franz Wong -// URL: http://www.codeguru.com/cpp/controls/staticctrl/article.php/c5801 -// Date: Jan 14, 2003 -// -// ==================================================================================================== - - - -// HyperlinkStatic.cpp : implementation file -// - -#include "stdafx.h" -#include "HyperlinkStatic.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -//CAL! Added the following as otherwise we need -// to set WINVER >= 0x0500 -#define IDC_HAND MAKEINTRESOURCE(32649) - -///////////////////////////////////////////////////////////////////////////// -// CHyperlinkStatic - -CHyperlinkStatic::CHyperlinkStatic() -{ - _strCaption = _strHyperlink = _T(""); - _bMouseInControl = _bCreateFont = _bGetCaptionSize = false; - - _hHandCursor = ::LoadCursor(0, IDC_HAND); - _hArrowCursor = ::LoadCursor(0, IDC_ARROW); -} - -CHyperlinkStatic::~CHyperlinkStatic() -{ -} - -BEGIN_MESSAGE_MAP(CHyperlinkStatic, CStatic) - //{{AFX_MSG_MAP(CHyperlinkStatic) - ON_WM_LBUTTONDOWN() - ON_WM_PAINT() - ON_WM_DESTROY() - ON_WM_MOUSEMOVE() - //}}AFX_MSG_MAP - ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave) -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CHyperlinkStatic message handlers - -void CHyperlinkStatic::SetHyperlink(CString strHyperlink) -{ - _strHyperlink = strHyperlink; -} - -void CHyperlinkStatic::SetCaption(CString strCaption) -{ - _strCaption = strCaption; - _bGetCaptionSize = false; -} - -void CHyperlinkStatic::OnLButtonDown(UINT nFlags, CPoint point) -{ - if ( _bGetCaptionSize == false ) - GetCaptionSize(); - if (InCaptionRange(point)) - ShellExecute(0, _T("open"), _strHyperlink, 0, 0, SW_SHOWNORMAL); - CStatic::OnLButtonDown(nFlags, point); -} - -void CHyperlinkStatic::OnPaint() -{ - if ( _bCreateFont == false ) - CreateFont(); - CPaintDC dc(this); - CFont *pOldFont = (CFont*)dc.SelectObject(&_fontCaption); - dc.SetBkMode(TRANSPARENT); - dc.SetTextColor(RGB(0,0,255)); - dc.TextOut(0, 0, _strCaption); - dc.SelectObject(pOldFont); -} - -void CHyperlinkStatic::OnDestroy() -{ - CStatic::OnDestroy(); - _fontCaption.DeleteObject(); -} - -void CHyperlinkStatic::PreSubclassWindow() -{ - ModifyStyle(0, SS_NOTIFY, TRUE); - GetWindowText(_strCaption); - _bGetCaptionSize = false; - CStatic::PreSubclassWindow(); -} - -LRESULT CHyperlinkStatic::OnMouseLeave(WPARAM wParam, LPARAM lParam) -{ - lParam; // Unreferenced param - wParam; // Unreferenced param - _bMouseInControl = false; - ::SetCursor(_hArrowCursor); - return 0; -} - -void CHyperlinkStatic::OnMouseMove(UINT nFlags, CPoint point) -{ - if ( _bMouseInControl == false ) { - //Track the mouse leave event - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(tme); - tme.hwndTrack = GetSafeHwnd(); - tme.dwFlags = TME_LEAVE; - _TrackMouseEvent(&tme); - _bMouseInControl = true; - } - else { - if ( _bGetCaptionSize == false ) - GetCaptionSize(); - ::SetCursor((InCaptionRange(point))?_hHandCursor:_hArrowCursor); - } - CStatic::OnMouseMove(nFlags, point); -} - -void CHyperlinkStatic::CreateFont() -{ - CFont* pFontParent = GetParent()->GetFont(); - if ( pFontParent ) { - LOGFONT lf; - pFontParent->GetObject(sizeof(lf), &lf); - lf.lfUnderline = TRUE; - _fontCaption.CreateFontIndirect(&lf); - _bCreateFont = true; - } -} - -void CHyperlinkStatic::GetCaptionSize() -{ - if (( _bGetCaptionSize == false ) && ( _bCreateFont )) { - CClientDC dc(this); - CFont *pOldFont = dc.SelectObject(&_fontCaption); - _sizeCaption = dc.GetTextExtent(_strCaption); - dc.SelectObject(pOldFont); - _bGetCaptionSize = true; - } -} - -bool CHyperlinkStatic::InCaptionRange(CPoint &point) -{ - if ( _bGetCaptionSize == false ) - return false; - return (( point.x >= 0 )&&( point.x < _sizeCaption.cx ) && - ( point.y >= 0 )&&( point.y < _sizeCaption.cy )); -} diff --git a/source/HyperlinkStatic.h b/source/HyperlinkStatic.h deleted file mode 100644 index f25511b..0000000 --- a/source/HyperlinkStatic.h +++ /dev/null @@ -1,99 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code is derived from the following project on CodeGuru: -// -// Title: HyperlinkStatic -// Author: Franz Wong -// URL: http://www.codeguru.com/cpp/controls/staticctrl/article.php/c5801 -// Date: Jan 14, 2003 -// -// ==================================================================================================== - - -#if !defined(AFX_HYPERLINKSTATIC_H__32A71426_1315_407C_9D90_A484C5589D80__INCLUDED_) -#define AFX_HYPERLINKSTATIC_H__32A71426_1315_407C_9D90_A484C5589D80__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - - -// HyperlinkStatic.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CHyperlinkStatic window - -class CHyperlinkStatic : public CStatic -{ -// Construction -public: - CHyperlinkStatic(); - -// Attributes -public: - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CHyperlinkStatic) - protected: - virtual void PreSubclassWindow(); - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~CHyperlinkStatic(); - - // Generated message map functions -protected: - //{{AFX_MSG(CHyperlinkStatic) - afx_msg void OnLButtonDown(UINT nFlags, CPoint point); - afx_msg void OnPaint(); - afx_msg void OnDestroy(); - afx_msg void OnMouseMove(UINT nFlags, CPoint point); - //}}AFX_MSG - afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam); - DECLARE_MESSAGE_MAP() -public: - void SetHyperlink(CString strHyperlink); - void SetCaption(CString strCaption); -private: - CString _strCaption, _strHyperlink; - CFont _fontCaption; - CSize _sizeCaption; - bool _bCreateFont, _bMouseInControl, _bGetCaptionSize; - HCURSOR _hHandCursor, _hArrowCursor; - - void CreateFont(); - void GetCaptionSize(); - bool InCaptionRange(CPoint &point); -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_HYPERLINKSTATIC_H__32A71426_1315_407C_9D90_A484C5589D80__INCLUDED_) diff --git a/source/ImgDecode.cpp b/source/ImgDecode.cpp index c9324a7..0cb02e9 100644 --- a/source/ImgDecode.cpp +++ b/source/ImgDecode.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -16,14 +16,15 @@ // along with this program. If not, see . // +#include + #include #include +#include "SnoopConfig.h" + #include "ImgDecode.h" -#include "snoop.h" -#include -#include "JPEGsnoop.h" // ------------------------------------------------------ // Settings @@ -38,12 +39,87 @@ // ------------------------------------------------------ // Main code +// Constructor for the Image Decoder +// - This constructor is called only once by Document class +CimgDecode::CimgDecode(CDocLog *pLog, CwindowBuf *pWBuf, CSnoopConfig *pAppConfig, QObject *_parent) : QObject(_parent), m_pLog(pLog), m_pWBuf(pWBuf), + m_pAppConfig(pAppConfig) +{ + m_bVerbose = false; + + m_pStatBar = 0; + m_bDibTempReady = false; + m_bPreviewIsJpeg = false; + m_bDibHistRgbReady = false; + m_bDibHistYReady = false; + + m_bHistEn = false; + m_bStatClipEn = false; // UNUSED + + m_pMcuFileMap = 0; + m_pBlkDcValY = 0; + m_pBlkDcValCb = 0; + m_pBlkDcValCr = 0; + m_pPixValY = 0; + m_pPixValCb = 0; + m_pPixValCr = 0; + + // Reset the image decoding state + Reset(); + + m_nImgSizeXPartMcu = 0; + m_nImgSizeYPartMcu = 0; + m_nImgSizeX = 0; + m_nImgSizeY = 0; + + // FIXME: Temporary hack to avoid divide-by-0 when displaying PSD (instead of JPEG) + m_nMcuWidth = 1; + m_nMcuHeight = 1; + + // Detailed VLC Decode mode + m_bDetailVlc = false; + m_nDetailVlcX = 0; + m_nDetailVlcY = 0; + m_nDetailVlcLen = 1; + + m_sHisto.nClipYMin = 0; + + connect(this, SIGNAL(updateImage()), _parent, SLOT(updateImage())); + + // Set up the IDCT lookup tables + PrecalcIdct(); + + GenLookupHuffMask(); + + // The following contain information that is set by + // the JFIF Decoder. We can only reset them here during + // the constructor and later by explicit call by JFIF Decoder. + ResetState(); + + // We don't call SetPreviewMode() here because it would + // automatically try to recalculate the view (but nothing ready yet) + m_nPreviewMode = PREVIEW_RGB; + SetPreviewZoom(false, false, true, PRV_ZOOM_12); + + m_bDecodeScanAc = true; + + m_bViewOverlaysMcuGrid = false; + + // Start off with no YCC offsets for CalcChannelPreview() + SetPreviewYccOffset(0, 0, 0, 0, 0); + + SetPreviewMcuInsert(0, 0, 0); + +// setStyleSheet("background-color: white"); +} + // Reset decoding state for start of new decode // Note that we don't touch the DQT or DHT entries as // those are set at different times versus reset (sometimes // before Reset() ). void CimgDecode::Reset() { + qDebug() << "CimgDecode::Reset() Start"; + DecodeRestartScanBuf(0, false); DecodeRestartDcState(); @@ -75,60 +151,57 @@ void CimgDecode::Reset() // If a DIB has been generated, release it! if(m_bDibTempReady) { -//@@ m_pDibTemp.Kill(); m_bDibTempReady = false; } if(m_bDibHistRgbReady) { -//@@ m_pDibHistRgb.Kill(); m_bDibHistRgbReady = false; } if(m_bDibHistYReady) { -//@@ m_pDibHistY.Kill(); m_bDibHistYReady = false; } if(m_pMcuFileMap) { delete[]m_pMcuFileMap; - m_pMcuFileMap = NULL; + m_pMcuFileMap = 0; } if(m_pBlkDcValY) { delete[]m_pBlkDcValY; - m_pBlkDcValY = NULL; + m_pBlkDcValY = 0; } if(m_pBlkDcValCb) { delete[]m_pBlkDcValCb; - m_pBlkDcValCb = NULL; + m_pBlkDcValCb = 0; } if(m_pBlkDcValCr) { delete[]m_pBlkDcValCr; - m_pBlkDcValCr = NULL; + m_pBlkDcValCr = 0; } if(m_pPixValY) { delete[]m_pPixValY; - m_pPixValY = NULL; + m_pPixValY = 0; } if(m_pPixValCb) { delete[]m_pPixValCb; - m_pPixValCb = NULL; + m_pPixValCb = 0; } if(m_pPixValCr) { delete[]m_pPixValCr; - m_pPixValCr = NULL; + m_pPixValCr = 0; } // Haven't warned about anything yet @@ -145,88 +218,6 @@ void CimgDecode::Reset() m_nPreviewSizeY = 0; } -// Constructor for the Image Decoder -// - This constructor is called only once by Document class -CimgDecode::CimgDecode(CDocLog *pLog, CwindowBuf *pWBuf, QWidget *parent) : QWidget(parent) -{ - // Ideally this would be passed by constructor, but simply access directly for now. -// CJPEGsnoopApp *pApp; - -//@@ pApp = (CJPEGsnoopApp*)AfxGetApp(); -//@@ m_pAppConfig = pApp->m_pAppConfig; -//@@ Q_ASSERT(m_pAppConfig); - - m_bVerbose = false; - - Q_ASSERT(pLog); - Q_ASSERT(pWBuf); - m_pLog = pLog; - m_pWBuf = pWBuf; - - m_pStatBar = NULL; - m_bDibTempReady = false; - m_bPreviewIsJpeg = false; - m_bDibHistRgbReady = false; - m_bDibHistYReady = false; - - m_bHistEn = false; - m_bStatClipEn = false; // UNUSED - - m_pMcuFileMap = NULL; - m_pBlkDcValY = NULL; - m_pBlkDcValCb = NULL; - m_pBlkDcValCr = NULL; - m_pPixValY = NULL; - m_pPixValCb = NULL; - m_pPixValCr = NULL; - - // Reset the image decoding state - Reset(); - - m_nImgSizeXPartMcu = 0; - m_nImgSizeYPartMcu = 0; - m_nImgSizeX = 0; - m_nImgSizeY = 0; - - // FIXME: Temporary hack to avoid divide-by-0 when displaying PSD (instead of JPEG) - m_nMcuWidth = 1; - m_nMcuHeight = 1; - - // Detailed VLC Decode mode - m_bDetailVlc = false; - m_nDetailVlcX = 0; - m_nDetailVlcY = 0; - m_nDetailVlcLen = 1; - - m_bDecodeScanAc = true; - - m_sHisto.nClipYMin = 0; - - // Set up the IDCT lookup tables - PrecalcIdct(); - - GenLookupHuffMask(); - - // The following contain information that is set by - // the JFIF Decoder. We can only reset them here during - // the constructor and later by explicit call by JFIF Decoder. - ResetState(); - - // We don't call SetPreviewMode() here because it would - // automatically try to recalculate the view (but nothing ready yet) - m_nPreviewMode = PREVIEW_RGB; - SetPreviewZoom(false, false, true, PRV_ZOOM_12); - - m_bViewOverlaysMcuGrid = false; - - // Start off with no YCC offsets for CalcChannelPreview() - SetPreviewYccOffset(0, 0, 0, 0, 0); - - SetPreviewMcuInsert(0, 0, 0); - - setStyleSheet("background-color: white"); -} - // Destructor for Image Decode class // - Deallocate any image-related dynamic storage CimgDecode::~CimgDecode() @@ -234,42 +225,42 @@ CimgDecode::~CimgDecode() if(m_pMcuFileMap) { delete[]m_pMcuFileMap; - m_pMcuFileMap = NULL; + m_pMcuFileMap = 0; } if(m_pBlkDcValY) { delete[]m_pBlkDcValY; - m_pBlkDcValY = NULL; + m_pBlkDcValY = 0; } if(m_pBlkDcValCb) { delete[]m_pBlkDcValCb; - m_pBlkDcValCb = NULL; + m_pBlkDcValCb = 0; } if(m_pBlkDcValCr) { delete[]m_pBlkDcValCr; - m_pBlkDcValCr = NULL; + m_pBlkDcValCr = 0; } if(m_pPixValY) { delete[]m_pPixValY; - m_pPixValY = NULL; + m_pPixValY = 0; } if(m_pPixValCb) { delete[]m_pPixValCb; - m_pPixValCb = NULL; + m_pPixValCb = 0; } if(m_pPixValCr) { delete[]m_pPixValCr; - m_pPixValCr = NULL; + m_pPixValCr = 0; } } @@ -307,156 +298,156 @@ void CimgDecode::ResetState() m_nMarkersBlkNum = 0; } -void CimgDecode::paintEvent(QPaintEvent *) -{ - int32_t top = 0; - - QRect bRect; - - QStyleOption opt; - opt.init(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); - p.setFont(QFont("Courier New", 14)); - - p.fillRect(0, 0, width(), height(), QColor(Qt::white)); - - if(m_bDibTempReady) - { - if(!m_bPreviewIsJpeg) - { - // For all non-JPEG images, report with simple title - m_strTitle = "Image"; - } - else - { - m_strTitle = "Image ("; - - switch (m_nPreviewMode) - { - case PREVIEW_RGB: - m_strTitle += "RGB"; - break; - - case PREVIEW_YCC: - m_strTitle += "YCC"; - break; - - case PREVIEW_R: - m_strTitle += "R"; - break; - - case PREVIEW_G: - m_strTitle += "G"; - break; - - case PREVIEW_B: - m_strTitle += "B"; - break; - - case PREVIEW_Y: - m_strTitle += "Y"; - break; - - case PREVIEW_CB: - m_strTitle += "Cb"; - break; +//void CimgDecode::paintEvent(QPaintEvent *) +//{ +// int32_t top = 0; - case PREVIEW_CR: - m_strTitle += "Cr"; - break; +// QRect bRect; - default: - m_strTitle += "???"; - break; - } +// QStyleOption opt; +// opt.init(this); +// QPainter p(this); +// style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); +// p.setFont(QFont("Courier New", 14)); - if(m_bDecodeScanAc) - { - m_strTitle += ", DC+AC)"; - } - else - { - m_strTitle += ", DC)"; - } - } +// p.fillRect(0, 0, width(), height(), QColor(Qt::white)); - switch (m_nZoomMode) - { - case PRV_ZOOM_12: - m_strTitle += " @ 12.5% (1/8)"; - break; +// if(m_bDibTempReady) +// { +// if(!m_bPreviewIsJpeg) +// { +// // For all non-JPEG images, report with simple title +// m_strTitle = "Image"; +// } +// else +// { +// m_strTitle = "Image ("; + +// switch (m_nPreviewMode) +// { +// case PREVIEW_RGB: +// m_strTitle += "RGB"; +// break; + +// case PREVIEW_YCC: +// m_strTitle += "YCC"; +// break; + +// case PREVIEW_R: +// m_strTitle += "R"; +// break; + +// case PREVIEW_G: +// m_strTitle += "G"; +// break; + +// case PREVIEW_B: +// m_strTitle += "B"; +// break; + +// case PREVIEW_Y: +// m_strTitle += "Y"; +// break; + +// case PREVIEW_CB: +// m_strTitle += "Cb"; +// break; + +// case PREVIEW_CR: +// m_strTitle += "Cr"; +// break; + +// default: +// m_strTitle += "???"; +// break; +// } + +// if(m_bDecodeScanAc) +// { +// m_strTitle += ", DC+AC)"; +// } +// else +// { +// m_strTitle += ", DC)"; +// } +// } + +// switch (m_nZoomMode) +// { +// case PRV_ZOOM_12: +// m_strTitle += " @ 12.5% (1/8)"; +// break; - case PRV_ZOOM_25: - m_strTitle += " @ 25% (1/4)"; - break; +// case PRV_ZOOM_25: +// m_strTitle += " @ 25% (1/4)"; +// break; - case PRV_ZOOM_50: - m_strTitle += " @ 50% (1/2)"; - break; +// case PRV_ZOOM_50: +// m_strTitle += " @ 50% (1/2)"; +// break; - case PRV_ZOOM_100: - m_strTitle += " @ 100% (1:1)"; - break; +// case PRV_ZOOM_100: +// m_strTitle += " @ 100% (1:1)"; +// break; - case PRV_ZOOM_150: - m_strTitle += " @ 150% (3:2)"; - break; +// case PRV_ZOOM_150: +// m_strTitle += " @ 150% (3:2)"; +// break; - case PRV_ZOOM_200: - m_strTitle += " @ 200% (2:1)"; - break; +// case PRV_ZOOM_200: +// m_strTitle += " @ 200% (2:1)"; +// break; - case PRV_ZOOM_300: - m_strTitle += " @ 300% (3:1)"; - break; +// case PRV_ZOOM_300: +// m_strTitle += " @ 300% (3:1)"; +// break; - case PRV_ZOOM_400: - m_strTitle += " @ 400% (4:1)"; - break; +// case PRV_ZOOM_400: +// m_strTitle += " @ 400% (4:1)"; +// break; - case PRV_ZOOM_800: - m_strTitle += " @ 800% (8:1)"; - break; +// case PRV_ZOOM_800: +// m_strTitle += " @ 800% (8:1)"; +// break; - default: - m_strTitle += ""; - break; - } +// default: +// m_strTitle += ""; +// break; +// } - // Draw image title - bRect = p.boundingRect(QRect(nTitleIndent, top, width(), 100), Qt::AlignLeft | Qt::AlignTop, m_strTitle); - p.drawText(bRect, Qt::AlignLeft | Qt::AlignCenter, m_strTitle); +// // Draw image title +// bRect = p.boundingRect(QRect(nTitleIndent, top, width(), 100), Qt::AlignLeft | Qt::AlignTop, m_strTitle); +// p.drawText(bRect, Qt::AlignLeft | Qt::AlignCenter, m_strTitle); - top = bRect.height() + nTitleLowGap; -// p.drawImage(nTitleIndent, top, m_pDibTemp->scaled(m_pDibTemp->width() / 4, m_pDibTemp->height() / 4, Qt::KeepAspectRatio)); +// top = bRect.height() + nTitleLowGap; +//// p.drawImage(nTitleIndent, top, m_pDibTemp->scaled(m_pDibTemp->width() / 4, m_pDibTemp->height() / 4, Qt::KeepAspectRatio)); -// top += m_pDibTemp->height() + nTitleLowGap; - top += nTitleLowGap; - } +//// top += m_pDibTemp->height() + nTitleLowGap; +// top += nTitleLowGap; +// } - if(m_bHistEn) - { - if(m_bDibHistRgbReady) - { - bRect = p.boundingRect(QRect(nTitleIndent, top, width(), 100), Qt::AlignLeft | Qt::AlignTop, "Histogram (RGB)"); - p.drawText(bRect, Qt::AlignLeft | Qt::AlignCenter, "Histogram (RGB)"); +// if(m_bHistEn) +// { +// if(m_bDibHistRgbReady) +// { +// bRect = p.boundingRect(QRect(nTitleIndent, top, width(), 100), Qt::AlignLeft | Qt::AlignTop, "Histogram (RGB)"); +// p.drawText(bRect, Qt::AlignLeft | Qt::AlignCenter, "Histogram (RGB)"); - top += bRect.height() + nTitleLowGap; - p.drawImage(nTitleIndent, top, *m_pDibHistRgb); - top += m_pDibHistRgb->height() + nTitleLowGap; - } +// top += bRect.height() + nTitleLowGap; +// p.drawImage(nTitleIndent, top, *m_pDibHistRgb); +// top += m_pDibHistRgb->height() + nTitleLowGap; +// } - if(m_bDibHistYReady) - { - bRect = p.boundingRect(QRect(nTitleIndent, top, width(), 100), Qt::AlignLeft | Qt::AlignTop, "Histogram (Y)"); - p.drawText(bRect, Qt::AlignLeft | Qt::AlignCenter, "Histogram (Y)"); +// if(m_bDibHistYReady) +// { +// bRect = p.boundingRect(QRect(nTitleIndent, top, width(), 100), Qt::AlignLeft | Qt::AlignTop, "Histogram (Y)"); +// p.drawText(bRect, Qt::AlignLeft | Qt::AlignCenter, "Histogram (Y)"); - top += bRect.height() + nTitleLowGap; - p.drawImage(nTitleIndent, top, *m_pDibHistY); - } - } -} +// top += bRect.height() + nTitleLowGap; +// p.drawImage(nTitleIndent, top, *m_pDibHistY); +// } +// } +//} // Save a copy of the status bar control // @@ -616,7 +607,7 @@ bool CimgDecode::SetDqtEntry(uint32_t nTblDestId, uint32_t nCoeffInd, uint32_t n Q_ASSERT(false); #endif - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -652,7 +643,7 @@ uint32_t CimgDecode::GetDqtEntry(uint32_t nTblDestId, uint32_t nCoeffInd) strTmp = QString("ERROR: GetDqtEntry(nTblDestId = %1, nCoeffInd = %2").arg(nTblDestId).arg(nCoeffInd); m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -696,7 +687,7 @@ bool CimgDecode::SetDqtTables(uint32_t nCompId, uint32_t nTbl) .arg(nTbl); m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -741,7 +732,7 @@ bool CimgDecode::SetDhtTables(uint32_t nCompInd, uint32_t nTblDc, uint32_t nTblA .arg(nTblAc); m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -828,12 +819,12 @@ void CimgDecode::SetSofSampFactors(uint32_t nCompInd, uint32_t nSampFactH, uint3 // - nMode = Mode used in channel display (eg. NONE, RGB, YCC) // See PREVIEW_* constants // -void CimgDecode::SetPreviewMode(uint32_t nMode) +void CimgDecode::setPreviewMode(QAction *action) { - // Need to check to see if mode has changed. If so, we - // need to recalculate the temporary preview. - m_nPreviewMode = nMode; + // Need to check to see if mode has changed. If so, we need to recalculate the temporary preview. + m_nPreviewMode = action->data().toInt(); CalcChannelPreview(); + emit updateImage(); } // Update any level shifts for the preview display @@ -951,7 +942,7 @@ bool CimgDecode::SetDhtEntry(uint32_t nDestId, uint32_t nClass, uint32_t nInd, u m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -1048,7 +1039,7 @@ bool CimgDecode::SetDhtSize(uint32_t nDestId, uint32_t nClass, uint32_t nSize) m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -2823,7 +2814,7 @@ void CimgDecode::DecodeIdctCalcFixedpt() // - m_pPixValCb // - m_pPixValCr // -void CimgDecode::ClrFullRes(uint32_t nWidth, uint32_t nHeight) +void CimgDecode::ClrFullRes(int32_t nWidth, int32_t nHeight) { Q_ASSERT(m_pPixValY); @@ -2834,12 +2825,12 @@ void CimgDecode::ClrFullRes(uint32_t nWidth, uint32_t nHeight) } // FIXME: Add in range checking here - memset(m_pPixValY, 0, (nWidth * nHeight * sizeof(short))); + memset(m_pPixValY, 0, (nWidth * nHeight * sizeof(int16_t))); if(m_nNumSosComps == NUM_CHAN_YCC) { - memset(m_pPixValCb, 0, (nWidth * nHeight * sizeof(short))); - memset(m_pPixValCr, 0, (nWidth * nHeight * sizeof(short))); + memset(m_pPixValCb, 0, (nWidth * nHeight * sizeof(int16_t))); + memset(m_pPixValCr, 0, (nWidth * nHeight * sizeof(int16_t))); } } @@ -2861,7 +2852,7 @@ void CimgDecode::ClrFullRes(uint32_t nWidth, uint32_t nHeight) // PRE: // - DecodeIdctCalc() already called on Lum AC, and Lum DC already done // -void CimgDecode::SetFullRes(uint32_t nMcuX, uint32_t nMcuY, uint32_t nComp, uint32_t nCssXInd, uint32_t nCssYInd, int16_t nDcOffset) +void CimgDecode::SetFullRes(int32_t nMcuX, int32_t nMcuY, int32_t nComp, uint32_t nCssXInd, uint32_t nCssYInd, int16_t nDcOffset) { uint32_t nYX; @@ -2869,7 +2860,7 @@ void CimgDecode::SetFullRes(uint32_t nMcuX, uint32_t nMcuY, uint32_t nComp, uint int16_t nVal; - uint32_t nChan; + int32_t nChan; // Convert from Component index (1-based) to Channel index (0-based) // Component index is direct from SOF/SOS @@ -2881,7 +2872,10 @@ void CimgDecode::SetFullRes(uint32_t nMcuX, uint32_t nMcuY, uint32_t nComp, uint QString strDebug; strTmp = QString("SetFullRes() with nComp <= 0 [%1]").arg(nComp); - strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("ImgDecode", -10).arg(strTmp); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n") + .arg(m_pAppConfig->strCurFname, -100) + .arg("ImgDecode", -10) + .arg(strTmp); qDebug() << strDebug; #else Q_ASSERT(false); @@ -2891,9 +2885,9 @@ void CimgDecode::SetFullRes(uint32_t nMcuX, uint32_t nMcuY, uint32_t nComp, uint nChan = nComp - 1; - uint32_t nPixMapW = m_nBlkXMax * BLK_SZ_X; // Width of pixel map - uint32_t nOffsetBlkCorner; // Linear offset to top-left corner of block - uint32_t nOffsetPixCorner; // Linear offset to top-left corner of pixel (start point for expansion) + int32_t nPixMapW = m_nBlkXMax * BLK_SZ_X; // Width of pixel map + int32_t nOffsetBlkCorner; // Linear offset to top-left corner of block + int32_t nOffsetPixCorner; // Linear offset to top-left corner of pixel (start point for expansion) // Calculate the linear pixel offset for the top-left corner of the block in the MCU nOffsetBlkCorner = ((nMcuY * m_nMcuHeight) + nCssYInd * BLK_SZ_X) * nPixMapW + ((nMcuX * m_nMcuWidth) + nCssXInd * BLK_SZ_Y); @@ -2909,8 +2903,7 @@ void CimgDecode::SetFullRes(uint32_t nMcuX, uint32_t nMcuY, uint32_t nComp, uint { nYX = nY * BLK_SZ_X + nX; - // Fetch the pixel value from the IDCT 8x8 block - // and perform DC level shift + // Fetch the pixel value from the IDCT 8x8 block and perform DC level shift #ifdef IDCT_FIXEDPT nVal = m_anIdctBlock[nYX]; // TODO: Why do I need AC value x8 multiplier? @@ -3145,31 +3138,33 @@ void CimgDecode::SetImageDimensions(uint32_t nWidth, uint32_t nHeight) // void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) { + qDebug() << "CimgDecode::DecodeScanImg Start"; + QString strTmp; bool bDieOnFirstErr = false; // FIXME: do we want this? It makes it less useful for corrupt jpegs // Fetch configuration values locally - bool bDumpHistoY = m_pAppConfig->bDumpHistoY; + bool bDumpHistoY = m_pAppConfig->displayYHistogram(); bool bDecodeScanAc; - uint32_t nScanErrMax = m_pAppConfig->nErrMaxDecodeScan; + int32_t nScanErrMax = m_pAppConfig->maxDecodeError(); // Add some extra speed-up in hidden mode (we don't need AC) if(bDisplay) { - bDecodeScanAc = m_pAppConfig->bDecodeScanImgAc; + bDecodeScanAc = m_pAppConfig->decodeAc(); } else { bDecodeScanAc = false; } - m_bHistEn = m_pAppConfig->bHistoEn; - m_bStatClipEn = m_pAppConfig->bStatClipEn; + m_bHistEn = m_pAppConfig->displayRgbHistogram(); + m_bStatClipEn = m_pAppConfig->clipStats(); - uint32_t nPixMapW = 0; - uint32_t nPixMapH = 0; + int32_t nPixMapW = 0; + int32_t nPixMapH = 0; // Reset the decoder state variables Reset(); @@ -3185,8 +3180,7 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) return; } - // Even though we support decoding of MAX_SOS_COMP_NS we limit - // the component flexibility further + // Even though we support decoding of MAX_SOS_COMP_NS we limit the component flexibility further if((m_nNumSosComps != NUM_CHAN_GRAYSCALE) && (m_nNumSosComps != NUM_CHAN_YCC)) { strTmp = QString(" NOTE: Number of SOS components not supported [%1]").arg(m_nNumSosComps); @@ -3285,12 +3279,12 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) m_nImgSizeXPartMcu = m_nMcuXMax * m_nMcuWidth; m_nImgSizeYPartMcu = m_nMcuYMax * m_nMcuHeight; - // Detect incomplete (partial) MCUs and round-up the MCU - // ranges if necessary. + // Detect incomplete (partial) MCUs and round-up the MCU ranges if necessary. if((m_nDimX % m_nMcuWidth) != 0) { m_nMcuXMax++; } + if((m_nDimY % m_nMcuHeight) != 0) { m_nMcuYMax++; @@ -3313,9 +3307,9 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) m_rectImgBase = QRect(QPoint(0, 0), QSize(m_nImgSizeX, m_nImgSizeY)); // Determine decoding range - uint32_t nDecMcuRowStart; - uint32_t nDecMcuRowEnd; // End to AC scan decoding - uint32_t nDecMcuRowEndFinal; // End to general decoding + int32_t nDecMcuRowStart; + int32_t nDecMcuRowEnd; // End to AC scan decoding + int32_t nDecMcuRowEndFinal; // End to general decoding nDecMcuRowStart = 0; nDecMcuRowEnd = m_nMcuYMax; @@ -3326,7 +3320,7 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) nDecMcuRowEndFinal = qMin(nDecMcuRowEndFinal, m_nMcuYMax); // Allocate the MCU File Map - Q_ASSERT(m_pMcuFileMap == NULL); + Q_ASSERT(m_pMcuFileMap == 0); m_pMcuFileMap = new uint32_t[m_nMcuYMax * m_nMcuXMax]; if(!m_pMcuFileMap) @@ -3334,7 +3328,7 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) strTmp = "ERROR: Not enough memory for Image Decoder MCU File Pos Map"; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -3343,17 +3337,17 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) return; } - memset(m_pMcuFileMap, 0, (m_nMcuYMax * m_nMcuXMax * sizeof(uint32_t))); + memset(m_pMcuFileMap, 0, (m_nMcuYMax * m_nMcuXMax * sizeof(int32_t))); // Allocate the 8x8 Block DC Map - m_pBlkDcValY = new short[m_nBlkYMax * m_nBlkXMax]; + m_pBlkDcValY = new int16_t[m_nBlkYMax * m_nBlkXMax]; if((!m_pBlkDcValY)) { strTmp = "ERROR: Not enough memory for Image Decoder Blk DC Value Map"; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -3364,16 +3358,15 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) if(m_nNumSosComps == NUM_CHAN_YCC) { - m_pBlkDcValCb = new short[m_nBlkYMax * m_nBlkXMax]; - - m_pBlkDcValCr = new short[m_nBlkYMax * m_nBlkXMax]; + m_pBlkDcValCb = new int16_t[m_nBlkYMax * m_nBlkXMax]; + m_pBlkDcValCr = new int16_t[m_nBlkYMax * m_nBlkXMax]; if((!m_pBlkDcValCb) || (!m_pBlkDcValCr)) { strTmp = "ERROR: Not enough memory for Image Decoder Blk DC Value Map"; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -3396,23 +3389,23 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) nPixMapW = m_nBlkXMax * BLK_SZ_X; // Ensure no image allocated yet - Q_ASSERT(m_pPixValY == NULL); + Q_ASSERT(m_pPixValY == 0); if(m_nNumSosComps == NUM_CHAN_YCC) { - Q_ASSERT(m_pPixValCb == NULL); - Q_ASSERT(m_pPixValCr == NULL); + Q_ASSERT(m_pPixValCb == 0); + Q_ASSERT(m_pPixValCr == 0); } // Allocate image (YCC) - m_pPixValY = new short[nPixMapW * nPixMapH]; + m_pPixValY = new int16_t[nPixMapW * nPixMapH]; if((!m_pPixValY)) { strTmp = "ERROR: Not enough memory for Image Decoder Pixel YCC Value Map"; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -3423,16 +3416,15 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) if(m_nNumSosComps == NUM_CHAN_YCC) { - m_pPixValCb = new short[nPixMapW * nPixMapH]; - - m_pPixValCr = new short[nPixMapW * nPixMapH]; + m_pPixValCb = new int16_t[nPixMapW * nPixMapH]; + m_pPixValCr = new int16_t[nPixMapW * nPixMapH]; if((!m_pPixValCb) || (!m_pPixValCr)) { strTmp = "ERROR: Not enough memory for Image Decoder Pixel YCC Value Map"; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -3448,38 +3440,9 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) ClrFullRes(nPixMapW, nPixMapH); } - // ------------------------------------- - // Allocate the device-independent bitmap (DIB) - - uint8_t *pDibImgTmpBits = NULL; - uint32_t nDibImgRowBytes; - // If a previous bitmap was created, deallocate it and start fresh -//@@ m_pDibTemp.Kill(); m_bDibTempReady = false; m_bPreviewIsJpeg = false; - - // Create the DIB - // Although we are creating a 32-bit DIB, it should also - // work to run in 16- and 8-bit modes - - bool bDoImage = false; // Are we safe to set bits? - - if(bDisplay) - { -//@@ m_pDibTemp.CreateDIB(m_nImgSizeX, m_nImgSizeY, 32); - nDibImgRowBytes = m_nImgSizeX * sizeof(QRgb); -//@@ pDibImgTmpBits = (uint8_t *) (m_pDibTemp.GetDIBBitArray()); - -// if(pDibImgTmpBits) -// { -// bDoImage = true; -// } -// else -// { -// // TODO: Should we be exiting here instead? -// } - } // ------------------------------------- @@ -3539,6 +3502,7 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) bDqtReady = false; } } + if(!bDqtReady) { m_pLog->AddLineErr("*** ERROR: Decoding image before DQT Table Selection via JFIF_SOF ***"); @@ -3547,9 +3511,8 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) } else { - // FIXME: Not sure that we can always depend on the indices to appear - // in this order. May need another layer of indirection to get at the - // frame image component index. + // FIXME: Not sure that we can always depend on the indices to appear in this order. + // May need another layer of indirection to get at the frame image component index. nDqtTblY = m_anDqtTblSel[DQT_DEST_Y]; nDqtTblCb = m_anDqtTblSel[DQT_DEST_CB]; nDqtTblCr = m_anDqtTblSel[DQT_DEST_CR]; @@ -3575,7 +3538,9 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) for(uint32_t nCompInd = 1; nCompInd <= m_nNumSosComps; nCompInd++) { if(m_anDhtTblSel[nClass][nCompInd] < 0) + { bDhtReady = false; + } } } @@ -3586,12 +3551,15 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) { // Check for DC DHT table nSel = m_anDhtTblSel[DHT_CLASS_DC][nCompInd]; + if(m_anDhtLookupSize[DHT_CLASS_DC][nSel] == 0) { bDhtReady = false; } + // Check for AC DHT table nSel = m_anDhtTblSel[DHT_CLASS_AC][nCompInd]; + if(m_anDhtLookupSize[DHT_CLASS_AC][nSel] == 0) { bDhtReady = false; @@ -3610,8 +3578,7 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) // image component index and class (AC,DC). // // No need to check if a table is valid here since we have - // previously checked to ensure that all required tables - // exist. + // previously checked to ensure that all required tables exist. // NOTE: If the table has not been defined, then the index // will be 0xFFFFFFFF. ReadScanVal() will trap this with Q_ASSERT // should it ever be used. @@ -3639,9 +3606,9 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) else { m_pLog->AddLine(" Scan Decode Mode: No IDCT (DC only)"); - m_pLog-> - AddLineWarn(" NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT]"); + m_pLog-> AddLineWarn(" NOTE: Low-resolution DC component shown. Can decode full-res with [Options->Scan Segment->Full IDCT]"); } + m_pLog->AddLine(""); } @@ -3681,16 +3648,13 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) // TODO: Trap escape keypress here (or run as thread) bool bDscRet; // Return value for DecodeScanComp() - bool bScanStop = false; for(uint32_t nMcuX = 0; (nMcuX < m_nMcuXMax) && (!bScanStop); nMcuX++) { - // Check to see if we should expect a restart marker! // FIXME: Should actually check to ensure that we do in - // fact get a restart marker, and that it was the right - // one! + // fact get a restart marker, and that it was the right one! if((m_bRestartEn) && (m_nRestartMcusLeft == 0)) { /* @@ -3699,6 +3663,7 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) m_pLog->AddLine(strTmp); } */ + if(m_bRestartRead) { /* @@ -3765,8 +3730,7 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) } // Luminance - // If there is chroma subsampling, then this block will have - // (css_x * css_y) luminance blocks to process + // If there is chroma subsampling, then this block will have (css_x * css_y) luminance blocks to process // We store them all in an array m_anDcLumCss[] // Give separator line between MCUs @@ -3836,7 +3800,9 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) #if 1 if(bDisplay) + { SetFullRes(nMcuX, nMcuY, nComp, nCssIndH, nCssIndV, m_nDcLum); + } #else // FIXME // Temporarily experiment with trying to handle multiple scans @@ -3874,7 +3840,6 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) // TODO: Counting pixels makes assumption that luminance is // not subsampled, so we increment by 64. m_nNumPixels += BLK_SZ_X * BLK_SZ_Y; - } } @@ -3971,12 +3936,11 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) } } } - } + #ifdef DEBUG_YCCK else if(m_nNumSosComps == NUM_CHAN_YCCK) { - // -------------------------------------------------------------- nComp = SCAN_COMP_CB; @@ -4144,10 +4108,13 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) #ifdef DEBUG_LOG QString strDebug; - strTmp = - QString("DecodeScanImg() with nBlkXY out of range. nBlkXY=[%1] m_nBlkXMax=[%2] m_nBlkYMax=[%3]").arg(nBlkXY). - arg(m_nBlkXMax).arg(m_nBlkYMax); - strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n").arg(m_pAppConfig->strCurFname, -100).arg("ImgDecode", -10).arg(strTmp); + strTmp = QString("DecodeScanImg() with nBlkXY out of range. nBlkXY=[%1] m_nBlkXMax=[%2] m_nBlkYMax=[%3]") + .arg(nBlkXY) + .arg(m_nBlkXMax) + .arg(m_nBlkYMax); + strDebug = QString("## File=[%1] Block=[%2] Error=[%3]\n") + .arg(m_pAppConfig->strCurFname, -100) + .arg("ImgDecode", -10).arg(strTmp); qDebug() << strDebug; #else Q_ASSERT(false); @@ -4240,7 +4207,6 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) bScanStop = true; } } // nMcuX - } // nMcuY if(!bQuiet) @@ -4264,7 +4230,6 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) { m_bDibTempReady = true; m_bPreviewIsJpeg = true; - update(); } // ------------------------------------ @@ -4281,7 +4246,9 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) static_cast((m_anScanBuffPtr_pos[0] - m_nScanBuffPtr_first) * 8); strTmp = QString(" Compression Ratio: %1:1").arg(nCompressionRatio, 5, 'f', 2); m_pLog->AddLine(strTmp); - double nBitsPerPixel = static_cast((m_anScanBuffPtr_pos[0] - m_nScanBuffPtr_first) * 8) / + + double nBitsPerPixel = + static_cast((m_anScanBuffPtr_pos[0] - m_nScanBuffPtr_first) * 8) / static_cast(m_nDimX * m_nDimY); strTmp = QString(" Bits per pixel: %1:1").arg(nBitsPerPixel, 5, 'f', 2); @@ -4336,8 +4303,7 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) if(bDisplay && m_bAvgYValid) { m_pLog->AddLine(" Average Pixel Luminance (Y):"); - strTmp = QString(" Y=[%1] (range: 0..255)").arg(m_nAvgY, 3); - m_pLog->AddLine(strTmp); + m_pLog->AddLine(QString(" Y=[%1] (range: 0..255)").arg(m_nAvgY, 3)); m_pLog->AddLine(""); } @@ -4366,7 +4332,6 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) m_pLog->AddLine(strTmp); strTmp = QString(" Next position in scan buffer: Offset %1").arg(GetScanBufPos()); m_pLog->AddLine(strTmp); - m_pLog->AddLine(""); } @@ -4568,92 +4533,84 @@ void CimgDecode::DrawHistogram(bool bQuiet, bool bDumpHistoY) int32_t nHistoPeakVal; int32_t nHistoX; int32_t nHistoCurVal; -// int32_t nDibHistoRowBytes; -// int8_t *pDibHistoBits; -//@@ m_pDibHistRgb.Kill(); m_bDibHistRgbReady = false; m_pDibHistRgb = new QImage(HISTO_BINS * HISTO_BIN_WIDTH, 3 * HISTO_BIN_HEIGHT_MAX, QImage::Format_RGB32); + m_pDibHistRgb->fill(Qt::white); -//@@ m_pDibHistRgb.CreateDIB(HISTO_BINS * HISTO_BIN_WIDTH, 3 * HISTO_BIN_HEIGHT_MAX, 32); -// nDibHistoRowBytes = (HISTO_BINS * HISTO_BIN_WIDTH) * 4; -//@@ pDibHistoBits = (uint8_t *) (m_pDibHistRgb.GetDIBBitArray()); - -// m_rectHistBase = QRect(QPoint(0, 0), QSize(HISTO_BINS * HISTO_BIN_WIDTH, 3 * HISTO_BIN_HEIGHT_MAX)); - -// if(pDibHistoBits != NULL) -// { -// memset(pDibHistoBits, 0, 3 * HISTO_BIN_HEIGHT_MAX * nDibHistoRowBytes); - - // Do peak detect first - // Don't want to reset peak value to 0 as otherwise we might get - // division by zero later when we calculate nHistoBinHeight - nHistoPeakVal = 1; + // Do peak detect first + // Don't want to reset peak value to 0 as otherwise we might get + // division by zero later when we calculate nHistoBinHeight + nHistoPeakVal = 1; - // Peak value is across all three channels! - for(int32_t nHistChan = 0; nHistChan < 3; nHistChan++) + // Peak value is across all three channels! + for(int32_t nHistChan = 0; nHistChan < 3; nHistChan++) + { + for(int32_t i = 0; i < HISTO_BINS; i++) { - for(int32_t i = 0; i < HISTO_BINS; i++) + if(nHistChan == 0) { - if(nHistChan == 0) - { - nHistoCurVal = m_anCcHisto_r[i]; - } - else if(nHistChan == 1) - { - nHistoCurVal = m_anCcHisto_g[i]; - } - else - { - nHistoCurVal = m_anCcHisto_b[i]; - } - - nHistoPeakVal = (nHistoCurVal > nHistoPeakVal) ? nHistoCurVal : nHistoPeakVal; + nHistoCurVal = m_anCcHisto_r[i]; } + else if(nHistChan == 1) + { + nHistoCurVal = m_anCcHisto_g[i]; + } + else + { + nHistoCurVal = m_anCcHisto_b[i]; + } + + nHistoPeakVal = (nHistoCurVal > nHistoPeakVal) ? nHistoCurVal : nHistoPeakVal; } + } - for(int32_t nHistChan = 0; nHistChan < 3; nHistChan++) + for(int32_t nHistChan = 0; nHistChan < 3; nHistChan++) + { + if(nHistChan == CHAN_R) + { + rgbHistOffset = HISTO_BIN_HEIGHT_MAX - 1; + } + else if(nHistChan == CHAN_G) + { + rgbHistOffset = HISTO_BIN_HEIGHT_MAX * 2 - 1; + } + else { - for(int32_t i = 0; i < HISTO_BINS; i++) + rgbHistOffset = HISTO_BIN_HEIGHT_MAX * 3 - 1; + } + + for(int32_t i = 0; i < HISTO_BINS; i++) + { + // Calculate bin's height (max HISTO_BIN_HEIGHT_MAX) + if(nHistChan == CHAN_R) { - // Calculate bin's height (max HISTO_BIN_HEIGHT_MAX) - if(nHistChan == CHAN_R) - { - nHistoCurVal = m_anCcHisto_r[i]; - rgbHistOffset = HISTO_BIN_HEIGHT_MAX - 1; - } - else if(nHistChan == CHAN_G) - { - nHistoCurVal = m_anCcHisto_g[i]; - rgbHistOffset = HISTO_BIN_HEIGHT_MAX * 2 - 1; - } - else - { - nHistoCurVal = m_anCcHisto_b[i]; - rgbHistOffset = HISTO_BIN_HEIGHT_MAX * 3 - 1; - } + nHistoCurVal = m_anCcHisto_r[i]; + } + else if(nHistChan == CHAN_G) + { + nHistoCurVal = m_anCcHisto_g[i]; + } + else + { + nHistoCurVal = m_anCcHisto_b[i]; + } - nHistoBinHeight = HISTO_BIN_HEIGHT_MAX * nHistoCurVal / nHistoPeakVal; + nHistoBinHeight = HISTO_BIN_HEIGHT_MAX * nHistoCurVal / nHistoPeakVal; - for(int32_t y = 0; y < nHistoBinHeight; y++) + for(int32_t y = 0; y < nHistoBinHeight; y++) + { + // Store the RGB triplet + for(int32_t bin_width = 0; bin_width < HISTO_BIN_WIDTH; bin_width++) { - // Store the RGB triplet - for(int32_t bin_width = 0; bin_width < HISTO_BIN_WIDTH; bin_width++) - { - nHistoX = (i * HISTO_BIN_WIDTH) + bin_width; -// nCoordY = ((2 - nHistChan) * HISTO_BIN_HEIGHT_MAX) + y; - nCoordY = (rgbHistOffset - y) -1; - m_pDibHistRgb->setPixelColor(nHistoX, nCoordY, QColor((nHistChan == CHAN_R) ? 255 : 0, (nHistChan == CHAN_G) ? 255 : 0, (nHistChan == CHAN_B) ? 255 : 0)); - -// pDibHistoBits[(nHistoX * 4) + 3 + (nCoordY * nDibHistoRowBytes)] = 0; -// pDibHistoBits[(nHistoX * 4) + 2 + (nCoordY * nDibHistoRowBytes)] = (nHistChan == 0) ? 255 : 0; -// pDibHistoBits[(nHistoX * 4) + 1 + (nCoordY * nDibHistoRowBytes)] = (nHistChan == 1) ? 255 : 0; -// pDibHistoBits[(nHistoX * 4) + 0 + (nCoordY * nDibHistoRowBytes)] = (nHistChan == 2) ? 255 : 0; - } + nHistoX = (i * HISTO_BIN_WIDTH) + bin_width; + // nCoordY = ((2 - nHistChan) * HISTO_BIN_HEIGHT_MAX) + y; + nCoordY = (rgbHistOffset - y) -1; + m_pDibHistRgb->setPixelColor(nHistoX, nCoordY, QColor((nHistChan == CHAN_R) ? 255 : 0, (nHistChan == CHAN_G) ? 255 : 0, (nHistChan == CHAN_B) ? 255 : 0)); } - } // i: 0..HISTO_BINS-1 -// } // nHistChan + } + } // i: 0..HISTO_BINS-1 m_bDibHistRgbReady = true; } @@ -4663,65 +4620,49 @@ void CimgDecode::DrawHistogram(bool bQuiet, bool bDumpHistoY) if(bDumpHistoY) { -//@@ m_pDibHistY.Kill(); - -//@@ m_pDibHistY.CreateDIB(SUBSET_HISTO_BINS * HISTO_BIN_WIDTH, SUBSET_HISTO_BINS * HISTO_BIN_WIDTH, 32); -// nDibHistoRowBytes = (SUBSET_HISTO_BINS * HISTO_BIN_WIDTH) * 4; -//@@ pDibHistoBits = (uint8_t *) (m_pDibHistY.GetDIBBitArray()); - m_pDibHistY = new QImage(SUBSET_HISTO_BINS * HISTO_BIN_WIDTH, HISTO_BIN_HEIGHT_MAX, QImage::Format_RGB32); -// m_rectHistYBase = QRect(QPoint(0, 0), QSize(SUBSET_HISTO_BINS * HISTO_BIN_WIDTH, HISTO_BIN_HEIGHT_MAX)); - -// if(pDibHistoBits != NULL) -// { -// memset(pDibHistoBits, 0, HISTO_BIN_HEIGHT_MAX * nDibHistoRowBytes); + m_pDibHistY->fill(Qt::white); - // Do peak detect first - // Don't want to reset peak value to 0 as otherwise we might get - // division by zero later when we calculate nHistoBinHeight - nHistoPeakVal = 1; + // Do peak detect first + // Don't want to reset peak value to 0 as otherwise we might get + // division by zero later when we calculate nHistoBinHeight + nHistoPeakVal = 1; - // TODO: Temporarily made quarter width - need to resample instead + // TODO: Temporarily made quarter width - need to resample instead - // Peak value - for(uint32_t i = 0; i < SUBSET_HISTO_BINS; i++) - { - nHistoCurVal = m_anHistoYFull[i * 4 + 0]; - nHistoCurVal += m_anHistoYFull[i * 4 + 1]; - nHistoCurVal += m_anHistoYFull[i * 4 + 2]; - nHistoCurVal += m_anHistoYFull[i * 4 + 3]; - nHistoPeakVal = (nHistoCurVal > nHistoPeakVal) ? nHistoCurVal : nHistoPeakVal; - } + // Peak value + for(uint32_t i = 0; i < SUBSET_HISTO_BINS; i++) + { + nHistoCurVal = m_anHistoYFull[i * 4 + 0]; + nHistoCurVal += m_anHistoYFull[i * 4 + 1]; + nHistoCurVal += m_anHistoYFull[i * 4 + 2]; + nHistoCurVal += m_anHistoYFull[i * 4 + 3]; + nHistoPeakVal = (nHistoCurVal > nHistoPeakVal) ? nHistoCurVal : nHistoPeakVal; + } - for(int32_t i = 0; i < SUBSET_HISTO_BINS; i++) + for(int32_t i = 0; i < SUBSET_HISTO_BINS; i++) + { + // Calculate bin's height (max HISTO_BIN_HEIGHT_MAX) + nHistoCurVal = m_anHistoYFull[i * 4 + 0]; + nHistoCurVal += m_anHistoYFull[i * 4 + 1]; + nHistoCurVal += m_anHistoYFull[i * 4 + 2]; + nHistoCurVal += m_anHistoYFull[i * 4 + 3]; + nHistoBinHeight = HISTO_BIN_HEIGHT_MAX * nHistoCurVal / nHistoPeakVal; + + for(int32_t y = 0; y < nHistoBinHeight; y++) { - // Calculate bin's height (max HISTO_BIN_HEIGHT_MAX) - nHistoCurVal = m_anHistoYFull[i * 4 + 0]; - nHistoCurVal += m_anHistoYFull[i * 4 + 1]; - nHistoCurVal += m_anHistoYFull[i * 4 + 2]; - nHistoCurVal += m_anHistoYFull[i * 4 + 3]; - nHistoBinHeight = HISTO_BIN_HEIGHT_MAX * nHistoCurVal / nHistoPeakVal; - - for(int32_t y = 0; y < nHistoBinHeight; y++) + // Store the RGB triplet + for(int32_t bin_width = 0; bin_width < HISTO_BIN_WIDTH; bin_width++) { - // Store the RGB triplet - for(int32_t bin_width = 0; bin_width < HISTO_BIN_WIDTH; bin_width++) - { - nHistoX = (i * HISTO_BIN_WIDTH) + bin_width; - nCoordY = (HISTO_BIN_HEIGHT_MAX - y) - 1; - m_pDibHistY->setPixelColor(nHistoX, nCoordY, QColor(0, 255, 255)); -// pDibHistoBits[(nHistoX * 4) + 3 + (nCoordY * nDibHistoRowBytes)] = 0; -// pDibHistoBits[(nHistoX * 4) + 2 + (nCoordY * nDibHistoRowBytes)] = 255; -// pDibHistoBits[(nHistoX * 4) + 1 + (nCoordY * nDibHistoRowBytes)] = 255; -// pDibHistoBits[(nHistoX * 4) + 0 + (nCoordY * nDibHistoRowBytes)] = 0; - } + nHistoX = (i * HISTO_BIN_WIDTH) + bin_width; + nCoordY = (HISTO_BIN_HEIGHT_MAX - y) - 1; + m_pDibHistY->setPixelColor(nHistoX, nCoordY, Qt::gray); } - } // i: 0..HISTO_BINS-1 - - m_bDibHistYReady = true; - } -// } // bDumpHistoY + } + } // i: 0..HISTO_BINS-1 + m_bDibHistYReady = true; + } } // Reset the decoder Scan Buff (at start of scan and @@ -4763,6 +4704,7 @@ void CimgDecode::DecodeRestartScanBuf(uint32_t nFilePos, bool bRestart) // ratio calculations. m_nScanBuffPtr_first = nFilePos; } + m_nScanBuffPtr_start = nFilePos; m_nScanBuffPtr_align = 0; // Start with byte alignment (0) m_anScanBuffPtr_pos[0] = 0; @@ -4824,9 +4766,7 @@ void CimgDecode::ConvertYCCtoRGBFastFloat(PixelCc & sPix) // Since the following seems to preserve the multiplies and subtractions // we could expand this out manually double fConstRed = 0.299f; - double fConstGreen = 0.587f; - double fConstBlue = 0.114f; // r = cr * 1.402 + y; @@ -4846,9 +4786,9 @@ void CimgDecode::ConvertYCCtoRGBFastFloat(PixelCc & sPix) // Limit // r/g/nPreclipB -> r/g/b //CapRgbRange(nMcuX,nMcuY,sPix); - sPix.nFinalR = (nValR < 0) ? 0 : (nValR > 255) ? 255 : (uint8_t) nValR; - sPix.nFinalG = (nValG < 0) ? 0 : (nValG > 255) ? 255 : (uint8_t) nValG; - sPix.nFinalB = (nValB < 0) ? 0 : (nValB > 255) ? 255 : (uint8_t) nValB; + sPix.nFinalR = (nValR < 0) ? 0 : (nValR > 255) ? 255 : static_cast(nValR); + sPix.nFinalG = (nValG < 0) ? 0 : (nValG > 255) ? 255 : static_cast(nValG); + sPix.nFinalB = (nValB < 0) ? 0 : (nValB > 255) ? 255 : static_cast(nValB); } // Color conversion from YCC to RGB @@ -5428,9 +5368,9 @@ void CimgDecode::CapRgbRange(uint32_t nMcuX, uint32_t nMcuY, PixelCc & sPix) } // Now convert to byteui - sPix.nFinalR = (uint8_t) nLimitR; - sPix.nFinalG = (uint8_t) nLimitG; - sPix.nFinalB = (uint8_t) nLimitB; + sPix.nFinalR = static_cast(nLimitR); + sPix.nFinalG = static_cast(nLimitG); + sPix.nFinalB = static_cast(nLimitB); } // Recalcs the full image based on the original YCC pixmap @@ -5507,8 +5447,6 @@ void CimgDecode::CalcChannelPreviewFull(QRect *, uint8_t *pTmp) uint32_t nMcuShiftInd = m_nPreviewShiftMcuY * (m_nImgSizeX / m_nMcuWidth) + m_nPreviewShiftMcuX; - m_pDibTemp = new QImage(m_nImgSizeX, m_nImgSizeY, QImage::Format_RGB32); - SetStatusText("Color conversion..."); if(m_bDetailVlc) @@ -5523,6 +5461,8 @@ void CimgDecode::CalcChannelPreviewFull(QRect *, uint8_t *pTmp) // Determine pixel count nNumPixels = (nRngY2 - nRngY1 + 1) * (nRngX2 - nRngX1 + 1); + m_pDibTemp = new QImage(m_nImgSizeX, m_nImgSizeY, QImage::Format_RGB32); + // Step through the image for(int32_t nPixY = nRngY1; nPixY < nRngY2; nPixY++) { @@ -5635,12 +5575,8 @@ void CimgDecode::CalcChannelPreviewFull(QRect *, uint8_t *pTmp) // Perform any channel filtering if enabled ChannelExtract(m_nPreviewMode, sPixSrc, sPixDst); - m_pDibTemp->setPixelColor(nPixX, nPixY, QColor(sPixDst.nFinalR, sPixDst.nFinalG, sPixDst.nFinalB)); // Assign the RGB pixel map -// pTmp[nPixByte + 3] = 0; -// pTmp[nPixByte + 2] = sPixDst.nFinalR; -// pTmp[nPixByte + 1] = sPixDst.nFinalG; -// pTmp[nPixByte + 0] = sPixDst.nFinalB; + m_pDibTemp->setPixelColor(nPixX, nPixY, QColor(sPixDst.nFinalR, sPixDst.nFinalG, sPixDst.nFinalB)); } // x } // y @@ -5782,7 +5718,7 @@ void CimgDecode::SetDetailVlc(bool bDetail, uint32_t nX, uint32_t nY, uint32_t n // - pMapCb = Pointer to pixel map for Cb component // - pMapCr = Pointer to pixel map for Cr component // -void CimgDecode::GetPixMapPtrs(short *&pMapY, short *&pMapCb, short *&pMapCr) +void CimgDecode::GetPixMapPtrs(int16_t *&pMapY, int16_t *&pMapCb, int16_t *&pMapCr) { Q_ASSERT(m_pPixValY); Q_ASSERT(m_pPixValCb); @@ -5811,14 +5747,14 @@ void CimgDecode::GetImageSize(uint32_t &nX, uint32_t &nY) // void CimgDecode::GetBitmapPtr(uint8_t *&pBitmap) { - uint8_t *pDibImgTmpBits = NULL; + uint8_t *pDibImgTmpBits = 0; //@@ pDibImgTmpBits = (uint8_t *) (m_pDibTemp.GetDIBBitArray()); // Ensure that the pointers are available! if(!pDibImgTmpBits) { - pBitmap = NULL; + pBitmap = 0; } else { @@ -5839,7 +5775,7 @@ void CimgDecode::GetBitmapPtr(uint8_t *&pBitmap) // void CimgDecode::CalcChannelPreview() { - uint8_t *pDibImgTmpBits = NULL; + uint8_t *pDibImgTmpBits = 0; //@@ pDibImgTmpBits = (uint8_t *) (m_pDibTemp.GetDIBBitArray()); @@ -5850,14 +5786,14 @@ void CimgDecode::CalcChannelPreview() // } // If we need to do a YCC shift, then do full recalc into tmp array - CalcChannelPreviewFull(NULL, pDibImgTmpBits); + CalcChannelPreviewFull(0, pDibImgTmpBits); // Since this was a complex mod, we don't mark this channel as // being "done", so we will need to recalculate any time we change // the channel display. // Force an update of the view to be sure - //m_pDoc->UpdateAllViews(NULL); + //m_pDoc->UpdateAllViews(0); return; } @@ -5871,14 +5807,13 @@ void CimgDecode::CalcChannelPreview() // - nByte = File offset (byte) // - nBit = File offset (bit) // -void CimgDecode::LookupFilePosPix(uint32_t nPixX, uint32_t nPixY, uint32_t &nByte, uint32_t &nBit) +void CimgDecode::LookupFilePosPix(QPoint p, uint32_t &nByte, uint32_t &nBit) { uint32_t nMcuX, nMcuY; - uint32_t nPacked; - nMcuX = nPixX / m_nMcuWidth; - nMcuY = nPixY / m_nMcuHeight; + nMcuX = p.x() / m_nMcuWidth; + nMcuY = p.y() / m_nMcuHeight; nPacked = m_pMcuFileMap[nMcuX + nMcuY * m_nMcuXMax]; UnpackFileOffset(nPacked, nByte, nBit); } @@ -5892,11 +5827,11 @@ void CimgDecode::LookupFilePosPix(uint32_t nPixX, uint32_t nPixY, uint32_t &nByt // - nByte = File offset (byte) // - nBit = File offset (bit) // -void CimgDecode::LookupFilePosMcu(uint32_t nMcuX, uint32_t nMcuY, uint32_t &nByte, uint32_t &nBit) +void CimgDecode::LookupFilePosMcu(QPoint p, uint32_t &nByte, uint32_t &nBit) { uint32_t nPacked; - nPacked = m_pMcuFileMap[nMcuX + nMcuY * m_nMcuXMax]; + nPacked = m_pMcuFileMap[p.x() + p.y() * m_nMcuXMax]; UnpackFileOffset(nPacked, nByte, nBit); } @@ -5910,13 +5845,14 @@ void CimgDecode::LookupFilePosMcu(uint32_t nMcuX, uint32_t nMcuY, uint32_t &nByt // - nCb = Cb channel value // - nCr = Cr channel value // -void CimgDecode::LookupBlkYCC(uint32_t nBlkX, uint32_t nBlkY, int32_t &nY, int32_t &nCb, int32_t &nCr) +void CimgDecode::LookupBlkYCC(QPoint p, int32_t &nY, int32_t &nCb, int32_t &nCr) { - nY = m_pBlkDcValY[nBlkX + nBlkY * m_nBlkXMax]; + nY = m_pBlkDcValY[p.x() + p.y() * m_nBlkXMax]; + if(m_nNumSosComps == NUM_CHAN_YCC) { - nCb = m_pBlkDcValCb[nBlkX + nBlkY * m_nBlkXMax]; - nCr = m_pBlkDcValCr[nBlkX + nBlkY * m_nBlkXMax]; + nCb = m_pBlkDcValCb[p.x() + p.y() * m_nBlkXMax]; + nCr = m_pBlkDcValCr[p.x() + p.y() * m_nBlkXMax]; } else { @@ -6051,7 +5987,7 @@ QPoint CimgDecode::GetMarkerBlk(uint32_t nInd) // - m_nMarkersBlkNum // - m_aptMarkersBlk[] // -void CimgDecode::SetMarkerBlk(uint32_t nBlkX, uint32_t nBlkY) +void CimgDecode::SetMarkerBlk(QPoint p) { if(m_nMarkersBlkNum == MAX_BLOCK_MARKERS) { @@ -6060,6 +5996,7 @@ void CimgDecode::SetMarkerBlk(uint32_t nBlkX, uint32_t nBlkY) { m_aptMarkersBlk[ind - 1] = m_aptMarkersBlk[ind]; } + // Reflect new reduced count m_nMarkersBlkNum--; } @@ -6067,39 +6004,31 @@ void CimgDecode::SetMarkerBlk(uint32_t nBlkX, uint32_t nBlkY) QString strTmp; int32_t nY, nCb, nCr; - - uint32_t nMcuX, nMcuY; - - uint32_t nCssX, nCssY; + int32_t nMcuX, nMcuY; + int32_t nCssX, nCssY; // Determine the YCC of the block // Then calculate the MCU coordinate and the block coordinate within the MCU - LookupBlkYCC(nBlkX, nBlkY, nY, nCb, nCr); - nMcuX = nBlkX / (m_nMcuWidth / BLK_SZ_X); - nMcuY = nBlkY / (m_nMcuHeight / BLK_SZ_Y); - nCssX = nBlkX % (m_nMcuWidth / BLK_SZ_X); - nCssY = nBlkY % (m_nMcuHeight / BLK_SZ_X); + LookupBlkYCC(p, nY, nCb, nCr); + nMcuX = p.x() / (m_nMcuWidth / BLK_SZ_X); + nMcuY = p.y() / (m_nMcuHeight / BLK_SZ_Y); + nCssX = p.x() % (m_nMcuWidth / BLK_SZ_X); + nCssY = p.y() % (m_nMcuHeight / BLK_SZ_X); - // Force text out to log -// bool bQuickModeSaved = m_pLog->GetQuickMode(); - -// m_pLog->SetQuickMode(false); strTmp = QString("Position Marked @ MCU=[%1,%2](%3,%4) Block=[%5,%6] YCC=[%7,%8,%9]") .arg(nMcuX, 4) .arg(nMcuY, 4) .arg(nCssX) .arg(nCssY) - .arg(nBlkX) - .arg(nBlkY) + .arg(p.x(), 4) + .arg(p.y(), 4) .arg(nY, 5) .arg(nCb, 5) .arg(nCr, 5); m_pLog->AddLine(strTmp); m_pLog->AddLine(""); -// m_pLog->SetQuickMode(bQuickModeSaved); - m_aptMarkersBlk[m_nMarkersBlkNum].setX(nBlkX); - m_aptMarkersBlk[m_nMarkersBlkNum].setY(nBlkY); + m_aptMarkersBlk[m_nMarkersBlkNum] = p; m_nMarkersBlkNum++; } @@ -6225,387 +6154,388 @@ void CimgDecode::SetPreviewZoom(bool bInc, bool bDec, bool bSet, uint32_t nVal) // OUTPUT: // - szNewScrollSize = New dimension used for SetScrollSizes() // -void CimgDecode::ViewOnDraw(QPainter * pDC, QRect rectClient, QPoint ptScrolledPos, QFont * pFont, QSize & szNewScrollSize) +void CimgDecode::ViewOnDraw(QPainter *, QRect, QPoint, QFont *, QSize &) +//void CimgDecode::ViewOnDraw(QPainter * pDC, QRect rectClient, QPoint ptScrolledPos, QFont * pFont, QSize & szNewScrollSize) { - m_nPageWidth = 600; - m_nPageHeight = 10; // Start with some margin - - QString strTmp; - QString strRender; - - int32_t nHeight; - - uint32_t nYPosImgTitle = 0; - uint32_t nYPosImg = 0; - uint32_t nYPosHistTitle = 0; - uint32_t nYPosHist = 0; - uint32_t nYPosHistYTitle = 0; - uint32_t nYPosHistY = 0; // Y position of Img & Histogram - - QRect rectTmp; +// m_nPageWidth = 600; +// m_nPageHeight = 10; // Start with some margin - qDebug() << "CimgDecode::ViewOnDraw Start"; +// QString strTmp; +// QString strRender; - // If we have displayed an image, make sure to allow for - // the additional space! +// int32_t nHeight; - bool bImgDrawn = false; +// uint32_t nYPosImgTitle = 0; +// uint32_t nYPosImg = 0; +// uint32_t nYPosHistTitle = 0; +// uint32_t nYPosHist = 0; +// uint32_t nYPosHistYTitle = 0; +// uint32_t nYPosHistY = 0; // Y position of Img & Histogram -// QBrush brGray(QColor(128, 128, 128)); -// QBrush brGrayLt1(QColor(210, 210, 210)); -// QBrush brGrayLt2(QColor(240, 240, 240)); -// QBrush brBlueLt(QColor(240, 240, 255)); +// QRect rectTmp; - QColor brGray = QColor(128, 128, 128); - QColor brGrayLt1 = QColor(210, 210, 210); - QColor brGrayLt2 = QColor(240, 240, 240); - QColor brBlueLt = QColor(240, 240, 255); +// qDebug() << "CimgDecode::ViewOnDraw Start"; - QPen penRed(Qt::red, 1, Qt::DotLine); +// // If we have displayed an image, make sure to allow for +// // the additional space! - if(m_bDibTempReady) - { - qDebug() << "CimgDecode::ViewOnDraw CP1"; - - nYPosImgTitle = m_nPageHeight; - m_nPageHeight += nTitleHeight; // Margin at top for title +// bool bImgDrawn = false; - m_rectImgReal = QRect(0, 0, static_cast(m_rectImgBase.right() * m_nZoom), static_cast(m_rectImgBase.bottom() * m_nZoom)); +//// QBrush brGray(QColor(128, 128, 128)); +//// QBrush brGrayLt1(QColor(210, 210, 210)); +//// QBrush brGrayLt2(QColor(240, 240, 240)); +//// QBrush brBlueLt(QColor(240, 240, 255)); - nYPosImg = m_nPageHeight; - m_nPageHeight += m_rectImgReal.height(); - m_nPageHeight += nBorderBottom; // Margin at bottom - bImgDrawn = true; +// QColor brGray = QColor(128, 128, 128); +// QColor brGrayLt1 = QColor(210, 210, 210); +// QColor brGrayLt2 = QColor(240, 240, 240); +// QColor brBlueLt = QColor(240, 240, 255); - m_rectImgReal.adjust(nBorderLeft, nYPosImg, 0, 0); +// QPen penRed(Qt::red, 1, Qt::DotLine); - // Now create the shadow of the main image -//!! rectTmp = m_rectImgReal; -//!! rectTmp.adjust(4, 4, 0, 0); -//!! pDC->fillRect(rectTmp, QBrush(brGrayLt1)); -//!! rectTmp.adjust(-1, -1, 1, 1); -//!! pDC->FrameRect(rectTmp, &brGrayLt2); - } - - if(m_bHistEn) - { - if(m_bDibHistRgbReady) - { - nYPosHistTitle = m_nPageHeight; - m_nPageHeight += nTitleHeight; // Margin at top for title - - m_rectHistReal = m_rectHistBase; - - nYPosHist = m_nPageHeight; - m_nPageHeight += m_rectHistReal.height(); - m_nPageHeight += nBorderBottom; // Margin at bottom - bImgDrawn = true; - - m_rectHistReal.adjust(nBorderLeft, nYPosHist, 0, 0); - - // Create the border - rectTmp = m_rectHistReal; - rectTmp.adjust(-1, -1, 1, 1); - pDC->setPen(QPen(brGray)); - pDC->drawRect(rectTmp); - } - - if(m_bDibHistYReady) - { - nYPosHistYTitle = m_nPageHeight; - m_nPageHeight += nTitleHeight; // Margin at top for title - - m_rectHistYReal = m_rectHistYBase; - - nYPosHistY = m_nPageHeight; - m_nPageHeight += m_rectHistYReal.height(); - m_nPageHeight += nBorderBottom; // Margin at bottom - bImgDrawn = true; +// if(m_bDibTempReady) +// { +// qDebug() << "CimgDecode::ViewOnDraw CP1"; - m_rectHistYReal.adjust(nBorderLeft, nYPosHistY, 0, 0); +// nYPosImgTitle = m_nPageHeight; +// m_nPageHeight += nTitleHeight; // Margin at top for title - // Create the border - rectTmp = m_rectHistYReal; - rectTmp.adjust(-1, -1, 1, 1); - pDC->setPen(QPen(brGray)); - pDC->drawRect(rectTmp); - } - } +// m_rectImgReal = QRect(0, 0, static_cast(m_rectImgBase.right() * m_nZoom), static_cast(m_rectImgBase.bottom() * m_nZoom)); - // Find a starting line based on scrolling - // and current client size +// nYPosImg = m_nPageHeight; +// m_nPageHeight += m_rectImgReal.height(); +// m_nPageHeight += nBorderBottom; // Margin at bottom +// bImgDrawn = true; - QRect rectClientScrolled = rectClient; +// m_rectImgReal.adjust(nBorderLeft, nYPosImg, 0, 0); - rectClientScrolled.adjust(ptScrolledPos.x(), ptScrolledPos.y(), 0, 0); +// // Now create the shadow of the main image +////!! rectTmp = m_rectImgReal; +////!! rectTmp.adjust(4, 4, 0, 0); +////!! pDC->fillRect(rectTmp, QBrush(brGrayLt1)); +////!! rectTmp.adjust(-1, -1, 1, 1); +////!! pDC->FrameRect(rectTmp, &brGrayLt2); +// } - // Change the font - QFont pOldFont; +// if(m_bHistEn) +// { +// if(m_bDibHistRgbReady) +// { +// nYPosHistTitle = m_nPageHeight; +// m_nPageHeight += nTitleHeight; // Margin at top for title - pOldFont = pDC->font(); +// m_rectHistReal = m_rectHistBase; - qDebug() << "Title 1"; +// nYPosHist = m_nPageHeight; +// m_nPageHeight += m_rectHistReal.height(); +// m_nPageHeight += nBorderBottom; // Margin at bottom +// bImgDrawn = true; - // Draw the bitmap if ready - if(m_bDibTempReady) - { - // Print label - qDebug() << "Title 2 m_bDibTempReady"; +// m_rectHistReal.adjust(nBorderLeft, nYPosHist, 0, 0); - if(!m_bPreviewIsJpeg) - { - // For all non-JPEG images, report with simple title - m_strTitle = "Image"; - } - else - { - qDebug() << "Title 3 m_bPreviewIsJpeg"; - m_strTitle = "Image ("; +// // Create the border +// rectTmp = m_rectHistReal; +// rectTmp.adjust(-1, -1, 1, 1); +// pDC->setPen(QPen(brGray)); +// pDC->drawRect(rectTmp); +// } - switch (m_nPreviewMode) - { - case PREVIEW_RGB: - m_strTitle += "RGB"; - break; +// if(m_bDibHistYReady) +// { +// nYPosHistYTitle = m_nPageHeight; +// m_nPageHeight += nTitleHeight; // Margin at top for title - case PREVIEW_YCC: - m_strTitle += "YCC"; - break; +// m_rectHistYReal = m_rectHistYBase; - case PREVIEW_R: - m_strTitle += "R"; - break; +// nYPosHistY = m_nPageHeight; +// m_nPageHeight += m_rectHistYReal.height(); +// m_nPageHeight += nBorderBottom; // Margin at bottom +// bImgDrawn = true; - case PREVIEW_G: - m_strTitle += "G"; - break; +// m_rectHistYReal.adjust(nBorderLeft, nYPosHistY, 0, 0); - case PREVIEW_B: - m_strTitle += "B"; - break; +// // Create the border +// rectTmp = m_rectHistYReal; +// rectTmp.adjust(-1, -1, 1, 1); +// pDC->setPen(QPen(brGray)); +// pDC->drawRect(rectTmp); +// } +// } - case PREVIEW_Y: - m_strTitle += "Y"; - break; +// // Find a starting line based on scrolling +// // and current client size - case PREVIEW_CB: - m_strTitle += "Cb"; - break; +// QRect rectClientScrolled = rectClient; - case PREVIEW_CR: - m_strTitle += "Cr"; - break; +// rectClientScrolled.adjust(ptScrolledPos.x(), ptScrolledPos.y(), 0, 0); - default: - m_strTitle += "???"; - break; - } +// // Change the font +// QFont pOldFont; - if(m_bDecodeScanAc) - { - m_strTitle += ", DC+AC)"; - } - else - { - m_strTitle += ", DC)"; - } - } +// pOldFont = pDC->font(); - switch (m_nZoomMode) - { - case PRV_ZOOM_12: - m_strTitle += " @ 12.5% (1/8)"; - break; +// qDebug() << "Title 1"; - case PRV_ZOOM_25: - m_strTitle += " @ 25% (1/4)"; - break; +// // Draw the bitmap if ready +// if(m_bDibTempReady) +// { +// // Print label +// qDebug() << "Title 2 m_bDibTempReady"; - case PRV_ZOOM_50: - m_strTitle += " @ 50% (1/2)"; - break; +// if(!m_bPreviewIsJpeg) +// { +// // For all non-JPEG images, report with simple title +// m_strTitle = "Image"; +// } +// else +// { +// qDebug() << "Title 3 m_bPreviewIsJpeg"; +// m_strTitle = "Image ("; + +// switch (m_nPreviewMode) +// { +// case PREVIEW_RGB: +// m_strTitle += "RGB"; +// break; + +// case PREVIEW_YCC: +// m_strTitle += "YCC"; +// break; + +// case PREVIEW_R: +// m_strTitle += "R"; +// break; + +// case PREVIEW_G: +// m_strTitle += "G"; +// break; + +// case PREVIEW_B: +// m_strTitle += "B"; +// break; + +// case PREVIEW_Y: +// m_strTitle += "Y"; +// break; + +// case PREVIEW_CB: +// m_strTitle += "Cb"; +// break; + +// case PREVIEW_CR: +// m_strTitle += "Cr"; +// break; + +// default: +// m_strTitle += "???"; +// break; +// } + +// if(m_bDecodeScanAc) +// { +// m_strTitle += ", DC+AC)"; +// } +// else +// { +// m_strTitle += ", DC)"; +// } +// } + +// switch (m_nZoomMode) +// { +// case PRV_ZOOM_12: +// m_strTitle += " @ 12.5% (1/8)"; +// break; - case PRV_ZOOM_100: - m_strTitle += " @ 100% (1:1)"; - break; +// case PRV_ZOOM_25: +// m_strTitle += " @ 25% (1/4)"; +// break; - case PRV_ZOOM_150: - m_strTitle += " @ 150% (3:2)"; - break; +// case PRV_ZOOM_50: +// m_strTitle += " @ 50% (1/2)"; +// break; - case PRV_ZOOM_200: - m_strTitle += " @ 200% (2:1)"; - break; +// case PRV_ZOOM_100: +// m_strTitle += " @ 100% (1:1)"; +// break; - case PRV_ZOOM_300: - m_strTitle += " @ 300% (3:1)"; - break; +// case PRV_ZOOM_150: +// m_strTitle += " @ 150% (3:2)"; +// break; - case PRV_ZOOM_400: - m_strTitle += " @ 400% (4:1)"; - break; +// case PRV_ZOOM_200: +// m_strTitle += " @ 200% (2:1)"; +// break; - case PRV_ZOOM_800: - m_strTitle += " @ 800% (8:1)"; - break; +// case PRV_ZOOM_300: +// m_strTitle += " @ 300% (3:1)"; +// break; - default: - m_strTitle += ""; - break; - } +// case PRV_ZOOM_400: +// m_strTitle += " @ 400% (4:1)"; +// break; - // Calculate the title width - QRect rectCalc = QRect(0, 0, 0, 0); +// case PRV_ZOOM_800: +// m_strTitle += " @ 800% (8:1)"; +// break; -//@@ nHeight = pDC->DrawText(m_strTitle,-1,&rectCalc,DT_CALQRect | DT_TOP | DT_NOPREFIX | DT_SINGLELINE); - int32_t nWidth = rectCalc.width() + 2 * nTitleIndent; +// default: +// m_strTitle += ""; +// break; +// } - // Determine the title area (could be larger than the image - // if the image zoom is < 100% or sized small) +// // Calculate the title width +// QRect rectCalc = QRect(0, 0, 0, 0); - // Draw title background - rectTmp = QRect(m_rectImgReal.left(), nYPosImgTitle, - qMax(m_rectImgReal.right(), m_rectImgReal.left() + nWidth), m_rectImgReal.top() - nTitleLowGap); - pDC->fillRect(rectTmp, brBlueLt); +////@@ nHeight = pDC->DrawText(m_strTitle,-1,&rectCalc,DT_CALQRect | DT_TOP | DT_NOPREFIX | DT_SINGLELINE); +// int32_t nWidth = rectCalc.width() + 2 * nTitleIndent; - // Draw the title - Qt::BGMode nBkMode = pDC->backgroundMode(); +// // Determine the title area (could be larger than the image +// // if the image zoom is < 100% or sized small) - pDC->setBackgroundMode(Qt::TransparentMode); - rectTmp.adjust(nTitleIndent, 0, 0, 0); -//@@ nHeight = pDC->DrawText(m_strTitle,-1,&rectTmp,DT_TOP | DT_NOPREFIX | DT_SINGLELINE); - pDC->setBackgroundMode(nBkMode); +// // Draw title background +// rectTmp = QRect(m_rectImgReal.left(), nYPosImgTitle, +// qMax(m_rectImgReal.right(), m_rectImgReal.left() + nWidth), m_rectImgReal.top() - nTitleLowGap); +// pDC->fillRect(rectTmp, brBlueLt); - // Draw image +// // Draw the title +// Qt::BGMode nBkMode = pDC->backgroundMode(); - // Assume that the temp image has already been generated! - // For speed purposes, we use m_pDibTemp only when we are - // in a mode other than RGB or YCC. In the RGB/YCC modes, - // we skip the CalcChannelPreview() step. +// pDC->setBackgroundMode(Qt::TransparentMode); +// rectTmp.adjust(nTitleIndent, 0, 0, 0); +////@@ nHeight = pDC->DrawText(m_strTitle,-1,&rectTmp,DT_TOP | DT_NOPREFIX | DT_SINGLELINE); +// pDC->setBackgroundMode(nBkMode); - // TODO: Improve redraw time by only redrawing the currently visible - // region. Requires a different CopyDIB routine with a subset region. - // Needs to take into account zoom setting (eg. intersection between - // rectClient and m_rectImgReal). +// // Draw image - // Use a common DIB instead of creating/swapping tmp / ycc and rgb. - // This way we can also have more flexibility in modifying RGB & YCC displays. - // Time calling CalcChannelPreview() seems small, so no real impact. +// // Assume that the temp image has already been generated! +// // For speed purposes, we use m_pDibTemp only when we are +// // in a mode other than RGB or YCC. In the RGB/YCC modes, +// // we skip the CalcChannelPreview() step. - // Image member usage: - // m_pDibTemp: +// // TODO: Improve redraw time by only redrawing the currently visible +// // region. Requires a different CopyDIB routine with a subset region. +// // Needs to take into account zoom setting (eg. intersection between +// // rectClient and m_rectImgReal). -//@@ m_pDibTemp.CopyDIB(pDC,m_rectImgReal.left,m_rectImgReal.top,m_nZoom); +// // Use a common DIB instead of creating/swapping tmp / ycc and rgb. +// // This way we can also have more flexibility in modifying RGB & YCC displays. +// // Time calling CalcChannelPreview() seems small, so no real impact. - // Now create overlays +// // Image member usage: +// // m_pDibTemp: - // Only draw overlay (eg. actual image boundary overlay) if the values - // have been set properly. Note that PSD decode currently sets these - // values to zero. - if((m_nDimX != 0) && (m_nDimY != 0)) - { - pDC->setPen(penRed); +////@@ m_pDibTemp.CopyDIB(pDC,m_rectImgReal.left,m_rectImgReal.top,m_nZoom); - // Draw boundary for end of valid data (inside partial MCU) - int32_t nXZoomed = static_cast(m_nDimX * m_nZoom); +// // Now create overlays - int32_t nYZoomed = static_cast(m_nDimY * m_nZoom); +// // Only draw overlay (eg. actual image boundary overlay) if the values +// // have been set properly. Note that PSD decode currently sets these +// // values to zero. +// if((m_nDimX != 0) && (m_nDimY != 0)) +// { +// pDC->setPen(penRed); - pDC->drawLine(m_rectImgReal.left() + nXZoomed, m_rectImgReal.top(), m_rectImgReal.left() + nXZoomed, m_rectImgReal.top() + nYZoomed); - pDC->drawLine(m_rectImgReal.left(), m_rectImgReal.top() + nYZoomed, m_rectImgReal.left() + nXZoomed, m_rectImgReal.top() + nYZoomed); -//!! pDC->setPen(pPen); - } +// // Draw boundary for end of valid data (inside partial MCU) +// int32_t nXZoomed = static_cast(m_nDimX * m_nZoom); - // Before we frame the region, let's draw any remaining overlays +// int32_t nYZoomed = static_cast(m_nDimY * m_nZoom); - // Only draw the MCU overlay if zoom is > 100%, otherwise we will have - // replaced entire image with the boundary lines! - if(m_bViewOverlaysMcuGrid && (m_nZoomMode >= PRV_ZOOM_25)) - { - ViewMcuOverlay(pDC); - } +// pDC->drawLine(m_rectImgReal.left() + nXZoomed, m_rectImgReal.top(), m_rectImgReal.left() + nXZoomed, m_rectImgReal.top() + nYZoomed); +// pDC->drawLine(m_rectImgReal.left(), m_rectImgReal.top() + nYZoomed, m_rectImgReal.left() + nXZoomed, m_rectImgReal.top() + nYZoomed); +////!! pDC->setPen(pPen); +// } - // Always draw the markers - ViewMcuMarkedOverlay(pDC); +// // Before we frame the region, let's draw any remaining overlays - // Final frame border - rectTmp = m_rectImgReal; - rectTmp.adjust(-1, -1, 1, 1); -//@@ pDC->setPen(brGray); - pDC->drawRect(rectTmp); +// // Only draw the MCU overlay if zoom is > 100%, otherwise we will have +// // replaced entire image with the boundary lines! +// if(m_bViewOverlaysMcuGrid && (m_nZoomMode >= PRV_ZOOM_25)) +// { +// ViewMcuOverlay(pDC); +// } - // Preserve the image placement (for other functions, such as click detect) - m_nPreviewPosX = m_rectImgReal.left(); - m_nPreviewPosY = m_rectImgReal.top(); - m_nPreviewSizeX = m_rectImgReal.width(); - m_nPreviewSizeY = m_rectImgReal.height(); +// // Always draw the markers +// ViewMcuMarkedOverlay(pDC); - // m_nPageWidth is already hardcoded above - Q_ASSERT(m_nPageWidth >= 0); - m_nPageWidth = qMax(static_cast(m_nPageWidth), m_nPreviewPosX + m_nPreviewSizeX); +// // Final frame border +// rectTmp = m_rectImgReal; +// rectTmp.adjust(-1, -1, 1, 1); +////@@ pDC->setPen(brGray); +// pDC->drawRect(rectTmp); - update(); - } +// // Preserve the image placement (for other functions, such as click detect) +// m_nPreviewPosX = m_rectImgReal.left(); +// m_nPreviewPosY = m_rectImgReal.top(); +// m_nPreviewSizeX = m_rectImgReal.width(); +// m_nPreviewSizeY = m_rectImgReal.height(); - if(m_bHistEn) - { - if(m_bDibHistRgbReady) - { - // Draw title background - rectTmp = QRect(m_rectHistReal.left(), nYPosHistTitle, m_rectHistReal.right(), m_rectHistReal.top() - nTitleLowGap); - pDC->fillRect(rectTmp, brBlueLt); - - // Draw the title - QRect boundingRect; - Qt::BGMode nBkMode = pDC->backgroundMode(); - pDC->setBackgroundMode(Qt::TransparentMode); - rectTmp.adjust(nTitleIndent, 0, 0, 0); - pDC->drawText(rectTmp, Qt::AlignLeft | Qt::AlignTop, "Histogram (RGB)", &boundingRect); - pDC->setBackgroundMode(nBkMode); - - // Draw image -//@@ m_pDibHistRgb.CopyDIB(pDC,m_rectHistReal.left,m_rectHistReal.top); - } +// // m_nPageWidth is already hardcoded above +// Q_ASSERT(m_nPageWidth >= 0); +// m_nPageWidth = qMax(static_cast(m_nPageWidth), m_nPreviewPosX + m_nPreviewSizeX); - if(m_bDibHistYReady) - { - // Draw title background - rectTmp = QRect(m_rectHistYReal.left(), nYPosHistYTitle, m_rectHistYReal.right(), m_rectHistYReal.top() - nTitleLowGap); - pDC->fillRect(rectTmp, brBlueLt); - - // Draw the title - Qt::BGMode nBkMode = pDC->backgroundMode(); - pDC->setBackgroundMode(Qt::TransparentMode); - rectTmp.adjust(nTitleIndent, 0, 0, 0); -//@@ nHeight = pDC->DrawText("Histogram (Y)",-1,&rectTmp,DT_TOP | DT_NOPREFIX | DT_SINGLELINE); - pDC->setBackgroundMode(nBkMode); - - // Draw image -//@@ m_pDibHistY.CopyDIB(pDC,m_rectHistYReal.left,m_rectHistYReal.top); - //m_pDibHistY.CopyDIB(pDC,nBorderLeft,nYPosHistY); - } +// update(); +// } - update(); - } +// if(m_bHistEn) +// { +// if(m_bDibHistRgbReady) +// { +// // Draw title background +// rectTmp = QRect(m_rectHistReal.left(), nYPosHistTitle, m_rectHistReal.right(), m_rectHistReal.top() - nTitleLowGap); +// pDC->fillRect(rectTmp, brBlueLt); + +// // Draw the title +// QRect boundingRect; +// Qt::BGMode nBkMode = pDC->backgroundMode(); +// pDC->setBackgroundMode(Qt::TransparentMode); +// rectTmp.adjust(nTitleIndent, 0, 0, 0); +// pDC->drawText(rectTmp, Qt::AlignLeft | Qt::AlignTop, "Histogram (RGB)", &boundingRect); +// pDC->setBackgroundMode(nBkMode); + +// // Draw image +////@@ m_pDibHistRgb.CopyDIB(pDC,m_rectHistReal.left,m_rectHistReal.top); +// } + +// if(m_bDibHistYReady) +// { +// // Draw title background +// rectTmp = QRect(m_rectHistYReal.left(), nYPosHistYTitle, m_rectHistYReal.right(), m_rectHistYReal.top() - nTitleLowGap); +// pDC->fillRect(rectTmp, brBlueLt); + +// // Draw the title +// Qt::BGMode nBkMode = pDC->backgroundMode(); +// pDC->setBackgroundMode(Qt::TransparentMode); +// rectTmp.adjust(nTitleIndent, 0, 0, 0); +////@@ nHeight = pDC->DrawText("Histogram (Y)",-1,&rectTmp,DT_TOP | DT_NOPREFIX | DT_SINGLELINE); +// pDC->setBackgroundMode(nBkMode); + +// // Draw image +////@@ m_pDibHistY.CopyDIB(pDC,m_rectHistYReal.left,m_rectHistYReal.top); +// //m_pDibHistY.CopyDIB(pDC,nBorderLeft,nYPosHistY); +// } + +// update(); +// } - // If no image has been drawn, indicate to user why! - if(!bImgDrawn) - { - //ScrollRect.top = m_nPageHeight; // FIXME:? +// // If no image has been drawn, indicate to user why! +// if(!bImgDrawn) +// { +// //ScrollRect.top = m_nPageHeight; // FIXME:? - // Print label - //nHeight = pDC->DrawText("Image Decode disabled. Enable with [Options->Decode Scan Image]", -1,&ScrollRect, - // DT_TOP | DT_NOPREFIX | DT_SINGLELINE); +// // Print label +// //nHeight = pDC->DrawText("Image Decode disabled. Enable with [Options->Decode Scan Image]", -1,&ScrollRect, +// // DT_TOP | DT_NOPREFIX | DT_SINGLELINE); - } +// } - // Restore the original font - pDC->setFont(pOldFont); +// // Restore the original font +// pDC->setFont(pOldFont); - // Set scroll bars accordingly. We use the page dimensions here. - QSize sizeTotal(m_nPageWidth + nBorderLeft, m_nPageHeight); +// // Set scroll bars accordingly. We use the page dimensions here. +// QSize sizeTotal(m_nPageWidth + nBorderLeft, m_nPageHeight); - szNewScrollSize = sizeTotal; +// szNewScrollSize = sizeTotal; } // Draw an overlay that shows the MCU grid diff --git a/source/ImgDecode.h b/source/ImgDecode.h index 689efef..7c074bb 100644 --- a/source/ImgDecode.h +++ b/source/ImgDecode.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -37,19 +37,18 @@ #include #include -#include "SnoopConfig.h" #include "snoop.h" #include "DocLog.h" #include "WindowBuf.h" -//#include "afxwin.h" -//#include "Dib.h" #include #include "General.h" +class CSnoopConfig; + // Color conversion clipping (YCC) reporting #define YCC_CLIP_REPORT_ERR true // Are YCC clips an error? #define YCC_CLIP_REPORT_MAX 10 // Number of same error to report @@ -160,9 +159,9 @@ static const uint32_t JFIF_EOI = 0xD9; #define CC_CLIP_YCC_MAX 255 // Image histogram definitions -static const int32_t HISTO_BINS = 128; +static const int32_t HISTO_BINS = 255; // 128; static const int32_t HISTO_BIN_WIDTH = 1; -static const int32_t HISTO_BIN_HEIGHT_MAX = 30; +static const int32_t HISTO_BIN_HEIGHT_MAX = 60; // Histogram of Y component (-1024..+1023) = 2048 bins static const int32_t FULL_HISTO_BINS = 2048; @@ -296,12 +295,12 @@ typedef struct uint32_t nCount; } PixelCcHisto; -class CimgDecode : public QWidget +class CimgDecode : public QObject { Q_OBJECT public: - CimgDecode(CDocLog * pLog, CwindowBuf * pWBuf, QWidget *parent); + CimgDecode(CDocLog * pLog, CwindowBuf * pWBuf, CSnoopConfig *pAppConfig, QObject *_parent); ~CimgDecode(); void Reset(); // Called during start of SOS decode @@ -314,6 +313,8 @@ class CimgDecode : public QWidget void ReportHistogramY(); void ReportColorStats(); + bool isYHistogramReady() {return m_bDibHistYReady; } + bool isRgbHistogramReady() {return m_bDibHistRgbReady; } bool IsPreviewReady(); // Config @@ -333,7 +334,7 @@ class CimgDecode : public QWidget void SetPrecision(uint32_t nPrecision); // Modes -- accessed from Doc - void SetPreviewMode(uint32_t nMode); +// void SetPreviewMode(uint32_t nMode); uint32_t GetPreviewMode(); void SetPreviewYccOffset(uint32_t nMcuX, uint32_t nMcuY, int32_t nY, int32_t nCb, int32_t nCr); void GetPreviewYccOffset(uint32_t & nMcuX, uint32_t & nMcuY, int32_t &nY, int32_t &nCb, int32_t &nCr); @@ -346,11 +347,11 @@ class CimgDecode : public QWidget void SetPreviewOverlayMcuGridToggle(); // Utilities - void LookupFilePosPix(uint32_t nPixX, uint32_t nPixY, uint32_t & nByte, uint32_t & nBit); - void LookupFilePosMcu(uint32_t nMcuX, uint32_t nMcuY, uint32_t & nByte, uint32_t & nBit); - void LookupBlkYCC(uint32_t nBlkX, uint32_t nBlkY, int32_t &nY, int32_t &nCb, int32_t &nCr); + void LookupFilePosPix(QPoint p, uint32_t &nByte, uint32_t &nBit); + void LookupFilePosMcu(QPoint p, uint32_t &nByte, uint32_t &nBit); + void LookupBlkYCC(QPoint p, int32_t &nY, int32_t &nCb, int32_t &nCr); - void SetMarkerBlk(uint32_t nBlkX, uint32_t nBlkY); + void SetMarkerBlk(QPoint p); uint32_t GetMarkerCount(); QPoint GetMarkerBlk(uint32_t nInd); @@ -389,6 +390,9 @@ class CimgDecode : public QWidget void SetStatusFilePosText(QString strText); QString GetStatusFilePosText(); + QImage *yHistogram() { return m_pDibHistY; } + QImage *rgbHistogram() { return m_pDibHistRgb; } + void ReportDctMatrix(); void ReportDctYccMatrix(); void ReportVlc(uint32_t nVlcPos, uint32_t nVlcAlign, @@ -406,11 +410,12 @@ class CimgDecode : public QWidget uint16_t m_anDqtCoeffZz[MAX_DQT_DEST_ID][MAX_DQT_COEFF]; // Original zigzag ordering int32_t m_anDqtTblSel[MAX_DQT_COMP]; // DQT table selector for image component in frame -protected: - void paintEvent(QPaintEvent *event) override; +public slots: + void setPreviewMode(QAction *action); signals: void updateStatus(QString statusMsg, int); + void updateImage(); private: CimgDecode &operator = (const CimgDecode&); @@ -453,8 +458,8 @@ class CimgDecode : public QWidget void DecodeIdctSet(uint32_t nTbl, uint32_t num_coeffs, uint32_t zrl, int16_t val); void DecodeIdctCalcFloat(uint32_t nCoefMax); void DecodeIdctCalcFixedpt(); - void ClrFullRes(uint32_t nWidth, uint32_t nHeight); - void SetFullRes(uint32_t nMcuX, uint32_t nMcuY, uint32_t nComp, uint32_t nCssXInd, uint32_t nCssYInd, int16_t nDcOffset); + void ClrFullRes(int32_t nWidth, int32_t nHeight); + void SetFullRes(int32_t nMcuX, int32_t nMcuY, int32_t nComp, uint32_t nCssXInd, uint32_t nCssYInd, int16_t nDcOffset); void ChannelExtract(uint32_t nMode, PixelCc & sSrc, PixelCc & sDst); void CalcChannelPreviewFull(QRect * pRectView, uint8_t * pTmp); @@ -464,17 +469,19 @@ class CimgDecode : public QWidget // Member variables // ------------------------------------------------------------- -// CSnoopConfig * m_pAppConfig; // Pointer to application config + CDocLog *m_pLog; + CwindowBuf *m_pWBuf; + CSnoopConfig *m_pAppConfig; // Pointer to application config QMessageBox msgBox; uint32_t *m_pMcuFileMap; - uint32_t m_nMcuWidth; // Width (pix) of MCU (e.g. 8,16) - uint32_t m_nMcuHeight; // Height (pix) of MCU (e.g. 8,16) - uint32_t m_nMcuXMax; // Number of MCUs across - uint32_t m_nMcuYMax; // Number of MCUs vertically - uint32_t m_nBlkXMax; // Number of 8x8 blocks across - uint32_t m_nBlkYMax; // Number of 8x8 blocks vertically + int32_t m_nMcuWidth; // Width (pix) of MCU (e.g. 8,16) + int32_t m_nMcuHeight; // Height (pix) of MCU (e.g. 8,16) + int32_t m_nMcuXMax; // Number of MCUs across + int32_t m_nMcuYMax; // Number of MCUs vertically + int32_t m_nBlkXMax; // Number of 8x8 blocks across + int32_t m_nBlkYMax; // Number of 8x8 blocks vertically // Fill these with the cumulative values so that we can do // a YCC to RGB conversion (for level shift previews, etc.) @@ -505,10 +512,10 @@ class CimgDecode : public QWidget QString m_strTitle; // Image title - uint32_t m_nImgSizeXPartMcu; // Image size with possible partial MCU - uint32_t m_nImgSizeYPartMcu; - uint32_t m_nImgSizeX; // Image size rounding up to full MCU - uint32_t m_nImgSizeY; + int32_t m_nImgSizeXPartMcu; // Image size with possible partial MCU + int32_t m_nImgSizeYPartMcu; + int32_t m_nImgSizeX; // Image size rounding up to full MCU + int32_t m_nImgSizeY; // Image rects QRect m_rectImgBase; // Image with no offset, no scaling @@ -544,39 +551,35 @@ class CimgDecode : public QWidget uint32_t m_nZoomMode; double m_nZoom; - // Logger connection - CDocLog *m_pLog; - CwindowBuf *m_pWBuf; - // Image details (from JFIF decode) set by SetImageDetails() bool m_bImgDetailsSet; // Have image details been set yet (from SOS) - uint32_t m_nDimX; // Image Dimension in X - uint32_t m_nDimY; // Image Dimension in Y - uint32_t m_nNumSosComps; // Number of Image Components (DHT?) - uint32_t m_nNumSofComps; // Number of Image Components (DQT?) - uint32_t m_nPrecision; // 8-bit or 12-bit (defined in JFIF_SOF1) - uint32_t m_anSofSampFactH[MAX_SOF_COMP_NF]; // Sampling factor per component ID in frame from SOF - uint32_t m_anSofSampFactV[MAX_SOF_COMP_NF]; // Sampling factor per component ID in frame from SOF - uint32_t m_nSosSampFactHMax; // Maximum sampling factor for scan - uint32_t m_nSosSampFactVMax; // Maximum sampling factor for scan - uint32_t m_nSosSampFactHMin; // Minimum sampling factor for scan - uint32_t m_nSosSampFactVMin; // Minimum sampling factor for scan - uint32_t m_anSampPerMcuH[MAX_SOF_COMP_NF]; // Number of samples of component ID per MCU - uint32_t m_anSampPerMcuV[MAX_SOF_COMP_NF]; // Number of samples of component ID per MCU - uint32_t m_anExpandBitsMcuH[MAX_SOF_COMP_NF]; // Number of bits to replicate in SetFullRes() due to sampling factor - uint32_t m_anExpandBitsMcuV[MAX_SOF_COMP_NF]; // Number of bits to replicate in SetFullRes() due to sampling factor + int32_t m_nDimX; // Image Dimension in X + int32_t m_nDimY; // Image Dimension in Y + int32_t m_nNumSosComps; // Number of Image Components (DHT?) + int32_t m_nNumSofComps; // Number of Image Components (DQT?) + int32_t m_nPrecision; // 8-bit or 12-bit (defined in JFIF_SOF1) + int32_t m_anSofSampFactH[MAX_SOF_COMP_NF]; // Sampling factor per component ID in frame from SOF + int32_t m_anSofSampFactV[MAX_SOF_COMP_NF]; // Sampling factor per component ID in frame from SOF + int32_t m_nSosSampFactHMax; // Maximum sampling factor for scan + int32_t m_nSosSampFactVMax; // Maximum sampling factor for scan + int32_t m_nSosSampFactHMin; // Minimum sampling factor for scan + int32_t m_nSosSampFactVMin; // Minimum sampling factor for scan + int32_t m_anSampPerMcuH[MAX_SOF_COMP_NF]; // Number of samples of component ID per MCU + int32_t m_anSampPerMcuV[MAX_SOF_COMP_NF]; // Number of samples of component ID per MCU + int32_t m_anExpandBitsMcuH[MAX_SOF_COMP_NF]; // Number of bits to replicate in SetFullRes() due to sampling factor + int32_t m_anExpandBitsMcuV[MAX_SOF_COMP_NF]; // Number of bits to replicate in SetFullRes() due to sampling factor bool m_bRestartEn; // Did decoder see DRI? - uint32_t m_nRestartInterval; // ... if so, what is the MCU interval - uint32_t m_nRestartRead; // Number RST read during m_nScanBuff - uint32_t m_nPreviewMode; // Preview mode + int32_t m_nRestartInterval; // ... if so, what is the MCU interval + int32_t m_nRestartRead; // Number RST read during m_nScanBuff + int32_t m_nPreviewMode; // Preview mode // Test shifting of YCC for ChannelPreview() int32_t m_nPreviewShiftY; int32_t m_nPreviewShiftCb; int32_t m_nPreviewShiftCr; - uint32_t m_nPreviewShiftMcuX; // Start co-ords of shift - uint32_t m_nPreviewShiftMcuY; + int32_t m_nPreviewShiftMcuX; // Start co-ords of shift + int32_t m_nPreviewShiftMcuY; uint32_t m_nPreviewInsMcuX; // Test blank MCU insert uint32_t m_nPreviewInsMcuY; diff --git a/source/JPEGsnoop.cpp b/source/JPEGsnoop.cpp deleted file mode 100644 index 515f77f..0000000 --- a/source/JPEGsnoop.cpp +++ /dev/null @@ -1,1729 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// JPEGsnoop is written in Microsoft Visual C++ using MFC - -// JPEGsnoop.cpp : Defines the class behaviors for the application. -// - -#include "stdafx.h" -#include "MainFrm.h" - -#include "JPEGsnoop.h" -#include "JPEGsnoopDoc.h" -#include "JPEGsnoopView.h" - -#include "snoop.h" - -#include "SnoopConfig.h" - -#include "AboutDlg.h" -#include "DbSubmitDlg.h" -#include "SettingsDlg.h" -#include "DbManageDlg.h" -#include "TermsDlg.h" -#include "UpdateAvailDlg.h" -#include "ModelessDlg.h" -#include "NoteDlg.h" -#include "HyperlinkStatic.h" - -#include "afxinet.h" // For internet -#include "io.h" // For _open_osfhandle - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - -// Global log file -CDocLog* glb_pDocLog = NULL; - -// CJPEGsnoopApp - -BEGIN_MESSAGE_MAP(CJPEGsnoopApp, CWinApp) - ON_COMMAND(ID_APP_ABOUT, OnAppAbout) - // Standard file based document commands - - ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) - //CAL! ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) - //ON_COMMAND(ID_FILE_NEW, MyOnFileNew) - ON_COMMAND(ID_FILE_OPEN, MyOnFileOpen) - - // Standard print setup command - ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) - - ON_COMMAND(ID_OPTIONS_DHTEXPAND, OnOptionsDhtexpand) - ON_COMMAND(ID_OPTIONS_MAKERNOTES, OnOptionsMakernotes) - ON_COMMAND(ID_OPTIONS_CONFIGURATION, OnOptionsConfiguration) - ON_COMMAND(ID_OPTIONS_CHECKFORUPDATES, OnOptionsCheckforupdates) - ON_COMMAND(ID_OPTIONS_SIGNATURESEARCH, OnOptionsSignaturesearch) - ON_COMMAND(ID_TOOLS_MANAGELOCALDB, OnToolsManagelocaldb) - ON_COMMAND(ID_SCANSEGMENT_DECODEIMAGE, OnScansegmentDecodeimage) - ON_COMMAND(ID_SCANSEGMENT_FULLIDCT, OnScansegmentFullidct) - ON_COMMAND(ID_SCANSEGMENT_HISTOGRAMY, OnScansegmentHistogramy) - ON_COMMAND(ID_SCANSEGMENT_DUMP, OnScansegmentDump) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_DHTEXPAND, OnUpdateOptionsDhtexpand) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_MAKERNOTES, OnUpdateOptionsMakernotes) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_SIGNATURESEARCH, OnUpdateOptionsSignaturesearch) - ON_UPDATE_COMMAND_UI(ID_SCANSEGMENT_DECODEIMAGE, OnUpdateScansegmentDecodeimage) - ON_UPDATE_COMMAND_UI(ID_SCANSEGMENT_FULLIDCT, OnUpdateScansegmentFullidct) - ON_UPDATE_COMMAND_UI(ID_SCANSEGMENT_HISTOGRAMY, OnUpdateScansegmentHistogramy) - ON_UPDATE_COMMAND_UI(ID_SCANSEGMENT_DUMP, OnUpdateScansegmentDump) - ON_COMMAND(ID_SCANSEGMENT_NOIDCT, OnScansegmentNoidct) - ON_UPDATE_COMMAND_UI(ID_SCANSEGMENT_NOIDCT, OnUpdateScansegmentNoidct) - ON_COMMAND(ID_SCANSEGMENT_HISTOGRAM, OnScansegmentHistogram) - ON_UPDATE_COMMAND_UI(ID_SCANSEGMENT_HISTOGRAM, OnUpdateScansegmentHistogram) - ON_COMMAND(ID_OPTIONS_HIDEUKNOWNEXIFTAGS, OnOptionsHideuknownexiftags) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_HIDEUKNOWNEXIFTAGS, OnUpdateOptionsHideuknownexiftags) - ON_COMMAND(ID_FILE_BATCHPROCESS, OnFileBatchprocess) - ON_COMMAND(ID_OPTIONS_RELAXEDPARSING, &CJPEGsnoopApp::OnOptionsRelaxedparsing) - ON_UPDATE_COMMAND_UI(ID_OPTIONS_RELAXEDPARSING, &CJPEGsnoopApp::OnUpdateOptionsRelaxedparsing) -END_MESSAGE_MAP() - -// FIXME: -// Would like to change string table JPEGsnoop.rc to add: -// AFX_IDS_OPENFILE 0xF000 (61440) = _T("Open Image / Movie") for Open Dialog -// but linker complains error RC2151 "cannot reuse string constants" - - -// ====================================== -// Command Line option support -// ====================================== - -// Display the command-line help/options summary -void CJPEGsnoopApp::CmdLineHelp() -{ - CString strMsg = _T(""); - CString strLine = _T(""); - strMsg += _T("\n"); - strLine.Format(_T("JPEGsnoop v%s\n"),VERSION_STR); - strMsg += strLine; - strMsg += _T("\n"); - strMsg += _T("JPEGsnoop.exe \n"); - strMsg += _T("\n"); - strMsg += _T(" One of the following input parameters:\n"); - strMsg += _T(" -help : Show command summary\n"); - strMsg += _T(" -i : Defines input JPEG filename\n"); - strMsg += _T(" -b

: Batch process directory\n"); - strMsg += _T(" -br : Batch process directory (recursive)\n"); - strMsg += _T(" Zero or more of the following input parameters:\n"); - strMsg += _T(" -o : Defines output log filename\n"); - strMsg += _T(" -ext_all : Extract all from file\n"); - strMsg += _T(" -ext_dht_avi : Force insert DHT for AVI (-ext_all mode)\n"); - strMsg += _T(" -scan : Enables Scan Segment decode\n"); - strMsg += _T(" -maker : Enables Makernote decode\n"); - strMsg += _T(" -scandump : Enables Scan Segment dumping\n"); - strMsg += _T(" -histo_y : Enables luminance histogram\n"); - strMsg += _T(" -dhtexp : Enables DHT table expansion into huffman bitstrings\n"); - strMsg += _T(" -exif_hide_unk : Disables decoding of unknown makernotes\n"); - strMsg += _T(" -offset_start : Decode at start of file\n"); - strMsg += _T(" -offset_srch1 : Decode at 1st SOI found in file\n"); - strMsg += _T(" -offset_srch2 : Decode at 1st SOI found after start of file\n"); - strMsg += _T(" -offset_pos <###> : Decode from byte ### (decimal) in file\n"); - strMsg += _T(" -done : Indicate when operations complete\n"); - strMsg += _T("\n"); - CmdLineMessage(strMsg); -} - -// Command-line parser class -class CMyCommandParser : public CCommandLineInfo -{ - typedef enum {cla_idle,cla_input,cla_output,cla_err,cla_batchdir,cla_offset_pos} cla_e; - int index; - cla_e next_arg; - CSnoopConfig* m_pCfg; - CString strTmp; - -public: - CMyCommandParser(CSnoopConfig* pCfg) { - m_pCfg = pCfg; - CCommandLineInfo(); - index=0; // initializes an index to allow make a positional analysis - next_arg = cla_idle; - }; - - virtual void ParseParam(LPCTSTR pszParam, BOOL bFlag, BOOL bLast) { - bLast; // Unreferenced param - - CString msg; - - // GUI mode decision - // - Default to GUI mode - // - If any command-line parameter identified, change to non-GUI mode - // - Drag & drop will remain GUI mode - bool bCmdLineDetected = false; - - switch(next_arg) { - - case cla_idle: - if (bFlag && !_tcscmp(pszParam,_T("i"))) { - next_arg = cla_input; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("o"))) { - next_arg = cla_output; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("b"))) { - next_arg = cla_batchdir; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("br"))) { - m_pCfg->bCmdLineBatchRec = true; - next_arg = cla_batchdir; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("help"))) { - m_nShellCommand = FileNothing; - m_pCfg->bCmdLineHelp = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("h"))) { - m_nShellCommand = FileNothing; - m_pCfg->bCmdLineHelp = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("?"))) { - m_nShellCommand = FileNothing; - m_pCfg->bCmdLineHelp = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("offset_start"))) { - m_pCfg->eCmdLineOffset = DEC_OFFSET_START; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("offset_srch1"))) { - m_pCfg->eCmdLineOffset = DEC_OFFSET_SRCH1; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("offset_srch2"))) { - m_pCfg->eCmdLineOffset = DEC_OFFSET_SRCH2; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("offset_pos"))) { - m_pCfg->eCmdLineOffset = DEC_OFFSET_POS; - m_pCfg->nCmdLineOffsetPos = 0; - next_arg = cla_offset_pos; - bCmdLineDetected = true; - } - - else if (bFlag && !_tcscmp(pszParam,_T("ext_all"))) { - m_pCfg->bCmdLineExtractEn = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("ext_dht_avi"))) { - m_pCfg->bCmdLineExtractDhtAvi = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("scan"))) { - m_pCfg->bDecodeScanImg = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("maker"))) { - m_pCfg->bDecodeMaker = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("scandump"))) { - m_pCfg->bOutputScanDump = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("histo_y"))) { - m_pCfg->bHistoEn = true; - m_pCfg->bDumpHistoY = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("dhtexp"))) { - m_pCfg->bOutputDHTexpand = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("exif_hide_unk"))) { - m_pCfg->bExifHideUnknown = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag && !_tcscmp(pszParam,_T("done"))) { - m_pCfg->bCmdLineDoneMsg = true; - next_arg = cla_idle; - bCmdLineDetected = true; - } - else if (bFlag) { - // Unknown flag - strTmp.Format(_T("ERROR: Unknown command-line flag [-%s]"),pszParam); - // Don't disable dialog in non-interactive mode as this could be an important error - - // Show dialog box with info - AfxMessageBox(strTmp); - - // And also report command line options - next_arg = cla_err; - m_nShellCommand = FileNothing; - m_pCfg->bCmdLineHelp = true; - bCmdLineDetected = true; - } - else { - // Not a flag, so assume it is a drag & drop file open - // Note that drag & drop doesn't appear to suffer from '-' prefix issues (see below) - m_pCfg->bCmdLineOpenEn = true; - m_pCfg->strCmdLineOpenFname = pszParam; - - // This will run in default mode which is GUI mode - m_nShellCommand = FileOpen; - m_strFileName = pszParam; - } - - break; - - case cla_input: - msg = _T("Input=["); - msg += pszParam; - msg += _T("]"); - - // Handle case where filename was preceded by dash ('-') - // Per CCommandLineInfo::ParseParam http://msdn.microsoft.com/en-us/library/bss6bxss.aspx - // If first char is '-' or '/' then it is treated as flag and - // the character is removed. - // - // Since we are in "cla_input" state due to preceding "-i" flag, - // we should not have bFlag set here. If so, we need to re-instate the - // character. - // - // NOTE: We actually roll-back the pszParam pointer as CWinApp::ParseCommandLine() - // increments the pointer when setting bFlag=true. - // Reference: C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\src\mfc\appcore.cpp - // - if (bFlag) { - // Fixing hyphen filename prefix by rolling back the pointer - pszParam--; - } - - m_pCfg->bCmdLineOpenEn = true; - m_pCfg->strCmdLineOpenFname = pszParam; - - m_nShellCommand = FileNothing; - m_strFileName = _T(""); // Unused - - next_arg = cla_idle; - break; - - - // Batch directory processing - case cla_batchdir: - msg = _T("BatchDir=["); - msg += pszParam; - msg += _T("]"); - - if (bFlag) { - // Fixing hyphen filename prefix by rolling back the pointer - pszParam--; - } - - // Store the batch directory name - m_pCfg->bCmdLineBatchEn = true; - m_pCfg->strCmdLineBatchDirName = pszParam; - - // Set the ShellCommand to FileNothing so that the InitProcess() - // call doesn't take any action. Instead, we can perform the - // batch processing ourself. - m_nShellCommand = FileNothing; - m_strFileName = _T(""); // Unused - - next_arg = cla_idle; - break; - - case cla_output: - msg = _T("Output=["); - msg += pszParam; - msg += _T("]"); - if (bFlag) { - // Fixing hyphen filename prefix by rolling back the pointer - pszParam--; - } - m_pCfg->bCmdLineOutputEn = true; - m_pCfg->strCmdLineOutputFname = pszParam; - next_arg = cla_idle; - break; - - case cla_offset_pos: - msg = _T("OffsetPos=["); - msg += pszParam; - msg += _T("]"); - m_pCfg->nCmdLineOffsetPos = _ttoi(pszParam); - next_arg = cla_idle; - break; - - case cla_err: - default: - break; - } - - // Now update to non-GUI mode if command-line param detected - if (bCmdLineDetected) { - m_pCfg->bGuiMode = false; - m_pCfg->bInteractive = false; - } - - }; -}; - - - -// CJPEGsnoopApp construction - -// Constructor -CJPEGsnoopApp::CJPEGsnoopApp() -{ - - // Reset fatal error flag - m_bFatal = false; - - // Application-level config options - m_pAppConfig = new CSnoopConfig(); - if (!m_pAppConfig) { - AfxMessageBox(_T("ERROR: Couldn't allocate memory for SnoopConfig")); - m_bFatal = true; - } - - if (DEBUG_EN) m_pAppConfig->DebugLogCreate(); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::CJPEGsnoopApp() Checkpoint 1")); - glb_pDocLog = new CDocLog(); - if (!glb_pDocLog) { - AfxMessageBox(_T("ERROR: Not enough memory for Log")); - exit(1); - } - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::CJPEGsnoopApp() Checkpoint 2")); - m_pDbSigs = new CDbSigs(); - if (!m_pDbSigs) { - AfxMessageBox(_T("ERROR: Couldn't allocate memory for DbSigs")); - m_bFatal = true; - } - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::CJPEGsnoopApp() Checkpoint 3")); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::CJPEGsnoopApp() End")); -} - -// Destructor -CJPEGsnoopApp::~CJPEGsnoopApp() -{ - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::~CJPEGsnoopApp() Start")); - - // Save and then Delete - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::~CJPEGsnoopApp() About to destroy Config")); - if (m_pAppConfig != NULL) - { - m_pAppConfig->RegistryStore(); - - delete m_pAppConfig; - m_pAppConfig = NULL; - } - - if (glb_pDocLog != NULL) { - delete glb_pDocLog; - glb_pDocLog = NULL; - } - - if (m_pDbSigs != NULL) - { - delete m_pDbSigs; - m_pDbSigs = NULL; - } - - -} - -// The one and only CJPEGsnoopApp object - -CJPEGsnoopApp theApp; - -// CJPEGsnoopApp initialization - -// Override localization virtual function to avoid potential for -// satellite DLL hijacking -HINSTANCE CJPEGsnoopApp::LoadAppLangResourceDLL() -{ - return NULL; -} - -BOOL CJPEGsnoopApp::InitInstance() -{ - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Start")); - - // InitCommonControls() is required on Windows XP if an application - // manifest specifies use of ComCtl32.dll version 6 or later to enable - // visual styles. Otherwise, any window creation will fail. - InitCommonControls(); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 1")); - CWinApp::InitInstance(); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 2")); - - - // Initialize OLE libraries - if (!AfxOleInit()) - { - AfxMessageBox(IDP_OLE_INIT_FAILED); - return FALSE; - } - AfxEnableControlContainer(); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 3")); - - // Check to see if we had any fatal errors yet (e.g. mem alloc) - if (m_bFatal) { - return FALSE; - } - - - // Standard initialization - // If you are not using these features and wish to reduce the size - // of your final executable, you should remove from the following - // the specific initialization routines you do not need - // Change the registry key under which our settings are stored - - // This call actually concatenates CWinApp::m_pszAppName ("JPEGsnoop") - // with the "REG_COMPANY_NAME" to create the full - // key path "Software/ImpulseAdventure/JPEGsnoop/Recent File List" - SetRegistryKey(REG_COMPANY_NAME); - LoadStdProfileSettings(4); // Load standard INI file options (including MRU) - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 4")); - - // ------------------------------------ - m_pAppConfig->RegistryLoad(); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 5")); - - // Now that we've loaded the registry, assign the first-run status (from EULA) - // Set the "First Run" flag for the Signature database to avoid warning messages - m_pDbSigs->SetFirstRun(!m_pAppConfig->bEulaAccepted); - - // Assign defaults - m_pAppConfig->UseDefaults(); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 6")); - - // Ensure that the user has previously signed the EULA - if (!CheckEula()) { - return false; - } - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 7")); - - // Has the user enabled checking for program updates? - if (m_pAppConfig->bUpdateAuto) { - CheckUpdates(false); - } - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 8")); - - m_pAppConfig->RegistryStore(); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 9")); - - // Update the User database directory setting - m_pDbSigs->SetDbDir(m_pAppConfig->strDbDir); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 10")); - - // Register the application's document templates. Document templates - // serve as the connection between documents, frame windows and views - - // FIXME: - CSingleDocTemplate* pDocTemplate; - pDocTemplate = new CSingleDocTemplate( - IDR_MAINFRAME, - RUNTIME_CLASS(CJPEGsnoopDoc), - RUNTIME_CLASS(CMainFrame), // main SDI frame window - RUNTIME_CLASS(CJPEGsnoopView)); - if (!pDocTemplate) - return FALSE; - pDocTemplate->SetContainerInfo(IDR_CNTR_INPLACE); - AddDocTemplate(pDocTemplate); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 11")); - - // Establish GUI mode defaults that can be overridden by the - // command line parsing results. - m_pAppConfig->bGuiMode = true; - m_pAppConfig->bInteractive = true; - - // Parse command line for standard shell commands, DDE, file open - CMyCommandParser cmdInfo(m_pAppConfig); - ParseCommandLine(cmdInfo); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 12")); - - if (m_pAppConfig->bGuiMode) { - // If the user has requested that we open up a file in GUI mode: - // - Normal operation - // - Drag & drop - // then we need to ensure that the view has been created before we - // enter the OnOpenDocument() in OpenDocumentFile(). The reason for this - // is that OnOpenDocument will call AnalyzeFile() and insert the log into - // the view. The view is only created at the end of OpenDocumentFile() as - // a result of OnInitialUpdate(). - // - // To achieve this, the easiest method is to force a New file operation - // first. This ensures that we create the view (in OnInitialUpdate) - // before we launch into any processing. - // - // For cosmetic reasons, also call UpdateWindow to ensure that the - // frame is drawn fully before any further processing. - OnFileNew(); - m_pMainWnd->ShowWindow(SW_SHOW); - m_pMainWnd->UpdateWindow(); - } - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 13")); - - // Do my own ProcessShellCommand(). The following is based - // on part of what exists in appui2.cpp with no real changes. - // I have dropped off some of the unsupported m_nShellCommand modes. - // Perhaps this will provide us with an easier means of extending - // support to other batch commands later. - // ---------------------------------------------------------- - if (!ProcessShellCommand(cmdInfo)) - return FALSE; - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 14")); - // ---------------------------------------------------------- - - // Now handle any other command-line directives that we haven't - // already covered above - if (m_pAppConfig->bGuiMode == false) { - //bool bCmdLineRet = false; - DoCmdLineCore(); - return false; - } - - // We only arrive here if there is a window to show (bResult) - - // Original wizard code follows - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 20")); - - // The one and only window has been initialized, so show and update it - m_pMainWnd->ShowWindow(SW_SHOW); - m_pMainWnd->UpdateWindow(); - // call DragAcceptFiles only if there's a suffix - // In an SDI app, this should occur after ProcessShellCommand - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() Checkpoint 21")); - // ---------------- - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopApp::InitInstance() End")); - - return TRUE; - - - -} - -// Process any command-line operations -void CJPEGsnoopApp::DoCmdLineCore() -{ - ASSERT(m_pAppConfig->bGuiMode == false); - - // Allocate the command-line processing core - CJPEGsnoopCore* pSnoopCore = NULL; - pSnoopCore = new CJPEGsnoopCore; - ASSERT(pSnoopCore); - if (!pSnoopCore) { - exit(1); - } - - BOOL bStatus = false; - // Perform processing requested by command-line - if (m_pAppConfig->bCmdLineHelp) { - // Display command-line summary - CmdLineHelp(); - } else if (m_pAppConfig->bCmdLineOpenEn) { - - // Single file processing - - // =================================== - // Handle "-i" - // =================================== - - // Process the file - bStatus = pSnoopCore->DoAnalyzeOffset(m_pAppConfig->strCmdLineOpenFname); - - if (!bStatus) { - // Issues during file open - // Error message was already added to the log file in AnalyzeOpen() - // So just report to user in console - CString strErr; - strErr.Format(_T("ERROR: during open of file [%s]\n"),(LPCTSTR)m_pAppConfig->strCmdLineOpenFname); - CmdLineMessage(strErr); - } - - // Save the output log if enabled - // Note that we will do this even if the input file open had - // an issue, so that post-processing will reveal error in - // the associated log report. - if (theApp.m_pAppConfig->bCmdLineOutputEn) { - pSnoopCore->DoLogSave(m_pAppConfig->strCmdLineOutputFname); - } - - if (bStatus) { - - // Now proceed to "extract all" if requested - if (m_pAppConfig->bCmdLineExtractEn) { - CString strInputFname = m_pAppConfig->strCmdLineOpenFname; - CString strExportFname = m_pAppConfig->strCmdLineOutputFname; - bool bOverlayEn = false; - bool bForceSoi = false; - bool bForceEoi = false; - bool bIgnoreEoi = false; - bool bExtractAllEn = true; - bool bDhtAviInsert = false; - CString strOutPath = _T(""); // unused - - // If the user didn't explicitly provide an output filename, default to one - if (strExportFname == _T("")) { - strExportFname = strInputFname + _T(".export.jpg"); - } - - pSnoopCore->DoExtractEmbeddedJPEG(strInputFname,strExportFname,bOverlayEn,bForceSoi,bForceEoi,bIgnoreEoi,bExtractAllEn,bDhtAviInsert,strOutPath); - - } // bCmdLineExtractEn - - } // bStatus - - } else if (m_pAppConfig->bCmdLineBatchEn) { - - // Batch file processing - - // =================================== - // Handle "-b" and "-br" - // =================================== - - // Settings for batch operations - CString strDirSrc; - CString strDirDst; - bool bSubdirs; - bool bExtractAll; - - strDirSrc = m_pAppConfig->strCmdLineBatchDirName; - strDirDst = m_pAppConfig->strCmdLineBatchDirName; // Only support same dir for now - bSubdirs = m_pAppConfig->bCmdLineBatchRec; - bExtractAll = m_pAppConfig->bCmdLineExtractEn; - - // Generate the batch file list - pSnoopCore->GenBatchFileList(strDirSrc,strDirDst,bSubdirs,bExtractAll); - - // Now that we've created the list of files, start processing them - unsigned nBatchFileCount; - nBatchFileCount = pSnoopCore->GetBatchFileCount(); - - // TODO: Clear the current RichEdit log - - for (unsigned nFileInd=0;nFileIndDoBatchFileProcess(nFileInd,true,bExtractAll); - } - - // TODO: ... - - - } - - - // Deallocate the command-line core - if (pSnoopCore) { - delete pSnoopCore; - pSnoopCore = NULL; - } - - // If requested, issue done indication to the prompt - if (m_pAppConfig->bCmdLineDoneMsg) { - CmdLineDoneMessage(); - } -} - - -// Report that application is finished to console -// This is an optional indicator to say that command-line -// operations have completed. -void CJPEGsnoopApp::CmdLineDoneMessage() -{ - CString strMsg; - strMsg = "\n"; - strMsg += "JPEGsnoop operations complete\n"; - strMsg += "\n"; - CmdLineMessage(strMsg); -} - -// Report a message to the console -// -// Note that this reporting may interject with -// the user's input to the command prompt since GUI application -// will release to command prompt immediately after launching -// and will not block. - -void CJPEGsnoopApp::CmdLineMessage(CString strMsg) -{ - // Report to the console - // REF: http://stackoverflow.com/questions/5094502/how-do-i-write-to-stdout-from-an-mfc-program - bool bConsoleAttached = FALSE; - if (AttachConsole(ATTACH_PARENT_PROCESS)) - { - int osfh = _open_osfhandle((intptr_t) GetStdHandle(STD_OUTPUT_HANDLE), 8); - if ((HANDLE)osfh != INVALID_HANDLE_VALUE) - { - *stdout = *_tfdopen(osfh, _T("a")); - bConsoleAttached = TRUE; - } - } - if (bConsoleAttached) { - - // ------------------------------------------- - // Now convert from unicode for printf - // REF: http://stackoverflow.com/questions/10578522/conversion-of-cstring-to-char - - // The number of characters in the string can be - // less than nMaxStrLen. Null terminating character added at end. - const size_t nMaxStrLen = 5000; - size_t nCharsConverted = 0; - char acMsg[nMaxStrLen]; - - wcstombs_s(&nCharsConverted, acMsg, - strMsg.GetLength()+1, strMsg, - _TRUNCATE); - // ------------------------------------------- - - // Output to console - printf("%s",acMsg); - - } -} - -// If it has been more than "nUpdateAutoDays" days since our -// last check for a recent update to the software, check the -// website for a newer version. -// - If a new version is available, the user is notified but -// no action or changes are made. The user needs to navigate -// to the website to download the latest version manually. -// -// INPUT: -// - bForceNow = Do we ignore day timer and force a check now? -// -void CJPEGsnoopApp::CheckUpdates(bool bForceNow) -{ - CString strUpdateLastChk = m_pAppConfig->strUpdateLastChk; - - unsigned nCheckYear,nCheckMon,nCheckDay; - if (strUpdateLastChk.GetLength()==8) { - nCheckYear = _tstoi(strUpdateLastChk.Mid(0,4)); - nCheckMon = _tstoi(strUpdateLastChk.Mid(4,2)); - nCheckDay = _tstoi(strUpdateLastChk.Mid(6,2)); - } else { - nCheckYear = 1980; - nCheckMon = 1; - nCheckDay = 1; - } - - CTime tmeUpdateLastChk(nCheckYear,nCheckMon,nCheckDay,0,0,0); - CTime tmeToday = CTime::GetCurrentTime(); - CTimeSpan tmePeriod(m_pAppConfig->nUpdateAutoDays, 0, 0, 0); - CTimeSpan tmeDiff; - tmeDiff = tmeToday - tmeUpdateLastChk; - - if ((bForceNow) || (tmeDiff >= tmePeriod)) { - CModelessDlg* pdlg; - pdlg = new CModelessDlg; - if (!pdlg) { - // Fatal error - exit(1); - } - pdlg->Create(IDD_MODELESSDLG,NULL); - - CheckUpdatesWww(); - - pdlg->OnCancel(); - - // Update the timestamp of the last update check - CString strCurDate; - strCurDate = tmeToday.Format(_T("%Y%m%d")); - m_pAppConfig->strUpdateLastChk = strCurDate; - m_pAppConfig->Dirty(); - - } - -} - -// Scrape the header of the web page to determine if a newer version -// of the software is available. -// - No information is sent to the website other than the current version number -// -// RETURN: -// - Success if connection to web page was OK -// -bool CJPEGsnoopApp::CheckUpdatesWww() -{ - - CString strVerLatest = _T(""); - CString strDateLatest = _T(""); - - CString strSubmitHost; - CString strSubmitPage; - strSubmitHost = IA_HOST; - strSubmitPage = IA_UPDATES_CHK_PAGE; - - static LPTSTR acceptTypes[2]={_T("*/*"), NULL}; - HINTERNET hINet, hConnection, hData; - - unsigned nLen; - - CString strFormat; - CString strFormData; - unsigned nFormDataLen; - CString strHeaders = - _T("Content-Type: application/x-www-form-urlencoded"); - strFormat = _T("ver=%s"); - - //*** Need to sanitize data for URL submission! - // Search for "&", "?", "=" - strFormData.Format(strFormat,VERSION_STR); - nFormDataLen = strFormData.GetLength(); - - CString strTmp; - - CHAR pcBuffer[2048] ; - CString strContents ; - DWORD dwRead; //dwStatus; - hINet = InternetOpen(_T("JPEGsnoop/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ); - if ( !hINet ) - { - AfxMessageBox(_T("InternetOpen Failed")); - return false; - } - try - { - hConnection = InternetConnect( hINet, (LPCTSTR)strSubmitHost, 80, NULL,NULL, INTERNET_SERVICE_HTTP, 0, 1 ); - if ( !hConnection ) - { - InternetCloseHandle(hINet); - return false; - } - hData = HttpOpenRequest( hConnection, _T("POST"), (LPCTSTR)strSubmitPage, NULL, NULL, NULL, 0, 1 ); - if ( !hData ) - { - InternetCloseHandle(hConnection); - InternetCloseHandle(hINet); - return false; - } - // GET HttpSendRequest( hData, NULL, 0, NULL, 0); - - if (!HttpSendRequest( hData, (LPCTSTR)strHeaders, strHeaders.GetLength(), strFormData.GetBuffer(), strFormData.GetLength())) { - InternetCloseHandle(hConnection); - InternetCloseHandle(hINet); - AfxMessageBox(_T("ERROR: Couldn't SendRequest")); - return false; - } - - - // Only read the first 1KB of page - bool bScrapeDone = false; - unsigned nScrapeLen = 0; - unsigned nScrapeMax = 1024; - while (!bScrapeDone) { - if (!InternetReadFile( hData, pcBuffer, 255, &dwRead )) { - bScrapeDone = true; - } else { - if ( dwRead == 0 ) { - bScrapeDone = true; - break; - } - pcBuffer[dwRead] = 0; - strContents += pcBuffer; - nScrapeLen += dwRead; - if (nScrapeLen >= nScrapeMax) { - bScrapeDone = true; - } - } - } - - // Parse the HTTP result and search for the latest - // version identification string - nLen = strContents.GetLength(); - - CString strData; - CString strParam; - CString strVal; - int nIndDataStart = -1; - int nIndDataEnd = -1; - unsigned nIndDataLen = 0; - bool bFoundRange = true; - nIndDataStart = strContents.Find(_T("***("))+4; - nIndDataEnd = strContents.Find(_T(")***")); - - if ((nIndDataStart == -1) || (nIndDataEnd == -1)) { - // Couldn't find start or end - bFoundRange = false; - } - - if (nIndDataStart > nIndDataEnd) { - // Start and End positions look wrong - bFoundRange = false; - } - - if (bFoundRange) { - // Found start & end markers - nIndDataLen = nIndDataEnd-nIndDataStart; - strData = strContents.Mid(nIndDataStart,nIndDataLen); - bool bDone = false; - bool bTokDone; - CString strCh; - unsigned nInd = 0; - while (!bDone) { - if (nInd >= nIndDataLen) { - bDone = true; - } else { - bTokDone = false; - strParam = _T(""); - while (!bTokDone) { - strCh = strData.GetAt(nInd); - if (strCh==_T("=")) { - bTokDone = true; - nInd+=2; // skip [ - } else { - strParam += strCh; - nInd++; - } - } - - bTokDone = false; - strVal = _T(""); - while (!bTokDone) { - strCh = strData.GetAt(nInd); - if (strCh==_T("]")) { - bTokDone = true; - nInd+=2; // skip , - } else { - strVal += strCh; - nInd++; - } - } - - //strTmp.Format(_T("Param[%s] Val[%s]"),strParam,strVal); - //AfxMessageBox(strTmp); - - if (strParam == _T("latest_ver")) { - strVerLatest = strVal; - } - if (strParam == _T("latest_date")) { - strDateLatest = strVal; - } - - } - } - - } // found range - - } - catch( CInternetException* e) - { - e->ReportError(); - e->Delete(); - //AfxMessageBox(_T("EXCEPTION!")); - } - InternetCloseHandle(hConnection); - InternetCloseHandle(hINet); - InternetCloseHandle(hData); - - // Report that a later version exists! - if (strVerLatest != VERSION_STR) { - CUpdateAvailDlg dlgUpdate; - dlgUpdate.strVerCur = VERSION_STR; - dlgUpdate.strVerLatest = strVerLatest; - dlgUpdate.strDateLatest = strDateLatest; - dlgUpdate.bUpdateAutoStill = m_pAppConfig->bUpdateAuto; - if (dlgUpdate.DoModal() == IDOK) { - m_pAppConfig->bUpdateAuto = (dlgUpdate.bUpdateAutoStill)?true:false; - m_pAppConfig->Dirty(); - } - } - - return true; -} - - - -// Check the End-User License Agreement status -// - Ensure that the EULA has been previously signed -// - If EULA hasn't been signed, then show dialog box -// -// POST: -// - m_pAppConfig->bEulaAccepted -// - m_pAppConfig->bUpdateAuto -// -bool CJPEGsnoopApp::CheckEula() -{ - if (m_pAppConfig->bEulaAccepted) { - return true; - } else { - CTermsDlg dlg; - if (dlg.DoModal() == IDOK) { - // They must have accepted the terms, update the - // acceptance in the registry - m_pAppConfig->bEulaAccepted = (dlg.bEulaOk != 0); - m_pAppConfig->bUpdateAuto = (dlg.bUpdateAuto != 0); - m_pAppConfig->Dirty(); - m_pAppConfig->RegistryStore(); - return true; - } else { - // They didn't accept, so quit the application - m_pAppConfig->bEulaAccepted = false; - m_pAppConfig->Dirty(); - m_pAppConfig->RegistryStore(); - - // How to quit? - return false; - } - } -} - - - -// App command to run the dialog -void CJPEGsnoopApp::OnAppAbout() -{ - CAboutDlg aboutDlg; - aboutDlg.DoModal(); -} - - -// CJPEGsnoopApp message handlers - -// Present file open dialog -// - Populate file filter list with main decode formats -// -// POST: -// - Calls OpenDocumentFile() -// -void CJPEGsnoopApp::MyOnFileOpen() -{ - - //bool bStatus = 0; - TCHAR aszFilter[] = - _T("JPEG Image (*.jpg;*.jpeg)|*.jpg;*.jpeg|")\ - _T("Thumbnail (*.thm)|*.thm|")\ - _T("AVI Movie (*.avi)|*.avi|")\ - _T("QuickTime Movie (*.mov)|*.mov|")\ - _T("Digital Negative (*.dng)|*.dng|")\ - _T("RAW Image (*.crw;*.cr2;*.nef;*.orf;*.pef)|*.crw;*.cr2;*.nef;*.orf;*.pef|")\ - _T("PDF Files (*.pdf)|*.pdf|")\ - _T("Photoshop Files (*.psd)|*.psd|")\ - _T("All Files (*.*)|*.*||"); - - /* - CFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs - LPCTSTR lpszDefExt = NULL, - LPCTSTR lpszFileName = NULL, - DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, - LPCTSTR lpszFilter = NULL, - CWnd* pParentWnd = NULL, - DWORD dwSize = 0); - */ - - // BUG: #1008 - CFileDialog FileDlg(TRUE, _T(".jpg"), NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, aszFilter); - - CString strTitle; - CString strFileName; - CString strPathName; // Added - VERIFY(strTitle.LoadString(IDS_CAL_FILEOPEN)); - FileDlg.m_ofn.lpstrTitle = strTitle; - - // Extend the maximum filename length - // Default is 64 for filename, 260 for path - // Some users have requested support for longer filenames - LPTSTR spFilePath; - spFilePath = new TCHAR[501]; - spFilePath[0] = TCHAR(0); - FileDlg.m_pOFN->lpstrFile = spFilePath; - FileDlg.m_pOFN->nMaxFile = 500; - FileDlg.m_pOFN->nMaxFileTitle = 300; - - // TODO: Should trap the following for exception (CommDlgExtendedError = FNERR_BUFFERTOOSMALL) - // For reference, see: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646960%28v=vs.85%29.aspx - if( FileDlg.DoModal() == IDOK ) - { - strFileName = FileDlg.GetFileName(); - strPathName = FileDlg.GetPathName(); - // - // For testing purposes, added this GetCurrentDirectory() check - TCHAR szDirCur[501]; - GetCurrentDirectory(500,szDirCur); - - // NOTE: - // The OpenDocumentFile() call converts any relative path to absolute path before loading the file. - // It appears that VS 2003 was allowing me to pass strFileName into the OpenDocumentFile() call - // and the user selected directory in the previous CFileDialog() caused a SetCurrentDirectory() - // which made the relative to absolute conversion work. - // - // In VS 2012, it appears that the CFileDialog() is no longer causing SetCurrentDirectory() - // to pick up the selected folder, so the relative to absolute conversion is returning a path - // to the project/executable directory. Net result is that the file doesn't get opened as it - // cannot be found. Opens from the MRU list will still work, however. - // - // In VS 2012, I can theoretically get CFileDialog to work in the old way if I happened to initialize COM - // with COINIT_MULTITHREADED, but this doesn't seem recommended. - // - // Instead, it looks like I can simply pass in the full path (GetPathName()) and everything - // works fine! - -// OpenDocumentFile(strFileName); - OpenDocumentFile(strPathName); // Added - - // if returns NULL, the user has already been alerted - } - - if (spFilePath) { delete[] spFilePath; } - -} - -// Basic placeholder for OnFileNew -void CJPEGsnoopApp::MyOnFileNew() -{ - // Default - CWinApp::OnFileNew(); -} - -// Retreive the currently active document (if it exists) -CJPEGsnoopDoc* CJPEGsnoopApp::GetCurDoc() -{ - CFrameWnd * pFrame = (CFrameWnd *)(AfxGetApp()->m_pMainWnd); - ASSERT(pFrame); - CJPEGsnoopDoc * pMyDoc; - pMyDoc = (CJPEGsnoopDoc *) pFrame->GetActiveDocument(); - return pMyDoc; -} - -// Reprocess the current file -// - Invokes the Reprocess action in the Document -// - Ensures that the document is available first -void CJPEGsnoopApp::DocReprocess() -{ - CJPEGsnoopDoc* pMyDoc; - pMyDoc = GetCurDoc(); - if (pMyDoc) { - pMyDoc->Reprocess(); - } -} - -// Mark the image view as needing update -// - Will take effect on next "Reprocess" call. -void CJPEGsnoopApp::DocImageDirty() -{ - CJPEGsnoopDoc* pMyDoc; - pMyDoc = GetCurDoc(); - if (pMyDoc) { - pMyDoc->J_ImgSrcChanged(); - } -} - -// -------------------- Handle Menu actions ------------------ - -// Set menu item toggle for Options DHT Expand -void CJPEGsnoopApp::OnOptionsDhtexpand() -{ - if (m_pAppConfig->bOutputDHTexpand) { - m_pAppConfig->bOutputDHTexpand = FALSE; - } else { - m_pAppConfig->bOutputDHTexpand = TRUE; - } - // Mark option as changed for next registry update - m_pAppConfig->Dirty(); - - HandleAutoReprocess(); - -} - -// Set menu item toggle for Options Makernotes -// - Invoke reprocess if enabled -void CJPEGsnoopApp::OnOptionsMakernotes() -{ - if (m_pAppConfig->bDecodeMaker) { - m_pAppConfig->bDecodeMaker = FALSE; - } else { - m_pAppConfig->bDecodeMaker = TRUE; - } - // Mark option as changed for next registry update - m_pAppConfig->Dirty(); - - HandleAutoReprocess(); - -} - -// Set menu item toggle for Scan Segment Dump -// - Invoke reprocess if enabled -void CJPEGsnoopApp::OnScansegmentDump() -{ - if (m_pAppConfig->bOutputScanDump) { - m_pAppConfig->bOutputScanDump = FALSE; - } else { - m_pAppConfig->bOutputScanDump = TRUE; - } - // Mark option as changed for next registry update - m_pAppConfig->Dirty(); - - HandleAutoReprocess(); -} - - -// Set menu item toggle for Scan Segment Dump -// - Invoke reprocess if enabled -void CJPEGsnoopApp::OnScansegmentDecodeimage() -{ - if (m_pAppConfig->bDecodeScanImg) { - m_pAppConfig->bDecodeScanImg = FALSE; - } else { - m_pAppConfig->bDecodeScanImg = TRUE; - } - // Mark option as changed for next registry update - m_pAppConfig->Dirty(); - - HandleAutoReprocess(); -} - - -// Set menu item toggle for Scan Segment Histogram (Y) -// - Mark the image as dirty -// - Invoke reprocess if enabled -void CJPEGsnoopApp::OnScansegmentHistogramy() -{ - if (m_pAppConfig->bDumpHistoY) { - m_pAppConfig->bDumpHistoY = FALSE; - } else { - m_pAppConfig->bDumpHistoY = TRUE; - } - // Mark option as changed for next registry update - m_pAppConfig->Dirty(); - - // Since changing the histogram can change the image - // output, assume that this will cause a change and - // require us to dirty the scan decode. - // FIXME: If someone has scan preview on, processes once, - // turns scan preview off, flips this option twice, and then - // turns scan preview on, they will need to recalc the scan. - // Perhaps fix is to leave all of this up to ImgDec() block, - // and have it look at the AppConfig options being sent. If - // different (or source file changes), then it should recalc. - - // Mark image view area as needing update - DocImageDirty(); - HandleAutoReprocess(); -} - - - -// If Automatic Reprocessing is enabled, reprocess the file -// - If Reprocessing is not enabled and the coach message has -// not been disabled, inform user of option to enable -void CJPEGsnoopApp::HandleAutoReprocess() -{ - if (m_pAppConfig->bReprocessAuto) { - DocReprocess(); - } else { - if (m_pAppConfig->bCoachReprocessAuto) { - // Show the coaching dialog - CNoteDlg dlg; - dlg.strMsg = COACH_REPROCESS_AUTO; - dlg.DoModal(); - m_pAppConfig->bCoachReprocessAuto = !dlg.bCoachOff; - m_pAppConfig->Dirty(); - } - } -} - -// Set menu item toggle for Scan Segment Full IDCT -// - Mark the image as dirty -// - Invoke reprocess if enabled -void CJPEGsnoopApp::OnScansegmentFullidct() -{ - if (m_pAppConfig->bDecodeScanImgAc) { - m_pAppConfig->bDecodeScanImgAc = FALSE; - } else { - m_pAppConfig->bDecodeScanImgAc = TRUE; - } - // Mark option as changed for next registry update - m_pAppConfig->Dirty(); - - // Since changing the AC can change the image - // output, assume that this will cause a change and - // require us to dirty the scan decode. - - // Mark image view area as needing update - DocImageDirty(); - HandleAutoReprocess(); -} - -// Set menu item toggle for Scan Segment No IDCT -// - Mark the image as dirty -// - Invoke reprocess if enabled -// NOTES: -// - Even though "Noidct" is the opposite of "Fullidct", the menu -// option simply toggles the state, so we can reuse the handler. -void CJPEGsnoopApp::OnScansegmentNoidct() -{ - OnScansegmentFullidct(); -} - - - - -// -------------------- Handle Menu status ------------------ - -// Set menu item status for Options DHT Expand -void CJPEGsnoopApp::OnUpdateOptionsDhtexpand(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bOutputDHTexpand) { - pCmdUI->SetCheck(TRUE); - } else { - pCmdUI->SetCheck(FALSE); - } -} - -// Set menu item status for Options Makernotes -void CJPEGsnoopApp::OnUpdateOptionsMakernotes(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bDecodeMaker) { - pCmdUI->SetCheck(TRUE); - } else { - pCmdUI->SetCheck(FALSE); - } -} - - -// Set menu item status for Scan Segment Dump -void CJPEGsnoopApp::OnUpdateScansegmentDump(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bOutputScanDump) { - pCmdUI->SetCheck(TRUE); - } else { - pCmdUI->SetCheck(FALSE); - } -} - - -// Set menu item status for Scan Segment Decode Image -void CJPEGsnoopApp::OnUpdateScansegmentDecodeimage(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bDecodeScanImg) { - pCmdUI->SetCheck(TRUE); - } else { - pCmdUI->SetCheck(FALSE); - } -} - -// Set menu item status for Scan Segment Histogram (Y) -// - May be disabled if Decode Scan Image or Histogram are disabled -void CJPEGsnoopApp::OnUpdateScansegmentHistogramy(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bDecodeScanImg && m_pAppConfig->bHistoEn) { - pCmdUI->Enable(true); - } else { - pCmdUI->Enable(false); - } - if (m_pAppConfig->bDumpHistoY) { - pCmdUI->SetCheck(TRUE); - } else { - pCmdUI->SetCheck(FALSE); - } -} - -// Set menu item status for Scan Segment Full IDCT -// - May be disabled if Decode Scan Image is disabled -void CJPEGsnoopApp::OnUpdateScansegmentFullidct(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bDecodeScanImg) { - pCmdUI->Enable(true); - } else { - pCmdUI->Enable(false); - } - if (m_pAppConfig->bDecodeScanImgAc) { - pCmdUI->SetCheck(TRUE); - } else { - pCmdUI->SetCheck(FALSE); - } -} - -// Set menu item status for Scan Segment No IDCT -// - May be disabled if Decode Scan Image is disabled -// NOTE: -// - Opposite functionality of Fullidct -void CJPEGsnoopApp::OnUpdateScansegmentNoidct(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bDecodeScanImg) { - pCmdUI->Enable(true); - } else { - pCmdUI->Enable(false); - } - if (m_pAppConfig->bDecodeScanImgAc) { - pCmdUI->SetCheck(FALSE); - } else { - pCmdUI->SetCheck(TRUE); - } -} - - -// Options Configuration Dialog -// - Show the dialog box -// - Pre-populate with current m_pAppConfig settings -// - If user clicks OK, then revised settings are stored back -// into the registry -void CJPEGsnoopApp::OnOptionsConfiguration() -{ - CSettingsDlg setDlg; - setDlg.m_bUpdateAuto = m_pAppConfig->bUpdateAuto; - setDlg.m_nUpdateChkDays = m_pAppConfig->nUpdateAutoDays; - setDlg.m_strDbDir = m_pAppConfig->strDbDir; - setDlg.m_bReprocessAuto = m_pAppConfig->bReprocessAuto; - setDlg.m_bDbSubmitNet = m_pAppConfig->bDbSubmitNet; - setDlg.m_nRptErrMaxScanDecode = m_pAppConfig->nErrMaxDecodeScan; - //setDlg.m_bReportClip = m_pAppConfig->bStatClipEn; - - if (setDlg.DoModal() == IDOK) - { - m_pAppConfig->bUpdateAuto = (setDlg.m_bUpdateAuto != 0); - m_pAppConfig->nUpdateAutoDays = setDlg.m_nUpdateChkDays; - m_pAppConfig->strDbDir = setDlg.m_strDbDir; - m_pAppConfig->bReprocessAuto = (setDlg.m_bReprocessAuto != 0); - m_pAppConfig->bDbSubmitNet = (setDlg.m_bDbSubmitNet != 0); - m_pAppConfig->nErrMaxDecodeScan = setDlg.m_nRptErrMaxScanDecode; - //m_pAppConfig->bStatClipEn = (setDlg.m_bReportClip != 0); - m_pAppConfig->Dirty(); - - // Since the signature database needs to know of the - // [possibly] updated user database directory, we must - // set it here. - m_pDbSigs->SetDbDir(m_pAppConfig->strDbDir); - - // Don't need to force registry write, as it will be done - // later when exit app, but this ensures that it gets done. - m_pAppConfig->RegistryStore(); - } -} - -// Menu item to check for JPEGsnoop updates -void CJPEGsnoopApp::OnOptionsCheckforupdates() -{ - CheckUpdates(true); -} - - -// Manage Local Signature Database -// - Present user with database dialog box -// - This dialog enables the user to view and delete entries that are -// defined and stored within the current installation file. -void CJPEGsnoopApp::OnToolsManagelocaldb() -{ - CDbManageDlg manageDlg; - CJPEGsnoopDoc* pMyDoc; - pMyDoc = GetCurDoc(); - if (pMyDoc) { - pMyDoc->J_ImgSrcChanged(); - - unsigned nDbUserEntries; - CString strTmp; - CompSig sMySig; - nDbUserEntries = m_pDbSigs->DatabaseExtraGetNum(); - - for (unsigned nInd=0;nIndDatabaseExtraGet(nInd); - - // TODO: Should we confirm that all entries are marked as valid already? - - if (sMySig.eEditor == ENUM_SOURCE_SW) { - manageDlg.InsertEntry(nInd,sMySig.strMSwDisp,_T(""),sMySig.strUmQual,sMySig.strCSig); - } else { - manageDlg.InsertEntry(nInd,sMySig.strXMake,sMySig.strXModel,sMySig.strUmQual,sMySig.strCSig); - } - } - - - if (manageDlg.DoModal() == IDOK) { - // Now determine which entries were deleted - // Set all flags to invalid - // Step through remaining list from dialog and fetch indices - // For each remaining index, set the corresponding valid indicator in the main list - unsigned nNumExtra = m_pDbSigs->DatabaseExtraGetNum(); - for (unsigned nInd=0;nIndSetEntryValid(nInd,false); - } - CUIntArray anRemain; - unsigned nRemainInd; - manageDlg.GetRemainIndices(anRemain); - for (unsigned nInd=0;nInd<(unsigned)anRemain.GetCount();nInd++) { - nRemainInd = anRemain.GetAt(nInd); - m_pDbSigs->SetEntryValid(nRemainInd,true); - } - - m_pDbSigs->DatabaseExtraStore(); - m_pDbSigs->DatabaseExtraLoad(); - - - } - - } - -} - -// Set menu item toggle for Options Signature Search -// - Invoke reprocess if enabled -void CJPEGsnoopApp::OnOptionsSignaturesearch() -{ - if (m_pAppConfig->bSigSearch) { - m_pAppConfig->bSigSearch = FALSE; - } else { - m_pAppConfig->bSigSearch = TRUE; - } - // Mark option as changed for next registry update - m_pAppConfig->Dirty(); - HandleAutoReprocess(); -} - -// Set menu item status for Options Signature Search -void CJPEGsnoopApp::OnUpdateOptionsSignaturesearch(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bSigSearch) { - pCmdUI->SetCheck(TRUE); - } else { - pCmdUI->SetCheck(FALSE); - } -} - - -// Set menu item toggle for Scan Segment Histogram -// - Mark the image as dirty -// - Invoke reprocess if enabled -void CJPEGsnoopApp::OnScansegmentHistogram() -{ - if (m_pAppConfig->bHistoEn) { - m_pAppConfig->bHistoEn = FALSE; - } else { - m_pAppConfig->bHistoEn = TRUE; - } - // Mark option as changed for next registry update - m_pAppConfig->Dirty(); - - // Since changing the histogram can change the image - // output, assume that this will cause a change and - // require us to dirty the scan decode. - // FIXME: If someone has scan preview on, processes once, - // turns scan preview off, flips this option twice, and then - // turns scan preview on, they will need to recalc the scan. - // Perhaps fix is to leave all of this up to ImgDec() block, - // and have it look at the AppConfig options being sent. If - // different (or source file changes), then it should recalc. - - // Mark image view area as needing update - DocImageDirty(); - HandleAutoReprocess(); -} - -// Set menu item status for Options Signature Search -// - May be disabled if Decode Scan Image is disabled -void CJPEGsnoopApp::OnUpdateScansegmentHistogram(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bDecodeScanImg) { - pCmdUI->Enable(true); - } else { - pCmdUI->Enable(false); - } - if (m_pAppConfig->bHistoEn) { - pCmdUI->SetCheck(TRUE); - } else { - pCmdUI->SetCheck(FALSE); - } -} - -// Set menu item toggle for Options Hide Unknown EXIF tags -// - Invoke reprocess if enabled -void CJPEGsnoopApp::OnOptionsHideuknownexiftags() -{ - if (m_pAppConfig->bExifHideUnknown) { - m_pAppConfig->bExifHideUnknown = FALSE; - } else { - m_pAppConfig->bExifHideUnknown = TRUE; - } - // Mark option as changed for next registry update - m_pAppConfig->Dirty(); - - HandleAutoReprocess(); - -} - -// Set menu item status for Options Hide Unknown EXIF tags -void CJPEGsnoopApp::OnUpdateOptionsHideuknownexiftags(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bExifHideUnknown) { - pCmdUI->SetCheck(TRUE); - } else { - pCmdUI->SetCheck(FALSE); - } -} - -// Menu item for File Batch Process -// - Invoke DoBatchProcess() from Document -void CJPEGsnoopApp::OnFileBatchprocess() -{ - // TODO: Add your command handler code here - CJPEGsnoopDoc* pMyDoc; - pMyDoc = GetCurDoc(); - if (pMyDoc) { - pMyDoc->DoBatchProcess(_T(""),false,false); - } -} - - - -// Set menu item toggle for Options Relaxed Parsing -// - Invoke reprocess if enabled -void CJPEGsnoopApp::OnOptionsRelaxedparsing() -{ - if (m_pAppConfig->bRelaxedParsing) { - m_pAppConfig->bRelaxedParsing = FALSE; - } else { - m_pAppConfig->bRelaxedParsing = TRUE; - } - // Mark option as changed for next registry update - m_pAppConfig->Dirty(); - - HandleAutoReprocess();} - - -// Set menu item status for Options Relaxed Parsing -void CJPEGsnoopApp::OnUpdateOptionsRelaxedparsing(CCmdUI *pCmdUI) -{ - if (m_pAppConfig->bRelaxedParsing) { - pCmdUI->SetCheck(TRUE); - } else { - pCmdUI->SetCheck(FALSE); - } -} diff --git a/source/JPEGsnoop.h b/source/JPEGsnoop.h deleted file mode 100644 index 7eeecbc..0000000 --- a/source/JPEGsnoop.h +++ /dev/null @@ -1,136 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Main application code entry-point -// -// ========================================================================== - - -// JPEGsnoop.h : main header file for the JPEGsnoop application -// -#pragma once - -//#ifndef __AFXWIN_H__ -// #error include 'stdafx.h' before including this file for PCH -//#endif - -#include "resource.h" // main symbols - -#include "snoop.h" -#include "JPEGsnoopCore.h" -//#include "JPEGsnoopDoc.h" -#include "SnoopConfig.h" - - -#include "JPEGsnoopCore.h" - -// CJPEGsnoopApp: -// See JPEGsnoop.cpp for the implementation of this class -// - -// Define global variable for application log -extern CDocLog* glb_pDocLog; -// Main config options -extern CSnoopConfig *m_pAppConfig; -// Needs to be accessed by JfifDec -extern CDbSigs* m_pDbSigs; - -extern CJPEGsnoopCore *pJPEGsnoopCore; - -class CJPEGsnoopApp // : public CWinApp -{ -public: - CJPEGsnoopApp(); - ~CJPEGsnoopApp(); - -// Overrides -public: - virtual bool InitInstance(); - -// Implementation -// afx_msg void OnAppAbout(); - -// DECLARE_MESSAGE_MAP() - -private: - void MyOnFileOpen(); - void MyOnFileNew(); - - void DoCmdLineCore(); - void CmdLineHelp(); - void CmdLineMessage(QString strMsg); - void CmdLineDoneMessage(); - - void CheckUpdates(bool bForceNow); - bool CheckUpdatesWww(); - bool CheckEula(); - QString RemoveTokenWithSeparators(QString& strText, QString szCharSet); - QString RemoveTokenFromCharset(QString& strText, QString szCharSet); -// CJPEGsnoopDoc* GetCurDoc(); - void DocReprocess(); - void DocImageDirty(); - void HandleAutoReprocess(); - -// HINSTANCE LoadAppLangResourceDLL(); // MFC override - -/* afx_msg void OnOptionsDhtexpand(); - afx_msg void OnOptionsMakernotes(); - afx_msg void OnOptionsScandump(); - afx_msg void OnOptionsDecodescan(); - afx_msg void OnOptionsHistoydump(); - afx_msg void OnUpdateOptionsDhtexpand(CCmdUI *pCmdUI); - afx_msg void OnUpdateOptionsMakernotes(CCmdUI *pCmdUI); - afx_msg void OnUpdateOptionsScandump(CCmdUI *pCmdUI); - afx_msg void OnUpdateOptionsDecodescan(CCmdUI *pCmdUI); - afx_msg void OnUpdateOptionsHistoydump(CCmdUI *pCmdUI); - afx_msg void OnOptionsConfiguration(); - afx_msg void OnOptionsCheckforupdates(); - afx_msg void OnToolsManagelocaldb(); - afx_msg void OnOptionsSignaturesearch(); - afx_msg void OnUpdateOptionsSignaturesearch(CCmdUI *pCmdUI); - afx_msg void OnOptionsDecodeac(); - afx_msg void OnUpdateOptionsDecodeac(CCmdUI *pCmdUI); - afx_msg void OnScansegmentDecodeimage(); - afx_msg void OnScansegmentFullidct(); - afx_msg void OnScansegmentHistogramy(); - afx_msg void OnScansegmentDump(); - afx_msg void OnUpdateScansegmentDecodeimage(CCmdUI *pCmdUI); - afx_msg void OnUpdateScansegmentFullidct(CCmdUI *pCmdUI); - afx_msg void OnUpdateScansegmentHistogramy(CCmdUI *pCmdUI); - afx_msg void OnUpdateScansegmentDump(CCmdUI *pCmdUI); - afx_msg void OnScansegmentNoidct(); - afx_msg void OnUpdateScansegmentNoidct(CCmdUI *pCmdUI); - afx_msg void OnScansegmentHistogram(); - afx_msg void OnUpdateScansegmentHistogram(CCmdUI *pCmdUI); - afx_msg void OnOptionsHideuknownexiftags(); - afx_msg void OnUpdateOptionsHideuknownexiftags(CCmdUI *pCmdUI); - afx_msg void OnFileBatchprocess(); */ - -public: - -private: - bool m_bFatal; // Fatal error occurred (e.g. mem alloc) - -public: -// afx_msg void OnOptionsRelaxedparsing(); -// afx_msg void OnUpdateOptionsRelaxedparsing(CCmdUI *pCmdUI); -}; - -extern CJPEGsnoopApp theApp; diff --git a/source/JPEGsnoop.rc b/source/JPEGsnoop.rc deleted file mode 100644 index dd8bfbe..0000000 --- a/source/JPEGsnoop.rc +++ /dev/null @@ -1,1031 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "//CAL! #define _AFX_NO_SPLITTER_RESOURCES\r\n" - "#define _AFX_NO_OLE_RESOURCES\r\n" - "#define _AFX_NO_TRACKER_RESOURCES\r\n" - "#define _AFX_NO_PROPERTY_RESOURCES\r\n" - "\r\n" - "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" - "LANGUAGE 9, 1\r\n" - "#pragma code_page(1252)\r\n" - "#include ""res\\JPEGsnoop.rc2"" // non-Microsoft Visual C++ edited resources\r\n" - "#include ""afxres.rc"" // Standard components\r\n" - "#include ""afxprint.rc"" // printing/print preview resources\r\n" - "#include ""afxolecl.rc"" // OLE container resources\r\n" - "#endif\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDR_MAINFRAME ICON "res\\jpegsnoop-prog-icon1-novista.ico" -IDR_JPEGsnoopTYPE ICON "res\\JPEGsnoopDoc.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Bitmap -// - -IDR_MAINFRAME BITMAP "res\\Toolbar.bmp" - -///////////////////////////////////////////////////////////////////////////// -// -// Toolbar -// - -IDR_MAINFRAME TOOLBAR 16, 15 -BEGIN - BUTTON ID_FILE_NEW - BUTTON ID_FILE_OPEN - BUTTON ID_FILE_SAVE_AS - SEPARATOR - BUTTON ID_EDIT_CUT - BUTTON ID_EDIT_COPY - BUTTON ID_EDIT_PASTE - SEPARATOR - BUTTON ID_FILE_PRINT - BUTTON ID_APP_ABOUT -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_MAINFRAME MENU -BEGIN - POPUP "&File" - BEGIN - MENUITEM "&Open Image...\tCtrl+O", ID_FILE_OPEN - MENUITEM "&Save Log...\tCtrl+S", ID_FILE_SAVE_AS - MENUITEM "Reprocess File\tCtrl+R", ID_FILE_REPROCESS - MENUITEM "Batch Process...", ID_FILE_BATCHPROCESS - MENUITEM SEPARATOR - MENUITEM "Offset...", ID_FILE_OFFSET - MENUITEM SEPARATOR - MENUITEM "&Print...\tCtrl+P", ID_FILE_PRINT - MENUITEM "Print Pre&view", ID_FILE_PRINT_PREVIEW - MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP - MENUITEM SEPARATOR - MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED - MENUITEM SEPARATOR - MENUITEM "E&xit", ID_APP_EXIT - END - POPUP "&Edit" - BEGIN - MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO - MENUITEM SEPARATOR - MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY - MENUITEM "Select A&ll\tCtrl+A", ID_EDIT_SELECT_ALL - MENUITEM SEPARATOR - MENUITEM "&Find...\tCtrl+F", ID_EDIT_FIND - MENUITEM "F&ind Next\tF3", ID_EDIT_REPEAT - END - POPUP "&View" - BEGIN - POPUP "Image Chan" - BEGIN - MENUITEM "RGB\tAlt+1", ID_PREVIEW_RGB - MENUITEM "YCC\tAlt+2", ID_PREVIEW_YCC - MENUITEM SEPARATOR - MENUITEM "R\tAlt+3", ID_PREVIEW_R - MENUITEM "G\tAlt+4", ID_PREVIEW_G - MENUITEM "B\tAlt+5", ID_PREVIEW_B - MENUITEM SEPARATOR - MENUITEM "Y (grayscale)\tAlt+6", ID_PREVIEW_Y - MENUITEM "Cb\tAlt+7", ID_PREVIEW_CB - MENUITEM "Cr\tAlt+8", ID_PREVIEW_CR - END - POPUP "Image Zoom" - BEGIN - MENUITEM "Zoom In\tCtrl++", ID_IMAGEZOOM_ZOOMIN - MENUITEM "Zoom Out\tCtrl+-", ID_IMAGEZOOM_ZOOMOUT - MENUITEM SEPARATOR - MENUITEM "12.5 %", ID_IMAGEZOOM_12 - MENUITEM "25 %", ID_IMAGEZOOM_25 - MENUITEM "50 %", ID_IMAGEZOOM_50 - MENUITEM "100 %", ID_IMAGEZOOM_100 - MENUITEM "150 %", ID_IMAGEZOOM_150 - MENUITEM "200 %", ID_IMAGEZOOM_200 - MENUITEM "300 %", ID_IMAGEZOOM_300 - MENUITEM "400 %", ID_IMAGEZOOM_400 - MENUITEM "800 %", ID_IMAGEZOOM_800 - END - POPUP "Overlays" - BEGIN - MENUITEM "MCU Grid\tCtrl+G", ID_OVERLAYS_MCUGRID - END - MENUITEM "Adjust...", ID_VIEW_ADJUST - MENUITEM SEPARATOR - MENUITEM "&Toolbar", ID_VIEW_TOOLBAR - MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR - END - POPUP "&Tools" - BEGIN - MENUITEM "Image Search Fwd\tCtrl+2", ID_TOOLS_SEARCHFORWARD - MENUITEM "Image Search Rev\tCtrl+1", ID_TOOLS_SEARCHREVERSE - MENUITEM SEPARATOR - MENUITEM "Lookup MCU Offset...", ID_TOOLS_LOOKUPMCUOFFSET - MENUITEM "File Overlay...", ID_TOOLS_FILEOVERLAY - MENUITEM "Search Executable for DQT...", ID_TOOLS_SEARCHEXECUTABLEFORDQT - MENUITEM "Export JPEG...", ID_TOOLS_EXTRACTEMBEDDEDJPEG - MENUITEM "Export TIFF...", ID_TOOLS_EXPORTTIFF - MENUITEM SEPARATOR - MENUITEM "Add Camera/SW to DB...\tAlt+S", ID_TOOLS_ADDCAMERATODB - MENUITEM "Manage Local DB...", ID_TOOLS_MANAGELOCALDB - END - POPUP "&Options" - BEGIN - MENUITEM "DHT Expand", ID_OPTIONS_DHTEXPAND - MENUITEM "Hide Unknown EXIF Tags", ID_OPTIONS_HIDEUKNOWNEXIFTAGS - MENUITEM "Maker Notes", ID_OPTIONS_MAKERNOTES - MENUITEM "Signature Search", ID_OPTIONS_SIGNATURESEARCH - MENUITEM "Relaxed Parsing", ID_OPTIONS_RELAXEDPARSING - MENUITEM SEPARATOR - POPUP "Scan Segment" - BEGIN - MENUITEM "Decode Image", ID_SCANSEGMENT_DECODEIMAGE - MENUITEM SEPARATOR - MENUITEM "Full IDCT (AC+DC - slow)", ID_SCANSEGMENT_FULLIDCT - MENUITEM "No IDCT (DC only - fast)", ID_SCANSEGMENT_NOIDCT - MENUITEM SEPARATOR - MENUITEM "Histogram RGB", ID_SCANSEGMENT_HISTOGRAM - MENUITEM "Histogram Y", ID_SCANSEGMENT_HISTOGRAMY - MENUITEM SEPARATOR - MENUITEM "Dump", ID_SCANSEGMENT_DUMP - MENUITEM "Detailed Decode...", ID_SCANSEGMENT_DETAILEDDECODE - END - MENUITEM SEPARATOR - MENUITEM "Configuration...", ID_OPTIONS_CONFIGURATION - MENUITEM "Check for Updates...", ID_OPTIONS_CHECKFORUPDATES - END - POPUP "&Help" - BEGIN - MENUITEM "&About JPEGsnoop...", ID_APP_ABOUT - END -END - -IDR_CNTR_INPLACE MENU -BEGIN - POPUP "&File" - BEGIN - MENUITEM "&New\tCtrl+N", ID_FILE_NEW - MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN - MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE - MENUITEM "Save &As...", ID_FILE_SAVE_AS - MENUITEM SEPARATOR - MENUITEM "&Print...\tCtrl+P", ID_FILE_PRINT - MENUITEM "Print Pre&view", ID_FILE_PRINT_PREVIEW - MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP - MENUITEM SEPARATOR - MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED - MENUITEM SEPARATOR - MENUITEM "E&xit", ID_APP_EXIT - END - MENUITEM SEPARATOR - MENUITEM SEPARATOR -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Accelerator -// - -IDR_MAINFRAME ACCELERATORS -BEGIN - VK_ESCAPE, ID_CANCEL_EDIT_CNTR, VIRTKEY, NOINVERT - "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT - VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT - VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT - "X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT - "F", ID_EDIT_FIND, VIRTKEY, CONTROL, NOINVERT - "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT - VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT - VK_F3, ID_EDIT_REPEAT, VIRTKEY, NOINVERT - "H", ID_EDIT_REPLACE, VIRTKEY, CONTROL, NOINVERT - "A", ID_EDIT_SELECT_ALL, VIRTKEY, CONTROL, NOINVERT - VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT - "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT - "N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT - "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT - "P", ID_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT - "R", ID_FILE_REPROCESS, VIRTKEY, CONTROL, NOINVERT - "S", ID_FILE_SAVE_AS, VIRTKEY, CONTROL, NOINVERT - VK_OEM_PLUS, ID_IMAGEZOOM_ZOOMIN, VIRTKEY, CONTROL, NOINVERT - VK_OEM_MINUS, ID_IMAGEZOOM_ZOOMOUT, VIRTKEY, CONTROL, NOINVERT - VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT - VK_RETURN, ID_OLE_EDIT_PROPERTIES, VIRTKEY, ALT, NOINVERT - "G", ID_OVERLAYS_MCUGRID, VIRTKEY, CONTROL, NOINVERT - VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT - "5", ID_PREVIEW_B, VIRTKEY, ALT, NOINVERT - "7", ID_PREVIEW_CB, VIRTKEY, ALT, NOINVERT - "8", ID_PREVIEW_CR, VIRTKEY, ALT, NOINVERT - "4", ID_PREVIEW_G, VIRTKEY, ALT, NOINVERT - "3", ID_PREVIEW_R, VIRTKEY, ALT, NOINVERT - "1", ID_PREVIEW_RGB, VIRTKEY, ALT, NOINVERT - "6", ID_PREVIEW_Y, VIRTKEY, ALT, NOINVERT - "2", ID_PREVIEW_YCC, VIRTKEY, ALT, NOINVERT - "2", ID_TOOLS_SEARCHFORWARD, VIRTKEY, CONTROL, NOINVERT - "1", ID_TOOLS_SEARCHREVERSE, VIRTKEY, CONTROL, NOINVERT -END - -IDR_CNTR_INPLACE ACCELERATORS -BEGIN - "N", ID_FILE_NEW, VIRTKEY, CONTROL - "O", ID_FILE_OPEN, VIRTKEY, CONTROL - "S", ID_FILE_SAVE, VIRTKEY, CONTROL - "P", ID_FILE_PRINT, VIRTKEY, CONTROL - VK_F6, ID_NEXT_PANE, VIRTKEY - VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT - VK_ESCAPE, ID_CANCEL_EDIT_CNTR, VIRTKEY, NOINVERT -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_ABOUTBOX DIALOGEX 0, 0, 242, 94 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "About JPEGsnoop" -FONT 8, "MS Shell Dlg", 0, 0, 0x1 -BEGIN - ICON IDR_MAINFRAME,IDC_STATIC,12,6,20,20 - LTEXT "JPEGsnoop",IDC_STATIC,42,6,39,8,SS_NOPREFIX - LTEXT "Copyright © 2017 Calvin Hass",IDC_STATIC,42,18,124,8 - DEFPUSHBUTTON "OK",IDOK,185,7,50,16,WS_GROUP - LTEXT "www.impulseadventure.com/photo/",IDC_URL,24,66,117,8 - LTEXT "Documentation and Updates for JPEGsnoop",IDC_URL_DOC,24,48,169,8 - LTEXT "Version",IDC_VER_NUM,96,6,86,10 - GROUPBOX "",IDC_STATIC,12,36,222,54 -END - -IDD_DBSUBMITDLG DIALOGEX 0, 0, 397, 180 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Submit Compression Signature to Database" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,340,7,50,16 - PUSHBUTTON "Cancel",IDCANCEL,340,26,50,16 - EDITTEXT IDC_QUAL,258,12,66,14,ES_AUTOHSCROLL - CONTROL "Direct from Camera",IDC_RADIO_CAM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,228,84,76,10 - CONTROL "Edited / Processed by Software",IDC_RADIO_SW,"Button",BS_AUTORADIOBUTTON,228,96,116,10 - EDITTEXT IDC_USER_SOFTWARE,276,108,108,14,ES_AUTOHSCROLL - CONTROL "I really don't know where it came from",IDC_RADIO_UNKNOWN, - "Button",BS_AUTORADIOBUTTON,228,126,138,10 - EDITTEXT IDC_NOTES,126,150,138,14,ES_AUTOHSCROLL - EDITTEXT IDC_MAKE,78,12,96,14,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_MODEL,78,30,96,14,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_SOFTWARE,78,48,96,14,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_SIG,48,72,150,14,ES_AUTOHSCROLL | ES_READONLY - LTEXT "e.g. superfine, normal, 70, 10, high, etc. For software, the save quality setting.",IDC_STATIC,198,30,125,17 - LTEXT "Camera / Software Quality Setting:",IDC_STATIC,186,12,66,18 - LTEXT "NOTE: Clicking OK will send compression signature (not the photo or any other information) to your local user database file and the ImpulseAdventure database used for JPEGsnoop to authenticate new digital cameras.",IDC_STATIC,6,96,186,42 - LTEXT "EXIF Make:",IDC_STATIC,6,12,38,8 - LTEXT "EXIF Model:",IDC_STATIC,6,30,40,8 - LTEXT "Signature:",IDC_STATIC,6,72,42,8 - LTEXT "EXIF Software:",IDC_STATIC,6,48,48,8 - LTEXT "Software:",IDC_STATIC,240,108,31,8 - GROUPBOX "This file is:",IDC_STATIC,216,72,174,71 - LTEXT "Any other notes about this file:",IDC_STATIC,18,150,96,8 -END - -IDD_OVERLAYBUFDLG DIALOGEX 0, 0, 376, 138 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "File Overlay Test" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,318,6,50,16 - PUSHBUTTON "Cancel",IDCANCEL,318,25,50,16 - EDITTEXT IDC_OVRPOS,84,30,78,14,ES_AUTOHSCROLL - EDITTEXT IDC_OVRNEW,42,102,178,14,ES_AUTOHSCROLL - LTEXT "Current value",IDC_OVRCUR,42,60,318,8 - PUSHBUTTON "Load Original",IDC_OVR_LOAD,172,30,50,14 - LTEXT "File Offset:",IDC_STATIC,18,30,53,8 - LTEXT "(Hex):",IDC_STATIC,18,60,24,8 - LTEXT "(Hex):",IDC_STATIC,18,102,24,8 - EDITTEXT IDC_OVRLEN,318,102,40,14,ES_AUTOHSCROLL | ES_NUMBER - LTEXT "Len (bytes)",IDC_STATIC,270,102,42,8 - CONTROL "Overlay Enabled?",IDC_OVREN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,12,72,10 - LTEXT "Current value",IDC_OVRCURBIN,42,73,318,8 - LTEXT "(Bin):",IDC_STATIC,18,73,24,8 - GROUPBOX "Original Data in Overlay Region",IDC_STATIC,6,48,360,36 - GROUPBOX "New Values for Overlay Region",IDC_STATIC,6,90,360,36 - PUSHBUTTON "Apply",IDC_APPLY,264,6,50,14 -END - -IDD_LOOKUP DIALOGEX 0, 0, 247, 78 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Lookup File Offset of MCU" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,190,7,50,14 - PUSHBUTTON "Cancel",IDCANCEL,190,24,50,14 - EDITTEXT IDC_X,27,27,40,14,ES_AUTOHSCROLL - EDITTEXT IDC_Y,89,27,40,14,ES_AUTOHSCROLL - LTEXT "X=",IDC_STATIC,15,27,10,8 - LTEXT "Y=",IDC_STATIC,77,27,10,8 - LTEXT "Pixels",IDC_STATIC,135,27,19,8 - LTEXT "File Offset:",IDC_STATIC,15,49,37,8 - PUSHBUTTON "Recalc",IDC_BTN_CALC,126,49,50,14 - LTEXT "Range",IDC_RNGX,27,14,41,8 - LTEXT "Range",IDC_RNGY,89,14,41,8 - RTEXT "Not Calculated",IDC_OFFSET,55,49,61,11,SS_SUNKEN -END - -IDD_OFFSETDLG DIALOGEX 0, 0, 263, 54 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Starting File Offset" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,206,7,50,14 - CONTROL "Decimal",IDC_BASED,"Button",BS_AUTORADIOBUTTON,69,28,40,10 - CONTROL "Hex",IDC_BASEH,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,69,14,29,10 - EDITTEXT IDC_OFFSETVAL,117,17,82,14,ES_AUTOHSCROLL - PUSHBUTTON "Cancel",IDCANCEL,206,24,50,14 - LTEXT "Offset (Bytes):",IDC_STATIC,14,15,50,8 -END - -IDD_SETTINGSDLG DIALOGEX 0, 0, 316, 217 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "JPEGsnoop Configuration" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - EDITTEXT IDC_DB_DIR,30,20,126,14,ES_AUTOHSCROLL - CONTROL "Automatically check for updates",IDC_UPDATE_CHK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,66,126,10 - EDITTEXT IDC_UPDATE_CHK_DAYS,168,66,24,14,ES_AUTOHSCROLL - CONTROL "Auto Reprocess files on change in Options (slower)",IDC_REPROCESS_AUTO, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,102,209,10 - CONTROL "Submit signature to Online DB when User submit",IDC_DBSUBMIT_NET, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,114,210,10 - EDITTEXT IDC_RPTERRMAX_SCANDECODE,150,150,40,12,ES_AUTOHSCROLL - LTEXT "Coach Messages can be re-enabled:",IDC_STATIC,12,186,125,8 - PUSHBUTTON "Reset",IDC_COACH_RESET,132,180,50,14 - DEFPUSHBUTTON "Save",IDOK,258,6,50,16 - PUSHBUTTON "Cancel",IDCANCEL,258,25,50,16 - LTEXT "Max # errors to report in Scan Decode",IDC_STATIC,12,150,138,8 - PUSHBUTTON "Browse",IDC_DB_DIR_BROWSE,159,17,50,10 - PUSHBUTTON "Default",IDC_DB_DIR_DEFAULT,159,28,50,10 - GROUPBOX "Directory for User Database",IDC_STATIC,6,6,228,42 - GROUPBOX "Software Updates",IDC_STATIC,6,54,228,30 - LTEXT "... every",IDC_STATIC,138,66,26,8 - LTEXT "days",IDC_STATIC,198,66,16,8 - GROUPBOX "Processing Options",IDC_STATIC,6,90,228,42 - GROUPBOX "Help",IDC_STATIC,6,174,228,30 - GROUPBOX "Report Settings",IDC_STATIC,6,138,228,30 -END - -IDD_TERMSDLG DIALOGEX 0, 0, 348, 220 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "JPEGsnoop License Agreement" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,291,7,50,16 - PUSHBUTTON "EXIT",IDCANCEL,291,26,50,16 - EDITTEXT IDC_EULA,25,55,252,78,ES_MULTILINE | ES_READONLY | WS_VSCROLL - CONTROL "I have read and agree to the terms above",IDC_EULA_OK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,137,165,10 - CONTROL "Automatically check for updates",IDC_UPDATE_AUTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,175,168,10 - LTEXT "You can always change this option later in Configuration",IDC_STATIC,37,186,181,8 - CTEXT "Welcome to JPEGsnoop!",IDC_STATIC,95,17,118,12,SS_CENTERIMAGE | SS_SUNKEN - GROUPBOX "Software Updates:",IDC_STATIC,15,162,270,41 - GROUPBOX "Software Agreement:",IDC_STATIC,15,44,270,109 -END - -IDD_UPDATEAVAILDLG DIALOGEX 0, 0, 314, 99 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "New Update Available!" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,257,7,50,16 - PUSHBUTTON "Cancel",IDCANCEL,257,26,50,16 - LTEXT "A newer version of JPEGsnoop is available for download!",IDC_STATIC,6,12,191,8 - LTEXT "Current Version:",IDC_STATIC,18,29,51,8 - LTEXT "Latest Version:",IDC_STATIC,18,48,48,8 - LTEXT "cur",IDC_VER_CUR,78,29,60,8 - LTEXT "latest",IDC_VER_LATEST,78,48,60,8 - PUSHBUTTON "Download Page",IDC_BUTTON1,151,49,84,14 - CONTROL "Continue to check for new updates in the future",IDC_UPDATE_AUTO_STILL, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,39,73,174,10 - LTEXT "Released on:",IDC_STATIC,18,58,46,8 - LTEXT "date",IDC_DATE_LATEST,78,58,55,8 -END - -IDD_MODELESSDLG DIALOGEX 0, 100, 259, 43 -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Checking for Updates" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - LTEXT "Checking ImpulseAdventure.com for JPEGsnoop updates ...",IDC_STATIC,29,16,198,8 -END - -IDD_NOTEDLG DIALOGEX 0, 0, 369, 73 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "JPEGsnoop - Note" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,312,7,50,16 - LTEXT "msg",IDC_MSG,6,6,285,27,SS_SUNKEN - CONTROL "In the future, do not show this message",IDC_COACH_OFF, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,42,151,10 - LTEXT "NOTE: You can always re-enable coach messages in Configuration",IDC_STATIC,30,54,225,8 -END - -IDD_DBMANAGEDLG DIALOGEX 0, 0, 405, 132 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Manage User Database" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,348,7,50,16 - PUSHBUTTON "Cancel",IDCANCEL,348,26,50,16 - LISTBOX IDC_LIST,6,6,332,96,LBS_USETABSTOPS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Remove",IDC_REMOVE,6,108,50,14 - PUSHBUTTON "Remove All",IDC_REMOVEALL,66,108,50,14 -END - -IDD_EXPORTDLG DIALOGEX 0, 0, 290, 126 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Export JPEG Settings" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,233,7,50,16 - PUSHBUTTON "Cancel",IDCANCEL,233,26,50,16 - CONTROL "Enable Overlays (Slower)",IDC_OVERLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,36,120,10 - CONTROL "Insert MJPEG DHT (for AVI Frame export)",IDC_DHTAVI, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,54,150,10 - LTEXT "Source file start offset:",IDC_STATIC,12,6,84,8 - LTEXT "Offset",IDC_OFFSET_START,102,6,48,8 - CONTROL "Missing EOI: Force EOI",IDC_FORCE_EOI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,78,150,10 - GROUPBOX "Settings",IDC_STATIC,6,24,216,90 - CONTROL "Missing EOI: Ignore",IDC_IGNORE_EOI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,90,96,10 - CONTROL "Missing SOI: Force SOI",IDC_FORCE_SOI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,66,150,10 - CONTROL "Extract All JPEGs",IDC_EXT_ALL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,138,36,78,10 -END - -IDD_DECODEDETAILDLG DIALOGEX 0, 0, 262, 121 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Detailed Scan Decode Options" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,204,6,50,16 - PUSHBUTTON "Cancel",IDCANCEL,204,25,50,16 - EDITTEXT IDC_EDIT1,54,18,40,14,ES_AUTOHSCROLL - EDITTEXT IDC_EDIT2,138,18,40,14,ES_AUTOHSCROLL - EDITTEXT IDC_EDIT3,54,60,40,14,ES_AUTOHSCROLL - RTEXT "MCU X =",IDC_STATIC,18,18,30,8 - RTEXT "MCU Y =",IDC_STATIC,102,18,30,8 - RTEXT "# MCUs =",IDC_STATIC,18,60,33,8 - GROUPBOX "Starting MCU for Decode",IDC_STATIC,6,6,186,36 - GROUPBOX "Length of Decode",IDC_STATIC,6,48,186,36 - CONTROL "Enable detailed Scan Decode?",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,90,114,10 - LTEXT "Detailed Scan Decode will be reported in the next decode operation",IDC_STATIC,18,102,228,8 - PUSHBUTTON "Load Coords",IDC_BTN_LOAD,204,72,50,14 - LTEXT "Load X/Y/Len from last 2 clicks:",IDC_STATIC,198,48,54,18 -END - -IDD_EXPORTTIFFDLG DIALOGEX 0, 0, 256, 108 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Export as TIFF" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,198,6,50,16 - PUSHBUTTON "Cancel",IDCANCEL,198,25,50,16 - CONTROL "RGB (8 bit)",IDC_RAD_RGB8,"Button",BS_AUTORADIOBUTTON | WS_GROUP,24,54,72,10 - CONTROL "RGB (16 bit)",IDC_RAD_RGB16,"Button",BS_AUTORADIOBUTTON,24,66,72,10 - CONTROL "YCC (8 bit)",IDC_RAD_YCC8,"Button",BS_AUTORADIOBUTTON,24,79,72,10 - GROUPBOX "Output Format",IDC_STATIC,12,36,90,60 - LTEXT "Save Filename:",IDC_STATIC,12,12,54,8 - EDITTEXT IDC_EDIT_FNAME,66,12,120,14,ES_AUTOHSCROLL | ES_READONLY -END - -IDD_BATCHDLG DIALOGEX 0, 0, 249, 146 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Batch Processing" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,174,102,50,16 - PUSHBUTTON "Cancel",IDCANCEL,174,121,50,16 - CONTROL "Process subdirectories?",IDC_CHECK_SUBDIRS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,42,110,98,10 - LTEXT "Input Image Directory:",IDC_STATIC,12,36,72,8 - LTEXT "NOTE 1: Recommend for use on backup copy of files only",IDC_STATIC,6,6,186,8 - LTEXT "NOTE 2: For faster operation, disable ""Decode Image"" before use",IDC_STATIC,6,18,210,8 - CONTROL "Extract all JPEGs",IDC_CHECK_EXT_ALL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,42,121,90,10 - PUSHBUTTON "...",IDC_BTN_DIR_SRC_BROWSE,204,48,18,14 - EDITTEXT IDC_EDIT_DIR_SRC,24,48,180,14,ES_AUTOHSCROLL - EDITTEXT IDC_EDIT_DIR_DST,24,78,180,14,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_BTN_DIR_DST_BROWSE,204,78,18,14 - LTEXT "Output Log Directory:",IDC_STATIC,12,66,72,8 -END - -IDD_OPERATIONDLG DIALOGEX 0, 0, 186, 73 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Operation Progress" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "Abort",ID_BTN_ABORT,66,48,50,14 - CONTROL "",IDC_PROGRESS_BAR,"msctls_progress32",WS_BORDER,6,6,174,14 - CTEXT "Progress: ddd of ddd",IDC_STATIC_PROGRESS,6,24,174,12,SS_SUNKEN -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,8,0,0 - PRODUCTVERSION 1,8,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "ImpulseAdventure" - VALUE "FileDescription", "JPEGsnoop" - VALUE "FileVersion", "1.8.0.0" - VALUE "InternalName", "JPEGsnoop.exe" - VALUE "LegalCopyright", "(c) 2017 Calvin Hass. All rights reserved." - VALUE "OriginalFilename", "JPEGsnoop.exe" - VALUE "ProductName", "JPEGsnoop" - VALUE "ProductVersion", "1.8.0.0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_ABOUTBOX, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 235 - TOPMARGIN, 7 - BOTTOMMARGIN, 87 - END - - IDD_DBSUBMITDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 390 - TOPMARGIN, 7 - BOTTOMMARGIN, 173 - END - - IDD_OVERLAYBUFDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 369 - TOPMARGIN, 7 - BOTTOMMARGIN, 131 - END - - IDD_LOOKUP, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 240 - TOPMARGIN, 7 - BOTTOMMARGIN, 71 - END - - IDD_OFFSETDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 256 - TOPMARGIN, 7 - BOTTOMMARGIN, 47 - END - - IDD_SETTINGSDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 309 - TOPMARGIN, 7 - BOTTOMMARGIN, 210 - END - - IDD_TERMSDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 341 - TOPMARGIN, 7 - BOTTOMMARGIN, 213 - END - - IDD_UPDATEAVAILDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 307 - TOPMARGIN, 7 - BOTTOMMARGIN, 92 - END - - IDD_MODELESSDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 252 - TOPMARGIN, 7 - BOTTOMMARGIN, 36 - END - - IDD_NOTEDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 362 - TOPMARGIN, 7 - BOTTOMMARGIN, 66 - END - - IDD_DBMANAGEDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 398 - TOPMARGIN, 7 - BOTTOMMARGIN, 125 - END - - IDD_EXPORTDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 283 - TOPMARGIN, 7 - BOTTOMMARGIN, 119 - END - - IDD_DECODEDETAILDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 255 - TOPMARGIN, 7 - BOTTOMMARGIN, 114 - END - - IDD_EXPORTTIFFDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 249 - TOPMARGIN, 7 - BOTTOMMARGIN, 101 - END - - IDD_BATCHDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 242 - TOPMARGIN, 7 - BOTTOMMARGIN, 139 - END - - IDD_OPERATIONDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 179 - TOPMARGIN, 7 - BOTTOMMARGIN, 66 - END -END -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN - IDR_MAINFRAME "JPEGsnoop\nUntitled\nJPEGsnoop\nJPEG Image/Video (*.jpg;*.jpeg;*.avi;*.mov)\n.jpg;.jpeg;.avi;.mov\nJPEGsnoop.Document\nJPEGsnoop.Document" - IDR_MAINFRAME_BAK "JPEGsnoop\n\nJPEGsnoop\n\n\nJPEGsnoop.Document\nJPEGsnoop.Document" - IDR_TEST1TYPE "Test1\test1 File\nTest1 Files(*.ts1)\n.ts1\nts1\nTest1" - IDR_TEST2TYPE "Test2\test2 File\nTest2 Files(*.ts2)\n.ts2\nts2\nTest2" - IDR_MAINFRAME2 "JPEGsnoop\nUntitled\nJPEGsnoop\nJPEG Files (*.jpg)\n.jpg\nJPEGsnoop.Document\nJPEGsnoop.Document" - IDR_MAINFRAME3 "JPEGsnoop\nUntitled\nJPEGsnoop\nJPEG Image (*.jpg;*.jpeg)\n.jpg;.jpeg\nJPEGsnoop.Document\nJPEGsnoop.Document" - IDR_MAINFRAME_AVI "JPEGsnoop\nUntitled\nJPEGsnoop\nAVI Movie (*.avi)\n.avi\nJPEGsnoop.Document\nJPEGsnoop.Document" - IDR_MAINFRAME_ALL "JPEGsnoop\nUntitled\nJPEGsnoop\nJPEG Image (*.jpg;*.jpeg)\n.jpg;.jpeg\nJPEGsnoop.Document\nJPEGsnoop.Document" - ID_INDICATOR_YCC "YCC DC=[00000,00000,00000]" - IDS_CAL_FILEOPEN "Open Image / Video file" - IDS_CAL_FILESAVE "Save JPEGsnoop Log File" - ID_INDICATOR_MCU "MCU [0000,0000]" - ID_INDICATOR_FILEPOS "File: 0x00000000:0" -END - -STRINGTABLE -BEGIN - AFX_IDS_APP_TITLE "JPEGsnoop" - AFX_IDS_IDLEMESSAGE "Ready" -END - -STRINGTABLE -BEGIN - ID_INDICATOR_EXT "EXT" - ID_INDICATOR_CAPS "CAP" - ID_INDICATOR_NUM "NUM" - ID_INDICATOR_SCRL "SCRL" - ID_INDICATOR_OVR "OVR" - ID_INDICATOR_REC "REC" -END - -STRINGTABLE -BEGIN - ID_FILE_NEW "Create a new document\nNew" - ID_FILE_OPEN "Open an existing document\nOpen" - ID_FILE_CLOSE "Close the active document\nClose" - ID_FILE_SAVE "Save the active document\nSave" - ID_FILE_SAVE_AS "Save the log output\nSave Log" - ID_FILE_PAGE_SETUP "Change the printing options\nPage Setup" - ID_FILE_PRINT_SETUP "Change the printer and printing options\nPrint Setup" - ID_FILE_PRINT "Print the active log\nPrint" - ID_FILE_PRINT_PREVIEW "Display full pages\nPrint Preview" -END - -STRINGTABLE -BEGIN - ID_APP_ABOUT "About JPEGsnoop\nAbout" - ID_APP_EXIT "Quit JPEGsnoop\nExit" -END - -STRINGTABLE -BEGIN - ID_FILE_MRU_FILE1 "Open this file" - ID_FILE_MRU_FILE2 "Open this document" - ID_FILE_MRU_FILE3 "Open this document" - ID_FILE_MRU_FILE4 "Open this document" - ID_FILE_MRU_FILE5 "Open this document" - ID_FILE_MRU_FILE6 "Open this document" - ID_FILE_MRU_FILE7 "Open this document" - ID_FILE_MRU_FILE8 "Open this document" - ID_FILE_MRU_FILE9 "Open this document" - ID_FILE_MRU_FILE10 "Open this document" - ID_FILE_MRU_FILE11 "Open this document" - ID_FILE_MRU_FILE12 "Open this document" - ID_FILE_MRU_FILE13 "Open this document" - ID_FILE_MRU_FILE14 "Open this document" - ID_FILE_MRU_FILE15 "Open this document" - ID_FILE_MRU_FILE16 "Open this document" -END - -STRINGTABLE -BEGIN - ID_NEXT_PANE "Switch to the next window pane\nNext Pane" - ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane" -END - -STRINGTABLE -BEGIN - ID_WINDOW_SPLIT "Split the active window into panes\nSplit" -END - -STRINGTABLE -BEGIN - ID_EDIT_CLEAR "Erase the selection\nErase" - ID_EDIT_CLEAR_ALL "Erase everything\nErase All" - ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy" - ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut" - ID_EDIT_FIND "Find the specified text\nFind" - ID_EDIT_PASTE "Insert Clipboard contents\nPaste" - ID_EDIT_PASTE_LINK "Insert Clipboard contents and a link to its source\nPaste Link" - ID_EDIT_PASTE_SPECIAL "Insert Clipboard contents with options\nPaste Special" - ID_EDIT_REPEAT "Repeat the last action\nRepeat" - ID_EDIT_REPLACE "Replace specific text with different text\nReplace" - ID_EDIT_SELECT_ALL "Select the entire document\nSelect All" - ID_EDIT_UNDO "Undo the last action\nUndo" - ID_EDIT_REDO "Redo the previously undone action\nRedo" -END - -STRINGTABLE -BEGIN - ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar" - ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar" -END - -STRINGTABLE -BEGIN - ID_OLE_INSERT_NEW "Insert new embedded object\nNew Object" - ID_OLE_EDIT_LINKS "Edit linked objects\nEdit Links" - ID_OLE_EDIT_CONVERT "Convert object to different type\nConvert Object" -END - -STRINGTABLE -BEGIN - ID_OLE_VERB_FIRST "Activate embedded or linked object" - 57873 "Activate embedded or linked object" - 57874 "Activate embedded or linked object" - 57875 "Activate embedded or linked object" -END - -STRINGTABLE -BEGIN - AFX_IDS_SCSIZE "Change the window size" - AFX_IDS_SCMOVE "Change the window position" - AFX_IDS_SCMINIMIZE "Reduce the window to an icon" - AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" - AFX_IDS_SCNEXTWINDOW "Switch to the next document window" - AFX_IDS_SCPREVWINDOW "Switch to the previous document window" - AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" -END - -STRINGTABLE -BEGIN - AFX_IDS_SCRESTORE "Restore the window to normal size" - AFX_IDS_SCTASKLIST "Activate Task List" -END - -STRINGTABLE -BEGIN - AFX_IDS_SAVEFILECOPY "Save Log File..." - AFX_IDS_PREVIEW_CLOSE "Close print preview mode\nCancel Preview" -END - -STRINGTABLE -BEGIN - ID_TOOLS_DECODE "Test decode" - ID_FILE_OFFSET "Start processing at an offset\nOffset" - 32773 "Search for next Image\nSearch Fwd" - 32774 "Search for previous Image\nSearch Rev" - 32775 "Calculate file offset for an MCU\nMCU Lookup" - 32776 "Test modification to file with Overlay\nOverlay" - 32777 "Detailed decode of scan segment\nDetailed Scan" - 32778 "Update database with compression signature\nAdd Sig" - ID_OPTIONS_DHTEXPAND "Dump expanded DHT Tables\nDHT Expand" - ID_OPTIONS_MAKERNOTES "Dump Makernotes\nMakernotes" - ID_OPTIONS_SCANDUMP "Hex dump of scan data\nDump Scan" -END - -STRINGTABLE -BEGIN - IDS_CAL_EXE_OPEN "Open Executable file for Search" -END - -STRINGTABLE -BEGIN - ID_OPTIONS_HISTOYDUMP "Display Luminance Histogram\nHisto Y" - ID_FILE_REPROCESS "Reprocess the current file\nReprocess" - ID_OPTIONS_DECODESCAN "Process Scan Segment, Display Image\nScan Image" - ID_OPTIONS_CONFIGURATION "Change configuration options\nConfig" - ID_OPTIONS_CHECKFORUPDATES "Check internet for updates\nUpdates" -END - -STRINGTABLE -BEGIN - ID_TOOLS_SEARCHEXECUTABLEFORDQT "Find DQT Table in Executable\nFind DQT" - ID_TOOLS_MANAGELOCALDB "Manage the local User signatures\nManage Sigs" - ID_OPTIONS_SIGNATURESEARCH - "Search for matching compression sigantures\nSig Search" - ID_OPTIONS_DECODEAC "Enable AC (IDCT) in Scan Decode" - ID_SCANSEGMENT_DECODEIMAGE "Enable Decode of Scan Image\nScan Decode" - ID_SCANSEGMENT_FULLIDCT "Enable full-res IDCT image (DC + AC components)\nFull Res" - ID_SCANSEGMENT_HISTOGRAMY - "Calc and display Histogram of Luminance (Y)\nHisto Y" - ID_SCANSEGMENT_DUMP "Dump hex of start of Scan Segment\nScan Dump" -END - -STRINGTABLE -BEGIN - 32800 "Show RGB channel\nRGB" - 32801 "Show YCC channel\nYCC" - 32802 "Show Red channel\nRed" - 32803 "Show Green channel\nGreen" - 32804 "Show Blue channel\nBlue" - 32805 "Show Luminance channel\nY" - 32806 "Show Chrominance (Cb) channel\nCb" - 32807 "Show Chrominance (Cr) channel\nCr" - 32808 "Increase Image View Zoom\nZoom In" - 32809 "Decrease Image View Zoom\nZoom Out" - 32810 "Set Image View zoom to 100%\n100%" - 32811 "Set Image View zoom to 150%\n150%" - 32812 "Set Image View zoom to 200%\n200%" - 32813 "Set Image View zoom to 300%\n300%" - 32814 "Set Image View zoom to 400%\n400%" - 32815 "Set Image View zoom to 800%\n800%" -END - -STRINGTABLE -BEGIN - ID_SCANSEGMENT_NOIDCT "No decode (DC component only)\nLow Res" - ID_OVERLAYS_MCUGRID "Display MCU Boundary grid\nMCU Grid" -END - -STRINGTABLE -BEGIN - ID_IMAGEZOOM_ZOOMIN "Zoom In\nZoom In" - ID_IMAGEZOOM_ZOOMOUT "Zoom Out\nZoom Out" - ID_IMAGEZOOM_12 "Zoom 12.5%\nZoom 12.5%" - ID_IMAGEZOOM_25 "Zoom 25%\nZoom 25%" - ID_IMAGEZOOM_50 "Zoom 50%\nZoom 50%" - ID_IMAGEZOOM_100 "Zoom 100%\nZoom 100%" - ID_IMAGEZOOM_150 "Zoom 150%\nZoom 150%" - ID_IMAGEZOOM_200 "Zoom 200%\nZoom 200%" - ID_IMAGEZOOM_300 "Zoom 300%\nZoom 300%" - ID_IMAGEZOOM_400 "Zoom 400%\nZoom 400%" - ID_IMAGEZOOM_800 "Zoom 800%\nZoom 800%" -END - -STRINGTABLE -BEGIN - ID_TOOLS_DETAILEDSCANDECODE "Report detailed VLC decode\nDetailed Scan" - ID_SCANSEGMENT_DETAILEDDECODE - "Detailed decode of Scan Data\nDetail Decode" - ID_SCANSEGMENT_HISTOGRAM "Calc and display RGB Histograms\nHisto RGB" -END - -STRINGTABLE -BEGIN - ID_OPTIONS_HIDEUKNOWNEXIFTAGS "Hide Unknown EXIF Tags\nEXIF Tags" - ID_FILE_BATCHPROCESS "Start batch processing" -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// -//CAL! #define _AFX_NO_SPLITTER_RESOURCES -#define _AFX_NO_OLE_RESOURCES -#define _AFX_NO_TRACKER_RESOURCES -#define _AFX_NO_PROPERTY_RESOURCES - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE 9, 1 -#pragma code_page(1252) -#include "res\JPEGsnoop.rc2" // non-Microsoft Visual C++ edited resources -#include "afxres.rc" // Standard components -#include "afxprint.rc" // printing/print preview resources -#include "afxolecl.rc" // OLE container resources -#endif - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/source/JPEGsnoopCore.cpp b/source/JPEGsnoopCore.cpp deleted file mode 100644 index 50d3594..0000000 --- a/source/JPEGsnoopCore.cpp +++ /dev/null @@ -1,1495 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include - -//#include "stdafx.h" -#include "JPEGsnoopCore.h" - -// For glb_pDocLog -#include "JPEGsnoop.h" - -CJPEGsnoopCore::CJPEGsnoopCore(void) -{ - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Begin"); - // Initialize processing classes - - // Save a local copy of the config struct pointer -//@@ m_pAppConfig = theApp.m_pAppConfig; - - // Ensure the local log isn't linked to a CDocument -// glb_pDocLog->SetDoc(NULL); - - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 1"); - - // Allocate the file window buffer - m_pWBuf = new CwindowBuf(); - - if(!m_pWBuf) - { - msgBox.setText("ERROR: Not enough memory for File Buffer"); - exit(1); - } - - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 2"); - - // Allocate the JPEG decoder -// m_pImgDec = new CimgDecode(glb_pDocLog, m_pWBuf); - - if(!m_pWBuf) - { - msgBox.setText("ERROR: Not enough memory for Image Decoder"); - exit(1); - } - - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 3"); - - m_pJfifDec = new CjfifDecode(glb_pDocLog, m_pWBuf, m_pImgDec); - - if(!m_pWBuf) - { - msgBox.setText("ERROR: Not enough memory for JFIF Decoder"); - exit(1); - } - - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 4"); - - // Reset all members - Reset(); - - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() Checkpoint 5"); - - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::CJPEGsnoopCore() End"); -} - -CJPEGsnoopCore::~CJPEGsnoopCore(void) -{ - if(m_pJfifDec != NULL) - { - delete m_pJfifDec; - m_pJfifDec = NULL; - } - - if(m_pWBuf != NULL) - { - delete m_pWBuf; - m_pWBuf = NULL; - } - - if(m_pImgDec != NULL) - { - delete m_pImgDec; - m_pImgDec = NULL; - } -} - -// Reset all state -void CJPEGsnoopCore::Reset() -{ - // Reset all members - m_pFile = NULL; - m_lFileSize = 0L; - m_strPathName = ""; - - // No log data available until we open & process a file - m_bFileOpened = false; - m_bFileAnalyzed = false; - - // FIXME: Should we be calling Reset on the JfifDecoder, ImgDecoder and WBuf? - - // Indicate to JFIF ProcessFile() that document has changed - // and that the scan decode needs to be redone if it - // is to be displayed. - m_pJfifDec->ImgSrcChanged(); - - // Clean up the quick log - glb_pDocLog->Clear(); -} - -void CJPEGsnoopCore::SetStatusBar(QStatusBar * pStatBar) -{ - // Save a copy of the status bar - //xxx m_pStatBar = pStatBar; - - // Now update the JFIF decoder and Image Decoder with the - // revised status bar pointer (or NULL) - m_pJfifDec->SetStatusBar(pStatBar); - m_pImgDec->SetStatusBar(pStatBar); -} - -// -// Has a file been analyzed previously? -// - This indicator is used extensively in the CJPEGsnoopDoc -// to determine whether menu items are enabled or not -// -bool CJPEGsnoopCore::IsAnalyzed() -{ - return m_bFileAnalyzed; -} - -// Open the file named in m_strPathName -// - Close / cleanup if another file was already open -// -// INPUT: -// - strFname = File to open -// -// POST: -// - m_pFile -// - m_lFileSize -// - m_pWBuf loaded -// -// RETURN: -// - Indicates if file open was successful -// -bool CJPEGsnoopCore::AnalyzeOpen() -{ - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeOpen() Begin"); - - Q_ASSERT(m_strPathName != ""); - - if(m_strPathName == "") - { - // Force dialog box to show as this is a major error - // TODO: Handle non-GUI mode - msgBox.setText("ERROR: AnalyzeOpen() but m_strPathName empty"); - return false; - } - - // Clean up if a file is already open - if(m_pFile != NULL) - { - // Mark previous buffer as closed - m_pWBuf->BufFileUnset(); - m_pFile->close(); - delete m_pFile; - - m_pFile = NULL; - m_lFileSize = 0L; - } - - // Open specified file - // Added in shareDenyNone as this apparently helps resolve some people's troubles - // with an error showing: Couldn't open file "Sharing Violation" - - m_pFile = new QFile(m_strPathName); - - if(m_pFile->open(QIODevice::ReadOnly) == false) - { - QString strError; - - // Note: msg includes m_strPathName - strError = QString("ERROR: Couldn't open file: [%1]").arg(m_strPathName); - glb_pDocLog->AddLineErr(strError); - - if(m_pAppConfig->bInteractive) - { - msgBox.setText(strError); - msgBox.exec(); - } - - m_pFile = NULL; - - return false; - } - - // Set the file size variable - m_lFileSize = m_pFile->size(); - - // Don't attempt to load buffer with zero length file! - if(m_lFileSize == 0) - { - return true; - } - - // Open up the buffer - m_pWBuf->BufFileSet(m_pFile); - m_pWBuf->BufLoadWindow(0); - - // Mark file as opened - m_bFileOpened = true; - - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeOpen() End"); - - return true; -} - -// Close the current file -// - Invalidate the buffer -// -// POST: -// - m_bFileOpened -// -void CJPEGsnoopCore::AnalyzeClose() -{ - // Indicate no file is currently opened - // Note that we don't clear m_bFileAnalyzed as the last - // decoder state is still available - m_bFileOpened = false; - - // Close the buffer window - m_pWBuf->BufFileUnset(); - - // Now that we've finished parsing the file, close it! - if(m_pFile != NULL) - { - m_pFile->close(); - delete m_pFile; - - m_pFile = NULL; - } -} - -// Perform the file analysis -// - Output the log header text -// - Process the current file via ProcessFile() -// - Dump the output to the log (if in QuickLog mode) -// -// PRE: -// - m_strPathname -// -// PRE: -// - m_bFileOpened -// - m_pFile -// - m_pJfifDec -// - m_pImgDec -// - m_lFileSize -// - m_pAppConfig->nPosStart = Starting file offset for decode -// -// POST: -// - m_bFileAnalyzed -// -void CJPEGsnoopCore::AnalyzeFileDo() -{ - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeFileDo() Checkpoint 1"); - - // Ensure file was already opened - Q_ASSERT(m_pFile); - Q_ASSERT(m_bFileOpened); - - // Reset the analyzed state in case this file is invalid (eg. zero length) - m_bFileAnalyzed = false; - - // Start in Quick mode (probably don't care for command-line mode) -// glb_pDocLog->SetQuickMode(true); - - // Clear the document log - glb_pDocLog->Clear(); - - QString strTmp; - - glb_pDocLog->AddLine(""); - strTmp = QString("JPEGsnoop %1 by Calvin Hass").arg(QString(VERSION_STR)); - glb_pDocLog->AddLine(strTmp); - glb_pDocLog->AddLine(" http://www.impulseadventure.com/photo/"); - glb_pDocLog->AddLine(" -------------------------------------"); - glb_pDocLog->AddLine(""); - strTmp = QString(" Filename: [%1]").arg(m_strPathName); - glb_pDocLog->AddLine(strTmp); - strTmp = QString(" Filesize: [%1] bytes").arg(m_lFileSize); - glb_pDocLog->AddLine(strTmp); - glb_pDocLog->AddLine(""); - - // Perform the actual decoding - if(m_lFileSize > 0xFFFFFFFFULL) - { - strTmp = QString("ERROR: File too large for this version of JPEGsnoop. [Size=0x%1]").arg(m_lFileSize); - glb_pDocLog->AddLineErr(strTmp); - } - else if(m_lFileSize == 0) - { - glb_pDocLog->AddLineErr("ERROR: File length is zero, no decoding done."); - } - else - { - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeFileDo() Checkpoint 2"); - - m_pJfifDec->ProcessFile(m_pFile); - // Now indicate that the file has been processed - m_bFileAnalyzed = true; - } -} - -// Analyze the current file -// - Open file -// - Analyze file -// - Close file -// -// INPUT: -// - strFname = File to analyze -// -// PRE: -// - m_pAppConfig->nPosStart = Starting file offset for decode -// -// RETURN: -// - Status from opening file -// -bool CJPEGsnoopCore::AnalyzeFile(QString strFname) -{ - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopCore::AnalyzeFile() Begin"); - - bool bRetVal; - - // Save the input filename - // This filename is used later to confirm that output filename doesn't - // match input filename when we save the log - m_strPathName = strFname; - - // Assumes that we have set up the member vars already - // Perform the actual processing. We have this in a routine - // so that we can quickly recalculate the log file again - // if an option changes. - - bRetVal = AnalyzeOpen(); - - if(bRetVal) - { - // Only now that we have successfully opened the document - // should be mark the flag as such. This flag is used by - // other menu items to know whether or not the file is ready. - AnalyzeFileDo(); - } - - AnalyzeClose(); - - // In the last part of AnalyzeClose(), we mark the file - // as not modified, so that we don't get prompted to save. - - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CJPEGsnoopDoc::AnalyzeFile() End"); - - return bRetVal; -} - -// Save the current log to text file with a simple implementation -// -// - This routine is implemented with a simple output mechanism rather -// than leveraging CRichEditCtrl::DoSave() so that we can perform -// this operation in command-line mode or batch mode operations. -// -// TODO: Should this be moved into CDocLog? -// -void CJPEGsnoopCore::DoLogSave(QString strLogName) -{ - QFile *pLog; - - // Open the file for output - Q_ASSERT(strLogName != ""); - - // OLD COMMENTS FOLLOW - // This save method will only work if we were in Quick Log mode - // where we have recorded the log to a string buffer and not - // directly to the RichEdit - // Note that m_bLogQuickMode is only toggled on during processing - // so we can't check the status here (except seeing that there are no - // lines in the array) - - // TODO: Ensure file doesn't exist and only overwrite if specified in command-line? - - // TODO: Confirm that we are not writing to the same file we opened (m_strPathName) -/* Q_ASSERT(strLogName != m_strPathName); - - pLog = new QFile(strLogName); - // Open specified file - - if(pLog->open(QIODevice::WriteOnly | QIODevice::Text) == false) - { - QString strError; - - strError = QString("ERROR: Couldn't open file for write [%s]: [%s]").arg(strLogName); - // FIXME: Find an alternate method of signaling error in command-line mode - msgBox.setText(strError); - pLog = NULL; - - return; - } - - // Step through the current log buffer - QString strLine; - - QColor sCol; - - unsigned nQuickLines = glb_pDocLog->GetNumLinesLocal(); - - for(unsigned nLine = 0; nLine < nQuickLines; nLine++) - { - glb_pDocLog->GetLineLogLocal(nLine, strLine, sCol); - - // NOTE: At this time, batch file processing uses an 8-bit text file output format - // rather than the Unicode-supporting CRichEdit that is used when we manually - // save the log file. - // - // If we pass extended characters to WriteString() when the CStdioFile has been - // opened as CFile::typeText, the extended characters will terminate the lines - // early. - // - // Therefore, we will convert all extended characters back to ASCII here. - // - // TODO: Revise this logic so that we can have more foreign-character support - // in the batch output files. -// CW2A strAscii(strLine); -// QString strConv(strAscii); - pLog->write(strLine.toLatin1().data()); - } */ - - // Close the file - if(pLog) - { - pLog->close(); - delete pLog; - } -} - -// -------------------------------------------------------------------- -// --- START OF BATCH PROCESSING -// -------------------------------------------------------------------- - -// -// Generate a list of files for a batch processing operation -// -// POST: -// - m_asBatchFiles = Contains list of full file paths -// -void CJPEGsnoopCore::GenBatchFileList(QString strDirSrc, QString strDirDst, bool bRecSubdir, bool bExtractAll) -{ - // TODO: - // - What is the best way to provide a "Cancel Dialog" for a - // recursive operation? I can easily create the cancel / progress - // dialog with operations that have can be single-stepped, but - // not ones that require accumulation on the stack. - // - For now, just leave as-is. - - // Example code that I can use for single-stepping the operation: - // - // // === START - // COperationDlg LengthyOp(this); - // LengthyOp.SetFunctions( PrepareOperation, NextIteration, GetProgress ); - // - // // Until-done based - // bool bOk = LengthyOp.RunUntilDone( true ); - // // === END - - m_asBatchFiles.clear(); - m_asBatchOutputs.clear(); - - // Start the batch operation - GenBatchFileListRecurse(strDirSrc, strDirDst, "", bRecSubdir, bExtractAll); -} - -// Recursive routine that searches for files and folders -// Used in batch file processing mode -// -// INPUT: -// - strSrcRootName Starting path for input files -// - strDstRootName Starting path for output files -// - strPathName Path (below strSrcRootName) and filename for current input file -// - bSubdirs Flag to descend into all sub-directories -// - bExtractAll Flag to extract all JPEG from file -// -void CJPEGsnoopCore::GenBatchFileListRecurse(QString strSrcRootName, QString strDstRootName, QString strPathName, bool bSubdirs, - bool bExtractAll) -{ - // The following code snippet is based on MSDN code: - // http://msdn.microsoft.com/en-us/library/scx99850%28VS.80%29.aspx - -// CFileFind finder; - - QString strWildcard; - QString strDirName; - QString strSubPath; - QString strPath; - - // build a string with wildcards - if(strPathName.isEmpty()) - { - strWildcard = QString("%1\\*.*").arg(strSrcRootName); - } - else - { - strWildcard = QString("%1\\%2\\*.*").arg(strSrcRootName).arg(strPathName); - } - - // start working for files -// bool bWorking = finder.FindFile(strWildcard); -/* - while(bWorking) - { - bWorking = finder.FindNextFile(); - - // skip . and .. files; otherwise, we'd - // recur infinitely! - - if(finder.IsDots()) - continue; - - strPath = finder.GetFilePath(); - - // Now need to remove "root" from "path" to recalculate - // new relative subpath - strDirName = finder.GetFileName(); - - if(strPathName.isEmpty()) - { - strSubPath = strDirName; - } - else - { - strSubPath = QString("%s\\%s").arg(strPathName).arg(strDirName); - } - - // if it's a directory, recursively search it - if(finder.IsDirectory()) - { - if(bSubdirs) - { - GenBatchFileListRecurse(strSrcRootName, strDstRootName, strSubPath, bSubdirs, bExtractAll); - } - } - else - { - // GetFilePath() includes both the path & filename - // when called on a file entry, so there is no need - // to specifically call GetFileName() - // QString strFname = finder.GetFileName(); - - // Now perform final filtering check on file - // and add to batch file list - GenBatchFileListSingle(strSrcRootName, strDstRootName, strSubPath, bExtractAll); - } - } - - finder.Close(); */ -} - -// Perform processing on file selected by the batch recursion -// process GenBatchFileListRecurse(). -// -// INPUT: -// - strSrcRootName Starting path for input files -// - strDstRootName Starting path for output files -// - strPathName Path (below szSrcRootName) and filename for current input file -// - bExtractAll Flag to extract all JPEG from file -// -void CJPEGsnoopCore::GenBatchFileListSingle(QString strSrcRootName, QString strDstRootName, QString strPathName, bool bExtractAll) -{ - //bool bDoSubmit = false; - uint32_t nInd; - - QString strFnameSrc; - QString strFnameDst; - QString strFnameOnly; - QString strFnameExt; - QString strFnameLog; - QString strFnameEmbed; - - strFnameSrc = QString("%1\\%2").arg(strSrcRootName).arg(strPathName); - strFnameDst = QString("%1\\%2").arg(strDstRootName).arg(strPathName); - - // Extract the filename (without extension) and extension from - // the full pathname. - // - // FIXME: Rewrite to use Windows APIs to do this or else - // use the boost library as they will be more robust than - // the simple searches for '\' and '.' that are done here. - // -#if 1 - // ----------- - strFnameOnly = strFnameSrc.mid(strFnameSrc.lastIndexOf('\\') + 1); - nInd = strFnameOnly.lastIndexOf('.'); - strFnameOnly = strFnameOnly.mid(0, nInd); - - // Extract the file extension - nInd = strFnameSrc.lastIndexOf('.'); - strFnameExt = strFnameSrc.mid(nInd); - strFnameExt = strFnameExt.toLower(); - // ----------- -#else - uint32_t nLen = strFnameSrc.GetLength(); - - LPTSTR lpstrSrcFullpath = new TCHAR[nLen + 1]; - - _tcscpy_s(lpstrSrcFullpath, nLen + 1, strFnameSrc); - - LPTSTR lpstrSrcFnameAndExt = NULL; - - lpstrSrcFnameAndExt = PathFindFileName(lpstrSrcFullpath); - ... -#endif - // Only process files that have an extension that implies JPEG - // Batch processing is generally limited to files that appear to - // represent a JPEG image (ie. ".jpg" an ".jpeg"). - // - // TODO: Enable user to present list of extensions or disable - // the check altogether. - // TODO: Add Batch processing support for .PSD? - bool bProcessFile = false; - - // TODO: Support m_pAppConfig->strBatchExtensions - if((strFnameExt == ".jpg") || (strFnameExt == ".jpeg")) - { - bProcessFile = true; - } - - if(bExtractAll) - { - // In the "Extract all" mode during batch processing, we disable - // the extension check altogether as "Extract all" mode generally - // implies that the files may not be standalone JPEG image files. - // They could also be corrupt files that contain JPEG images. - // - // TODO: Provide additional configuration options ahead of time. - bProcessFile = true; - } - - if(bProcessFile) - { - // Generate the output log file name - // - // IMPORTANT NOTE: - // It is *essential* that this Append function work properly - // as it is used to generate the log filename from the - // image filename. Since we may be automatically overwriting - // the logfile, it is imperative that we ensure that there is - // no chance that the log filename happens to be the original - // JPEG filename. - // - // In the interests of paranoia, we perform some extra checks - // here to ensure that this doesn't happen. - - strFnameLog = strFnameDst; - strFnameLog.append(".txt"); - - // Now double check the filenames to ensure they don't match the image - - // - Is the last 4 characters of the strFname ".txt"? - if(strFnameLog.right(4) != ".txt") - { - // Report error message and skip logfile save - // TODO: Handle non-GUI mode - msgBox.setText("ERROR: Internal error #10100"); - return; - } - - // - Is the strFnameLog different from the input filename (strFname)? - if(strFnameLog == strPathName) - { - // Report error message and skip logfile save - // TODO: Handle non-GUI mode - msgBox.setText("ERROR: Internal error #10101"); - return; - } - - // Add filename pair to the list - // - Input filename to analyze - // - Output filename for associated log/report - m_asBatchFiles.append(strFnameSrc); - m_asBatchDest.append(strFnameDst); - m_asBatchOutputs.append(strFnameLog); - } -} - -// Return the number of files in the batch list -uint32_t CJPEGsnoopCore::GetBatchFileCount() -{ - return m_asBatchFiles.count(); -} - -// Return the filename at the batch index specified -QString CJPEGsnoopCore::GetBatchFileInfo(uint32_t nFileInd) -{ - if(nFileInd < GetBatchFileCount()) - { - return m_asBatchFiles[nFileInd]; - } - else - { - return "???"; - } -} - -// Perform AnalyzeFile() but handle any search modes first -// -// RETURN: -// - true if file opened OK, false if issue during open -// -bool CJPEGsnoopCore::DoAnalyzeOffset(QString strFname) -{ - // Handle the different file offset / search modes - bool bStatus = false; - bool bSearchResult = false; - - uint32_t nStartPos = 0; - uint32_t nSearchPos = 0; - - if(m_pAppConfig->eCmdLineOffset == DEC_OFFSET_START) - { - // Decode at start of file - m_pAppConfig->nPosStart = 0; - bStatus = AnalyzeFile(strFname); - } - else if(m_pAppConfig->eCmdLineOffset == DEC_OFFSET_SRCH1) - { - // Decode at 1st SOI found in file - m_pAppConfig->nPosStart = 0; - bStatus = AnalyzeFile(strFname); - - if(bStatus) - { - if(!m_pJfifDec->GetDecodeStatus()) - { - // SOI not found at start, so begin search - bStatus = AnalyzeOpen(); - nStartPos = m_pAppConfig->nPosStart; - bSearchResult = B_BufSearch(nStartPos, 0xFFD8FF, 3, true, nSearchPos); - AnalyzeClose(); - - if(bSearchResult) - { - // If found, update offset & re-analyze - m_pAppConfig->nPosStart = nSearchPos; - bStatus = AnalyzeFile(strFname); - } - } - } - } - else if(m_pAppConfig->eCmdLineOffset == DEC_OFFSET_SRCH2) - { - // Decode at 1st SOI found after start of file - // Force a search - m_pAppConfig->nPosStart = 0; - bStatus = AnalyzeFile(strFname); - - if(bStatus) - { - bStatus = AnalyzeOpen(); - nStartPos = m_pAppConfig->nPosStart; - bSearchResult = B_BufSearch(nStartPos, 0xFFD8FF, 3, true, nSearchPos); - AnalyzeClose(); - - if(bSearchResult) - { - // If found, update offset & re-analyze - m_pAppConfig->nPosStart = nSearchPos; - bStatus = AnalyzeFile(strFname); - } - } - } - else if(m_pAppConfig->eCmdLineOffset == DEC_OFFSET_POS) - { - // Decode from quint8 ### in file - m_pAppConfig->nPosStart = m_pAppConfig->nCmdLineOffsetPos; - bStatus = AnalyzeFile(strFname); - } - else - { - Q_ASSERT(false); - } - - // bStatus reports the success in opening the file - - return bStatus; -} - -// Process a file in the batch file list -// -// INPUT: -// - nFileInd = Index into batch file list -// - bWriteLog = Write out log file after processing file? -// - bExtractAll = Perform extract-all on this file? -// -void CJPEGsnoopCore::DoBatchFileProcess(uint32_t nFileInd, bool bWriteLog, bool bExtractAll) -{ - bool bStatus = false; - - uint32_t nBatchFileCount; - - QString strFnameFile; - QString strFnameDst; - QString strFnameLog; - QString strFnameEmbed; - - nBatchFileCount = GetBatchFileCount(); - - if(nFileInd >= nBatchFileCount) - { - Q_ASSERT(false); - return; - } - - //TODO: strFnameDst is not really used as it is base destination filename - strFnameFile = m_asBatchFiles[nFileInd]; - strFnameDst = m_asBatchDest[nFileInd]; - strFnameLog = m_asBatchOutputs[nFileInd]; - - // Indicate that the file source has changed so that any image decoding is enabled - J_ImgSrcChanged(); - - // Save the current filename into the temporary config space - // This is only done to assist debugging reporting - m_pAppConfig->strCurFname = strFnameFile; - - // Handle the different file offset / search modes - bStatus = DoAnalyzeOffset(strFnameFile); - - if(!bStatus) - { - // If we had an issue opening the file, abort here - // TODO: Consider whether we should alert the user (perhaps in direct window log write) - return; - } - - if(bWriteLog || bExtractAll) - { - // Now we need to ensure that the destination directory has been created - // Build up the subdirectories as required - BuildDirPath(strFnameDst); - } - - // Save the output log - if(bWriteLog) - { - DoLogSave(strFnameLog); - } - - if(bExtractAll) - { - // - // TODO: In the "Extract all" mode we should ask the - // user for the full configuration ahead of the batch - // process. - - // Create the filepath for any batch embedded JPEG extraction - strFnameEmbed = strFnameDst; - strFnameEmbed.append(".export.jpg"); - - QString strInputFname = strFnameFile; - QString strExportFname = strFnameEmbed; - - bool bOverlayEn = false; - bool bForceSoi = false; - bool bForceEoi = false; - bool bIgnoreEoi = false; - bool bExtractAllEn = true; - bool bDhtAviInsert = false; - - QString strOutPath = ""; // unused - - DoExtractEmbeddedJPEG(strInputFname, strExportFname, bOverlayEn, bForceSoi, bForceEoi, bIgnoreEoi, bExtractAllEn, - bDhtAviInsert, strOutPath); - } - - // Now submit entry to database! -#if 0 // Not supported currently -#ifdef BATCH_DO_DBSUBMIT - bDoSubmit = m_pJfifDec->CompareSignature(true); - if(bDoSubmit) - { - // FIXME: Check function param values. Might be outdated - m_pJfifDec->PrepareSendSubmit(m_pJfifDec->m_strImgQualExif, m_pJfifDec->m_eDbReqSuggest, ""), "BATCH"; - } -#endif -#endif -} - -// -------------------------------------------------------------------- -// --- END OF BATCH PROCESSING -// -------------------------------------------------------------------- - -// Ensure that the file system path exists, -// create the nested subdirectories as required -void CJPEGsnoopCore::BuildDirPath(QString strPath) -{ - // Now we need to ensure that the destination directory has been created - // Build up the subdirectories as required - // - // Use PathRemoveFileSpec() to find the directory path instead of - // simply looking for the last '\'. This should be safer. -// unsigned nLen = strPath.length(); - -// char *lpstrDstPathOnly = new char[nLen + 1]; - -// strcpy(lpstrDstPathOnly, strPath.toLatin1().data()); -// PathRemoveFileSpec(lpstrDstPathOnly); - -// SHCreateDirectoryEx(NULL, lpstrDstPathOnly, NULL); - QDir dir; - strPath = dir.filePath(strPath); - dir.mkdir(strPath); -// if(lpstrDstPathOnly) -// { -// delete[]lpstrDstPathOnly; -// lpstrDstPathOnly = NULL; -// } -} - -#if 0 //xxx -// Placeholder code for command-line call to extract JPEGs -void CJPEGsnoopCore::DoExtractEmbeddedJPEGCmdLine() -{ - // Determine if file is AVI - // If so, default to DHT AVI insert mode - // NOTE: Calling GetAviMode() requires that the CDocument JFIF decoder - // instance has processed the file. - bool bIsAvi, bIsMjpeg; - - m_pJfifDec->GetAviMode(bIsAvi, bIsMjpeg); - dlgExport.m_bDhtAviInsert = bIsMjpeg; - - bExtractAllEn = true; - bForceSoi = false; - bForceEoi = false; - bIgnoreEoi = false; - bOverlayEn = false; - bDhtAviInsert = bInsDhtAvi; - - DoExtractEmbeddedJPEG1(..); -} -#endif - -// Extracts an embedded JPEG from the current file -// Also support extraction of all embedded JPEG from the file -// -// NOTE: In "Extract All" mode, all file types are processed. -// -// TODO: -// - strOutPath unused -void CJPEGsnoopCore::DoExtractEmbeddedJPEG(QString strInputFname, QString strOutputFname, - bool bOverlayEn, bool bForceSoi, bool bForceEoi, bool bIgnoreEoi, bool bExtractAllEn, - bool bDhtAviInsert, QString strOutPath) -{ - unsigned int nFileSize = 0; - - bool bRet; - - if(!bExtractAllEn) - { - // ======================================================== - // Extract Single mode - // ======================================================== - - // For export, we need to analyze first to get some info - // including suitability for export - // AnalyzeOpen() calls require m_strPathName to be set - m_strPathName = strInputFname; - bRet = AnalyzeOpen(); - - if(bRet) - { - AnalyzeFileDo(); - } - - // FIXME: Is this being used anywhere? - // strTmp = QString("0x%08X",m_pJfifDec->GetPosEmbedStart()); - - // If we are not in "extract all" mode, then check now to see if - // the current file position looks OK to extract a valid JPEG. - - // Is the currently-decoded file in a suitable - // state for JPEG extraction (ie. have we seen all - // the necessary markers?) - bRet = m_pJfifDec->ExportJpegPrepare(strInputFname, bForceSoi, bForceEoi, bIgnoreEoi); - - if(!bRet) - { - return; - } - - // -------------------------------------------------------- - // Perform extraction of single embedded JPEG - // -------------------------------------------------------- - - if(m_lFileSize > 0xFFFFFFFFUL) - { - QString strTmp = "Extract file too large. Skipping."; - - glb_pDocLog->AddLineErr(strTmp); - - if(m_pAppConfig->bInteractive) - msgBox.setText(strTmp); - } - else - { - // Extract the JPEG file - nFileSize = static_cast < uint32_t >(m_lFileSize); - - bRet = m_pJfifDec->ExportJpegDo(strInputFname, strOutputFname, nFileSize, bOverlayEn, bDhtAviInsert, bForceSoi, bForceEoi); - } - - AnalyzeClose(); - - } - else - { - // ======================================================== - // Extract All mode - // ======================================================== - - Q_ASSERT(strOutputFname != ""); - - // In extract-all, start at file offset 0 - m_pAppConfig->nPosStart = 0; - - // For added safety, reset the JFIF decoder state - // Note that this is already covered by the AnalyzeFileDo() call to JFIF Process() later - m_pJfifDec->Reset(); - - // -------------------------------------------------------- - // Perform batch extraction of all embedded JPEGs - // -------------------------------------------------------- - - // Ensure we have no file state left over - // FIXME: Do I really need this here? - AnalyzeClose(); - - bool bDoneBatch = false; - - uint32_t nExportCnt = 1; - - uint32_t nStartPos = 0; - - bool bSearchResult = false; - - uint32_t nSearchPos = 0; - - bool bSkipFrame = false; - - // Determine the root filename - // Filename selected by user: strEmbedFileName - QString strRootFileName; - - int nExtInd; - - // FIXME: Do I really want to use strOutputFname? That is typically the log file - nExtInd = strOutputFname.lastIndexOf('.'); - Q_ASSERT(nExtInd != -1); - - if(nExtInd == -1) - { - QString strTmp; - - strTmp = QString("ERROR: Invalid filename [%1]").arg(strOutputFname); - glb_pDocLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) - msgBox.setText(strTmp); - return; - } - - strRootFileName = strOutputFname.left(nExtInd); - QString strOutputFnameTemp = ""; - - // Loop through file until done - while(!bDoneBatch) - { - - bSkipFrame = false; - - // Create filename - // 6 digits of numbering will support videos at 60 fps for over 4.5hrs. - strOutputFnameTemp = QString("%1.%06u.jpg").arg(strRootFileName).arg(nExportCnt); - - // Opens file (m_strPathName), resets window buffer, file size, etc. - AnalyzeOpen(); - - // AnalyzeFileDo() also resets all JFIF decoder state for us - // Perform the JFIF parsing & decoding - // Decoding starts at file offset m_pAppConfig->nPosStart - AnalyzeFileDo(); - - // Is the currently-decoded file in a suitable state for JPEG extraction? - // (ie. have we seen all the necessary markers?) - bRet = m_pJfifDec->ExportJpegPrepare(strInputFname, bForceSoi, bForceEoi, bIgnoreEoi); - - if(!bRet) - { - // Skip this particular frame - bSkipFrame = true; - } - - if(!bSkipFrame) - { - if(m_lFileSize > 0xFFFFFFFFULL) - { - QString strTmp; - - strTmp = QString("ERROR: Extract file too large. Skipping. [Size=0x%1]").arg(m_lFileSize); - glb_pDocLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) - msgBox.setText(strTmp); - } - else - { - // Extract the JPEG file - nFileSize = static_cast < uint32_t >(m_lFileSize); - - bRet = m_pJfifDec->ExportJpegDo(strInputFname, strOutputFnameTemp, nFileSize, - bOverlayEn, bDhtAviInsert, bForceSoi, bForceEoi); - } - - // Still increment frame # even if we skipped export (due to file size) - nExportCnt++; - } - - // See if we can find the next embedded JPEG (file must still be open for this) - Q_ASSERT(m_bFileOpened); - nStartPos = m_pAppConfig->nPosStart; - m_pJfifDec->ImgSrcChanged(); - - bSearchResult = m_pWBuf->BufSearch(nStartPos, 0xFFD8FF, 3, true, nSearchPos); - - if(bSearchResult) - { - // Set starting file offset - m_pAppConfig->nPosStart = nSearchPos; - - // AnalyzeFileDo() also resets all JFIF decoder state for us - AnalyzeFileDo(); - - } - else - { - // No SOI Marker found in Forward search -> Stop batch - bDoneBatch = true; - } - - // For export, we need to call AnalyzeClose() - AnalyzeClose(); - } // bDoneBatch - - // Close the file in case we aborted above - AnalyzeClose(); - } // bExtractAllEn -} - -// ============================================== - -// ---------------------------------------------- -// Accessors for CjfifDecode -// ---------------------------------------------- - -void CJPEGsnoopCore::J_GetAviMode(bool & bIsAvi, bool & bIsMjpeg) -{ - m_pJfifDec->GetAviMode(bIsAvi, bIsMjpeg); -} - -void CJPEGsnoopCore::J_SetAviMode(bool bIsAvi, bool bIsMjpeg) -{ - m_pJfifDec->SetAviMode(bIsAvi, bIsMjpeg); -} - -void CJPEGsnoopCore::J_ImgSrcChanged() -{ - m_pJfifDec->ImgSrcChanged(); -} - -uint32_t CJPEGsnoopCore::J_GetPosEmbedStart() -{ - return m_pJfifDec->GetPosEmbedStart(); -} - -uint32_t CJPEGsnoopCore::J_GetPosEmbedEnd() -{ - return m_pJfifDec->GetPosEmbedEnd(); -} - -void CJPEGsnoopCore::J_GetDecodeSummary(QString & strHash, QString & strHashRot, QString & strImgExifMake, - QString & strImgExifModel, QString & strImgQualExif, QString & strSoftware, - teDbAdd & eDbReqSuggest) -{ - m_pJfifDec->GetDecodeSummary(strHash, strHashRot, strImgExifMake, strImgExifModel, strImgQualExif, strSoftware, eDbReqSuggest); -} - -uint32_t CJPEGsnoopCore::J_GetDqtZigZagIndex(uint32_t nInd, bool bZigZag) -{ - return m_pJfifDec->GetDqtZigZagIndex(nInd, bZigZag); -} - -uint32_t CJPEGsnoopCore::J_GetDqtQuantStd(uint32_t nInd) -{ - return m_pJfifDec->GetDqtQuantStd(nInd); -} - -void CJPEGsnoopCore::J_SetStatusBar(QStatusBar * pStatBar) -{ - m_pJfifDec->SetStatusBar(pStatBar); -} - -void CJPEGsnoopCore::J_ProcessFile(QFile * inFile) -{ - m_pJfifDec->ProcessFile(inFile); -} - -void CJPEGsnoopCore::J_PrepareSendSubmit(QString strQual, teSource eUserSource, QString strUserSoftware, QString strUserNotes) -{ - m_pJfifDec->PrepareSendSubmit(strQual, eUserSource, strUserSoftware, strUserNotes); -} - -// ---------------------------------------------- -// Accessors for CwindowBuf -// ---------------------------------------------- - -void CJPEGsnoopCore::B_SetStatusBar(QStatusBar * pStatBar) -{ - m_pWBuf->SetStatusBar(pStatBar); -} - -void CJPEGsnoopCore::B_BufLoadWindow(uint32_t nPosition) -{ - m_pWBuf->BufLoadWindow(nPosition); -} - -void CJPEGsnoopCore::B_BufFileSet(QFile * inFile) -{ - m_pWBuf->BufFileSet(inFile); -} - -void CJPEGsnoopCore::B_BufFileUnset() -{ - m_pWBuf->BufFileUnset(); -} - -quint8 CJPEGsnoopCore::B_Buf(uint32_t nOffset, bool bClean) -{ - return m_pWBuf->Buf(nOffset, bClean); -} - -bool CJPEGsnoopCore::B_BufSearch(uint32_t nStartPos, uint32_t nSearchVal, uint32_t nSearchLen, - bool bDirFwd, uint32_t &nFoundPos) -{ - return m_pWBuf->BufSearch(nStartPos, nSearchVal, nSearchLen, bDirFwd, nFoundPos); -} - -bool CJPEGsnoopCore::B_OverlayInstall(uint32_t nOvrInd, quint8 * pOverlay, uint32_t nLen, uint32_t nBegin, - uint32_t nMcuX, uint32_t nMcuY, uint32_t nMcuLen, uint32_t nMcuLenIns, - int nAdjY, int nAdjCb, int nAdjCr) -{ - return m_pWBuf->OverlayInstall(nOvrInd, pOverlay, nLen, nBegin, nMcuX, nMcuY, nMcuLen, nMcuLenIns, nAdjY, nAdjCb, nAdjCr); -} - -void CJPEGsnoopCore::B_OverlayRemoveAll() -{ - m_pWBuf->OverlayRemoveAll(); -} - -bool CJPEGsnoopCore::B_OverlayGet(uint32_t nOvrInd, quint8 * &pOverlay, uint32_t &nLen, uint32_t &nBegin) -{ - return m_pWBuf->OverlayGet(nOvrInd, pOverlay, nLen, nBegin); -} - -// ---------------------------------------------- -// Accessors for CImgDec -// ---------------------------------------------- -void CJPEGsnoopCore::I_SetStatusBar(QStatusBar * pStatBar) -{ - m_pImgDec->SetStatusBar(pStatBar); -} - -uint32_t CJPEGsnoopCore::I_GetDqtEntry(uint32_t nTblDestId, uint32_t nCoeffInd) -{ - return m_pImgDec->GetDqtEntry(nTblDestId, nCoeffInd); -} - -void CJPEGsnoopCore::I_SetPreviewMode(uint32_t nMode) -{ - m_pImgDec->SetPreviewMode(nMode); -} - -uint32_t CJPEGsnoopCore::I_GetPreviewMode() -{ - return m_pImgDec->GetPreviewMode(); -} - -void CJPEGsnoopCore::I_SetPreviewYccOffset(uint32_t nMcuX, uint32_t nMcuY, int nY, int nCb, int nCr) -{ - m_pImgDec->SetPreviewYccOffset(nMcuX, nMcuY, nY, nCb, nCr); -} - -void CJPEGsnoopCore::I_GetPreviewYccOffset(uint32_t &nMcuX, uint32_t &nMcuY, int &nY, int &nCb, int &nCr) -{ - m_pImgDec->GetPreviewYccOffset(nMcuX, nMcuY, nY, nCb, nCr); -} - -void CJPEGsnoopCore::I_SetPreviewMcuInsert(uint32_t nMcuX, uint32_t nMcuY, int nLen) -{ - m_pImgDec->SetPreviewMcuInsert(nMcuX, nMcuY, nLen); -} - -void CJPEGsnoopCore::I_GetPreviewMcuInsert(uint32_t &nMcuX, uint32_t &nMcuY, uint32_t &nLen) -{ - m_pImgDec->GetPreviewMcuInsert(nMcuX, nMcuY, nLen); -} - -void CJPEGsnoopCore::I_SetPreviewZoom(bool bInc, bool bDec, bool bSet, uint32_t nVal) -{ - m_pImgDec->SetPreviewZoom(bInc, bDec, bSet, nVal); -} - -uint32_t CJPEGsnoopCore::I_GetPreviewZoomMode() -{ - return m_pImgDec->GetPreviewZoomMode(); -} - -float CJPEGsnoopCore::I_GetPreviewZoom() -{ - return m_pImgDec->GetPreviewZoom(); -} - -bool CJPEGsnoopCore::I_GetPreviewOverlayMcuGrid() -{ - return m_pImgDec->GetPreviewOverlayMcuGrid(); -} - -void CJPEGsnoopCore::I_SetPreviewOverlayMcuGridToggle() -{ - m_pImgDec->SetPreviewOverlayMcuGridToggle(); -} - -QPoint CJPEGsnoopCore::I_PixelToMcu(QPoint ptPix) -{ - return m_pImgDec->PixelToMcu(ptPix); -} - -QPoint CJPEGsnoopCore::I_PixelToBlk(QPoint ptPix) -{ - return m_pImgDec->PixelToBlk(ptPix); -} - -uint32_t CJPEGsnoopCore::I_McuXyToLinear(QPoint ptMcu) -{ - return m_pImgDec->McuXyToLinear(ptMcu); -} - -void CJPEGsnoopCore::I_GetImageSize(uint32_t &nX, uint32_t &nY) -{ - m_pImgDec->GetImageSize(nX, nY); -} - -void CJPEGsnoopCore::I_GetPixMapPtrs(short *&pMapY, short *&pMapCb, short *&pMapCr) -{ - m_pImgDec->GetPixMapPtrs(pMapY, pMapCb, pMapCr); -} - -void CJPEGsnoopCore::I_GetDetailVlc(bool & bDetail, uint32_t &nX, uint32_t &nY, uint32_t &nLen) -{ - m_pImgDec->GetDetailVlc(bDetail, nX, nY, nLen); -} - -void CJPEGsnoopCore::I_SetDetailVlc(bool bDetail, uint32_t nX, uint32_t nY, uint32_t nLen) -{ - m_pImgDec->SetDetailVlc(bDetail, nX, nY, nLen); -} - -uint32_t CJPEGsnoopCore::I_GetMarkerCount() -{ - return m_pImgDec->GetMarkerCount(); -} - -void CJPEGsnoopCore::I_SetMarkerBlk(uint32_t nBlkX, uint32_t nBlkY) -{ - m_pImgDec->SetMarkerBlk(nBlkX, nBlkY); -} - -QPoint CJPEGsnoopCore::I_GetMarkerBlk(uint32_t nInd) -{ - return m_pImgDec->GetMarkerBlk(nInd); -} - -void CJPEGsnoopCore::I_SetStatusText(QString strText) -{ - m_pImgDec->SetStatusText(strText); -} - -QString CJPEGsnoopCore::I_GetStatusYccText() -{ - return m_pImgDec->GetStatusYccText(); -} - -void CJPEGsnoopCore::I_SetStatusYccText(QString strText) -{ - m_pImgDec->SetStatusYccText(strText); -} - -QString CJPEGsnoopCore::I_GetStatusMcuText() -{ - return m_pImgDec->GetStatusMcuText(); -} - -void CJPEGsnoopCore::I_SetStatusMcuText(QString strText) -{ - m_pImgDec->SetStatusMcuText(strText); -} - -QString CJPEGsnoopCore::I_GetStatusFilePosText() -{ - return m_pImgDec->GetStatusFilePosText(); -} - -void CJPEGsnoopCore::I_SetStatusFilePosText(QString strText) -{ - m_pImgDec->SetStatusFilePosText(strText); -} - -void CJPEGsnoopCore::I_GetBitmapPtr(unsigned char *&pBitmap) -{ - m_pImgDec->GetBitmapPtr(pBitmap); -} - -void CJPEGsnoopCore::I_LookupFilePosMcu(uint32_t nMcuX, uint32_t nMcuY, uint32_t &nquint8, uint32_t &nBit) -{ - m_pImgDec->LookupFilePosMcu(nMcuX, nMcuY, nquint8, nBit); -} - -void CJPEGsnoopCore::I_LookupFilePosPix(uint32_t nPixX, uint32_t nPixY, uint32_t &nquint8, uint32_t &nBit) -{ - m_pImgDec->LookupFilePosPix(nPixX, nPixY, nquint8, nBit); -} - -void CJPEGsnoopCore::I_LookupBlkYCC(uint32_t nBlkX, uint32_t nBlkY, int &nY, int &nCb, int &nCr) -{ - m_pImgDec->LookupBlkYCC(nBlkX, nBlkY, nY, nCb, nCr); -} - -void CJPEGsnoopCore::I_ViewOnDraw(QPainter *pDC, QRect rectClient, QPoint ptScrolledPos, QFont *pFont, QSize & szNewScrollSize) -{ - m_pImgDec->ViewOnDraw(pDC, rectClient, ptScrolledPos, pFont, szNewScrollSize); -} - -void CJPEGsnoopCore::I_GetPreviewPos(uint32_t &nX, uint32_t &nY) -{ - m_pImgDec->GetPreviewPos(nX, nY); -} - -void CJPEGsnoopCore::I_GetPreviewSize(uint32_t &nX, uint32_t &nY) -{ - m_pImgDec->GetPreviewSize(nX, nY); -} - -bool CJPEGsnoopCore::I_IsPreviewReady() -{ - return m_pImgDec->IsPreviewReady(); -} diff --git a/source/JPEGsnoopCore.h b/source/JPEGsnoopCore.h deleted file mode 100644 index a674d2b..0000000 --- a/source/JPEGsnoopCore.h +++ /dev/null @@ -1,164 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - This module performs all of the main decoding and processing functions -// - It contains the major context (m_pWBuf, m_pImgDec, m_pJfifDec) -// -// ========================================================================== - -#pragma once - -#include -#include - -#include "JfifDecode.h" -#include "ImgDecode.h" -#include "WindowBuf.h" -#include "SnoopConfig.h" - -class CJPEGsnoopCore -{ -public: - CJPEGsnoopCore(void); - ~CJPEGsnoopCore(void); - - void Reset(); - - void SetStatusBar(QStatusBar * pStatBar); - - bool AnalyzeFile(QString strFname); - void AnalyzeFileDo(); - bool AnalyzeOpen(); - void AnalyzeClose(); - bool IsAnalyzed(); - bool DoAnalyzeOffset(QString strFname); - - void DoLogSave(QString strLogName); - - void GenBatchFileList(QString strDirSrc, QString strDirDst, bool bRecSubdir, bool bExtractAll); - uint32_t GetBatchFileCount(); - void DoBatchFileProcess(uint32_t nFileInd, bool bWriteLog, bool bExtractAll); - QString GetBatchFileInfo(uint32_t nFileInd); - - void BuildDirPath(QString strPath); - - void DoExtractEmbeddedJPEG(QString strInputFname, QString strOutputFname, - bool bOverlayEn, bool bForceSoi, bool bForceEoi, bool bIgnoreEoi, bool bExtractAllEn, - bool bDhtAviInsert, QString strOutPath); - - // Accessor wrappers for CjfifDecode - void J_GetAviMode(bool & bIsAvi, bool & bIsMjpeg); - void J_SetAviMode(bool bIsAvi, bool bIsMjpeg); - void J_ImgSrcChanged(); - uint32_t J_GetPosEmbedStart(); - uint32_t J_GetPosEmbedEnd(); - void J_GetDecodeSummary(QString & strHash, QString & strHashRot, QString & strImgExifMake, QString & strImgExifModel, - QString & strImgQualExif, QString & strSoftware, teDbAdd & eDbReqSuggest); - uint32_t J_GetDqtZigZagIndex(uint32_t nInd, bool bZigZag); - uint32_t J_GetDqtQuantStd(uint32_t nInd); - void J_SetStatusBar(QStatusBar * pStatBar); - void J_ProcessFile(QFile * inFile); - void J_PrepareSendSubmit(QString strQual, teSource eUserSource, QString strUserSoftware, QString strUserNotes); - - // Accessor wrappers for CImgDec - void I_SetStatusBar(QStatusBar * pStatBar); - uint32_t I_GetDqtEntry(uint32_t nTblDestId, uint32_t nCoeffInd); - void I_SetPreviewMode(uint32_t nMode); - uint32_t I_GetPreviewMode(); - void I_SetPreviewYccOffset(uint32_t nMcuX, uint32_t nMcuY, int nY, int nCb, int nCr); - void I_GetPreviewYccOffset(uint32_t &nMcuX, uint32_t &nMcuY, int &nY, int &nCb, int &nCr); - void I_SetPreviewMcuInsert(uint32_t nMcuX, uint32_t nMcuY, int nLen); - void I_GetPreviewMcuInsert(uint32_t &nMcuX, uint32_t &nMcuY, uint32_t &nLen); - void I_SetPreviewZoom(bool bInc, bool bDec, bool bSet, uint32_t nVal); - uint32_t I_GetPreviewZoomMode(); - float I_GetPreviewZoom(); - bool I_GetPreviewOverlayMcuGrid(); - void I_SetPreviewOverlayMcuGridToggle(); - QPoint I_PixelToMcu(QPoint ptPix); - QPoint I_PixelToBlk(QPoint ptPix); - uint32_t I_McuXyToLinear(QPoint ptMcu); - void I_GetImageSize(uint32_t &nX, uint32_t &nY); - void I_GetPixMapPtrs(short *&pMapY, short *&pMapCb, short *&pMapCr); - void I_GetDetailVlc(bool & bDetail, uint32_t &nX, uint32_t &nY, uint32_t &nLen); - void I_SetDetailVlc(bool bDetail, uint32_t nX, uint32_t nY, uint32_t nLen); - uint32_t I_GetMarkerCount(); - void I_SetMarkerBlk(uint32_t nBlkX, uint32_t nBlkY); - QPoint I_GetMarkerBlk(uint32_t nInd); - void I_SetStatusText(QString strText); - QString I_GetStatusYccText(); - void I_SetStatusYccText(QString strText); - QString I_GetStatusMcuText(); - void I_SetStatusMcuText(QString strText); - QString I_GetStatusFilePosText(); - void I_SetStatusFilePosText(QString strText); - void I_GetBitmapPtr(unsigned char *&pBitmap); - void I_LookupFilePosMcu(uint32_t nMcuX, uint32_t nMcuY, uint32_t &nByte, uint32_t &nBit); - void I_LookupFilePosPix(uint32_t nPixX, uint32_t nPixY, uint32_t &nByte, uint32_t &nBit); - void I_LookupBlkYCC(uint32_t nBlkX, uint32_t nBlkY, int &nY, int &nCb, int &nCr); - void I_ViewOnDraw(QPainter* pDC,QRect rectClient,QPoint ptScrolledPos,QFont* pFont, QSize &szNewScrollSize); - void I_GetPreviewPos(uint32_t &nX, uint32_t &nY); - void I_GetPreviewSize(uint32_t &nX, uint32_t &nY); - bool I_IsPreviewReady(); - - // Accessor wrappers for CwindowBuf - void B_SetStatusBar(QStatusBar * pStatBar); - void B_BufLoadWindow(uint32_t nPosition); - void B_BufFileSet(QFile * inFile); - void B_BufFileUnset(); - quint8 B_Buf(uint32_t nOffset, bool bClean = false); - bool B_BufSearch(uint32_t nStartPos, uint32_t nSearchVal, uint32_t nSearchLen, bool bDirFwd, uint32_t &nFoundPos); - bool B_OverlayInstall(uint32_t nOvrInd, quint8 * pOverlay, uint32_t nLen, uint32_t nBegin, - uint32_t nMcuX, uint32_t nMcuY, uint32_t nMcuLen, uint32_t nMcuLenIns, int nAdjY, int nAdjCb, int nAdjCr); - void B_OverlayRemoveAll(); - bool B_OverlayGet(uint32_t nOvrInd, quint8 * &pOverlay, uint32_t &nLen, uint32_t &nBegin); - - CimgDecode *imgDecoder() { return m_pImgDec; } -private: - - // Batch processing - void GenBatchFileListRecurse(QString strSrcRootName, QString strDstRootName, QString strPathName, bool bSubdirs, - bool bExtractAll); - void GenBatchFileListSingle(QString strSrcRootName, QString strDstRootName, QString strPathName, bool bExtractAll); - -private: - QMessageBox msgBox; - - // Config - CSnoopConfig *m_pAppConfig; // Pointer to application config - - // Input JPEG file - QFile *m_pFile; - quint64 m_lFileSize; - - QString m_strPathName; - bool m_bFileAnalyzed; // Have we opened and analyzed a file? - bool m_bFileOpened; // Is a file currently opened? - - // Decoders and Buffers - CjfifDecode *m_pJfifDec; - CimgDecode *m_pImgDec; - CwindowBuf *m_pWBuf; - - // Batch processing - QStringList m_asBatchFiles; - QStringList m_asBatchDest; - QStringList m_asBatchOutputs; - -}; diff --git a/source/JPEGsnoopDoc.cpp b/source/JPEGsnoopDoc.cpp deleted file mode 100644 index d05a3af..0000000 --- a/source/JPEGsnoopDoc.cpp +++ /dev/null @@ -1,2227 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// JPEGsnoopDoc.cpp : implementation of the CJPEGsnoopDoc class -// - -#include "stdafx.h" -#include "JPEGsnoop.h" - -#include "JPEGsnoopDoc.h" -#include "CntrItem.h" - -#include "OffsetDlg.h" -#include "DbSubmitDlg.h" -#include "NoteDlg.h" -#include "OverlayBufDlg.h" -#include "LookupDlg.h" -#include "ExportDlg.h" -#include "DecodeDetailDlg.h" -#include "ExportTiffDlg.h" - -//#include "OperationDlg.h" - -#include "General.h" - -#include "FileTiff.h" - - - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - - -// CJPEGsnoopDoc - -IMPLEMENT_DYNCREATE(CJPEGsnoopDoc, CRichEditDoc) - -BEGIN_MESSAGE_MAP(CJPEGsnoopDoc, CRichEditDoc) - // Enable default OLE container implementation - ON_COMMAND(ID_OLE_EDIT_LINKS, CRichEditDoc::OnEditLinks) - ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_LINKS, CRichEditDoc::OnUpdateEditLinksMenu) - ON_UPDATE_COMMAND_UI_RANGE(ID_OLE_VERB_FIRST, ID_OLE_VERB_LAST, CRichEditDoc::OnUpdateObjectVerbMenu) - - ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs) - //ON_COMMAND(ID_FILE_OPENIMAGE, OnFileOpenimage) - ON_COMMAND(ID_FILE_OFFSET, OnFileOffset) - ON_COMMAND(ID_FILE_REPROCESS, OnFileReprocess) - ON_COMMAND(ID_TOOLS_ADDCAMERATODB, OnToolsAddcameratodb) - ON_COMMAND(ID_TOOLS_SEARCHFORWARD, OnToolsSearchforward) - ON_COMMAND(ID_TOOLS_SEARCHREVERSE, OnToolsSearchreverse) - ON_UPDATE_COMMAND_UI(ID_TOOLS_ADDCAMERATODB, OnUpdateToolsAddcameratodb) - ON_UPDATE_COMMAND_UI(ID_TOOLS_SEARCHFORWARD, OnUpdateToolsSearchforward) - ON_UPDATE_COMMAND_UI(ID_TOOLS_SEARCHREVERSE, OnUpdateToolsSearchreverse) - - ON_COMMAND_RANGE(ID_PREVIEW_RGB,ID_PREVIEW_CR,OnPreviewRng) - ON_UPDATE_COMMAND_UI_RANGE(ID_PREVIEW_RGB,ID_PREVIEW_CR,OnUpdatePreviewRng) - - ON_COMMAND_RANGE(ID_IMAGEZOOM_ZOOMIN,ID_IMAGEZOOM_800,OnZoomRng) - ON_UPDATE_COMMAND_UI_RANGE(ID_IMAGEZOOM_ZOOMIN,ID_IMAGEZOOM_800,OnUpdateZoomRng) - - - ON_COMMAND(ID_TOOLS_SEARCHEXECUTABLEFORDQT, OnToolsSearchexecutablefordqt) - ON_UPDATE_COMMAND_UI(ID_FILE_REPROCESS, OnUpdateFileReprocess) - ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs) - ON_COMMAND(ID_TOOLS_EXTRACTEMBEDDEDJPEG, OnToolsExtractembeddedjpeg) - ON_UPDATE_COMMAND_UI(ID_TOOLS_EXTRACTEMBEDDEDJPEG, OnUpdateToolsExtractembeddedjpeg) - ON_COMMAND(ID_TOOLS_FILEOVERLAY, OnToolsFileoverlay) - ON_UPDATE_COMMAND_UI(ID_TOOLS_FILEOVERLAY, OnUpdateToolsFileoverlay) - ON_COMMAND(ID_TOOLS_LOOKUPMCUOFFSET, OnToolsLookupmcuoffset) - ON_UPDATE_COMMAND_UI(ID_TOOLS_LOOKUPMCUOFFSET, OnUpdateToolsLookupmcuoffset) - ON_COMMAND(ID_OVERLAYS_MCUGRID, OnOverlaysMcugrid) - ON_UPDATE_COMMAND_UI(ID_OVERLAYS_MCUGRID, OnUpdateOverlaysMcugrid) - - - - ON_UPDATE_COMMAND_UI(ID_INDICATOR_YCC, OnUpdateIndicatorYcc) - ON_UPDATE_COMMAND_UI(ID_INDICATOR_MCU, OnUpdateIndicatorMcu) - ON_UPDATE_COMMAND_UI(ID_INDICATOR_FILEPOS, OnUpdateIndicatorFilePos) - ON_COMMAND(ID_SCANSEGMENT_DETAILEDDECODE, OnScansegmentDetaileddecode) - ON_UPDATE_COMMAND_UI(ID_SCANSEGMENT_DETAILEDDECODE, OnUpdateScansegmentDetaileddecode) - ON_COMMAND(ID_TOOLS_EXPORTTIFF, OnToolsExporttiff) - ON_UPDATE_COMMAND_UI(ID_TOOLS_EXPORTTIFF, OnUpdateToolsExporttiff) -END_MESSAGE_MAP() - - -// CJPEGsnoopDoc construction/destruction - -// Constructor allocates dynamic structures and resets state -CJPEGsnoopDoc::CJPEGsnoopDoc() -: m_pView(NULL) -{ - - // Ideally this would be passed by constructor, but simply access - // directly for now. - CJPEGsnoopApp* pApp; - pApp = (CJPEGsnoopApp*)AfxGetApp(); - ASSERT(pApp); - m_pAppConfig = pApp->m_pAppConfig; - ASSERT(m_pAppConfig); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::CJPEGsnoopDoc() Begin")); - - // Allocate the processing core - m_pCore = new CJPEGsnoopCore; - ASSERT(m_pCore); - if (!m_pCore) { - AfxMessageBox(_T("ERROR: Not enough memory for Processing Core")); - exit(1); - } - - // Setup link to CDocument for document log - ASSERT(glb_pDocLog); - glb_pDocLog->SetDoc(this); - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::CJPEGsnoopDoc() Checkpoint 1")); - - // Reset all members - Reset(); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::CJPEGsnoopDoc() Checkpoint 5")); - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::CJPEGsnoopDoc() End")); -} - -// Cleanup all of the allocated classes -CJPEGsnoopDoc::~CJPEGsnoopDoc() -{ - - if (m_pCore != NULL) { - delete m_pCore; - m_pCore = NULL; - } - - // Sever link to CDocument in log - ASSERT(glb_pDocLog); - glb_pDocLog->SetDoc(NULL); - -} - -// Reset is only called by the constructor, New and Open -// - Clear all major document state -// - Clear log -// -void CJPEGsnoopDoc::Reset() -{ - // Reset all members - m_pFile = NULL; - m_lFileSize = 0L; - - // No log data available until we open & process a file - m_strPathNameOpened = _T(""); - - // Indicate to JFIF ProcessFile() that document has changed - // and that the scan decode needs to be redone if it - // is to be displayed. - m_pCore->J_ImgSrcChanged(); - - // Clean up the quick log - glb_pDocLog->Clear(); - -} - -// NOTE -// Currently, the status bar assignment is done in both the -// OnNewDocument() and OnOpenDocument(). There is probably a -// single entrypoint that would be more suitable to use (one -// that guarantees that the window has been created, not in -// the constructor). - - -// Main entry point for creation of a new document -BOOL CJPEGsnoopDoc::OnNewDocument() -{ - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::OnNewDocument() Start")); - if (!CRichEditDoc::OnNewDocument()) - return FALSE; - - // TODO: add reinitialization code here - // (SDI documents will reuse this document) - Reset(); - - // --------------------------------------- - // Get the status bar and configure the decoder to link up to it - CStatusBar* pStatBar; - pStatBar = GetStatusBar(); - - // Hook up the status bar - m_pCore->J_SetStatusBar(pStatBar); - m_pCore->I_SetStatusBar(pStatBar); - // --------------------------------------- - - if (DEBUG_EN) m_pAppConfig->DebugLogAdd(_T("CJPEGsnoopDoc::OnNewDocument() End")); - - return TRUE; -} - -// Default CreateClientItem() implementation -CRichEditCntrItem* CJPEGsnoopDoc::CreateClientItem(REOBJECT* preo) const -{ - return new CJPEGsnoopCntrItem(preo, const_cast(this)); -} - - - - -// CJPEGsnoopDoc serialization -// -// NOTE: -// - This is called during the standard OnOpenDocument() and presumably -// OnSaveDocument(). Currently it is not implemented. -// -void CJPEGsnoopDoc::Serialize(CArchive& ar) -{ - if (ar.IsStoring()) - { - // TODO: add storing code here - } - else - { - // TODO: add loading code here - } - - // Calling the base class CRichEditDoc enables serialization - // of the container document's COleClientItem objects. - // TODO: set CRichEditDoc::m_bRTF = FALSE if you are serializing as text - CRichEditDoc::Serialize(ar); -} - - -// CJPEGsnoopDoc diagnostics - -#ifdef _DEBUG -void CJPEGsnoopDoc::AssertValid() const -{ - CRichEditDoc::AssertValid(); -} - -void CJPEGsnoopDoc::Dump(CDumpContext& dc) const -{ - CRichEditDoc::Dump(dc); -} -#endif //_DEBUG - - -// CJPEGsnoopDoc commands - - -// Add a line to the end of the log -// -// PRE: -// - m_pView (view from RichEdit must already be established) -// -int CJPEGsnoopDoc::AppendToLog(CString strTxt, COLORREF sColor) -{ - - ASSERT(m_pView); - if (!m_pView) return -1; - CRichEditCtrl* pCtrl = &m_pView->GetRichEditCtrl(); - ASSERT(pCtrl); - if (!pCtrl) return -1; - int nOldLines = 0, nNewLines = 0, nScroll = 0; - long nInsertionPoint = 0; - CHARFORMAT cf; - - // Save number of lines before insertion of new text - nOldLines = pCtrl->GetLineCount(); - // Initialize character format structure - cf.cbSize = sizeof(CHARFORMAT); - cf.dwMask = CFM_COLOR; - cf.dwEffects = 0; // To disable CFE_AUTOCOLOR - cf.crTextColor = sColor; - // Set insertion point to end of text - nInsertionPoint = pCtrl->GetWindowTextLength(); - pCtrl->SetSel(nInsertionPoint, -1); - // Set the character format - pCtrl->SetSelectionCharFormat(cf); - // Replace selection. Because we have nothing - // selected, this will simply insert - // the string at the current caret position. - pCtrl->ReplaceSel(strTxt); - // Get new line count - nNewLines = pCtrl->GetLineCount(); - // Scroll by the number of lines just inserted - nScroll = nNewLines - nOldLines; - //pCtrl->LineScroll(nScroll); - - // ********************************************************** - // Very important that we mark the RichEdit log as not - // being modified. Otherwise we will be asked to save - // changes... If the user hit Yes, they may overwrite their - // image file with the log file! - SetModifiedFlag(false); // Mark as not modified - // ********************************************************** - - return 0; -} - -// Call RedrawWindow() on RichEdit window -void CJPEGsnoopDoc::RedrawLog() -{ - ASSERT(m_pView); - if (!m_pView) return; - CRichEditCtrl* pCtrl = &m_pView->GetRichEditCtrl(); - ASSERT(pCtrl); - - pCtrl->RedrawWindow(); -} - -// Transfer the contents of the QuickLog buffer to the RichEdit control -// for display. -// -// In command-line nogui mode we skip this step as there may not be a -// RichEdit control assigned (m_pView will be NULL). Instead, we will -// later call DoLogSave() to release the buffer. -// -// PRE: -// - m_pView (view from RichEdit must already be established) -// -int CJPEGsnoopDoc::InsertQuickLog() -{ - - // Assume we are in GUI mode - if (!theApp.m_pAppConfig->bGuiMode) { - ASSERT(false); - return 0; - } - - ASSERT(m_pView); - if (!m_pView) return -1; - CRichEditCtrl* pCtrl = &m_pView->GetRichEditCtrl(); - ASSERT(pCtrl); - if (!pCtrl) return -1; - int nOldLines = 0, nNewLines = 0, nScroll = 0; - long nInsertionPoint = 0; - - - CHARFORMAT cf; - - // Save number of lines before insertion of new text - nOldLines = pCtrl->GetLineCount(); - - - // Set insertion point to end of text - nInsertionPoint = pCtrl->GetWindowTextLength(); - pCtrl->SetSel(nInsertionPoint, -1); - - - // Replace selection. Because we have nothing - // selected, this will simply insert - // the string at the current caret position. - - - pCtrl->SetRedraw(false); - unsigned nQuickLines = glb_pDocLog->GetNumLinesLocal(); - COLORREF nCurCol = RGB(0,0,0); - COLORREF nLastCol = RGB(255,255,255); - - for (unsigned nLine=0;nLineGetLineLogLocal(nLine,strTxt,sCol); - nCurCol = sCol; - - if (nCurCol != nLastCol) { - // Initialize character format structure - cf.cbSize = sizeof(CHARFORMAT); - cf.dwMask = CFM_COLOR; - cf.dwEffects = 0; // To disable CFE_AUTOCOLOR - cf.crTextColor = nCurCol; - // Set the character format - pCtrl->SetSelectionCharFormat(cf); - } - pCtrl->ReplaceSel(strTxt); - - } - pCtrl->SetRedraw(true); - pCtrl->RedrawWindow(); - - // Empty the quick log since we've used it now - glb_pDocLog->Clear(); - - // Get new line count - nNewLines = pCtrl->GetLineCount(); - // Scroll by the number of lines just inserted - nScroll = nNewLines - nOldLines; - //pCtrl->LineScroll(nScroll); - - // Scroll to the top of the window - pCtrl->LineScroll(-nNewLines); - - // ********************************************************** - // Very important that we mark the RichEdit log as not - // being modified. Otherwise we will be asked to save - // changes... If the user hit Yes, they may overwrite their - // image file with the log file! - SetModifiedFlag(false); // Mark as not modified - // ********************************************************** - - return 0; -} - -// Save the view pointer (from View init) -void CJPEGsnoopDoc::SetupView(CRichEditView* pView) -{ - m_pView = pView; -} - -// *************************************** - -// Fetch a pointer to the frame's status bar -// -// RETURN: -// - Pointer to the main frame's status bar -// -CStatusBar* CJPEGsnoopDoc::GetStatusBar() -{ - CWnd *pMainWnd = AfxGetMainWnd(); - if (!pMainWnd) return NULL; - - if (pMainWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd))) - { - CWnd* pMessageBar = ((CFrameWnd*)pMainWnd)->GetMessageBar(); - return DYNAMIC_DOWNCAST(CStatusBar,pMessageBar); - } - else - return DYNAMIC_DOWNCAST(CStatusBar,pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR)); -} - -// NOTE: -// - When calling AnalyzeClose() from CDocument, may need to address the following: -// // Mark the doc as clean so that we don't get questioned to save anytime -// // we change the file or quit. -// SetModifiedFlag(false); - - -// Read a line from the current opened file (m_pFile) -// UNUSED -BOOL CJPEGsnoopDoc::ReadLine(CString& strLine, - int nLength, - LONG lOffset /* = -1L */) -{ - ULONGLONG lPosition; - - if (lOffset != -1L) - lPosition = m_pFile->Seek(lOffset,CFile::begin); - else - lPosition = m_pFile->GetPosition(); - - if (lPosition == -1L) - { - TRACE2("CJPEGsnoopDoc::ReadLine returns FALSE Seek (%8.8lX, %8.8lX)\n", - lOffset, lPosition); - return FALSE; - } - - BYTE* pszBuffer = new BYTE[nLength]; - if (!pszBuffer) { - AfxMessageBox(_T("ERROR: Not enough memory for Document ReadLine")); - exit(1); - } - - int nReturned = m_pFile->Read(pszBuffer, nLength); - - // The Read is supposed to only return a maximum of nLength bytes - // This check helps avoid a Read Overrun Code Analysis warning below - // warning : C6385: Reading invalid data from 'pszBuffer': the readable size - // is 'nLength*1' bytes, but '2' bytes may be read. - if (nReturned > nLength) { - return FALSE; - } - - if (nReturned <= 0) - { - TRACE2("CJPEGsnoopDoc::ReadLine returns FALSE Read (%d, %d)\n", - nLength, - nReturned); - if (pszBuffer) { - delete [] pszBuffer; - } - return FALSE; - } - - CString strTemp; - CString strCharsIn; - - strTemp.Format(_T("%8.8I64X - "), lPosition); - strLine = strTemp; - - for (int nIndex = 0; nIndex < nReturned; nIndex++) - { - if (nIndex == 0) - strTemp.Format(_T("%2.2X"), pszBuffer[nIndex]); - else if (nIndex %16 == 0) - strTemp.Format(_T("=%2.2X"), pszBuffer[nIndex]); - else if (nIndex %8 == 0) - strTemp.Format(_T("-%2.2X"), pszBuffer[nIndex]); - else - strTemp.Format(_T(" %2.2X"), pszBuffer[nIndex]); - - if (_istprint(pszBuffer[nIndex])) - strCharsIn += pszBuffer[nIndex]; - else - strCharsIn += _T('.'); - strLine += strTemp; - } - - if (nReturned < nLength) - { - CString strPadding(_T(' '),3*(nLength-nReturned)); - strLine += strPadding; - } - - strLine += _T(" "); - strLine += strCharsIn; - - if (pszBuffer) { - delete [] pszBuffer; - } - - return TRUE; -} - - -// -------------------------------------------------------------------- -// --- START OF BATCH PROCESSING -// -------------------------------------------------------------------- - - - -// The root of the batch recursion. It simply jumps into the -// recursion loop but initializes the search to start with an -// empty search result. -// -// INPUT: -// - strBatchDir The root folder of the batch process -// - bRecSubdir Flag to descend recursively into sub-directories -// - bExtractAll Flag to extract all JPEGs from files -// -void CJPEGsnoopDoc::DoBatchProcess(CString strBatchDir,bool bRecSubdir,bool bExtractAll) -{ - bRecSubdir; // Unreferenced param - - CFolderDialog myFolderDlg(NULL); - CString strRootDir; - CString strDir; - bool bSubdirs = false; - - CString strDirSrc; - CString strDirDst; - - // Bring up dialog to select subdir recursion - bool bAllOk= true; - - // Here is where we ask about recursion - // We also ask whether "extract all" mode is desired - CBatchDlg myBatchDlg; - myBatchDlg.m_bProcessSubdir = false; - myBatchDlg.m_strDirSrc = m_pAppConfig->strBatchLastInput; - myBatchDlg.m_strDirDst = m_pAppConfig->strBatchLastOutput; - myBatchDlg.m_bExtractAll = bExtractAll; - if (myBatchDlg.DoModal() == IDOK) { - // Fetch the settings from the dialog - bSubdirs = (myBatchDlg.m_bProcessSubdir != 0); - bExtractAll = (myBatchDlg.m_bExtractAll != 0); - strDirSrc = myBatchDlg.m_strDirSrc; - strDirDst = myBatchDlg.m_strDirDst; - // Update the config - m_pAppConfig->strBatchLastInput = myBatchDlg.m_strDirSrc; - m_pAppConfig->strBatchLastOutput = myBatchDlg.m_strDirDst; - m_pAppConfig->Dirty(true); - } else { - bAllOk = false; - } - - // In Batch Processing mode, we'll temporarily turn off the Interactive mode - // so that any errors that arise in decoding are only output to the log files - // and not to an alert dialog box. - bool bInteractiveSaved = m_pAppConfig->bInteractive; - m_pAppConfig->bInteractive = false; - - if (bAllOk) { - - - // Allocate core engine - CJPEGsnoopCore* pSnoopCore = NULL; - pSnoopCore = new CJPEGsnoopCore; - ASSERT(pSnoopCore); - if (!pSnoopCore) { - return; - } - - // Enable and hook up the status bar - CStatusBar* pStatBar; - pStatBar = GetStatusBar(); - pSnoopCore->SetStatusBar(pStatBar); - - // Indicate long operation ahead! - CWaitCursor wc; - - // TODO: Add a "Cancel Dialog" for the batch operation - // Example code that I can use for single-stepping the operation: - // - // // === START - // COperationDlg LengthyOp(this); - // LengthyOp.SetFunctions( PrepareOperation, NextIteration, GetProgress ); - // - // // Until-done based - // BOOL bOk = LengthyOp.RunUntilDone( true ); - // // === END - - - // Generate the batch file list - pSnoopCore->GenBatchFileList(strDirSrc,strDirDst,bSubdirs,bExtractAll); - - // Now that we've created the list of files, start processing them - unsigned nBatchFileCount; - nBatchFileCount = pSnoopCore->GetBatchFileCount(); - - // TODO: Clear the current RichEdit log - DeleteContents(); - - CString strStat; - for (unsigned nFileInd=0;nFileIndGetBatchFileInfo(nFileInd); - strStat.Format(_T("Batch processing file %6u of %6u (%6.2f %%): [%s]"), - nFileInd+1,nBatchFileCount,(100.0*(nFileInd+1)/nBatchFileCount), - (LPCTSTR)strSrcFname); - - // Inject progress message into main log window - AppendToLog(strStat+_T("\n"),RGB(1,1,1)); - RedrawLog(); - - // Process file - pSnoopCore->DoBatchFileProcess(nFileInd,true,bExtractAll); - } - - AppendToLog(_T("Batch processing complete"),RGB(1,255,1)); - RedrawLog(); - - // TODO: Add the most recent file to the current RichEdit log - - // TODO: Clean up after last log output - - // Alert the user that we are done - // TODO: Is this the right flag to check? - if (bInteractiveSaved) { - AfxMessageBox(_T("Batch Processing Complete!")); - } - - // Deallocate the core - if (pSnoopCore) { - delete pSnoopCore; - pSnoopCore = NULL; - } - - } - - // Restore the Interactive mode setting - m_pAppConfig->bInteractive = bInteractiveSaved; - -} - - -// -------------------------------------------------------------------- -// --- END OF BATCH PROCESSING -// -------------------------------------------------------------------- - - - -// Menu command for specifying a file offset to start decoding process -// - Present a dialog box that allows user to specify the address -// -// TODO: Perhaps this menu item should be disabled when no file has been analyzed -// -void CJPEGsnoopDoc::OnFileOffset() -{ - COffsetDlg offsetDlg; - - // NOTE: This function assumes that we've previously opened a file - // Otherwise, there isn't much point in setting the offset value - // since it gets reset to 0 when we open a new file manually! - - if (!m_pCore->IsAnalyzed()) { - return; - } - if (!m_pCore->AnalyzeOpen()) { - return; - } - - offsetDlg.SetOffset(theApp.m_pAppConfig->nPosStart); - if (offsetDlg.DoModal() == IDOK) { - theApp.m_pAppConfig->nPosStart = offsetDlg.GetOffset(); - - // Clean out document first (especially buffer) - DeleteContents(); - // Process the file from new offset - m_pCore->AnalyzeFileDo(); - InsertQuickLog(); - - // Indicate that scan data needs to be re-analyzed - m_pCore->J_ImgSrcChanged(); - - // Now try to update all views. This is particularly important - // for View 2 (ScrollView) as it does not automatically invalidate - UpdateAllViews(NULL); - } - - if (m_pCore->IsAnalyzed()) { - m_pCore->AnalyzeClose(); - } - - -} - -// Menu command for Adding camera signature to the signature database -// - This command brings up a dialog box to specify the -// characteristics of the selected image -// - Upon completion, the current signature is added to the database -// -void CJPEGsnoopDoc::OnToolsAddcameratodb() -{ - CDbSubmitDlg submitDlg; - unsigned nUserSrcPre; - teSource eUserSrc; - CString strUserSoftware; - CString strQual; - CString strUserNotes; - - // Return values from JfifDec - CString strDecHash; - CString strDecHashRot; - CString strDecImgExifMake; - CString strDecImgExifModel; - CString strDecImgQualExif; - CString strDecSoftware; - teDbAdd eDecDbReqSuggest; - - m_pCore->J_GetDecodeSummary(strDecHash,strDecHashRot,strDecImgExifMake,strDecImgExifModel,strDecImgQualExif,strDecSoftware,eDecDbReqSuggest); - - if (strDecHash == _T("NONE")) - { - // No valid signature, can't submit! - CString strTmp = _T("No valid signature could be created, so DB submit is temporarily disabled"); - glb_pDocLog->AddLineErr(strTmp); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strTmp); - - return; - } - - submitDlg.m_strExifMake = strDecImgExifMake; - submitDlg.m_strExifModel = strDecImgExifModel; - submitDlg.m_strExifSoftware = strDecSoftware; - submitDlg.m_strUserSoftware = strDecSoftware; - submitDlg.m_strSig = strDecHash; // Only show unrotated sig - submitDlg.m_strQual = strDecImgQualExif; - - // Does the image appear to be edited? If so, warn - // the user before submission... - - if (eDecDbReqSuggest == DB_ADD_SUGGEST_CAM) { - submitDlg.m_nSource = 0; // Camera - } else if (eDecDbReqSuggest == DB_ADD_SUGGEST_SW) { - submitDlg.m_nSource = 1; // Software - } else { - submitDlg.m_nSource = 2; // I don't know! - } - - - if (submitDlg.DoModal() == IDOK) { - strQual = submitDlg.m_strQual; - nUserSrcPre = submitDlg.m_nSource; - strUserSoftware = submitDlg.m_strUserSoftware; - strUserNotes = submitDlg.m_strNotes; - - // Prior to v1.8.0 the nUserSrcPre was compared against the ENUM_SOURCE_* values - // - This led to an incorrect mapping to the database value - // - As of v1.8.0 (and DB signature version "03"), this has been corrected - // and a "js_vers" parameter is now passed to the external DB to help resolve - // the error for older versions. - switch (nUserSrcPre) { - case 0: - eUserSrc = ENUM_SOURCE_CAM; - break; - case 1: - eUserSrc = ENUM_SOURCE_SW; - break; - case 2: - eUserSrc = ENUM_SOURCE_UNSURE; - break; - default: - eUserSrc = ENUM_SOURCE_UNSURE; - break; - - } - - m_pCore->J_PrepareSendSubmit(strQual,eUserSrc,strUserSoftware,strUserNotes); - } -} - -// Menu enable status for Tools -> Add camera to database -// -void CJPEGsnoopDoc::OnUpdateToolsAddcameratodb(CCmdUI *pCmdUI) -{ - pCmdUI->Enable(m_pCore->IsAnalyzed()); -} - -// Menu command for searching forward in file for JPEG -// - The search process looks for the JFIF_SOI marker -// -void CJPEGsnoopDoc::OnToolsSearchforward() -{ - // Search for start: - unsigned long nSearchPos = 0; - unsigned long nStartPos; - bool bSearchResult; - CString strTmp; - - // Get status bar pointer - CStatusBar* pStatBar; - pStatBar = GetStatusBar(); - - // NOTE: m_bFileAnalyzed doesn't actually refer to underlying file.... - // so therefore it is not reliable. - - // If file got renamed or moved, AnalyzeOpen() will return false - if (m_pCore->AnalyzeOpen() == false) { - return; - } - - nStartPos = theApp.m_pAppConfig->nPosStart; - m_pCore->J_ImgSrcChanged(); - - // Update status bar - if (pStatBar) { - strTmp.Format(_T("Searching forward...")); - pStatBar->SetPaneText(0,strTmp); - } - - m_pCore->B_SetStatusBar(GetStatusBar()); - bSearchResult = m_pCore->B_BufSearch(nStartPos,0xFFD8FF,3,true,nSearchPos); - - // Update status bar - if (pStatBar) { - strTmp.Format(_T("Done")); - pStatBar->SetPaneText(0,strTmp); - } - - if (bSearchResult) { - theApp.m_pAppConfig->nPosStart = nSearchPos; - Reprocess(); - } else { - if (m_pAppConfig->bInteractive) - AfxMessageBox(_T("No SOI Marker found in Forward search")); - } - m_pCore->AnalyzeClose(); - -} - -// Menu command for searching reverse in file for JPEG image -// - The search process looks for the JFIF_SOI marker -// -void CJPEGsnoopDoc::OnToolsSearchreverse() -{ - // Search for start: - - unsigned long nSearchPos = 0; - unsigned long nStartPos; - bool bSearchResult; - CString strTmp; - - // Get status bar pointer - CStatusBar* pStatBar; - pStatBar = GetStatusBar(); - - // If file got renamed or moved, AnalyzeOpen() will return false - if (m_pCore->AnalyzeOpen() == false) { - return; - } - - nStartPos = theApp.m_pAppConfig->nPosStart; - m_pCore->J_ImgSrcChanged(); - - // Don't attempt to search past start of file - if (nStartPos > 0) { - - // Update status bar - if (pStatBar) { - strTmp.Format(_T("Searching reverse...")); - pStatBar->SetPaneText(0,strTmp); - } - - m_pCore->B_SetStatusBar(GetStatusBar()); - bSearchResult = m_pCore->B_BufSearch(nStartPos,0xFFD8FF,3,false,nSearchPos); - - // Update status bar - if (pStatBar) { - strTmp.Format(_T("Done")); - pStatBar->SetPaneText(0,strTmp); - } - - if (bSearchResult) { - theApp.m_pAppConfig->nPosStart = nSearchPos; - Reprocess(); - } else { - theApp.m_pAppConfig->nPosStart = 0; - if (m_pAppConfig->bInteractive) - AfxMessageBox(_T("No SOI Marker found in Reverse search")); - Reprocess(); - } - } - m_pCore->AnalyzeClose(); - -} - -// Menu enable status for Tools -> Search forward -// -void CJPEGsnoopDoc::OnUpdateToolsSearchforward(CCmdUI *pCmdUI) -{ - pCmdUI->Enable(m_pCore->IsAnalyzed()); -} - -// Menu enable status for Tools -> Search reverse -// -void CJPEGsnoopDoc::OnUpdateToolsSearchreverse(CCmdUI *pCmdUI) -{ - pCmdUI->Enable(m_pCore->IsAnalyzed()); -} - -// Reprocess the current file -// - This command will initiate all processing of the currently-opened file -// - Show a coach message for first time ever -// - Update both views (invalidate and redraw) -// -BOOL CJPEGsnoopDoc::Reprocess() -{ - BOOL bRet = false; - - // ------------------------------------------------ - // Give coach message - // ------------------------------------------------ - - // Show coach message once - if (theApp.m_pAppConfig->bDecodeScanImg && - theApp.m_pAppConfig->bCoachDecodeIdct) { - // Show the coaching dialog - CNoteDlg dlg; - if (theApp.m_pAppConfig->bDecodeScanImgAc) { - dlg.strMsg = COACH_DECODE_IDCT_AC; - } else { - dlg.strMsg = COACH_DECODE_IDCT_DC; - } - dlg.DoModal(); - theApp.m_pAppConfig->bCoachDecodeIdct = !dlg.bCoachOff; - theApp.m_pAppConfig->Dirty(); - } - - // ------------------------------------------------ - // Reprocess file - // ------------------------------------------------ - - // Clean out document first (especially buffer) - DeleteContents(); - // Now we can reprocess the file - bRet = m_pCore->AnalyzeFile(m_strPathName); - // Insert the log - InsertQuickLog(); - - // ------------------------------------------------ - // Update views - // ------------------------------------------------ - - // Now force a redraw (especially for Img View window) - // Force a redraw so that we can see animated previews (e.g. AVI) - // when holding down Fwd/Rev Search hotkey - - POSITION pos = GetFirstViewPosition(); - if (pos != NULL) { - CView* pFirstView = GetNextView( pos ); - pFirstView->Invalidate(); - pFirstView->RedrawWindow(NULL,0,RDW_UPDATENOW); - } - if (pos != NULL) { - CView* pSecondView = GetNextView( pos ); - pSecondView->Invalidate(); - pSecondView->RedrawWindow(NULL,0,RDW_UPDATENOW); - } - - return bRet; -} - - - -// Menu command to reprocess the current file -// - This command will initiate all processing of the currently-opened file -// -void CJPEGsnoopDoc::OnFileReprocess() -{ - m_pCore->J_ImgSrcChanged(); - Reprocess(); -} - -// Trap the end of the JPEGsnoop document in case we want to perform -// any other clearing actions. -void CJPEGsnoopDoc::DeleteContents() -{ - // TODO: Add your specialized code here and/or call the base class - - CRichEditDoc::DeleteContents(); -} - -// Open Document handler -// -// This is called from the File->Open... as well as -// from command-line execution and -// during MRU list invocation: -// CJPEGsnoopDoc::OnOpenDocument() -// CSingleDocTemplate::OnOpenDocumentFile() -// CDocManager::OnOpenDocumentFile() -// CWinApp::OpenDocumentFile() -// CWinApp::OnOpenRecentFile() -// ... -// -// NOTES: -// Want to avoid automatic StreamIn() and serialization that -// will attempt to be done on the JPEG file into the RichEditCtrl. -// However, these probably fail (not RTF) or else relies on the -// serialize function here to do something. -// -BOOL CJPEGsnoopDoc::OnOpenDocument(LPCTSTR lpszPathName) -{ - // Before entering this function, the default file dialog - // has already been presented, so we can't override anything. - - // FIXME: - // Not sure if we should use the inherited OnOpenDocument() call - // as it will try to interpret the file as well as call the - // DeleteContents() on the RichEdit. - if (!CRichEditDoc::OnOpenDocument(lpszPathName)) - return FALSE; - - // Reset internal state - Reset(); - - SetPathName(lpszPathName,true); // Sets m_strPathName, validate len, sets window title - - // Save mirror of m_strPathName just so that we can add safety - // check during OnSaveDocument(). By the time OnSaveDocument() is called, - // the original m_strPathName has already been modified to indicate the - // log/output filename. - m_strPathNameOpened = m_strPathName; - - BOOL bStatus; - - // Reset the offset pointer! - theApp.m_pAppConfig->nPosStart = 0; - - // Save the current filename into the temporary config space - // This is only done to assist debugging reporting - m_pAppConfig->strCurFname = m_strPathName; - - // --------------------------------------- - // Get the status bar and configure the decoder to link up to it - CStatusBar* pStatBar; - pStatBar = GetStatusBar(); - - // Hook up the status bar - m_pCore->J_SetStatusBar(pStatBar); - m_pCore->I_SetStatusBar(pStatBar); - // --------------------------------------- - - // Now process the file! - bStatus = Reprocess(); - - return bStatus; -} - - -// Menu comamnd for File -> Save As -// - Brings up a Save As dialog box before saving -void CJPEGsnoopDoc::OnFileSaveAs() -{ - - CString strPathName; - BOOL bRTF; - - // Preserve - strPathName = m_strPathName; - bRTF = m_bRTF; - - // FIXME: - // Need to determine the best method to allow user selection between - // plain-text and RTF formats and have the filename change when they - // change the drop-down filter type. Currently the user would have - // to do that manually. - // - // Possible solution: Use OnLBSelChangeNotify override in CFileDialog - // - // For now, force plain-text output - // - m_bRTF = false; - m_strPathName = m_strPathName + _T(".txt"); - - //bool status = 0; - /* - TCHAR aszFilter[] = - _T("Log - Plain Text (*.txt)|*.txt|")\ - //_T("Log - Rich Text (*.rtf)|*.rtf|")\ - _T("All Files (*.*)|*.*||"); - */ - TCHAR aszFilter[] = - _T("Log - Plain Text (*.txt)|*.txt|")\ - _T("All Files (*.*)|*.*||"); - - CFileDialog FileDlg(FALSE, _T(".txt"), m_strPathName, OFN_OVERWRITEPROMPT, aszFilter); - - CString strTitle; - CString strFileName; - VERIFY(strTitle.LoadString(IDS_CAL_FILESAVE)); - FileDlg.m_ofn.lpstrTitle = strTitle; - - if( FileDlg.DoModal() == IDOK ) - { - strFileName = FileDlg.GetPathName(); - - // Determine the extension - // If the user entered an ".rtf" extension, then we allow RTF - // saving, otherwise we default to plain text - CString cstrSelFileExt = strFileName.Right(strFileName.GetLength() - strFileName.ReverseFind('.')); - - //if (cstrSelFileExt == _T(".rtf")) { - // m_bRTF = true; - //} - - // Perform the save - DoSave(strFileName,false); - - } - - // Revert - m_strPathName = strPathName; - m_bRTF = bRTF; -} - - - -// Menu command for Channel Preview -// - Supports a range in sub-items -// -void CJPEGsnoopDoc::OnPreviewRng(UINT nID) -{ - unsigned nInd; - nInd = nID - ID_PREVIEW_RGB + PREVIEW_RGB; - m_pCore->I_SetPreviewMode(nInd); - UpdateAllViews(NULL); -} - -// Menu enable status for Channel Preview -// - Supports a range in sub-items -// -void CJPEGsnoopDoc::OnUpdatePreviewRng(CCmdUI* pCmdUI) -{ - unsigned nID; - nID = pCmdUI->m_nID - ID_PREVIEW_RGB + PREVIEW_RGB; - if (m_pCore->I_GetPreviewMode() == nID) { - pCmdUI->SetCheck(true); - } else { - pCmdUI->SetCheck(false); - } -} - -// Menu command for Zoom -// - Supports a range in sub-items -// -void CJPEGsnoopDoc::OnZoomRng(UINT nID) -{ - unsigned nInd; - if (nID == ID_IMAGEZOOM_ZOOMIN) { - m_pCore->I_SetPreviewZoom(true,false,false,0); - UpdateAllViews(NULL); - } else if (nID == ID_IMAGEZOOM_ZOOMOUT) { - m_pCore->I_SetPreviewZoom(false,true,false,0); - UpdateAllViews(NULL); - } else { - nInd = nID - ID_IMAGEZOOM_12 + PRV_ZOOM_12; - m_pCore->I_SetPreviewZoom(false,false,true,nInd); - UpdateAllViews(NULL); - } -} - -// Menu enable status for Zoom -// - Supports a range in sub-items -// -void CJPEGsnoopDoc::OnUpdateZoomRng(CCmdUI* pCmdUI) -{ - unsigned nID; - if (pCmdUI->m_nID == ID_IMAGEZOOM_ZOOMIN) { - // No checkmark - } else if (pCmdUI->m_nID == ID_IMAGEZOOM_ZOOMOUT) { - // No checkmark - } else { - nID = pCmdUI->m_nID - ID_IMAGEZOOM_12 + PRV_ZOOM_12; - unsigned nGetZoom; - nGetZoom = m_pCore->I_GetPreviewZoomMode(); - unsigned nMenuOffset; - nMenuOffset = pCmdUI->m_nID - ID_IMAGEZOOM_12; - pCmdUI->SetCheck(m_pCore->I_GetPreviewZoomMode() == nID); - } -} - -// Menu command for Searching an Executable for a DQT table -// - File is already open (and DQT present) -// - Look in another file (exe) to see if a DQT exists -// -void CJPEGsnoopDoc::OnToolsSearchexecutablefordqt() -{ - - // Don't need to do AnalyzeOpen() because a file pointer to - // the executable is created here. - - //bool bStatus = 0; - TCHAR astrFilter[] = - _T("Executable (*.exe)|*.exe|")\ - _T("DLL Library (*.dll)|*.dll|")\ - _T("All Files (*.*)|*.*||"); - - CFileDialog FileDlg(TRUE, _T(".exe"), NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, astrFilter); - - CString strTitle; - CString strFileName; - CString strPathName; - VERIFY(strTitle.LoadString(IDS_CAL_EXE_OPEN)); - FileDlg.m_ofn.lpstrTitle = strTitle; - - // Extend the maximum filename length - // Default is 64 for filename, 260 for path - // Some users have requested support for longer filenames - LPTSTR spFilePath; - spFilePath = new TCHAR[501]; - spFilePath[0] = TCHAR(0); - FileDlg.m_pOFN->lpstrFile = spFilePath; - FileDlg.m_pOFN->nMaxFile = 500; - FileDlg.m_pOFN->nMaxFileTitle = 300; - - if( FileDlg.DoModal() != IDOK ) - { - return; - } - - // We selected a file! - strFileName = FileDlg.GetFileName(); - strPathName = FileDlg.GetPathName(); - - CFile* pFileExe; - CString strTmp; - - - ASSERT(strFileName != _T("")); - if (strFileName == _T("")) { - if (m_pAppConfig->bInteractive) - AfxMessageBox(_T("ERROR: SearchExe() but strFileName empty")); - return; - } - - try - { - // Open specified file - pFileExe = new CFile(strPathName, CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone); - } - catch (CFileException* e) - { - TCHAR msg[MAX_BUF_EX_ERR_MSG]; - CString strError; - e->GetErrorMessage(msg,MAX_BUF_EX_ERR_MSG); - e->Delete(); - strError.Format(_T("ERROR: Couldn't open file [%s]: [%s]"), - (LPCTSTR)strFileName, (LPCTSTR)msg); - if (m_pAppConfig->bInteractive) - AfxMessageBox(strError); - pFileExe = NULL; - - return; // FALSE; - - } - - // Set the file size variable - unsigned long lFileSize = (unsigned long)pFileExe->GetLength(); - - // Search the file! - - glb_pDocLog->AddLineHdr(_T("*** Searching Executable for DQT ***")); - strTmp.Format(_T(" Filename: [%s]"),(LPCTSTR)strPathName); - glb_pDocLog->AddLine(strTmp); - strTmp.Format(_T(" Size: [%lu]"),lFileSize); - glb_pDocLog->AddLine(strTmp); - - CwindowBuf* pExeBuf; - pExeBuf = new CwindowBuf(); - - ASSERT(pExeBuf); - if (!pExeBuf) { - if (m_pAppConfig->bInteractive) - AfxMessageBox(_T("ERROR: Not enough memory for EXE Search")); - return; - } - - pExeBuf->SetStatusBar(GetStatusBar()); - pExeBuf->BufFileSet(pFileExe); - pExeBuf->BufLoadWindow(0); - - //bool bDoneFile = false; - //long nFileInd = 0; - unsigned nEntriesWidth; - bool bEntriesByteSwap; - unsigned long nFoundPos=0; - bool bFound = false; - //bool bFoundEntry = false; - - BYTE abSearchMatrix[(64*4)+4]; - unsigned nSearchMatrixLen; - unsigned nSearchSetMax; - - unsigned nVal; - - bool bAllSame = true; - bool bBaseline = true; - - nSearchSetMax = 1; - if (m_pCore->IsAnalyzed()) { - nVal = m_pCore->I_GetDqtEntry(0,0); - for (unsigned ind=1;ind<64;ind++) { - if (m_pCore->I_GetDqtEntry(0,ind) != nVal) { - bAllSame = false; - } - // Are there any DQT entries > 8 bits? - if (m_pCore->I_GetDqtEntry(0,ind) > 255) { - bBaseline = false; - } - - } - - if (bAllSame) { - strTmp.Format(_T(" NOTE: Because the JPEG's DQT Luminance table is constant nValue (0x%02X),_T("),nVal); - glb_pDocLog->AddLineWarn(strTmp); - glb_pDocLog->AddLineWarn(_T(") matching for this table has been disabled.")); - glb_pDocLog->AddLineWarn(_T(" Please select a different reference image.")); - nSearchSetMax = 1; - } else { - nSearchSetMax = 2; - } - } - - - glb_pDocLog->AddLine(_T(" Searching for DQT Luminance tables:")); - for (unsigned nZigZagSet=0;nZigZagSet<2;nZigZagSet++) { - strTmp.Format(_T(" DQT Ordering: %s"),(nZigZagSet?_T("post-zigzag"):_T("pre-zigzag"))); - glb_pDocLog->AddLine(strTmp); - for (unsigned nSearchSet=0;nSearchSetAddLine(strTmp); - } else { - strTmp.Format(_T(" Matching [%s]"),(LPCTSTR)m_strPathName); - glb_pDocLog->AddLine(strTmp); - } - - // Perform the search using a number of different variations on - // byteswap and matrix element width - for (unsigned nSearchPattern=0;nSearchPattern<5;nSearchPattern++) { - - switch(nSearchPattern) { - case 0: - nEntriesWidth = 1; - bEntriesByteSwap = false; - break; - case 1: - nEntriesWidth = 2; - bEntriesByteSwap = false; - break; - case 2: - nEntriesWidth = 2; - bEntriesByteSwap = true; - break; - case 3: - nEntriesWidth = 4; - bEntriesByteSwap = false; - break; - case 4: - nEntriesWidth = 4; - bEntriesByteSwap = true; - break; - default: - nEntriesWidth = 1; - bEntriesByteSwap = false; - break; - } - if (nEntriesWidth == 1) { - strTmp.Format(_T(" Searching patterns with %u-byte DQT entries"), - nEntriesWidth); - glb_pDocLog->AddLine(strTmp); - if (!bBaseline) { - strTmp.Format(_T(" DQT Table is not baseline, skipping 1-byte search")); - glb_pDocLog->AddLine(strTmp); - continue; - } - } else { - strTmp.Format(_T(" Searching patterns with %u-byte DQT entries%s"), - nEntriesWidth,(bEntriesByteSwap)?_T(", endian byteswap"):_T("")); - glb_pDocLog->AddLine(strTmp); - } - - nSearchMatrixLen = (nEntriesWidth*64); - - for (unsigned nInd=0;nIndJ_GetDqtZigZagIndex(nInd,(nZigZagSet!=0)); - if (nSearchSet == 0) { - // Standard JPEG table - nVal = m_pCore->J_GetDqtQuantStd(nDqtInd); - } else { - // Matching JPEG table - nVal = m_pCore->I_GetDqtEntry(0,nDqtInd); - } - - for (unsigned nEntryInd=0;nEntryInd> 8; - } else { - abSearchMatrix[(nInd*2)+(2-1)] = (nVal & 0x00FF); - abSearchMatrix[(nInd*2)+(2-2)] = (nVal & 0xFF00) >> 8; - } - } - } else if (nEntriesWidth == 4) { - if (bBaseline) { - if (bEntriesByteSwap) { - abSearchMatrix[(nInd*4)+0] = (nVal & 0x00FF); - } else { - abSearchMatrix[(nInd*4)+(4-1)] = (nVal & 0x00FF); - } - } else { - if (bEntriesByteSwap) { - abSearchMatrix[(nInd*4)+0] = (nVal & 0x00FF); - abSearchMatrix[(nInd*4)+1] = (nVal & 0xFF00) >> 8; - } else { - abSearchMatrix[(nInd*4)+(4-1)] = (nVal & 0x00FF); - abSearchMatrix[(nInd*4)+(4-2)] = (nVal & 0xFF00) >> 8; - } - } - } - - } - - bool bDoneAllMatches = false; - unsigned long nStartOffset = 0; - while (!bDoneAllMatches) { - - bFound = pExeBuf->BufSearchX(nStartOffset,abSearchMatrix,64*nEntriesWidth,true,nFoundPos); - if (bFound) { - strTmp.Format(_T(" Found @ 0x%08X"),nFoundPos); - glb_pDocLog->AddLineGood(strTmp); - nStartOffset = nFoundPos+1; - } else { - bDoneAllMatches = true; - } - } - - - } // nSearchPattern - } // nSearchSet - } // nZigZagSet - - glb_pDocLog->AddLine(_T(" Done Search")); - - // Since this command can be run without a normal file open, we - // need to flush the output if we happen to be in quick log mode - InsertQuickLog(); - - - if (pExeBuf) { - delete pExeBuf; - } -} - - - -// Menu enable status for File->Reprocess -// -void CJPEGsnoopDoc::OnUpdateFileReprocess(CCmdUI *pCmdUI) -{ - pCmdUI->Enable(m_pCore->IsAnalyzed()); -} - -// Menu enable status for File->Save As -// -void CJPEGsnoopDoc::OnUpdateFileSaveAs(CCmdUI *pCmdUI) -{ - pCmdUI->Enable(m_pCore->IsAnalyzed()); -} - -// NOTE: This routine should ONLY be called if we have selected -// a different name for the file (i.e. not the original JPEG file!) -// The toolbar and menu items are hooked up to Save As, so there -// should be nothing else connected to this. -// -// Just in case, I am checking the filename to see if it matches -// the last opened file. If so, I abort. -BOOL CJPEGsnoopDoc::OnSaveDocument(LPCTSTR lpszPathName) -{ - // Different from opened file, we're ok - if (lpszPathName != m_strPathNameOpened) { - return CRichEditDoc::OnSaveDocument(lpszPathName); - } else { - // Pretend we were successful so that we don't allow it - // to try to write the file if not successful! - AfxMessageBox(_T("NOTE: Attempt to overwrite source file prevented")); - return true; - } - - //return CRichEditDoc::OnSaveDocument(lpszPathName); - -} - - - - -// Menu command to extract embedded JPEGs from a file -// -void CJPEGsnoopDoc::OnToolsExtractembeddedjpeg() -{ - DoGuiExtractEmbeddedJPEG(); -} - - -// Extracts an embedded JPEG from the current file -// Also support extraction of all embedded JPEG from the file (default for non-interactive -// and optional in interactive mode). -// -// NOTE: In "Extract All" mode, all file types are processed. -// -void CJPEGsnoopDoc::DoGuiExtractEmbeddedJPEG() -{ - bool bAllOk = true; - CExportDlg dlgExport; - CString strTmp; - //unsigned int nFileSize = 0; - - // Original function params - //bool bInteractive = true; - //bool bInsDhtAvi = false; - CString strOutPath = _T(""); - - bool bOverlayEn = false; - bool bForceSoi = false; - bool bForceEoi = false; - bool bIgnoreEoi = false; - bool bExtractAllEn = false; - bool bDhtAviInsert = false; - CString strOffsetStart = _T(""); - - // Get operation configuration from user - // ------------------------------------------ - - // Determine if file is AVI - // If so, default to DHT AVI insert mode - // NOTE: Calling GetAviMode() requires that the CDocument JFIF decoder - // instance has processed the file. - bool bIsAvi,bIsMjpeg; - m_pCore->J_GetAviMode(bIsAvi,bIsMjpeg); - dlgExport.m_bDhtAviInsert = bIsMjpeg; - - dlgExport.m_bOverlayEn = false; // Changed default on 08/22/2011 - dlgExport.m_bForceSoi = false; - dlgExport.m_bForceEoi = false; - dlgExport.m_bIgnoreEoi = false; - dlgExport.m_bExtractAllEn = false; - dlgExport.m_strOffsetStart = strTmp; - - if (dlgExport.DoModal() == IDOK) { - // OK - bExtractAllEn = (dlgExport.m_bExtractAllEn != 0); - bForceSoi = (dlgExport.m_bForceSoi != 0); - bForceEoi = (dlgExport.m_bForceEoi != 0); - bIgnoreEoi = (dlgExport.m_bIgnoreEoi != 0); - bOverlayEn = (dlgExport.m_bOverlayEn != 0); - bDhtAviInsert = (dlgExport.m_bDhtAviInsert != 0); - } else { - bAllOk = false; - } - - - // Confirm output filename - // ------------------------------------------ - - CString strInputFname; - CString strExportFname; - - // Preserve CDocument settings - BOOL bSavedRTF = m_bRTF; - - // Override the RTF setting - m_bRTF = false; - - // Generate default export filename - strInputFname = m_strPathName; - strExportFname = strInputFname + _T(".export.jpg"); - - // Save File Dialog - TCHAR aszFilter[] = - _T("JPEG Image (*.jpg)|*.jpg|")\ - _T("All Files (*.*)|*.*||"); - - CFileDialog FileDlg(FALSE, _T(".jpg"), strExportFname, OFN_OVERWRITEPROMPT, aszFilter); - - CString title; - //VERIFY(title.LoadString(IDS_CAL_FILESAVE)); - title = _T("Save Exported JPEG file as"); - FileDlg.m_ofn.lpstrTitle = title; - - INT_PTR nDlgResult = FileDlg.DoModal(); - if (nDlgResult == IDOK) { - // Update the export filename - strExportFname = FileDlg.GetPathName(); - } - - // Now revert the CDocument members - m_bRTF = bSavedRTF; - - if (nDlgResult != IDOK) { - // User wanted to abort - strTmp.Format(_T(" User cancelled")); - glb_pDocLog->AddLineErr(strTmp); - - bAllOk = false; - return; - } - - - // Extract file operation - // ------------------------------------------ - - // Clear the log as DoExtractEmbeddedJPEG will re-analyze file into log - DeleteContents(); - - m_pCore->DoExtractEmbeddedJPEG(strInputFname,strExportFname,bOverlayEn,bForceSoi,bForceEoi,bIgnoreEoi,bExtractAllEn,bDhtAviInsert,strOutPath); - - // As the extraction adds some status lines, update the log - InsertQuickLog(); - -} - - - -// Menu enable status for Tools -> Extract embedded JPEG -void CJPEGsnoopDoc::OnUpdateToolsExtractembeddedjpeg(CCmdUI *pCmdUI) -{ - pCmdUI->Enable(m_pCore->IsAnalyzed()); -} - -// Create static wrapper for B_Buf callback function -BYTE CJPEGsnoopDoc::CbWrap_B_Buf(void* pWrapClass,unsigned long nNum,bool bBool) -{ - CJPEGsnoopDoc* mySelf = (CJPEGsnoopDoc*) pWrapClass; - return mySelf->m_pCore->B_Buf(nNum,bBool); -} - - - -// Menu command for configuring the file overlays -// - This method allows user to specify one or more bytes to -// temporarily replace the currently active file processing -// -void CJPEGsnoopDoc::OnToolsFileoverlay() -{ - CString strDlg; - - unsigned nOffset; - CString strValNew; - unsigned nValLen; - BYTE anValData[16]; - - bool bCurEn; - BYTE* pCurData; - unsigned nCurLen; - unsigned nCurStart; - CString strCurDataHex; - CString strCurDataBin; - CString strTmp; - CString strTmpByte; - unsigned nTmpByte; - - // NOTE: This function assumes that we've previously opened a file - // Otherwise, there isn't much point in setting the offset value - // since it gets reset to 0 when we open a new file manually! - - bool bDone = false; - while (!bDone) { - - strCurDataHex = _T(""); - strCurDataBin = _T(""); - - if (m_pCore->AnalyzeOpen() == false) { - return; - } - - // Set overlay dialog starting values... - bCurEn = m_pCore->B_OverlayGet(0,pCurData,nCurLen,nCurStart); - // Were any overlays previously defined? - if (!bCurEn) { - // If not, don't try to read the buffer! Simply force string - strCurDataHex = _T(""); - strCurDataBin = _T(""); - nCurStart = 0; - nCurLen = 0; - } else { - for (unsigned nInd=0;nIndB_OverlayInstall(0,anValData,nValLen,nOffset, - 0,0,0,0,0,0,0); - } else { - // Assume that if I'm using this dialog method to access the overlay - // that I'm only ever using a single overlay! Therefore, to be safe - // I'm going to call OverlayRemoveAll() instead of OverlayRemove() (which just - // deletes last one). - m_pCore->B_OverlayRemoveAll(); - } - - m_pCore->J_ImgSrcChanged(); - - Reprocess(); - - } else { - } - - m_pCore->AnalyzeClose(); - - if (!dlgOverlay.m_bApply) { - bDone = true; - } - - } // while -} - - -// Menu enable status for Tools -> File overlay -void CJPEGsnoopDoc::OnUpdateToolsFileoverlay(CCmdUI *pCmdUI) -{ - if (m_pCore->IsAnalyzed()) { - pCmdUI->Enable(true); - } else { - pCmdUI->Enable(false); - } -} - -// Create static wrapper for I_LookupFilePosPix callback function -void CJPEGsnoopDoc::CbWrap_I_LookupFilePosPix(void* pWrapClass, - unsigned int nX, unsigned int nY, unsigned int &nByte, unsigned int &nBit) -{ - CJPEGsnoopDoc* mySelf = (CJPEGsnoopDoc*) pWrapClass; - return mySelf->m_pCore->I_LookupFilePosPix(nX,nY,nByte,nBit); -} - -// Menu command to look up an MCU's file offset -void CJPEGsnoopDoc::OnToolsLookupmcuoffset() -{ - // Don't need to use AnalyzeOpen() here as this function - // simply checks the MCU map variable. - - unsigned nPicWidth,nPicHeight; - m_pCore->I_GetImageSize(nPicWidth,nPicHeight); - CLookupDlg lookupDlg(NULL,nPicWidth,nPicHeight); - // Set the call-back function - lookupDlg.SetCbLookup((void*)this,CJPEGsnoopDoc::CbWrap_I_LookupFilePosPix); - - if (lookupDlg.DoModal() == IDOK) { - } else { - } -} - -// Menu enable status for Tools -> Lookup MCU offset -void CJPEGsnoopDoc::OnUpdateToolsLookupmcuoffset(CCmdUI *pCmdUI) -{ - if (m_pCore->IsAnalyzed()) { - pCmdUI->Enable(true); - } else { - pCmdUI->Enable(false); - } -} - -// Menu command to enable/disable the MCU overlay grid -void CJPEGsnoopDoc::OnOverlaysMcugrid() -{ - m_pCore->I_SetPreviewOverlayMcuGridToggle(); - UpdateAllViews(NULL); -} - - -// Menu enable status for MCU overlay grid -void CJPEGsnoopDoc::OnUpdateOverlaysMcugrid(CCmdUI *pCmdUI) -{ - if (m_pCore->I_GetPreviewOverlayMcuGrid()) { - pCmdUI->SetCheck(true); - } else { - pCmdUI->SetCheck(false); - } -} - - - - - -// Menu enable status for YCC indicator -void CJPEGsnoopDoc::OnUpdateIndicatorYcc(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(TRUE); - pCmdUI->SetText(m_pCore->I_GetStatusYccText()); -} - -// Menu enable status for MCU indicator -void CJPEGsnoopDoc::OnUpdateIndicatorMcu(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(TRUE); - pCmdUI->SetText(m_pCore->I_GetStatusMcuText()); -} - -// Menu enable status for file position indicator -void CJPEGsnoopDoc::OnUpdateIndicatorFilePos(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(TRUE); - pCmdUI->SetText(m_pCore->I_GetStatusFilePosText()); -} - - -// Menu command for Detailed Decode settings -// - Take last two image click positions (marker) to define the begin and -// end of the detailed decode region -// - Or allow user to specify the starting MCU and length -// - Update the decoder ranging for the next processing operation -// -void CJPEGsnoopDoc::OnScansegmentDetaileddecode() -{ - CDecodeDetailDlg dlgDetail(NULL); - - bool bEn; - m_pCore->I_GetDetailVlc(bEn,dlgDetail.m_nMcuX,dlgDetail.m_nMcuY,dlgDetail.m_nMcuLen); - dlgDetail.m_bEn = bEn; - - - // Sequence of markers: - // #1 - Start MCU - // #2 - End MCU - CPoint ptScan1,ptScan2; - - unsigned nStartMcuX=0; - unsigned nStartMcuY=0; - unsigned nEndMcuX=0; - unsigned nEndMcuY=0; - int nMcuRngLen=0; - - unsigned nMarkerCnt; - CPoint ptMcuStart,ptMcuEnd; - unsigned nStartMcu,nEndMcu; - - nMarkerCnt = m_pCore->I_GetMarkerCount(); - - // Double-point, gives range - if (nMarkerCnt >= 2) { - // Get last two block selections - ptScan1 = m_pCore->I_GetMarkerBlk(nMarkerCnt-2); - ptScan2 = m_pCore->I_GetMarkerBlk(nMarkerCnt-1); - // Convert block index to MCU - ptScan1.x *= BLK_SZ_X; - ptScan1.y *= BLK_SZ_Y; - ptScan2.x *= BLK_SZ_X; - ptScan2.y *= BLK_SZ_Y; - ptMcuStart = m_pCore->I_PixelToMcu(ptScan1); - ptMcuEnd = m_pCore->I_PixelToMcu(ptScan2); - nStartMcuX = ptMcuStart.x; - nStartMcuY = ptMcuStart.y; - nEndMcuX = ptMcuEnd.x; - nEndMcuY = ptMcuEnd.y; - - // Check to see if order needs to be reversed - if ( (nStartMcuY > nEndMcuY) || ( (nStartMcuY == nEndMcuY) && (nStartMcuX > nEndMcuX) ) ) { - // Reverse order - nStartMcu = m_pCore->I_McuXyToLinear(ptMcuEnd); - nEndMcu = m_pCore->I_McuXyToLinear(ptMcuStart); - } else { - nStartMcu = m_pCore->I_McuXyToLinear(ptMcuStart); - nEndMcu = m_pCore->I_McuXyToLinear(ptMcuEnd); - } - - // Calculate length from linear positions - nMcuRngLen = nEndMcu-nStartMcu + 1; - - // Single point, gives start point - } else if (nMarkerCnt >= 1) { - ptScan1 = m_pCore->I_GetMarkerBlk(nMarkerCnt-1); - // Convert block index to MCU - ptScan1.x *= BLK_SZ_X; - ptScan1.y *= BLK_SZ_Y; - ptMcuStart = m_pCore->I_PixelToMcu(ptScan1); - nStartMcuX = ptMcuStart.x; - nStartMcuY = ptMcuStart.y; - nMcuRngLen = 0; - } - - // Set the "load" values from the last MCU click - dlgDetail.m_nLoadMcuX = nStartMcuX; - dlgDetail.m_nLoadMcuY = nStartMcuY; - dlgDetail.m_nLoadMcuLen = nMcuRngLen; - - - // If the user completed the configuration dialog then proceed - // to update the MCU ranging for the next decode process - if (dlgDetail.DoModal() == IDOK) { - m_pCore->I_SetDetailVlc((dlgDetail.m_bEn!=0),dlgDetail.m_nMcuX,dlgDetail.m_nMcuY,dlgDetail.m_nMcuLen); - } -} - -// Menu enable status for Scan Segment -> Detailed Decode -void CJPEGsnoopDoc::OnUpdateScansegmentDetaileddecode(CCmdUI *pCmdUI) -{ - pCmdUI->Enable(true); -} - - -// Menu command for Export to TIFF -// - Export the currently-decoded JPEG file as a TIFF -// -void CJPEGsnoopDoc::OnToolsExporttiff() -{ - - // Get filename - CString strFnameOut; - - strFnameOut = m_strPathName + _T(".tif"); - - TCHAR aszFilter[] = - _T("TIFF (*.tif)|*.tif|")\ - _T("All Files (*.*)|*.*||"); - - CFileDialog FileDlg(FALSE, _T(".tif"), strFnameOut, OFN_OVERWRITEPROMPT, aszFilter); - - CString strTitle; - CString strFileName; - strTitle = _T("Output TIFF Filename"); -// VERIFY(strTitle.LoadString(IDS_CAL_FILESAVE)); - FileDlg.m_ofn.lpstrTitle = strTitle; - - if( FileDlg.DoModal() == IDOK ) - { - strFnameOut = FileDlg.GetPathName(); - } else { - return; - } - - - - FileTiff myTiff; - unsigned char* pBitmapRgb = NULL; - short* pBitmapYccY = NULL; - short* pBitmapYccCb = NULL; - short* pBitmapYccCr = NULL; - unsigned char* pBitmapSel8 = NULL; - unsigned short* pBitmapSel16 = NULL; - - unsigned nSizeX,nSizeY; - unsigned nOffsetSrc,nOffsetDst; - bool bModeYcc; // YCC (true), RGB (false) - bool bMode16b; // 16b (true), 8b (false) - short nValY,nValCb,nValCr; - unsigned short nValR,nValG,nValB; - - // Initialize min/max range values (to 16-bit signed limits) - short nValMaxY = -32768; - short nValMinY = +32767; - short nValMaxCb = -32768; - short nValMinCb = +32767; - short nValMaxCr = -32768; - short nValMinCr = +32767; - - m_pCore->I_GetImageSize(nSizeX,nSizeY); - m_pCore->I_GetBitmapPtr(pBitmapRgb); - m_pCore->I_GetPixMapPtrs(pBitmapYccY,pBitmapYccCb,pBitmapYccCr); - pBitmapSel8 = NULL; - pBitmapSel16 = NULL; - - CExportTiffDlg myTiffDlg; - int rVal,nModeSel; - myTiffDlg.m_sFname = strFnameOut; - rVal = myTiffDlg.DoModal(); - nModeSel = myTiffDlg.m_nCtlFmt; - - switch(nModeSel) { - default: - case 0: - bModeYcc = false; - bMode16b = false; - break; - case 1: - bModeYcc = false; - bMode16b = true; - break; - case 2: - bModeYcc = true; - bMode16b = false; - break; - } - - if (bModeYcc && bMode16b) { - AfxMessageBox(_T("ERROR: Can't output 16-bit YCC!")); - return; - } - - // Create a separate bitmap array - if (bMode16b) { - pBitmapSel16 = new unsigned short[nSizeX*nSizeY*3]; - ASSERT(pBitmapSel16); - if (!pBitmapSel16) { - AfxMessageBox(_T("ERROR: Insufficient memory for export")); - return; - } - } else { - pBitmapSel8 = new unsigned char[nSizeX*nSizeY*3]; - ASSERT(pBitmapSel8); - if (!pBitmapSel8) { - AfxMessageBox(_T("ERROR: Insufficient memory for export")); - return; - } - } - if (!bModeYcc) { - // RGB mode - for (unsigned nIndY=0;nIndY +1023) { nValY = +1023; } - if (nValCb < -1024) { nValCb = -1024; } - if (nValCb > +1023) { nValCb = +1023; } - if (nValCr < -1024) { nValCr = -1024; } - if (nValCr > +1023) { nValCr = +1023; } - - // Expect original YCC range is: -1024 .. +1023 - // For 8bit mode: - // .. add +1024 = 0..2047 - // .. div /8 = 0..255 - if (!bMode16b) { - // Rearrange into file-order - pBitmapSel8[nOffsetDst+0] = (unsigned char)((0x0400+nValY)>>3); - pBitmapSel8[nOffsetDst+1] = (unsigned char)((0x0400+nValCb)>>3); - pBitmapSel8[nOffsetDst+2] = (unsigned char)((0x0400+nValCr)>>3); - } else { - ASSERT(false); - // YCC-16b not defined! - // Note that this error is trapped earlier - } - } - } - } - - if (bMode16b) { - myTiff.WriteFile(strFnameOut,bModeYcc,bMode16b,(void*)pBitmapSel16,nSizeX,nSizeY); - } else { - myTiff.WriteFile(strFnameOut,bModeYcc,bMode16b,(void*)pBitmapSel8,nSizeX,nSizeY); - } - - if (pBitmapSel8) { - delete [] pBitmapSel8; - pBitmapSel8 = NULL; - } - if (pBitmapSel16) { - delete [] pBitmapSel16; - pBitmapSel16 = NULL; - } - -} - -// Menu enable status for Tools -> Export to TIFF -void CJPEGsnoopDoc::OnUpdateToolsExporttiff(CCmdUI *pCmdUI) -{ - pCmdUI->Enable(m_pCore->IsAnalyzed()); -} - - -// ------------------------- -// Public accessors - -void CJPEGsnoopDoc::J_ImgSrcChanged() -{ - m_pCore->J_ImgSrcChanged(); -} - -void CJPEGsnoopDoc::I_ViewOnDraw(CDC* pDC,CRect rectClient,CPoint ptScrolledPos,CFont* pFont, CSize &szNewScrollSize) -{ - m_pCore->I_ViewOnDraw(pDC,rectClient,ptScrolledPos,pFont,szNewScrollSize); -} - -void CJPEGsnoopDoc::I_GetPreviewPos(unsigned &nX,unsigned &nY) -{ - m_pCore->I_GetPreviewPos(nX,nY); -} - -void CJPEGsnoopDoc::I_GetPreviewSize(unsigned &nX,unsigned &nY) -{ - m_pCore->I_GetPreviewSize(nX,nY); -} - -float CJPEGsnoopDoc::I_GetPreviewZoom() -{ - return m_pCore->I_GetPreviewZoom(); -} diff --git a/source/JPEGsnoopDoc.h b/source/JPEGsnoopDoc.h deleted file mode 100644 index aecdcca..0000000 --- a/source/JPEGsnoopDoc.h +++ /dev/null @@ -1,175 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - JPEGsnoop SDI document class -// -// ========================================================================== - - -// JPEGsnoopDoc.h : interface of the CJPEGsnoopDoc class -// - - -#pragma once - -#include "JPEGsnoopCore.h" - -#include "FolderDlg.h" -#include "BatchDlg.h" - - -#define DOCLOG_MAX_LINES 30000 - - -class CJPEGsnoopDoc : public CRichEditDoc -{ -protected: // create from serialization only - CJPEGsnoopDoc(); - DECLARE_DYNCREATE(CJPEGsnoopDoc) - -// Attributes -public: - -// Operations -public: - -// Overrides - public: - virtual BOOL OnNewDocument(); - virtual void Serialize(CArchive& ar); - virtual CRichEditCntrItem* CreateClientItem(REOBJECT* preo) const; - -// Implementation -public: - virtual ~CJPEGsnoopDoc(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - - void SetupView(CRichEditView* pView); - - int AppendToLog(CString strTxt, COLORREF sColor); - int InsertQuickLog(); - - CStatusBar* GetStatusBar(); - - void DoBatchProcess(CString strBatchDir,bool bRecSubdir,bool bExtractAll); - - BOOL ReadLine(CString& strLine, int nLength, LONG lOffset = -1L); - - void Reset(); - BOOL Reprocess(); - - - - -protected: - -// Generated message map functions -protected: - DECLARE_MESSAGE_MAP() - - -private: - - CSnoopConfig* m_pAppConfig; // Pointer to application config - - // Input JPEG file - CFile* m_pFile; - ULONGLONG m_lFileSize; - - // The following is a mirror of m_strPathName, but only set during Open - // This is used only during OnSaveDocument() to ensure that we are - // not overwriting our input file. - CString m_strPathNameOpened; - - CRichEditView* m_pView; // Preserved reference to View - -public: - // Allocate the processing core - // - Public access by CJPEGsnoopViewImg - CJPEGsnoopCore* m_pCore; - -public: - - // Public accessors from CJPEGsnoopApp - void J_ImgSrcChanged(); - - // Public accessors from CJPEGsnoopViewImg - void I_ViewOnDraw(CDC* pDC,CRect rectClient,CPoint ptScrolledPos,CFont* pFont, CSize &szNewScrollSize); - void I_GetPreviewPos(unsigned &nX,unsigned &nY); - void I_GetPreviewSize(unsigned &nX,unsigned &nY); - float I_GetPreviewZoom(); - - - // Callback functions - static BYTE CbWrap_B_Buf(void* pWrapClass, - unsigned long nNum,bool bBool); - static void CbWrap_I_LookupFilePosPix(void* pWrapClass, - unsigned int nX, unsigned int nY, unsigned int &nByte, unsigned int &nBit); - -public: - void DoGuiExtractEmbeddedJPEG(); -private: - virtual void DeleteContents(); - void RedrawLog(); - -public: - // OnOpenDocument() is public for View:OnDropFiles() - virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); -private: - virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); - afx_msg void OnFileOffset(); - afx_msg void OnToolsDecode(); - afx_msg void OnToolsAddcameratodb(); - afx_msg void OnUpdateToolsAddcameratodb(CCmdUI *pCmdUI); - afx_msg void OnToolsSearchforward(); - afx_msg void OnToolsSearchreverse(); - afx_msg void OnUpdateToolsSearchforward(CCmdUI *pCmdUI); - afx_msg void OnUpdateToolsSearchreverse(CCmdUI *pCmdUI); - afx_msg void OnFileReprocess(); - afx_msg void OnFileOpenimage(); - afx_msg void OnFileSaveAs(); - afx_msg void OnPreviewRng(UINT nID); - afx_msg void OnUpdatePreviewRng(CCmdUI *pCmdUI); - afx_msg void OnZoomRng(UINT nID); - afx_msg void OnUpdateZoomRng(CCmdUI * pCmdUI); - afx_msg void OnToolsSearchexecutablefordqt(); - afx_msg void OnUpdateFileReprocess(CCmdUI *pCmdUI); - afx_msg void OnUpdateFileSaveAs(CCmdUI *pCmdUI); - afx_msg void OnToolsExtractembeddedjpeg(); - afx_msg void OnUpdateToolsExtractembeddedjpeg(CCmdUI *pCmdUI); - afx_msg void OnToolsFileoverlay(); - afx_msg void OnUpdateToolsFileoverlay(CCmdUI *pCmdUI); - afx_msg void OnToolsLookupmcuoffset(); - afx_msg void OnUpdateToolsLookupmcuoffset(CCmdUI *pCmdUI); - afx_msg void OnOverlaysMcugrid(); - afx_msg void OnUpdateOverlaysMcugrid(CCmdUI *pCmdUI); - afx_msg void OnUpdateIndicatorYcc(CCmdUI* pCmdUI); - afx_msg void OnUpdateIndicatorMcu(CCmdUI* pCmdUI); - afx_msg void OnUpdateIndicatorFilePos(CCmdUI* pCmdUI); - afx_msg void OnScansegmentDetaileddecode(); - afx_msg void OnUpdateScansegmentDetaileddecode(CCmdUI *pCmdUI); - afx_msg void OnToolsExporttiff(); - afx_msg void OnUpdateToolsExporttiff(CCmdUI *pCmdUI); -}; - - diff --git a/source/JPEGsnoopView.cpp b/source/JPEGsnoopView.cpp deleted file mode 100644 index a016d8f..0000000 --- a/source/JPEGsnoopView.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// JPEGsnoopView.cpp : implementation of the CJPEGsnoopView class -// - -#include "stdafx.h" -#include "JPEGsnoop.h" - -#include "JPEGsnoopDoc.h" -#include "CntrItem.h" -#include "JPEGsnoopView.h" -#include ".\jpegsnoopview.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - - -// CJPEGsnoopView - -IMPLEMENT_DYNCREATE(CJPEGsnoopView, CRichEditView) - -BEGIN_MESSAGE_MAP(CJPEGsnoopView, CRichEditView) - ON_WM_DESTROY() - // Standard printing commands - ON_COMMAND(ID_FILE_PRINT, CRichEditView::OnFilePrint) - ON_COMMAND(ID_FILE_PRINT_DIRECT, CRichEditView::OnFilePrint) - ON_COMMAND(ID_FILE_PRINT_PREVIEW, CRichEditView::OnFilePrintPreview) - ON_WM_DROPFILES() -END_MESSAGE_MAP() - -// CJPEGsnoopView construction/destruction - -CJPEGsnoopView::CJPEGsnoopView() -{ - -} - -CJPEGsnoopView::~CJPEGsnoopView() -{ -} - -BOOL CJPEGsnoopView::PreCreateWindow(CREATESTRUCT& cs) -{ - // TODO: Modify the Window class or styles here by modifying - // the CREATESTRUCT cs - - - return CRichEditView::PreCreateWindow(cs); - -} - -// This is called initially in the first time the view -// is drawn, and again after the contents have finished loading -// with OnOpenDocument() -void CJPEGsnoopView::OnInitialUpdate() -{ - CRichEditView::OnInitialUpdate(); - - // FIXME This seems like the best place to add this call - // as we know that the view will now be available - // Want to allow drag & drop from Explorer into window - DragAcceptFiles(true); - - // Set the printing margins (720 twips = 1/2 inch) - SetMargins(CRect(720, 720, 720, 720)); - - // Set the word wrap to off - // Other modes: WrapNone, WrapToWindow, WrapToTargetDevice - m_nWordWrap = WrapNone; - WrapChanged(); - - GetRichEditCtrl().SetReadOnly(true); - - // The following is a nice idea, but it isn't sufficent as it - // doesn't actually handle the URL click message - //GetRichEditCtrl().SetAutoURLDetect(true); - - //const COLORREF CLOUDBLUE = RGB(128, 184, 223); - //const COLORREF WHITE = RGB(255, 255, 255); - const COLORREF BLACK = RGB(1, 1, 1); - //const COLORREF DKGRAY = RGB(128, 128, 128); - //const COLORREF PURPLE = RGB(255, 0, 255); - - // Set the default character formatting - CHARFORMAT cf; - COLORREF myColor = BLACK; //0x00ff00ff; // 00BBGGRR (purple) - TCHAR szFaceName[LF_FACESIZE] = _T("Courier New"); - _tcscpy_s(cf.szFaceName, szFaceName); - CDC* pDC = GetDC(); - - // Modify the default character format - cf.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE | CFM_BOLD; - cf.dwEffects = 0; - cf.crTextColor = myColor; - cf.bCharSet = ANSI_CHARSET; - cf.bPitchAndFamily = FIXED_PITCH | FF_DONTCARE; - cf.yHeight = 12*72*20/pDC->GetDeviceCaps(LOGPIXELSY); - - GetRichEditCtrl().SetDefaultCharFormat(cf); - - GetDocument()->SetupView((CRichEditView*)this); -} - - -// CJPEGsnoopView printing - -BOOL CJPEGsnoopView::OnPreparePrinting(CPrintInfo* pInfo) -{ - // default preparation - return DoPreparePrinting(pInfo); -} - - -void CJPEGsnoopView::OnDestroy() -{ - // Deactivate the item on destruction; this is important - // when a splitter view is being used - COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this); - if (pActiveItem != NULL && pActiveItem->GetActiveView() == this) - { - pActiveItem->Deactivate(); - ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL); - } - CRichEditView::OnDestroy(); -} - - - -// CJPEGsnoopView diagnostics - -#ifdef _DEBUG -void CJPEGsnoopView::AssertValid() const -{ - CRichEditView::AssertValid(); -} - -void CJPEGsnoopView::Dump(CDumpContext& dc) const -{ - CRichEditView::Dump(dc); -} - -CJPEGsnoopDoc* CJPEGsnoopView::GetDocument() const // non-debug version is inline -{ - ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CJPEGsnoopDoc))); - return (CJPEGsnoopDoc*)m_pDocument; -} -#endif //_DEBUG - - -// CJPEGsnoopView message handlers - -void CJPEGsnoopView::OnDropFiles(HDROP hDropInfo) -{ - UINT uNumFiles; - TCHAR szNextFile [MAX_PATH]; - - // Get the # of files being dropped. - uNumFiles = DragQueryFile ( hDropInfo, 0xFFFFFFFF, NULL, 0 ); - - /* - for ( UINT uFile = 0; uFile < uNumFiles; uFile++ ) - { - // Get the next filename from the HDROP info. - if ( DragQueryFile ( hDropInfo, uFile, szNextFile, MAX_PATH ) > 0 ) - { - // *** - // Do whatever you want with the filename in szNextFile. - // *** - } - } - */ - - // FIXME: For now, only support a single file but later may - // consider somehow allowing multiple files to be processed? - if (uNumFiles > 0) { - if ( DragQueryFile ( hDropInfo, 0, szNextFile, MAX_PATH ) > 0 ) { - GetDocument()->OnOpenDocument(szNextFile); - } - } - - // Free up memory. - DragFinish ( hDropInfo ); - - - // Don't want to call built-in functionality! - //CRichEditView::OnDropFiles(hDropInfo); -} diff --git a/source/JPEGsnoopView.h b/source/JPEGsnoopView.h deleted file mode 100644 index cdef443..0000000 --- a/source/JPEGsnoopView.h +++ /dev/null @@ -1,79 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - JPEGsnoop SDI View class for the main text log window -// -// ========================================================================== - - -// JPEGsnoopView.h : interface of the CJPEGsnoopView class -// - - -#pragma once - -#include "JPEGsnoopDoc.h" - -class CJPEGsnoopCntrItem; - -class CJPEGsnoopView : public CRichEditView -{ -protected: // create from serialization only - CJPEGsnoopView(); - DECLARE_DYNCREATE(CJPEGsnoopView) - -// Attributes -public: - CJPEGsnoopDoc* GetDocument() const; - -// Operations -public: - -// Overrides -public: - virtual BOOL PreCreateWindow(CREATESTRUCT& cs); -protected: - virtual void OnInitialUpdate(); // called first time after construct - virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); - -// Implementation -public: - virtual ~CJPEGsnoopView(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - -protected: - -// Generated message map functions -protected: - afx_msg void OnDestroy(); - - DECLARE_MESSAGE_MAP() -public: - afx_msg void OnDropFiles(HDROP hDropInfo); -}; - -#ifndef _DEBUG // debug version in JPEGsnoopView.cpp -inline CJPEGsnoopDoc* CJPEGsnoopView::GetDocument() const - { return reinterpret_cast(m_pDocument); } -#endif - diff --git a/source/JPEGsnoopViewImg.cpp b/source/JPEGsnoopViewImg.cpp deleted file mode 100644 index e33854f..0000000 --- a/source/JPEGsnoopViewImg.cpp +++ /dev/null @@ -1,349 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// JPEGsnoopViewImg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "JPEGsnoopDoc.h" -#include "JPEGsnoopViewImg.h" - - -// CJPEGsnoopViewImg - -IMPLEMENT_DYNCREATE(CJPEGsnoopViewImg, CScrollView) - -CJPEGsnoopViewImg::CJPEGsnoopViewImg() -{ - //_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); //CAL! - - CWindowDC dc(NULL); - - // Create main log font - memset(&m_logfont, 0, sizeof(m_logfont)); - m_nPointSize = 120; - //_tcscpy(m_logfont.lfFaceName,_T("Courier New")); - _tcscpy_s(m_logfont.lfFaceName,_T("Arial")); - - m_logfont.lfHeight = ::MulDiv(m_nPointSize, - dc.GetDeviceCaps(LOGPIXELSY),720); - m_logfont.lfPitchAndFamily = FIXED_PITCH; - - m_pFont = new CFont; - m_pFont->CreateFontIndirect(&m_logfont); - -} - -CJPEGsnoopViewImg::~CJPEGsnoopViewImg() -{ - if (m_pFont != NULL) - { - delete m_pFont; - } -} - - -BEGIN_MESSAGE_MAP(CJPEGsnoopViewImg, CScrollView) - ON_WM_LBUTTONDOWN() - ON_WM_LBUTTONUP() - ON_WM_RBUTTONUP() - ON_WM_MOUSEWHEEL() - ON_WM_MOUSEMOVE() - ON_WM_ERASEBKGND() -END_MESSAGE_MAP() - - -CJPEGsnoopCore* CJPEGsnoopViewImg::GetCore() -{ - CJPEGsnoopDoc* pDoc = (CJPEGsnoopDoc*)GetDocument(); - ASSERT_VALID(pDoc); - if (!pDoc) - return NULL; - - // TODO: add draw code for native data here - CJPEGsnoopCore* pCore = pDoc->m_pCore; - return pCore; -} - - -// CJPEGsnoopViewImg drawing - -void CJPEGsnoopViewImg::OnInitialUpdate() -{ - CScrollView::OnInitialUpdate(); - - CJPEGsnoopDoc* pDoc = (CJPEGsnoopDoc*)GetDocument(); - ASSERT_VALID(pDoc); - - - CSize sizeTotal(0,0); - sizeTotal.cx = 500; // FIXME: - sizeTotal.cy = 200; // FIXME: - SetScrollSizes(MM_TEXT, sizeTotal); - -} - - -void CJPEGsnoopViewImg::OnDraw(CDC* pDC) -{ - CJPEGsnoopDoc* pDoc = (CJPEGsnoopDoc*)GetDocument(); - ASSERT_VALID(pDoc); - if (!pDoc) - return; - - // TODO: add draw code for native data here - CJPEGsnoopCore* pCore = GetCore(); - if (!pCore) - return; - - CPoint ScrolledPos = GetScrollPosition(); - CRect rectClient; - CSize szNewScrollSize; - - GetClientRect(&rectClient); - - pCore->I_ViewOnDraw(pDC,rectClient,ScrolledPos,m_pFont,szNewScrollSize); - SetScrollSizes(MM_TEXT, szNewScrollSize); - -} - -// CJPEGsnoopViewImg diagnostics - -#ifdef _DEBUG -void CJPEGsnoopViewImg::AssertValid() const -{ - CScrollView::AssertValid(); -} - -void CJPEGsnoopViewImg::Dump(CDumpContext& dc) const -{ - CScrollView::Dump(dc); -} -#endif //_DEBUG - - -// CJPEGsnoopViewImg message handlers - - - -// FIXME: Migrate into ImgDec! -bool CJPEGsnoopViewImg::InPreviewArea(CPoint point,CPoint &ptPix) -{ - int pix_x; - int pix_y; - float fZoom; - unsigned nImgPosX; - unsigned nImgPosY; - unsigned nPixX; // 8x8 block number (not MCU unless CSS=1x1) - unsigned nPixY; - - CJPEGsnoopCore* pCore = GetCore(); - - fZoom = pCore->I_GetPreviewZoom(); - pCore->I_GetPreviewPos(nImgPosX,nImgPosY); - - ASSERT(fZoom != 0); - - CPoint ScrolledPos = GetScrollPosition(); - CString strTmp; - - pix_x = point.x; - pix_y = point.y; - pix_x -= (nImgPosX - ScrolledPos.x); - pix_y -= (nImgPosY - ScrolledPos.y); - - ptPix.x = 0; - ptPix.y = 0; - - // Is the preview even displayed? - //if (!GetImgDec()->m_bDibTempReady) { - // return false; - //} - // FIXME - - // Note that m_nPreviewSize already includes effects of zoom level - unsigned nPreviewSzX,nPreviewSzY; - pCore->I_GetPreviewSize(nPreviewSzX,nPreviewSzY); - if ( ((pix_x >= 0) && ((unsigned)pix_x < nPreviewSzX)) && - ((pix_y >= 0) && ((unsigned)pix_y < nPreviewSzY)) ) - { - // Undo zoom - nPixX = (unsigned)(pix_x / fZoom); - nPixY = (unsigned)(pix_y / fZoom); - - ptPix.x = nPixX; - ptPix.y = nPixY; - - return true; - } - return false; -} - -// The following routine was intended to automatically recenter the image -// TODO: However, what is the best way to have it called during redraw? -// Currently not used -void CJPEGsnoopViewImg::SetScrollCenter(float fZoomOld, float fZoomNew) -{ - unsigned nImgPosX; - unsigned nImgPosY; - - ASSERT(fZoomOld != 0); - ASSERT(fZoomNew != 0); - GetCore()->I_GetPreviewPos(nImgPosX,nImgPosY); - - CPoint ScrolledPos = GetScrollPosition(); - ScrolledPos.Offset(-(int)nImgPosX,-(int)nImgPosY); - - ScrolledPos.x = (long)(ScrolledPos.x * fZoomNew / fZoomOld); - ScrolledPos.y = (long)(ScrolledPos.y * fZoomNew / fZoomOld); - - ScrolledPos.Offset(+nImgPosX,+nImgPosY); - - ScrollToPosition(ScrolledPos); -} - - -int CJPEGsnoopViewImg::MeasureFontHeight(CFont* pFont, CDC* pDC) -{ - // how tall is the identified font in the identified DC? - - CFont* pOldFont; - pOldFont = pDC->SelectObject(pFont); - - CRect rectDummy; - CString strRender = _T("1234567890ABCDEF- abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ[]"); - int nHeight = pDC->DrawText(strRender, -1, rectDummy, - DT_TOP | DT_SINGLELINE | DT_CALCRECT); - pDC->SelectObject(pOldFont); - - return nHeight; -} - - -void CJPEGsnoopViewImg::OnLButtonDown(UINT nFlags, CPoint point) -{ - // TODO: Add your message handler code here and/or call default - - //AfxMessageBox(_T("LButtonDown!")); - - CScrollView::OnLButtonDown(nFlags, point); -} - -void CJPEGsnoopViewImg::OnLButtonUp(UINT nFlags, CPoint point) -{ - CString strTmp; - CPoint ptPix; - CPoint ptMcu; - CPoint ptBlk; - - // Need to ensure that the Preview image was based on a JPEG with - // MCU/Block map info - //if (InPreviewArea(point,ptPix)) { - if ( (GetCore()->I_IsPreviewReady() && InPreviewArea(point,ptPix)) ) { - - // Set the marker - ptBlk = GetCore()->I_PixelToBlk(ptPix); - GetCore()->I_SetMarkerBlk(ptBlk.x,ptBlk.y); - - //Invalidate(); - - } else { - GetCore()->I_SetStatusText(_T("")); - } - - - CScrollView::OnLButtonUp(nFlags, point); -} - -void CJPEGsnoopViewImg::OnRButtonUp(UINT nFlags, CPoint point) -{ - - CScrollView::OnLButtonUp(nFlags, point); -} - - -BOOL CJPEGsnoopViewImg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) -{ - // TODO: Add your message handler code here and/or call default - CPoint ScrolledPos = GetScrollPosition(); - ScrolledPos.Offset(0,-zDelta); - ScrollToPosition(ScrolledPos); - - // Want to update the status text - OnMouseMove(0,pt); - - return CScrollView::OnMouseWheel(nFlags, zDelta, pt); -} - -void CJPEGsnoopViewImg::OnMouseMove(UINT nFlags, CPoint point) -{ - CString strTmp; - unsigned nByte; - unsigned nBit; - CPoint ptPix; - CPoint ptMcu; - CPoint ptBlk; - int nY1,nCb1,nCr1; - - // FIXME: Migrate the following into ImgDec! - // Need to ensure that the Preview image was based on a JPEG with - // MCU/Block map info - if ( (GetCore()->I_IsPreviewReady() && InPreviewArea(point,ptPix)) ) { - - ptMcu = GetCore()->I_PixelToMcu(ptPix); - GetCore()->I_LookupFilePosMcu(ptMcu.x,ptMcu.y,nByte,nBit); - - ptBlk = GetCore()->I_PixelToBlk(ptPix); - GetCore()->I_LookupBlkYCC(ptBlk.x,ptBlk.y,nY1,nCb1,nCr1); - -/* - strTmp.Format(_T("MCU [%04u,%04u] File: 0x%08X:%u\tYCC=[%05d,%05d,%05d]"), - ptMcu.x,ptMcu.y,nByte,nBit, - nY1,nCb1,nCr1); - GetCore()->I_SetStatusText(strTmp); -*/ - strTmp.Format(_T("MCU [%04u,%04u]"),ptMcu.x,ptMcu.y); - GetCore()->I_SetStatusMcuText(strTmp); - - strTmp.Format(_T("File: 0x%08X:%u"),nByte,nBit); - GetCore()->I_SetStatusFilePosText(strTmp); - - strTmp.Format(_T("YCC DC=[%05d,%05d,%05d]"),nY1,nCb1,nCr1); - GetCore()->I_SetStatusYccText(strTmp); - - } else { -// GetCore()->I_SetStatusText(_T("")); - GetCore()->I_SetStatusMcuText(_T("")); - GetCore()->I_SetStatusFilePosText(_T("")); - GetCore()->I_SetStatusYccText(_T("")); - } - - CScrollView::OnMouseMove(nFlags, point); -} - -BOOL CJPEGsnoopViewImg::OnEraseBkgnd(CDC* pDC) -{ - // TODO: Add your message handler code here and/or call default - - // FIXME: - // Apparently this could help remove flicker! But it is disabled for now. - //return 1; - - return CScrollView::OnEraseBkgnd(pDC); -} diff --git a/source/JPEGsnoopViewImg.h b/source/JPEGsnoopViewImg.h deleted file mode 100644 index dc66779..0000000 --- a/source/JPEGsnoopViewImg.h +++ /dev/null @@ -1,78 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - JPEGsnoop SDI View class for the main image preview window -// - Handles user mouse-click events to mark MCUs -// - Tracks mouse position to provide continuous read-out in the status bar -// -// ========================================================================== - - -#pragma once - -#include "JPEGsnoopDoc.h" -#include "Dib.h" -#include "snoop.h" - -// CJPEGsnoopViewImg view - - - -class CJPEGsnoopViewImg : public CScrollView -{ - DECLARE_DYNCREATE(CJPEGsnoopViewImg) - -protected: - CJPEGsnoopViewImg(); // protected constructor used by dynamic creation - virtual ~CJPEGsnoopViewImg(); - -public: -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - -protected: - virtual void OnDraw(CDC* pDC); // overridden to draw this view - virtual void OnInitialUpdate(); // first time after construct - - DECLARE_MESSAGE_MAP() - -private: - CJPEGsnoopCore* GetCore(); - bool InPreviewArea(CPoint point,CPoint &ptPix); - void SetScrollCenter(float fZoomOld, float fZoomNew); - int MeasureFontHeight(CFont* pFont, CDC* pDC); - - afx_msg void OnLButtonDown(UINT nFlags, CPoint point); - afx_msg void OnLButtonUp(UINT nFlags, CPoint point); - afx_msg void OnRButtonUp(UINT nFlags, CPoint point); - afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); - afx_msg void OnMouseMove(UINT nFlags, CPoint point); - afx_msg BOOL OnEraseBkgnd(CDC* pDC); - -private: - CFont* m_pFont; - LOGFONT m_logfont; - int m_nPointSize; - -}; - - diff --git a/source/JfifDecode.cpp b/source/JfifDecode.cpp index 308a5c8..79a52c4 100644 --- a/source/JfifDecode.cpp +++ b/source/JfifDecode.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -27,20 +27,114 @@ #include "JfifDecode.h" #include "snoop.h" -#include "JPEGsnoop.h" // for m_pAppConfig get - +//#include "JPEGsnoop.h" // for m_pAppConfig get +#include "SnoopConfig.h" +#include "DbSigs.h" +#include "DocLog.h" +#include "DbSigs.h" #include "WindowBuf.h" - #include "Md5.h" - #include "UrlString.h" #include "DbSigs.h" - #include "General.h" // Maximum number of component values to extract into array for display -static const quint32 MAX_anValues = 64; +static const uint32_t MAX_anValues = 64; + + +//----------------------------------------------------------------------------- +// Initialize the JFIF decoder. Several class pointers are provided +// as parameters, so that we can directly access the output log, the +// file buffer and the image scan decoder. +// Loads up the signature database. +// +// INPUT: +// - pLog Ptr to log file class +// - pWBuf Ptr to Window Buf class +// - pImgDec Ptr to Image Decoder class +// +// PRE: +// - Requires that CDocLog, CwindowBuf and CimgDecode classes +// are already initialized +// +CjfifDecode::CjfifDecode(CDocLog *pLog, CDbSigs *pDbSigs, CwindowBuf *pWBuf, CimgDecode *pImgDec, CSnoopConfig *pAppConfig, QObject *_parent) : + QObject(_parent), m_pLog(pLog), m_pDbSigs(pDbSigs), m_pWBuf(pWBuf), m_pImgDec(pImgDec), m_pAppConfig(pAppConfig) +{ + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CjfifDecode::CjfifDecode() Begin"); + + // Need to zero out the private members + m_bOutputDB = false; // mySQL output for web + + // Enable verbose reporting + m_bVerbose = false; + + m_pImgSrcDirty = true; + + // Generate lookup tables for Huffman codes + GenLookupHuffMask(); + + // Window status bar is not ready yet, wait for call to SetStatusBar() + m_pStatBar = 0; + + // Reset decoding state + Reset(); + + // Load the local database (if it exists) +//@@ m_pDbSigs->DatabaseExtraLoad(); + + // Allocate the Photoshop decoder + m_pPsDec = new CDecodePs(pWBuf, pLog, m_pAppConfig); + + connect(m_pAppConfig, SIGNAL(ImgSrcChanged()), this, SLOT(ImgSrcChanged())); + connect(_parent, SIGNAL(ImgSrcChanged()), this, SLOT(ImgSrcChanged())); + + if(!m_pPsDec) + { + Q_ASSERT(false); + return; + } + +#ifdef SUPPORT_DICOM + // Allocate the DICOM decoder + m_pDecDicom = new CDecodeDicom(pWBuf, pLog); + + if(!m_pDecDicom) + { + Q_ASSERT(false); + return; + } + + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CjfifDecode::CjfifDecode() Checkpoint 5"); +#endif +} + +//----------------------------------------------------------------------------- +// Destructor +CjfifDecode::~CjfifDecode() +{ + // Free the Photoshop decoder + if(m_pPsDec) + { + delete m_pPsDec; + + m_pPsDec = NULL; + } +#ifdef SUPPORT_DICOM + // Free the DICOM decoder + if(m_pDecDicom) + { + delete m_pDecDicom; + + m_pDecDicom = NULL; + } +#endif + +} + +//----------------------------------------------------------------------------- // Clear out internal members void CjfifDecode::Reset() { @@ -134,110 +228,9 @@ void CjfifDecode::Reset() m_bStateSos = false; m_bStateSosOk = false; m_bStateEoi = false; - -} - -// Initialize the JFIF decoder. Several class pointers are provided -// as parameters, so that we can directly access the output log, the -// file buffer and the image scan decoder. -// Loads up the signature database. -// -// INPUT: -// - pLog Ptr to log file class -// - pWBuf Ptr to Window Buf class -// - pImgDec Ptr to Image Decoder class -// -// PRE: -// - Requires that CDocLog, CwindowBuf and CimgDecode classes -// are already initialized -// -CjfifDecode::CjfifDecode(CDocLog *pLog, CwindowBuf *pWBuf, CimgDecode *pImgDec) -{ - // Ideally this would be passed by constructor, but simply access - // directly for now. - -// m_pAppConfig = pAppConfig; - - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CjfifDecode::CjfifDecode() Begin"); - -// Q_ASSERT(m_pAppConfig); - Q_ASSERT(pLog); - Q_ASSERT(pWBuf); - Q_ASSERT(pImgDec); - - // Need to zero out the private members - m_bOutputDB = false; // mySQL output for web - - // Enable verbose reporting - m_bVerbose = false; - - m_pImgSrcDirty = true; - - // Generate lookup tables for Huffman codes - GenLookupHuffMask(); - - // Window status bar is not ready yet, wait for call to SetStatusBar() - m_pStatBar = NULL; - - // Save copies of other class pointers - m_pLog = pLog; - m_pWBuf = pWBuf; - m_pImgDec = pImgDec; - - // Reset decoding state - Reset(); - - // Load the local database (if it exists) -//@@ m_pDbSigs->DatabaseExtraLoad(); - - // Allocate the Photoshop decoder - m_pPsDec = new CDecodePs(pWBuf, pLog); - - if(!m_pPsDec) - { - Q_ASSERT(false); - return; - } - -#ifdef SUPPORT_DICOM - // Allocate the DICOM decoder - m_pDecDicom = new CDecodeDicom(pWBuf, pLog); - - if(!m_pDecDicom) - { - Q_ASSERT(false); - return; - } - - if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CjfifDecode::CjfifDecode() Checkpoint 5"); -#endif -} - -// Destructor -CjfifDecode::~CjfifDecode() -{ - // Free the Photoshop decoder - if(m_pPsDec) - { - delete m_pPsDec; - - m_pPsDec = NULL; - } - -#ifdef SUPPORT_DICOM - // Free the DICOM decoder - if(m_pDecDicom) - { - delete m_pDecDicom; - - m_pDecDicom = NULL; - } -#endif - } +//----------------------------------------------------------------------------- // Asynchronously update a local pointer to the status bar once // it becomes available. Note that the status bar is not ready by // the time of the CjfifDecode class constructor call. @@ -253,6 +246,7 @@ void CjfifDecode::SetStatusBar(QStatusBar * pStatBar) m_pStatBar = pStatBar; } +//----------------------------------------------------------------------------- // Indicate that the source of the image scan data // has been dirtied. Either the source has changed // or some of the View2 options have changed. @@ -265,6 +259,7 @@ void CjfifDecode::ImgSrcChanged() m_pImgSrcDirty = true; } +//----------------------------------------------------------------------------- // Set the AVI mode flag for this file // // POST: @@ -277,6 +272,7 @@ void CjfifDecode::SetAviMode(bool bIsAvi, bool bIsMjpeg) m_bAviMjpeg = bIsMjpeg; } +//----------------------------------------------------------------------------- // Fetch the AVI mode flag for this file // // PRE: @@ -293,6 +289,7 @@ void CjfifDecode::GetAviMode(bool & bIsAvi, bool & bIsMjpeg) bIsMjpeg = m_bAviMjpeg; } +//----------------------------------------------------------------------------- // Fetch the starting file position of the embedded thumbnail // // PRE: @@ -306,6 +303,7 @@ uint32_t CjfifDecode::GetPosEmbedStart() return m_nPosEmbedStart; } +//----------------------------------------------------------------------------- // Fetch the ending file position of the embedded thumbnail // // PRE: @@ -319,6 +317,7 @@ uint32_t CjfifDecode::GetPosEmbedEnd() return m_nPosEmbedEnd; } +//----------------------------------------------------------------------------- // Determine if the last analysis revealed a JFIF with known markers // // RETURN: @@ -329,6 +328,7 @@ bool CjfifDecode::GetDecodeStatus() return m_bImgOK; } +//----------------------------------------------------------------------------- // Fetch a summary of the JFIF decoder results // These details are used in preparation of signature submission to the DB // @@ -362,6 +362,7 @@ void CjfifDecode::GetDecodeSummary(QString & strHash, QString & strHashRot, QStr eDbReqSuggest = m_eDbReqSuggest; } +//----------------------------------------------------------------------------- // Fetch an element from the "standard" luminance quantization table // // PRE: @@ -393,6 +394,7 @@ uint32_t CjfifDecode::GetDqtQuantStd(uint32_t nInd) } } +//----------------------------------------------------------------------------- // Fetch the DQT ordering index (with optional zigzag sequence) // // INPUT: @@ -431,6 +433,7 @@ uint32_t CjfifDecode::GetDqtZigZagIndex(uint32_t nInd, bool bZigZag) } } +//----------------------------------------------------------------------------- // Reset the DQT tables // // POST: @@ -456,6 +459,7 @@ void CjfifDecode::ClearDQT() } } +//----------------------------------------------------------------------------- // Set the DQT matrix element // // INPUT: @@ -483,6 +487,7 @@ void CjfifDecode::SetDQTQuick(uint16_t anDqt0[64], uint16_t anDqt1[64]) m_strImgQuantCss = "NA"; } +//----------------------------------------------------------------------------- // Construct a lookup table for the Huffman code masks // The result is a simple bit sequence of zeros followed by // an increasing number of 1 bits. @@ -502,12 +507,13 @@ void CjfifDecode::GenLookupHuffMask() for(uint32_t len = 0; len < 32; len++) { - mask = (1 << (len)) - 1; + mask = (1 << len) - 1; mask <<= 32 - len; m_anMaskLookup[len] = mask; } } +//----------------------------------------------------------------------------- // Provide a short-hand alias for the m_pWBuf buffer // Also support redirection to a local table in case we are // faking out the DHT (eg. for MotionJPEG files). @@ -540,6 +546,7 @@ uint8_t CjfifDecode::Buf(uint32_t nOffset, bool bClean = false) } } +//----------------------------------------------------------------------------- // Write out a line to the log buffer if we are in verbose mode // // PRE: @@ -565,6 +572,7 @@ void CjfifDecode::DbgAddLine(QString strLine) } } +//----------------------------------------------------------------------------- // Convert a UINT32 and decompose into 4 bytes, but support // either endian byte-swap mode // @@ -603,6 +611,7 @@ void CjfifDecode::UnByteSwap4(uint32_t nVal, uint32_t &nByte0, uint32_t &nByte1, } } +//----------------------------------------------------------------------------- // Perform conversion from 4 bytes into UINT32 with // endian byte-swapping support // @@ -636,6 +645,7 @@ uint32_t CjfifDecode::ByteSwap4(uint32_t nByte0, uint32_t nByte1, uint32_t nByte return nVal; } +//----------------------------------------------------------------------------- // Perform conversion from 2 bytes into half-word with // endian byte-swapping support // @@ -667,6 +677,7 @@ uint32_t CjfifDecode::ByteSwap2(uint32_t nByte0, uint32_t nByte1) return nVal; } +//----------------------------------------------------------------------------- // Decode Canon Makernotes // Only the most common makernotes are supported; there are a large // number of makernotes that have not been documented anywhere. @@ -906,6 +917,7 @@ CStr2 CjfifDecode::LookupMakerCanonTag(uint32_t nMainTag, uint32_t nSubTag, uint sRetVal.bUnknown = true; break; } // switch nSubTag + break; case 0x000F: @@ -1034,6 +1046,7 @@ CStr2 CjfifDecode::LookupMakerCanonTag(uint32_t nMainTag, uint32_t nSubTag, uint return sRetVal; } +//----------------------------------------------------------------------------- // Perform decode of EXIF IFD tags including MakerNote tags // // PRE: @@ -1630,7 +1643,6 @@ QString CjfifDecode::LookupExifTag(QString strSect, uint32_t nTag, bool & bUnkno // handled by the LookupMakerCanonTag() call. if(m_strImgExifMake == "Canon") { - switch (nTag) { case 0x0001: @@ -2114,6 +2126,7 @@ QString CjfifDecode::LookupExifTag(QString strSect, uint32_t nTag, bool & bUnkno return QString("???"); } +//----------------------------------------------------------------------------- // Interpret the MakerNote header to determine any applicable MakerNote subtype. // // PRE: @@ -2163,7 +2176,8 @@ bool CjfifDecode::DecodeMakerSubType() { strTmp = "ERROR: Unknown Nikon Makernote Type"; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -2202,7 +2216,7 @@ bool CjfifDecode::DecodeMakerSubType() strTmp = "ERROR: Unknown SIGMA Makernote identifier"; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -2215,11 +2229,13 @@ bool CjfifDecode::DecodeMakerSubType() else if(m_strImgExifMake == "FUJIFILM") { strTmp = ""; + for(uint32_t ind = 0; ind < 8; ind++) { if(Buf(m_nPos + ind) != 0) strTmp += Buf(m_nPos + ind); } + if(strTmp == "FUJIFILM") { // Valid marker @@ -2231,7 +2247,8 @@ bool CjfifDecode::DecodeMakerSubType() { strTmp = "ERROR: Unknown FUJIFILM Makernote identifier"; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -2244,11 +2261,13 @@ bool CjfifDecode::DecodeMakerSubType() else if(m_strImgExifMake == "SONY") { strTmp = ""; + for(uint32_t ind = 0; ind < 12; ind++) { if(Buf(m_nPos + ind) != 0) strTmp += Buf(m_nPos + ind); } + if(strTmp == "SONY DSC ") { // Valid marker @@ -2259,7 +2278,8 @@ bool CjfifDecode::DecodeMakerSubType() { strTmp = "ERROR: Unknown SONY Makernote identifier"; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + + if(m_pAppConfig->interactive()) { msgBox.setText(strTmp); msgBox.exec(); @@ -2267,13 +2287,12 @@ bool CjfifDecode::DecodeMakerSubType() return false; } - } // SONY return true; - } +//----------------------------------------------------------------------------- // Read two UINT32 from the buffer (8B) and interpret // as a rational entry. Convert to floating point. // Byte swap as required @@ -2285,7 +2304,7 @@ bool CjfifDecode::DecodeMakerSubType() // RETURN: // - Was the conversion successful? // -bool CjfifDecode::DecodeValRational(uint32_t nPos, float &nVal) +bool CjfifDecode::DecodeValRational(uint32_t nPos, double &nVal) { int nValNumer; @@ -2303,11 +2322,12 @@ bool CjfifDecode::DecodeValRational(uint32_t nPos, float &nVal) } else { - nVal = (float) nValNumer / (float) nValDenom; + nVal = static_cast(nValNumer) / static_cast(nValDenom); return true; } } +//----------------------------------------------------------------------------- // Read two UINT32 from the buffer (8B) to create a formatted // fraction string. Byte swap as required // @@ -2329,6 +2349,7 @@ QString CjfifDecode::DecodeValFraction(uint32_t nPos) return strTmp; } +//----------------------------------------------------------------------------- // Convert multiple coordinates into a formatted GPS string // // INPUT: @@ -2343,15 +2364,15 @@ QString CjfifDecode::DecodeValFraction(uint32_t nPos) // RETURN: // - Was the conversion successful? // -bool CjfifDecode::PrintValGPS(uint32_t nCount, float fCoord1, float fCoord2, float fCoord3, QString & strCoord) +bool CjfifDecode::PrintValGPS(uint32_t nCount, double fCoord1, double fCoord2, double fCoord3, QString & strCoord) { - float fTemp; + double fTemp; uint32_t nCoordDeg; uint32_t nCoordMin; - float fCoordSec; + double fCoordSec; // TODO: Extend to support 1 & 2 coordinate GPS entries if(nCount == 3) @@ -2362,8 +2383,8 @@ bool CjfifDecode::PrintValGPS(uint32_t nCount, float fCoord1, float fCoord2, flo if(fCoord3 == 0) { - fTemp = fCoord2 - (float) nCoordMin; - fCoordSec = fTemp * (float) 60.0; + fTemp = fCoord2 - static_cast(nCoordMin); + fCoordSec = fTemp * static_cast(60.0); } else { @@ -2381,6 +2402,7 @@ bool CjfifDecode::PrintValGPS(uint32_t nCount, float fCoord1, float fCoord2, flo } +//----------------------------------------------------------------------------- // Read in 3 rational values from the buffer and output as a formatted GPS string // // INPUT: @@ -2394,11 +2416,9 @@ bool CjfifDecode::PrintValGPS(uint32_t nCount, float fCoord1, float fCoord2, flo // bool CjfifDecode::DecodeValGPS(uint32_t nPos, QString & strCoord) { - float fCoord1 = 0; - - float fCoord2 = 0; - - float fCoord3 = 0; + double fCoord1 = 0; + double fCoord2 = 0; + double fCoord3 = 0; bool bRet; @@ -2408,11 +2428,13 @@ bool CjfifDecode::DecodeValGPS(uint32_t nPos, QString & strCoord) bRet = DecodeValRational(nPos, fCoord1); nPos += 8; } + if(bRet) { bRet = DecodeValRational(nPos, fCoord2); nPos += 8; } + if(bRet) { bRet = DecodeValRational(nPos, fCoord3); @@ -2430,6 +2452,7 @@ bool CjfifDecode::DecodeValGPS(uint32_t nPos, QString & strCoord) } } +//----------------------------------------------------------------------------- // Read a UINT16 from the buffer, byte swap as required // // INPUT: @@ -2443,6 +2466,7 @@ uint32_t CjfifDecode::ReadSwap2(uint32_t nPos) return ByteSwap2(Buf(nPos + 0), Buf(nPos + 1)); } +//----------------------------------------------------------------------------- // Read a UINT32 from the buffer, byte swap as required // // INPUT: @@ -2456,6 +2480,7 @@ uint32_t CjfifDecode::ReadSwap4(uint32_t nPos) return ByteSwap4(Buf(nPos), Buf(nPos + 1), Buf(nPos + 2), Buf(nPos + 3)); } +//----------------------------------------------------------------------------- // Read a UINT32 from the buffer, force as big endian // // INPUT: @@ -2470,6 +2495,7 @@ uint32_t CjfifDecode::ReadBe4(uint32_t nPos) return (Buf(nPos) << 24) + (Buf(nPos + 1) << 16) + (Buf(nPos + 2) << 8) + Buf(nPos + 3); } +//----------------------------------------------------------------------------- // Print hex from array of unsigned char // // INPUT: @@ -2523,10 +2549,12 @@ QString CjfifDecode::PrintAsHexUC(uint8_t *anBytes, uint32_t nCount) } } + strFull += "]"; return strFull; } +//----------------------------------------------------------------------------- // Print hex from array of unsigned bytes // // INPUT: @@ -2551,6 +2579,7 @@ QString CjfifDecode::PrintAsHex8(uint32_t *anBytes, uint32_t nCount) strFull = "0x["; bExceedMaxDisplay = (nCount > nMaxDisplay); + for(uint32_t nInd = 0; nInd < nCount; nInd++) { if(nInd < nMaxDisplay) @@ -2578,10 +2607,12 @@ QString CjfifDecode::PrintAsHex8(uint32_t *anBytes, uint32_t nCount) } } + strFull += "]"; return strFull; } +//----------------------------------------------------------------------------- // Print hex from array of unsigned words // // INPUT: @@ -2605,6 +2636,7 @@ QString CjfifDecode::PrintAsHex32(uint32_t *anWords, uint32_t nCount) bool bExceedMaxDisplay; bExceedMaxDisplay = (nCount > nMaxDisplay); + for(uint32_t nInd = 0; nInd < nCount; nInd++) { if(nInd < nMaxDisplay) @@ -2629,10 +2661,12 @@ QString CjfifDecode::PrintAsHex32(uint32_t *anWords, uint32_t nCount) } } + strFull += "]"; return strFull; } +//----------------------------------------------------------------------------- // Process all of the entries within an EXIF IFD directory // This is used for the main EXIF IFDs as well as MakerNotes // @@ -2683,7 +2717,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint QString strValTmp; - float fValReal; + double fValReal; QString strMaker; @@ -2711,9 +2745,9 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint uint32_t anValues[MAX_anValues]; // Array of decoded values (Uint32) - signed anValuesS[MAX_anValues]; // Array of decoded values (Int32) + int32_t anValuesS[MAX_anValues]; // Array of decoded values (Int32) - float afValues[MAX_anValues]; // Array of decoded values (float) + double afValues[MAX_anValues]; // Array of decoded values (float) uint32_t nIfdOffset; // First DWORD decode, usually offset @@ -2754,7 +2788,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint // Mark the image as containing Makernotes m_bImgExifMakernotes = true; - if(!m_pAppConfig->bDecodeMaker) + if(!m_pAppConfig->decodeMaker()) { strTmp = QString(" Makernote decode option not enabled."); m_pLog->AddLine(strTmp); @@ -2810,7 +2844,6 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint // decode accordingly. for(uint32_t nIfdEntryInd = 0; nIfdEntryInd < nIfdDirLen; nIfdEntryInd++) { - // By default, show single-line value summary // bExtraDecode is used to indicate that additional special // parsing output is available for this entry @@ -2877,6 +2910,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint { acIfdValOffsetStr[i] = Buf(m_nPos + i); } + acIfdValOffsetStr[4] = '\0'; // ... now as an unsigned value @@ -2916,7 +2950,6 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint switch (nIfdFormat) { - // ---------------------------------------- // --- IFD Entry Type: Unsigned Byte // ---------------------------------------- @@ -2950,8 +2983,10 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint anValues[nInd] = Buf(nPosExifStart + nIfdOffset + nInd); } } + strValOut = PrintAsHex8(anValues, nIfdNumComps); } + strFull += strValOut; strFull += "]"; DbgAddLine(strFull); @@ -3009,15 +3044,17 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint // TODO: Clean this up if(nVal != 0) { - cVal = (char) nVal; + cVal = static_cast(nVal); + if(!isprint(nVal)) { cVal = '.'; } + strValOut += cVal; } - } + strFull += strValOut; DbgAddLine(strFull); @@ -3072,21 +3109,24 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint strValOut = ""; strFull = " Unsigned Short=["; + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) { if(nInd != 0) { strValOut += ", "; } + anValues[nInd] = ReadSwap2(nPosExifStart + nIfdOffset + (2 * nInd)); strValTmp = QString("%1").arg(anValues[nInd]); strValOut += strValTmp; } + strFull += strValOut; strFull += "]"; DbgAddLine(strFull); - } + break; // ---------------------------------------- @@ -3113,13 +3153,16 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint anValues[nInd] = ReadSwap4(nPosExifStart + nIfdOffset + (nInd * 4)); } } + strValOut = PrintAsHex32(anValues, nIfdNumComps); + // If we only have a single component, then display both the hex and decimal if(nCompsToDisplay == 1) { strTmp = QString("%1 / %2").arg(strValOut).arg(anValues[0]); strValOut = strTmp; } + break; // ---------------------------------------- @@ -3139,11 +3182,13 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint { strValOut += ", "; } + strValTmp = DecodeValFraction(nPosExifStart + nIfdOffset + (nInd * 8)); bRet = DecodeValRational(nPosExifStart + nIfdOffset + (nInd * 8), fValReal); afValues[nInd] = fValReal; strValOut += strValTmp; } + strFull += strValOut; strFull += "]"; DbgAddLine(strFull); @@ -3170,9 +3215,9 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint { anValues[nInd] = Buf(m_nPos + nInd); } + strValOut = PrintAsHex8(anValues, nIfdNumComps); strFull += strValOut; - } else { @@ -3182,9 +3227,11 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint { anValues[nInd] = Buf(nPosExifStart + nIfdOffset + nInd); } + strValOut = PrintAsHex8(anValues, nIfdNumComps); strFull += strValOut; } + strFull += "]"; DbgAddLine(strFull); @@ -3242,21 +3289,24 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint // "signed short". strValOut = ""; strFull = " Signed Short=["; + for(uint32_t nInd = 0; nInd < nCompsToDisplay; nInd++) { if(nInd != 0) { strValOut += ", "; } + anValuesS[nInd] = ReadSwap2(nPosExifStart + nIfdOffset + (2 * nInd)); strValTmp = QString("%1").arg(anValuesS[nInd]); strValOut += strValTmp; } + strFull += strValOut; strFull += "]"; DbgAddLine(strFull); - } + break; // ---------------------------------------- @@ -3276,11 +3326,13 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint { strValOut += ", "; } + strValTmp = DecodeValFraction(nPosExifStart + nIfdOffset + (nInd * 8)); bRet = DecodeValRational(nPosExifStart + nIfdOffset + (nInd * 8), fValReal); afValues[nInd] = fValReal; strValOut += strValTmp; } + strFull += strValOut; strFull += "]"; DbgAddLine(strFull); @@ -3625,6 +3677,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint break; } } + strValOut += "]"; } @@ -3637,7 +3690,6 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint strVal = m_pWBuf->BufReadUniStr2(nPosExifStart + nIfdOffset, nIfdNumComps); strValOut += strVal; strValOut += "\""; - } else if(strIfdTag == "UserComment") { @@ -3648,6 +3700,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint { anCharCode[vInd] = Buf(nPosExifStart + nIfdOffset + 0 + vInd); } + // Actual string strValOut = "\""; bool bDone = false; @@ -3657,6 +3710,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint for(uint32_t vInd = 0; (vInd < nIfdNumComps - 8) && (!bDone); vInd++) { cTmp = Buf(nPosExifStart + nIfdOffset + 8 + vInd); + if(cTmp == 0) { bDone = true; @@ -3666,6 +3720,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint strValOut += cTmp; } } + strValOut += "\""; } else if(strIfdTag == "MeteringMode") @@ -3942,11 +3997,8 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint if(strIfdTag == "CFAPattern") { uint32_t nHorzRepeat, nVertRepeat; - uint32_t anCfaVal[16][16]; - uint32_t nInd = 0; - uint32_t nVal; QString strLine, strCol; @@ -3954,20 +4006,24 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint nHorzRepeat = anValues[nInd + 0] * 256 + anValues[nInd + 1]; nVertRepeat = anValues[nInd + 2] * 256 + anValues[nInd + 3]; nInd += 4; + if((nHorzRepeat < 16) && (nVertRepeat < 16)) { bExtraDecode = true; strTmp = QString(" [%1] =").arg(strIfdTag, -36); m_pLog->AddLine(strTmp); + for(uint32_t nY = 0; nY < nVertRepeat; nY++) { strLine = QString(" %1 = [ ").arg("", -36); + for(uint32_t nX = 0; nX < nHorzRepeat; nX++) { if(nInd < MAX_anValues) { nVal = anValues[nInd++]; anCfaVal[nY][nX] = nVal; + switch (nVal) { case 0: @@ -4004,7 +4060,6 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint m_pLog->AddLine(strLine); } } - } if((strIfd == "InteropIFD") && (strIfdTag == "InteroperabilityVersion")) @@ -4031,7 +4086,8 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint // Print summary line now, before sub details // Disable later summary line bExtraDecode = true; - if((!m_pAppConfig->bExifHideUnknown) || (!nIfdTagUnknown)) + + if((!m_pAppConfig->hideUnknownExif()) || (!nIfdTagUnknown)) { strTmp = QString(" [%1]").arg(strIfdTag, -36); m_pLog->AddLine(strTmp); @@ -4048,7 +4104,8 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint strRetVal = LookupMakerCanonTag(nIfdTagVal, ind, anValues[ind]); strMaker = strRetVal.strTag; strValTmp = QString(" [%1] = %2").arg(strMaker, -34).arg(strRetVal.strVal); - if((!m_pAppConfig->bExifHideUnknown) || (!strRetVal.bUnknown)) + + if((!m_pAppConfig->hideUnknownExif()) || (!strRetVal.bUnknown)) { m_pLog->AddLine(strValTmp); } @@ -4150,6 +4207,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint // Embedded thumbnail, compression format m_nImgExifThumbComp = ReadSwap4(m_nPos); } + if((strIfd == "IFD1") && (strIfdTag == "JpegIFOffset")) { // Embedded thumbnail, offset @@ -4158,6 +4216,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint .arg(nIfdOffset, 4, 16, QChar('0')) .arg(m_nImgExifThumbOffset, 4, 16, QChar('0')); } + if((strIfd == "IFD1") && (strIfdTag == "JpegIFByteCount")) { // Embedded thumbnail, length @@ -4176,6 +4235,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint // use of the Make field m_bImgExifMakeSupported = false; + if(m_strImgExifMake == "Canon") { m_bImgExifMakeSupported = true; @@ -4225,9 +4285,8 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint if(!bExtraDecode) { // Provide option to skip unknown fields - if((!m_pAppConfig->bExifHideUnknown) || (!nIfdTagUnknown)) + if((!m_pAppConfig->hideUnknownExif()) || (!nIfdTagUnknown)) { - // If the tag is an ASCII string, we want to wrap with quote marks if(nIfdFormat == 2) { @@ -4237,13 +4296,12 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint { strTmp = QString(" [%1] = %2").arg(strIfdTag, -36).arg(strValOut); } - m_pLog->AddLine(strTmp); + m_pLog->AddLine(strTmp); } } DbgAddLine(""); - } // for nIfdEntryInd // =========== EXIF IFD (End) =========== @@ -4255,6 +4313,7 @@ uint32_t CjfifDecode::DecodeExifIfd(QString strIfd, uint32_t nPosExifStart, uint return 0; } +//----------------------------------------------------------------------------- // Handle APP13 marker // This includes: // - Photoshop "Save As" and "Save for Web" quality settings @@ -4315,6 +4374,7 @@ uint32_t CjfifDecode::DecodeApp13Ps() return 0; } +//----------------------------------------------------------------------------- // Start decoding a single ICC header segment @ nPos uint32_t CjfifDecode::DecodeIccHeader(uint32_t nPos) { @@ -4564,6 +4624,7 @@ uint32_t CjfifDecode::DecodeIccHeader(uint32_t nPos) strTmp1 = QString("? (0x%1)").arg(nPrimPlatSig, 8, 16, QChar('0')); break; } + strTmp = QString(" %1 : %2 (%3)").arg("Primary platform", -33).arg(strTmp1).arg(Uint2Chars(nPrimPlatSig)); m_pLog->AddLine(strTmp); @@ -4628,6 +4689,7 @@ uint32_t CjfifDecode::DecodeIccHeader(uint32_t nPos) strTmp1 = QString("0x%1").arg(nRenderIntent, 8, 16, QChar('0')); break; } + strTmp = QString(" %1 : %2").arg("Rendering intent", -33).arg(strTmp1); m_pLog->AddLine(strTmp); @@ -4648,6 +4710,7 @@ uint32_t CjfifDecode::DecodeIccHeader(uint32_t nPos) return 0; } +//----------------------------------------------------------------------------- // Provide special output formatter for ICC Date/Time // NOTE: It appears that the nParts had to be decoded in the // reverse order from what I had expected, so one should @@ -4664,8 +4727,7 @@ QString CjfifDecode::DecodeIccDateTime(uint32_t anVal[]) anParts[3] = (anVal[1] & 0x0000FFFF); // Hour anParts[4] = (anVal[0] & 0xFFFF0000) >> 16; // Min anParts[5] = (anVal[0] & 0x0000FFFF); // Sec - strDate = - QString("%1-%2-%3 %4:%5:%6") + strDate = QString("%1-%2-%3 %4:%5:%6") .arg(anParts[0], 4, 10, QChar('0')) .arg(anParts[1], 2, 10, QChar('0')) .arg(anParts[2], 2, 10, QChar('0')) @@ -4675,6 +4737,7 @@ QString CjfifDecode::DecodeIccDateTime(uint32_t anVal[]) return strDate; } +//----------------------------------------------------------------------------- // Parser for APP2 ICC profile marker uint32_t CjfifDecode::DecodeApp2IccProfile(uint32_t nLen) { @@ -4708,20 +4771,16 @@ uint32_t CjfifDecode::DecodeApp2IccProfile(uint32_t nLen) return 0; } +//----------------------------------------------------------------------------- // Parser for APP2 FlashPix marker uint32_t CjfifDecode::DecodeApp2Flashpix() { - QString strTmp; uint32_t nFpxVer; - uint32_t nFpxSegType; - uint32_t nFpxInteropCnt; - uint32_t nFpxEntitySz; - uint32_t nFpxDefault; bool bFpxStorage; @@ -4729,17 +4788,13 @@ uint32_t CjfifDecode::DecodeApp2Flashpix() QString strFpxStorageClsStr; uint32_t nFpxStIndexCont; - uint32_t nFpxStOffset; - uint32_t nFpxStWByteOrder; - uint32_t nFpxStWFormat; QString strFpxStClsidStr; uint32_t nFpxStDwOsVer; - uint32_t nFpxStRsvd; QString streamStr; @@ -4769,6 +4824,7 @@ uint32_t CjfifDecode::DecodeApp2Flashpix() // a "storage". It looks like we should probably be using this to determine // that we have a "storage" bFpxStorage = false; + if(nFpxEntitySz == 0xFFFFFFFF) { bFpxStorage = true; @@ -4790,7 +4846,7 @@ uint32_t CjfifDecode::DecodeApp2Flashpix() // BUG: #1112 //streamStr = m_pWBuf->BufReadUniStr(m_nPos); streamStr = m_pWBuf->BufReadUniStr2(m_nPos, MAX_BUF_READ_STR); - m_nPos += 2 * ((uint32_t) streamStr.length() + 1); // 2x because unicode + m_nPos += 2 * (static_cast(streamStr.length()) + 1); // 2x because unicode strTmp = QString(" Stream Name = [%1]").arg(streamStr); m_pLog->AddLine(strTmp); @@ -4802,23 +4858,23 @@ uint32_t CjfifDecode::DecodeApp2Flashpix() // FIXME: // NOTE: Very strange reordering required here. Doesn't seem consistent // This means that other fields are probably wrong as well (endian) - strFpxStorageClsStr = - QString("%1%2%3%4-%5%6-%7%8-%9%10-%11%12%13%14%15%16").arg(Buf(m_nPos + 3), 2, 16, QChar('0')).arg(Buf(m_nPos + 2), 2, - 16, - QChar('0')). - arg(Buf(m_nPos + 1), 2, 16, QChar('0')).arg(Buf(m_nPos + 0), 2, 16, QChar('0')).arg(Buf(m_nPos + 5), 2, 16, - QChar('0')).arg(Buf(m_nPos + 4), 2, - 16, - QChar('0')). - arg(Buf(m_nPos + 7), 2, 16, QChar('0')).arg(Buf(m_nPos + 6), 2, 16, QChar('0')).arg(Buf(m_nPos + 8), 2, 16, - QChar('0')).arg(Buf(m_nPos + 9), 2, - 16, - QChar('0')). - arg(Buf(m_nPos + 10), 2, 16, QChar('0')).arg(Buf(m_nPos + 11), 2, 16, QChar('0')).arg(Buf(m_nPos + 12), 2, 16, - QChar('0')).arg(Buf(m_nPos + 13), - 2, 16, - QChar('0')). - arg(Buf(m_nPos + 14), 2, 16, QChar('0')).arg(Buf(m_nPos + 15), 2, 16, QChar('0')); + strFpxStorageClsStr = QString("%1%2%3%4-%5%6-%7%8-%9%10-%11%12%13%14%15%16") + .arg(Buf(m_nPos + 3), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 2), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 1), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 0), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 5), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 4), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 7), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 6), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 8), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 9), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 10), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 11), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 12), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 13), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 14), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 15), 2, 16, QChar('0')); m_nPos += 16; strTmp = QString(" Storage Class = [%1]").arg(strFpxStorageClsStr); m_pLog->AddLine(strTmp); @@ -4826,7 +4882,6 @@ uint32_t CjfifDecode::DecodeApp2Flashpix() } return 0; - } else if(nFpxSegType == 2) { @@ -4855,19 +4910,23 @@ uint32_t CjfifDecode::DecodeApp2Flashpix() // NOTE: Very strange reordering required here. Doesn't seem consistent! // This means that other fields are probably wrong as well (endian) strFpxStClsidStr = - QString("%1%2%3%4-%5%6-%7%8-%9%10-%11%12%13%14%15%16").arg(Buf(m_nPos + 3), 2, 16, QChar('0')).arg(Buf(m_nPos + 2), 2, 16, - QChar('0')). - arg(Buf(m_nPos + 1), 2, 16, QChar('0')).arg(Buf(m_nPos + 0), 2, 16, QChar('0')).arg(Buf(m_nPos + 5), 2, 16, - QChar('0')).arg(Buf(m_nPos + 4), 2, 16, - QChar('0')). - arg(Buf(m_nPos + 7), 2, 16, QChar('0')).arg(Buf(m_nPos + 6), 2, 16, QChar('0')).arg(Buf(m_nPos + 8), 2, 16, - QChar('0')).arg(Buf(m_nPos + 9), 2, 16, - QChar('0')). - arg(Buf(m_nPos + 10), 2, 16, QChar('0')).arg(Buf(m_nPos + 11), 2, 16, QChar('0')).arg(Buf(m_nPos + 12), 2, 16, - QChar('0')).arg(Buf(m_nPos + 13), 2, - 16, - QChar('0')). - arg(Buf(m_nPos + 14), 2, 16, QChar('0')).arg(Buf(m_nPos + 15), 2, 16, QChar('0')); + QString("%1%2%3%4-%5%6-%7%8-%9%10-%11%12%13%14%15%16") + .arg(Buf(m_nPos + 3), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 2), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 1), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 0), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 5), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 4), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 7), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 6), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 8), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 9), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 10), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 11), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 12), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 13), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 14), 2, 16, QChar('0')) + .arg(Buf(m_nPos + 15), 2, 16, QChar('0')); m_nPos += 16; nFpxStRsvd = (Buf(m_nPos++) << 8) + Buf(m_nPos++); @@ -4898,6 +4957,7 @@ uint32_t CjfifDecode::DecodeApp2Flashpix() } } +//----------------------------------------------------------------------------- // Decode the DHT marker segment (Huffman Tables) // In some cases (such as for MotionJPEG), we fake out // the DHT tables (when bInject=true) with a standard table @@ -4938,7 +4998,6 @@ void CjfifDecode::DecodeDHT(bool bInject) m_pLog->AddLine(strTmp); uint32_t nDhtClass_Tc; // Range 0..1 - uint32_t nDhtHuffTblId_Th; // Range 0..3 // In various places, added m_bStateAbort check to allow us @@ -4966,6 +5025,7 @@ void CjfifDecode::DecodeDHT(bool bInject) //m_bStateAbort = true; // Stop decoding break; } + if(nDhtHuffTblId_Th >= MAX_DHT_DEST_ID) { strTmp = QString("ERROR: Invalid DHT Dest ID (%1). Aborting DHT Load.").arg(nDhtHuffTblId_Th); @@ -4982,11 +5042,8 @@ void CjfifDecode::DecodeDHT(bool bInject) } #define DECODE_DHT_MAX_DHT 256 - uint32_t anDhtCodeVal[DECODE_DHT_MAX_DHT + 1]; // Should only need max 162 codes - uint32_t nDhtInd; - uint32_t nDhtCodesTotal; // Clear out the code list @@ -4999,14 +5056,15 @@ void CjfifDecode::DecodeDHT(bool bInject) // read in earlier nDhtCodesTotal = 0; nDhtInd = 0; + for(uint32_t nIndLen = 1; ((!m_bStateAbort) && (nIndLen <= MAX_DHT_CODELEN)); nIndLen++) { // Keep a total count of the number of DHT codes read nDhtCodesTotal += m_anDhtNumCodesLen_Li[nIndLen]; strFull = QString(" Codes of length %1 bits (%2 total): ") - .arg(nIndLen, 2, 10, QChar('0')) - .arg(m_anDhtNumCodesLen_Li[nIndLen], 3, 10, QChar('0')); + .arg(nIndLen, 2, 10, QChar('0')) + .arg(m_anDhtNumCodesLen_Li[nIndLen], 3, 10, QChar('0')); for(uint32_t nIndCode = 0; ((!m_bStateAbort) && (nIndCode < m_anDhtNumCodesLen_Li[nIndLen])); nIndCode++) { @@ -5015,6 +5073,7 @@ void CjfifDecode::DecodeDHT(bool bInject) { strFull = " "; } + nTmpVal = Buf(m_nPos++); strTmp = QString("%1 ").arg(nTmpVal, 2, 16, QChar('0')); strFull += strTmp; @@ -5038,15 +5097,17 @@ void CjfifDecode::DecodeDHT(bool bInject) nDhtInd++; strTmp = QString("Excessive DHT entries (%1)... skipping").arg(nDhtInd); m_pLog->AddLineErr(strTmp); + if(!m_bStateAbort) { DecodeErrCheck(true); } } - } + m_pLog->AddLine(strFull); } + strTmp = QString(" Total number of codes: %1").arg(nDhtCodesTotal, 3, 10, QChar('0')); m_pLog->AddLine(strTmp); @@ -5056,26 +5117,28 @@ void CjfifDecode::DecodeDHT(bool bInject) uint32_t nCodeVal = 0; nDhtInd = 0; - if(m_pAppConfig->bOutputDHTexpand) + + if(m_pAppConfig->expandDht()) { m_pLog->AddLine(""); m_pLog->AddLine(" Expanded Form of Codes:"); } + for(uint32_t nBitLen = 1; ((!m_bStateAbort) && (nBitLen <= 16)); nBitLen++) { if(m_anDhtNumCodesLen_Li[nBitLen] > 0) { - if(m_pAppConfig->bOutputDHTexpand) + if(m_pAppConfig->expandDht()) { strTmp = QString(" Codes of length %1 bits:").arg(nBitLen, 2, 10, QChar('0')); m_pLog->AddLine(strTmp); } + // Codes exist for this bit-length // Walk through and generate the bitvalues for(uint32_t bit_ind = 1; ((!m_bStateAbort) && (bit_ind <= m_anDhtNumCodesLen_Li[nBitLen])); bit_ind++) { uint32_t nDecVal = nCodeVal; - uint32_t nBinBit; char acBinStr[17] = ""; @@ -5084,13 +5147,14 @@ void CjfifDecode::DecodeDHT(bool bInject) // If the user has enabled output of DHT expanded tables, // report the bit-string sequences. - if(m_pAppConfig->bOutputDHTexpand) + if(m_pAppConfig->expandDht()) { for(uint32_t nBinInd = nBitLen; nBinInd >= 1; nBinInd--) { nBinBit = (nDecVal >> (nBinInd - 1)) & 1; acBinStr[nBinStrLen++] = (nBinBit) ? '1' : '0'; } + acBinStr[nBinStrLen] = '\0'; strFull = QString(" %1 = %2").arg(acBinStr).arg(anDhtCodeVal[nDhtInd], 2, 16, QChar('0')); @@ -5116,9 +5180,7 @@ void CjfifDecode::DecodeDHT(bool bInject) // Store the lookup value // Shift left to MSB of 32-bit uint32_t nTmpMask = m_anMaskLookup[nBitLen]; - uint32_t nTmpBits = nDecVal << (32 - nBitLen); - uint32_t nTmpCode = anDhtCodeVal[nDhtInd]; bRet = m_pImgDec->SetDhtEntry(nDhtHuffTblId_Th, nDhtClass_Tc, nDhtLookupInd, nBitLen, nTmpBits, nTmpMask, nTmpCode); @@ -5132,6 +5194,7 @@ void CjfifDecode::DecodeDHT(bool bInject) nDhtInd++; } } + // For each loop iteration (on bit length), we shift the code value nCodeVal <<= 1; } @@ -5140,13 +5203,13 @@ void CjfifDecode::DecodeDHT(bool bInject) uint32_t nTmpSize = nDhtLookupInd; bRet = m_pImgDec->SetDhtSize(nDhtHuffTblId_Th, nDhtClass_Tc, nTmpSize); + if(!m_bStateAbort) { DecodeErrCheck(bRet); } m_pLog->AddLine(""); - } if(bInject) @@ -5157,6 +5220,7 @@ void CjfifDecode::DecodeDHT(bool bInject) } } +//----------------------------------------------------------------------------- // Check return value of previous call. If failed, then ask // user if they wish to continue decoding. If no, then flag to // the decoder that we're done (avoids continuous failures) @@ -5164,7 +5228,7 @@ void CjfifDecode::DecodeErrCheck(bool bRet) { if(!bRet) { - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText("Do you want to continue decoding?"); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); @@ -5177,6 +5241,7 @@ void CjfifDecode::DecodeErrCheck(bool bRet) } } +//----------------------------------------------------------------------------- // This routine is called after the expected fields of the marker segment // have been processed. The file position should line up with the offset // dictated by the marker length. If a mismatch is detected, report an @@ -5190,7 +5255,6 @@ bool CjfifDecode::ExpectMarkerEnd(uint32_t nMarkerStart, uint32_t nMarkerLen) QString strTmp; uint32_t nMarkerEnd = nMarkerStart + nMarkerLen; - uint32_t nMarkerExtra = nMarkerEnd - m_nPos; if(m_nPos < nMarkerEnd) @@ -5198,7 +5262,8 @@ bool CjfifDecode::ExpectMarkerEnd(uint32_t nMarkerStart, uint32_t nMarkerLen) // The length indicates that there is more data than we processed strTmp = QString(" WARNING: Marker length longer than expected"); m_pLog->AddLineWarn(strTmp); - if(!m_pAppConfig->bRelaxedParsing) + + if(!m_pAppConfig->relaxedParsing()) { // Abort m_pLog->AddLineErr(" Stopping decode"); @@ -5218,7 +5283,8 @@ bool CjfifDecode::ExpectMarkerEnd(uint32_t nMarkerStart, uint32_t nMarkerLen) // The length indicates that there is less data than we processed strTmp = QString(" WARNING: Marker length shorter than expected"); m_pLog->AddLineWarn(strTmp); - if(!m_pAppConfig->bRelaxedParsing) + + if(!m_pAppConfig->relaxedParsing()) { // Abort m_pLog->AddLineErr(" Stopping decode"); @@ -5258,6 +5324,7 @@ bool CjfifDecode::ExpectMarkerEnd(uint32_t nMarkerStart, uint32_t nMarkerLen) return true; } +//----------------------------------------------------------------------------- // Validate an unsigned value to ensure it is in allowable range // - If the value is outside the range, an error is shown and // the parsing stops if relaxed parsing is not enabled @@ -5299,7 +5366,8 @@ bool CjfifDecode::ValidateValue(uint32_t &nVal, uint32_t nMin, uint32_t nMax, QS strErr = QString(" ERROR: %1 value too large (Actual = %2, Expected <= %3)").arg(strName).arg(nVal).arg(nMax); m_pLog->AddLineErr(strErr); } - if(!m_pAppConfig->bRelaxedParsing) + + if(!m_pAppConfig->relaxedParsing()) { // Defined as fatal error // TODO: Replace with glb_strMsgStopDecode? @@ -5327,9 +5395,9 @@ bool CjfifDecode::ValidateValue(uint32_t &nVal, uint32_t nMin, uint32_t nMax, QS return true; } } - } +//----------------------------------------------------------------------------- // This is the primary JFIF marker parser. It reads the // marker value at the current file position and launches the // specific parser routine. This routine exits when @@ -5341,31 +5409,24 @@ uint32_t CjfifDecode::DecodeMarker() char acIdentifier[MAX_IDENTIFIER]; QString strTmp; - QString strFull; // Used for concatenation uint32_t nLength; // General purpose uint32_t nTmpVal; - - quint8 nTmpVal1; + uint8_t nTmpVal1; uint16_t nTmpVal2; uint32_t nCode; - uint32_t nPosEnd; - uint32_t nPosSaved; // General-purpose saved position in file - uint32_t nPosExifStart; - uint32_t nRet; // General purpose return value bool bRet; uint32_t nPosMarkerStart; // Offset for current marker - uint32_t nColTransform = 0; // Color Transform from APP14 marker // For DQT @@ -5392,9 +5453,11 @@ uint32_t CjfifDecode::DecodeMarker() .arg(m_nPos, 8, 16, QChar('0')); m_pLog->AddLineErr(strTmp); } + m_nPos++; return DECMARK_ERR; } + m_nPos++; // Read the current marker code @@ -5448,7 +5511,7 @@ uint32_t CjfifDecode::DecodeMarker() acIdentifier[MAX_IDENTIFIER - 1] = 0; // Null terminate just in case strTmp = QString(" Identifier = [%1]").arg(acIdentifier); m_pLog->AddLine(strTmp); - m_nPos += (uint32_t) strlen(acIdentifier) + 1; + m_nPos += static_cast(strlen(acIdentifier)) + 1; if(strcmp(acIdentifier, "Ducky") != 0) { @@ -5462,6 +5525,7 @@ uint32_t CjfifDecode::DecodeMarker() strTmp = QString(" Photoshop Save For Web Quality = [%1]").arg(m_nImgQualPhotoshopSfw); m_pLog->AddLine(strTmp); } + // Restore original position in file to a point // after the section m_nPos = nPosSaved + nLength; @@ -5517,7 +5581,6 @@ uint32_t CjfifDecode::DecodeMarker() default: strTmp = QString(" ColorTransform = %1 [???]").arg(nColTransform); break; - } m_pLog->AddLine(strTmp); @@ -5552,7 +5615,7 @@ uint32_t CjfifDecode::DecodeMarker() acIdentifier[MAX_IDENTIFIER - 1] = 0; // Null terminate just in case strTmp = QString(" Identifier = [%1]").arg(acIdentifier); m_pLog->AddLine(strTmp); - m_nPos += (uint32_t) strlen(acIdentifier) + 1; + m_nPos += static_cast(strlen(acIdentifier)) + 1; if(strcmp(acIdentifier, "Photoshop 3.0") != 0) { @@ -5582,7 +5645,7 @@ uint32_t CjfifDecode::DecodeMarker() acIdentifier[MAX_IDENTIFIER - 1] = 0; // Null terminate just in case strTmp = QString(" Identifier = [%1]").arg(acIdentifier); m_pLog->AddLine(strTmp); - m_nPos += (uint32_t) strlen(acIdentifier); + m_nPos += static_cast(strlen(acIdentifier)); if(strncmp(acIdentifier, "http://ns.adobe.com/xap/1.0/\x00", 29) == 0) { //@@ @@ -5597,7 +5660,6 @@ uint32_t CjfifDecode::DecodeMarker() // updated to support unicode properly. uint32_t nPosMarkerEnd = nPosSaved + nLength - 1; - uint32_t sXmpLen = nPosMarkerEnd - m_nPos; uint8_t cXmpChar; @@ -5661,10 +5723,12 @@ uint32_t CjfifDecode::DecodeMarker() strTmp = ""; strFull = " Identifier TIFF = "; + for(uint32_t i = 0; i < 8; i++) { - acIdentifierTiff[i] = (uint8_t) Buf(m_nPos++); + acIdentifierTiff[i] = static_cast(Buf(m_nPos++)); } + strTmp = PrintAsHexUC(acIdentifierTiff, 8); strFull += strTmp; m_pLog->AddLine(strFull); @@ -5724,9 +5788,9 @@ uint32_t CjfifDecode::DecodeMarker() } nIfdCount = 0; + while(!exif_done) { - m_pLog->AddLine(""); strTmp = QString("IFD%1").arg(nIfdCount); @@ -5766,22 +5830,24 @@ uint32_t CjfifDecode::DecodeMarker() m_pLog->AddLine(""); DecodeExifIfd("SubIFD", nPosExifStart, m_nImgExifSubIfdPtr); } + if(m_nImgExifMakerPtr != 0) { m_pLog->AddLine(""); DecodeExifIfd("MakerIFD", nPosExifStart, m_nImgExifMakerPtr); } + if(m_nImgExifGpsIfdPtr != 0) { m_pLog->AddLine(""); DecodeExifIfd("GPSIFD", nPosExifStart, m_nImgExifGpsIfdPtr); } + if(m_nImgExifInteropIfdPtr != 0) { m_pLog->AddLine(""); DecodeExifIfd("InteropIFD", nPosExifStart, m_nImgExifInteropIfdPtr); } - } else { @@ -5838,7 +5904,7 @@ uint32_t CjfifDecode::DecodeMarker() acIdentifier[MAX_IDENTIFIER - 1] = 0; // Null terminate just in case strTmp = QString(" Identifier = [%1]").arg(acIdentifier); m_pLog->AddLine(strTmp); - m_nPos += (uint32_t) strlen(acIdentifier) + 1; + m_nPos += static_cast(strlen(acIdentifier)) + 1; if(strcmp(acIdentifier, "FPXR") == 0) { @@ -5931,6 +5997,7 @@ uint32_t CjfifDecode::DecodeMarker() { strFull += "."; } + if((i % 32) == 31) { m_pLog->AddLine(strFull); @@ -5960,7 +6027,7 @@ uint32_t CjfifDecode::DecodeMarker() // Only process remainder if it is JFIF. This marker // is also used for application-specific functions. - m_nPos += (uint32_t) (strlen(m_acApp0Identifier) + 1); + m_nPos += static_cast((strlen(m_acApp0Identifier)) + 1); m_nImgVersionMajor = Buf(m_nPos++); m_nImgVersionMinor = Buf(m_nPos++); @@ -6145,6 +6212,7 @@ uint32_t CjfifDecode::DecodeMarker() { strDqtPrecision = "16 bits"; } + strTmp = QString(" Precision=%1"), strDqtPrecision; m_pLog->AddLine(strTmp); } @@ -6177,6 +6245,7 @@ uint32_t CjfifDecode::DecodeMarker() { strDqtZigZagOrder = "Alternate coeff scan seqeunce"; } + strTmp = QString(" Coeff Scan Sequence=%s"), strDqtZigZagOrder; m_pLog->AddLine(strTmp); @@ -6192,11 +6261,13 @@ uint32_t CjfifDecode::DecodeMarker() nTmpVal = Buf(m_nPos++); strTmp = QString("%u"), nTmpVal; strSequence += strTmp; + if(nInd != 63) { strSequence += ", "; } } + strTmp = QString(" Custom sequence = [ %s ]"), strSequence; m_pLog->AddLine(strTmp); } @@ -6228,7 +6299,7 @@ uint32_t CjfifDecode::DecodeMarker() { m_pLog->AddLineErr(QString("ERROR: Destination ID = %1, >= %2").arg(nDqtQuantDestId_Tq).arg(MAX_DQT_DEST_ID)); - if(!m_pAppConfig->bRelaxedParsing) + if(!m_pAppConfig->relaxedParsing()) { m_pLog->AddLineErr(" Stopping decode"); return DECMARK_ERR; @@ -6275,15 +6346,15 @@ uint32_t CjfifDecode::DecodeMarker() if(m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]] != 0) { m_afStdQuantLumCompare[glb_anZigZag[nCoeffInd]] = - (float) (glb_anStdQuantLum[glb_anZigZag[nCoeffInd]]) / - (float) (m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]]); + static_cast((glb_anStdQuantLum[glb_anZigZag[nCoeffInd]])) / + static_cast((m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]])); dComparePercent = 100.0 * - (double) (m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]]) / - (double) (glb_anStdQuantLum[glb_anZigZag[nCoeffInd]]); + static_cast((m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]])) / + static_cast((glb_anStdQuantLum[glb_anZigZag[nCoeffInd]])); } else { - m_afStdQuantLumCompare[glb_anZigZag[nCoeffInd]] = (float) 999.99; + m_afStdQuantLumCompare[glb_anZigZag[nCoeffInd]] = 999.99; dComparePercent = 999.99; } } @@ -6292,15 +6363,15 @@ uint32_t CjfifDecode::DecodeMarker() if(m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]] != 0) { m_afStdQuantChrCompare[glb_anZigZag[nCoeffInd]] = - (float) (glb_anStdQuantChr[glb_anZigZag[nCoeffInd]]) / - (float) (m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]]); + static_cast((glb_anStdQuantChr[glb_anZigZag[nCoeffInd]])) / + static_cast((m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]])); dComparePercent = 100.0 * - (double) (m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]]) / - (double) (glb_anStdQuantChr[glb_anZigZag[nCoeffInd]]); + static_cast((m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]])) / + static_cast((glb_anStdQuantChr[glb_anZigZag[nCoeffInd]])); } else { - m_afStdQuantChrCompare[glb_anZigZag[nCoeffInd]] = (float) 999.99; + m_afStdQuantChrCompare[glb_anZigZag[nCoeffInd]] = 999.99; } } @@ -6310,7 +6381,6 @@ uint32_t CjfifDecode::DecodeMarker() // Check just in case entire table are ones (Quality 100) if(m_anImgDqtTbl[nDqtQuantDestId_Tq][glb_anZigZag[nCoeffInd]] != 1) bQuantAllOnes = 0; - } // 0..63 // Note that the DQT table that we are saving is already @@ -6356,7 +6426,6 @@ uint32_t CjfifDecode::DecodeMarker() */ m_pLog->AddLine(strFull); - } // Perform some statistical analysis of the quality factor @@ -6444,6 +6513,7 @@ uint32_t CjfifDecode::DecodeMarker() if(!ValidateValue(nDAC_Cs, 0, 255, "Conditioning table value ", true, 0)) return DECMARK_ERR; } + if(!ExpectMarkerEnd(nPosMarkerStart, nLength)) return DECMARK_ERR; @@ -6465,6 +6535,7 @@ uint32_t CjfifDecode::DecodeMarker() if(!ExpectMarkerEnd(nPosMarkerStart, nLength)) return DECMARK_ERR; + break; case JFIF_EXP: @@ -6520,10 +6591,12 @@ uint32_t CjfifDecode::DecodeMarker() // (non-differential) with Huffman coding. Progressive, Lossless, // Differential and Arithmetic coded modes are not supported. m_bImgSofUnsupported = true; + if(nCode == JFIF_SOF0) { m_bImgSofUnsupported = false; } + if(nCode == JFIF_SOF1) { m_bImgSofUnsupported = false; @@ -6544,6 +6617,7 @@ uint32_t CjfifDecode::DecodeMarker() m_nSofPrecision_P = Buf(m_nPos++); // P strTmp = QString(" Precision = %1").arg(m_nSofPrecision_P); m_pLog->AddLine(strTmp); + if(!ValidateValue(m_nSofPrecision_P, 2, 16, "Precision

", true, 8)) return DECMARK_ERR; @@ -6570,19 +6644,21 @@ uint32_t CjfifDecode::DecodeMarker() // m_nSofSampsPerLine_X = X // m_nSofNumLines_Y = Y m_eImgLandscape = ENUM_LANDSCAPE_YES; + if(m_nSofNumLines_Y > m_nSofSampsPerLine_X) m_eImgLandscape = ENUM_LANDSCAPE_NO; + strTmp = QString(" Raw Image Orientation = %1").arg(m_eImgLandscape == ENUM_LANDSCAPE_YES ? "Landscape" : "Portrait"); m_pLog->AddLine(strTmp); m_nSofNumComps_Nf = Buf(m_nPos++); // Nf, range 1..255 strTmp = QString(" Number of Img components = %1").arg(m_nSofNumComps_Nf); m_pLog->AddLine(strTmp); + if(!ValidateValue(m_nSofNumComps_Nf, 1, 255, "Number of Img components ", true, 1)) return DECMARK_ERR; uint32_t nCompIdent; - uint32_t anSofSampFact[MAX_SOF_COMP_NF]; m_nSofHorzSampFactMax_Hmax = 0; @@ -6644,13 +6720,13 @@ uint32_t CjfifDecode::DecodeMarker() // Create subsampling ratio // - Protect against division-by-zero QString strSubsampH = "?"; - QString strSubsampV = "?"; if(m_anSofHorzSampFact_Hi[nCompIdent] > 0) { strSubsampH = QString("%1").arg(m_nSofHorzSampFactMax_Hmax / m_anSofHorzSampFact_Hi[nCompIdent]); } + if(m_anSofVertSampFact_Vi[nCompIdent] > 0) { strSubsampV = QString("%1").arg(m_nSofVertSampFactMax_Vmax / m_anSofVertSampFact_Vi[nCompIdent]); @@ -6711,8 +6787,8 @@ uint32_t CjfifDecode::DecodeMarker() { strFull += " (???)"; // Unknown } - m_pLog->AddLine(strFull); + m_pLog->AddLine(strFull); } // Test for bad input, clean up if bad @@ -6746,12 +6822,10 @@ uint32_t CjfifDecode::DecodeMarker() // Store the Precision (to handle 12-bit decode) m_pImgDec->SetPrecision(m_nSofPrecision_P); - } if(!m_bStateAbort) { - // Set the component sampling factors (chroma subsampling) // FIXME: check ranging for(uint32_t nCompInd = 1; nCompInd <= m_nSofNumComps_Nf; nCompInd++) @@ -6768,7 +6842,6 @@ uint32_t CjfifDecode::DecodeMarker() m_bImgOK = true; m_bStateSofOk = true; - } if(!ExpectMarkerEnd(nPosMarkerStart, nLength)) @@ -6811,11 +6884,13 @@ uint32_t CjfifDecode::DecodeMarker() { bDoneSearch = true; } + if(m_nPos >= m_pWBuf->GetPosEof()) { bDoneSearch = true; } } + strTmp = QString(" Skipped %1 bytes").arg(m_nPos - nSkipStart); m_pLog->AddLineErr(strTmp); @@ -6826,9 +6901,11 @@ uint32_t CjfifDecode::DecodeMarker() // Assume COM field valid length (ie. >= 2) strFull = " Comment="; m_strComment = ""; + for(uint32_t ind = 0; ind < nLength - 2; ind++) { nTmpVal1 = Buf(m_nPos++); + if(isprint(nTmpVal1)) { strTmp = QString("%1").arg(nTmpVal1); @@ -6839,6 +6916,7 @@ uint32_t CjfifDecode::DecodeMarker() m_strComment += "."; } } + strFull += m_strComment; m_pLog->AddLine(strFull); @@ -6928,7 +7006,7 @@ uint32_t CjfifDecode::DecodeMarker() strTmp = QString(" Successive approximation = 0x%1").arg(m_nSosSuccApprox_A, 2, 16, QChar('0')); m_pLog->AddLine(strTmp); - if(m_pAppConfig->bOutputScanDump) + if(m_pAppConfig->scanDump()) { m_pLog->AddLine(""); m_pLog->AddLine(" Scan Data: (after bitstuff removed)"); @@ -6992,7 +7070,7 @@ uint32_t CjfifDecode::DecodeMarker() } } - if(m_pAppConfig->bOutputScanDump && (!bSkipDone)) + if(m_pAppConfig->scanDump() && (!bSkipDone)) { // Only display 20 lines of scan data if(nSkipPos > 640) @@ -7037,24 +7115,25 @@ uint32_t CjfifDecode::DecodeMarker() } } + m_pLog->AddLine(strFull); // } // --- PASS 2 --- // If the option is set, start parsing! - if(m_pAppConfig->bDecodeScanImg && m_bImgSofUnsupported) + if(m_pAppConfig->decodeImage() && m_bImgSofUnsupported) { // SOF marker was of type we don't support, so skip decoding m_pLog->AddLineWarn(" NOTE: Scan parsing doesn't support this SOF mode."); #ifndef DEBUG_YCCK } - else if(m_pAppConfig->bDecodeScanImg && (m_nSofNumComps_Nf == 4)) + else if(m_pAppConfig->decodeImage() && (m_nSofNumComps_Nf == 4)) { m_pLog->AddLineWarn(" NOTE: Scan parsing doesn't support CMYK files yet."); #endif } - else if(m_pAppConfig->bDecodeScanImg && !m_bImgSofUnsupported) + else if(m_pAppConfig->decodeImage() && !m_bImgSofUnsupported) { if(!m_bStateSofOk) { @@ -7067,7 +7146,6 @@ uint32_t CjfifDecode::DecodeMarker() else if(!m_bStateDhtOk) { m_pLog->AddLineWarn(" NOTE: Scan decode disabled as DHT not decoded."); - } else { @@ -7087,7 +7165,6 @@ uint32_t CjfifDecode::DecodeMarker() m_pImgSrcDirty = false; } } - } m_bStateSosOk = true; @@ -7113,6 +7190,7 @@ uint32_t CjfifDecode::DecodeMarker() { m_nImgRstEn = false; } + strTmp = QString(" interval = %1").arg(m_nImgRstInterval); m_pLog->AddLine(strTmp); m_nPos += 4; @@ -7180,7 +7258,7 @@ uint32_t CjfifDecode::DecodeMarker() strTmp = QString(" WARNING: Restart marker [0xFF%1] detected outside scan").arg(nCode, 2, 16, QChar('0')); m_pLog->AddLineWarn(strTmp); - if(!m_pAppConfig->bRelaxedParsing) + if(!m_pAppConfig->relaxedParsing()) { // Abort m_pLog->AddLineErr(" Stopping decode"); @@ -7214,7 +7292,7 @@ uint32_t CjfifDecode::DecodeMarker() strTmp = QString(" WARNING: Unknown marker [0xFF%1]").arg(nCode, 2, 16, QChar('0')); m_pLog->AddLineWarn(strTmp); - if(!m_pAppConfig->bRelaxedParsing) + if(!m_pAppConfig->relaxedParsing()) { // Abort m_pLog->AddLineErr(" Stopping decode"); @@ -7246,6 +7324,7 @@ uint32_t CjfifDecode::DecodeMarker() return DECMARK_OK; } +//----------------------------------------------------------------------------- // Print out a header for the current JFIF marker code void CjfifDecode::AddHeader(uint32_t nCode) { @@ -7487,6 +7566,7 @@ void CjfifDecode::AddHeader(uint32_t nCode) m_pLog->AddLine(strTmp); } +//----------------------------------------------------------------------------- // Update the status bar with a message void CjfifDecode::SetStatusText(QString strText) { @@ -7500,9 +7580,9 @@ void CjfifDecode::SetStatusText(QString strText) emit(strText, 0); QCoreApplication::processEvents(); - qDebug() << strText; } +//----------------------------------------------------------------------------- // Generate a special output form of the current image's // compression signature and other characteristics. This is only // used during development and batch import to build the MySQL repository. @@ -7549,29 +7629,34 @@ void CjfifDecode::OutputSpecial() { strFull = ""; + for(uint32_t nY = 0; nY < 8; nY++) { strFull += "'"; + for(uint32_t nX = 0; nX < 8; nX++) { // Rotate the matrix if necessary! nMatrixInd = (m_eImgLandscape != ENUM_LANDSCAPE_NO) ? (nY * 8 + nX) : (nX * 8 + nY); strTmp = QString("%1").arg(m_anImgDqtTbl[nDqtInd][nMatrixInd]); strFull += strTmp; + if(nX != 7) { strFull += ","; } } + strFull += "', "; + if(nY == 3) { m_pLog->AddLine(strFull); strFull = ""; } } - m_pLog->AddLine(strFull); + m_pLog->AddLine(strFull); } strFull = ""; @@ -7586,9 +7671,9 @@ void CjfifDecode::OutputSpecial() m_pLog->AddLine("*** DB OUTPUT END ***"); } - } +//----------------------------------------------------------------------------- // Generate the compression signatures (both unrotated and // rotated) in advance of submitting to the database. void CjfifDecode::PrepareSignature() @@ -7744,7 +7829,7 @@ void CjfifDecode::PrepareSignatureSingle(bool bRotate) // m_strHash = QCryptographicHash::hash(reinterpret_cast(pHashIn), QCryptographicHash::Md5).toHex(); } - +//----------------------------------------------------------------------------- // Generate the compression signatures for the thumbnails void CjfifDecode::PrepareSignatureThumb() { @@ -7754,6 +7839,7 @@ void CjfifDecode::PrepareSignatureThumb() PrepareSignatureThumbSingle(true); } +//----------------------------------------------------------------------------- // Prepare the image signature for later submission // NOTE: ASCII vars are used (instead of unicode) to support usage of MD5 library void CjfifDecode::PrepareSignatureThumbSingle(bool bRotate) @@ -7792,6 +7878,7 @@ void CjfifDecode::PrepareSignatureThumbSingle(bool bRotate) bDqtDefined = true; } } + if(!bDqtDefined) { m_strHashThumb = "NONE"; @@ -7893,9 +7980,9 @@ void CjfifDecode::PrepareSignatureThumbSingle(bool bRotate) .arg(sMd5.digest32[2], 8, 16, QChar('0')) .arg(sMd5.digest32[3], 8, 16, QChar('0')); } - } +//----------------------------------------------------------------------------- // Compare the image compression signature & metadata against the database. // This is the routine that is also responsible for creating an // "Image Assessment" -- ie. whether the image may have been edited or not. @@ -7943,7 +8030,7 @@ bool CjfifDecode::CompareSignature(bool bQuiet = false) strHashOut += m_strHashRot; m_pLog->AddLine(strHashOut); - strTmp = QString(" File Offset: %1 bytes").arg(m_pAppConfig->nPosStart, 1); + strTmp = QString(" File Offset: %1 bytes").arg(m_pAppConfig->startPos(), 1); m_pLog->AddLine(strTmp); // Output the CSS @@ -8266,34 +8353,36 @@ bool CjfifDecode::CompareSignature(bool bQuiet = false) // ============================================ bool bEditDefinite = false; - bool bEditLikely = false; - bool bEditNot = false; - bool bEditNotUnknownSw = false; if(bCurXps) { bEditDefinite = true; } + if(!bCurXmm) { bEditDefinite = true; } + if(bCurXextrasw) { bEditDefinite = true; } + if(bCurXcomsw) { bEditDefinite = true; } + if(bSrchXsw) { // Software field matches known software string bEditDefinite = true; } + if(m_pDbSigs->LookupExcMmIsEdit(m_strImgExifMake, m_strImgExifModel)) { // Make/Model is in exception list of ones that mark known software @@ -8324,7 +8413,6 @@ bool CjfifDecode::CompareSignature(bool bQuiet = false) // Filter down remaining scenarios if(!bEditDefinite && !bEditLikely) { - if(bSrchXmmUsig) { // DB cam signature matches DQT & make/model @@ -8363,7 +8451,6 @@ bool CjfifDecode::CompareSignature(bool bQuiet = false) // but no compression signatures in the database match this // particular make/model. Therefore, result is UNSURE. } - } // Now make final assessment call @@ -8400,13 +8487,15 @@ bool CjfifDecode::CompareSignature(bool bQuiet = false) } // If the file offset is non-zero, then don't ask for submit or show assessment - if(m_pAppConfig->nPosStart != 0) + if(m_pAppConfig->startPos() != 0) { m_pLog->AddLine(" ASSESSMENT not done as file offset non-zero"); + if(bQuiet) { m_pLog->Enable(); } + return false; } @@ -8443,16 +8532,17 @@ bool CjfifDecode::CompareSignature(bool bQuiet = false) { m_pLog->AddLineErr(" ASSESSMENT: *** Failed to complete ***"); } + m_pLog->AddLine(""); // Determine if user should add entry to DB bool bDbReqAdd = false; // Ask user to add - bool bDbReqAddAuto = false; // Automatically add (in batch operation) // TODO: This section should be rewritten to reduce complexity m_eDbReqSuggest = DB_ADD_SUGGEST_UNSET; + if(m_eImgEdited == EDITED_NO) { bDbReqAdd = false; @@ -8538,9 +8628,9 @@ bool CjfifDecode::CompareSignature(bool bQuiet = false) // Return a value that indicates whether or not we should add this // entry to the database return bDbReqAddAuto; - } +//----------------------------------------------------------------------------- // Build the image data string that will be sent to the database repository // This data string contains the compression siganture and a few special // fields such as image dimensions, etc. @@ -8552,7 +8642,6 @@ void CjfifDecode::PrepareSendSubmit(QString strQual, teSource eUserSource, QStri { // Generate the DQT arrays suitable for posting QString strTmp1; - QString asDqt[4]; uint32_t nMatrixInd; @@ -8573,12 +8662,14 @@ void CjfifDecode::PrepareSendSubmit(QString strQual, teSource eUserSource, QStri // Not a big deal if we get it wrong as we still add // both pre- and post-rotated sigs. nMatrixInd = (m_eImgLandscape != ENUM_LANDSCAPE_NO) ? nInd : glb_anQuantRotate[nInd]; + if((nInd % 8 == 0) && (nInd != 0)) { asDqt[nSet].append("!"); } asDqt[nSet].append(QString("%1").arg(m_anImgDqtTbl[nSet][nMatrixInd])); + if(nInd % 8 != 7) { asDqt[nSet].append(","); @@ -8616,6 +8707,7 @@ void CjfifDecode::PrepareSendSubmit(QString strQual, teSource eUserSource, QStri strSig0 = m_strHashRot; strSig1 = m_strHash; } + if(m_strHashThumb <= m_strHashThumbRot) { strSigThm0 = m_strHashThumb; @@ -8628,19 +8720,20 @@ void CjfifDecode::PrepareSendSubmit(QString strQual, teSource eUserSource, QStri } SendSubmit(m_strImgExifMake, m_strImgExifModel, strQual, asDqt[0], asDqt[1], asDqt[2], asDqt[3], m_strImgQuantCss, - strSig0, strSig1, strSigThm0, strSigThm1, (float) m_adImgDqtQual[0], (float) m_adImgDqtQual[1], nOrigW, nOrigH, + strSig0, strSig1, strSigThm0, strSigThm1, static_cast(m_adImgDqtQual[0]), static_cast(m_adImgDqtQual[1]), nOrigW, nOrigH, m_strSoftware, m_strComment, eMaker, eUserSource, strUserSoftware, m_strImgExtras, strUserNotes, m_eImgLandscape, nOrigThumbW, nOrigThumbH); } +//----------------------------------------------------------------------------- // Send the compression signature string to the local database file // in addition to the web repository if the user has enabled it. void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString strQual, QString strDqt0, QString strDqt1, QString strDqt2, QString strDqt3, QString strCss, QString strSig, QString strSigRot, QString strSigThumb, - QString strSigThumbRot, float fQFact0, float fQFact1, uint32_t nImgW, uint32_t nImgH, + QString strSigThumbRot, double fQFact0, double fQFact1, uint32_t nImgW, uint32_t nImgH, QString strExifSoftware, QString strComment, teMaker eMaker, teSource eUserSource, QString strUserSoftware, QString strExtra, QString strUserNotes, uint32_t nExifLandscape, uint32_t nThumbX, uint32_t nThumbY) @@ -8658,7 +8751,7 @@ void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString #ifndef BATCH_DO if(m_bSigExactInDB) { - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) msgBox.setText("Compression signature already in database"); } else @@ -8666,7 +8759,7 @@ void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString // Now append it to the local database and resave //@@ m_pDbSigs->DatabaseExtraAdd(strExifMake, strExifModel, strQual, strSig, strSigRot, strCss, eUserSource, strUserSoftware); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText("Added Compression signature to database"); } @@ -8675,7 +8768,7 @@ void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString // Is automatic internet update enabled? //@@ if(!m_pAppConfig->bDbSubmitNet) - if(!m_pAppConfig->bDbSubmitNet) + if(!m_pAppConfig->submitDbNet()) { return; } @@ -8779,7 +8872,7 @@ void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString nFormDataLen = strFormData.length(); #ifdef DEBUG_SIG - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strFormDataPre); msgBox.setText(strFormData); @@ -8796,7 +8889,7 @@ void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString hINet = InternetOpen("JPEGsnoop/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ; if ( !hINet ) { - if (m_pAppConfig->bInteractive) + if (m_pAppConfig->interactive()) msgBox.setText("InternetOpen Failed"); return; } @@ -8888,7 +8981,7 @@ void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString TRACE("Submit Failed! - %s", szErr); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) msgBox.setText(szErr); pEx->Delete(); @@ -8907,6 +9000,7 @@ void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString } } +//----------------------------------------------------------------------------- // Parse the embedded JPEG thumbnail. This routine is a much-reduced // version of the main JFIF parser, in that it focuses primarily on the // DQT tables. @@ -9035,6 +9129,7 @@ void CjfifDecode::DecodeEmbeddedThumb() strTmp = QString(" Precision=%1").arg(strPrecision); m_pLog->AddLine(strTmp); strTmp = QString(" Destination ID=%1").arg(nDqtQuantDestId_Tq); + // NOTE: The mapping between destination IDs and the actual // usage is defined in the SOF marker which is often later. // In nearly all images, the following is true. However, I have @@ -9090,11 +9185,9 @@ void CjfifDecode::DecodeEmbeddedThumb() bRet = m_pImgDec->SetDqtEntry(nDqtQuantDestId_Tq, nY * 8 + nX, glb_anUnZigZag[nY * 8 + nX], m_anImgDqtTbl[nDqtQuantDestId_Tq][nY * 8 + nX]); DecodeErrCheck(bRet); - } m_pLog->AddLine(strFull); - } } @@ -9202,12 +9295,12 @@ void CjfifDecode::DecodeEmbeddedThumb() m_strHashThumb = "ERR: Len=0"; m_strHashThumbRot = "ERR: Len=0"; } - } // if JPEG compressed m_nPos = nPosSaved; } +//----------------------------------------------------------------------------- // Lookup the EXIF marker name from the code value bool CjfifDecode::GetMarkerName(uint32_t nCode, QString & markerStr) { @@ -9245,6 +9338,7 @@ bool CjfifDecode::GetMarkerName(uint32_t nCode, QString & markerStr) return true; } +//----------------------------------------------------------------------------- // Determine if the file is an AVI MJPEG. // If so, parse the headers. // TODO: Expand this function to use sub-functions for each block type @@ -9440,11 +9534,11 @@ bool CjfifDecode::DecodeAvi() strTmp = QString(" -[FourCC Codec] = [%1]").arg(fccHandler); m_pLog->AddLine(strTmp); - float fSampleRate = 0; + double fSampleRate = 0; if(dwScale != 0) { - fSampleRate = (float) dwRate / (float) dwScale; + fSampleRate = static_cast(dwRate) / static_cast(dwScale); } strTmp = QString(" -[Sample Rate] = [%.2f]").arg(fSampleRate); @@ -9651,28 +9745,32 @@ bool CjfifDecode::DecodeAvi() // Reset file position m_nPos = nPosSaved; + if(DEBUG_EN) + m_pAppConfig->DebugLogAdd("CfifDecode::DecodeAvi() End"); + return m_bAviMjpeg; } +//----------------------------------------------------------------------------- // This is the primary JFIF parsing routine. // The main loop steps through all of the JFIF markers and calls // DecodeMarker() each time until we reach the end of file or an error. // Finally, we invoke the compression signature search function. // -// Processing starts at the file offset m_pAppConfig->nPosStart +// Processing starts at the file offset m_pAppConfig->startPos() // // INPUT: // - inFile = Input file pointer // // PRE: -// - m_pAppConfig->nPosStart = Starting file offset for decode +// - m_pAppConfig->startPos() = Starting file offset for decode // -void CjfifDecode::ProcessFile(QFile * inFile) +void CjfifDecode::ProcessFile(QFile *inFile) { QString strTmp; if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("CfifDecode::ProcessFile() Checkpoint 1"); + m_pAppConfig->DebugLogAdd("CfifDecode::ProcessFile() Begin"); // Reset the JFIF decoder state as we may be redoing another file Reset(); @@ -9710,7 +9808,7 @@ void CjfifDecode::ProcessFile(QFile * inFile) strTmp = "File too large. Skipping."; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) msgBox.setText(strTmp); return; @@ -9719,13 +9817,12 @@ void CjfifDecode::ProcessFile(QFile * inFile) if(DEBUG_EN) m_pAppConfig->DebugLogAdd("CfifDecode::ProcessFile() Checkpoint 3"); - qDebug() << m_pAppConfig; m_nPosFileEnd = static_cast < uint32_t >(nPosFileEnd); uint32_t nStartPos; - nStartPos = m_pAppConfig->nPosStart; + nStartPos = m_pAppConfig->startPos(); m_nPos = nStartPos; m_nPosEmbedStart = nStartPos; // Save the embedded file start position @@ -9735,20 +9832,17 @@ void CjfifDecode::ProcessFile(QFile * inFile) m_pLog->AddLine(QString("Start Offset: 0x%1").arg(nStartPos, 8, 16, QChar('0'))); // ---------------------------------------------------------------- - // Test for AVI file // - Detect header // - start from beginning of file DecodeAvi(); // TODO: Should we skip decode of file if not MJPEG? - // ---------------------------------------------------------------- // Test for PSD file // - Detect header // - FIXME: start from current offset? uint32_t nWidth = 0; - uint32_t nHeight = 0; #ifdef PS_IMG_DEC_EN @@ -9756,9 +9850,10 @@ void CjfifDecode::ProcessFile(QFile * inFile) // the current DIB. After decoding, flag the DIB as ready for display. // Attempt decode as PSD - bool bDecPsdOk = false; + bool bDecPsdOk; //@@ bDecPsdOk = m_pPsDec->DecodePsd(nStartPos, &m_pImgDec->m_pDibTemp, nWidth, nHeight); + bDecPsdOk = false; if(bDecPsdOk) { @@ -9802,9 +9897,9 @@ void CjfifDecode::ProcessFile(QFile * inFile) // Adjust start of JPEG decoding if we are currently without an offset if(nStartPos == 0) { - m_pAppConfig->nPosStart = nPosJpeg; + m_pAppConfig->startPos() = nPosJpeg; - nStartPos = m_pAppConfig->nPosStart; + nStartPos = m_pAppConfig->startPos(); m_nPos = nStartPos; m_nPosEmbedStart = nStartPos; // Save the embedded file start position @@ -9820,9 +9915,9 @@ void CjfifDecode::ProcessFile(QFile * inFile) // Decode as JPEG JFIF file // If we are in a non-zero offset, add this to extras - if(m_pAppConfig->nPosStart != 0) + if(m_pAppConfig->startPos() != 0) { - strTmp = QString("[Offset]=[%1],").arg(m_pAppConfig->nPosStart); + strTmp = QString("[Offset]=[%1],").arg(m_pAppConfig->startPos()); m_strImgExtras += strTmp; } @@ -9883,9 +9978,7 @@ void CjfifDecode::ProcessFile(QFile * inFile) // NOTE: The following assumes m_anSofHorzSampFact_Hi and m_anSofVertSampFact_Vi // are non-zero as otherwise we'll have a divide-by-0 exception. uint32_t nCompIdent = m_anSofQuantCompId[SCAN_COMP_CB]; - uint32_t nCssFactH = m_nSofHorzSampFactMax_Hmax / m_anSofHorzSampFact_Hi[nCompIdent]; - uint32_t nCssFactV = m_nSofVertSampFactMax_Vmax / m_anSofVertSampFact_Vi[nCompIdent]; if(m_eImgLandscape != ENUM_LANDSCAPE_NO) @@ -9910,7 +10003,7 @@ void CjfifDecode::ProcessFile(QFile * inFile) PrepareSignature(); // Compare compression signature - if(m_pAppConfig->bSigSearch) + if(m_pAppConfig->searchSig()) { // In the case of lossless files, there won't be any DQT and // hence no compression signatures to compare. Therefore, skip this process. @@ -9951,6 +10044,7 @@ void CjfifDecode::ProcessFile(QFile * inFile) } +//----------------------------------------------------------------------------- // Determine if the analyzed file is in a state ready for image // extraction. Confirms that the important JFIF markers have been // detected in the previous analysis. @@ -10026,8 +10120,8 @@ bool CjfifDecode::ExportJpegPrepare(QString strFileIn, bool bForceSoi, bool bFor // We're missing the SOI but the user has requested // that we force an SOI, so let's fix things up } - } + if(!m_bStateSos) { strTmp = QString(" ERROR: Missing marker: %1").arg("SOS"); @@ -10041,11 +10135,13 @@ bool CjfifDecode::ExportJpegPrepare(QString strFileIn, bool bForceSoi, bool bFor bExtractWarn = true; strMissing += "DQT "; } + if(!m_bStateDht) { bExtractWarn = true; strMissing += "DHT "; } + if(!m_bStateSof) { bExtractWarn = true; @@ -10063,7 +10159,7 @@ bool CjfifDecode::ExportJpegPrepare(QString strFileIn, bool bForceSoi, bool bFor { strTmp = QString("ERROR: Invalid SOI-EOI order. Export aborted."); m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) msgBox.setText(strTmp); return false; } @@ -10073,6 +10169,7 @@ bool CjfifDecode::ExportJpegPrepare(QString strFileIn, bool bForceSoi, bool bFor #define EXPORT_BUF_SIZE 131072 +//----------------------------------------------------------------------------- // Export the embedded JPEG image at the current position in the file (with overlays) // (may be the primary image or even an embedded thumbnail). bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, @@ -10089,18 +10186,21 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, { strTmp = QString("ERROR: Can't overwrite source file. Aborting export."); m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + + if(m_pAppConfig->interactive()) msgBox.setText(strTmp); return false; } Q_ASSERT(strFileIn != ""); + if(strFileIn == "") { strTmp = QString("ERROR: Export but source filename empty"); m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + + if(m_pAppConfig->interactive()) msgBox.setText(strTmp); return false; @@ -10119,7 +10219,7 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, strError = QString("ERROR: Couldn't open file for write [%1]: [%2]").arg(strFileOut).arg(pFileOutput->errorString()); m_pLog->AddLineErr(strError); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strError); msgBox.exec(); @@ -10135,7 +10235,8 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, { strTmp = QString("ERROR: Source file length error. Please Reprocess first."); m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + + if(m_pAppConfig->interactive()) msgBox.setText(strTmp); if(pFileOutput) @@ -10144,6 +10245,7 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, pFileOutput = NULL; } + return false; } @@ -10165,7 +10267,6 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, if(pFileOutput) { delete pFileOutput; - pFileOutput = NULL; } @@ -10229,6 +10330,7 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, { nCopyLeft = EXPORT_BUF_SIZE; } + for(uint32_t ind1 = 0; ind1 < nCopyLeft; ind1++) { pBuf[ind1] = Buf(ind + ind1, !bOverlayEn); @@ -10262,7 +10364,6 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, if(pFileOutput) { delete pFileOutput; - pFileOutput = NULL; } @@ -10273,6 +10374,7 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, return true; } +//----------------------------------------------------------------------------- // Export a subset of the file with no overlays or mods bool CjfifDecode::ExportJpegDoRange(QString strFileIn, QString strFileOut, uint32_t nStart, uint32_t nEnd) { @@ -10287,7 +10389,7 @@ bool CjfifDecode::ExportJpegDoRange(QString strFileIn, QString strFileOut, uint3 { strTmp = "ERROR: Can't overwrite source file. Aborting export."; m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) msgBox.setText(strTmp); return false; @@ -10299,7 +10401,7 @@ bool CjfifDecode::ExportJpegDoRange(QString strFileIn, QString strFileOut, uint3 { strTmp = QString("ERROR: Export but source filename empty"); m_pLog->AddLineErr(strTmp); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) msgBox.setText(strTmp); return false; @@ -10314,7 +10416,7 @@ bool CjfifDecode::ExportJpegDoRange(QString strFileIn, QString strFileOut, uint3 strError = QString("ERROR: Couldn't open file for write [%1]: [%2]").arg(strFileOut).arg(pFileOutput->errorString()); m_pLog->AddLineErr(strError); - if(m_pAppConfig->bInteractive) + if(m_pAppConfig->interactive()) { msgBox.setText(strError); msgBox.exec(); @@ -10339,9 +10441,9 @@ bool CjfifDecode::ExportJpegDoRange(QString strFileIn, QString strFileOut, uint3 if(pFileOutput) { delete pFileOutput; - pFileOutput = NULL; } + return false; } @@ -10382,7 +10484,6 @@ bool CjfifDecode::ExportJpegDoRange(QString strFileIn, QString strFileOut, uint3 if(pFileOutput) { delete pFileOutput; - pFileOutput = NULL; } diff --git a/source/JfifDecode.h b/source/JfifDecode.h index 8fdb71b..6e998a9 100644 --- a/source/JfifDecode.h +++ b/source/JfifDecode.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -31,15 +31,15 @@ #include #include -#include "DocLog.h" #include "ImgDecode.h" #include "DecodePs.h" #include "DecodeDicom.h" #include "WindowBuf.h" -#include "snoop.h" -#include "SnoopConfig.h" +//#include "snoop.h" -#include "DbSigs.h" +class CDocLog; +class CSnoopConfig; +class CDbSigs; // Disable DICOM support until fully tested //#define SUPPORT_DICOM @@ -139,7 +139,7 @@ class CjfifDecode : public QObject // Constructor & Initialization public: - CjfifDecode(CDocLog * pLog, CwindowBuf * pWBuf, CimgDecode * pImgDec); + CjfifDecode(CDocLog * pLog, CDbSigs *pDbSigs, CwindowBuf * pWBuf, CimgDecode * pImgDec, CSnoopConfig *pAppConfig, QObject *_parent = 0); ~CjfifDecode(); void Reset(); @@ -151,7 +151,6 @@ class CjfifDecode : public QObject // Public accesssor & mutator functions void GetAviMode(bool & bIsAvi, bool & bIsMjpeg); void SetAviMode(bool bIsAvi, bool bIsMjpeg); - void ImgSrcChanged(); uint32_t GetPosEmbedStart(); uint32_t GetPosEmbedEnd(); void GetDecodeSummary(QString & strHash, QString & strHashRot, QString & strImgExifMake, QString & strImgExifModel, @@ -177,6 +176,9 @@ class CjfifDecode : public QObject signals: void updateStatus(QString statusMsg, int); +public slots: + void ImgSrcChanged(); + private: CjfifDecode &operator = (const CjfifDecode&); CjfifDecode(CjfifDecode&); @@ -190,7 +192,7 @@ class CjfifDecode : public QObject QString strDqt0, QString strDqt1, QString strDqt2, QString strDqt3, QString strCss, QString strSig, QString strSigRot, QString strSigThumb, - QString strSigThumbRot, float fQFact0, float fQFact1, uint32_t nImgW, uint32_t nImgH, + QString strSigThumbRot, double fQFact0, double fQFact1, uint32_t nImgW, uint32_t nImgH, QString strExifSoftware, QString strComment, teMaker eMaker, teSource eUserSource, QString strUserSoftware, QString strExtra, QString strUserNotes, uint32_t nExifLandscape, uint32_t nThumbX, uint32_t nThumbY); @@ -238,10 +240,10 @@ class CjfifDecode : public QObject void GenLookupHuffMask(); // Field parsing - bool DecodeValRational(uint32_t nPos, float &nVal); + bool DecodeValRational(uint32_t nPos, double &nVal); QString DecodeValFraction(uint32_t nPos); bool DecodeValGPS(uint32_t nPos, QString & strCoord); - bool PrintValGPS(uint32_t nCount, float fCoord1, float fCoord2, float fCoord3, QString & strCoord); + bool PrintValGPS(uint32_t nCount, double fCoord1, double fCoord2, double fCoord3, QString & strCoord); QString DecodeIccDateTime(uint32_t anVal[3]); QString LookupExifTag(QString strSect, uint32_t nTag, bool & bUnknown); CStr2 LookupMakerCanonTag(uint32_t nMainTag, uint32_t nSubTag, uint32_t nVal); @@ -253,21 +255,22 @@ class CjfifDecode : public QObject // Class variables // -------------------------------------- - // Configuration - // CSnoopConfig * m_pAppConfig; - bool m_bVerbose; - bool m_bOutputDB; - bool m_bBufFakeDHT; // Flag to redirect DHT read to AVI DHT over Buffer content - - // General classes required for decoding + // Pointers + CDocLog *m_pLog; + CDbSigs *m_pDbSigs; CwindowBuf *m_pWBuf; CimgDecode *m_pImgDec; + CSnoopConfig * m_pAppConfig; CDecodePs *m_pPsDec; CDecodeDicom *m_pDecDicom; + bool m_bVerbose; + bool m_bOutputDB; + bool m_bBufFakeDHT; // Flag to redirect DHT read to AVI DHT over Buffer content + + // UI elements & log QMessageBox msgBox; - CDocLog *m_pLog; QStatusBar *m_pStatBar; // Link to status bar // Constants @@ -293,8 +296,8 @@ class CjfifDecode : public QObject // Decoder state char m_acApp0Identifier[MAX_IDENTIFIER]; // APP0 type: JFIF, AVI1, etc. - float m_afStdQuantLumCompare[64]; - float m_afStdQuantChrCompare[64]; + double m_afStdQuantLumCompare[64]; + double m_afStdQuantChrCompare[64]; uint32_t m_anMaskLookup[32]; diff --git a/source/LookupDlg.cpp b/source/LookupDlg.cpp deleted file mode 100644 index a31c9f0..0000000 --- a/source/LookupDlg.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// LookupDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "jpegsnoop.h" -#include "LookupDlg.h" -#include ".\lookupdlg.h" - - -// CLookupDlg dialog - - -IMPLEMENT_DYNAMIC(CLookupDlg, CDialog) -CLookupDlg::CLookupDlg(CWnd* pParent /*=NULL*/) - : CDialog(CLookupDlg::IDD, pParent) - , m_nPixX(0) - , m_nPixY(0) - , m_strOffset(_T("")) - , m_strRngX(_T("")) - , m_strRngY(_T("")) - , m_nSizeX(0) - , m_nSizeY(0) -{ - // Initialize callback functions to NULL - m_pCbLookup = NULL; - m_pClassCbLookup = NULL; -} - -CLookupDlg::CLookupDlg(CWnd* pParent, unsigned nSizeX, unsigned nSizeY) - : CDialog(CLookupDlg::IDD, pParent) - , m_nPixX(0) - , m_nPixY(0) - , m_strOffset(_T("Not Calculated")) - , m_strRngX(_T("")) - , m_strRngY(_T("")) - , m_nSizeX(nSizeX) - , m_nSizeY(nSizeY) -{ - m_strRngX.Format(_T("(0..%u)"),m_nSizeX-1); - m_strRngY.Format(_T("(0..%u)"),m_nSizeY-1); - - // Initialize callback functions to NULL - m_pCbLookup = NULL; - m_pClassCbLookup = NULL; -} - -CLookupDlg::~CLookupDlg() -{ -} - -void CLookupDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Text(pDX, IDC_X, m_nPixX); - DDX_Text(pDX, IDC_Y, m_nPixY); - DDX_Text(pDX, IDC_OFFSET, m_strOffset); - DDX_Text(pDX, IDC_RNGX, m_strRngX); - DDX_Text(pDX, IDC_RNGY, m_strRngY); -} - - -BEGIN_MESSAGE_MAP(CLookupDlg, CDialog) - ON_BN_CLICKED(IDC_BTN_CALC, OnBnClickedBtnCalc) -END_MESSAGE_MAP() - - -// Set callback function for Buf() -void CLookupDlg::SetCbLookup(void* pClassCbLookup, - void (*pCbLookup)(void* pClassCbLookup, unsigned nX,unsigned nY,unsigned &nByte,unsigned &nBit) - ) -{ - // Save pointer to class and function - m_pClassCbLookup = pClassCbLookup; - m_pCbLookup = pCbLookup; -} - -// CLookupDlg message handlers - -void CLookupDlg::OnBnClickedBtnCalc() -{ - ASSERT(m_pCbLookup); - unsigned nByte = 0; - unsigned nBit = 0; - UpdateData(); - - if (m_nPixX > m_nSizeX-1) { - AfxMessageBox(_T("Pixel X coord out of range")); - } else if (m_nPixY > m_nSizeY-1) { - AfxMessageBox(_T("Pixel Y coord out of range")); - } else { - if (m_pCbLookup) { - // Use callback function for lookup - m_pCbLookup(m_pClassCbLookup,m_nPixX,m_nPixY,nByte,nBit); - m_strOffset.Format(_T("0x%08X : %u"),nByte,nBit); - UpdateData(FALSE); - } - } -} - diff --git a/source/LookupDlg.h b/source/LookupDlg.h deleted file mode 100644 index 4ce4520..0000000 --- a/source/LookupDlg.h +++ /dev/null @@ -1,70 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box used to look up a file offset from a pixel coordinate -// -// ========================================================================== - - -#pragma once - -// CLookupDlg dialog - -class CLookupDlg : public CDialog -{ - DECLARE_DYNAMIC(CLookupDlg) - -public: - CLookupDlg(CWnd* pParent = NULL); // standard constructor - CLookupDlg(CWnd* pParent, unsigned nSizeX, unsigned nSizeY); - virtual ~CLookupDlg(); - -// Dialog Data - enum { IDD = IDD_LOOKUP }; - - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -private: - afx_msg void OnBnClickedBtnCalc(); - -public: - // Callback function for LookupFilePosPix() - void SetCbLookup(void* pClassCbLookup, - void (*pCbLookup)(void* pClassCbBuf, unsigned nX,unsigned nY,unsigned &nByte,unsigned &nBit)); -private: - // References to callback function for LookupFilePosPix() - void* m_pClassCbLookup; - void (*m_pCbLookup)(void* pClassCbLookup,unsigned nX,unsigned nY,unsigned &nByte,unsigned &nBit); - -private: - UINT m_nPixX; - UINT m_nPixY; - CString m_strOffset; - UINT m_nTestVal; - - UINT m_nSizeX; - UINT m_nSizeY; - - CString m_strRngX; - CString m_strRngY; -}; diff --git a/source/MainFrm.cpp b/source/MainFrm.cpp deleted file mode 100644 index 203fa3e..0000000 --- a/source/MainFrm.cpp +++ /dev/null @@ -1,229 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// MainFrm.cpp : implementation of the CMainFrame class -// - -#include "stdafx.h" -#include "JPEGsnoop.h" - -#include "MainFrm.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - - -// CMainFrame - -IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) - -BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) - ON_WM_CREATE() -END_MESSAGE_MAP() - -static UINT indicators[] = -{ - ID_SEPARATOR, // status line indicator - ID_INDICATOR_MCU, - ID_INDICATOR_FILEPOS, - ID_INDICATOR_YCC, // Added YCC Value - //ID_INDICATOR_CAPS, - //ID_INDICATOR_NUM, - //ID_INDICATOR_SCRL, -}; - - -// CMainFrame construction/destruction - -CMainFrame::CMainFrame() -{ - // TODO: add member initialization code here -} - -CMainFrame::~CMainFrame() -{ -} - - -int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) -{ - if (CFrameWnd::OnCreate(lpCreateStruct) == -1) - return -1; - - if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP - | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || - !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) - { - TRACE0("Failed to create toolbar\n"); - return -1; // fail to create - } - - if (!m_wndStatusBar.Create(this) || - !m_wndStatusBar.SetIndicators(indicators, - sizeof(indicators)/sizeof(UINT))) - { - TRACE0("Failed to create status bar\n"); - return -1; // fail to create - } - // TODO: Delete these three lines if you don't want the toolbar to be dockable - m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); - EnableDocking(CBRS_ALIGN_ANY); - DockControlBar(&m_wndToolBar); - - - - return 0; -} - -BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) -{ - if( !CFrameWnd::PreCreateWindow(cs) ) - return FALSE; - // TODO: Modify the Window class or styles here by modifying - // the CREATESTRUCT cs - - return TRUE; -} - - - -// FindMenuItem() will find a menu item string from the specified -// popup menu and returns its position (0-based) in the specified -// popup menu. It returns -1 if no such menu item string is found. -int CMainFrame::FindMenuItem(CMenu* Menu, LPCTSTR MenuString) -{ - ASSERT(Menu); - ASSERT(::IsMenu(Menu->GetSafeHmenu())); - - int count = Menu->GetMenuItemCount(); - for (int i = 0; i < count; i++) - { - CString str; - if (Menu->GetMenuString(i, str, MF_BYPOSITION) && - (_tcscmp(str, MenuString) == 0)) - return i; - } - - return -1; -} - - -// CMainFrame diagnostics - -#ifdef _DEBUG -void CMainFrame::AssertValid() const -{ - CFrameWnd::AssertValid(); -} - -void CMainFrame::Dump(CDumpContext& dc) const -{ - CFrameWnd::Dump(dc); -} - -#endif //_DEBUG - - -// CMainFrame message handlers - -//CAL! Following code was added to support split windows -BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) -{ - lpcs; // Unreferenced param - - //calculate client size - CRect cr; - GetClientRect( &cr); - - if ( !m_mainSplitter.CreateStatic( this, 2, 1 ) ) - { - MessageBox( _T("Error setting up splitter frames!"), - _T("Init Error!"), MB_OK | MB_ICONERROR ); - return FALSE; - } - - if ( !m_mainSplitter.CreateView( 0, 0, - RUNTIME_CLASS(CJPEGsnoopView), - CSize(cr.Width(), cr.Height()*3/4), pContext ) ) - { - MessageBox( _T("Error setting up splitter frames!"), - _T("Init Error!"), MB_OK | MB_ICONERROR ); - return FALSE; - } - - if ( !m_mainSplitter.CreateView( 1, 0, - RUNTIME_CLASS(CJPEGsnoopViewImg), - CSize(cr.Width(), cr.Height()*1/4), pContext ) ) - { - MessageBox( _T("Error setting up splitter frames!"), - _T("Init Error!"), MB_OK | MB_ICONERROR ); - return FALSE; - } - - m_bInitSplitter = TRUE; - - - //return TRUE instead of the parent method since that would - //not show our window - //return CFrameWnd::OnCreateClient(lpcs, pContext); - return TRUE; -} - - - -void CMainFrame::OnSize(UINT nType, int cx, int cy) -{ - CFrameWnd::OnSize(nType, cx, cy); - - // TODO: Add your message handler code here - - CRect cr; - GetWindowRect(&cr); - - if ( m_bInitSplitter && nType != SIZE_MINIMIZED ) - { - - /* - // FIXME: - // The following was intended to allow the current ratio / position - // of the splitter windows to be remembered, so that the proportion - // after resizing was the same. Unfortunately, it seems to really - // mess up the display. Stepping into the RecalcLayout() function - // reveals that perhaps the # rows or cols gets messed up. Perhaps - // it is due to bad handling of the 2nd & 3rd params to GetRowInfo()? - - int nHOld0,nHOld1,nHOldTotal,nMinOld; - m_mainSplitter.GetRowInfo(0,nHOld0,nMinOld); - m_mainSplitter.GetRowInfo(1,nHOld1,nMinOld); - nHOldTotal = nHOld0 + nHOld1; - - m_mainSplitter.SetColumnInfo( 0, cx, 0); - m_mainSplitter.SetRowInfo( 0, cr.Height() * nHOld0 / nHOldTotal, 50); - m_mainSplitter.SetRowInfo( 1, cr.Height() * nHOld1 / nHOldTotal, 50); - */ - m_mainSplitter.SetColumnInfo( 0, cx, 0); - m_mainSplitter.SetRowInfo( 0, cr.Height() * 2/3, 50); - m_mainSplitter.SetRowInfo( 1, cr.Height() * 1/3, 50); - - m_mainSplitter.RecalcLayout(); - } - -} - -// *********** END ************ diff --git a/source/MainFrm.h b/source/MainFrm.h deleted file mode 100644 index c1db752..0000000 --- a/source/MainFrm.h +++ /dev/null @@ -1,84 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - JPEGsnoop main frame window -// - Splitter window -// - Status bar -// -// ========================================================================== - - -// MainFrm.h : interface of the CMainFrame class -// - - -#pragma once - -#include "JPEGsnoopView.h" -#include "JPEGsnoopViewImg.h" - - -class CMainFrame : public CFrameWnd -{ - -protected: // create from serialization only - CMainFrame(); - DECLARE_DYNCREATE(CMainFrame) - -// Attributes -public: - -// Operations -public: - -// Overrides -public: - virtual BOOL PreCreateWindow(CREATESTRUCT& cs); - -// Implementation -public: - virtual ~CMainFrame(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - -private: - int FindMenuItem(CMenu* Menu, LPCTSTR MenuString); -protected: - // Generated message map functions - afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); - virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); - DECLARE_MESSAGE_MAP() -private: - afx_msg void OnSize(UINT nType, int cx, int cy); - -private: - // Splitter - CSplitterWnd m_mainSplitter; - BOOL m_bInitSplitter; - -protected: // control bar embedded members - CStatusBar m_wndStatusBar; - CToolBar m_wndToolBar; - -}; - - diff --git a/source/Md5.cpp b/source/Md5.cpp index 91d07ba..a2b789c 100644 --- a/source/Md5.cpp +++ b/source/Md5.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/Md5.h b/source/Md5.h index c92abfa..452a567 100644 --- a/source/Md5.h +++ b/source/Md5.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/ModelessDlg.cpp b/source/ModelessDlg.cpp deleted file mode 100644 index 2a99abd..0000000 --- a/source/ModelessDlg.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ModelessDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "ModelessDlg.h" -#include ".\modelessdlg.h" - - -// CModelessDlg dialog - -IMPLEMENT_DYNAMIC(CModelessDlg, CDialog) -CModelessDlg::CModelessDlg(CWnd* pParent /*=NULL*/) - : CDialog(CModelessDlg::IDD, pParent) -{ -} - -CModelessDlg::~CModelessDlg() -{ -} - -void CModelessDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); -} - - -BEGIN_MESSAGE_MAP(CModelessDlg, CDialog) -END_MESSAGE_MAP() - - -// CModelessDlg message handlers - - -void CModelessDlg::OnCancel() -{ - // NOTE: The following OnCancel() routine is apparently not supposed to be - // called for a modeless dialog. Instead, we are supposed to call - // DestroyWindow(). - - //CDialog::OnCancel(); - DestroyWindow(); -} diff --git a/source/ModelessDlg.h b/source/ModelessDlg.h deleted file mode 100644 index 1578977..0000000 --- a/source/ModelessDlg.h +++ /dev/null @@ -1,56 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box displayed while checking for updates -// - Modeless dialog box -// -// ========================================================================== - - -#pragma once - - -// CModelessDlg dialog - -class CModelessDlg : public CDialog -{ - DECLARE_DYNAMIC(CModelessDlg) - -public: - CModelessDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CModelessDlg(); - -// Dialog Data - enum { IDD = IDD_MODELESSDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -public: - BOOL Create(UINT nID, CWnd* pWnd) - { return CDialog::Create(nID,pWnd); } - CString strMsg; - - virtual void OnCancel(); - -protected: - virtual void PostNcDestroy() {delete this;} -}; diff --git a/source/NoteDlg.cpp b/source/NoteDlg.cpp deleted file mode 100644 index 45e9be5..0000000 --- a/source/NoteDlg.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// NoteDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "NoteDlg.h" - - -// CNoteDlg dialog - -IMPLEMENT_DYNAMIC(CNoteDlg, CDialog) -CNoteDlg::CNoteDlg(CWnd* pParent /*=NULL*/) - : CDialog(CNoteDlg::IDD, pParent) - , strMsg(_T("")) - , bCoachOff(TRUE) -{ -} - -CNoteDlg::~CNoteDlg() -{ -} - -void CNoteDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Text(pDX, IDC_MSG, strMsg); - DDX_Check(pDX, IDC_COACH_OFF, bCoachOff); -} - - -BEGIN_MESSAGE_MAP(CNoteDlg, CDialog) -END_MESSAGE_MAP() - - -// CNoteDlg message handlers diff --git a/source/NoteDlg.h b/source/NoteDlg.h deleted file mode 100644 index b6bd499..0000000 --- a/source/NoteDlg.h +++ /dev/null @@ -1,51 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box showing a warning note -// - Provide a means of disabling the specific coach message -// -// ========================================================================== - - -#pragma once - - -// CNoteDlg dialog - -class CNoteDlg : public CDialog -{ - DECLARE_DYNAMIC(CNoteDlg) - -public: - CNoteDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CNoteDlg(); - -// Dialog Data - enum { IDD = IDD_NOTEDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() - -public: - CString strMsg; - BOOL bCoachOff; -}; diff --git a/source/OffsetDlg.cpp b/source/OffsetDlg.cpp deleted file mode 100644 index ff1c628..0000000 --- a/source/OffsetDlg.cpp +++ /dev/null @@ -1,187 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// dlg_offset.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "OffsetDlg.h" - - -// COffsetDlg dialog - -IMPLEMENT_DYNAMIC(COffsetDlg, CDialog) -COffsetDlg::COffsetDlg(CWnd* pParent /*=NULL*/) - : CDialog(COffsetDlg::IDD, pParent) - , m_sOffsetVal(_T("")) -{ - m_nBaseMode = 0; // 0=hex, 1=dec - m_nRadioBaseMode = 0; -} - -COffsetDlg::~COffsetDlg() -{ -} - - -// Set the initial file offset -void COffsetDlg::SetOffset(unsigned nPos) -{ - m_nOffsetVal = nPos; - OffsetNum2Str(); -} - -// Fetch the current offset value from the dialog -unsigned COffsetDlg::GetOffset() -{ - return m_nOffsetVal; -} - - -void COffsetDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Text(pDX, IDC_OFFSETVAL, m_sOffsetVal); - DDX_Radio(pDX, IDC_BASEH, m_nRadioBaseMode); -} - - -BEGIN_MESSAGE_MAP(COffsetDlg, CDialog) - ON_BN_CLICKED(IDC_BASEH, OnBnClickedBaseh) - ON_BN_CLICKED(IDC_BASED, OnBnClickedBased) - ON_BN_CLICKED(IDOK, OnBnClickedOk) -END_MESSAGE_MAP() - - -// COffsetDlg message handlers - - -// Convert internal offset number to dialog string -void COffsetDlg::OffsetNum2Str() -{ - CString strVal; - - if (m_nBaseMode == 0) { - // Hex - strVal.Format(_T("0x%08X"),m_nOffsetVal); - m_sOffsetVal = strVal; - } else { - // Dec - strVal.Format(_T("%u"),m_nOffsetVal); - m_sOffsetVal = strVal; - } - -} - -// Convert the current dialog offset string into -// the internal offset value. If data validation -// fails, then display a dialog box. -// -// RETURN: -// - True if validation OK -// -bool COffsetDlg::OffsetStr2Num() -{ - CString strVal; - - - if (m_nBaseMode == 0) { - // Hex - if (!Str2Uint32(m_sOffsetVal,16,m_nOffsetVal)) { - AfxMessageBox(_T("Invalid hex string")); - return false; - } - } else { - // Decimal - if (!Str2Uint32(m_sOffsetVal,10,m_nOffsetVal)) { - AfxMessageBox(_T("Invalid decimal string")); - return false; - } - } - return true; - -} - -// Change dialog mode to hex -// - If in decimal mode, convert from decimal to hex -// - Report data validation error -void COffsetDlg::OnBnClickedBaseh() -{ - CString strVal; - bool bOk; - - UpdateData(true); - if (m_nBaseMode == 0) { - // If it was hex before, don't do anything - } else { - // If it was decimal before, convert it! - bOk = OffsetStr2Num(); - m_nBaseMode = 0; - if (!bOk) { - // There was a validation error - // - Force the value to zero - // TODO: Would be nice if we could instead - // prevent the radio button from transitioning state. - m_nOffsetVal = 0; - } - } - OffsetNum2Str(); - UpdateData(false); -} - -// Change dialog mode to decimal -// - If in hex mode, convert from hex to decimal -// - Report data validation error -void COffsetDlg::OnBnClickedBased() -{ - CString strVal; - bool bOk; - - UpdateData(true); - if (m_nBaseMode == 1) { - // If it was decimal before, don't do anything - } else { - // If it was hex before, convert it! - bOk = OffsetStr2Num(); - m_nBaseMode = 1; - if (!bOk) { - // There was a validation error - // - Force the value to zero - // TODO: Would be nice if we could instead - // prevent the radio button from transitioning state. - m_nOffsetVal = 0; - } - } - OffsetNum2Str(); - UpdateData(false); -} - -void COffsetDlg::OnBnClickedOk() -{ - // Store the new local value before we return to dialog caller - UpdateData(); - - bool bOk = OffsetStr2Num(); - - // Only leave the dialog if the data validation was successful - if (bOk) { - OnOK(); - } - -} diff --git a/source/OffsetDlg.h b/source/OffsetDlg.h deleted file mode 100644 index dba1dff..0000000 --- a/source/OffsetDlg.h +++ /dev/null @@ -1,68 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box for adjusting the starting file decode offset -// -// ========================================================================== - - -#pragma once -#include "afxwin.h" - - -// COffsetDlg dialog - -class COffsetDlg : public CDialog -{ - DECLARE_DYNAMIC(COffsetDlg) - -public: - COffsetDlg(CWnd* pParent = NULL); // standard constructor - virtual ~COffsetDlg(); -// Dialog Data - enum { IDD = IDD_OFFSETDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() - - -public: - void SetOffset(unsigned nPos); - unsigned GetOffset(); - -private: - void OffsetNum2Str(); - bool OffsetStr2Num(); - -private: - afx_msg void OnBnClickedOk(); - afx_msg void OnBnClickedBaseh(); - afx_msg void OnBnClickedBased(); - - -private: - unsigned m_nOffsetVal; - int m_nRadioBaseMode; - unsigned m_nBaseMode; - CString m_sOffsetVal; - -}; diff --git a/source/OverlayBufDlg.cpp b/source/OverlayBufDlg.cpp deleted file mode 100644 index a391085..0000000 --- a/source/OverlayBufDlg.cpp +++ /dev/null @@ -1,193 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// OverlayBufDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "jpegsnoop.h" -#include "OverlayBufDlg.h" -#include ".\overlaybufdlg.h" - -#include "General.h" - -// COverlayBufDlg dialog - -IMPLEMENT_DYNAMIC(COverlayBufDlg, CDialog) -COverlayBufDlg::COverlayBufDlg(CWnd* pParent /*=NULL*/) - : CDialog(COverlayBufDlg::IDD, pParent) - , m_sOffset(_T("")) - , m_sValueCurHex(_T("")) - , m_sValueNewHex(_T("")) - , m_nLen(0) - , m_bEn(FALSE) - , m_sValueCurBin(_T("")) -{ - // FIXME: Should probably mark this as invalid - m_bApply = false; - m_nOffset = 0; - - // Initialize callback functions to NULL - m_pCbBuf = NULL; - m_pClassCbBuf = NULL; -} - -COverlayBufDlg::COverlayBufDlg(CWnd* pParent, - bool bEn, unsigned nOffset, unsigned nLen, CString sNewHex, CString sNewBin) - : CDialog(COverlayBufDlg::IDD, pParent) - , m_sOffset(_T("")) - , m_sValueCurHex(_T("")) - , m_sValueNewHex(_T("")) - , m_nLen(0) - , m_bEn(FALSE) -{ - m_bEn = bEn; - m_nOffset = nOffset; - m_nLen = nLen; - m_sValueNewHex = sNewHex; - m_sValueNewBin = sNewBin; - - // Initialize callback functions to NULL - m_pCbBuf = NULL; - m_pClassCbBuf = NULL; - - m_bApply = false; - - // Now recalc string fields - m_sOffset.Format(_T("0x%08X"),m_nOffset); - -} - - -COverlayBufDlg::~COverlayBufDlg() -{ -} - -void COverlayBufDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Text(pDX, IDC_OVRPOS, m_sOffset); - DDX_Text(pDX, IDC_OVRCUR, m_sValueCurHex); - DDX_Text(pDX, IDC_OVRNEW, m_sValueNewHex); - DDX_Text(pDX, IDC_OVRLEN, m_nLen); - DDX_Check(pDX, IDC_OVREN, m_bEn); - DDX_Text(pDX, IDC_OVRCURBIN, m_sValueCurBin); -} - - -BEGIN_MESSAGE_MAP(COverlayBufDlg, CDialog) - ON_BN_CLICKED(IDC_OVR_LOAD, OnBnClickedOvrLoad) - ON_BN_CLICKED(IDOK, OnBnClickedOk) - ON_BN_CLICKED(IDC_APPLY, OnBnClickedApply) -END_MESSAGE_MAP() - - -// Set callback function for Buf() -void COverlayBufDlg::SetCbBuf(void* pClassCbBuf, - BYTE (*pCbBuf)(void* pClassCbBuf, unsigned long nNum, bool bBool) - ) -{ - // Save pointer to class and function - m_pClassCbBuf = pClassCbBuf; - m_pCbBuf = pCbBuf; -} - - -// COverlayBufDlg message handlers - - - -void COverlayBufDlg::OnBnClickedOvrLoad() -{ - // TODO: Add your control notification handler code here - CString strTmp; - unsigned anCurVal[17]; - - ASSERT(m_pCbBuf); - if (!m_pCbBuf) { - return; - } - - UpdateData(); - m_nOffset = _tcstoul(m_sOffset,NULL,16); - - // get the data at the file position - for (unsigned nInd=0;nInd<16;nInd++) { - // Request the "clean" data as otherwise we'll see the - // last overlay data, which might be confusing! - if (m_pCbBuf) { - // Use callback function for Buf() - anCurVal[nInd] = m_pCbBuf(m_pClassCbBuf,m_nOffset+nInd,true); - } else { - anCurVal[nInd] = 0; // FIXME: - - } - } - - strTmp.Format(_T("0x %02X %02X %02X %02X %02X %02X %02X %02X ..."), - anCurVal[0],anCurVal[1],anCurVal[2],anCurVal[3], - anCurVal[4],anCurVal[5],anCurVal[6],anCurVal[7]); - m_sValueCurHex = strTmp; - - CString strTmpBin = _T("0b "); - strTmpBin += Dec2Bin(anCurVal[0],8); strTmpBin += _T(" "); - strTmpBin += Dec2Bin(anCurVal[1],8); strTmpBin += _T(" "); - strTmpBin += Dec2Bin(anCurVal[2],8); strTmpBin += _T(" "); - strTmpBin += Dec2Bin(anCurVal[3],8); strTmpBin += _T(" "); - strTmpBin += Dec2Bin(anCurVal[4],8); strTmpBin += _T(" "); - strTmpBin += Dec2Bin(anCurVal[5],8); strTmpBin += _T(" "); - strTmpBin += Dec2Bin(anCurVal[6],8); strTmpBin += _T(" "); - strTmpBin += Dec2Bin(anCurVal[7],8); strTmpBin += _T(" ..."); - m_sValueCurBin = strTmpBin; - - UpdateData(false); -} - -void COverlayBufDlg::OnBnClickedOk() -{ - UpdateData(); - m_nOffset = _tcstoul(m_sOffset,NULL,16); - - m_bApply = false; - OnOK(); -} - -void COverlayBufDlg::OnBnClickedApply() -{ - UpdateData(); - m_nOffset = _tcstoul(m_sOffset,NULL,16); - - m_bApply = true; - OnOK(); -} - -BOOL COverlayBufDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - CRect rect; - // TODO: Add extra initialization here - GetWindowRect(&rect); - SetWindowPos(NULL,50,50,rect.Width(),rect.Height(),0); - - // Get the initial values - OnBnClickedOvrLoad(); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} diff --git a/source/OverlayBufDlg.h b/source/OverlayBufDlg.h deleted file mode 100644 index 59c95a7..0000000 --- a/source/OverlayBufDlg.h +++ /dev/null @@ -1,77 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box for configuring a file decoder overlay -// - Enables local overwrite of the file buffer during decode for testing purposes -// -// ========================================================================== - - -#pragma once - - -// COverlayBufDlg dialog - -class COverlayBufDlg : public CDialog -{ - DECLARE_DYNAMIC(COverlayBufDlg) - -public: - COverlayBufDlg(CWnd* pParent = NULL); // standard constructor - COverlayBufDlg(CWnd* pParent, - bool bEn, unsigned nOffset, unsigned nLen, CString sNewHex, CString sNewBin); - virtual ~COverlayBufDlg(); - - -// Dialog Data - enum { IDD = IDD_OVERLAYBUFDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -private: - afx_msg void OnBnClickedOvrLoad(); - afx_msg void OnBnClickedOk(); - afx_msg void OnBnClickedApply(); - virtual BOOL OnInitDialog(); - -public: - // Callback function for Buf() - void SetCbBuf(void* pClassCbBuf, - BYTE (*pCbBuf)(void* pClassCbBuf, unsigned long nNum, bool bBool)); -private: - // References to callback function for Buf() - void* m_pClassCbBuf; - BYTE (*m_pCbBuf)(void* pClassCbBuf, unsigned long nNum, bool bBool); - -public: - unsigned m_nOffset; - unsigned m_nLen; - bool m_bApply; // When OnOK(), indicate apply and redo dialog - BOOL m_bEn; - CString m_sValueNewHex; -private: - CString m_sOffset; - CString m_sValueCurHex; - CString m_sValueCurBin; - CString m_sValueNewBin; - -}; diff --git a/source/Registry.cpp b/source/Registry.cpp deleted file mode 100644 index 1b1840b..0000000 --- a/source/Registry.cpp +++ /dev/null @@ -1,647 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code is derived from the following project on CodeProject: -// -// Title: Another registry class -// Author: SteveKing -// URL: http://www.codeproject.com/Articles/2521/Another-registry-class -// Date: Apr 25, 2003 -// License: CPOL (Code Project Open License) -// -// ==================================================================================================== - - -#include "stdafx.h" -#include "Registry.h" - -#ifdef _MFC_VER -//MFC is available - also use the MFC-based classes - -CRegDWORD::CRegDWORD(void) -{ - m_value = 0; - m_defaultvalue = 0; - m_key = ""; - m_base = HKEY_CURRENT_USER; - m_read = FALSE; - m_force = FALSE; -} - -/** - * Constructor. - * @param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * @param def the default value used when the key does not exist or a read error occured - * @param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * @param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ -CRegDWORD::CRegDWORD(CString key, DWORD def, BOOL force, HKEY base) -{ - m_value = 0; - m_defaultvalue = def; - m_force = force; - m_base = base; - m_read = FALSE; - key.TrimLeft(_T("\\")); - m_path = key.Left(key.ReverseFind(_T('\\'))); - m_path.TrimRight(_T("\\")); - m_key = key.Right(key.GetLength() - key.ReverseFind(_T('\\'))); - m_key.Trim(_T("\\")); - read(); -} - -CRegDWORD::~CRegDWORD(void) -{ - //write(); -} - -DWORD CRegDWORD::read() -{ - ASSERT(m_key != _T("")); - if (RegOpenKeyEx(m_base, m_path, 0, KEY_EXECUTE, &m_hKey)==ERROR_SUCCESS) - { - int size = sizeof(m_value); - DWORD type; - if (RegQueryValueEx(m_hKey, m_key, NULL, &type, (BYTE*) &m_value,(LPDWORD) &size)==ERROR_SUCCESS) - { - ASSERT(type==REG_DWORD); - m_read = TRUE; - RegCloseKey(m_hKey); - return m_value; - } - else - { - RegCloseKey(m_hKey); - return m_defaultvalue; - } - } - return m_defaultvalue; -} - -void CRegDWORD::write() -{ - ASSERT(m_key != _T("")); - DWORD disp; - if (RegCreateKeyEx(m_base, m_path, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &m_hKey, &disp)!=ERROR_SUCCESS) - { - return; - } - if (RegSetValueEx(m_hKey, m_key, 0, REG_DWORD,(const BYTE*) &m_value, sizeof(m_value))==ERROR_SUCCESS) - { - m_read = TRUE; - } - RegCloseKey(m_hKey); -} - - -CRegDWORD::operator DWORD() -{ - if ((m_read)&&(!m_force)) - return m_value; - else - { - return read(); - } -} - -CRegDWORD& CRegDWORD::operator =(DWORD d) -{ - if ((d==m_value)&&(!m_force)) - { - //no write to the registry required, its the same value - return *this; - } - m_value = d; - write(); - return *this; -} - -////////////////////////////////////////////////////////////////////////////////////////////// - -CRegString::CRegString(void) -{ - m_value = _T(""); - m_defaultvalue = _T(""); - m_key = _T(""); - m_base = HKEY_CURRENT_USER; - m_read = FALSE; - m_force = FALSE; -} - -/** - * Constructor. - * @param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * @param def the default value used when the key does not exist or a read error occured - * @param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * @param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ -CRegString::CRegString(CString key, CString def, BOOL force, HKEY base) -{ - m_value = ""; - m_defaultvalue = def; - m_force = force; - m_base = base; - m_read = FALSE; - key.TrimLeft(_T("\\")); - m_path = key.Left(key.ReverseFind(_T('\\'))); - m_path.TrimRight(_T("\\")); - m_key = key.Right(key.GetLength() - key.ReverseFind(_T('\\'))); - m_key.Trim(_T("\\")); - read(); -} - -CRegString::~CRegString(void) -{ - //write(); -} - -CString CRegString::read() -{ - ASSERT(m_key != _T("")); - if (RegOpenKeyEx(m_base, m_path, 0, KEY_EXECUTE, &m_hKey)==ERROR_SUCCESS) - { - int size = 0; - DWORD type; - RegQueryValueEx(m_hKey, m_key, NULL, &type, NULL, (LPDWORD) &size); - TCHAR* pStr = new TCHAR[size]; - if (RegQueryValueEx(m_hKey, m_key, NULL, &type, (BYTE*) pStr,(LPDWORD) &size)==ERROR_SUCCESS) - { - m_value = CString(pStr); - delete [] pStr; - ASSERT(type==REG_SZ); - m_read = TRUE; - RegCloseKey(m_hKey); - return m_value; - } - else - { - delete [] pStr; - RegCloseKey(m_hKey); - return m_defaultvalue; - } - } - return m_defaultvalue; -} - -void CRegString::write() -{ - ASSERT(m_key != _T("")); - DWORD disp; - if (RegCreateKeyEx(m_base, m_path, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &m_hKey, &disp)!=ERROR_SUCCESS) - { - return; - } -#ifdef _UNICODE - if (RegSetValueEx(m_hKey, m_key, 0, REG_SZ, (BYTE *)(LPCTSTR)m_value, (m_value.GetLength()+1)*2)==ERROR_SUCCESS) -#else - if (RegSetValueEx(m_hKey, m_key, 0, REG_SZ, (BYTE *)(LPCTSTR)m_value, m_value.GetLength()+1)==ERROR_SUCCESS) -#endif - { - m_read = TRUE; - } - RegCloseKey(m_hKey); -} - -CRegString::operator CString() -{ - if ((m_read)&&(!m_force)) - return m_value; - else - { - return read(); - } -} - -CRegString& CRegString::operator =(CString s) -{ - if ((s==m_value)&&(!m_force)) - { - //no write to the registry required, its the same value - return *this; - } - m_value = s; - write(); - return *this; -} - -////////////////////////////////////////////////////////////////////////////////////////////// -#if 0 // Remove CRegRect (unneeded, triggers C2440) -CRegRect::CRegRect(void) -{ - m_value = CRect(0,0,0,0); - m_defaultvalue = CRect(0,0,0,0); - m_key = _T(""); - m_base = HKEY_CURRENT_USER; - m_read = FALSE; - m_force = FALSE; -} - -/** - * Constructor. - * @param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * @param def the default value used when the key does not exist or a read error occured - * @param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * @param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ -CRegRect::CRegRect(CString key, CRect def, BOOL force, HKEY base) -{ - m_value = CRect(0,0,0,0); - m_defaultvalue = def; - m_force = force; - m_base = base; - m_read = FALSE; - key.TrimLeft(_T("\\")); - m_path = key.Left(key.ReverseFind(_T('\\'))); - m_path.TrimRight(_T("\\")); - m_key = key.Right(key.GetLength() - key.ReverseFind(_T('\\'))); - m_key.Trim(_T("\\")); - read(); -} - -CRegRect::~CRegRect(void) -{ - //write(); -} - -CRect CRegRect::read() -{ - ASSERT(m_key != _T("")); - if (RegOpenKeyEx(m_base, m_path, 0, KEY_EXECUTE, &m_hKey)==ERROR_SUCCESS) - { - int size = 0; - DWORD type; - RegQueryValueEx(m_hKey, m_key, NULL, &type, NULL, (LPDWORD) &size); - LPRECT pRect = (LPRECT)new char[size]; - if (RegQueryValueEx(m_hKey, m_key, NULL, &type, (BYTE*) pRect,(LPDWORD) &size)==ERROR_SUCCESS) - { - m_value = CRect(pRect); - delete [] pRect; - ASSERT(type==REG_BINARY); - m_read = TRUE; - RegCloseKey(m_hKey); - return m_value; - } - else - { - delete [] pRect; - RegCloseKey(m_hKey); - return m_defaultvalue; - } - } - return m_defaultvalue; -} - -void CRegRect::write() -{ - ASSERT(m_key != _T("")); - DWORD disp; - if (RegCreateKeyEx(m_base, m_path, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &m_hKey, &disp)!=ERROR_SUCCESS) - { - return; - } - - if (RegSetValueEx(m_hKey, m_key, 0, REG_BINARY, (BYTE *)(LPRECT)m_value, sizeof(m_value))==ERROR_SUCCESS) - { - m_read = TRUE; - } - RegCloseKey(m_hKey); -} - -CRegRect::operator CRect() -{ - if ((m_read)&&(!m_force)) - return m_value; - else - { - return read(); - } -} - -CRegRect& CRegRect::operator =(CRect s) -{ - if ((s==m_value)&&(!m_force)) - { - //no write to the registry required, its the same value - return *this; - } - m_value = s; - write(); - return *this; -} -#endif // Remove CRegRect - -////////////////////////////////////////////////////////////////////////////////////////////// - -CRegPoint::CRegPoint(void) -{ - m_value = CPoint(0,0); - m_defaultvalue = CPoint(0,0); - m_key = ""; - m_base = HKEY_CURRENT_USER; - m_read = FALSE; - m_force = FALSE; -} - -/** - * Constructor. - * @param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * @param def the default value used when the key does not exist or a read error occured - * @param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * @param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ -CRegPoint::CRegPoint(CString key, CPoint def, BOOL force, HKEY base) -{ - m_value = CPoint(0,0); - m_defaultvalue = def; - m_force = force; - m_base = base; - m_read = FALSE; - key.TrimLeft(_T("\\")); - m_path = key.Left(key.ReverseFind(_T('\\'))); - m_path.TrimRight(_T("\\")); - m_key = key.Right(key.GetLength() - key.ReverseFind(_T('\\'))); - m_key.Trim(_T("\\")); - read(); -} - -CRegPoint::~CRegPoint(void) -{ - //write(); -} - -CPoint CRegPoint::read() -{ - ASSERT(m_key != _T("")); - if (RegOpenKeyEx(m_base, m_path, 0, KEY_EXECUTE, &m_hKey)==ERROR_SUCCESS) - { - int size = 0; - DWORD type; - RegQueryValueEx(m_hKey, m_key, NULL, &type, NULL, (LPDWORD) &size); - POINT* pPoint = (POINT *)new char[size]; - if (RegQueryValueEx(m_hKey, m_key, NULL, &type, (BYTE*) pPoint,(LPDWORD) &size)==ERROR_SUCCESS) - { - m_value = CPoint(*pPoint); - delete [] pPoint; - ASSERT(type==REG_BINARY); - m_read = TRUE; - RegCloseKey(m_hKey); - return m_value; - } - else - { - delete [] pPoint; - RegCloseKey(m_hKey); - return m_defaultvalue; - } - } - return m_defaultvalue; -} - -void CRegPoint::write() -{ - ASSERT(m_key != _T("")); - DWORD disp; - if (RegCreateKeyEx(m_base, m_path, 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &m_hKey, &disp)!=ERROR_SUCCESS) - { - return; - } - - if (RegSetValueEx(m_hKey, m_key, 0, REG_BINARY, (BYTE *)(POINT *)&m_value, sizeof(m_value))==ERROR_SUCCESS) - { - m_read = TRUE; - } - RegCloseKey(m_hKey); -} - -CRegPoint::operator CPoint() -{ - if ((m_read)&&(!m_force)) - return m_value; - else - { - return read(); - } -} - -CRegPoint& CRegPoint::operator =(CPoint s) -{ - if ((s==m_value)&&(!m_force)) - { - //no write to the registry required, its the same value - return *this; - } - m_value = s; - write(); - return *this; -} - -#endif - -///////////////////////////////////////////////////////////////////// - -CRegStdString::CRegStdString(void) -{ - m_value = _T(""); - m_defaultvalue = _T(""); - m_key = _T(""); - m_base = HKEY_CURRENT_USER; - m_read = FALSE; - m_force = FALSE; -} - -/** - * Constructor. - * @param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * @param def the default value used when the key does not exist or a read error occured - * @param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * @param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ -CRegStdString::CRegStdString(stdstring key, stdstring def, BOOL force, HKEY base) -{ - m_value = _T(""); - m_defaultvalue = def; - m_force = force; - m_base = base; - m_read = FALSE; - - stdstring::size_type pos = key.find_last_of(_T('\\')); - m_path = key.substr(0, pos); - m_key = key.substr(pos + 1); - read(); -} - -CRegStdString::~CRegStdString(void) -{ - //write(); -} - -stdstring CRegStdString::read() -{ - if (RegOpenKeyEx(m_base, m_path.c_str(), 0, KEY_EXECUTE, &m_hKey)==ERROR_SUCCESS) - { - int size = 0; - DWORD type; - RegQueryValueEx(m_hKey, m_key.c_str(), NULL, &type, NULL, (LPDWORD) &size); - TCHAR* pStr = new TCHAR[size]; - if (RegQueryValueEx(m_hKey, m_key.c_str(), NULL, &type, (BYTE*) pStr,(LPDWORD) &size)==ERROR_SUCCESS) - { - m_value.assign(pStr); - delete [] pStr; - m_read = TRUE; - RegCloseKey(m_hKey); - return m_value; - } - else - { - delete [] pStr; - RegCloseKey(m_hKey); - return m_defaultvalue; - } - } - return m_defaultvalue; -} - -void CRegStdString::write() -{ - DWORD disp; - if (RegCreateKeyEx(m_base, m_path.c_str(), 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &m_hKey, &disp)!=ERROR_SUCCESS) - { - return; - } - if (RegSetValueEx(m_hKey, m_key.c_str(), 0, REG_SZ, (BYTE *)m_value.c_str(), (DWORD)m_value.size()+1)==ERROR_SUCCESS) - { - m_read = TRUE; - } - RegCloseKey(m_hKey); -} - -CRegStdString::operator LPCTSTR() -{ - if ((m_read)&&(!m_force)) - return m_value.c_str(); - else - return read().c_str(); -} - -CRegStdString::operator stdstring() -{ - if ((m_read)&&(!m_force)) - return m_value; - else - { - return read(); - } -} - -CRegStdString& CRegStdString::operator =(stdstring s) -{ - if ((s==m_value)&&(!m_force)) - { - //no write to the registry required, its the same value - return *this; - } - m_value = s; - write(); - return *this; -} - -///////////////////////////////////////////////////////////////////// - -CRegStdWORD::CRegStdWORD(void) -{ - m_value = 0; - m_defaultvalue = 0; - m_key = _T(""); - m_base = HKEY_CURRENT_USER; - m_read = FALSE; - m_force = FALSE; -} - -/** - * Constructor. - * @param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * @param def the default value used when the key does not exist or a read error occured - * @param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * @param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ -CRegStdWORD::CRegStdWORD(stdstring key, DWORD def, BOOL force, HKEY base) -{ - m_value = 0; - m_defaultvalue = def; - m_force = force; - m_base = base; - m_read = FALSE; - - stdstring::size_type pos = key.find_last_of(_T('\\')); - m_path = key.substr(0, pos); - m_key = key.substr(pos + 1); - read(); -} - -CRegStdWORD::~CRegStdWORD(void) -{ - //write(); -} - -DWORD CRegStdWORD::read() -{ - if (RegOpenKeyEx(m_base, m_path.c_str(), 0, KEY_EXECUTE, &m_hKey)==ERROR_SUCCESS) - { - int size = sizeof(m_value); - DWORD type; - if (RegQueryValueEx(m_hKey, m_key.c_str(), NULL, &type, (BYTE*) &m_value,(LPDWORD) &size)==ERROR_SUCCESS) - { - m_read = TRUE; - RegCloseKey(m_hKey); - return m_value; - } - else - { - RegCloseKey(m_hKey); - return m_defaultvalue; - } - } - return m_defaultvalue; -} - -void CRegStdWORD::write() -{ - DWORD disp; - if (RegCreateKeyEx(m_base, m_path.c_str(), 0, _T(""), REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &m_hKey, &disp)!=ERROR_SUCCESS) - { - return; - } - if (RegSetValueEx(m_hKey, m_key.c_str(), 0, REG_DWORD,(const BYTE*) &m_value, sizeof(m_value))==ERROR_SUCCESS) - { - m_read = TRUE; - } - RegCloseKey(m_hKey); -} - -CRegStdWORD::operator DWORD() -{ - if ((m_read)&&(!m_force)) - return m_value; - else - { - return read(); - } -} diff --git a/source/Registry.h b/source/Registry.h deleted file mode 100644 index fcc468f..0000000 --- a/source/Registry.h +++ /dev/null @@ -1,706 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code is derived from the following project on CodeProject: -// -// Title: Another registry class -// Author: SteveKing -// URL: http://www.codeproject.com/Articles/2521/Another-registry-class -// Date: Apr 25, 2003 -// License: CPOL (Code Project Open License) -// -// ==================================================================================================== - -#pragma once -#include -#include -#include -#ifdef _MFC_VER - -/** - * \ingroup CommonClasses - * Base class for the registry classes. - * - * \par requirements - * - win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later - * - import library Shlwapi.lib - * - * \author Stefan Kueng - * - * \par license - * This code is absolutely free to use and modify. The code is provided "as is" with - * no expressed or implied warranty. The author accepts no liability if it causes - * any damage to your computer, causes your pet to fall ill, increases baldness - * or makes your car start emitting strange noises when you start it up. - * This code has no bugs, just undocumented features! - * - * \version 1.0 - * \date 06-2002 - * \todo - * \bug - * \warning - * - */ -class CRegBase -{ -public: //methods - /** - * Removes the whole registry key including all values. So if you set the registry - * entry to be HKCU\Software\Company\Product\key\value there will only be - * HKCU\Software\Company\Product key in the registry. - * \return ERROR_SUCCESS or an nonzero errorcode. Use FormatMessage() to get an error description. - */ - DWORD removeKey() { RegOpenKeyEx(m_base, m_path, 0, KEY_WRITE, &m_hKey); return SHDeleteKey(m_base, (LPCTSTR)m_path); } - /** - * Removes the value of the registry object. If you set the registry entry to - * be HKCU\Software\Company\Product\key\value there will only be - * HKCU\Software\Company\Product\key\ in the registry. - * \return ERROR_SUCCESS or an nonzero errorcode. Use FormatMessage() to get an error description. - */ - LONG removeValue() { RegOpenKeyEx(m_base, m_path, 0, KEY_WRITE, &m_hKey); return RegDeleteValue(m_hKey, (LPCTSTR)m_key); } - -public: //members - HKEY m_base; ///< handle to the registry base - HKEY m_hKey; ///< handle to the open registry key - CString m_key; ///< the name of the value - CString m_path; ///< the path to the key -}; - -/** - * \ingroup CommonClasses - * DWORD value in registry. with this class you can use DWORD values in registry - * like normal DWORD variables in your program. - * Usage: - * in your header file, declare your registry DWORD variable: - * \code - * CRegDWORD regvalue; - * \endcode - * next initialize the variable e.g. in the constructor of your class: - * \code - * regvalue = CRegDWORD("Software\\Company\\SubKey\\MyValue", 100); - * \endcode - * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path - * "Software\Company\SubKey" to the variable. If the key does not yet exist or - * an error occured during read from the registry, a default - * value of 100 is used when accessing the variable. - * now the variable can be used like any other DWORD variable: - * \code - * regvalue = 200; //stores the value 200 in the registry - * int temp = regvalue + 300; //temp has value 500 now - * regvalue += 300; //now the registry has the value 500 too - * \endcode - * to avoid too much access to the registry the value is cached inside the object. - * once the value is read, no more read accesses to the registry will be made. - * this means the variable will contain a wrong value if the corresponding registry - * entry is changed by anything else than this variable! If you think that could happen - * then use - * \code - * regvalue.read(); - * \endcode - * to force a refresh of the variable with the registry. - * a write to the registry is only made if the new value assigned with the variable - * is different than the last assigned value. - * to force a write use the method write(); - * another option to force reads and writes to the registry is to specify TRUE as the - * third parameter in the constructor. - * - * \par requirements - * win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later - * import library Shlwapi.lib - * - * \author Stefan Kueng (stefan_kueng@catv.rol.ch) - * - * \par license - * This code is absolutely free to use and modify. The code is provided "as is" with - * no expressed or implied warranty. The author accepts no liability if it causes - * any damage to your computer, causes your pet to fall ill, increases baldness - * or makes your car start emitting strange noises when you start it up. - * This code has no bugs, just undocumented features! - * - * \version 1.1 - * added base class CRegBase with methods removeKey() and removeValue() - * \version 1.0 - * \date 06-2002 - * \todo - * \bug - * \warning - * - */ -class CRegDWORD : public CRegBase -{ -public: - CRegDWORD(void); - /** - * Constructor. - * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * \param def the default value used when the key does not exist or a read error occured - * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ - CRegDWORD(CString key, DWORD def = 0, BOOL force = FALSE, HKEY base = HKEY_CURRENT_USER); - ~CRegDWORD(void); - /** - * reads the assigned value from the registry. Use this method only if you think the registry - * value could have been altered without using the CRegDWORD object. - * \return the read value - */ - DWORD read(); ///< reads the value from the registry - void write(); ///< writes the value to the registry - - operator DWORD(); - CRegDWORD& operator=(DWORD d); - CRegDWORD& operator+=(DWORD d) { return *this = *this + d;} - CRegDWORD& operator-=(DWORD d) { return *this = *this - d;} - CRegDWORD& operator*=(DWORD d) { return *this = *this * d;} - CRegDWORD& operator/=(DWORD d) { return *this = *this / d;} - CRegDWORD& operator%=(DWORD d) { return *this = *this % d;} - CRegDWORD& operator<<=(DWORD d) { return *this = *this << d;} - CRegDWORD& operator>>=(DWORD d) { return *this = *this >> d;} - CRegDWORD& operator&=(DWORD d) { return *this = *this & d;} - CRegDWORD& operator|=(DWORD d) { return *this = *this | d;} - CRegDWORD& operator^=(DWORD d) { return *this = *this ^ d;} - -protected: - - DWORD m_value; ///< the cached value of the registry - DWORD m_defaultvalue; ///< the default value to use - BOOL m_read; ///< indicates if the value has already been read from the registry - BOOL m_force; ///< indicates if no cache should be used, i.e. always read and write directly from registry -}; - -/** - * \ingroup CommonClasses - * CString value in registry. with this class you can use CString values in registry - * almost like normal CString variables in your program. - * Usage: - * in your header file, declare your registry CString variable: - * \code - * CRegString regvalue; - * \endcode - * next initialize the variable e.g. in the constructor of your class: - * \code - * regvalue = CRegString("Software\\Company\\SubKey\\MyValue", "default"); - * \endcode - * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path - * "Software\Company\SubKey" to the variable. If the key does not yet exist or - * an error occured during read from the registry, a default - * value of "default" is used when accessing the variable. - * now the variable can be used like any other CString variable: - * \code - * regvalue = "some string"; //stores the value "some string" in the registry - * CString temp = regvalue + "!!"; //temp has value "some string!!" now - * \endcode - * to use the normal methods of the CString class, just typecast the CRegString to a CString - * and do whatever you want with the string: - * \code - * ((CString)regvalue).GetLength(); - * ((CString)regvalue).Trim(); - * \endcode - * please be aware that in the second line the change in the string won't be written - * to the registry! To force a write use the write() method. A write() is only needed - * if you change the String with Methods not overloaded by CRegString. - * to avoid too much access to the registry the value is cached inside the object. - * once the value is read, no more read accesses to the registry will be made. - * this means the variable will contain a wrong value if the corresponding registry - * entry is changed by anything else than this variable! If you think that could happen - * then use - * \code - * regvalue.read(); - * \endcode - * to force a refresh of the variable with the registry. - * a write to the registry is only made if the new value assigned with the variable - * is different than the last assigned value. - * to force a write use the method write(); - * another option to force reads and writes to the registry is to specify TRUE as the - * third parameter in the constructor. - * - * \par requirements - * win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later - * import library Shlwapi.lib - * - * \author Stefan Kueng (stefan_kueng@catv.rol.ch) - * - * \par license - * This code is absolutely free to use and modify. The code is provided "as is" with - * no expressed or implied warranty. The author accepts no liability if it causes - * any damage to your computer, causes your pet to fall ill, increases baldness - * or makes your car start emitting strange noises when you start it up. - * This code has no bugs, just undocumented features! - * - * \version 1.1 - * corrected a bug, thanks to Hans Dietrich for the correction. - * added base class CRegBase with methods removeKey() and removeValue() - * \version 1.0 - * \date 06-2002 - * \todo - * \bug - * \warning - */ -class CRegString : public CRegBase -{ -public: - CRegString(); - /** - * Constructor. - * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * \param def the default value used when the key does not exist or a read error occured - * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ - CRegString(CString key, CString def = _T(""), BOOL force = FALSE, HKEY base = HKEY_CURRENT_USER); - ~CRegString(void); - - CString read(); ///< reads the value from the registry - void write(); ///< writes the value to the registry - - operator CString(); - CRegString& operator=(CString s); - CRegString& operator+=(CString s) { return *this = (CString)*this + s; } - - - -protected: - - CString m_value; ///< the cached value of the registry - CString m_defaultvalue; ///< the default value to use - BOOL m_read; ///< indicates if the value has already been read from the registry - BOOL m_force; ///< indicates if no cache should be used, i.e. always read and write directly from registry -}; - -/** - * \ingroup CommonClasses - * CRect value in registry. with this class you can use CRect values in registry - * almost like normal CRect variables in your program. - * Usage: - * in your header file, declare your registry CString variable: - * \code - * CRegRect regvalue; - * \endcode - * next initialize the variable e.g. in the constructor of your class: - * \code - * regvalue = CRegRect("Software\\Company\\SubKey\\MyValue", CRect(100,100,200,200)); - * \endcode - * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path - * "Software\Company\SubKey" to the variable. If the key does not yet exist or - * an error occured during read from the registry, a default - * value of 100,100,200,200 is used when accessing the variable. - * now the variable can be used like any other CRect variable: - * \code - * regvalue = CRect(40,20,300,500); //stores the value in the registry - * CRect temp = regvalue + CPoint(1,1); - * temp |= CSize(5,5); - * \endcode - * to use the normal methods of the CRect class, just typecast the CRegRect to a CRect - * and do whatever you want with the rect: - * \code - * ((CRect)regvalue).MoveToX(100); - * ((CRect)regvalue).DeflateRect(10,10); - * \endcode - * please be aware that in the second line the change in the CRect won't be written - * to the registry! To force a write use the write() method. A write() is only needed - * if you change the CRect with Methods not overloaded by CRegRect. - * to avoid too much access to the registry the value is cached inside the object. - * once the value is read, no more read accesses to the registry will be made. - * this means the variable will contain a wrong value if the corresponding registry - * entry is changed by anything else than this variable! If you think that could happen - * then use - * \code - * regvalue.read(); - * \endcode - * to force a refresh of the variable with the registry. - * a write to the registry is only made if the new value assigned with the variable - * is different than the last assigned value. - * to force a write use the method write(); - * another option to force reads and writes to the registry is to specify TRUE as the - * third parameter in the constructor. - * - * \par requirements - * win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later - * import library Shlwapi.lib - * - * \author Stefan Kueng (stefan_kueng@catv.rol.ch) - * - * \par license - * This code is absolutely free to use and modify. The code is provided "as is" with - * no expressed or implied warranty. The author accepts no liability if it causes - * any damage to your computer, causes your pet to fall ill, increases baldness - * or makes your car start emitting strange noises when you start it up. - * This code has no bugs, just undocumented features! - * - * \version 1.1 - * corrected a bug, thanks to Hans Dietrich for the correction. - * added base class CRegBase with methods removeKey() and removeValue() - * \version 1.0 - * \date 06-2002 - * \todo - * \bug - * \warning - */ -#if 0 // Remove CRegRect (unneeded, triggers C2440) -class CRegRect : public CRegBase -{ -public: - CRegRect(); - /** - * Constructor. - * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * \param def the default value used when the key does not exist or a read error occured - * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ - CRegRect(CString key, CRect def = CRect(), BOOL force = FALSE, HKEY base = HKEY_CURRENT_USER); - ~CRegRect(void); - - CRect read(); ///< reads the value from the registry - void write(); ///< writes the value to the registry - - operator CRect(); - operator LPCRECT() { return (LPCRECT)(CRect)*this; } - operator LPRECT() { return (LPRECT)(CRect)*this; } - CRegRect& operator=(CRect r); - CRegRect& operator+=(POINT r) { return *this = (CRect)*this + r;} - CRegRect& operator+=(SIZE r) { return *this = (CRect)*this + r;} - CRegRect& operator+=(LPCRECT r) { return *this = (CRect)*this + r;} - CRegRect& operator-=(POINT r) { return *this = (CRect)*this - r;} - CRegRect& operator-=(SIZE r) { return *this = (CRect)*this - r;} - CRegRect& operator-=(LPCRECT r) { return *this = (CRect)*this - r;} - - CRegRect& operator&=(CRect r) { return *this = r & *this;} - CRegRect& operator|=(CRect r) { return *this = r | *this;} - - -protected: - - CRect m_value; ///< the cached value of the registry - CRect m_defaultvalue; ///< the default value to use - BOOL m_read; ///< indicates if the value has already been read from the registry - BOOL m_force; ///< indicates if no cache should be used, i.e. always read and write directly from registry -}; -#endif // Remove CRegRect - -/** - * \ingroup CommonClasses - * CPoint value in registry. with this class you can use CPoint values in registry - * almost like normal CPoint variables in your program. - * Usage: - * in your header file, declare your registry CPoint variable: - * \code - * CRegPoint regvalue; - * \endcode - * next initialize the variable e.g. in the constructor of your class: - * \code - * regvalue = CRegPoint("Software\\Company\\SubKey\\MyValue", CPoint(100,100)); - * \endcode - * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path - * "Software\Company\SubKey" to the variable. If the key does not yet exist or - * an error occured during read from the registry, a default - * value of 100,100 is used when accessing the variable. - * now the variable can be used like any other CPoint variable: - * \code - * regvalue = CPoint(40,20); //stores the value in the registry - * CPoint temp = regvalue + CPoint(1,1); - * temp += CSize(5,5); - * \endcode - * to use the normal methods of the CPoint class, just typecast the CRegPoint to a CPoint - * and do whatever you want with the point: - * \code - * ((CRect)regvalue).Offset(100,10); - * \endcode - * please be aware that in the above example the change in the CPoint won't be written - * to the registry! To force a write use the write() method. A write() is only needed - * if you change the CPoint with Methods not overloaded by CRegPoint. - * to avoid too much access to the registry the value is cached inside the object. - * once the value is read, no more read accesses to the registry will be made. - * this means the variable will contain a wrong value if the corresponding registry - * entry is changed by anything else than this variable! If you think that could happen - * then use - * \code - * regvalue.read(); - * \endcode - * to force a refresh of the variable with the registry. - * a write to the registry is only made if the new value assigned with the variable - * is different than the last assigned value. - * to force a write use the method write(); - * another option to force reads and writes to the registry is to specify TRUE as the - * third parameter in the constructor. - * - * \par requirements - * win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later - * import library Shlwapi.lib - * - * \author Stefan Kueng (stefan_kueng@catv.rol.ch) - * - * \par license - * This code is absolutely free to use and modify. The code is provided "as is" with - * no expressed or implied warranty. The author accepts no liability if it causes - * any damage to your computer, causes your pet to fall ill, increases baldness - * or makes your car start emitting strange noises when you start it up. - * This code has no bugs, just undocumented features! - * - * \version 1.1 - * corrected a bug, thanks to Hans Dietrich for the correction. - * added base class CRegBase with methods removeKey() and removeValue() - * \version 1.0 - * \date 06-2002 - * \todo - * \bug - * \warning - */ -class CRegPoint : public CRegBase -{ -public: - CRegPoint(); - /** - * Constructor. - * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * \param def the default value used when the key does not exist or a read error occured - * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ - CRegPoint(CString key, CPoint def = CPoint(), BOOL force = FALSE, HKEY base = HKEY_CURRENT_USER); - ~CRegPoint(void); - - CPoint read(); - void write(); ///< writes the value to the registry - - operator CPoint(); - CRegPoint& operator=(CPoint p); - - CRegPoint& operator+=(CPoint p) { return *this = p + *this; } - CRegPoint& operator-=(CPoint p) { return *this = p - *this; } - - -protected: - - CPoint m_value; ///< the cached value of the registry - CPoint m_defaultvalue; ///< the default value to use - BOOL m_read; ///< indicates if the value has already been read from the registry - BOOL m_force; ///< indicates if no cache should be used, i.e. always read and write directly from registry -}; - -#endif - -typedef std::basic_string stdstring; - -class CRegStdBase -{ -public: //methods - /** - * Removes the whole registry key including all values. So if you set the registry - * entry to be HKCU\Software\Company\Product\key\value there will only be - * HKCU\Software\Company\Product key in the registry. - * \return ERROR_SUCCESS or an nonzero errorcode. Use FormatMessage() to get an error description. - */ - DWORD removeKey() { RegOpenKeyEx(m_base, m_path.c_str(), 0, KEY_WRITE, &m_hKey); return SHDeleteKey(m_base, m_path.c_str()); } - /** - * Removes the value of the registry object. If you set the registry entry to - * be HKCU\Software\Company\Product\key\value there will only be - * HKCU\Software\Company\Product\key\ in the registry. - * \return ERROR_SUCCESS or an nonzero errorcode. Use FormatMessage() to get an error description. - */ - LONG removeValue() { RegOpenKeyEx(m_base, m_path.c_str(), 0, KEY_WRITE, &m_hKey); return RegDeleteValue(m_hKey, m_key.c_str()); } - -public: //members - HKEY m_base; ///< handle to the registry base - HKEY m_hKey; ///< handle to the open registry key - stdstring m_key; ///< the name of the value - stdstring m_path; ///< the path to the key -}; - -/** - * \ingroup CommonClasses - * std::string value in registry. with this class you can use std::string values in registry - * almost like normal std::string variables in your program. - * Usage: - * in your header file, declare your registry std::string variable: - * \code - * CRegStdString regvalue; - * \endcode - * next initialize the variable e.g. in the constructor of your class: - * \code - * regvalue = CRegStdString("Software\\Company\\SubKey\\MyValue", "default"); - * \endcode - * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path - * "Software\Company\SubKey" to the variable. If the key does not yet exist or - * an error occured during read from the registry, a default - * value of "default" is used when accessing the variable. - * to avoid too much access to the registry the value is cached inside the object. - * once the value is read, no more read accesses to the registry will be made. - * this means the variable will contain a wrong value if the corresponding registry - * entry is changed by anything else than this variable! If you think that could happen - * then use - * \code - * regvalue.read(); - * \endcode - * to force a refresh of the variable with the registry. - * a write to the registry is only made if the new value assigned with the variable - * is different than the last assigned value. - * to force a write use the method write(); - * another option to force reads and writes to the registry is to specify TRUE as the - * third parameter in the constructor. - * - * \par requirements - * win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later - * import library Shlwapi.lib - * - * \author Stefan Kueng (stefan_kueng@catv.rol.ch) - * - * \par license - * This code is absolutely free to use and modify. The code is provided "as is" with - * no expressed or implied warranty. The author accepts no liability if it causes - * any damage to your computer, causes your pet to fall ill, increases baldness - * or makes your car start emitting strange noises when you start it up. - * This code has no bugs, just undocumented features! - * - * \version 1.0 - * first version which uses std::string instead of CString. - * \date 10-2002 - */ -class CRegStdString : public CRegStdBase -{ -public: - CRegStdString(); - /** - * Constructor. - * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * \param def the default value used when the key does not exist or a read error occured - * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ - CRegStdString(stdstring key, stdstring def = _T(""), BOOL force = FALSE, HKEY base = HKEY_CURRENT_USER); - ~CRegStdString(void); - - stdstring read(); ///< reads the value from the registry - void write(); ///< writes the value to the registry - - operator stdstring(); - CRegStdString& operator=(stdstring s); - //CAL! Commended out the following as otherwise we get error C2440. We don't - // use this function anyway. - //CRegStdString& operator+=(stdstring s) { return *this = (stdstring)*this + s; } - operator LPCTSTR(); - - -protected: - - stdstring m_value; ///< the cached value of the registry - stdstring m_defaultvalue; ///< the default value to use - BOOL m_read; ///< indicates if the value has already been read from the registry - BOOL m_force; ///< indicates if no cache should be used, i.e. always read and write directly from registry -}; - -/** - * \ingroup CommonClasses - * DWORD value in registry. with this class you can use DWORD values in registry - * like normal DWORD variables in your program. - * Usage: - * in your header file, declare your registry DWORD variable: - * \code - * CRegStdWORD regvalue; - * \endcode - * next initialize the variable e.g. in the constructor of your class: - * \code - * regvalue = CRegStdWORD("Software\\Company\\SubKey\\MyValue", 100); - * \endcode - * this will set the registry value "MyValue" under HKEY_CURRENT_USER with path - * "Software\Company\SubKey" to the variable. If the key does not yet exist or - * an error occured during read from the registry, a default - * value of 100 is used when accessing the variable. - * now the variable can be used like any other DWORD variable: - * \code - * regvalue = 200; //stores the value 200 in the registry - * int temp = regvalue + 300; //temp has value 500 now - * regvalue += 300; //now the registry has the value 500 too - * \endcode - * to avoid too much access to the registry the value is cached inside the object. - * once the value is read, no more read accesses to the registry will be made. - * this means the variable will contain a wrong value if the corresponding registry - * entry is changed by anything else than this variable! If you think that could happen - * then use - * \code - * regvalue.read(); - * \endcode - * to force a refresh of the variable with the registry. - * a write to the registry is only made if the new value assigned with the variable - * is different than the last assigned value. - * to force a write use the method write(); - * another option to force reads and writes to the registry is to specify TRUE as the - * third parameter in the constructor. - * - * \par requirements - * win98 or later, win2k or later, win95 with IE4 or later, winNT4 with IE4 or later - * import library Shlwapi.lib - * - * \author Stefan Kueng - * - * \par license - * This code is absolutely free to use and modify. The code is provided "as is" with - * no expressed or implied warranty. The author accepts no liability if it causes - * any damage to your computer, causes your pet to fall ill, increases baldness - * or makes your car start emitting strange noises when you start it up. - * This code has no bugs, just undocumented features! - * - * \version 1.0 - * \date 11-2002 - * \todo - * \bug - * \warning - * - */ -class CRegStdWORD : public CRegStdBase -{ -public: - CRegStdWORD(); - /** - * Constructor. - * \param key the path to the key, including the key. example: "Software\\Company\\SubKey\\MyValue" - * \param def the default value used when the key does not exist or a read error occured - * \param force set to TRUE if no cache should be used, i.e. always read and write directly from/to registry - * \param base a predefined base key like HKEY_LOCAL_MACHINE. see the SDK documentation for more information. - */ - CRegStdWORD(stdstring key, DWORD def = 0, BOOL force = FALSE, HKEY base = HKEY_CURRENT_USER); - ~CRegStdWORD(void); - - DWORD read(); ///< reads the value from the registry - void write(); ///< writes the value to the registry - - operator DWORD(); - CRegStdWORD& operator=(DWORD d); - CRegStdWORD& operator+=(DWORD d) { return *this = *this + d;} - CRegStdWORD& operator-=(DWORD d) { return *this = *this - d;} - CRegStdWORD& operator*=(DWORD d) { return *this = *this * d;} - CRegStdWORD& operator/=(DWORD d) { return *this = *this / d;} - CRegStdWORD& operator%=(DWORD d) { return *this = *this % d;} - CRegStdWORD& operator<<=(DWORD d) { return *this = *this << d;} - CRegStdWORD& operator>>=(DWORD d) { return *this = *this >> d;} - CRegStdWORD& operator&=(DWORD d) { return *this = *this & d;} - CRegStdWORD& operator|=(DWORD d) { return *this = *this | d;} - CRegStdWORD& operator^=(DWORD d) { return *this = *this ^ d;} - - -protected: - - DWORD m_value; ///< the cached value of the registry - DWORD m_defaultvalue; ///< the default value to use - BOOL m_read; ///< indicates if the value has already been read from the registry - BOOL m_force; ///< indicates if no cache should be used, i.e. always read and write directly from registry -}; - diff --git a/source/SettingsDlg.cpp b/source/SettingsDlg.cpp deleted file mode 100644 index d937bcf..0000000 --- a/source/SettingsDlg.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// SettingsDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "SettingsDlg.h" -#include ".\settingsdlg.h" - -#include "FolderDlg.h" -#include "JPEGsnoop.h" -#include "SnoopConfig.h" - - -// CSettingsDlg dialog - -IMPLEMENT_DYNAMIC(CSettingsDlg, CDialog) -CSettingsDlg::CSettingsDlg(CWnd* pParent /*=NULL*/) - : CDialog(CSettingsDlg::IDD, pParent) - , m_strDbDir(_T("")) - , m_bUpdateAuto(FALSE) - , m_bReprocessAuto(FALSE) - , m_nUpdateChkDays(0) - , m_bDbSubmitNet(FALSE) - , m_nRptErrMaxScanDecode(0) -{ -} - -CSettingsDlg::~CSettingsDlg() -{ -} - -void CSettingsDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Text(pDX, IDC_DB_DIR, m_strDbDir); - DDX_Check(pDX, IDC_UPDATE_CHK, m_bUpdateAuto); - DDX_Check(pDX, IDC_REPROCESS_AUTO, m_bReprocessAuto); - DDX_Text(pDX, IDC_UPDATE_CHK_DAYS, m_nUpdateChkDays); - DDV_MinMaxUInt(pDX, m_nUpdateChkDays, 1, 365); - DDX_Check(pDX, IDC_DBSUBMIT_NET, m_bDbSubmitNet); - DDX_Text(pDX, IDC_RPTERRMAX_SCANDECODE, m_nRptErrMaxScanDecode); -} - - -BEGIN_MESSAGE_MAP(CSettingsDlg, CDialog) - ON_BN_CLICKED(IDC_DB_DIR_BROWSE, OnBnClickedDbDirBrowse) - ON_BN_CLICKED(IDC_DB_DIR_DEFAULT, OnBnClickedDbDirDefault) - ON_BN_CLICKED(IDC_COACH_RESET, OnBnClickedCoachReset) -END_MESSAGE_MAP() - - -// CSettingsDlg message handlers - -void CSettingsDlg::OnBnClickedDbDirBrowse() -{ - // TODO: Add your control notification handler code here - - CString strDir; - strDir = SelectFolder(_T("Please select folder for User Database")); - if (strDir == _T("")) { - // User cancelled - } else { - m_strDbDir = strDir; - UpdateData(false); - } -} - -CString CSettingsDlg::SelectFolder(const CString& strMessage) -{ - CString Result; - - BROWSEINFO BrowseInfo; - memset(&BrowseInfo, 0, sizeof(BrowseInfo)); - - TCHAR szBuffer[MAX_PATH]; - - szBuffer[0] = '\0'; // Start as null-terminated - - BrowseInfo.hwndOwner = m_hWnd; - BrowseInfo.pszDisplayName = szBuffer; - BrowseInfo.lpszTitle = strMessage; - BrowseInfo.ulFlags = BIF_RETURNONLYFSDIRS; - - // Throw display dialog - LPITEMIDLIST pList = SHBrowseForFolder(&BrowseInfo); - ASSERT(_tcslen(szBuffer) < sizeof(szBuffer)); - - if (pList != NULL) - { - // Convert from MIDLISt to real string path - SHGetPathFromIDList(pList, szBuffer); - Result = szBuffer; - - // Global pointer to the shell's IMalloc interface. - LPMALLOC pMalloc; - - // Get the shell's allocator and free the PIDL returned by - // SHBrowseForFolder. - if (SUCCEEDED(SHGetMalloc(&pMalloc))) - pMalloc->Free(pList); - } - - return Result; -} - -LPITEMIDLIST CSettingsDlg::ConvertPathToLpItemIdList(const char *pszPath) -{ - LPITEMIDLIST pidl = NULL; - LPSHELLFOLDER pDesktopFolder; - OLECHAR olePath[MAX_PATH]; - ULONG* pchEaten = NULL; - ULONG dwAttributes = 0; - HRESULT hr; - - if (SUCCEEDED(SHGetDesktopFolder(&pDesktopFolder))) - { - MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszPath, -1, olePath, MAX_PATH); - hr = pDesktopFolder->ParseDisplayName(NULL,NULL,olePath,pchEaten, &pidl,&dwAttributes); - pDesktopFolder->Release(); - } - return pidl; -} - -void CSettingsDlg::OnBnClickedDbDirDefault() -{ - CJPEGsnoopApp* pApp; - pApp = (CJPEGsnoopApp*)AfxGetApp(); - m_strDbDir = pApp->m_pAppConfig->GetDefaultDbDir(); - UpdateData(false); -} - -void CSettingsDlg::OnBnClickedCoachReset() -{ - CJPEGsnoopApp* pApp; - pApp = (CJPEGsnoopApp*)AfxGetApp(); - pApp->m_pAppConfig->CoachReset(); -} diff --git a/source/SettingsDlg.h b/source/SettingsDlg.h deleted file mode 100644 index ee8f2b6..0000000 --- a/source/SettingsDlg.h +++ /dev/null @@ -1,60 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box for the application settings -// -// ========================================================================== - - -#pragma once - - -// CSettingsDlg dialog - -class CSettingsDlg : public CDialog -{ - DECLARE_DYNAMIC(CSettingsDlg) - -public: - CSettingsDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CSettingsDlg(); - -// Dialog Data - enum { IDD = IDD_SETTINGSDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -private: - afx_msg void OnBnClickedDbDirBrowse(); - CString SelectFolder(const CString& strMessage); - LPITEMIDLIST ConvertPathToLpItemIdList(const char *pszPath); - afx_msg void OnBnClickedDbDirDefault(); - afx_msg void OnBnClickedCoachReset(); - -public: - CString m_strDbDir; - BOOL m_bUpdateAuto; - UINT m_nUpdateChkDays; - BOOL m_bReprocessAuto; - BOOL m_bDbSubmitNet; - UINT m_nRptErrMaxScanDecode; -}; diff --git a/source/SnoopConfig.cpp b/source/SnoopConfig.cpp index e9831bd..0e06d85 100644 --- a/source/SnoopConfig.cpp +++ b/source/SnoopConfig.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -16,21 +16,23 @@ // along with this program. If not, see . // +#include #include #include +#include +#include +#include "eula.h" #include "JfifDecode.h" -#include "JPEGsnoop.h" -//#include "JPEGsnoopCore.h" +#include "note.h" #include "snoop.h" #include "SnoopConfig.h" +//----------------------------------------------------------------------------- // Define the defaults for the application configuration -CSnoopConfig::CSnoopConfig(CjfifDecode *pJfifDec) +CSnoopConfig::CSnoopConfig(QObject *_parent) : QObject(_parent) { - m_pJfifDec = pJfifDec; - // Debug log strDebugLogFname = ".\\JPEGsnoop-debug.log"; fpDebugLog = NULL; @@ -99,41 +101,20 @@ CSnoopConfig::CSnoopConfig(CjfifDecode *pJfifDec) // Reset coach message flags CoachReset(); + strReprocess = "You have changed a processing option. To see these changes, you need to Reprocess the file or enable [Auto Reprocessing] in Configuration."; + // Reset the current filename strCurFname = ""; - // -------------------------------- - - // Determine operating system - // Particularly for: WinHTTP functions -// OSVERSIONINFO osvi; - -// ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); -// osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - -// GetVersionEx(&osvi); - -// bIsWindowsNTorLater = (osvi.dwPlatformId >= VER_PLATFORM_WIN32_NT); - -// bIsWindowsXPorLater = -// ( (osvi.dwMajorVersion > 5) || -// ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1) )); - - /* - // Debug code to output the version info - QString strTmp; - strTmp.Format("OS Version: Platform=[%u] VerMajor=[%u] VerMinor=[%u] (>=NT:%s >=XP:%s)", - osvi.dwPlatformId,osvi.dwMajorVersion,osvi.dwMinorVersion, - (bIsWindowsNTorLater)?"Y":"N",(bIsWindowsXPorLater)?"Y":"N"); - AfxMessageBox(strTmp); - */ qDebug() << "CSnoopConfig::CSnoopConfig End"; } +//----------------------------------------------------------------------------- CSnoopConfig::~CSnoopConfig(void) { } +//----------------------------------------------------------------------------- // This is generally called after app initializes and registry has just been loaded. void CSnoopConfig::UseDefaults() { @@ -141,6 +122,7 @@ void CSnoopConfig::UseDefaults() // But some need copying over } +//----------------------------------------------------------------------------- // Update the flag to mark the configuration as dirty / modified // - This is used later to indicate that a resave is required // @@ -149,6 +131,7 @@ void CSnoopConfig::Dirty(bool mode) bDirty = mode; } +//----------------------------------------------------------------------------- // Fetch all configuration values from the registry void CSnoopConfig::RegistryLoad() { @@ -160,7 +143,15 @@ void CSnoopConfig::RegistryLoad() if(regUserDbPath == "") { // None specified, so determine a suitable default -// strDbDir = GetDefaultDbDir(); + strDbDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + + QDir appDir(strDbDir); + + if(!appDir.exists()) + { + appDir.mkpath(strDbDir); + } + bDirty = true; } else @@ -169,10 +160,7 @@ void CSnoopConfig::RegistryLoad() strDbDir = regUserDbPath; } - ////////////////// - QString strCurDate = QDateTime::currentDateTime().toString("yyyymmdd"); - QString regUpdateLastChk = settings.value("General\\UpdateLastChk", "").toString(); // Try to load the registry entry @@ -221,7 +209,28 @@ void CSnoopConfig::RegistryLoad() docImageDirty(); } + bEulaAccepted = false; + + if(!bEulaAccepted) + { + Q_Eula *eulaDlg = new Q_Eula; + eulaDlg->exec(); + + if(eulaDlg->result()) + { + bEulaAccepted = true; + bUpdateAuto = eulaDlg->updateStatus(); + bDirty = true; + RegistryStore(); + } + else + { + exit(1); + } + } + printSettings(); + // Deprecated Registry strings // FIXME: Later on, decide if we should delete deprecated strings if found // "General\\ScanImgDec" @@ -230,6 +239,7 @@ void CSnoopConfig::RegistryLoad() // "General\\SigSearchAuto" } +//----------------------------------------------------------------------------- // Write all configuration parameters to the registry // - Skip write if no changes were made (!bDirty) // @@ -272,10 +282,10 @@ void CSnoopConfig::RegistryStore() // Registry entries are no longer dirty bDirty = false; - qDebug() << settings.status(); } } +//----------------------------------------------------------------------------- void CSnoopConfig::printSettings() { qDebug() << "strDbDir" << strDbDir; @@ -308,6 +318,8 @@ void CSnoopConfig::printSettings() qDebug() << "bCoachDecodeIdct" << bCoachDecodeIdct; } + +//----------------------------------------------------------------------------- // Reset coach messages void CSnoopConfig::CoachReset() { @@ -318,9 +330,10 @@ void CSnoopConfig::CoachReset() Dirty(); } +//----------------------------------------------------------------------------- // Select a suitable working directory, create it if it doesn't already exist -QString CSnoopConfig::GetDefaultDbDir() -{ +//QString CSnoopConfig::GetDefaultDbDir() +//{ /* TCHAR szUserProfile[MAX_PATH]; TCHAR szFilePath[MAX_PATH]; @@ -388,7 +401,7 @@ QString CSnoopConfig::GetDefaultDbDir() } } return szFilePath; */ -} +//} // Get the directory path of the JPEGsnoop executable // - This is used as a default location for the user signature database @@ -538,8 +551,6 @@ bool CSnoopConfig::DebugLogCreate() // bool CSnoopConfig::DebugLogAdd(QString strText) { - qDebug() << strText; - #ifdef DEBUG_LOG_OUT if(!bDebugLogEnable) @@ -614,11 +625,38 @@ bool CSnoopConfig::DebugLogAdd(QString strText) return true; } +//----------------------------------------------------------------------------- + void CSnoopConfig::docImageDirty() { - m_pJfifDec->ImgSrcChanged(); + emit ImgSrcChanged(); +} + +//----------------------------------------------------------------------------- +// If Automatic Reprocessing is enabled, reprocess the file +// - If Reprocessing is not enabled and the coach message has +// not been disabled, inform user of option to enable +void CSnoopConfig::HandleAutoReprocess() +{ + if(bReprocessAuto) + { + emit reprocess(); + } + else + { + if(bCoachReprocessAuto) + { + // Show the coaching dialog + Q_Note *note = new Q_Note(strReprocess); + note->exec(); + bCoachReprocessAuto = !note->hideStatus(); + Dirty(); + } + } } +//----------------------------------------------------------------------------- + void CSnoopConfig::onOptionsDhtexpand() { if(bOutputDHTexpand) @@ -631,9 +669,11 @@ void CSnoopConfig::onOptionsDhtexpand() } Dirty(); -// HandleAutoReprocess(); + HandleAutoReprocess(); } +//----------------------------------------------------------------------------- + void CSnoopConfig::onOptionsMakernotes() { if(bOutputDHTexpand) @@ -646,9 +686,11 @@ void CSnoopConfig::onOptionsMakernotes() } Dirty(); -// HandleAutoReprocess(); + HandleAutoReprocess(); } +//----------------------------------------------------------------------------- + void CSnoopConfig::onOptionsHideuknownexiftags() { if(bExifHideUnknown) @@ -661,10 +703,11 @@ void CSnoopConfig::onOptionsHideuknownexiftags() } Dirty(); - -// HandleAutoReprocess(); + HandleAutoReprocess(); } +//----------------------------------------------------------------------------- + void CSnoopConfig::onOptionsSignaturesearch() { if(bSigSearch) @@ -677,9 +720,11 @@ void CSnoopConfig::onOptionsSignaturesearch() } Dirty(); -// HandleAutoReprocess(); + HandleAutoReprocess(); } +//----------------------------------------------------------------------------- + void CSnoopConfig::onOptionsRelaxedparsing() { if(bRelaxedParsing) @@ -692,9 +737,11 @@ void CSnoopConfig::onOptionsRelaxedparsing() } Dirty(); -// HandleAutoReprocess(); + HandleAutoReprocess(); } +//----------------------------------------------------------------------------- + void CSnoopConfig::onScansegmentDecodeImage() { if(bDecodeScanImg) @@ -707,9 +754,11 @@ void CSnoopConfig::onScansegmentDecodeImage() } Dirty(); -// HandleAutoReprocess(); + HandleAutoReprocess(); } +//----------------------------------------------------------------------------- + void CSnoopConfig::onScansegmentNoidct() { if(bDecodeScanImgAc) @@ -717,13 +766,14 @@ void CSnoopConfig::onScansegmentNoidct() bDecodeScanImgAc = false; } - qDebug() << "CSnoopConfig::onScansegmentNoidct()" << bDecodeScanImgAc; + emit scanImageAc(bDecodeScanImgAc); Dirty(); - docImageDirty(); -// HandleAutoReprocess(); + HandleAutoReprocess(); } +//----------------------------------------------------------------------------- + void CSnoopConfig::onScansegmentFullidct() { if(!bDecodeScanImgAc) @@ -731,13 +781,14 @@ void CSnoopConfig::onScansegmentFullidct() bDecodeScanImgAc = true; } - qDebug() << "CSnoopConfig::onScansegmentFullidct()" << bDecodeScanImgAc; + emit scanImageAc(bDecodeScanImgAc); Dirty(); - docImageDirty(); -// HandleAutoReprocess(); + HandleAutoReprocess(); } +//----------------------------------------------------------------------------- + void CSnoopConfig::onScansegmentHistogram() { if(bHistoEn) @@ -752,9 +803,11 @@ void CSnoopConfig::onScansegmentHistogram() Dirty(); docImageDirty(); -// HandleAutoReprocess(); + HandleAutoReprocess(); } +//----------------------------------------------------------------------------- + void CSnoopConfig::onScansegmentHistogramy() { if(bDumpHistoY) @@ -769,9 +822,11 @@ void CSnoopConfig::onScansegmentHistogramy() Dirty(); docImageDirty(); -// HandleAutoReprocess(); + HandleAutoReprocess(); } +//----------------------------------------------------------------------------- + void CSnoopConfig::onScansegmentDump() { if(bOutputScanDump) @@ -784,6 +839,5 @@ void CSnoopConfig::onScansegmentDump() } Dirty(); - -// HandleAutoReprocess(); + HandleAutoReprocess(); } diff --git a/source/SnoopConfig.h b/source/SnoopConfig.h index ae66580..17dc6ff 100644 --- a/source/SnoopConfig.h +++ b/source/SnoopConfig.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -39,7 +39,7 @@ class CSnoopConfig : public QObject Q_OBJECT public: - CSnoopConfig(CjfifDecode *pJfifDec); + CSnoopConfig(QObject *_parent = 0); ~CSnoopConfig(void); void UseDefaults(); @@ -51,20 +51,85 @@ class CSnoopConfig : public QObject void CoachReset(); // Reset all coach messages - QString GetDefaultDbDir(); // Public use by CSettingsDlg +// QString GetDefaultDbDir(); // Public use by CSettingsDlg + // Getter functions QString dbPath() { return strDbDir; } + int32_t autoUpdateDays() { return nUpdateAutoDays; } int32_t maxDecodeError() { return nErrMaxDecodeScan; } - bool swUpdateEnabled() { return bUpdateAuto; } + + uint32_t startPos() { return nPosStart; } + bool autoReprocess() { return bReprocessAuto; } + bool clipStats() { return bStatClipEn; } + bool coachIdct() { return bCoachDecodeIdct; } bool dbSubmitNet() { return bDbSubmitNet; } + bool decodeAc() { return bDecodeScanImgAc; } + bool decodeImage() { return bDecodeScanImg; } + bool decodeMaker() { return bDecodeMaker; } + bool displayRgbHistogram() { return bHistoEn; } + bool displayYHistogram() { return bDumpHistoY; } + bool expandDht() { return bOutputDHTexpand; } + bool hideUnknownExif() { return bExifHideUnknown; } + bool interactive() { return bInteractive; } + bool relaxedParsing() { return bRelaxedParsing; } + bool scanDump() { return bOutputScanDump; } + bool searchSig() { return bSigSearch; } + bool submitDbNet() { return bDbSubmitNet; } + bool swUpdateEnabled() { return bUpdateAuto; } + + // Setter functions + void setDbPath(QString path) {strDbDir = path; } + void setAutoUpdate(bool b) { bUpdateAuto = b; } + void setUpdatePeriod(int32_t days) {nUpdateAutoDays = days; } + void setAutoReprocess(bool b) { bReprocessAuto = b; } + void setOnlineDb(bool b) { bDbSubmitNet = b; } + void setMaxErrors(int32_t errors) { nErrMaxDecodeScan = errors; } + void setStartPos(uint32_t start) { nPosStart = start; } + void setCoachIdct(bool b) { bCoachDecodeIdct = b; } // Debug Log // - Used if DEBUG_LOG_OUT bool DebugLogCreate(); bool DebugLogAdd(QString strText); + // Temporary status (not saved) + QString strCurFname; // Current filename (Debug use only) + + // TODO Move tp commandline processing + teOffsetMode eCmdLineOffset; // Offset operating mode + unsigned long nCmdLineOffsetPos; // File offset for DEC_OFFSET_POS mode + +signals: + void ImgSrcChanged(); + void scanImageAc(bool); + void reprocess(); + +public slots: + void onOptionsDhtexpand(); + void onOptionsMakernotes(); + void onScansegmentDecodeImage(); + void onOptionsHideuknownexiftags(); + void onOptionsRelaxedparsing(); + void onOptionsSignaturesearch(); + void onScansegmentNoidct(); + void onScansegmentFullidct(); + void onScansegmentHistogram(); + void onScansegmentHistogramy(); + void onScansegmentDump(); + +private: + CSnoopConfig &operator = (const CSnoopConfig&); + CSnoopConfig(CSnoopConfig&); + + QString GetExeDir(); + void CreateDir(QString Path); + void docImageDirty(); + void HandleAutoReprocess(); + + CjfifDecode *m_pJfifDec; + // Interactive mode: shows message dialog box alerts // In non-interactive mode we suppress most alert dialogs but still // show them in certain circumstances: @@ -89,9 +154,6 @@ class CSnoopConfig : public QObject bool bCmdLineDoneMsg; // Indicate to user when command-line operations complete? - teOffsetMode eCmdLineOffset; // Offset operating mode - unsigned long nCmdLineOffsetPos; // File offset for DEC_OFFSET_POS mode - bool bCmdLineHelp; // Show command list unsigned nPosStart; // Starting decode file offset @@ -107,7 +169,6 @@ class CSnoopConfig : public QObject QString strBatchLastOutput; // Last batch process output directory QString strBatchExtensions; // Extension list for batch processing (eg. ".jpg,.jpeg") - int nUpdateAutoDays; // How many days between checks int nErrMaxDecodeScan; // Max # errs to show in scan decode @@ -130,42 +191,17 @@ class CSnoopConfig : public QObject bool bCoachReprocessAuto; // Coach msg: Need to reprocess or change to auto bool bCoachDecodeIdct; // Coach msg: Warn about slow AC decode / lowres DC + // Coach Message + QString strReprocess; + // Extra config (not in registry) bool bDecodeColorConvert; // Do we do color convert after scan decode? - // Temporary status (not saved) - QString strCurFname; // Current filename (Debug use only) - // Debug log // - Used if DEBUG_LOG_OUT bool bDebugLogEnable; QString strDebugLogFname; QTextStream *fpDebugLog; - -public slots: - void onOptionsDhtexpand(); - void onOptionsMakernotes(); - void onScansegmentDecodeImage(); - void onOptionsHideuknownexiftags(); - void onOptionsRelaxedparsing(); - void onOptionsSignaturesearch(); - void onScansegmentNoidct(); - void onScansegmentFullidct(); - void onScansegmentHistogram(); - void onScansegmentHistogramy(); - void onScansegmentDump(); - -private: - CSnoopConfig &operator = (const CSnoopConfig&); - CSnoopConfig(CSnoopConfig&); - - QString GetExeDir(); - void CreateDir(QString Path); - void docImageDirty(); - -// QSettings settings; - - CjfifDecode *m_pJfifDec; }; #endif diff --git a/source/TermsDlg.cpp b/source/TermsDlg.cpp deleted file mode 100644 index c52b862..0000000 --- a/source/TermsDlg.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// TermsDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "TermsDlg.h" -#include ".\termsdlg.h" - - -// CTermsDlg dialog - -IMPLEMENT_DYNAMIC(CTermsDlg, CDialog) -CTermsDlg::CTermsDlg(CWnd* pParent /*=NULL*/) - : CDialog(CTermsDlg::IDD, pParent) - , strEula(_T("")) - , bEulaOk(FALSE) - , bUpdateAuto(FALSE) -{ - bEulaOk = false; - bUpdateAuto = true; - - - // Present the user with the GPLv2 license - // - This is done primarily to inform the user of their rights and - // freedoms while reminding them that there are no warranties or - // guarantees supplied with the free software per GPLv2. - - strEula = _T(""); - strEula += _T("JPEGsnoop\r\n"); - strEula += _T("Copyright (C) 2018 Calvin Hass\r\n"); - strEula += _T("\r\n"); - strEula += _T("This program is free software; you can redistribute it and/or modify\r\n"); - strEula += _T("it under the terms of the GNU General Public License as published by\r\n"); - strEula += _T("the Free Software Foundation; either version 2 of the License, or\r\n"); - strEula += _T("(at your option) any later version.\r\n"); - strEula += _T("\r\n"); - strEula += _T("This program is distributed in the hope that it will be useful,\r\n"); - strEula += _T("but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n"); - strEula += _T("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r\n"); - strEula += _T("GNU General Public License for more details.\r\n"); - strEula += _T("\r\n"); - strEula += _T("You should have received a copy of the GNU General Public License\r\n"); - strEula += _T("along with this program. If not, see .\r\n"); - -} - -CTermsDlg::~CTermsDlg() -{ -} - -void CTermsDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Text(pDX, IDC_EULA, strEula); - DDX_Check(pDX, IDC_EULA_OK, bEulaOk); - DDX_Check(pDX, IDC_UPDATE_AUTO, bUpdateAuto); -} - - -BEGIN_MESSAGE_MAP(CTermsDlg, CDialog) - ON_BN_CLICKED(IDOK, OnBnClickedOk) -END_MESSAGE_MAP() - - -// CTermsDlg message handlers - -void CTermsDlg::OnBnClickedOk() -{ - // TODO: Add your control notification handler code here - UpdateData(true); - if (bEulaOk) { - OnOK(); - } else { - AfxMessageBox(_T("You need to agree to the terms or else click EXIT")); - } -} - diff --git a/source/TermsDlg.h b/source/TermsDlg.h deleted file mode 100644 index 7f5cc2c..0000000 --- a/source/TermsDlg.h +++ /dev/null @@ -1,56 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box for the terms & conditions (EULA) -// - This dialog must be agreed to before application can be used -// -// ========================================================================== - - -#pragma once - - -// CTermsDlg dialog - -class CTermsDlg : public CDialog -{ - DECLARE_DYNAMIC(CTermsDlg) - -public: - CTermsDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CTermsDlg(); - -// Dialog Data - enum { IDD = IDD_TERMSDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -private: - afx_msg void OnBnClickedOk(); - -private: - CString strEula; -public: - BOOL bEulaOk; - BOOL bUpdateAuto; - -}; diff --git a/source/UpdateAvailDlg.cpp b/source/UpdateAvailDlg.cpp deleted file mode 100644 index 49b9e93..0000000 --- a/source/UpdateAvailDlg.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// UpdateAvailDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "JPEGsnoop.h" -#include "UpdateAvailDlg.h" -#include ".\updateavaildlg.h" - - -// CUpdateAvailDlg dialog - -IMPLEMENT_DYNAMIC(CUpdateAvailDlg, CDialog) -CUpdateAvailDlg::CUpdateAvailDlg(CWnd* pParent /*=NULL*/) - : CDialog(CUpdateAvailDlg::IDD, pParent) - , strVerCur(_T("")) - , strVerLatest(_T("")) - , bUpdateAutoStill(FALSE) - , strDateLatest(_T("")) -{ -} - -CUpdateAvailDlg::~CUpdateAvailDlg() -{ -} - -void CUpdateAvailDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Text(pDX, IDC_VER_CUR, strVerCur); - DDX_Text(pDX, IDC_VER_LATEST, strVerLatest); - DDX_Check(pDX, IDC_UPDATE_AUTO_STILL, bUpdateAutoStill); - DDX_Text(pDX, IDC_DATE_LATEST, strDateLatest); -} - - -BEGIN_MESSAGE_MAP(CUpdateAvailDlg, CDialog) - ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1) -END_MESSAGE_MAP() - - -// CUpdateAvailDlg message handlers - -void CUpdateAvailDlg::OnBnClickedButton1() -{ - // Open website - ShellExecute(0, _T("open"), IA_UPDATES_DL_PAGE, 0, 0, SW_SHOWNORMAL); -} diff --git a/source/UpdateAvailDlg.h b/source/UpdateAvailDlg.h deleted file mode 100644 index 8247b8c..0000000 --- a/source/UpdateAvailDlg.h +++ /dev/null @@ -1,54 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ========================================================================== -// CLASS DESCRIPTION: -// - Dialog box alerting user of new application updates available -// -// ========================================================================== - - -#pragma once - - -// CUpdateAvailDlg dialog - -class CUpdateAvailDlg : public CDialog -{ - DECLARE_DYNAMIC(CUpdateAvailDlg) - -public: - CUpdateAvailDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CUpdateAvailDlg(); - -// Dialog Data - enum { IDD = IDD_UPDATEAVAILDLG }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - DECLARE_MESSAGE_MAP() -private: - afx_msg void OnBnClickedButton1(); - -public: - CString strVerCur; - CString strVerLatest; - BOOL bUpdateAutoStill; - CString strDateLatest; -}; diff --git a/source/Viewer.cpp b/source/Viewer.cpp new file mode 100644 index 0000000..e41d0ab --- /dev/null +++ b/source/Viewer.cpp @@ -0,0 +1,224 @@ +#include +#include + +#include "ImgDecode.h" +#include "labelClick.h" +#include "SnoopConfig.h" + +#include "Viewer.h" + +Q_Viewer::Q_Viewer(CSnoopConfig *pAppConfig, CimgDecode *pImgDecoder, QWidget *_parent, Qt::WindowFlags f) : + QWidget(_parent, f), m_pAppConfig(pAppConfig), imageLabel(0), scrollArea(0), m_pImgDecoder(pImgDecoder), scaleFactor(0.125), m_nZoomMode(PRV_ZOOM_12) +{ + setGeometry(200, 50, 400, 400); + + QFont font("Courier", 12); + + statusBar = new QStatusBar(this); + + mcuLabel = new QLabel(statusBar); + mcuLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); + mcuLabel->setFont(font); + statusBar->addPermanentWidget(mcuLabel); + + fileLabel = new QLabel(statusBar); + fileLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); + fileLabel->setFont(font); + statusBar->addPermanentWidget(fileLabel); + + yccLabel = new QLabel(statusBar); + yccLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken); + yccLabel->setFont(font); + statusBar->addPermanentWidget(yccLabel); + + imageLabel = new labelClick; + imageLabel->setMouseTracking(true); + imageLabel->setBackgroundRole(QPalette::Base); + imageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + imageLabel->setScaledContents(true); + + scrollArea = new QScrollArea(this); + scrollArea->setBackgroundRole(QPalette::Dark); + scrollArea->setWidgetResizable(true); + scrollArea->setWidget(imageLabel); + scrollArea->setVisible(false); + + QGridLayout *loGrid = new QGridLayout(this); + loGrid->addWidget(scrollArea, 0, 0); + loGrid->addWidget(statusBar, 1, 0); + loGrid->setContentsMargins(0, 0, 0, 0); + setLayout(loGrid); + + m_strPreview = "RGB"; + setWindowTitle(m_strPreview + " " + m_strZoom); + m_strZoom = QString("@ %1%").arg(scaleFactor * 100.0); + + setVisible(false); + + connect(imageLabel, SIGNAL(released(QMouseEvent *)), this, SLOT(mouseReleased(QMouseEvent *))); + connect(imageLabel, SIGNAL(moved(QMouseEvent *)), this, SLOT(mouseMoved(QMouseEvent *))); + connect(m_pAppConfig, SIGNAL(scanImageAc(bool)), this, SLOT(scanImageAc(bool))); +} + +void Q_Viewer::mouseReleased(QMouseEvent *e) +{ + m_pImgDecoder->SetMarkerBlk(e->pos()); +} + +void Q_Viewer::mouseMoved(QMouseEvent *e) +{ + uint32_t nByte; + uint32_t nBit; + + int32_t nY; + int32_t nCb; + int32_t nCr; + + QPoint p; + p = m_pImgDecoder->PixelToMcu(e->pos()); + mcuLabel->setText(QString("MCU [%1,%2]") + .arg(p.x(), 4, 10, QChar('0')) + .arg(p.y(), 4, 10, QChar('0'))); + m_pImgDecoder->LookupFilePosMcu(e->pos(), nByte, nBit); + p = m_pImgDecoder->PixelToBlk(e->pos()); + m_pImgDecoder->LookupBlkYCC(e->pos(), nY, nCb, nCr); + fileLabel->setText(QString("File 0x%1:%2").arg(nByte, 8, 16, QChar('0')).arg(nBit)); + yccLabel->setText(QString("YCC DC=[%1,%2,%3]") + .arg(nY, 5, 10, QChar('0')) + .arg(nCb, 5, 10, QChar('0')) + .arg(nCr, 5, 10, QChar('0'))); +} + +void Q_Viewer::drawImage() +{ + qDebug() << "Q_Viewer::drawImage"; + setWindowTitle(m_strPreview + " " + m_strIdct + " " + m_strZoom); + imageLabel->setPixmap(QPixmap::fromImage((*m_pImgDecoder->m_pDibTemp).scaledToWidth(static_cast(m_pImgDecoder->m_pDibTemp->width() * scaleFactor)))); + scrollArea->setVisible(true); + setVisible(true); +} + +void Q_Viewer::zoom(QAction* action) +{ + if(action->data().toInt() == PRV_ZOOM_IN) + { + if(m_nZoomMode + 1 < PRV_ZOOMEND) + { + m_nZoomMode++; + + } + } + else if(action->data().toInt() == PRV_ZOOM_OUT) + { + if(m_nZoomMode - 1 > PRV_ZOOMBEGIN) + { + m_nZoomMode--; + } + } + else + { + m_nZoomMode = action->data().toInt(); + } + + switch(m_nZoomMode) + { + case PRV_ZOOM_12: + scaleFactor = 0.125; + break; + + case PRV_ZOOM_25: + scaleFactor = 0.25; + break; + + case PRV_ZOOM_50: + scaleFactor = 0.5; + break; + + case PRV_ZOOM_100: + scaleFactor = 1.0; + break; + + case PRV_ZOOM_150: + scaleFactor = 1.5; + break; + + case PRV_ZOOM_200: + scaleFactor = 2.0; + break; + + case PRV_ZOOM_300: + scaleFactor = 3.0; + break; + + case PRV_ZOOM_400: + scaleFactor = 4.0; + break; + + case PRV_ZOOM_800: + scaleFactor = 8.0; + break; + + default: + scaleFactor = 1.0; + break; + } + + drawImage(); + m_strZoom = QString("@ %1%").arg(scaleFactor * 100.0); +} + +void Q_Viewer::setPreviewTitle(QAction *action) +{ + switch(action->data().toInt()) + { + case PREVIEW_RGB: + m_strPreview += "RGB"; + break; + + case PREVIEW_YCC: + m_strPreview += "YCC"; + break; + + case PREVIEW_R: + m_strPreview += "R"; + break; + + case PREVIEW_G: + m_strPreview += "G"; + break; + + case PREVIEW_B: + m_strPreview += "B"; + break; + + case PREVIEW_Y: + m_strPreview += "Y"; + break; + + case PREVIEW_CB: + m_strPreview += "Cb"; + break; + + case PREVIEW_CR: + m_strPreview += "Cr"; + break; + + default: + m_strPreview += "???"; + break; + } +} + +void Q_Viewer::scanImageAc(bool b) +{ + qDebug() << "scanImageAc" << b; + + if(b) + { + m_strIdct = "DC+AC"; + } + else + { + m_strIdct = "DC"; + } +} diff --git a/source/Viewer.h b/source/Viewer.h new file mode 100644 index 0000000..21a1c6b --- /dev/null +++ b/source/Viewer.h @@ -0,0 +1,51 @@ +#ifndef Q_VIEWER_H +#define Q_VIEWER_H + +#include +#include +#include +#include + +#include "snoop.h" + +class CimgDecode; +class QLabel; +class labelClick; +class QScrollArea; +class QStatusBar; +class CSnoopConfig; + +class Q_Viewer : public QWidget +{ + Q_OBJECT +public: + explicit Q_Viewer(CSnoopConfig *pAppConfig, CimgDecode *pImgDecoder, QWidget *parent = nullptr, Qt::WindowFlags f = 0); + void drawImage(); + +public slots: + void mouseReleased(QMouseEvent *); + void mouseMoved(QMouseEvent *); + void zoom(QAction *action); + void setPreviewTitle(QAction *preview); + void scanImageAc(bool); + +private: + CSnoopConfig *m_pAppConfig; + CimgDecode *m_pImgDecoder; + + labelClick *imageLabel; + QScrollArea *scrollArea; + double scaleFactor; + int32_t m_nZoomMode; + + QString m_strPreview; + QString m_strZoom; + QString m_strIdct; + + QStatusBar *statusBar; + QLabel *mcuLabel; + QLabel *fileLabel; + QLabel *yccLabel; +}; + +#endif // Q_VIEWER_H diff --git a/source/WindowBuf.cpp b/source/WindowBuf.cpp index b8d07b7..962f670 100644 --- a/source/WindowBuf.cpp +++ b/source/WindowBuf.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -21,21 +21,12 @@ #include "WindowBuf.h" -// Reset the main state -// -void CwindowBuf::Reset() -{ - // File handling - m_bBufOK = false; // Initialize the buffer to not loaded yet - m_pBufFile = NULL; // No file open yet -} - // Constructor for WindowBuf class // - Allocates storage for the buffer // - Resets state // - Clears all buffer overlay bytes // -CwindowBuf::CwindowBuf() +CwindowBuf::CwindowBuf(CDocLog *pDocLog) : m_pDocLog(pDocLog) { m_pBuffer = new unsigned char[MAX_BUF]; @@ -84,6 +75,15 @@ CwindowBuf::~CwindowBuf() } } +// Reset the main state +// +void CwindowBuf::Reset() +{ + // File handling + m_bBufOK = false; // Initialize the buffer to not loaded yet + m_pBufFile = NULL; // No file open yet +} + // Accessor for m_bBufOk bool CwindowBuf::GetBufOk() { diff --git a/source/WindowBuf.h b/source/WindowBuf.h index a53a17f..103c398 100644 --- a/source/WindowBuf.h +++ b/source/WindowBuf.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -37,14 +37,15 @@ #include "DocLog.h" class QPlainTextEdit; +class CDocLog; // For now, we only ever use MAX_BUF_WINDOW bytes, even though we // have allocated MAX_BUF bytes up front. I might change this // later. We don't want the window size to be too large as it // could have an impact on performance. -#define MAX_BUF 262144L -#define MAX_BUF_WINDOW 131072L -#define MAX_BUF_WINDOW_REV 16384L //1024L +#define MAX_BUF 262144 +#define MAX_BUF_WINDOW 131072 +#define MAX_BUF_WINDOW_REV 16384 //1024L #define NUM_OVERLAYS 500 #define MAX_OVERLAY 500 // 500 bytes @@ -58,7 +59,7 @@ typedef struct bool bEn; // Enabled? -- not used currently uint32_t nStart; // File position uint32_t nLen; // MCU Length - quint8 anData[MAX_OVERLAY]; // Byte data + uint8_t anData[MAX_OVERLAY]; // Byte data // For reporting purposes: uint32_t nMcuX; // Starting MCU X @@ -73,7 +74,7 @@ typedef struct class CwindowBuf { public: - CwindowBuf(); + CwindowBuf(class CDocLog *pDocLog); ~CwindowBuf(); public: @@ -115,6 +116,8 @@ class CwindowBuf CwindowBuf &operator = (const CwindowBuf&); CwindowBuf(CwindowBuf&); + CDocLog *m_pDocLog; + unsigned char *m_pBuffer; QFile *m_pBufFile; uint32_t m_nBufWinSize; diff --git a/source/eula.cpp b/source/eula.cpp new file mode 100644 index 0000000..ba26ba8 --- /dev/null +++ b/source/eula.cpp @@ -0,0 +1,39 @@ +#include + +#include "eula.h" +#include "ui_eula.h" + +Q_Eula::Q_Eula(QWidget *parent) : QDialog(parent), ui(new Ui::Q_Eula) +{ + ui->setupUi(this); + + QFile eula(":/eula.txt"); + + eula.open(QFile::ReadOnly); + + ui->plainTextEdit->setPlainText(QString(eula.readAll())); + + connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(okClicked())); +} + +Q_Eula::~Q_Eula() +{ + delete ui; +} + +void Q_Eula::okClicked() +{ + if(!ui->cbAgreed->isChecked()) + { + QMessageBox::warning(this, "JPEGSnoop", "You need to agree to the terms or else click Cancel", QMessageBox::Ok); + } + else + { + done(1); + } +} + +bool Q_Eula::updateStatus() +{ + return ui->cbUpdate->isChecked(); +} diff --git a/source/eula.h b/source/eula.h new file mode 100644 index 0000000..03f457c --- /dev/null +++ b/source/eula.h @@ -0,0 +1,27 @@ +#ifndef EULA_H +#define EULA_H + +#include + +namespace Ui { +class Q_Eula; +} + +class Q_Eula : public QDialog +{ + Q_OBJECT + +public: + explicit Q_Eula(QWidget *parent = 0); + ~Q_Eula(); + + bool updateStatus(); + +private slots: + void okClicked(); + +private: + Ui::Q_Eula *ui; +}; + +#endif // EULA_H diff --git a/source/eula.ui b/source/eula.ui new file mode 100644 index 0000000..247450b --- /dev/null +++ b/source/eula.ui @@ -0,0 +1,134 @@ + + + Q_Eula + + + + 0 + 0 + 639 + 419 + + + + JPEGsnoop License Agreement + + + + + 540 + 10 + 81 + 71 + + + + Qt::Vertical + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + 20 + 20 + 520 + 16 + + + + Welcome to JPEGsnoop! + + + Qt::AlignCenter + + + + + + 10 + 50 + 520 + 261 + + + + Software Agreement: + + + + + 10 + 30 + 500 + 191 + + + + true + + + + + + 10 + 230 + 500 + 20 + + + + I have read and agree to the terms above + + + + + + + 10 + 320 + 520 + 91 + + + + Software Updates: + + + + + 10 + 30 + 500 + 41 + + + + Automatically check for updates +You can always change this option later in Configuration + + + + + + + + buttonBox + rejected() + Q_Eula + reject() + + + 566 + 80 + + + 286 + 274 + + + + + diff --git a/source/jpegsnoop.rc-1.5.2.japanese b/source/jpegsnoop.rc-1.5.2.japanese deleted file mode 100644 index bd9ee53..0000000 --- a/source/jpegsnoop.rc-1.5.2.japanese +++ /dev/null @@ -1,1079 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_JAPANESE, SUBLANG_NEUTRAL -#pragma code_page(932) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "//CAL! #define _AFX_NO_SPLITTER_RESOURCES\r\n" - "#define _AFX_NO_OLE_RESOURCES\r\n" - "#define _AFX_NO_TRACKER_RESOURCES\r\n" - "#define _AFX_NO_PROPERTY_RESOURCES\r\n" - "\r\n" - "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" - "LANGUAGE 9, 1\r\n" - "#pragma code_page(1252)\r\n" - "#include ""res\\JPEGsnoop.rc2"" // non-Microsoft Visual C++ edited resources\r\n" - "#include ""afxres.rc"" // Standard components\r\n" - "#include ""afxprint.rc"" // printing/print preview resources\r\n" - "#include ""afxolecl.rc"" // OLE container resources\r\n" - "#endif\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDR_MAINFRAME ICON "res\\jpegsnoop-prog-icon1-novista.ico" -IDR_JPEGsnoopTYPE ICON "res\\JPEGsnoopDoc.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Bitmap -// - -IDR_MAINFRAME BITMAP "res\\Toolbar.bmp" - -///////////////////////////////////////////////////////////////////////////// -// -// Toolbar -// - -IDR_MAINFRAME TOOLBAR 16, 15 -BEGIN - BUTTON ID_FILE_NEW - BUTTON ID_FILE_OPEN - BUTTON ID_FILE_SAVE_AS - SEPARATOR - BUTTON ID_EDIT_CUT - BUTTON ID_EDIT_COPY - BUTTON ID_EDIT_PASTE - SEPARATOR - BUTTON ID_FILE_PRINT - BUTTON ID_APP_ABOUT -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_MAINFRAME MENU -BEGIN - POPUP "ƒtƒ@ƒCƒ‹(&F)" - BEGIN - MENUITEM "ƒCƒ[ƒW‚ðŠJ‚­...(&O)\tCtrl+O", ID_FILE_OPEN - MENUITEM "ƒƒO‚Ì•Û‘¶...(&S)\tCtrl+S", ID_FILE_SAVE_AS - MENUITEM "ƒtƒ@ƒCƒ‹‚ðĈ—\tCtrl+R", ID_FILE_REPROCESS - MENUITEM "ƒoƒbƒ`ˆ—...", ID_FILE_BATCHPROCESS - MENUITEM SEPARATOR - MENUITEM "ƒIƒtƒZƒbƒg...", ID_FILE_OFFSET - MENUITEM SEPARATOR - MENUITEM "ˆóü...(&P)\tCtrl+P", ID_FILE_PRINT - MENUITEM "ˆóüƒvƒŒƒrƒ…[(&V)", ID_FILE_PRINT_PREVIEW - MENUITEM "ˆóü‚ÌÝ’è(&R)...", ID_FILE_PRINT_SETUP - MENUITEM SEPARATOR - MENUITEM "ŋߎg—p‚µ‚½ƒtƒ@ƒCƒ‹", ID_FILE_MRU_FILE1, GRAYED - MENUITEM SEPARATOR - MENUITEM "I—¹(&X)", ID_APP_EXIT - END - POPUP "•ÒW(&E)" - BEGIN - MENUITEM "Œ³‚É–ß‚·(&U)\tCtrl+Z", ID_EDIT_UNDO - MENUITEM SEPARATOR - MENUITEM "ƒRƒs[(&C)\tCtrl+C", ID_EDIT_COPY - MENUITEM "‚·‚ׂđI‘ð(&L)\tCtrl+A", ID_EDIT_SELECT_ALL - MENUITEM SEPARATOR - MENUITEM "ŒŸõ...(&F)\tCtrl+F", ID_EDIT_FIND - MENUITEM "ŽŸ‚ðŒŸõ(&I)\tF3", ID_EDIT_REPEAT - END - POPUP "•\Ž¦(&V)" - BEGIN - POPUP "‰æ‘œ‚̃`ƒƒƒ“ƒlƒ‹" - BEGIN - MENUITEM "RGB\tAlt+1", ID_PREVIEW_RGB - MENUITEM "YCC\tAlt+2", ID_PREVIEW_YCC - MENUITEM SEPARATOR - MENUITEM "R\tAlt+3", ID_PREVIEW_R - MENUITEM "G\tAlt+4", ID_PREVIEW_G - MENUITEM "B\tAlt+5", ID_PREVIEW_B - MENUITEM SEPARATOR - MENUITEM "Y (ƒOƒŒ[ƒXƒP[ƒ‹)\tAlt+6", ID_PREVIEW_Y - MENUITEM "Cb\tAlt+7", ID_PREVIEW_CB - MENUITEM "Cr\tAlt+8", ID_PREVIEW_CR - END - POPUP "ƒCƒ[ƒW‚̃Y[ƒ€" - BEGIN - MENUITEM "Šg‘å\tCtrl++", ID_IMAGEZOOM_ZOOMIN - MENUITEM "k¬\tCtrl+-", ID_IMAGEZOOM_ZOOMOUT - MENUITEM SEPARATOR - MENUITEM "12.5 %", ID_IMAGEZOOM_12 - MENUITEM "25 %", ID_IMAGEZOOM_25 - MENUITEM "50 %", ID_IMAGEZOOM_50 - MENUITEM "100 %", ID_IMAGEZOOM_100 - MENUITEM "150 %", ID_IMAGEZOOM_150 - MENUITEM "200 %", ID_IMAGEZOOM_200 - MENUITEM "300 %", ID_IMAGEZOOM_300 - MENUITEM "400 %", ID_IMAGEZOOM_400 - MENUITEM "800 %", ID_IMAGEZOOM_800 - END - POPUP "ƒI[ƒo[ƒŒƒC" - BEGIN - MENUITEM "MCU ƒOƒŠƒbƒh\tCtrl+G", ID_OVERLAYS_MCUGRID - END - MENUITEM "’²ß...", ID_VIEW_ADJUST - MENUITEM SEPARATOR - MENUITEM "ƒc[ƒ‹ ƒo[(&T)", ID_VIEW_TOOLBAR - MENUITEM "ƒXƒe[ƒ^ƒX ƒo[(&S)", ID_VIEW_STATUS_BAR - END - POPUP "ƒc[ƒ‹(&T)" - BEGIN - MENUITEM "‰æ‘œ‚Ì‘O•ûŒŸõ\tCtrl+2", ID_TOOLS_SEARCHFORWARD - MENUITEM "‰æ‘œ‚ÌŒã•ûŒŸõ\tCtrl+1", ID_TOOLS_SEARCHREVERSE - MENUITEM SEPARATOR - MENUITEM "MCU ƒIƒtƒZƒbƒg‚ÌŒŸõ...", ID_TOOLS_LOOKUPMCUOFFSET - MENUITEM "ƒtƒ@ƒCƒ‹ ƒI[ƒo[ƒŒƒC...", ID_TOOLS_FILEOVERLAY - MENUITEM "DQT ‚ÌŒŸõŽÀs‰Â”\ƒtƒ@ƒCƒ‹...", - ID_TOOLS_SEARCHEXECUTABLEFORDQT - - MENUITEM "JPEG ‚̃GƒNƒXƒ|[ƒg...", ID_TOOLS_EXTRACTEMBEDDEDJPEG - MENUITEM "TIFF ‚ɃGƒNƒXƒ|[ƒg...", ID_TOOLS_EXPORTTIFF - MENUITEM SEPARATOR - MENUITEM "DB ‚ɃJƒƒ‰/SW ‚̒ljÁ...\tAlt+S", ID_TOOLS_ADDCAMERATODB - MENUITEM "ƒ[ƒJƒ‹ DB ‚ÌŠÇ—...", ID_TOOLS_MANAGELOCALDB - END - POPUP "ƒIƒvƒVƒ‡ƒ“(&O)" - BEGIN - MENUITEM "DHT Šg’£", ID_OPTIONS_DHTEXPAND - MENUITEM "•s–¾‚È EXIF ƒ^ƒO‚ð”ñ•\Ž¦", ID_OPTIONS_HIDEUKNOWNEXIFTAGS - - MENUITEM "ƒ[ƒJ[ ƒm[ƒg", ID_OPTIONS_MAKERNOTES - MENUITEM "ƒVƒOƒlƒ`ƒƒ‚ÌŒŸõ", ID_OPTIONS_SIGNATURESEARCH - MENUITEM SEPARATOR - POPUP "ƒZƒOƒƒ“ƒg‚̃XƒLƒƒƒ“" - BEGIN - MENUITEM "ƒCƒ[ƒW‚̉ð“Ç", ID_SCANSEGMENT_DECODEIMAGE - - MENUITEM SEPARATOR - MENUITEM "Š®‘S IDCT (AC+DC - ’x‚¢)", ID_SCANSEGMENT_FULLIDCT - MENUITEM "IDCT ‚È‚µ (DC ‚Ì‚Ý - ‘¬‚¢)", ID_SCANSEGMENT_NOIDCT - MENUITEM SEPARATOR - MENUITEM "RGB ƒqƒXƒgƒOƒ‰ƒ€", ID_SCANSEGMENT_HISTOGRAM - MENUITEM "Y ƒqƒXƒgƒOƒ‰ƒ€", ID_SCANSEGMENT_HISTOGRAMY - - MENUITEM SEPARATOR - MENUITEM "ƒ_ƒ“ƒv", ID_SCANSEGMENT_DUMP - MENUITEM "Ú׉ð“Ç...", ID_SCANSEGMENT_DETAILEDDECODE - - END - MENUITEM SEPARATOR - MENUITEM "Ý’è...", ID_OPTIONS_CONFIGURATION - MENUITEM "XV‚ÌŠm”F...", ID_OPTIONS_CHECKFORUPDATES - END - POPUP "ƒwƒ‹ƒv(&H)" - BEGIN - MENUITEM "JPEGsnoop ‚ɂ‚¢‚Ä(&A)...", ID_APP_ABOUT - END -END - -IDR_CNTR_INPLACE MENU -BEGIN - POPUP "ƒtƒ@ƒCƒ‹(&F)" - BEGIN - MENUITEM "V‹K(&N)\tCtrl+N", ID_FILE_NEW - MENUITEM "ŠJ‚­...(&O)\tCtrl+O", ID_FILE_OPEN - MENUITEM "•Û‘¶(&S)\tCtrl+S", ID_FILE_SAVE - MENUITEM "–¼‘O‚ð•t‚¯‚Ä•Û‘¶(&A)...", ID_FILE_SAVE_AS - MENUITEM SEPARATOR - MENUITEM "ˆóü...(&P)\tCtrl+P", ID_FILE_PRINT - MENUITEM "ˆóüƒvƒŒƒrƒ…[(&V)", ID_FILE_PRINT_PREVIEW - MENUITEM "ˆóü‚ÌÝ’è(&R)...", ID_FILE_PRINT_SETUP - MENUITEM SEPARATOR - MENUITEM "ŋߎg—p‚µ‚½ƒtƒ@ƒCƒ‹", ID_FILE_MRU_FILE1, GRAYED - MENUITEM SEPARATOR - MENUITEM "I—¹(&X)", ID_APP_EXIT - END - MENUITEM SEPARATOR - MENUITEM SEPARATOR -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Accelerator -// - -IDR_MAINFRAME ACCELERATORS -BEGIN - VK_ESCAPE, ID_CANCEL_EDIT_CNTR, VIRTKEY, NOINVERT - "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT - VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT - VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT - "X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT - "F", ID_EDIT_FIND, VIRTKEY, CONTROL, NOINVERT - "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT - VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT - VK_F3, ID_EDIT_REPEAT, VIRTKEY, NOINVERT - "H", ID_EDIT_REPLACE, VIRTKEY, CONTROL, NOINVERT - "A", ID_EDIT_SELECT_ALL, VIRTKEY, CONTROL, NOINVERT - VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT - "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT - "N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT - "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT - "P", ID_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT - "R", ID_FILE_REPROCESS, VIRTKEY, CONTROL, NOINVERT - "S", ID_FILE_SAVE_AS, VIRTKEY, CONTROL, NOINVERT - VK_OEM_PLUS, ID_IMAGEZOOM_ZOOMIN, VIRTKEY, CONTROL, NOINVERT - VK_OEM_MINUS, ID_IMAGEZOOM_ZOOMOUT, VIRTKEY, CONTROL, NOINVERT - VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT - VK_RETURN, ID_OLE_EDIT_PROPERTIES, VIRTKEY, ALT, NOINVERT - "G", ID_OVERLAYS_MCUGRID, VIRTKEY, CONTROL, NOINVERT - VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT - "5", ID_PREVIEW_B, VIRTKEY, ALT, NOINVERT - "7", ID_PREVIEW_CB, VIRTKEY, ALT, NOINVERT - "8", ID_PREVIEW_CR, VIRTKEY, ALT, NOINVERT - "4", ID_PREVIEW_G, VIRTKEY, ALT, NOINVERT - "3", ID_PREVIEW_R, VIRTKEY, ALT, NOINVERT - "1", ID_PREVIEW_RGB, VIRTKEY, ALT, NOINVERT - "6", ID_PREVIEW_Y, VIRTKEY, ALT, NOINVERT - "2", ID_PREVIEW_YCC, VIRTKEY, ALT, NOINVERT - "2", ID_TOOLS_SEARCHFORWARD, VIRTKEY, CONTROL, NOINVERT - "1", ID_TOOLS_SEARCHREVERSE, VIRTKEY, CONTROL, NOINVERT -END - -IDR_CNTR_INPLACE ACCELERATORS -BEGIN - "N", ID_FILE_NEW, VIRTKEY, CONTROL - "O", ID_FILE_OPEN, VIRTKEY, CONTROL - "S", ID_FILE_SAVE, VIRTKEY, CONTROL - "P", ID_FILE_PRINT, VIRTKEY, CONTROL - VK_F6, ID_NEXT_PANE, VIRTKEY - VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT - VK_ESCAPE, ID_CANCEL_EDIT_CNTR, VIRTKEY, NOINVERT -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_ABOUTBOX DIALOGEX 0, 0, 242, 94 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "JPEGsnoop ‚ɂ‚¢‚Ä" -FONT 8, "MS Shell Dlg", 0, 0, 0x1 -BEGIN - ICON IDR_MAINFRAME,IDC_STATIC,12,6,20,20 - LTEXT "JPEGsnoop",IDC_STATIC,42,6,39,8,SS_NOPREFIX - LTEXT "Copyright c 2010 Calvin Hass",IDC_STATIC,42,18,124,8 - DEFPUSHBUTTON "OK",IDOK,185,7,50,16,WS_GROUP - LTEXT "www.impulseadventure.com/photo/",IDC_URL,24,66,117,8 - LTEXT "JPEGsnoop ‚̃hƒLƒ…ƒƒ“ƒg‚ÆXV",IDC_URL_DOC,24, - 48,169,8 - LTEXT "ƒo[ƒWƒ‡ƒ“",IDC_VER_NUM,96,6,86,10 - GROUPBOX "",IDC_STATIC,12,36,222,54 -END - -IDD_DBSUBMITDLG DIALOGEX 0, 0, 397, 180 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "ƒf[ƒ^ƒx[ƒX‚Öˆ³kƒVƒOƒlƒ`ƒƒ‚ð’ño" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,340,7,50,16 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,340,26,50,16 - EDITTEXT IDC_QUAL,258,12,66,14,ES_AUTOHSCROLL - CONTROL "ƒJƒƒ‰‚©‚ç’¼Ú",IDC_RADIO_CAM,"Button", - BS_AUTORADIOBUTTON | WS_GROUP,228,84,76,10 - CONTROL "ƒ\ƒtƒgƒEƒFƒA‚É‚æ‚Á‚Ä•ÒW / ˆ—‚³‚ê‚Ä‚¢‚é",IDC_RADIO_SW,"Button", - BS_AUTORADIOBUTTON,228,96,116,10 - EDITTEXT IDC_USER_SOFTWARE,276,108,108,14,ES_AUTOHSCROLL - CONTROL "‚Ç‚±‚©‚çŽæ“¾‚µ‚½‚©‚ç‚í‚©‚ç‚È‚¢", - IDC_RADIO_UNKNOWN,"Button",BS_AUTORADIOBUTTON,228,126, - 138,10 - EDITTEXT IDC_NOTES,126,150,138,14,ES_AUTOHSCROLL - EDITTEXT IDC_MAKE,78,12,96,14,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_MODEL,78,30,96,14,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_SOFTWARE,78,48,96,14,ES_AUTOHSCROLL | ES_READONLY - EDITTEXT IDC_SIG,48,72,150,14,ES_AUTOHSCROLL | ES_READONLY - LTEXT "—á. ƒX[ƒp[ƒtƒ@ƒCƒ“, •W€, 70, 10, ƒnƒC, ‚È‚ÇBƒ\ƒtƒgƒEƒFƒA‚Ìꇕۑ¶•iŽ¿‚ÌÝ’èB", - IDC_STATIC,198,30,125,17 - LTEXT "ƒJƒƒ‰ / ƒ\ƒtƒgƒEƒFƒA‚Ì•iŽ¿Ý’è:",IDC_STATIC,186,12, - 66,18 - LTEXT "ƒm[ƒg: OK ‚ðƒNƒŠƒbƒN‚·‚é‚ƈ³kƒVƒOƒlƒ`ƒƒ‚̓[ƒJƒ‹ ƒ†[ƒU[ ƒf[ƒ^ƒx[ƒX ƒtƒ@ƒCƒ‹‚Æ JPEGsnoop ‚ÌV‚µ‚¢ƒfƒWƒ^ƒ‹ ƒJƒƒ‰‚ÌØ–¾‚ÉŽg‚í‚ê‚é ImpulseAdventure ƒf[ƒ^ƒx[ƒX‚É‘—M‚³‚ê‚Ü‚·B", - IDC_STATIC,6,96,186,42 - LTEXT "EXIF ì¬:",IDC_STATIC,6,12,38,8 - LTEXT "EXIF ƒ‚ƒfƒ‹:",IDC_STATIC,6,30,40,8 - LTEXT "ƒVƒOƒlƒ`ƒƒ:",IDC_STATIC,6,72,42,8 - LTEXT "EXIF ƒ\ƒtƒgƒEƒFƒA:",IDC_STATIC,6,48,48,8 - LTEXT "ƒ\ƒtƒgƒEƒFƒA:",IDC_STATIC,240,108,31,8 - GROUPBOX "‚±‚̃tƒ@ƒCƒ‹‚Í:",IDC_STATIC,216,72,174,71 - LTEXT "ƒtƒ@ƒCƒ‹‚ɂ‚¢‚ĉ½‚©‘¼‚ÌŠo‚¦‘‚«:",IDC_STATIC,18,150,96, - 8 -END - -IDD_OVERLAYBUFDLG DIALOGEX 0, 0, 376, 138 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "ƒtƒ@ƒCƒ‹ ƒI[ƒo[ƒŒƒC‚̃eƒXƒg" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,318,6,50,16 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,318,25,50,16 - EDITTEXT IDC_OVRPOS,84,30,78,14,ES_AUTOHSCROLL - EDITTEXT IDC_OVRNEW,42,102,178,14,ES_AUTOHSCROLL - LTEXT "Œ»Ý’n",IDC_OVRCUR,42,60,318,8 - PUSHBUTTON "ƒIƒŠƒWƒiƒ‹‚Ì“Ç‚Ýž‚Ý",IDC_OVR_LOAD,172,30,50,14 - LTEXT "ƒtƒ@ƒCƒ‹ ƒIƒtƒZƒbƒg:",IDC_STATIC,18,30,53,8 - LTEXT "(16i”):",IDC_STATIC,18,60,24,8 - LTEXT "(16i”):",IDC_STATIC,18,102,24,8 - EDITTEXT IDC_OVRLEN,318,102,40,14,ES_AUTOHSCROLL | ES_NUMBER - LTEXT "’·‚³ (ƒoƒCƒg)",IDC_STATIC,270,102,42,8 - CONTROL "ƒI[ƒo[ƒŒƒC‚ð—LŒø‰»?",IDC_OVREN,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,6,12,72,10 - LTEXT "Œ»Ý’n",IDC_OVRCURBIN,42,73,318,8 - LTEXT "(ƒoƒCƒiƒŠ):",IDC_STATIC,18,73,24,8 - GROUPBOX "ƒI[ƒo[ƒŒƒC—̈æ‚ÌŒ³‚̃f[ƒ^",IDC_STATIC,6,48,360,36 - GROUPBOX "ƒI[ƒo[ƒŒƒC—̈æ‚ÌV‚µ‚¢’l",IDC_STATIC,6,90,360,36 - PUSHBUTTON "“K—p",IDC_APPLY,264,6,50,14 -END - -IDD_LOOKUP DIALOGEX 0, 0, 247, 78 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "MCU ‚̃tƒ@ƒCƒ‹ ƒIƒtƒZƒbƒg‚ðŒŸõ" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,190,7,50,14 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,190,24,50,14 - EDITTEXT IDC_X,27,27,40,14,ES_AUTOHSCROLL - EDITTEXT IDC_Y,89,27,40,14,ES_AUTOHSCROLL - LTEXT "X=",IDC_STATIC,15,27,10,8 - LTEXT "Y=",IDC_STATIC,77,27,10,8 - LTEXT "ƒsƒNƒZƒ‹",IDC_STATIC,135,27,19,8 - LTEXT "ƒtƒ@ƒCƒ‹ ƒIƒtƒZƒbƒg:",IDC_STATIC,15,49,37,8 - PUSHBUTTON "ÄŒvŽZ",IDC_BTN_CALC,126,49,50,14 - LTEXT "”͈Í",IDC_RNGX,27,14,41,8 - LTEXT "”͈Í",IDC_RNGY,89,14,41,8 - RTEXT "–¢ŒvŽZ",IDC_OFFSET,55,49,61,11,SS_SUNKEN -END - -IDD_OFFSETDLG DIALOGEX 0, 0, 263, 54 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "ƒtƒ@ƒCƒ‹‚ÌŠJŽnƒIƒtƒZƒbƒg" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,206,7,50,14 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,206,24,50,14 - LTEXT "ƒIƒtƒZƒbƒg (ƒoƒCƒg):",IDC_STATIC,14,15,50,8 - CONTROL "16i”",IDC_BASEH,"Button",BS_AUTORADIOBUTTON | WS_GROUP | - WS_TABSTOP,69,14,29,10 - CONTROL "10i”",IDC_BASED,"Button",BS_AUTORADIOBUTTON,69,28,40, - 10 - EDITTEXT IDC_OFFSETVAL,117,17,82,14,ES_AUTOHSCROLL -END - -IDD_SETTINGSDLG DIALOGEX 0, 0, 316, 217 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "JPEGsnoop ‚ÌÝ’è" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - EDITTEXT IDC_DB_DIR,30,20,126,14,ES_AUTOHSCROLL - CONTROL "Ž©“®“I‚ÉXV‚ðŠm”F",IDC_UPDATE_CHK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,12,66,126,10 - EDITTEXT IDC_UPDATE_CHK_DAYS,168,66,24,14,ES_AUTOHSCROLL - CONTROL "ƒIƒvƒVƒ‡ƒ“‚Ì•ÏXŽž‚ÉŽ©“®“I‚ÉĈ—‚·‚é", - IDC_REPROCESS_AUTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, - 12,102,209,10 - CONTROL "ƒ†[ƒU[’ñoŽž‚ɃIƒ“ƒ‰ƒCƒ“ DB ‚ɃVƒOƒlƒ`ƒƒ‚ð’ño", - IDC_DBSUBMIT_NET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, - 12,114,210,10 - EDITTEXT IDC_RPTERRMAX_SCANDECODE,150,150,40,12,ES_AUTOHSCROLL - LTEXT "Žw“±ƒƒbƒZ[ƒW‚ÌÄ—LŒø‰»:",IDC_STATIC,12,186, - 125,8 - PUSHBUTTON "ƒŠƒZƒbƒg",IDC_COACH_RESET,132,180,50,14 - DEFPUSHBUTTON "•Û‘¶",IDOK,258,6,50,16 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,258,25,50,16 - LTEXT "‰ð“ǃXƒLƒƒƒ“‚É•ñ‚·‚éÅ‘åƒGƒ‰[”",IDC_STATIC,12, - 150,138,8 - PUSHBUTTON "ŽQÆ",IDC_DB_DIR_BROWSE,159,17,50,10 - PUSHBUTTON "•W€",IDC_DB_DIR_DEFAULT,159,28,50,10 - GROUPBOX "ƒ†[ƒU[ ƒf[ƒ^ƒx[ƒX‚̃fƒBƒŒƒNƒgƒŠ",IDC_STATIC,6,6,228,42 - GROUPBOX "ƒ\ƒtƒgƒEƒFƒA‚ÌXV",IDC_STATIC,6,54,228,30 - LTEXT "... –ˆ",IDC_STATIC,138,66,26,8 - LTEXT "“ú",IDC_STATIC,198,66,16,8 - GROUPBOX "ˆ—‚̃IƒvƒVƒ‡ƒ“",IDC_STATIC,6,90,228,42 - GROUPBOX "ƒwƒ‹ƒv",IDC_STATIC,6,174,228,30 - GROUPBOX "•ñ‚ÌÝ’è",IDC_STATIC,6,138,228,30 -END - -IDD_TERMSDLG DIALOGEX 0, 0, 348, 220 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "JPEGsnoop ‚̃‰ƒCƒZƒ“ƒXŒ_–ñ" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,291,7,50,16 - PUSHBUTTON "I—¹",IDCANCEL,291,26,50,16 - EDITTEXT IDC_EULA,25,55,252,78,ES_MULTILINE | ES_READONLY | - WS_VSCROLL - CONTROL "ƒ‰ƒCƒZƒ“ƒX‚ð“Ç‚ÝAã‹L‚ÌðŒ‚É“¯ˆÓ‚µ‚Ü‚·",IDC_EULA_OK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,25,137,165,10 - CONTROL "Ž©“®“I‚ÉXV‚ðŠm”F",IDC_UPDATE_AUTO,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,25,175,168,10 - LTEXT "Ý’è‰æ–ʂŌォ‚炱‚Ì‘I‘ð‚ð•ÏX‚Å‚«‚Ü‚·", - IDC_STATIC,37,186,181,8 - CTEXT "‚悤‚±‚» JPEGsnoop ‚Ö!",IDC_STATIC,95,17,118,12, - SS_CENTERIMAGE | SS_SUNKEN - GROUPBOX "ƒ\ƒtƒgƒEƒFƒA‚ÌXV:",IDC_STATIC,15,162,270,41 - GROUPBOX "ƒ\ƒtƒgƒEƒFƒA‚ÌŒ_–ñ:",IDC_STATIC,15,44,270,109 -END - -IDD_UPDATEAVAILDLG DIALOGEX 0, 0, 314, 99 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "V‚µ‚¢XV‚ª—˜—p‰Â”\‚Å‚·!" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,257,7,50,16 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,257,26,50,16 - LTEXT "V‚µ‚¢ƒo[ƒWƒ‡ƒ“‚Ì JEPGsnoop ‚ªƒ_ƒEƒ“ƒ[ƒh‰Â”\‚Å‚·!", - IDC_STATIC,6,12,191,8 - LTEXT "Œ»Ý‚̃o[ƒWƒ‡ƒ“:",IDC_STATIC,18,29,51,8 - LTEXT "ÅV‚̃o[ƒWƒ‡ƒ“:",IDC_STATIC,18,48,48,8 - LTEXT "cur",IDC_VER_CUR,78,29,60,8 - LTEXT "latest",IDC_VER_LATEST,78,48,60,8 - PUSHBUTTON "ƒ_ƒEƒ“ƒ[ƒh ƒy[ƒW",IDC_BUTTON1,151,49,84,14 - CONTROL "¡Œã‚àV‚µ‚¢XV‚ðŠm”F‚µ‘±‚¯‚é", - IDC_UPDATE_AUTO_STILL,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,39,73,174,10 - LTEXT "ƒŠƒŠ[ƒX“ú:",IDC_STATIC,18,58,46,8 - LTEXT "date",IDC_DATE_LATEST,78,58,55,8 -END - -IDD_MODELESSDLG DIALOGEX 0, 100, 259, 43 -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | - WS_CAPTION | WS_SYSMENU -CAPTION "XV‚ÌŠm”F’†" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - LTEXT "ImpulseAdventure.com ‚É JPEGsnoop ‚ÌXV‚ðŠm”F’†...", - IDC_STATIC,29,16,198,8 -END - -IDD_NOTEDLG DIALOGEX 0, 0, 369, 73 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "JPEGsnoop - ƒm[ƒg" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,312,7,50,16 - LTEXT "msg",IDC_MSG,6,6,285,27,SS_SUNKEN - CONTROL "ŽŸ‚©‚炱‚̃ƒbƒZ[ƒW‚ð•\Ž¦‚µ‚È‚¢",IDC_COACH_OFF, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,42,151,10 - LTEXT "ƒm[ƒg: Ý’è‚Å‚±‚ÌŽw“±ƒƒbƒZ[ƒW‚ðÄ‚Ñ—LŒø‚É‚Å‚«‚Ü‚·", - IDC_STATIC,30,54,225,8 -END - -IDD_DBMANAGEDLG DIALOGEX 0, 0, 405, 132 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "ƒ†[ƒU[ ƒf[ƒ^ƒx[ƒX‚ÌŠÇ—" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,348,7,50,16 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,348,26,50,16 - LISTBOX IDC_LIST,6,6,332,96,LBS_USETABSTOPS | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "íœ",IDC_REMOVE,6,108,50,14 - PUSHBUTTON "‚·‚ׂÄíœ",IDC_REMOVEALL,66,108,50,14 -END - -IDD_EXPORTDLG DIALOGEX 0, 0, 290, 126 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "JPEG ‚̃GƒNƒXƒ|[ƒgÝ’è" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,233,7,50,16 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,233,26,50,16 - CONTROL "ƒI[ƒo[ƒŒƒC‚ð—LŒø (’x‚¢)",IDC_OVERLAY,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,12,36,120,10 - CONTROL "MJPEG DHT ‚Ì‘}“ü (AVI ƒtƒŒ[ƒ€ ƒGƒNƒXƒ|[ƒg‚Ì‚½‚ß)",IDC_DHTAVI, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,54,150,10 - LTEXT "Œ³ƒtƒ@ƒCƒ‹‚ÌŠJŽnƒIƒtƒZƒbƒg:",IDC_STATIC,12,6,84,8 - LTEXT "ƒIƒtƒZƒbƒg",IDC_OFFSET_START,102,6,48,8 - CONTROL "EOI ‚ÌŒ‡—Ž: EOI ‚Ì‹­§",IDC_FORCE_EOI,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,12,78,150,10 - GROUPBOX "Ý’è",IDC_STATIC,6,24,216,90 - CONTROL "EOI ‚ÌŒ‡—Ž: –³Ž‹",IDC_IGNORE_EOI,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,12,90,96,10 - CONTROL "SOI ‚ÌŒ‡—Ž: SOI ‚Ì‹­§",IDC_FORCE_SOI,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,12,66,150,10 -END - -IDD_DECODEDETAILDLG DIALOGEX 0, 0, 262, 121 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Úׂȉð“ǃXƒLƒƒƒ“‚̃IƒvƒVƒ‡ƒ“" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,204,6,50,16 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,204,25,50,16 - EDITTEXT IDC_EDIT1,54,18,40,14,ES_AUTOHSCROLL - EDITTEXT IDC_EDIT2,138,18,40,14,ES_AUTOHSCROLL - EDITTEXT IDC_EDIT3,54,60,40,14,ES_AUTOHSCROLL - RTEXT "MCU X =",IDC_STATIC,18,18,30,8 - RTEXT "MCU Y =",IDC_STATIC,102,18,30,8 - RTEXT "# MCUs =",IDC_STATIC,18,60,33,8 - GROUPBOX "‰ð“Ç‚ÌŠJŽn MCU",IDC_STATIC,6,6,186,36 - GROUPBOX "‰ð“Ç‚Ì’·‚³",IDC_STATIC,6,48,186,36 - CONTROL "Úׂȉð“ǃXƒLƒƒƒ“‚ð—LŒø‰»?",IDC_CHECK1,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,6,90,114,10 - LTEXT "Úׂȉð“ǃXƒLƒƒƒ“‚ÍŽŸ‰ñ‚̉ð“Ç‘€ìŽž‚É•ñ‚³‚ê‚Ü‚·", - IDC_STATIC,18,102,228,8 - PUSHBUTTON "À•W‚Ì“Ç‚Ýž‚Ý",IDC_BTN_LOAD,204,72,50,14 - LTEXT "ÅI 2 ƒNƒŠƒbƒN‚©‚ç X/Y/Len ‚ð“Ç‚Ýž‚Ý:",IDC_STATIC,198,48,54, - 18 -END - -IDD_EXPORTTIFFDLG DIALOGEX 0, 0, 256, 108 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "TIFF Œ`Ž®‚ŃGƒNƒXƒ|[ƒg" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,198,6,50,16 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,198,25,50,16 - CONTROL "RGB (8 ƒrƒbƒg)",IDC_RAD_RGB8,"Button",BS_AUTORADIOBUTTON | - WS_GROUP,24,54,72,10 - CONTROL "RGB (16 ƒrƒbƒg)",IDC_RAD_RGB16,"Button",BS_AUTORADIOBUTTON, - 24,66,72,10 - CONTROL "YCC (8 ƒrƒbƒg)",IDC_RAD_YCC8,"Button",BS_AUTORADIOBUTTON, - 24,79,72,10 - GROUPBOX "o—ÍŒ`Ž®",IDC_STATIC,12,36,90,60 - LTEXT "•Û‘¶ƒtƒ@ƒCƒ‹–¼:",IDC_STATIC,12,12,54,8 - EDITTEXT IDC_EDIT_FNAME,66,12,120,14,ES_AUTOHSCROLL | ES_READONLY -END - -IDD_BATCHDLG DIALOGEX 0, 0, 232, 108 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "ƒoƒbƒ`ˆ—" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,162,66,50,16 - PUSHBUTTON "ƒLƒƒƒ“ƒZƒ‹",IDCANCEL,162,84,50,16 - CONTROL "ƒTƒuƒfƒBƒŒƒNƒgƒŠ‚àˆ—‚µ‚Ü‚·‚©?",IDC_CHECK_SUBDIRS,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,30,73,98,10 - EDITTEXT IDC_EDIT_DIR,30,49,180,14,ES_AUTOHSCROLL | ES_READONLY - LTEXT "ƒfƒBƒŒƒNƒgƒŠ:",IDC_STATIC,24,36,42,8 - LTEXT "’ˆÓ 1: ƒoƒbƒNƒAƒbƒv‚µ‚½ƒtƒ@ƒCƒ‹‚É‚Ì‚Ý‚ÉŽg—p‚·‚邱‚Æ‚ð„§‚µ‚Ü‚·", - IDC_STATIC,6,6,186,8 - LTEXT "’ˆÓ 2: ˆ—‚Ì‚‘¬‰»‚Ì‚½‚ß‚ÉA""ƒCƒ[ƒW‚̃fƒR[ƒh"" ‚𖳌ø‰»‚µ‚ĉº‚³‚¢", - IDC_STATIC,6,18,210,8 -END - -IDD_OPERATIONDLG DIALOGEX 0, 0, 186, 73 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "‘€ì‚Ìis" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "’†’f",ID_BTN_ABORT,66,48,50,14 - CONTROL "",IDC_PROGRESS_BAR,"msctls_progress32",WS_BORDER,6,6, - 174,14 - CTEXT "is: ddd / ddd",IDC_STATIC_PROGRESS,6,24,174,12, - SS_SUNKEN -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,5,2,0 - PRODUCTVERSION 1,5,2,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "001103a4" - BEGIN - VALUE "CompanyName", "ImpulseAdventure" - VALUE "FileDescription", "JPEGsnoop" - VALUE "FileVersion", "1.5.2.0" - VALUE "InternalName", "JPEGsnoop.exe" - VALUE "LegalCopyright", "(c) 2011 Calvin Hass. All rights reserved." - VALUE "OriginalFilename", "JPEGsnoop.exe" - VALUE "ProductName", "JPEGsnoop" - VALUE "ProductVersion", "1.5.2.0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0011, 932 - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_ABOUTBOX, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 235 - TOPMARGIN, 7 - BOTTOMMARGIN, 87 - END - - IDD_DBSUBMITDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 390 - TOPMARGIN, 7 - BOTTOMMARGIN, 173 - END - - IDD_OVERLAYBUFDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 369 - TOPMARGIN, 7 - BOTTOMMARGIN, 131 - END - - IDD_LOOKUP, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 240 - TOPMARGIN, 7 - BOTTOMMARGIN, 71 - END - - IDD_OFFSETDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 256 - TOPMARGIN, 7 - BOTTOMMARGIN, 47 - END - - IDD_SETTINGSDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 309 - TOPMARGIN, 7 - BOTTOMMARGIN, 210 - END - - IDD_TERMSDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 341 - TOPMARGIN, 7 - BOTTOMMARGIN, 213 - END - - IDD_UPDATEAVAILDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 307 - TOPMARGIN, 7 - BOTTOMMARGIN, 92 - END - - IDD_MODELESSDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 252 - TOPMARGIN, 7 - BOTTOMMARGIN, 36 - END - - IDD_NOTEDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 362 - TOPMARGIN, 7 - BOTTOMMARGIN, 66 - END - - IDD_DBMANAGEDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 398 - TOPMARGIN, 7 - BOTTOMMARGIN, 125 - END - - IDD_EXPORTDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 283 - TOPMARGIN, 7 - BOTTOMMARGIN, 119 - END - - IDD_DECODEDETAILDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 255 - TOPMARGIN, 7 - BOTTOMMARGIN, 114 - END - - IDD_EXPORTTIFFDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 249 - TOPMARGIN, 7 - BOTTOMMARGIN, 101 - END - - IDD_BATCHDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 225 - TOPMARGIN, 7 - BOTTOMMARGIN, 101 - END - - IDD_OPERATIONDLG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 179 - TOPMARGIN, 7 - BOTTOMMARGIN, 66 - END -END -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN - IDR_MAINFRAME "JPEGsnoop\nUntitled\nJPEGsnoop\nJPEG Image/Video (*.jpg;*.jpeg;*.avi;*.mov)\n.jpg;.jpeg;.avi;.mov\nJPEGsnoop.Document\nJPEGsnoop.Document" - IDR_MAINFRAME_BAK "JPEGsnoop\n\nJPEGsnoop\n\n\nJPEGsnoop.Document\nJPEGsnoop.Document" - IDR_TEST1TYPE "Test1\test1 File\nTest1 Files(*.ts1)\n.ts1\nts1\nTest1" - IDR_TEST2TYPE "Test2\test2 File\nTest2 Files(*.ts2)\n.ts2\nts2\nTest2" - IDR_MAINFRAME2 "JPEGsnoop\nUntitled\nJPEGsnoop\nJPEG Files (*.jpg)\n.jpg\nJPEGsnoop.Document\nJPEGsnoop.Document" - IDR_MAINFRAME3 "JPEGsnoop\nUntitled\nJPEGsnoop\nJPEG Image (*.jpg;*.jpeg)\n.jpg;.jpeg\nJPEGsnoop.Document\nJPEGsnoop.Document" - IDR_MAINFRAME_AVI "JPEGsnoop\nUntitled\nJPEGsnoop\nAVI Movie (*.avi)\n.avi\nJPEGsnoop.Document\nJPEGsnoop.Document" - IDR_MAINFRAME_ALL "JPEGsnoop\nUntitled\nJPEGsnoop\nJPEG Image (*.jpg;*.jpeg)\n.jpg;.jpeg\nJPEGsnoop.Document\nJPEGsnoop.Document" - ID_INDICATOR_YCC "YCC DC=[00000,00000,00000]" - IDS_CAL_FILEOPEN "ƒCƒ[ƒW / ƒrƒfƒI ƒtƒ@ƒCƒ‹‚ðŠJ‚­" - IDS_CAL_FILESAVE "JPEGSnoop ƒƒO ƒtƒ@ƒCƒ‹‚ð•Û‘¶" - ID_INDICATOR_MCU "MCU [0000,0000]" - ID_INDICATOR_FILEPOS "File: 0x00000000:0" -END - -STRINGTABLE -BEGIN - AFX_IDS_APP_TITLE "JPEGsnoop" - AFX_IDS_IDLEMESSAGE "€”õŠ®—¹" -END - -STRINGTABLE -BEGIN - ID_INDICATOR_EXT "EXT" - ID_INDICATOR_CAPS "CAP" - ID_INDICATOR_NUM "NUM" - ID_INDICATOR_SCRL "SCRL" - ID_INDICATOR_OVR "OVR" - ID_INDICATOR_REC "REC" -END - -STRINGTABLE -BEGIN - ID_FILE_NEW "V‚µ‚¢ƒhƒLƒ…ƒƒ“ƒg‚Ìì¬\nV‹K" - ID_FILE_OPEN "Šù‘¶‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­\nŠJ‚­" - ID_FILE_CLOSE "Œ»Ý‚̃hƒLƒ…ƒƒ“ƒg‚ð•Â‚¶‚é\n•Â‚¶‚é" - ID_FILE_SAVE "Œ»Ý‚̃hƒLƒ…ƒƒ“ƒg‚ð•Û‘¶\n•Û‘¶" - ID_FILE_SAVE_AS "‹L˜^o—Í‚Ì•Û‘¶\n‹L˜^‚Ì•Û‘¶" - ID_FILE_PAGE_SETUP "ˆóüƒIƒvƒVƒ‡ƒ“‚Ì•ÏX\nƒy[ƒWÝ’è" - ID_FILE_PRINT_SETUP "ƒvƒŠƒ“ƒ^‚ƈóü‚̃IƒvƒVƒ‡ƒ“‚ð•ÏX\nˆóüÝ’è" - ID_FILE_PRINT "Œ»Ý‚Ì‹L˜^‚ðˆóü\nˆóü" - ID_FILE_PRINT_PREVIEW "‚·‚ׂẴy[ƒW‚ð•\Ž¦\nˆóüƒvƒŒƒrƒ…[" -END - -STRINGTABLE -BEGIN - ID_APP_ABOUT "JPEGsnoop ‚ɂ‚¢‚Ä\nƒo[ƒWƒ‡ƒ“î•ñ" - ID_APP_EXIT "JPEGsnoop ‚ÌI—¹\nI—¹" -END - -STRINGTABLE -BEGIN - ID_FILE_MRU_FILE1 "‚±‚̃tƒ@ƒCƒ‹‚ðŠJ‚­" - ID_FILE_MRU_FILE2 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE3 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE4 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE5 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE6 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE7 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE8 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE9 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE10 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE11 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE12 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE13 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE14 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE15 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" - ID_FILE_MRU_FILE16 "‚±‚̃hƒLƒ…ƒƒ“ƒg‚ðŠJ‚­" -END - -STRINGTABLE -BEGIN - ID_NEXT_PANE "ŽŸ‚̃EƒBƒ“ƒhƒE ƒyƒCƒ“‚ÉØ‚è‘Ö‚¦\nŽŸ‚̃yƒCƒ“" - ID_PREV_PANE "‘O‚̃EƒBƒ“ƒhƒE ƒyƒCƒ“‚ÉØ‚è‘Ö‚¦\n‘O‚̃yƒCƒ“" -END - -STRINGTABLE -BEGIN - ID_WINDOW_SPLIT "Œ»Ý‚̃EƒBƒ“ƒhƒE‚ðƒyƒCƒ“‚É•ªŠ„\n•ªŠ„" -END - -STRINGTABLE -BEGIN - ID_EDIT_CLEAR "‘I‘ð‚ÌÁ‹Ž\nÁ‹Ž" - ID_EDIT_CLEAR_ALL "‚·‚ׂÄÁ‹Ž\n‚·‚ׂÄÁ‹Ž" - ID_EDIT_COPY "‘I‘ð‚ðƒNƒŠƒbƒvƒ{[ƒh‚ɃRƒs[\nƒRƒs[" - ID_EDIT_CUT "‘I‘ð‚ðØ‚èŽæ‚Á‚ăNƒŠƒbƒvƒ{[ƒh‚ɃRƒs[\nØ‚èŽæ‚è" - ID_EDIT_FIND "Žw’肳‚ꂽƒeƒLƒXƒg‚ðŒŸõ\nŒŸõ" - ID_EDIT_PASTE "ƒNƒŠƒbƒvƒ{[ƒh‚Ì“à—e‚ð‘}“ü\n“\‚è•t‚¯" - ID_EDIT_PASTE_LINK "ƒNƒŠƒbƒvƒ{[ƒh‚Ì“à—e‚ð‘}“ü‚µ‚ăŠƒ\[ƒX‚ɃŠƒ“ƒN\nƒŠƒ“ƒN‚ð“\‚è•t‚¯" - ID_EDIT_PASTE_SPECIAL "ƒNƒŠƒbƒvƒ{[ƒh‚Ì“à—e‚ðƒIƒvƒVƒ‡ƒ“•t‚«‚Å‘}“ü\n“ÁŽê“\‚è•t‚¯" - ID_EDIT_REPEAT "ÅŒã‚Ì‘€ì‚ðŒJ‚è•Ô‚·\nŒJ‚è•Ô‚µ" - ID_EDIT_REPLACE "Žw’è‚̃eƒLƒXƒg‚ð•Ê‚̃eƒLƒXƒg‚É’uŠ·\n’uŠ·" - ID_EDIT_SELECT_ALL "ƒhƒLƒ…ƒƒ“ƒg‘S‘Ì‚ð‘I‘ð\n‚·‚ׂđI‘ð" - ID_EDIT_UNDO "ÅŒã‚Ì“®ì‚ðŒ³‚É–ß‚·\nŒ³‚É–ß‚·" - ID_EDIT_REDO "‘O‰ñ‚ÌŒ³‚É–ß‚·‘€ì‚ð‚â‚è’¼‚µ\n‚â‚è’¼‚µ" -END - -STRINGTABLE -BEGIN - ID_VIEW_TOOLBAR "ƒc[ƒ‹ ƒo[‚Ì•\Ž¦‚Ü‚½‚Í”ñ•\Ž¦\nƒc[ƒ‹ƒo[‚Ì•\Ž¦Ø‚è‘Ö‚¦" - ID_VIEW_STATUS_BAR "ƒXƒe[ƒ^ƒX ƒo[‚ð•\Ž¦‚Ü‚½‚Í”ñ•\Ž¦\nƒXƒe[ƒ^ƒX ƒo[‚Ì•\Ž¦Ø‚è‘Ö‚¦" -END - -STRINGTABLE -BEGIN - ID_OLE_INSERT_NEW "V‚µ‚¢–„‚ßž‚݃IƒuƒWƒFƒNƒg‚ð‘}“ü\nV‚µ‚¢ƒIƒuƒWƒFƒNƒg" - ID_OLE_EDIT_LINKS "ƒŠƒ“ƒN‚³‚ꂽƒIƒuƒWƒFƒNƒg‚ð•ÒW\nƒŠƒ“ƒN‚ð•ÒW" - ID_OLE_EDIT_CONVERT "ƒIƒuƒWƒFƒNƒg‚ð•Ê‚ÌŽí—Þ‚É•ÏŠ·\nƒIƒuƒWƒFƒNƒg‚ð•ÏŠ·" -END - -STRINGTABLE -BEGIN - ID_OLE_VERB_FIRST "–„‚ßž‚܂ꂽ‚Ü‚½‚̓Šƒ“ƒN‚³‚ꂽƒIƒuƒWƒFƒNƒg‚ð—LŒø‰»" - 57873 "–„‚ßž‚܂ꂽ‚Ü‚½‚̓Šƒ“ƒN‚³‚ꂽƒIƒuƒWƒFƒNƒg‚ð—LŒø‰»" - 57874 "–„‚ßž‚܂ꂽ‚Ü‚½‚̓Šƒ“ƒN‚³‚ꂽƒIƒuƒWƒFƒNƒg‚ð—LŒø‰»" - 57875 "–„‚ßž‚܂ꂽ‚Ü‚½‚̓Šƒ“ƒN‚³‚ꂽƒIƒuƒWƒFƒNƒg‚ð—LŒø‰»" -END - -STRINGTABLE -BEGIN - AFX_IDS_SCSIZE "ƒEƒCƒ“ƒhƒE‚̃TƒCƒY‚ð•ÏX" - AFX_IDS_SCMOVE "ƒEƒCƒ“ƒhƒE‚̈ʒu‚ð•ÏX" - AFX_IDS_SCMINIMIZE "ƒEƒBƒ“ƒhƒE‚ðŬ‰»‚µ‚Ü‚·" - AFX_IDS_SCMAXIMIZE "ƒEƒBƒ“ƒhƒE‚ðő剻‚µ‚Ü‚·" - AFX_IDS_SCNEXTWINDOW "ŽŸ‚̃hƒLƒ…ƒƒ“ƒg ƒEƒBƒ“ƒhƒE‚ÉØ‚è‘Ö‚¦‚Ü‚·" - AFX_IDS_SCPREVWINDOW "‘O‚̃EƒBƒ“ƒhƒE‚ÉØ‚è‘Ö‚¦‚Ü‚·" - AFX_IDS_SCCLOSE "ƒhƒLƒ…ƒƒ“ƒg‚Ì•Û‘¶‚ðŠm”F‚µ‚Äì‹Æ’†‚̃EƒBƒ“ƒhƒE‚ð•Â‚¶‚Ü‚·" -END - -STRINGTABLE -BEGIN - AFX_IDS_SCRESTORE "ƒEƒCƒ“ƒhƒE‚ð•W€‚̃TƒCƒY‚É•œŒ³" - AFX_IDS_SCTASKLIST "ƒ^ƒXƒN ƒŠƒXƒg‚ðƒAƒNƒeƒBƒu‰»" -END - -STRINGTABLE -BEGIN - AFX_IDS_SAVEFILECOPY "‹L˜^ƒtƒ@ƒCƒ‹‚Ì•Û‘¶..." - AFX_IDS_PREVIEW_CLOSE "ˆóüƒvƒŒƒrƒ…[ ƒ‚[ƒh‚ð•Â‚¶‚é\nƒvƒŒƒrƒ…[‚̃Lƒƒƒ“ƒZƒ‹" -END - -STRINGTABLE -BEGIN - ID_TOOLS_DECODE "‰ð“ǂ̃eƒXƒg" - ID_FILE_OFFSET "ƒIƒtƒZƒbƒg‚ň—‚ðŠJŽn\nƒIƒtƒZƒbƒg" - 32773 "ŽŸ‚̃Cƒ[ƒW‚ðŒŸõ\n‘O•ûŒŸõ" - 32774 "‘O‚̃Cƒ[ƒW‚ðŒŸõ\nŒã•ûŒŸõ" - 32775 "MCU ‚̃tƒ@ƒCƒ‹ ƒIƒtƒZƒbƒg‚ÌŒvŽZ\nMCU ‚ÌŒŸõ" - 32776 "ƒI[ƒo[ƒŒƒC‚Ńtƒ@ƒCƒ‹‚Ì•ÏX‚ðƒeƒXƒg\nƒI[ƒo[ƒŒƒC" - 32777 "ƒZƒOƒƒ“ƒg‚̃XƒLƒƒƒ“‚ÌÚ׉ð“Ç\nÚ׃XƒLƒƒƒ“" - 32778 "ˆ³kƒVƒOƒlƒ`ƒƒ‚Ńf[ƒ^ƒx[ƒX‚ÌXV\nƒVƒOƒlƒ`ƒƒ‚̒ljÁ" - ID_OPTIONS_DHTEXPAND "Šg’£ DHT ƒe[ƒuƒ‹‚ðƒ_ƒ“ƒv\nDHT Šg’£" - ID_OPTIONS_MAKERNOTES "ƒ[ƒJ[ ƒm[ƒg‚ðƒ_ƒ“ƒv\nƒ[ƒJ[ ƒm[ƒg" - ID_OPTIONS_SCANDUMP "ƒf[ƒ^ ƒXƒLƒƒƒ“‚Ì16i”ƒ_ƒ“ƒv\nƒXƒLƒƒƒ“‚̃_ƒ“ƒv" -END - -STRINGTABLE -BEGIN - IDS_CAL_EXE_OPEN "ŒŸõ—p‚ÌŽÀs‰Â”\ƒtƒ@ƒCƒ‹‚ðŠJ‚­" -END - -STRINGTABLE -BEGIN - ID_OPTIONS_HISTOYDUMP "‹P“x‚̃qƒXƒgƒOƒ‰ƒ€‚ð•\Ž¦\nY ƒqƒXƒgƒOƒ‰ƒ€" - ID_FILE_REPROCESS "Œ»Ý‚̃tƒ@ƒCƒ‹‚ðĈ—\nĈ—" - ID_OPTIONS_DECODESCAN "ƒZƒO–ʂ̃XƒLƒƒƒ“ˆ—, ƒCƒ[ƒW‚Ì•\Ž¦\nƒCƒ[ƒW‚̃XƒLƒƒƒ“" - ID_OPTIONS_CONFIGURATION "Ý’èƒIƒvƒVƒ‡ƒ“‚Ì•ÏX\nÝ’è" - ID_OPTIONS_CHECKFORUPDATES "ƒCƒ“ƒ^[ƒlƒbƒg‚ÅXV‚ÌŠm”F\nXV" -END - -STRINGTABLE -BEGIN - ID_TOOLS_SEARCHEXECUTABLEFORDQT "ŽÀs‰Â”\ƒtƒ@ƒCƒ‹‚Å DQT ƒe[ƒuƒ‹‚ðŒŸõ\nDQT ‚ÌŒŸõ" - ID_TOOLS_MANAGELOCALDB "ƒ[ƒJƒ‹ ƒ†[ƒU[ ƒVƒOƒlƒ`ƒƒ‚ÌŠÇ—\nƒVƒOƒlƒ`ƒƒ‚ÌŠÇ—" - ID_OPTIONS_SIGNATURESEARCH - "ˆê’v‚·‚鈳kƒVƒOƒlƒ`ƒƒ‚ÌŒŸõ\nƒVƒOƒlƒ`ƒƒ‚ÌŒŸõ" - ID_OPTIONS_DECODEAC "‰ð“ǃXƒLƒƒƒ“‚Å AC (IDCT) ‚ð—LŒø‰»" - ID_SCANSEGMENT_DECODEIMAGE "ƒCƒ[ƒW‚̃XƒLƒƒƒ“‚ʼnð“Ç‚ð—LŒø‰»\nƒXƒLƒƒƒ“ ƒfƒR[ƒh" - ID_SCANSEGMENT_FULLIDCT "Š®‘S IDCT ƒCƒ[ƒW‚ð—LŒø‰» (DC + AC ƒRƒ“ƒ|[ƒlƒ“ƒg)\nFull Res" - ID_SCANSEGMENT_HISTOGRAMY - "‹P“x‚̃qƒXƒgƒOƒ‰ƒ€ (Y) ‚ÌŒvŽZ‚Æ•\Ž¦\nY ƒqƒXƒgƒOƒ‰ƒ€" - ID_SCANSEGMENT_DUMP "ƒZƒOƒƒ“ƒg ƒXƒLƒƒƒ“‚ÌŠJŽn16i”‚ðƒ_ƒ“ƒv\nƒXƒLƒƒƒ“ ƒ_ƒ“ƒv" -END - -STRINGTABLE -BEGIN - 32800 "RGB ƒ`ƒƒƒ“ƒlƒ‹‚Ì•\Ž¦\nRGB" - 32801 "YCC ƒ`ƒƒƒ“ƒlƒ‹‚Ì•\Ž¦\nYCC" - 32802 "Ôƒ`ƒƒƒ“ƒlƒ‹‚Ì•\Ž¦\nÔ" - 32803 "—΃`ƒƒƒ“ƒlƒ‹‚Ì•\Ž¦\n—Î" - 32804 "ƒ`ƒƒƒ“ƒlƒ‹‚Ì•\Ž¦\nÂ" - 32805 "‹P“xƒ`ƒƒƒ“ƒlƒ‹‚Ì•\Ž¦\nY" - 32806 "ƒNƒƒ~ƒiƒ“ƒX ƒ`ƒƒƒ“ƒlƒ‹ (Cb)‚Ì•\Ž¦\nCb" - 32807 "ƒNƒƒ~ƒiƒ“ƒX ƒ`ƒƒƒ“ƒlƒ‹ (Cr) ‚Ì•\Ž¦\nCr" - 32808 "ƒCƒ[ƒW ƒrƒ…[‚ÌŠg‘å\nŠg‘å" - 32809 "ƒCƒ[ƒW ƒrƒ…[‚Ìk¬\nk¬" - 32810 "ƒCƒ[ƒW ƒrƒ…[‚̃Y[ƒ€‚ð 100% ‚ÉÝ’è\n100%" - 32811 "ƒCƒ[ƒW ƒrƒ…[‚̃Y[ƒ€‚ð 150% ‚ÉÝ’è\n150%" - 32812 "ƒCƒ[ƒW ƒrƒ…[‚̃Y[ƒ€‚ð 200% ‚ÉÝ’è\n200%" - 32813 "ƒCƒ[ƒW ƒrƒ…[‚̃Y[ƒ€‚ð 300% ‚ÉÝ’è\n300%" - 32814 "ƒCƒ[ƒW ƒrƒ…[‚̃Y[ƒ€‚ð 400% ‚ÉÝ’è\n400%" - 32815 "ƒCƒ[ƒW ƒrƒ…[‚̃Y[ƒ€‚ð 800% ‚ÉÝ’è\n800%" -END - -STRINGTABLE -BEGIN - ID_SCANSEGMENT_NOIDCT "‰ð“Ç‚µ‚È‚¢ (DC ƒRƒ“ƒ|[ƒlƒ“ƒg‚Ì‚Ý)\nLow Res" - ID_OVERLAYS_MCUGRID "MCU ‚Ì‹«ŠEƒOƒŠƒbƒh‚Ì•\Ž¦\nMCU ƒOƒŠƒbƒh" -END - -STRINGTABLE -BEGIN - ID_IMAGEZOOM_ZOOMIN "Šg‘å\nŠg‘å" - ID_IMAGEZOOM_ZOOMOUT "k¬\nk¬" - ID_IMAGEZOOM_12 "12.5% ƒY[ƒ€\n12.5% ƒY[ƒ€" - ID_IMAGEZOOM_25 "25% ƒY[ƒ€\n25% ƒY[ƒ€" - ID_IMAGEZOOM_50 "50% ƒY[ƒ€\n50% ƒY[ƒ€" - ID_IMAGEZOOM_100 "100% ƒY[ƒ€\n100% ƒY[ƒ€" - ID_IMAGEZOOM_150 "150% ƒY[ƒ€\n150% ƒY[ƒ€" - ID_IMAGEZOOM_200 "200% ƒY[ƒ€\n200% ƒY[ƒ€" - ID_IMAGEZOOM_300 "300% ƒY[ƒ€\n300% ƒY[ƒ€" - ID_IMAGEZOOM_400 "400% ƒY[ƒ€\n400% ƒY[ƒ€" - ID_IMAGEZOOM_800 "800% ƒY[ƒ€\n800% ƒY[ƒ€" -END - -STRINGTABLE -BEGIN - ID_TOOLS_DETAILEDSCANDECODE "VLC ƒfƒR[ƒh‚ÌÚוñ\nÚ׃XƒLƒƒƒ“" - ID_SCANSEGMENT_DETAILEDDECODE - "ƒXƒLƒƒƒ“ ƒf[ƒ^‚ÌÚ׃fƒR[ƒh\nÚ׃fƒR[ƒh" - ID_SCANSEGMENT_HISTOGRAM "RGB ƒqƒXƒgƒOƒ‰ƒ€‚ÌŒvŽZ‚Æ•\Ž¦\nRGB ƒqƒXƒgƒOƒ‰ƒ€" -END - -STRINGTABLE -BEGIN - ID_OPTIONS_HIDEUKNOWNEXIFTAGS "•s–¾‚È EXIF ƒ^ƒO‚ð”ñ•\Ž¦\nEXIF ƒ^ƒO" - ID_FILE_BATCHPROCESS "ƒoƒbƒ`ˆ—‚ðŠJŽn" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// -//CAL! #define _AFX_NO_SPLITTER_RESOURCES -#define _AFX_NO_OLE_RESOURCES -#define _AFX_NO_TRACKER_RESOURCES -#define _AFX_NO_PROPERTY_RESOURCES - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE 17, 0 -#pragma code_page(932) -#include "res\JPEGsnoop.rc2" // non-Microsoft Visual C++ edited resources -#include "afxres.rc" // Standard components -#include "afxprint.rc" // printing/print preview resources -#include "afxolecl.rc" // OLE container resources -#endif - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/source/labelClick.cpp b/source/labelClick.cpp new file mode 100644 index 0000000..2cd8287 --- /dev/null +++ b/source/labelClick.cpp @@ -0,0 +1,43 @@ +#include +#include "labelClick.h" + +//--------------------------------------------------------------------------- + +labelClick::labelClick(QWidget *_parent, Qt::WindowFlags f) : QLabel(_parent, f) +{ +} + +//--------------------------------------------------------------------------- + +labelClick::labelClick(QString s, QWidget *_parent, Qt::WindowFlags f) : QLabel(s, _parent, f) +{ +} + +//--------------------------------------------------------------------------- + +labelClick::~labelClick() +{ +} + +//--------------------------------------------------------------------------- + +void labelClick::mousePressEvent(QMouseEvent *_event) +{ + QMouseEvent *mouseEvent = static_cast(_event); + emit clicked(mouseEvent); +} + +//--------------------------------------------------------------------------- + +void labelClick::mouseMoveEvent(QMouseEvent *_event) +{ + QMouseEvent *mouseEvent = static_cast(_event); + emit moved(mouseEvent); +} + +//--------------------------------------------------------------------------- + +void labelClick::mouseReleaseEvent(QMouseEvent *_event) +{ + emit released(static_cast(_event)); +} diff --git a/source/labelClick.h b/source/labelClick.h new file mode 100644 index 0000000..be53587 --- /dev/null +++ b/source/labelClick.h @@ -0,0 +1,30 @@ +#ifndef LABELCLICK_H +#define LABELCLICK_H + +#include "QWidget" +#include "QLabel" + +class QMouseEvent; + +class labelClick : public QLabel +{ + Q_OBJECT + +public: + labelClick(QWidget * parent = 0, Qt::WindowFlags f = 0); + labelClick(QString, QWidget * parent = 0, Qt::WindowFlags f = 0); + virtual ~labelClick(); + +protected: + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + +signals: + void clicked(QMouseEvent *); + void released(QMouseEvent *); + void moved(QMouseEvent *); + +}; + +#endif // LABELCLICK_H diff --git a/source/main.cpp b/source/main.cpp index e440f49..453d7fd 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,19 +1,8 @@ #include #include -#include "DbSigs.h" -#include "DocLog.h" -#include "JPEGsnoop.h" -#include "JPEGsnoopCore.h" -#include "SnoopConfig.h" - #include "mainwindow.h" -CDocLog *glb_pDocLog; -CSnoopConfig* m_pAppConfig; -CDbSigs *m_pDbSigs; -CJPEGsnoopCore *pJPEGsnoopCore; - int main(int argc, char *argv[]) { QApplication a(argc, argv); @@ -21,14 +10,6 @@ int main(int argc, char *argv[]) QCoreApplication::setOrganizationDomain("www.impulseadventure.com"); QCoreApplication::setApplicationName("JPEGsnoopQt"); -// m_pAppConfig = new CSnoopConfig(); -// m_pAppConfig->UseDefaults(); - glb_pDocLog = new CDocLog(); - glb_pDocLog->Enable(); - m_pDbSigs = new CDbSigs(); -// pJPEGsnoopCore = new CJPEGsnoopCore(); -// m_pAppConfig->RegistryLoad(); - MainWindow w; w.show(); diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index 336c7d2..aeb570c 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -1,27 +1,48 @@ #include +#include +#include +#include +#include -#include "SnoopConfig.h" -#include "snoopconfigdialog.h" -#include "JPEGsnoop.h" -//#include "Viewer.h" -#include "JfifDecode.h" +#include "DbSigs.h" #include "ImgDecode.h" +#include "JfifDecode.h" +#include "SnoopConfig.h" +#include "Viewer.h" #include "WindowBuf.h" +#include "note.h" +#include "snoop.h" +#include "snoopconfigdialog.h" #include "mainwindow.h" -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent) +#ifdef Q_OS_MAC +const QString rsrcPath = ":/images/mac"; +#else +const QString rsrcPath = ":/images/win"; +#endif + +//----------------------------------------------------------------------------- + +MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), textEdit(new QPlainTextEdit) { if(DEBUG_EN) - m_pAppConfig->DebugLogAdd("MainWindow::MainWindow() Begin"); + qDebug() << "MainWindow::MainWindow() Begin"; QWidget *widget = new QWidget; setCentralWidget(widget); setGeometry(100, 100, 800, 700); + m_pDocLog = new CDocLog(); + m_pDocLog->Enable(); + + m_pAppConfig = new CSnoopConfig(this); + m_pAppConfig->RegistryLoad(); + + m_pDbSigs = new CDbSigs(m_pDocLog, m_pAppConfig); + // Allocate the file window buffer - m_pWBuf = new CwindowBuf(); + m_pWBuf = new CwindowBuf(m_pDocLog); if(!m_pWBuf) { @@ -30,48 +51,60 @@ MainWindow::MainWindow(QWidget *parent) : } // Allocate the JPEG decoder - m_pImgDec = new CimgDecode(glb_pDocLog, m_pWBuf, this); + m_pImgDec = new CimgDecode(m_pDocLog, m_pWBuf, m_pAppConfig, this); - if(!m_pWBuf) + if(!m_pImgDec) { msgBox.setText("ERROR: Not enough memory for Image Decoder"); exit(1); } - m_pJfifDec = new CjfifDecode(glb_pDocLog, m_pWBuf, m_pImgDec); + m_pJfifDec = new CjfifDecode(m_pDocLog, m_pDbSigs, m_pWBuf, m_pImgDec, m_pAppConfig, this); - if(!m_pWBuf) + if(!m_pJfifDec) { msgBox.setText("ERROR: Not enough memory for JFIF Decoder"); exit(1); } - m_pAppConfig = new CSnoopConfig(m_pJfifDec); - m_pAppConfig->RegistryLoad(); + imgWindow = new Q_Viewer(m_pAppConfig, m_pImgDec, this, Qt::Window); +#ifdef Q_OS_LINUX menuBar()->setNativeMenuBar(false); - +#endif + + fileToolBar = addToolBar(tr("File")); + createActions(); createMenus(); -// QScrollArea *scrollArea = new QScrollArea(this); -// scrollArea->setWidget(m_pImgDec); -// scrollArea->setBackgroundRole(QPalette::Dark); -// scrollArea->setVisible(false); + QHBoxLayout *hLayout = new QHBoxLayout; + QVBoxLayout *vLayout = new QVBoxLayout; + + rgbHisto = new QLabel; + rgbHisto->setAlignment(Qt::AlignBottom | Qt::AlignLeft); + rgbHisto->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + rgbHisto->setMinimumSize(width() / 2, 180); + rgbHisto->setStyleSheet("background-color: white"); + hLayout->addWidget(rgbHisto); + + yHisto = new QLabel; + yHisto->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + yHisto->setMinimumSize(width() / 2, 180); + yHisto->setStyleSheet("background-color: white"); + hLayout->addWidget(yHisto); + + vLayout->addWidget(textEdit); + vLayout->addLayout(hLayout); + + QWidget *w = new QWidget; + w->setLayout(vLayout); + setCentralWidget(w); - QSplitter *splitter = new QSplitter(Qt::Vertical); - doc = new QPlainTextEdit; - doc->setMaximumBlockCount(0); QFont f; f.setFamily("Courier"); - doc->setFont(f); - doc->appendPlainText(""); - -// v = new Q_Viewer(this); - splitter->addWidget(doc); - splitter->addWidget(m_pImgDec); -// splitter->addWidget(scrollArea); - setCentralWidget(splitter); + textEdit->setFont(f); + textEdit->appendPlainText(""); m_StatusBar = statusBar(); QLabel *st1 = new QLabel(" "); @@ -81,54 +114,75 @@ MainWindow::MainWindow(QWidget *parent) : m_StatusBar->addPermanentWidget(st1); st1->setText("1234"); m_pJfifDec->SetStatusBar(m_StatusBar); + connect(m_pJfifDec, SIGNAL(updateStatus(QString, int)), m_StatusBar, SLOT(showMessage(QString,int))); connect(m_pImgDec, SIGNAL(updateStatus(QString, int)), m_StatusBar, SLOT(showMessage(QString,int))); + connect(m_pAppConfig, SIGNAL(reprocess()), this, SLOT(reprocess())); + + m_pDocLog->setDoc(textEdit); + + // Coach Messages + strLoRes = "Currently only decoding low-res view (DC-only). Full-resolution image decode can be enabled in [Options->Scan Segment->Full IDCT], but it is slower."; + strHiRes = "Currently decoding high-res view (AC+DC), which can be slow. For faster operation, low-resolution image decode can be enabled in [Options->Scan Segment->No IDCT]."; - glb_pDocLog->setDoc(doc); } +//----------------------------------------------------------------------------- + MainWindow::~MainWindow() { } +//----------------------------------------------------------------------------- + void MainWindow::createActions(void) { if(DEBUG_EN) m_pAppConfig->DebugLogAdd("MainWindow::createActions() Begin"); -// newAct = new QAction(tr("&New"), this); -// newAct->setShortcuts(QKeySequence::New); -// newAct->setStatusTip(tr("Create a new file")); -// connect(newAct, &QAction::triggered, this, &MainWindow::newFile); + const QIcon newIcon = QIcon::fromTheme("document-new", QIcon(rsrcPath + "/filenew.png")); + newAct = new QAction(newIcon, tr("&New"), this); + newAct->setShortcuts(QKeySequence::New); + newAct->setStatusTip(tr("New")); +// connect(newAct, &QAction::triggered, this, &MainWindow::newFile); + fileToolBar->addAction(newAct); - openAct = new QAction(tr("&Open Image..."), this); + const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(rsrcPath + "/fileopen.png")); + openAct = new QAction(openIcon, tr("&Open Image..."), this); openAct->setShortcuts(QKeySequence::Open); -// openAct->setStatusTip(tr("Open an existing file")); + openAct->setStatusTip(tr("Open")); + fileToolBar->addAction(openAct); connect(openAct, &QAction::triggered, this, &MainWindow::open); - saveLogAct = new QAction(tr("&Save Log..."), this); + const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(rsrcPath + "/filesave.png")); + saveLogAct = new QAction(saveIcon, tr("&Save Log..."), this); saveLogAct->setShortcuts(QKeySequence::Save); saveLogAct->setEnabled(false); -// saveAct->setStatusTip(tr("Save the document to disk")); + saveLogAct->setStatusTip(tr("Save Log")); + fileToolBar->addAction(saveLogAct); connect(saveLogAct, &QAction::triggered, this, &MainWindow::saveLog); reprocessAct = new QAction(tr("Reprocess File"), this); reprocessAct->setShortcut(tr("Ctrl+R")); reprocessAct->setEnabled(false); // saveAct->setStatusTip(tr("Save the document to disk")); -// connect(saveAct, &QAction::triggered, this, &MainWindow::save); + connect(reprocessAct, &QAction::triggered, this, &MainWindow::reprocess); batchProcessAct = new QAction(tr("Batch Process..."), this); OffsetAct = new QAction(tr("Offset"), this); - printAct = new QAction(tr("&Print..."), this); + const QIcon printIcon = QIcon::fromTheme("document-print", QIcon(rsrcPath + "/fileprint.png")); + printAct = new QAction(printIcon, tr("&Print..."), this); printAct->setShortcuts(QKeySequence::Print); -// printAct->setStatusTip(tr("Print the document")); -// connect(printAct, &QAction::triggered, this, &MainWindow::print); + printAct->setStatusTip(tr("Print the document")); + fileToolBar->addAction(printAct); + connect(printAct, &QAction::triggered, this, &MainWindow::filePrint); + + fileToolBar->addSeparator(); printPreviewAct = new QAction(tr("Print Preview"), this); -// printAct->setStatusTip(tr("Print the document")); -// connect(printAct, &QAction::triggered, this, &MainWindow::print); +// printPreviewAct->setStatusTip(tr("Print the document")); + connect(printPreviewAct, &QAction::triggered, this, &MainWindow::filePrintPreview); printSetupAct = new QAction(tr("Print Setup..."), this); // printAct->setStatusTip(tr("Print the document")); @@ -140,7 +194,7 @@ void MainWindow::createActions(void) exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcuts(QKeySequence::Quit); // exitAct->setStatusTip(tr("Exit the application")); - connect(exitAct, &QAction::triggered, this, &MainWindow::Quit); + connect(exitAct, &QAction::triggered, this, &MainWindow::close); undoAct = new QAction(tr("Undo"), this); undoAct->setShortcuts(QKeySequence::Undo); @@ -168,35 +222,43 @@ void MainWindow::createActions(void) // Image Channel rgbAct = new QAction(tr("RGB"), this); rgbAct->setShortcut(tr("Alt+1")); + rgbAct->setData(PREVIEW_RGB); rgbAct->setCheckable(true); rgbAct->setChecked(true); yccAct = new QAction(tr("YCC"), this); yccAct->setShortcut(tr("Alt+2")); + yccAct->setData(PREVIEW_YCC); yccAct->setCheckable(true); rAct = new QAction(tr("R"), this); rAct->setShortcut(tr("Alt+3")); + rAct->setData(PREVIEW_R); rAct->setCheckable(true); gAct = new QAction(tr("G"), this); gAct->setShortcut(tr("Alt+4")); + gAct->setData(PREVIEW_G); gAct->setCheckable(true); bAct = new QAction(tr("B"), this); bAct->setShortcut(tr("Alt+5")); + bAct->setData(PREVIEW_B); bAct->setCheckable(true); yAct = new QAction(tr("Y (Greyscale)"), this); yAct->setShortcut(tr("Alt+6")); + yAct->setData(PREVIEW_Y); yAct->setCheckable(true); cbAct = new QAction(tr("Cb"), this); cbAct->setShortcut(tr("Alt+7")); + cbAct->setData(PREVIEW_CB); cbAct->setCheckable(true); crAct = new QAction(tr("Cr"), this); crAct->setShortcut(tr("Alt+8")); + crAct->setData(PREVIEW_CR); crAct->setCheckable(true); channelGroup = new QActionGroup(this); @@ -208,40 +270,62 @@ void MainWindow::createActions(void) channelGroup->addAction(yAct); channelGroup->addAction(cbAct); channelGroup->addAction(crAct); + connect(channelGroup, SIGNAL(triggered(QAction*)), imgWindow, SLOT(setPreviewTitle(QAction*))); + connect(channelGroup, SIGNAL(triggered(QAction*)), m_pImgDec, SLOT(setPreviewMode(QAction*))); // Image Zoom - zoomInAct = new QAction(tr("Zoom In")); + const QIcon zoomInIcon = QIcon::fromTheme("document-print", QIcon(rsrcPath + "/zoomin.png")); + zoomInAct = new QAction(zoomInIcon, tr("Zoom In")); + zoomInAct->setData(PRV_ZOOM_IN); zoomInAct->setShortcuts(QKeySequence::ZoomIn); + fileToolBar->addAction(zoomInAct); - zoomOutAct = new QAction(tr("Zoom Out")); + const QIcon zoomOutIcon = QIcon::fromTheme("document-print", QIcon(rsrcPath + "/zoomout.png")); + zoomOutAct = new QAction(zoomOutIcon, tr("Zoom Out")); + zoomOutAct->setData(PRV_ZOOM_OUT); zoomOutAct->setShortcuts(QKeySequence::ZoomOut); + fileToolBar->addAction(zoomOutAct); + + zoomInOutGroup = new QActionGroup(this); + zoomInOutGroup->addAction(zoomInAct); + zoomInOutGroup->addAction(zoomOutAct); + connect(zoomInOutGroup, SIGNAL(triggered(QAction*)), imgWindow, SLOT(zoom(QAction*))); zoom12_5Act = new QAction(tr("12.5%"), this); + zoom12_5Act->setData(PRV_ZOOM_12); zoom12_5Act->setCheckable(true); zoom12_5Act->setChecked(true); zoom25Act = new QAction(tr("25%"), this); + zoom25Act->setData(PRV_ZOOM_25); zoom25Act->setCheckable(true); zoom50Act = new QAction(tr("50%"), this); + zoom50Act->setData(PRV_ZOOM_50); zoom50Act->setCheckable(true); zoom100Act = new QAction(tr("100%"), this); + zoom100Act->setData(PRV_ZOOM_100); zoom100Act->setCheckable(true); zoom150Act = new QAction(tr("150%"), this); + zoom150Act->setData(PRV_ZOOM_150); zoom150Act->setCheckable(true); zoom200Act = new QAction(tr("200%"), this); + zoom200Act->setData(PRV_ZOOM_200); zoom200Act->setCheckable(true); zoom300Act = new QAction(tr("300%"), this); + zoom300Act->setData(PRV_ZOOM_300); zoom300Act->setCheckable(true); zoom400Act = new QAction(tr("400%"), this); + zoom400Act->setData(PRV_ZOOM_400); zoom400Act->setCheckable(true); - zoom500Act = new QAction(tr("500%"), this); + zoom500Act = new QAction(tr("800%"), this); + zoom500Act->setData(PRV_ZOOM_800); zoom500Act->setCheckable(true); zoomGroup = new QActionGroup(this); @@ -254,6 +338,7 @@ void MainWindow::createActions(void) zoomGroup->addAction(zoom300Act); zoomGroup->addAction(zoom400Act); zoomGroup->addAction(zoom500Act); + connect(zoomGroup, SIGNAL(triggered(QAction*)), imgWindow, SLOT(zoom(QAction*))); mcuGridAct = new QAction(tr("MCU Grid"), this); mcuGridAct->setShortcut(tr("Ctrl+G")); @@ -298,27 +383,27 @@ void MainWindow::createActions(void) // Options dhtExpandAct = new QAction(tr("DHT Expand"), this); dhtExpandAct->setCheckable(true); - dhtExpandAct->setChecked(m_pAppConfig->bOutputDHTexpand); + dhtExpandAct->setChecked(m_pAppConfig->expandDht()); connect(dhtExpandAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onOptionsDhtexpand())); hideUnknownTagsAct = new QAction(tr("Hide Unknown EXIF Tags"), this); hideUnknownTagsAct->setCheckable(true); - hideUnknownTagsAct->setChecked(m_pAppConfig->bExifHideUnknown); + hideUnknownTagsAct->setChecked(m_pAppConfig->hideUnknownExif()); connect(hideUnknownTagsAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onOptionsHideuknownexiftags())); makerNotesAct = new QAction(tr("Maker Notes"), this); makerNotesAct->setCheckable(true); - hideUnknownTagsAct->setChecked(m_pAppConfig->bDecodeMaker); + hideUnknownTagsAct->setChecked(m_pAppConfig->decodeMaker()); connect(makerNotesAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onOptionsMakernotes())); sigSearchAct = new QAction(tr("Signature Search"), this); sigSearchAct->setCheckable(true); - sigSearchAct->setChecked(m_pAppConfig->bSigSearch); + sigSearchAct->setChecked(m_pAppConfig->searchSig()); connect(sigSearchAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onOptionsSignaturesearch())); relaxedParseAct = new QAction(tr("Relaxed Parsing"), this); relaxedParseAct->setCheckable(true); - relaxedParseAct->setChecked(m_pAppConfig->bRelaxedParsing); + relaxedParseAct->setChecked(m_pAppConfig->relaxedParsing()); connect(relaxedParseAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onOptionsRelaxedparsing())); configAct = new QAction(tr("Configuration..."), this); @@ -329,7 +414,7 @@ void MainWindow::createActions(void) // Scan Segment menu decodeImageAct = new QAction(tr("Decode Image"), this); decodeImageAct->setCheckable(true); - decodeImageAct->setChecked(m_pAppConfig->bDecodeScanImg); + decodeImageAct->setChecked(m_pAppConfig->decodeImage()); connect(decodeImageAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentDecodeImage())); fullIdtcAct = new QAction(tr("Full IDCT (AC+DC - slow)"), this);; @@ -340,9 +425,7 @@ void MainWindow::createActions(void) noIdtcAct->setCheckable(true); connect(noIdtcAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentNoidct())); - qDebug() << "Action" << m_pAppConfig->bDecodeScanImgAc; - - if(m_pAppConfig->bDecodeScanImgAc) + if(m_pAppConfig->decodeAc()) { fullIdtcAct->setChecked(true); } @@ -357,17 +440,17 @@ void MainWindow::createActions(void) histogramRgbAct = new QAction(tr("Histogram RGB"), this);; histogramRgbAct->setCheckable(true); - histogramRgbAct->setChecked(m_pAppConfig->bHistoEn); + histogramRgbAct->setChecked(m_pAppConfig->displayRgbHistogram()); connect(histogramRgbAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentHistogram())); histogramYAct = new QAction(tr("Histogram Y"), this);; histogramYAct->setCheckable(true); - histogramYAct->setChecked(m_pAppConfig->bDumpHistoY); + histogramYAct->setChecked(m_pAppConfig->displayYHistogram()); connect(histogramYAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentHistogramy())); dumpAct = new QAction(tr("Dump"), this);; dumpAct->setCheckable(true); - dumpAct->setChecked(m_pAppConfig->bOutputScanDump); + dumpAct->setChecked(m_pAppConfig->scanDump()); connect(dumpAct, SIGNAL(triggered()), m_pAppConfig, SLOT(onScansegmentDump())); detailedDecodeAct = new QAction(tr("Detailed Decode..."), this); @@ -379,6 +462,8 @@ void MainWindow::createActions(void) m_pAppConfig->DebugLogAdd("MainWindow::createActions() End"); } +//----------------------------------------------------------------------------- + void MainWindow::createMenus(void) { if(DEBUG_EN) @@ -485,6 +570,8 @@ void MainWindow::createMenus(void) helpMenu->addAction(aboutAct); } +//----------------------------------------------------------------------------- + void MainWindow::open() { QFileDialog dialog(this); @@ -505,55 +592,62 @@ void MainWindow::open() if(dialog.exec()) { - QStringList files = dialog.selectedFiles(); + m_currentFile = dialog.selectedFiles().at(0); + + AnalyzeFile(); + } +} + +//----------------------------------------------------------------------------- - m_currentFile = files.at(0); +void MainWindow::AnalyzeFile() +{ + m_pFile = new QFile(m_currentFile); - m_pFile = new QFile(m_currentFile); + if(m_pFile->open(QIODevice::ReadOnly) == false) + { + QString strError; - if(m_pFile->open(QIODevice::ReadOnly) == false) + // Note: msg includes m_strPathName + strError = QString("ERROR: Couldn't open file: [%1]").arg(m_currentFile); + m_pDocLog->AddLineErr(strError); + + if(m_pAppConfig->interactive()) { - QString strError; + msgBox.setText(strError); + msgBox.exec(); + } - // Note: msg includes m_strPathName - strError = QString("ERROR: Couldn't open file: [%1]").arg(m_currentFile); - glb_pDocLog->AddLineErr(strError); + m_pFile = NULL; + } + else + { + // Set the file size variable + m_lFileSize = m_pFile->size(); + + // Don't attempt to load buffer with zero length file! + if(m_lFileSize > 0) + { + // Open up the buffer + m_pWBuf->BufFileSet(m_pFile); + m_pWBuf->BufLoadWindow(0); - if(m_pAppConfig->bInteractive) - { - msgBox.setText(strError); - msgBox.exec(); - } + // Mark file as opened + m_bFileOpened = true; - m_pFile = NULL; + enableMenus(); + AnalyzeFileDo(); + AnalyzeClose(); } else { - // Set the file size variable - m_lFileSize = m_pFile->size(); - - // Don't attempt to load buffer with zero length file! - if(m_lFileSize > 0) - { - // Open up the buffer - m_pWBuf->BufFileSet(m_pFile); - m_pWBuf->BufLoadWindow(0); - - // Mark file as opened - m_bFileOpened = true; - - enableMenus(); - AnalyzeFileDo(); - AnalyzeClose(); - } - else - { - m_pFile->close(); - } + m_pFile->close(); } } } +//----------------------------------------------------------------------------- + void MainWindow::AnalyzeFileDo() { if(DEBUG_EN) @@ -567,25 +661,25 @@ void MainWindow::AnalyzeFileDo() m_bFileAnalyzed = false; // Clear the document log - glb_pDocLog->Clear(); + m_pDocLog->Clear(); - glb_pDocLog->AddLine(""); - glb_pDocLog->AddLine(QString("JPEGsnoop %1 by Calvin Hass").arg(QString(VERSION_STR))); - glb_pDocLog->AddLine(" http://www.impulseadventure.com/photo/"); - glb_pDocLog->AddLine(" -------------------------------------"); - glb_pDocLog->AddLine(""); - glb_pDocLog->AddLine(QString(" Filename: [%1]").arg(m_currentFile)); - glb_pDocLog->AddLine(QString(" Filesize: [%1] bytes").arg(m_lFileSize)); - glb_pDocLog->AddLine(""); + m_pDocLog->AddLine(""); + m_pDocLog->AddLine(QString("JPEGsnoop %1 by Calvin Hass").arg(QString(VERSION_STR))); + m_pDocLog->AddLine(" http://www.impulseadventure.com/photo/"); + m_pDocLog->AddLine(" -------------------------------------"); + m_pDocLog->AddLine(""); + m_pDocLog->AddLine(QString(" Filename: [%1]").arg(m_currentFile)); + m_pDocLog->AddLine(QString(" Filesize: [%1] bytes").arg(m_lFileSize)); + m_pDocLog->AddLine(""); // Perform the actual decoding if(m_lFileSize > 0xFFFFFFFF) { - glb_pDocLog->AddLineErr(QString("ERROR: File too large for this version of JPEGsnoop. [Size=0x%1]").arg(m_lFileSize)); + m_pDocLog->AddLineErr(QString("ERROR: File too large for this version of JPEGsnoop. [Size=0x%1]").arg(m_lFileSize)); } else if(m_lFileSize == 0) { - glb_pDocLog->AddLineErr("ERROR: File length is zero, no decoding done."); + m_pDocLog->AddLineErr("ERROR: File length is zero, no decoding done."); } else { @@ -594,12 +688,38 @@ void MainWindow::AnalyzeFileDo() m_pJfifDec->ProcessFile(m_pFile); + int32_t h; + + if(m_pAppConfig->displayRgbHistogram() && m_pImgDec->isRgbHistogramReady()) + { + h = m_pImgDec->rgbHistogram()->height(); + rgbHisto->setPixmap(QPixmap::fromImage((*m_pImgDec->rgbHistogram()).scaled(rgbHisto->width(), h))); + } + + if(m_pAppConfig->displayYHistogram() && m_pImgDec->isRgbHistogramReady()) + { + h = m_pImgDec->yHistogram()->height(); + yHisto->setPixmap(QPixmap::fromImage((*m_pImgDec->yHistogram()).scaled(yHisto->width(), h))); + } + + if(m_pImgDec->m_bDibTempReady & m_pImgDec->m_bPreviewIsJpeg) + { + imgWindow->drawImage(); + } + // Now indicate that the file has been processed m_bFileAnalyzed = true; } } +//----------------------------------------------------------------------------- + +void MainWindow::updateImage() +{ + imgWindow->drawImage(); +} +//----------------------------------------------------------------------------- // Close the current file // - Invalidate the buffer // @@ -650,11 +770,13 @@ void MainWindow::saveLog() } QTextStream out(&file); - out << doc->toPlainText(); + out << textEdit->toPlainText(); file.close(); } +//----------------------------------------------------------------------------- + void MainWindow::enableMenus() { saveLogAct->setEnabled(true); @@ -672,14 +794,88 @@ void MainWindow::enableMenus() manageLocalDbAct->setEnabled(true); } +//----------------------------------------------------------------------------- + void MainWindow::onConfig() { - configDialog = new SnoopConfigDialog(); + configDialog = new SnoopConfigDialog(m_pAppConfig); configDialog->show(); } -void MainWindow::Quit() +//----------------------------------------------------------------------------- + +void MainWindow::filePrint() +{ + QPrinter printer(QPrinter::HighResolution); + QPrintDialog *dlg = new QPrintDialog(&printer, this); + + if (textEdit->textCursor().hasSelection()) + { + dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection); + } + + dlg->setWindowTitle(tr("Print Document")); + + if (dlg->exec() == QDialog::Accepted) + { + textEdit->print(&printer); + } + + delete dlg; +} + +//----------------------------------------------------------------------------- + +void MainWindow::reprocess() +{ + // Show coach message once + if(m_pAppConfig->decodeImage() && m_pAppConfig->coachIdct()) + { + // Show the coaching dialog + QString msg; + + if(m_pAppConfig->decodeAc()) + { + msg = strHiRes; + } + else + { + msg = strLoRes; + } + + Q_Note *note = new Q_Note(msg); + note->exec(); + m_pAppConfig->setCoachIdct(!note->hideStatus()); + } + + emit ImgSrcChanged(); + + textEdit->clear(); + AnalyzeFile(); + + // TODO: Handle AVI +} + +//----------------------------------------------------------------------------- + +void MainWindow::filePrintPreview() +{ + QPrinter printer(QPrinter::HighResolution); + QPrintPreviewDialog preview(&printer, this); + connect(&preview, &QPrintPreviewDialog::paintRequested, this, &MainWindow::printPreview); + preview.exec(); +} + +//----------------------------------------------------------------------------- + +void MainWindow::printPreview(QPrinter *printer) +{ + textEdit->print(printer); +} + +//----------------------------------------------------------------------------- + +void MainWindow::closeEvent(QCloseEvent *) { m_pAppConfig->RegistryStore(); - QApplication::quit(); } diff --git a/source/mainwindow.h b/source/mainwindow.h index 6455ca8..ff9cfa3 100644 --- a/source/mainwindow.h +++ b/source/mainwindow.h @@ -8,29 +8,44 @@ #include #include +class QPrinter; + class SnoopConfigDialog; -//class Q_Viewer; +class Q_Viewer; class CjfifDecode; class CimgDecode; class CwindowBuf; - +class CDocLog; +class CSnoopConfig; +class CDbSigs; class MainWindow : public QMainWindow { - Q_OBJECT + Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); - ~MainWindow(); + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + + QPlainTextEdit *textEdit; + +protected: + void closeEvent(QCloseEvent *e) override; - QPlainTextEdit *doc; -// Q_Viewer *v; +signals: + void ImgSrcChanged(); + +public slots: + void updateImage(); + void reprocess(); private slots: void open(); void saveLog(); void onConfig(); - void Quit(); + void filePrint(); + void filePrintPreview(); + void printPreview(QPrinter *); private: MainWindow &operator = (const MainWindow&); @@ -39,16 +54,23 @@ private slots: void createActions(void); void createMenus(void); void enableMenus(); + void AnalyzeFile(); void AnalyzeFileDo(); void AnalyzeClose(); + CDocLog *m_pDocLog; + CDbSigs *m_pDbSigs; + CSnoopConfig *m_pAppConfig; SnoopConfigDialog *configDialog; + Q_Viewer *imgWindow; // Decoders and Buffers CjfifDecode *m_pJfifDec; CimgDecode *m_pImgDec; CwindowBuf *m_pWBuf; + QToolBar *fileToolBar; + QMenu *fileMenu; QMenu *editMenu; QMenu *viewMenu; @@ -109,6 +131,7 @@ private slots: QAction *zoom400Act; QAction *zoom500Act; QActionGroup *zoomGroup; + QActionGroup *zoomInOutGroup; // Overlay menu QAction *mcuGridAct; @@ -159,6 +182,12 @@ private slots: bool m_bFileAnalyzed; // Have we opened and analyzed a file? bool m_bFileOpened; // Is a file currently opened? + QLabel *rgbHisto; + QLabel *yHisto; + + // Coach Messages + QString strLoRes; + QString strHiRes; }; #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/source/mainwindow.ui similarity index 100% rename from mainwindow.ui rename to source/mainwindow.ui diff --git a/source/note.cpp b/source/note.cpp new file mode 100644 index 0000000..8981e88 --- /dev/null +++ b/source/note.cpp @@ -0,0 +1,20 @@ +#include "note.h" +#include "ui_note.h" + +Q_Note::Q_Note(QString &msg, QWidget *parent) : QDialog(parent), + ui(new Ui::Q_Note) +{ + ui->setupUi(this); + + ui->lbCoachMsg->setText(msg); +} + +Q_Note::~Q_Note() +{ + delete ui; +} + +bool Q_Note::hideStatus() +{ + return ui->cbHideMsg->isChecked(); +} diff --git a/source/note.h b/source/note.h new file mode 100644 index 0000000..d432f34 --- /dev/null +++ b/source/note.h @@ -0,0 +1,23 @@ +#ifndef NOTE_H +#define NOTE_H + +#include + +namespace Ui { +class Q_Note; +} + +class Q_Note : public QDialog +{ + Q_OBJECT + +public: + explicit Q_Note(QString &msg, QWidget *parent = 0); + ~Q_Note(); + bool hideStatus(); + +private: + Ui::Q_Note *ui; +}; + +#endif // NOTE_H diff --git a/source/note.ui b/source/note.ui new file mode 100644 index 0000000..8f62c69 --- /dev/null +++ b/source/note.ui @@ -0,0 +1,113 @@ + + + Q_Note + + + + 0 + 0 + 592 + 138 + + + + JPEGSnoop - Note + + + true + + + + + 500 + 10 + 81 + 41 + + + + Qt::Vertical + + + QDialogButtonBox::Ok + + + + + + 10 + 10 + 481 + 101 + + + + + + + + + + Qt::AutoText + + + true + + + + + + + In the future, do not show this message + + + true + + + + + + + NOTE: You can always re-enable coach messages in Configuration + + + + + + + + + + buttonBox + accepted() + Q_Note + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Q_Note + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/source/resource.h b/source/resource.h deleted file mode 100644 index 9dfa5f9..0000000 --- a/source/resource.h +++ /dev/null @@ -1,204 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by JPEGsnoop.rc -// -#define IDS_CAL_EXE_OPEN 1 -#define IDR_CNTR_INPLACE 6 -#define IDD_ABOUTBOX 100 -#define IDP_OLE_INIT_FAILED 100 -#define IDP_FAILED_TO_CREATE 102 -#define IDD_SETTINGSDLG 103 -#define IDD_TERMSDLG 104 -#define IDD_UPDATEAVAILDLG 105 -#define IDD_MODELESSDLG 106 -#define IDD_NOTEDLG 107 -#define IDD_DBMANAGEDLG 109 -#define IDD_EXPORTDLG 112 -#define IDD_DECODEDETAILDLG 113 -#define IDD_EXPORTTIFFDLG 116 -#define IDD_BATCHDLG 117 -#define IDR_MAINFRAME 128 -#define IDR_JPEGsnoopTYPE 129 -#define IDR_MAINFRAME_BAK 129 -#define IDD_DBSUBMITDLG 130 -#define IDR_TEST1TYPE 130 -#define IDD_OVERLAYBUFDLG 131 -#define IDR_TEST2TYPE 131 -#define IDD_LOOKUP 132 -#define IDR_MAINFRAME2 132 -#define IDD_OFFSETDLG 133 -#define IDR_MAINFRAME3 133 -#define IDR_MAINFRAME_AVI 134 -#define IDR_MAINFRAME_ALL 135 -#define ID_INDICATOR_YCC 136 -#define IDS_CAL_FILEOPEN 137 -#define IDS_CAL_FILESAVE 138 -#define ID_INDICATOR_MCU 139 -#define ID_INDICATOR_FILEPOS 140 -#define IDD_OPERATIONDLG 145 -#define IDC_DB_DIR 1000 -#define IDC_URL 1001 -#define IDC_DB_DIR_BROWSE 1001 -#define IDC_URL_DOC 1002 -#define IDC_UPDATE_CHK 1002 -#define IDC_VER_NUM 1003 -#define IDC_DB_DIR_DEFAULT 1003 -#define IDC_EULA 1004 -#define IDC_EULA_OK 1005 -#define IDC_UPDATE_AUTO 1006 -#define IDC_BASEH 1007 -#define IDC_BUTTON1 1007 -#define IDC_BASED 1008 -#define IDC_VER_CUR 1008 -#define IDC_OFFSETVAL 1009 -#define IDC_VER_LATEST 1009 -#define IDC_X 1010 -#define IDC_UPDATE_AUTO_STILL 1010 -#define IDC_Y 1011 -#define IDC_OFFSET 1012 -#define IDC_DATE_LATEST 1012 -#define IDC_BTN_CALC 1013 -#define IDC_COACH_OFF 1013 -#define IDC_RNGX 1014 -#define IDC_MSG 1014 -#define IDC_RNGY 1015 -#define IDC_COACH_RESET 1015 -#define IDC_REPROCESS_AUTO 1016 -#define IDC_UPDATE_CHK_DAYS 1017 -#define IDC_OVRPOS 1018 -#define IDC_OVRNEW 1019 -#define IDC_OVRCUR 1020 -#define IDC_LIST 1020 -#define IDC_OVR_LOAD 1021 -#define IDC_REMOVEALL 1022 -#define IDC_OVRCURBIN 1022 -#define IDC_OVRLEN 1023 -#define IDC_REMOVE 1023 -#define IDC_OVREN 1024 -#define IDC_QUAL 1025 -#define IDC_DBSUBMIT_NET 1025 -#define IDC_MAKE 1026 -#define IDC_MODEL 1027 -#define IDC_SIG 1028 -#define IDC_RPTERRMAX_SCANDECODE 1028 -#define IDC_SOFTWARE 1029 -#define IDC_APPLY 1029 -#define IDC_RADIO_CAM 1031 -#define IDC_RADIO_SW 1032 -#define IDC_USER_SOFTWARE 1033 -#define IDC_RADIO_UNKNOWN 1035 -#define IDC_NOTES 1036 -#define IDC_OVERLAY 1052 -#define IDC_DHTAVI 1053 -#define IDC_OFFSET_START 1054 -#define IDC_EDIT1 1071 -#define IDC_EDIT2 1072 -#define IDC_EDIT3 1073 -#define IDC_CHECK1 1074 -#define IDC_FORCE_EOI 1077 -#define IDC_FORCE_SOI 1078 -#define IDC_IGNORE_EOI 1081 -#define IDC_BTN_LOAD 1109 -#define IDC_EDIT_FNAME 1112 -#define IDC_RAD_RGB16 1113 -#define IDC_RAD_YCC8 1114 -#define IDC_RAD_RGB8 1115 -#define IDC_CHECK_SUBDIRS 1117 -#define IDC_EDIT_DIR 1118 -#define ID_BTN_ABORT 1119 -#define IDC_PROGRESS_BAR 1120 -#define IDC_STATIC_PROGRESS 1121 -#define IDC_EXT_ALL 1122 -#define IDC_CHECK_EXT_ALL 1123 -#define IDC_BTN_DIR_SRC_BROWSE 1126 -#define IDC_BTN_DIR_DST_BROWSE 1127 -#define IDC_EDIT_DIR_SRC 1128 -#define IDC_EDIT_DIR_DST 1129 -#define ID_CANCEL_EDIT_CNTR 32768 -#define ID_TOOLS_DECODE 32771 -#define ID_FILE_OFFSET 32772 -#define ID_TOOLS_SEARCHFORWARD 32773 -#define ID_TOOLS_SEARCHREVERSE 32774 -#define ID_TOOLS_LOOKUPMCUOFFSET 32775 -#define ID_TOOLS_FILEOVERLAY 32776 -#define ID_TOOLS_DECODESCANRANGE 32777 -#define ID_TOOLS_ADDCAMERATODB 32778 -#define ID_TOOLS_RESETLOCALDB 32779 -#define ID_OPTIONS_DHTEXPAND 32780 -#define ID_OPTIONS_MAKERNOTES 32781 -#define ID_OPTIONS_SCANDUMP 32782 -#define ID_OPTIONS_SCANPARSE 32783 -#define ID_OPTIONS_HISTOYDUMP 32784 -#define ID_FILE_REPROCESS 32788 -#define ID_FILE_OPENIMAGE 32789 -#define ID_FILE_SAVELOG 32790 -#define ID_OPTIONS_DECODESCAN 32795 -#define ID_OPTIONS_CONFIGURATION 32796 -#define ID_OPTIONS_CHECKFORUPDATES 32799 -#define ID_PREVIEW_RGB 32800 -#define ID_PREVIEW_YCC 32801 -#define ID_PREVIEW_R 32802 -#define ID_PREVIEW_G 32803 -#define ID_PREVIEW_B 32804 -#define ID_PREVIEW_Y 32805 -#define ID_PREVIEW_CB 32806 -#define ID_PREVIEW_CR 32807 -#define ID_PREVIEWZOOM_ZOOMIN 32808 -#define ID_PREVIEWZOOM_ZOOMOUT 32809 -#define ID_PREVIEWZOOM_100 32810 -#define ID_PREVIEWZOOM_150 32811 -#define ID_PREVIEWZOOM_200 32812 -#define ID_PREVIEWZOOM_300 32813 -#define ID_PREVIEWZOOM_400 32814 -#define ID_PREVIEWZOOM_800 32815 -#define ID_TOOLS_SEARCHEXECUTABLEFORDQT 32819 -#define ID_TOOLS_MANAGELOCALDB 32820 -#define ID_OPTIONS_SIGNATURESEARCH 32821 -#define ID_TOOLS_EXTRACTEMBEDDEDJPEG 32822 -#define ID_OPTIONS_DECODEAC 32824 -#define ID_OPTIONS_SCANSEGMENT 32825 -#define ID_SCANSEGMENT_DECODEIMAGE 32826 -#define ID_SCANSEGMENT_FULLIDCT 32827 -#define ID_SCANSEGMENT_HISTOGRAMY 32828 -#define ID_SCANSEGMENT_SCANDUMP 32829 -#define ID_SCANSEGMENT_DUMP 32830 -#define ID_Menu 32831 -#define ID_VIEW_ZOOM 32832 -#define ID_VIEW_IMAGEZOOM 32833 -#define ID_IMAGEZOOM_ZOOMIN 32834 -#define ID_IMAGEZOOM_ZOOMOUT 32835 -#define ID_IMAGEZOOM_12 32836 -#define ID_IMAGEZOOM_25 32837 -#define ID_IMAGEZOOM_50 32838 -#define ID_IMAGEZOOM_100 32839 -#define ID_IMAGEZOOM_150 32840 -#define ID_IMAGEZOOM_200 32841 -#define ID_IMAGEZOOM_300 32842 -#define ID_IMAGEZOOM_400 32843 -#define ID_IMAGEZOOM_800 32844 -#define ID_SCANSEGMENT_NOIDCT 32849 -#define ID_TOOLS_LOOKUPMCUOFFSET32850 32850 -#define ID_TOOLS_FILEOVERLAY32851 32851 -#define ID_VIEW_OVERLAYS 32854 -#define ID_OVERLAYS_MCUGRID 32855 -#define ID_DEV_DELMCU2 32858 -#define ID_VIEW_ADJUST 32859 -#define ID_TOOLS_EXPORTMODIFIEDJPEG 32860 -#define ID_TOOLS_DETAILEDSCANDECODE 32870 -#define ID_SCANSEGMENT_DETAILEDDECODE 32871 -#define ID_SCANSEGMENT_HISTOGRAM 32872 -#define ID_OPTIONS_HIDEUKNOWNEXIFTAGS 32883 -#define ID_TOOLS_EXPORTTIFF 32884 -#define ID_FILE_BATCHPROCESS 32885 -#define ID_OPTIONS_RELAXEDPARSING 32886 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 147 -#define _APS_NEXT_COMMAND_VALUE 32887 -#define _APS_NEXT_CONTROL_VALUE 1130 -#define _APS_NEXT_SYMED_VALUE 118 -#endif -#endif diff --git a/source/snoop.h b/source/snoop.h index 133fc49..0389d0d 100644 --- a/source/snoop.h +++ b/source/snoop.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2018 - Calvin Hass +// Copyright (C) 2017 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -30,7 +30,7 @@ // - Note that when the version number is incremented, I need // to also update the corresponding version numbers in the // JPEGsnoop.rc resource under "Version.VS_VERSION_INFO". -#define VERSION_STR "2.0.0 (alpha)" +#define VERSION_STR "1.8.0" // Version number for the database signatures // - This version number has been provided in case I decide @@ -103,7 +103,7 @@ enum tePreviewMode PREVIEW_B, PREVIEW_Y, PREVIEW_CB, - PREVIEW_CR, + PREVIEW_CR }; enum tePreviewZoom @@ -119,6 +119,8 @@ enum tePreviewZoom PRV_ZOOM_400, PRV_ZOOM_800, PRV_ZOOMEND, + PRV_ZOOM_IN, + PRV_ZOOM_OUT }; // DB Signature modes @@ -127,14 +129,14 @@ enum teSource ENUM_SOURCE_UNSET = 0, ENUM_SOURCE_CAM, ENUM_SOURCE_SW, - ENUM_SOURCE_UNSURE, + ENUM_SOURCE_UNSURE }; enum teMaker { ENUM_MAKER_UNSET = 0, ENUM_MAKER_PRESENT, - ENUM_MAKER_NONE, + ENUM_MAKER_NONE }; enum teEdited @@ -143,14 +145,14 @@ enum teEdited EDITED_YES, EDITED_NO, EDITED_UNSURE, - EDITED_YESPROB, // Probably edited + EDITED_YESPROB // Probably edited }; enum teDbAdd { DB_ADD_SUGGEST_UNSET = 0, DB_ADD_SUGGEST_CAM, - DB_ADD_SUGGEST_SW, + DB_ADD_SUGGEST_SW }; enum teEditor @@ -158,14 +160,14 @@ enum teEditor ENUM_EDITOR_UNSET = 0, ENUM_EDITOR_CAM, ENUM_EDITOR_SW, - ENUM_EDITOR_UNSURE, + ENUM_EDITOR_UNSURE }; enum teLandscape { ENUM_LANDSCAPE_UNSET = 0, ENUM_LANDSCAPE_YES, - ENUM_LANDSCAPE_NO, + ENUM_LANDSCAPE_NO }; enum teOffsetMode @@ -176,6 +178,7 @@ enum teOffsetMode DEC_OFFSET_POS }; + // Define a few coach messages #define COACH_REPROCESS_AUTO "You have changed a processing option. To see these changes, "\ diff --git a/source/snoopconfigdialog.cpp b/source/snoopconfigdialog.cpp index da4c4b4..b3872c6 100644 --- a/source/snoopconfigdialog.cpp +++ b/source/snoopconfigdialog.cpp @@ -1,11 +1,12 @@ -#include "JPEGsnoop.h" +#include +#include + +#include "SnoopConfig.h" #include "snoopconfigdialog.h" #include "ui_snoopconfigdialog.h" -SnoopConfigDialog::SnoopConfigDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::SnoopConfigDialog) +SnoopConfigDialog::SnoopConfigDialog(CSnoopConfig *pAppConfig, QWidget *parent) : QDialog(parent), ui(new Ui::SnoopConfigDialog), m_pAppConfig(pAppConfig) { ui->setupUi(this); connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(onSave())); @@ -15,8 +16,7 @@ SnoopConfigDialog::SnoopConfigDialog(QWidget *parent) : connect(ui->btnDefault, SIGNAL(released()), this, SLOT(onDefault())); connect(ui->btnDefault, SIGNAL(released()), this, SLOT(onReset())); - dbPath = m_pAppConfig->dbPath(); - ui->leDbPath->setText(dbPath); + ui->leDbPath->setText(m_pAppConfig->dbPath()); bAutoUpdate = m_pAppConfig->swUpdateEnabled(); ui->cbAutoUpdate->setChecked(bAutoUpdate); @@ -38,12 +38,21 @@ SnoopConfigDialog::~SnoopConfigDialog() void SnoopConfigDialog::onBrowse() { + QFileDialog dialog(this); + + dialog.setDirectory(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); + dialog.setOption(QFileDialog::ShowDirsOnly); + if(dialog.exec()) + { + dbPath = dialog.selectedFiles().at(0); + ui->leDbPath->setText(dbPath); + } } void SnoopConfigDialog::onDefault() { - + ui->leDbPath->setText(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); } void SnoopConfigDialog::onReset() diff --git a/source/snoopconfigdialog.h b/source/snoopconfigdialog.h index efc32cf..9d82b68 100644 --- a/source/snoopconfigdialog.h +++ b/source/snoopconfigdialog.h @@ -7,12 +7,14 @@ namespace Ui { class SnoopConfigDialog; } +class CSnoopConfig; + class SnoopConfigDialog : public QDialog { Q_OBJECT public: - explicit SnoopConfigDialog(QWidget *parent = 0); + explicit SnoopConfigDialog(CSnoopConfig *pAppConfig, QWidget *parent = 0); ~SnoopConfigDialog(); private slots: @@ -28,6 +30,8 @@ private slots: Ui::SnoopConfigDialog *ui; + CSnoopConfig *m_pAppConfig; + QString dbPath; bool bAutoUpdate; bool bAutoReprocess; diff --git a/source/stdafx.cpp b/source/stdafx.cpp deleted file mode 100644 index c0a9155..0000000 --- a/source/stdafx.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// stdafx.cpp : source file that includes just the standard includes -// JPEGsnoop.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - diff --git a/source/stdafx.h b/source/stdafx.h deleted file mode 100644 index fb6bc3c..0000000 --- a/source/stdafx.h +++ /dev/null @@ -1,63 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, -// but are changed infrequently - -#pragma once - -#ifndef VC_EXTRALEAN -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#endif - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. -#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. -#define WINVER 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. -#endif - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. -#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. -#endif - -#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. -#define _WIN32_WINDOWS 0x0501 // Change this to the appropriate value to target Windows Me or later. -#endif - -#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. -#define _WIN32_IE 0x0501 // Change this to the appropriate value to target IE 5.0 or later. -#endif - -#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit - -// turns off MFC's hiding of some common and often safely ignored warning messages -#define _AFX_ALL_WARNINGS - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC OLE classes -#include // MFC OLE dialog classes -#include // MFC Automation classes - -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#include // MFC rich edit classes diff --git a/ui_q_decodedetaildlg.h b/ui_q_decodedetaildlg.h deleted file mode 100644 index fe4a828..0000000 --- a/ui_q_decodedetaildlg.h +++ /dev/null @@ -1,212 +0,0 @@ -/******************************************************************************** -** Form generated from reading UI file 'q_decodedetaildlg.ui' -** -** Created by: Qt User Interface Compiler version 5.11.0 -** -** WARNING! All changes made in this file will be lost when recompiling UI file! -********************************************************************************/ - -#ifndef UI_Q_DECODEDETAILDLG_H -#define UI_Q_DECODEDETAILDLG_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class Ui_Q_DecodeDetailDlg -{ -public: - QDialogButtonBox *buttonBox; - QGroupBox *groupBox; - QWidget *widget; - QHBoxLayout *horizontalLayout; - QLabel *label; - QLineEdit *leMcuX; - QSpacerItem *horizontalSpacer; - QLabel *label_2; - QLineEdit *leMcuY; - QGroupBox *groupBox_2; - QWidget *widget1; - QHBoxLayout *horizontalLayout_2; - QLabel *label_3; - QLineEdit *leNumMcus; - QCheckBox *cbEnableDec; - QLabel *label_4; - QWidget *widget2; - QVBoxLayout *verticalLayout; - QLabel *label_5; - QPushButton *pbLoadCoords; - - void setupUi(QDialog *Q_DecodeDetailDlg) - { - if (Q_DecodeDetailDlg->objectName().isEmpty()) - Q_DecodeDetailDlg->setObjectName(QStringLiteral("Q_DecodeDetailDlg")); - Q_DecodeDetailDlg->resize(462, 212); - Q_DecodeDetailDlg->setModal(true); - buttonBox = new QDialogButtonBox(Q_DecodeDetailDlg); - buttonBox->setObjectName(QStringLiteral("buttonBox")); - buttonBox->setGeometry(QRect(370, 10, 81, 61)); - buttonBox->setOrientation(Qt::Vertical); - buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); - groupBox = new QGroupBox(Q_DecodeDetailDlg); - groupBox->setObjectName(QStringLiteral("groupBox")); - groupBox->setGeometry(QRect(10, 10, 301, 61)); - groupBox->setStyleSheet(QLatin1String("QGroupBox {\n" -" border: 1px solid gray;\n" -" border-radius: 9px;\n" -" margin-top: 0.5em;\n" -"}\n" -"\n" -"QGroupBox::title {\n" -" subcontrol-origin: margin;\n" -" left: 10px;\n" -" padding: 0 3px 0 3px;\n" -"}")); - groupBox->setFlat(true); - widget = new QWidget(groupBox); - widget->setObjectName(QStringLiteral("widget")); - widget->setGeometry(QRect(10, 30, 270, 23)); - horizontalLayout = new QHBoxLayout(widget); - horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); - horizontalLayout->setContentsMargins(0, 0, 0, 0); - label = new QLabel(widget); - label->setObjectName(QStringLiteral("label")); - QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); - sizePolicy.setHorizontalStretch(0); - sizePolicy.setVerticalStretch(0); - sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); - label->setSizePolicy(sizePolicy); - - horizontalLayout->addWidget(label); - - leMcuX = new QLineEdit(widget); - leMcuX->setObjectName(QStringLiteral("leMcuX")); - leMcuX->setMinimumSize(QSize(61, 0)); - leMcuX->setMaximumSize(QSize(30, 21)); - - horizontalLayout->addWidget(leMcuX); - - horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - - horizontalLayout->addItem(horizontalSpacer); - - label_2 = new QLabel(widget); - label_2->setObjectName(QStringLiteral("label_2")); - sizePolicy.setHeightForWidth(label_2->sizePolicy().hasHeightForWidth()); - label_2->setSizePolicy(sizePolicy); - - horizontalLayout->addWidget(label_2); - - leMcuY = new QLineEdit(widget); - leMcuY->setObjectName(QStringLiteral("leMcuY")); - leMcuY->setMinimumSize(QSize(61, 0)); - leMcuY->setMaximumSize(QSize(61, 21)); - - horizontalLayout->addWidget(leMcuY); - - groupBox_2 = new QGroupBox(Q_DecodeDetailDlg); - groupBox_2->setObjectName(QStringLiteral("groupBox_2")); - groupBox_2->setGeometry(QRect(10, 80, 301, 61)); - groupBox_2->setStyleSheet(QLatin1String("QGroupBox {\n" -" border: 1px solid gray;\n" -" border-radius: 9px;\n" -" margin-top: 0.5em;\n" -"}\n" -"\n" -"QGroupBox::title {\n" -" subcontrol-origin: margin;\n" -" left: 10px;\n" -" padding: 0 3px 0 3px;\n" -"}")); - groupBox_2->setFlat(true); - widget1 = new QWidget(groupBox_2); - widget1->setObjectName(QStringLiteral("widget1")); - widget1->setGeometry(QRect(10, 30, 132, 23)); - horizontalLayout_2 = new QHBoxLayout(widget1); - horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); - horizontalLayout_2->setContentsMargins(0, 0, 0, 0); - label_3 = new QLabel(widget1); - label_3->setObjectName(QStringLiteral("label_3")); - - horizontalLayout_2->addWidget(label_3); - - leNumMcus = new QLineEdit(widget1); - leNumMcus->setObjectName(QStringLiteral("leNumMcus")); - sizePolicy.setHeightForWidth(leNumMcus->sizePolicy().hasHeightForWidth()); - leNumMcus->setSizePolicy(sizePolicy); - leNumMcus->setMinimumSize(QSize(61, 0)); - leNumMcus->setMaximumSize(QSize(31, 16777215)); - - horizontalLayout_2->addWidget(leNumMcus); - - cbEnableDec = new QCheckBox(Q_DecodeDetailDlg); - cbEnableDec->setObjectName(QStringLiteral("cbEnableDec")); - cbEnableDec->setGeometry(QRect(10, 150, 211, 20)); - label_4 = new QLabel(Q_DecodeDetailDlg); - label_4->setObjectName(QStringLiteral("label_4")); - label_4->setGeometry(QRect(10, 180, 421, 16)); - widget2 = new QWidget(Q_DecodeDetailDlg); - widget2->setObjectName(QStringLiteral("widget2")); - widget2->setGeometry(QRect(329, 90, 120, 81)); - verticalLayout = new QVBoxLayout(widget2); - verticalLayout->setObjectName(QStringLiteral("verticalLayout")); - verticalLayout->setContentsMargins(0, 0, 0, 0); - label_5 = new QLabel(widget2); - label_5->setObjectName(QStringLiteral("label_5")); - - verticalLayout->addWidget(label_5); - - pbLoadCoords = new QPushButton(widget2); - pbLoadCoords->setObjectName(QStringLiteral("pbLoadCoords")); - - verticalLayout->addWidget(pbLoadCoords); - -#ifndef QT_NO_SHORTCUT - label->setBuddy(leMcuX); - label_2->setBuddy(leMcuY); - label_3->setBuddy(leNumMcus); -#endif // QT_NO_SHORTCUT - - retranslateUi(Q_DecodeDetailDlg); - QObject::connect(buttonBox, SIGNAL(accepted()), Q_DecodeDetailDlg, SLOT(accept())); - QObject::connect(buttonBox, SIGNAL(rejected()), Q_DecodeDetailDlg, SLOT(reject())); - - QMetaObject::connectSlotsByName(Q_DecodeDetailDlg); - } // setupUi - - void retranslateUi(QDialog *Q_DecodeDetailDlg) - { - Q_DecodeDetailDlg->setWindowTitle(QApplication::translate("Q_DecodeDetailDlg", "Detailed Scan Decode Options", nullptr)); - groupBox->setTitle(QApplication::translate("Q_DecodeDetailDlg", "Starting MCU for Decode", nullptr)); - label->setText(QApplication::translate("Q_DecodeDetailDlg", "MCU X =", nullptr)); - label_2->setText(QApplication::translate("Q_DecodeDetailDlg", "MCU Y =", nullptr)); - groupBox_2->setTitle(QApplication::translate("Q_DecodeDetailDlg", "Length of Decode", nullptr)); - label_3->setText(QApplication::translate("Q_DecodeDetailDlg", "# MCUs =", nullptr)); - cbEnableDec->setText(QApplication::translate("Q_DecodeDetailDlg", "Enable detailed Scan Decode?", nullptr)); - label_4->setText(QApplication::translate("Q_DecodeDetailDlg", "Detailed Scan Decode will be reported in the next decode operation", nullptr)); - label_5->setText(QApplication::translate("Q_DecodeDetailDlg", "Load X/Y/Len\n" -"from last 2 clicks:", nullptr)); - pbLoadCoords->setText(QApplication::translate("Q_DecodeDetailDlg", "Load Coords", nullptr)); - } // retranslateUi - -}; - -namespace Ui { - class Q_DecodeDetailDlg: public Ui_Q_DecodeDetailDlg {}; -} // namespace Ui - -QT_END_NAMESPACE - -#endif // UI_Q_DECODEDETAILDLG_H diff --git a/ui_snoopconfigdialog.h b/ui_snoopconfigdialog.h deleted file mode 100644 index 3671995..0000000 --- a/ui_snoopconfigdialog.h +++ /dev/null @@ -1,309 +0,0 @@ -/******************************************************************************** -** Form generated from reading UI file 'snoopconfigdialog.ui' -** -** Created by: Qt User Interface Compiler version 5.11.0 -** -** WARNING! All changes made in this file will be lost when recompiling UI file! -********************************************************************************/ - -#ifndef UI_SNOOPCONFIGDIALOG_H -#define UI_SNOOPCONFIGDIALOG_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class Ui_SnoopConfigDialog -{ -public: - QDialogButtonBox *buttonBox; - QWidget *layoutWidget; - QVBoxLayout *verticalLayout_3; - QGroupBox *groupBox; - QWidget *layoutWidget1; - QHBoxLayout *horizontalLayout_2; - QLineEdit *leDbPath; - QVBoxLayout *verticalLayout; - QPushButton *btnBrowse; - QPushButton *btnDefault; - QGroupBox *groupBox_2; - QWidget *layoutWidget2; - QHBoxLayout *horizontalLayout; - QCheckBox *cbAutoUpdate; - QLineEdit *leUpdateDays; - QLabel *label_2; - QGroupBox *groupBox_3; - QWidget *layoutWidget3; - QVBoxLayout *verticalLayout_2; - QCheckBox *cbAutoReprocess; - QCheckBox *cbOblineDb; - QGroupBox *groupBox_4; - QWidget *layoutWidget4; - QHBoxLayout *horizontalLayout_3; - QLabel *label; - QLineEdit *leMaxErrors; - QGroupBox *groupBox_5; - QWidget *layoutWidget5; - QHBoxLayout *horizontalLayout_4; - QLabel *label_3; - QPushButton *btnReset; - - void setupUi(QDialog *SnoopConfigDialog) - { - if (SnoopConfigDialog->objectName().isEmpty()) - SnoopConfigDialog->setObjectName(QStringLiteral("SnoopConfigDialog")); - SnoopConfigDialog->resize(541, 426); - SnoopConfigDialog->setModal(true); - buttonBox = new QDialogButtonBox(SnoopConfigDialog); - buttonBox->setObjectName(QStringLiteral("buttonBox")); - buttonBox->setGeometry(QRect(440, 10, 81, 71)); - buttonBox->setOrientation(Qt::Vertical); - buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Save); - layoutWidget = new QWidget(SnoopConfigDialog); - layoutWidget->setObjectName(QStringLiteral("layoutWidget")); - layoutWidget->setGeometry(QRect(20, 10, 402, 406)); - verticalLayout_3 = new QVBoxLayout(layoutWidget); - verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3")); - verticalLayout_3->setContentsMargins(0, 0, 0, 0); - groupBox = new QGroupBox(layoutWidget); - groupBox->setObjectName(QStringLiteral("groupBox")); - groupBox->setMinimumSize(QSize(400, 80)); - groupBox->setStyleSheet(QLatin1String("QGroupBox {\n" -" border: 1px solid gray;\n" -" border-radius: 9px;\n" -" margin-top: 0.5em;\n" -"}\n" -"\n" -"QGroupBox::title {\n" -" subcontrol-origin: margin;\n" -" left: 10px;\n" -" padding: 0 3px 0 3px;\n" -"}")); - groupBox->setFlat(true); - layoutWidget1 = new QWidget(groupBox); - layoutWidget1->setObjectName(QStringLiteral("layoutWidget1")); - layoutWidget1->setGeometry(QRect(10, 10, 381, 71)); - horizontalLayout_2 = new QHBoxLayout(layoutWidget1); - horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); - horizontalLayout_2->setContentsMargins(0, 0, 0, 0); - leDbPath = new QLineEdit(layoutWidget1); - leDbPath->setObjectName(QStringLiteral("leDbPath")); - leDbPath->setMaximumSize(QSize(320, 20)); - - horizontalLayout_2->addWidget(leDbPath); - - verticalLayout = new QVBoxLayout(); - verticalLayout->setObjectName(QStringLiteral("verticalLayout")); - btnBrowse = new QPushButton(layoutWidget1); - btnBrowse->setObjectName(QStringLiteral("btnBrowse")); - - verticalLayout->addWidget(btnBrowse); - - btnDefault = new QPushButton(layoutWidget1); - btnDefault->setObjectName(QStringLiteral("btnDefault")); - - verticalLayout->addWidget(btnDefault); - - - horizontalLayout_2->addLayout(verticalLayout); - - - verticalLayout_3->addWidget(groupBox); - - groupBox_2 = new QGroupBox(layoutWidget); - groupBox_2->setObjectName(QStringLiteral("groupBox_2")); - groupBox_2->setMinimumSize(QSize(400, 60)); - groupBox_2->setStyleSheet(QLatin1String("QGroupBox {\n" -" border: 1px solid gray;\n" -" border-radius: 9px;\n" -" margin-top: 0.5em;\n" -"}\n" -"\n" -"QGroupBox::title {\n" -" subcontrol-origin: margin;\n" -" left: 10px;\n" -" padding: 0 3px 0 3px;\n" -"}")); - groupBox_2->setFlat(true); - layoutWidget2 = new QWidget(groupBox_2); - layoutWidget2->setObjectName(QStringLiteral("layoutWidget2")); - layoutWidget2->setGeometry(QRect(10, 20, 381, 31)); - horizontalLayout = new QHBoxLayout(layoutWidget2); - horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); - horizontalLayout->setContentsMargins(0, 0, 0, 0); - cbAutoUpdate = new QCheckBox(layoutWidget2); - cbAutoUpdate->setObjectName(QStringLiteral("cbAutoUpdate")); - cbAutoUpdate->setMaximumSize(QSize(260, 20)); - - horizontalLayout->addWidget(cbAutoUpdate); - - leUpdateDays = new QLineEdit(layoutWidget2); - leUpdateDays->setObjectName(QStringLiteral("leUpdateDays")); - leUpdateDays->setMaximumSize(QSize(40, 20)); - - horizontalLayout->addWidget(leUpdateDays); - - label_2 = new QLabel(layoutWidget2); - label_2->setObjectName(QStringLiteral("label_2")); - label_2->setMaximumSize(QSize(40, 20)); - - horizontalLayout->addWidget(label_2); - - - verticalLayout_3->addWidget(groupBox_2); - - groupBox_3 = new QGroupBox(layoutWidget); - groupBox_3->setObjectName(QStringLiteral("groupBox_3")); - groupBox_3->setMinimumSize(QSize(400, 80)); - groupBox_3->setStyleSheet(QLatin1String("QGroupBox {\n" -" border: 1px solid gray;\n" -" border-radius: 9px;\n" -" margin-top: 0.5em;\n" -"}\n" -"\n" -"QGroupBox::title {\n" -" subcontrol-origin: margin;\n" -" left: 10px;\n" -" padding: 0 3px 0 3px;\n" -"}")); - groupBox_3->setFlat(true); - layoutWidget3 = new QWidget(groupBox_3); - layoutWidget3->setObjectName(QStringLiteral("layoutWidget3")); - layoutWidget3->setGeometry(QRect(10, 20, 335, 41)); - verticalLayout_2 = new QVBoxLayout(layoutWidget3); - verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2")); - verticalLayout_2->setContentsMargins(0, 0, 0, 0); - cbAutoReprocess = new QCheckBox(layoutWidget3); - cbAutoReprocess->setObjectName(QStringLiteral("cbAutoReprocess")); - - verticalLayout_2->addWidget(cbAutoReprocess); - - cbOblineDb = new QCheckBox(layoutWidget3); - cbOblineDb->setObjectName(QStringLiteral("cbOblineDb")); - - verticalLayout_2->addWidget(cbOblineDb); - - - verticalLayout_3->addWidget(groupBox_3); - - groupBox_4 = new QGroupBox(layoutWidget); - groupBox_4->setObjectName(QStringLiteral("groupBox_4")); - groupBox_4->setMinimumSize(QSize(400, 60)); - groupBox_4->setMaximumSize(QSize(16777215, 60)); - groupBox_4->setStyleSheet(QLatin1String("QGroupBox {\n" -" border: 1px solid gray;\n" -" border-radius: 9px;\n" -" margin-top: 0.5em;\n" -"}\n" -"\n" -"QGroupBox::title {\n" -" subcontrol-origin: margin;\n" -" left: 10px;\n" -" padding: 0 3px 0 3px;\n" -"}")); - groupBox_4->setFlat(true); - layoutWidget4 = new QWidget(groupBox_4); - layoutWidget4->setObjectName(QStringLiteral("layoutWidget4")); - layoutWidget4->setGeometry(QRect(10, 20, 325, 31)); - horizontalLayout_3 = new QHBoxLayout(layoutWidget4); - horizontalLayout_3->setObjectName(QStringLiteral("horizontalLayout_3")); - horizontalLayout_3->setContentsMargins(0, 0, 0, 0); - label = new QLabel(layoutWidget4); - label->setObjectName(QStringLiteral("label")); - label->setMinimumSize(QSize(240, 20)); - label->setMaximumSize(QSize(240, 20)); - - horizontalLayout_3->addWidget(label); - - leMaxErrors = new QLineEdit(layoutWidget4); - leMaxErrors->setObjectName(QStringLiteral("leMaxErrors")); - leMaxErrors->setMaximumSize(QSize(40, 20)); - - horizontalLayout_3->addWidget(leMaxErrors); - - - verticalLayout_3->addWidget(groupBox_4); - - groupBox_5 = new QGroupBox(layoutWidget); - groupBox_5->setObjectName(QStringLiteral("groupBox_5")); - groupBox_5->setMinimumSize(QSize(400, 60)); - groupBox_5->setMaximumSize(QSize(16777215, 60)); - groupBox_5->setStyleSheet(QLatin1String("QGroupBox {\n" -" border: 1px solid gray;\n" -" border-radius: 9px;\n" -" margin-top: 0.5em;\n" -"}\n" -"\n" -"QGroupBox::title {\n" -" subcontrol-origin: margin;\n" -" left: 10px;\n" -" padding: 0 3px 0 3px;\n" -"}")); - groupBox_5->setFlat(true); - layoutWidget5 = new QWidget(groupBox_5); - layoutWidget5->setObjectName(QStringLiteral("layoutWidget5")); - layoutWidget5->setGeometry(QRect(10, 10, 311, 48)); - horizontalLayout_4 = new QHBoxLayout(layoutWidget5); - horizontalLayout_4->setObjectName(QStringLiteral("horizontalLayout_4")); - horizontalLayout_4->setContentsMargins(0, 0, 0, 0); - label_3 = new QLabel(layoutWidget5); - label_3->setObjectName(QStringLiteral("label_3")); - label_3->setMaximumSize(QSize(230, 20)); - - horizontalLayout_4->addWidget(label_3); - - btnReset = new QPushButton(layoutWidget5); - btnReset->setObjectName(QStringLiteral("btnReset")); - btnReset->setMinimumSize(QSize(80, 32)); - btnReset->setMaximumSize(QSize(80, 32)); - - horizontalLayout_4->addWidget(btnReset); - - - verticalLayout_3->addWidget(groupBox_5); - - - retranslateUi(SnoopConfigDialog); - - QMetaObject::connectSlotsByName(SnoopConfigDialog); - } // setupUi - - void retranslateUi(QDialog *SnoopConfigDialog) - { - SnoopConfigDialog->setWindowTitle(QApplication::translate("SnoopConfigDialog", "JPEGsnoop Confguration", nullptr)); - groupBox->setTitle(QApplication::translate("SnoopConfigDialog", "Directory for User Database", nullptr)); - btnBrowse->setText(QApplication::translate("SnoopConfigDialog", "Browse", nullptr)); - btnDefault->setText(QApplication::translate("SnoopConfigDialog", "Default", nullptr)); - groupBox_2->setTitle(QApplication::translate("SnoopConfigDialog", "Software Update", nullptr)); - cbAutoUpdate->setText(QApplication::translate("SnoopConfigDialog", "Automatically check for updates every ", nullptr)); - label_2->setText(QApplication::translate("SnoopConfigDialog", "days", nullptr)); - groupBox_3->setTitle(QApplication::translate("SnoopConfigDialog", "Processing Options", nullptr)); - cbAutoReprocess->setText(QApplication::translate("SnoopConfigDialog", "Auto Reprocess files on change in Options (slower)", nullptr)); - cbOblineDb->setText(QApplication::translate("SnoopConfigDialog", "Submit signature to Online DB when User submit", nullptr)); - groupBox_4->setTitle(QApplication::translate("SnoopConfigDialog", "Report Settings", nullptr)); - label->setText(QApplication::translate("SnoopConfigDialog", "Max # errors to report in Scan Decode", nullptr)); - groupBox_5->setTitle(QApplication::translate("SnoopConfigDialog", "Help", nullptr)); - label_3->setText(QApplication::translate("SnoopConfigDialog", "Coach Messages can be re-enabled:", nullptr)); - btnReset->setText(QApplication::translate("SnoopConfigDialog", "Reset", nullptr)); - } // retranslateUi - -}; - -namespace Ui { - class SnoopConfigDialog: public Ui_SnoopConfigDialog {}; -} // namespace Ui - -QT_END_NAMESPACE - -#endif // UI_SNOOPCONFIGDIALOG_H From 59c0ed6fd1dff0a4c5c683017b15b450049f34ea Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Tue, 24 Jul 2018 22:53:34 -0700 Subject: [PATCH 03/14] Add images/ resource files from Bob Parker (archive 2018/07/23) --- images/jpegsnoop.ico | Bin 0 -> 25214 bytes images/mac/editcopy.png | Bin 0 -> 1468 bytes images/mac/editcut.png | Bin 0 -> 1512 bytes images/mac/editpaste.png | Bin 0 -> 1906 bytes images/mac/editredo.png | Bin 0 -> 1752 bytes images/mac/editundo.png | Bin 0 -> 1746 bytes images/mac/exportpdf.png | Bin 0 -> 1215 bytes images/mac/filenew.png | Bin 0 -> 1172 bytes images/mac/fileopen.png | Bin 0 -> 2168 bytes images/mac/fileprint.png | Bin 0 -> 2087 bytes images/mac/filesave.png | Bin 0 -> 1206 bytes images/mac/textbold.png | Bin 0 -> 1611 bytes images/mac/textcenter.png | Bin 0 -> 1404 bytes images/mac/textitalic.png | Bin 0 -> 1164 bytes images/mac/textjustify.png | Bin 0 -> 1257 bytes images/mac/textleft.png | Bin 0 -> 1235 bytes images/mac/textright.png | Bin 0 -> 1406 bytes images/mac/textunder.png | Bin 0 -> 1183 bytes images/mac/zoomin.png | Bin 0 -> 1696 bytes images/mac/zoomout.png | Bin 0 -> 1662 bytes images/win/editcopy.png | Bin 0 -> 1325 bytes images/win/editcut.png | Bin 0 -> 1896 bytes images/win/editpaste.png | Bin 0 -> 1482 bytes images/win/editredo.png | Bin 0 -> 1787 bytes images/win/editundo.png | Bin 0 -> 1768 bytes images/win/exportpdf.png | Bin 0 -> 1059 bytes images/win/filenew.png | Bin 0 -> 768 bytes images/win/fileopen.png | Bin 0 -> 1662 bytes images/win/fileprint.png | Bin 0 -> 1456 bytes images/win/filesave.png | Bin 0 -> 1205 bytes images/win/textbold.png | Bin 0 -> 1134 bytes images/win/textcenter.png | Bin 0 -> 627 bytes images/win/textitalic.png | Bin 0 -> 829 bytes images/win/textjustify.png | Bin 0 -> 695 bytes images/win/textleft.png | Bin 0 -> 673 bytes images/win/textright.png | Bin 0 -> 677 bytes images/win/textunder.png | Bin 0 -> 971 bytes images/win/zoomin.png | Bin 0 -> 1208 bytes images/win/zoomout.png | Bin 0 -> 1226 bytes 39 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/jpegsnoop.ico create mode 100644 images/mac/editcopy.png create mode 100644 images/mac/editcut.png create mode 100644 images/mac/editpaste.png create mode 100644 images/mac/editredo.png create mode 100644 images/mac/editundo.png create mode 100644 images/mac/exportpdf.png create mode 100644 images/mac/filenew.png create mode 100644 images/mac/fileopen.png create mode 100644 images/mac/fileprint.png create mode 100644 images/mac/filesave.png create mode 100644 images/mac/textbold.png create mode 100644 images/mac/textcenter.png create mode 100644 images/mac/textitalic.png create mode 100644 images/mac/textjustify.png create mode 100644 images/mac/textleft.png create mode 100644 images/mac/textright.png create mode 100644 images/mac/textunder.png create mode 100644 images/mac/zoomin.png create mode 100644 images/mac/zoomout.png create mode 100644 images/win/editcopy.png create mode 100644 images/win/editcut.png create mode 100644 images/win/editpaste.png create mode 100644 images/win/editredo.png create mode 100644 images/win/editundo.png create mode 100644 images/win/exportpdf.png create mode 100644 images/win/filenew.png create mode 100644 images/win/fileopen.png create mode 100644 images/win/fileprint.png create mode 100644 images/win/filesave.png create mode 100644 images/win/textbold.png create mode 100644 images/win/textcenter.png create mode 100644 images/win/textitalic.png create mode 100644 images/win/textjustify.png create mode 100644 images/win/textleft.png create mode 100644 images/win/textright.png create mode 100644 images/win/textunder.png create mode 100644 images/win/zoomin.png create mode 100644 images/win/zoomout.png diff --git a/images/jpegsnoop.ico b/images/jpegsnoop.ico new file mode 100644 index 0000000000000000000000000000000000000000..61893cf0631bfcfc2c3562d17e7850ed7064346e GIT binary patch literal 25214 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 Byovw- literal 0 HcmV?d00001 diff --git a/images/mac/editcopy.png b/images/mac/editcopy.png new file mode 100644 index 0000000000000000000000000000000000000000..f551364464a7f4500a2660fd3aa450e79010b0cb GIT binary patch literal 1468 zcmV;t1w;CYP)j91nuo^rMU``FpK}lmcH2BoZ zAH4JCyEWmjwMzgT#=uOCdmd7JuO$v)s8lK_84mKr3f?+?`0VR1?tg<)*HQ}J{^;_d zx+S0Y_4P-WQtN}){+tE#xOPNB3Z5T~fVOJdJdnQKmA@NUp8wZ z?$zp{)J%XNrjyRSus42A?Cl?jb<@afrs%r1WnkxaM7vZ3@+)At< zl`TV!sF2PwGTtu5AKvyjs4rA-qt%${9h(@D41&{(T zn8XDH>P|Q8whCx0La*w<^E@zO22eD33b<_!Q`>H{03sKo>$;F2@wvzODg1sK81Se7 zXg2VlTtfnRF4nRvL9>8>%_G3Q_jpaTF#^JSA{Ha<@i)NsIHARWyv9?(=O$}&1Ssr8 zEDDn5bPZisMnMBy1?bt#Jx4g$#%n0TPNX!_qa+0JbW~kLfJ9nCPGg4pF{+ML3+gaHLO^`>>3d5AaWOXXLDedCV3tU)P&1)oPTCjX*K5}0@QqH zO(G~76n^TCB#t^`Ik$*k#>bF(lmH~zwB+suqqLR=5F{VyIR3p>h-svrPjk~WiIfCT zL!y!I&5m8e$d!l4mh?p>q)stJ7Fjj8$jsFE%#H5~03raG4_Dc!$cT(gi@c~ zLseB0#6L51ows7ID$$1^8eBO$E%%%;5Jcm#~)CE0Jxx)4}dz+2FRW35VI&O1b5c ztKVJ_qymyagMj8jXkHb6&l~<30XPL<7Qj^iH-Gr@Oj@d$Ao7XPguGq^8idrf;(q`V WtAfH(WC6_p0000P)<*VVWcuS0Ev&yc^UgmMxPuCq=o+h)UUDGbvCiz9KZ#z>#2T zH*7#DEhZZSSjH(6t!!&*4Y=|TLKTXy*{F8wRwLgUrhFc}3~-1;E4$B<4F?4UCH_=X(?2pYg3Kt<)7W_X9hIt7q`_@k0wj;P zCfM+)m>3-G@5iiwfL76-3y8I0zP_2K%FFu)2M1B&N>2}dn~=~air9DByWrkbv=$cr zW-u6#IhUKu`P>}h9olgM)(;$H&K!xq0;} zmZYZMsIIQY*49?+?Cdmh{`6@qiHp0);s~!9ZNqy7us5e`YOW0r52ISG#^mH=tgWrZ z;^Jb|YPER0Aph2D9v%mU*9&I6j%Do_vBJS&_ko0j>t$tS#t{4a`=gDG4Gs(p;PHkA zOo@)}p3bJ6%BYPfuy?umb~`)&d?Yt_vZA5_v$L}?FE0-(D=V?Sz8)`Kx@6?CPG<;E zsnQ=5_9+F>$CJI__W+)D`vJy`ZD(eN1y)w5NlU}S`T3K(Vq<%gZN12L2=UTp0B0!K&mQ7SXV z{VXv z>S`#owl-dS9bgBYJtX4^;?#e#IfgL1l?{0uT_METfDHM8dfVYJ(58)+?c}9jxoO5BWAeIx)5pQns^E+0Ukuh;h ztv1mAZ^%=ymh-Ri^1_23+|>mnbq&=)SAjx-yzfh#osAUHgyWqb0uWC>@)i$fL!<{nxj2az zWULo$M?Zl;A;wokgwx|B(xbTVAc`Ty+W|iR44{biW-+;(vhGgE-Txy2O3^8bsV1R< zm`6NJ*b_@c-e-~mXEE9>Oc7uvhRb}>at@-pm;H+(Tq2CyifPM^nN7Kjgot@UgtZ8t zy~v}fZOFnG2`AXNx!ikGwxJ|~!)7H?Vr{}8S}4N(h%js^o}-X^&-@MJSdp!hcmgc| O00002`C_)0KC{3#V>P6y5 z{***fN|TDJMNOkdidvOO7HMchA*}*}7Gf?oHpW-*jkUcO@9yl*<#ae&W!3d!3;Ig0 z&S=gYeb4#6Z_dsNDJA73gxC(OXK{5&DgVxWN&%DvUaM(Z)C2pT<2W5GBJbHh0G$Pp zUhYv^>8=kvz3Hc~@7wwFCpNBm^5Vsd3=R!3H0XJ#;K4yPdiU|>+5P0^XFhm!=WA=5 z!q0i|5$;h&3BZQ-Xm(dsWsa*MNl#A?;c%F{DV0iLObygI-2-(?v~(&$`FtMRwyCYHr6N8>qC&%Vxi1+d^%O{OfySWV z!oU88nVCbwMFIkd=q|b@@Cku&Te2)-AaKE`2t4(|&%XZBFS{NBHULqe8E8R?&w+Oi z|6qMzS%4!)jtE`XHK{oYVAZM>_%b?@5K>CdAOzHhg9HqnfKOvQE4V%}$-gJZ2yWWB zXY00Ydn&>qmevLc1$3$_b?U-?qE&u+Mw0EvKAQ>v`%3`kccl<`ivz5QR+6jKxa;R+-IR|+(t?knF)Iehi$%|z?!Rd1A$>X&3PNiY~x&HVlC&Di#hB191Y z_U_#)J32aCLkN5t_;n4#(9sasx{E7O0EVU!Ff{dyna!#oKA(?rvMh^4B0)_}jRFV+ z0_Z#-&H6t3$^q3ak1s>THFTx-nbY~tx0*}RSANJ4&{*(}tW zCJV`N95R`VDg(tvXJbo%O9R>GfukBlAwB6D7&`cU0$WN3VkxdB4UAP=c(DChzP#gQ z>bE>g&BI%{)<44O)2E5WVyfn+PMzZL;lpYyp0IHI_;C&$I>f<)2kGqWr2obsww>36 zr}+T70$^x1%ehI1)*T&e`{7Y4x4y#o13S3vJjP}D1exV~XnA};mZ;;{hn?zF93GwI zn@{cK%9Se$K-YCbp%9gomFhYYiC`E8u4+>EE^mPlOlBqVrLBDDz%NMY^(0a`gl>T* zNatK)ag$UkPj}wsa#ethty{R#+s9b8jhV9(7%G7LB4|rXi#oJ~5L8uFF_8psPL>4_ z8Vsi-yI%Y;;U&u$>3o-|{>vDF3R+t>uzb~{^iG7iF`ObcV=_9GVa&538kveEXn!n7 zLlHpj-rF^Gb#(v=D&?fT(Ux~KKLZ-HLC z+c&t_6KBlMkV@uBr!CJm2tXFk1n&(|0EMGof%%L)LYH^Xz_N%SZx7(Fj8M0-mV#K( zP(?gr(SPb~lJ)=Lp@&}}nf75>4z}Ye8$Jzbstiyf1*J@Ju3QF`8zMe@p#Y_-t@QCg z*w5K3XIcNqZbCtWtY_Pno?Q%G15k}7C<+M(i7aM^yJkRHsBxao56mz)Yq6u_EqZ37 z=z$c$pss@3mVwXEP`h+pBqfp*<`x0aG=WfNp8BU!y!u`j{kPJHYLn*r3bLj{&a^ST zantG=&YUP;0$}kH2=TvJC{=4ynAdl&XDDH#H>_sOy056tE{HQD(AL(rFo0aF2No#7 zD_J_{-WPyG0%G9|WX8Gyia|}uXhL!=<}#L& z=3u@q@$IS=jrR)RIF2$H3%`bz12b7k|BUBpmx(!PPNil4Y*zLU$7RpDE$!>8n_8bK z0xTYQdU~4C(NQMSL10eq#J$~ z14yUS>VHI6R~I)1N71TR5^3HH8t;??82xnExzRl($H!B$%YzvLCV_Dv4fp^Z2wHj5 za2=-{fcgNLn3zyM%iZ1G#L_x}hP70!-iGE6{oc}yx4p09bL9ZK{@CUG1c(6xfC+?w zN+7^INeTce#WOQAT)%#uOP4M&IzCO_*F;6bX8d)Lv#xaB8@_h#Pk;U0k8XRwZrQiM zo9GonTn98DPzam{bU*@5VNUn?gSJF4Gds(~__zu>Ff>Zau0pSFK{P!&W~CD!4xIbw zgG;C1?*rxllM)%smn;S&2ME9^fEZr@1VXWqTT@*9>@Q4b1NfuO7>(NzX7ndJ0| s3m^aXw#k*dH0@s?zwlm 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 RY-0cb002ovPDHLkV1oVh`pp0U literal 0 HcmV?d00001 diff --git a/images/mac/filesave.png b/images/mac/filesave.png new file mode 100644 index 0000000000000000000000000000000000000000..b41ecf5319863b3c5319579e19116f346802563b GIT binary patch literal 1206 zcmV;n1WEgeP)&5=xu1RdJ#IDvEdG#3 zHaCTnPtA0PfLqE+VPYbS+|emGrh`l-GZFyPPdo~Dysj3;K6>T=x3rysAOY8jkHDy!V7X1OV!!}8XFd%6MIs~jQ1$9!5 zC684vblv5b$90roQufLluWeb+J+m-_W$hJgV2{9qtn45cPc!se-reB4C7@O=? zSt*nu*e2O#AAJF6LZvoJVsqj}O+|wL3Pm)M5-y^j?GN-k$3p6HY%j6jAAryzwER*m zLs|wz+R}70^>H|C-W?nQS~*cHDGZ{aDOW;cNnsIwkl0J?_X8jj-vZu53TIz?{%{+e zcMXH`+@8}HmVc#PDfV&nWk3k!TnGclk5AD8QzI!vY^zk-RdzcObTA-b(Ec|J0oQTx z^MzH6AMsRuxR=J;y1KikY#D~3L<|C8@aher6t7*cVC%1H5*o<;^f~w~q8vk4bobM` zNtMxL=WKf*14_Y&(3*hGV1l(eK~iWF&sN~0=cP& z4-*2tdZvpj*2f=xfSsKk)M_=fTCD`2Mb$ADPE_t0G|#EnQ_=D1aEj&gFTPSXS=h%A z1~?B4OlEV*{}&e*v9z?L9B=`eot>pBId^Cl*p`TLppyZk6F{7V4rOlKip3(G<#bQT z<&+c(g(1~hc7(x67AC}yLZrhW)TtLYmyTIJ8Dom$zF+HFrP7x@cgdX$AVSC>4j4I@ zJlx;)?ufRmj1IX0mGD5>?uqx_8s9DWF5uIRiKQU z25$Ym-5NbgsDi-@lIk0gSG! UB0_&5sQ>@~07*qoM6N<$f^ZKn4*&oF literal 0 HcmV?d00001 diff --git a/images/mac/textbold.png b/images/mac/textbold.png new file mode 100644 index 0000000000000000000000000000000000000000..38400bd1f69dd4b49ffc29bb2f0eddd14ca39a34 GIT binary patch literal 1611 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 KMNUMnLSTZ+RFne% literal 0 HcmV?d00001 diff --git a/images/mac/textitalic.png b/images/mac/textitalic.png new file mode 100644 index 0000000000000000000000000000000000000000..0170ee26a6fc568e9b6490e4a45e04f4ff55a19e GIT binary patch literal 1164 zcmV;71atd|P)8>eW)l!AzGVM8#k=|EC4uK5YENM=>0xku0=q3%Tx@Cy=CPKKK1sA6|N30mSsXZy!Ca>jN5} z@ZcGS$#QE2LlE2rz5BYAo}Mll$j*K|%ZG;~fQZL?LqSQAOdFul0MPYJH;4ctijdG_ z5a~b(`Hfo!07M>23W&KczB~`e8_x_6C8wrdNy$o7u}}z)Kro07?K(Su>4*Gx7p`nl zYUZGg?Wzc=9^N~4?4`4#hsF{$6F`yxG!9=sR6)3Adm7^=0c_h{z*wD?ikr7E|LeX9p!`Qe zVeP4KSFcvH+yh7q@bIs-s^8}b3=O7Jp<2z&ze5H1Pq9G#@4tX-A{Eza)PCFo0f43J zf9+WWM&o)q!f!u|`adWGtSsjY%>SN5V5F-z$qNt|N&E^sblsUNiKxfZ@+X4Irqzh>Aw?C>se*5X~I8~7jLZNj*@*{BD zUO@ZJ6-0e@^8J@X;qYXrI~6f%?iI`!&wr`Ln7#Z+EHeNAQF?%ekr1Mh7@7R-EPzys zNMQ8U4<=rC^VDZ!Z=E?eG<P`TXFfSHJ*D@>`qd^VQnd=ezrG9QHJSSY3ZUEJ=g0fT zkBs-_mRAPPef`bB&Gp5TrIm#Z0I)p%8PY(gCfXOF5Rm204owR<;0UEc(d27P!)zAv z>vbwKP*hdwkH?iQ{H1)`U1(GcsNO9#DD)!I^av5}xeI=opS|HYaAtXF@pWvmAUI8_ z(XdUkdS?wBM?e9h6p%GVjie}d4j*n8Z(gq4Eg27b4mb$=_2TSh9Iqm(H;;%!qwt?K zO%DykBJ5W9ckTj*U`QP?kP1>pw(f&6t*at6Z~ogxz(J$Kqk#Y|vgv>H<;eCC@J4|V ewuk0+hta>;sLepRg`ge)0000=P)qhXCOuvAB1>1$~LJ*45g^Hl43wge}u?lK;3c7G(7uL^E5Eoro zL90--YNtA5+o_%DOxu}v?@f*&Sp>rMPN^99b8>IaBe^-hcTOUz%0ca^6AJ+Zpx8kv zWP9O@xpHtrR5ed>eDMZwjNv9D?{#!B!#aQA-27btM`_2-d@w(oGBLD$fDmHeVGMDMWL2|_QD!rE>$TGWX#s}PlC!gbz@_VO zXlCQ&mP>1bh_Gw}-~6m;@(`47*RpTpO!R@^eOm0-S2}th@F66hw(D4#!o^>eiIwpX z48&QA%JXpi(W8Y}d@=f@49>lJH+@2+_S0fis_ z1ZNGiY3#2HjdKw^!%u&Kk&poYKKfXr)DY&_D>a0*Ol5~443(_~pu-^$&H(QLHmN{2 z&0>}6J-a08bXeKbauYFzYj>x zgiT{m1<(kOu)WjatWEDBXTixtl8*+#H5t<2g=O0@om%=nXGsy*-Cgp;<5OOGc^E>m z0;tlq9anC^-d>9Um#+u*9s~}rH2iVbpgyPQtD8dTm5Gz+uXM|RApEka2}s{7Yug5A z!5aAOjsq$PpFIAy0HC}H90dfR+H&&#UeEVhv&0fe{Exzi#1R2+Ix(LipLo^VOaE0f5Hl^4d6q06r+j2;M6q zBq(?9ba+0tSy1QkLE7!iztm8o#@)Ix_Kr0oLJ#$bT!TX1M>z|$lMx8p1l}-&zADX(K}ZeVNJ(b&>r0=5Abk4sPv)y3z;fwv z&Jt7;JRt!Hh@=eZoJ0#66l3$aH3o!KF-0W78-c`#A!r6y12hdhck1*ogaUYkU7H{K>!d$NI)j&kTeFMkoic*J>|snr}p=#` zT8V&ZBHsvX?;8X~Ltt|!gQ^O*VqZ1uP6X8$a{oaFPf>2&Rb&Lh^Us`IP={bdb<+`1 zY{`Tp7nAC8QlNC@xw@E?Ojn?*E+zHFqz(ajus&4KXBEP;*efdOx2pZ4lLPz%BE0P^ TcPZ9h00000NkvXXu0mjf)&4_P literal 0 HcmV?d00001 diff --git a/images/mac/textleft.png b/images/mac/textleft.png new file mode 100644 index 0000000000000000000000000000000000000000..83a66d553556318edf017cbb0575eb767401d708 GIT binary patch literal 1235 zcmV;^1T6cBP)Z1U5Qg9C?isHQ7moNJguein{0qo|6CVP}oIv6dtu{dl;Q%rxkl?_DT!7q=5Qj)8 zND+`rferwbYuKRTN5k-R+*5?%J(qt7b?= zHA24$;&|oDv0$-51Bi!w55Y5iego?=6iko4x^ij!J^(l*d+y?gZ|9kQ;*<7;ggDJQQ!nwG)iE>FOg335L^+^nHP!m)KRdH;Rz^V++ zJb)J<__>32iZWf_M$f0_G{VK1>vuf}q}$$5AEU6{*d&zBh5HEu+$0ENp~)f4WzyISA@`)jo){G z`PUj-Z~g`VW0$c`!}^Z0*+CTa)eRfNTTv zm?`)!^U0f+f6i}NsRKn{79%3SMCF}YXJP*OOg+ISE z&y71Op^llp2H`?yCH(x8@w3w-)`h}qd(}>-yR*c~Cm;frO2Xm88q1>s0MyqS(k{p% zD4d1001JVcVTiCYBE0(M1OP5{L5Qm6K(W!qjR(NWl7R^0?mcK#BS@GFh=KrYO&uEV zwT*A?8x3H2WU+Y=%L52^_XMM2eocb^a2>ey#@cy>@X71Ia0)sD$RM=c5UR=n2&xWRyEUt#p7JvG0K(QkZq~O#SpN?0Vf!WN%Ijb-kq6i=WBCU|l%}40E zwbYJt2ZFY8B2su8&lr^kFTXzF*piV4Ve%^BeM|e+z8Af(w(ds{a-1#tYcpaVm0h&$0}{XPtcB=pgOOD zi`#MDR30C~G*?UG>6a#*PsOJ$eKuaL8^9XCD_Df8VtwhT8$sbni9zLc$cH}e3C_IM^J1dzBKiRO;1TJa)=~gW57z_sPmFFU%-B0rP!+h{X?w5) z-4CD|gLeK%KTr$vfq=|FC4BLf$#$NC0p%ur>UuHB-i)%h;QZwzLFuAw{$i3UovO|% xU-mGX%w%-tFmc*65gv7%l*(`PYlaU`_8+QxueyjM5HSD%002ovPDHLkV1fu7LRJ6( literal 0 HcmV?d00001 diff --git a/images/mac/textright.png b/images/mac/textright.png new file mode 100644 index 0000000000000000000000000000000000000000..e7c04645cf4db5caf5558a356d6969eeefb5c17c GIT binary patch literal 1406 zcmV-^1%djBP)#K_=t~%38c?zswBGxN0hto8X>(%-@OYLs&MeQvTjL6967!|V%)O|VyAq5IN{!vN*p=9|4X>W{$sWl*arhfcuVi#>`kcSw2lrN;Q!XnpAn0gX3yZEPlr_kqYMs=44K4TKPgBS#zy zApit?5Yp6Biz5J9Ny^|r%;lzMV3y;;WXjNBOe;0|YeFl5*#q!e2La_2NSn>=3`hsd zt?k?@Q&N?JHrTX?s1z|!E5@k!e2RepWIzfe#h8^M6k%hdb=$P1Q6C$vH>Nvq_0Mww z#tz_-Y4@t#sCw#9;mFmo62j?E?=ZgHx?}hHl|w=>ICRVy8TL4*{CY|m8O~>adn9B1 zazRA-^^|bOqKsM;@x$M+W@$iC4jnf}mUx^hLxal8+o~A2D!>&2zIf~H`uYo#o?7g< z-11;XUoFCbB=tm2$+CcRN*qJ873hl{W`+;ooZ!9ToX~7#%o&Vu%1i-m_PZhluXIR( zc7ZTdq`+pRqdf%`0$d5Yz9RaIu~x(ss8fI?MYMosF}6xj`XUV2JvLh3GgE-E6L_=@ zHthhRRJ?-L!-*aa7~j6Qr@rBqfjqB295Y6i3aR(}c2ZckLJ1yz8HY8?q1p5tKBa89 zO=z|PKm84BZxy0Q`0*I59uCAc<(F|-H9t_RDJp^O+xJ#7pcvom+gIN(dC{<7s8du8 zpFxsks49_DLNMZ5UM4SHN|-xT<8sr$z(oakk$^#(<|48r05Eq*dG>`8g!gaWGiBw} zyZ_jg>*;B@-V}tk>vA193p_YBTDR#AOs{@Zu=Te=*jE7RN`=T5ptaf{Y?k0GSH)db z5Ox#LkMS(O_P@XQO14iNSb@cz5?)oBK)2NgpE($t8e+>k5_ z_z)PJ9g(I6NIoYEI8_YjtHIOH-7ujPY~A z@K7L%9OLKV*7;xtNB<2hnZXEphKz-whGscp6d9Ke~R2I%QMB(Iwv21~o zW`VPpl!b#}!8mqf%-=8 z4Kv9fPjZS?bNxO9KuUmtYCcyTgpgOi5DXPavs{1(`3S^uX8}7pq@YuD+L&}+3tq>@ zq^dH;r6T1jHYUE*a?`fTcZG}gU9+@r&pU{46(J=7R-(KdUH=^5KeRqG?paFC4*&oF M07*qoM6N<$g4^GUS^xk5 literal 0 HcmV?d00001 diff --git a/images/mac/textunder.png b/images/mac/textunder.png new file mode 100644 index 0000000000000000000000000000000000000000..968bac5e90e3bc101959e8acc0f06fdaa79bbc73 GIT binary patch literal 1183 zcmV;Q1YrA#P)f&a`GGn%E-KNVXQ8%L@nVL-sQ%vvA(bS zArVvC?sQjL9Igtp!*vB*wK`m49p7`uUh(R4*K9*vZ??NexQz%ub2-;@JHHv&l%8Wd zoL||aYjL`p28c`!BFh~j>z$F&Um^HSW`2vm42bbHZBBQ`eWDsngrB+GZw5R%Qi50x zXzU}ZyG2yrOLQ==vIpgfV1d7N72{d7>j9B4a4eVm-2*;4YBXWyHC^KZ>4(pCploTN z8;s*ST||5hXcPMCpb-K(2pAxcCPAQmSf+pxOHkE;W#}PFl_1b6SHOS`c(sj4e;Wda zf){AMFH@ivGcRu@s_rC8ksx5ZCsRO&nP0Xc3s{Ej2ZI-|-jykE4I8l3N>tG*O~5=P zQ{W0_e!+w+U>TAn2sAil3jEVfbhd%01j~?gAb5fLL74)VTZoGOCAx@ZNR%LOeL$u_ zDN9Ul=h(RUIAYWrmh{B@J)L@m*2bn&eO0o{Kx1^&hoX!OW}0pEfj%Wk18I>5n| zaj7}B@~)9l+*e5z$UR==aA|6gg*u|_0(~E!83GiDPJ?h^-P7lWU<9`8Db)AnVfHy% zNNAmIJ|zVxp#JHSZHVLjNl(^E=<01pEPt9tMt{dLGh1tlO1J`Fqvo?oQe{7yt%Mt0KClI|kQ@c$R_>sW$g+NEw}Mcey8qqUF0 z&&=L4#(_`2I?{xgIH8}Ai6s0DJ_Ec6W`S40YagsmPKk(9S8m#QqBA3}y8q|$_Tk*> z-iHj|b6HH%FRdTO?A$*u{ImBE^AdOgOlOHn1%$z;3WIa-tKcp0E|?D%f<<%R|M<%# ztF~q>Ta!|-{EPJS%h#qAFZ(?8kMQViYURA8QD_qe-Ugihmj#JwzOvvg5F#|3`BBV{ zeX0$+ZCJybm~{)%*~+X~pV2lEVw>^y>Sm5t#b-8Qe^_`Q`O1PX0Zvya2a10}I)|kr z_Q4xAXaNJhWQ-2yLal(#KK`r|@9iFSeDx^ft6^}QU<97&5(Kmf!D6t)gT+EQ@B9Ul xH{oQjAy9%h!5lExgE@le8^WM0K0A=t@DY&122E81RKNfL002ovPDHLkV1kBi8^r(s literal 0 HcmV?d00001 diff --git a/images/mac/zoomin.png b/images/mac/zoomin.png new file mode 100644 index 0000000000000000000000000000000000000000..d46f5aff0d9810d21bc98be02776e843b2db7ee9 GIT binary patch literal 1696 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 IM6N<$f`v>W)&Kwi literal 0 HcmV?d00001 diff --git a/images/win/editcopy.png b/images/win/editcopy.png new file mode 100644 index 0000000000000000000000000000000000000000..1121b47d8b6b48f6cdf525851e7c0f502454ffe1 GIT binary patch literal 1325 zcmV+|1=9M7P)+{buk{F=nCJX#i^AQGtBfP^U9E=s!&EKn3+*9AyOC5y5_m4HQB2~pH` zRYX%2)m58>DgqW&sAx;EBU4=37{7w!SM2eOJs!`@eVlXtjqY3tTS5?(-{yaHb@l)B zec!pdSBVIB!=;~|e%P7xymRJ$5osgh_&4efy`JyCUMhx9Kk}ogMRI&{UihAR)H(VP z5`ixu00_b{5e5q-zVY>M|NPMBA38(Y-oZLchI61bL7|V$#mUE~-@NcRpbiK;|6O(N zfk%J%Y@t+fHjUDudrucpC_qYs_XMTNy?z?C^q*foM`|MO`|`smOlCq5Y$|AffYRZk z1m#2g^824X`-5laF9IMU{OT;%tWD%U5hqqQHn+rzNOfaXUit9}xpwhevNrpY)K=e+ z>e6d6H~pftTia5-{gJHQcvaqe>5RPb)EA!+5j21}j7vL!fJ7h$Fxhq7s2$=XbQ*apq!syTR7h7DJ;ak=_$L@YoY5qR0x4qnI>JyURTfv?kuG)9hFQ(Bzig%{x2T0Vw))rZsUuJTqc?}RB zayzmI$t>XKE_%9=#B-p^;FY>ji9xH7Anaju4o)p z9%uqB5oz!1paas%Pl^wu;12>?@7Wcg0d(Zx zhlqm$W(R^Xh!-Io1+@po6A*q0JdbvDCs~`i(%Gx6@WB#qEmxCq5xK#C!6ygR1K}{F z4Jh9Og<%N$=~Oqu`pG7hW&{7(U;2z<{$co^Ef>^0+f z`TE<9*>|q)G;S}O%acqlZ1T6YZ9d*=aWjvj1$6F8Kzppmtr|VSaptG4)aU>DhsN&h zS#$oPdv2-51h5X&^WrRbO)e0I{N~r^&-Nf3pIBgF>R(LU+~oac!W>Y~iu;rt_-#>2 jRe%!E1{&Go|C3Ju!Z7S4^>URZ00000NkvXXu0mjfFDrHZ literal 0 HcmV?d00001 diff --git a/images/win/editcut.png b/images/win/editcut.png new file mode 100644 index 0000000000000000000000000000000000000000..38e55f7420e267a891dcbf805d8ce51dc8b27a4b GIT binary patch literal 1896 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 kH>AflK=n!07*qoM6N<$f|Xs>*8l(j literal 0 HcmV?d00001 diff --git a/images/win/editredo.png b/images/win/editredo.png new file mode 100644 index 0000000000000000000000000000000000000000..9d679fe6fcbb334eafcc2dfd8af377bf050f0f76 GIT binary patch literal 1787 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 KMNUMnLSTY!`bcR2 literal 0 HcmV?d00001 diff --git a/images/win/exportpdf.png b/images/win/exportpdf.png new file mode 100644 index 0000000000000000000000000000000000000000..eef5132928be462a4aa01552c3ea09312dc6ee12 GIT binary patch literal 1059 zcmV+;1l;?HP)gY~PDBh=qfNApHBybnVEtGSgDgmlF?QjuZcTSCx@)?q z#F#d-ZdlkRWh17zfT(F3Eu|Hzduh@iDWYrQ7SlK}v8Lqm+6KFw>FFH@MBVx+g1 zcv~BX`}+YH>FcAkv{ZILFh+X-*6oncYgBv|P9_-{v66rMcN00L8)-CFe9ATud4`bV&eUS=4f;$M2o69kO{d#4* zI6O?_i4)`|CYZc*iBK|$D7CJ!2wG{h(p6Ts1vtyg+#eXIjHfagrZSnz_|Ca=)k#zd zkpisk0hZ6l<9G_kAHpYQM;W>rs=*G|U{y2-JOKct-s$E_YZ|RRfEa@ah^)Vj2x0_d z1o8U`HXTGM7(@(OdqM_-0mKMcf^rQ?DTL4# zfDJpkeRG`JkmjS~2k}{g5rZ)Xr8Gusl-4L$G5=_l+jADRsd^s#JwqfK#&y-!l`Q3A z(b}aZ7Nt2Uyp*ovhk+lt`qMQ;;LESR;Q5Yr9LK>aDVh>~#up5S4mC6L?*gu?a9veZ zXo1a{V2pU@iZR%BiMhFX?oHeW;NkK^3i&*a<4`JbWI z7-NXVVq~)`72~U`Hrk}tE7^5XuB!IHvMdX*IzITWe{}S(!Tn9CL?IR+5;QD4c6qkr z6hCxMXby#|ct$432_iJWNm=QppI>fM#DTq-r9;Nz1bQfU$rG&z`vo+t=(TaRecA@ dS$qB4@*jxcBlgPF?Z*HB002ovPDHLkV1i~?^WXpg literal 0 HcmV?d00001 diff --git a/images/win/filenew.png b/images/win/filenew.png new file mode 100644 index 0000000000000000000000000000000000000000..af5d1221412881e8727fe26930e5d0b5b0633aae GIT binary patch literal 768 zcmV+b1ONPqP)R27cmB`+Wkx8a_@65j^u^siVQp>_ zPwn8;)Y0kK7)l|lBE%wFmC-v$eL~)Yfy# z^Ob>gz1owlwa4nuL@ZOXxYpY|_=&3meg}r2l-hGYxpQ6xt+akF&AwE-Rj{%5WonE%=bMnbMjE6fFxi8F4En`*+~J=7Qars`&=Io zhuwOigX}AaoB2WbpNI;Z{V^LaLk(JDtl#%qy z0f>Sm3j{{aCY8&CEXN`MM|ZE8%R+uhohP>-UnM8m)ey5NDv83-9qxc}B#Vq3KoHKA zr9$dh3?K|tQxUGnzF?FXfupNPBJcqpK@|`Kj_Uz9$Li`v=>Q=x&=v?xE!YNlY%Pp2 z`(c97k@x;0y2r zSkx79I6z~aP_V?vz+;97?mOd?a$#bTcUmw3OasdW&9Ju0FEPu=Z0000NkluMLp6h%0z3=<;A2g_#%st8T@8|R6`^WPY zN+~|cy!}H_Tu~a@KD%tm_m%7DBeBj`kG8vQU){vgw8h}2SJgOx_Wy$a@FNi_DPZfe z`nBJwsC#Z*QE@GJoQ`tuDa(UlIM}E5i50 zBA$rOU%pfGhYOm1CieM!Vph$nt*?~TY^loi`LXV`5}%pm#t@`))-rF!=crz=2waH* z;&%?&t(Tk+00|(JQV1c$vDa8QD>{33#j+hQ&7QY9D6ARciDBIrh-i^WiBC;mWoDv} z!6`vsx{B(RFHl;wgmA7OUDr{{iz~czzq@99`0t%p{lXW}qVfl#^_OC$#}{5(QTOzo zk_Fo%L2DS5x`{{AAP_~_I{M52cSceSW=aW^ZDx7>212EvwFb$?inmyRDnA3U(o1R+5=&d7U!}&E2ZTB0{=@8pPcNL+3uBftDi44tm{OIN(koEl8E)va^lqVyXUj5-2)s2 zuHBC#0hkYqo2M57N?UsXwh`2YX_07*qo IM6N<$f-Pt`I{*Lx literal 0 HcmV?d00001 diff --git a/images/win/fileprint.png b/images/win/fileprint.png new file mode 100644 index 0000000000000000000000000000000000000000..ba7c02dc18d3145ffc2565afd7761cf8d3bbea99 GIT binary patch literal 1456 zcmV;h1yA~kP)b-8&)Yht(3npj! zhVZz-1RFN&M_Jjs*iyCsr1Br})rl5`9!vdS1b~`S#iy$JW0wVxgL2xnlvejVftS)` zTKUc6;s?zyOrQ~b4PSpzcWVZ4(}_)5%DYZrOq#!QQ`PI0w4^^aL2|-VFePLo-nasN z*IK{-{nt6Te1OXfI6O;fodf8H!d2_Ev=sjnEGa1o(b3Tl5_n}VWUm)KAEByLKX9faxzp;q-{ z>lTYhucS2H_>FX@YA5Z$@Dy-s3>f$m7#f)`>;2jfo|YtOx5wjoB=}+neBJL?ffbTv zfBCMO^w=tAkqc_N@rAcvg)IH?>4}DuF+}ni$veda50xlz zt)=B6k$96%pJo?^z%^$>&$TW{BVO2LH-dO3l7yfjEpFY8fW?x5LqQUtv$GSD+YMuEJR-uvpwVhzFlgX$`>|^E zYT=ym@o{8iWMoD}L`)w#bf|zJuiZyLz(v{F*tvNb6ir(H{*zI;Y z9>eg^5T>j%h>M9sFx0ezpyPT40fGFLmzP(>a-2DHMgV4IWg#UcMF21vcf&dl5fBrz zG=bHeW$;rtmDJc;eGYPwgH7zbKMpsuC1_lPi z@L49UR*NulRBmoAmM>q9=*Va|Jr1axufdtDLX&dtewzjd2S>6L9I>&nsHv&J;NT#- zySvfQ&>$+0i;EL!GMT`|Fahh&UG(()f>RBr@KQ+y;*yQ9OE&*P2Z|sd879u3KaVwQ z)+{oor>6@bzSi8_LNaL(85t?&Fg-nqt5>fIx!k-*$N*KZR3b4kQMhl}GK-Ps6CzB* zn~Z%;>pIfBv97Kzk%t}FfNaML7cK~Cbh;26Ir0e&+$Dycl9Gyqghb@$=cA&cf|Y<@ z@gpxc&)(P9_dG$|6d*jrdnBtZDk@T1T3QxAlQa*dz5Sxn)^#{D?mf0*?u}E%yICkwE#w=FOWGvZK<`(V-kXctBaZ_E}}e zj#}mD(JPA0HV@p`*r<>h=zE7BDc_+q-}kl)5Cpb=AlNAs>*>{SgEkw#4y}~mQNCv~ zrMGY2{-#1Zm|q8tl+_CrKNyc9V3*tznNMq!WhGU zDb0?ir%%5E<_$1MjY0D7B#lW{;<)?El`Cg|1R~9@%$x6h^uLpO_>ug@xmmgJ*No_P znnEHG0)+hmDMa6YiFRG4o_LlgUp&G194;$ z#|Q7e%Hu~Tky2s+BT^*7)&c<-q*B=0DRAb}Cf_b=^dCQH;0Q1UG+z@p-S0s>z(fLJdaXofa#Y{a{XE!DHR|93_w4?hG<8kq+lom3=aj}y`daH}yY*TMGX*PU}a?k^Z$mMe=dBBKr3MP(B@#**TcTpzBa|A=h93v%QS-kjptJB{4u^z@&y0LCI4T6TSa45CS|$;yRAqEsIM__GKF%A16&yfb3{?Ev3O= zWp`NK(`0awX_vDHsHDgM8ZYP2344@ECC0|a7#$t8fc=zn6g_`~Gzu^#jRElxKudw6 z9$4;tmaREZLZad}%d_8@%6e3-*Khp}bb(|KKnidjfs}wT93TtVTG{6kY+YmJ^6l=8 z>lZ#>U;q0&umyDY?jo%iDv^z46gTJE4_y{w-(;l(uB)>!J7T{u)|M^Y%M$(Q0;0yWQjJ)lC|WuBldAVWm>@ zYqi>@@7LCS|K4h~T3%gTynM%)v;o`!%0SCx>I0b8{Dmvcx$`r{^6IAfuzWTu7V=>n zht*cAvEloba;37qRxV#(t5)yUfG*GhflRd$wsDcfR`M{f{>xbi>|uW%=st z#`gB=U1QP^==3?TwFS`Yb4+F%ysJLI!or#FfIoo|Kmay)=NJKTf0)V094!6;(N7PE TmU#bB00000NkvXXu0mjf&~!wG literal 0 HcmV?d00001 diff --git a/images/win/textbold.png b/images/win/textbold.png new file mode 100644 index 0000000000000000000000000000000000000000..9cbc7138b90d84b6d11e56227d4327ca4cef4d76 GIT binary patch literal 1134 zcmV-!1d;oRP)ua>XPW*|HpIlFET8~IOVRLqtUK*+x_A8?)}|$3&MkQt3Td*_U!w4KCjQu=c@pq z_&+t_W#xwb2~^K*NJG6x&6pNIqrlyVw5IES0z%iu0OKfdl^XaBF#Qe;{oy<)h8qiR)|Y-y+S=ISM|^|U zo?jTKJm&vWv^FVEGWQGv9X#v#2{_qc7=8BDohkzEbqf%5VX$=d2QS7Q)S5bO08Iq6 zn}O_;vSnf5>qR^lQO;Q&`DtbCWvji##0&k1 z!I8Oi@Q|=s5tWjx))__{uL1Q8;?mE+hPZsgTyOtXRO*Lqbw(#Zf5UNed1T^6o(E8OO$*pTKoe7!`UtrSWS;m3z;k63qir!e&&0E! zs(WNnP(%gK7kiXJY`WG|$Mh?EfU~_oT8V6N&HpF4lKFI})n3i)Y6v*qFgWJ7Vq>G% ztVg!e`D~ARu$_P!reAh}6VeIj23Q78OBb8j&gs#yEN8ys=t_fQ%ho1#E)H2=Oy`eN z_jm+|IiNLF8Gw>@ptJ)hsvowcYh+8t38&8X*&I^86Y@>J<7Rx0WDW_BPkr+FcfC9U zY$M<_>tEDL0JGR%EL*&nzFe{Bx$pwfi;(b-n^Q{(Vi2b;u~f`R1Q4v;bAVagJuP4> z0pezg~iE>3IoIEJXkcm7k0o`Wo*#0Q2-Cu)+NL%=P0< zr&l{UmK!{yfwM)gg@mQpb zjG;9p@egwZyjZ2cqM1sJH#_{XXeK;mCpQ$?3zBoX!6csY$1%F#_9so0C-pA*%T+H(sFgzgyvDH&-!>?z=!=HTR zrHfsT)Lb=>D*@6A%SBc}!DU8K+yhS_m z)2{yt^o%<6_KO3=b(?JLd`I-@asv1Yj%Zh0nq=pJ3s?6frmI!D@d=FyVA5HDXqFz{4kvN3ZyOC)U~ttKrM4497U zT&BXP{S2r-0v%?cl5Q( zRa`21(KlAF2WopLA}Vs~-MS%PahQCjzIO$XTh?N-)%F5Ux~Rxh=va!(-P4El|H_2` zv^DhGC(C)Dq7$g;9-jz_y{IAcP|}il0oZ^^GZe;W6wgDo15nHvtbq|H>dD-Ht^zv) zklw1|EeeXJs2O1I?6ZGp!lRiMn;-z0uV?ueaI`I3f%__24-`|1Twz@6C%HlZZ1n&(j5wMpb_JkorKQHyKpj)110GZM zr5!+})^UxU6*d~IyANMuyJ(r(v_F%~gI!v7Y=Mzhu}Pgp-fYn3ngyq}>3sADF*owLD2&Ff00000NkvXX Hu0mjfNaS)2 literal 0 HcmV?d00001 diff --git a/images/win/textjustify.png b/images/win/textjustify.png new file mode 100644 index 0000000000000000000000000000000000000000..9de0c8808502f5c30ed02ff038e0325464ee0fa1 GIT binary patch literal 695 zcmV;o0!aOdP)uVEB-sve*Bfa?nb*cY@aIQoyPBadhbG&yHQtlji7QW5+a5@S{Z1`Lt zd6$H3g%3Hs!ap7p^L%5UPJq*qwRet>()m{8bwqAVHHt%p>N$+BP#}rR{If`08fg=| zmo{Hwd^YfL+FzJlWg>Z-le#MR@6GOr+`b~&h-ZMe-<<-LG0#HP#x)j)dH)4#a)979 z4zFJT5q>Yq@?w06NL8a@>XkV!tv}myy^hGEzd-Xsq0PN{m)iQNc#RI@)>NT0)2p0d zQr{%rok^{_?O~1h{?(mt^59yVqHM+ZQJ@TP2%3n=5qYk d53cV?Uzt_*yVa0;;G-w82-&`E=vsl|NRlZ${171%fCqpl2f#iX=F~$xN>PZ3QcU5RbeQX5i% z549YY#Kj(rFZdBhL@?JzG|y2XzK9kAjUG8-r<3&pv6kpNG0ip|(#;5enq@!S(Ci=Y11a`K{Eaaa-Xj#pX>&ERT(G_ z8sL76@ST$o?vT9+`110pt_(DqlLdn|Pr$zfnk24~uyIb2kw%pwb_ zs7;>t4+7ThYw{AWt+lZ3{VTv{9c{jtXP;Tq3l3T*!dfFmTpKI<0;fJ;pSrvZ`BsDl zmwIszB+$Fk@W%?BiAHxK0?Jq+Y18+|j8CE^DSQm;n zp_z(OeuYzK>U6erIyI+F4ayn9d-1~QdGwv>+}w82;0N!{`JeMY&vVXs4vP@N`k$Q`y5XP3&t*}^WrsI(U_ z$o^jh1#Q^ZB2{U|U@=u6Wj}GeUsQU9gR4(8X!mW-7dX26p7)O6^w>Ii6heCt;IJuzjbQkFDvFjatQk1E zo#KPo7TBSy4d>*0qGo6w4A??3XhHzXEt{-s&Aw_+VBAy8bsFBQ>Y0xo6(P9-L=|bZMsOg?H)1XyJ(Va7dq?urVn$I(4 z8Z;{?x^)^1a!oU6|8Ay1(-=j!OcIi6f&pqiO_^!X01-4Q3E`SxfSP8dc?M;bT`J9o z2}16d)G0muFFn|J!F03u$-+(^gVrDJqJWVm+7F2f5HcSyxRMV&SImdkk0}mL` zJ}+w-|AqP!A)FG>xtU^M4L7vbf7WN`Bt5kOOO12Pgs*_Ij&CGmRr>q&)P;tEC zL2DcPcrdUtYJepnEGah;CLXEmU08VsCeNxR^HALSwZ!s@rPzjjHw7ZOXK)g(-fLr- z&}#s{oxpBjPe9zg+rjaV>V=|?x$^dz|9R61Vv|J_>JN0JlQ&&ykW11lp5&gGm|@E^)&dRp);^6G%=?T@;?Om z9)UD{1>~U#k4FP9XDR$I+@0`^PMh?NN?pY-nx}-5Ga8yG7=aQmjYuvS00i3^SfFqc zUnoGaWIEb0_}~~d=!P;a2HIxUXlH2K1~D_nn1S9D!AtdRE7%Tz4)?@piVSQrZk!9? tiWdlQXE+KR0i2nq5l@d5E>L%q{{n6TIQ-)vN!tJb002ovPDHLkV1h)(w53rU9b}h+zvU zvdt-Gx`Bk+iiy+!DMK?HAf-^(YFA1l#B5Pnlrg*b!*09YySzoz6%sSG$;nG!-@WJi z&OPUSWdOkbO|bus06#GZg-WF|C=`k#JRa|5{JtMij8G!t5WIgxfS-+0skE}LuI}Uh z{{BlIkLN}(7`!z;K7Q3^v-wOWlU*W_7&)T*mm<1b^YpT^vUeR0hd&SqfYa%Owzf7f zo6XSC(E$?^6X5lF!D6ul3kwT7@%bFY%19)CTRAl!86ExJ?RJCdmD=C(_ZzPjG#m?S z-?qZmx;I0+8_hp=T0aWoZoq1@UD0SX7OcyRMDi!iNfuf;H7`9}bM@&%uTP~kcLrHZ z8nD>Sz*c91tl2X2!ilcw_P(z{t!+d5{0IWUG7N)Vc8=NUD;Ok|5Ss zAz~3LA`$FGY36C5N<;lLi&4VHta5m+s2aBDUW2Tc8X>2=88UPYz~T#mt;vJK18%R+ z=YxuhifdT^210<~MpMTn@7L$2rlyGCCe|NE2oVoNBG~70x#r1=s#nd^G*FgM1Z=}jg#HgahLF;AC)A7t zFZlg_&}y}`gQJK9#DkFtiYY|o^NOa{xujz~L&EpI857!m8e<|{u>^@EdJx+~!-}zA zdY&4Z`_$_B_A)sM(@ry}UTz0UN+^Yhd|rIgdNKZl%eD6O>%H5ZaBdJugQ8ci9Q zw;RW1-JYpHxTU29WHQ+h*6&zu25}UBN+>y_y>DQ+`!qi;9YuByx z^z`dk*NdRA$s^`~BcT^p4#l4mN+F`%kQK=-G*BWYS@4+!rBWG6O-+UTG~xAw+csRm z+5?p6r3iT3J0+9iPYIFGrH|*`h~6#%v*&OOm1MP&zc}pS(@7?2*Y4tsv`>zbQoAmCxO$-^EDM zuM)2Mu39aE)>1j_(TII`UwhBaWR9d;BYt=`FL^aJFGoCdPY-==W~9CLPV@idU&Zf9 WSJt-!dAjKU0000&r*aqEiG-2SS)^r%jLd--*+JL5E8^P1os~i;AeGQTwI}6t8MM< z>>PJGoi}|x->l7MyJ0XG+$AL?#@N_c4NG+Id_;F@E>)>iADc`jkJsykfq?<2tE+>W zni|mQbTBwL2ricknwpw?IXO8EczrrzaVV0%-8nV4SgqeN3AMqfDEI8xtn*6(mQprWE;l*i*~v0g}W%|{?6%}Exzb80R+@X3Je zc!yJCa!gd7yEs$W>6lJA-95UpuIqe$^I5mqHW+MaX@QK4jBc#YM1=o!in#>YMx)V1 zn#&7z{~)M5Y0YaeUC{KnU2ikvo+{?s%TpJSMCHer#}BvlE?$udOA}SFB6T+iHWb71lwA;> zm=B!Tm*MH&i7&F+zv&wu9wvfYSbqe;N8A^R;5ED5K1Ehc+gCHP^4OO>oJZxr5pD*~ zD)k?D0uiT%B=e-P%;FpJcs!s`C}@HMh-k$9p$PIQMC9{=>O&JW0sq9se!k(ye!-c5 zRnQi&M4t(q7a9X*asN+kG=biE`5HM1(@r}mU1$OcC6q!$KF|9=e<|vy-5z=BnuGVL ze~8yS!yqmQJ`Y%vEK^2J{}|&O_6BQfYat;ap%?47F0_MX6n{!6IitR#+pli?+7nYh zbS_FaZi{S~bO>6ftnsD^6E$yV+&`PmW{}Bb{)mW((^$WDAs2CJ3W`4^ltw3?lNHG= zv{2HVWN~`DL29nvwry4_mCj&YJA%R{3Yi0zgdSY!6n{!6g@~phE0SAip+row;5B}U zL=s3&PKL}i{Fz;wR$a&1os{VL2)OJsC57To38fH`&&i797FsB2jE&{5+NJ^A~r-vSSyyY3te{)hhtqExg=2d>~g5ijRRfL z8rZ)zacnM0sP_Svl`EWG9FMhNG<)Q+=S4`;w?6uzfMz`(-c!ayW3d#f)ldCSvfwL| zC0az*BY#tf*kc%bo_-f1NoN{=$< Date: Tue, 24 Jul 2018 23:40:17 -0700 Subject: [PATCH 04/14] Minor corrections for Windows compilation - Temp disable unicode handling in CDbSigs::BufWriteStr() - Add missing file --- eula.txt | 15 +++++++++++++++ source/DbSigs.cpp | 4 +++- source/mainwindow.cpp | 3 +-- 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 eula.txt diff --git a/eula.txt b/eula.txt new file mode 100644 index 0000000..8323333 --- /dev/null +++ b/eula.txt @@ -0,0 +1,15 @@ +JPEGsnoop +Copyright (C) 2018 Calvin Hass + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . diff --git a/source/DbSigs.cpp b/source/DbSigs.cpp index be6694b..fbabe70 100644 --- a/source/DbSigs.cpp +++ b/source/DbSigs.cpp @@ -279,6 +279,8 @@ bool CDbSigs::BufWriteStr(unsigned char *pBuf,QString strIn,uint32_t nMaxBytes,b pBufUni = (wchar_t *)pBufBase; pBufAsc = pBufBase; + /* //CAL! Commented out the following until unicode equivalent available + #ifdef UNICODE // Create non-Unicode version of string // Ref: http://social.msdn.microsoft.com/Forums/vstudio/en-US/85f02321-de88-47d2-98c8-87daa839a98e/how-to-convert-cstring-to-const-char-?forum=vclanguage @@ -294,7 +296,7 @@ bool CDbSigs::BufWriteStr(unsigned char *pBuf,QString strIn,uint32_t nMaxBytes,b uint32_t nStrLen; uint32_t nChInd; nStrLen = strIn.size(); -/* + for (nChInd=0;(nChInd Date: Wed, 25 Jul 2018 08:04:16 -0700 Subject: [PATCH 05/14] Fix compilation under MSVC - Windows 10: Tested compilation with MinGW - Windows 10: Tested compilation with MSVC 2017 --- JPEGSnoopQt.pro | 9 + msvc/JPEGsnoop.sln | 19 -- msvc/JPEGsnoop.vcproj | 421 --------------------------------- msvc/JPEGsnoop.vcxproj | 232 ------------------ msvc/JPEGsnoop.vcxproj.filters | 297 ----------------------- source/DbSigs.cpp | 5 +- source/SnoopConfig.cpp | 1 + 7 files changed, 13 insertions(+), 971 deletions(-) delete mode 100644 msvc/JPEGsnoop.sln delete mode 100644 msvc/JPEGsnoop.vcproj delete mode 100644 msvc/JPEGsnoop.vcxproj delete mode 100644 msvc/JPEGsnoop.vcxproj.filters diff --git a/JPEGSnoopQt.pro b/JPEGSnoopQt.pro index a16cdc4..d71fa59 100644 --- a/JPEGSnoopQt.pro +++ b/JPEGSnoopQt.pro @@ -11,7 +11,9 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = JPEGSnoopQt TEMPLATE = app +gcc{ QMAKE_CXXFLAGS += -std=c++11 +} macx{ QMAKE_CXXFLAGS += -isystem /Users/bob/Qt/5.11.0/clang_64/lib/QtCore.framework/Versions/5/Headers @@ -25,11 +27,18 @@ QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtGui QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtWidgets } +gcc{ QMAKE_CXXFLAGS += -fstrict-aliasing -Wextra -pedantic -Weffc++ -Wfloat-equal -Wswitch-default -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment QMAKE_CXXFLAGS += -Wdisabled-optimization -Wformat-nonliteral -Wformat-security -Wconversion -Wformat-nonliteral -Wformat-y2k -Wformat=2 -Wimport QMAKE_CXXFLAGS += -Winit-self -Winline -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wold-style-cast QMAKE_CXXFLAGS += -Wpacked -Wpointer-arith -Wredundant-decls -Wshadow -Wstack-protector -Wstrict-aliasing=2 -Wswitch-enum -Wunreachable-code QMAKE_CXXFLAGS += -Wunused -Wvariadic-macros -Wwrite-strings +} + +# Address C1228 for DbSigs +msvc{ +QMAKE_CXXFLAGS += -bigobj +} # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings diff --git a/msvc/JPEGsnoop.sln b/msvc/JPEGsnoop.sln deleted file mode 100644 index ba3b015..0000000 --- a/msvc/JPEGsnoop.sln +++ /dev/null @@ -1,19 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JPEGsnoop", "JPEGsnoop.vcxproj", "{B2881D75-41FE-4A97-90B3-AB8B6BD4ACB3}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B2881D75-41FE-4A97-90B3-AB8B6BD4ACB3}.Debug|Win32.ActiveCfg = Debug|Win32 - {B2881D75-41FE-4A97-90B3-AB8B6BD4ACB3}.Debug|Win32.Build.0 = Debug|Win32 - {B2881D75-41FE-4A97-90B3-AB8B6BD4ACB3}.Release|Win32.ActiveCfg = Release|Win32 - {B2881D75-41FE-4A97-90B3-AB8B6BD4ACB3}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/msvc/JPEGsnoop.vcproj b/msvc/JPEGsnoop.vcproj deleted file mode 100644 index 9da965f..0000000 --- a/msvc/JPEGsnoop.vcproj +++ /dev/null @@ -1,421 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/msvc/JPEGsnoop.vcxproj b/msvc/JPEGsnoop.vcxproj deleted file mode 100644 index 2914ede..0000000 --- a/msvc/JPEGsnoop.vcxproj +++ /dev/null @@ -1,232 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {B2881D75-41FE-4A97-90B3-AB8B6BD4ACB3} - JPEGsnoop - MFCProj - - - - Application - v110_xp - Static - Unicode - - - Application - v110_xp - Static - Unicode - - - - - - - - - - - - - <_ProjectFileVersion>11.0.60315.1 - - - Debug\ - Debug\ - true - - - Release\ - Release\ - false - - - - Disabled - WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - true - Use - Level4 - EditAndContinue - source;.;%(AdditionalIncludeDirectories) - - - true - Windows - MachineX86 - Wininet.lib - false - - - _DEBUG;%(PreprocessorDefinitions) - false - - - _DEBUG;%(PreprocessorDefinitions) - 0x0409 - $(IntDir);%(AdditionalIncludeDirectories) - - - - - WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) - false - MultiThreaded - true - Use - Level3 - ProgramDatabase - All - - - true - Windows - true - true - MachineX86 - Wininet.lib - true - true - - - NDEBUG;%(PreprocessorDefinitions) - false - - - NDEBUG;%(PreprocessorDefinitions) - 0x0409 - $(IntDir);%(AdditionalIncludeDirectories) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/msvc/JPEGsnoop.vcxproj.filters b/msvc/JPEGsnoop.vcxproj.filters deleted file mode 100644 index 89a9373..0000000 --- a/msvc/JPEGsnoop.vcxproj.filters +++ /dev/null @@ -1,297 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Header Files - - - Resource Files - - - - - - Resource Files - - - Resource Files - - - Resource Files - - - - - - - - - - - - - Resource Files - - - \ No newline at end of file diff --git a/source/DbSigs.cpp b/source/DbSigs.cpp index fbabe70..3d67b49 100644 --- a/source/DbSigs.cpp +++ b/source/DbSigs.cpp @@ -268,7 +268,9 @@ bool CDbSigs::BufWriteStr(unsigned char *pBuf,QString strIn,uint32_t nMaxBytes,b Q_ASSERT(pBuf); bool bRet = false; - char chAsc; + + /* // FIXME Commented out the following until unicode equivalent available + char chAsc; wchar_t chUni; uint32_t nCharSz = ((bUni)?sizeof(wchar_t):sizeof(char)); unsigned char *pBufBase; @@ -279,7 +281,6 @@ bool CDbSigs::BufWriteStr(unsigned char *pBuf,QString strIn,uint32_t nMaxBytes,b pBufUni = (wchar_t *)pBufBase; pBufAsc = pBufBase; - /* //CAL! Commented out the following until unicode equivalent available #ifdef UNICODE // Create non-Unicode version of string diff --git a/source/SnoopConfig.cpp b/source/SnoopConfig.cpp index 0e06d85..07a9a2c 100644 --- a/source/SnoopConfig.cpp +++ b/source/SnoopConfig.cpp @@ -421,6 +421,7 @@ QString CSnoopConfig::GetExeDir() ASSERT(_tcslen(szPath) < sizeof(szPath)); return szPath; */ + return QString(); // FIXME temporary fix for C4716 } // Recursively create directories as needed to create full path From ae0136399d20a15bb52e7fcccf09327614d0a3f7 Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Thu, 26 Jul 2018 08:12:44 -0700 Subject: [PATCH 06/14] Add Windows resource definition --- JPEGSnoopQt.pro | 11 +++++++++++ win_res.rc | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 win_res.rc diff --git a/JPEGSnoopQt.pro b/JPEGSnoopQt.pro index d71fa59..6ce8743 100644 --- a/JPEGSnoopQt.pro +++ b/JPEGSnoopQt.pro @@ -40,6 +40,14 @@ msvc{ QMAKE_CXXFLAGS += -bigobj } +win32{ + RC_FILE += win_res.rc +} + +OTHER_FILES += \ + images\jpegsnoop.ico \ + win_res.rc + # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the @@ -95,3 +103,6 @@ FORMS += \ source/eula.ui RESOURCES = JPEGSnoop.qrc + +DISTFILES += \ + win_res.rc diff --git a/win_res.rc b/win_res.rc new file mode 100644 index 0000000..1bb6f88 --- /dev/null +++ b/win_res.rc @@ -0,0 +1,26 @@ +#include + +VS_VERSION_INFO VERSIONINFO +FILEVERSION 2, 0, 0, 0 +PRODUCTVERSION 2, 0, 0, 0 +BEGIN + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "JPEGsnoop image decoder and analysis\0" + VALUE "FileVersion", "2.0.0.0\0" + VALUE "InternalName", "JPEGsnoop\0" + VALUE "LegalCopyright", "(c) Calvin Hass, 2018\0" + VALUE "OriginalFilename", "JPEGsnoop.exe\0" + VALUE "ProductName", "JPEGsnoop\0" + VALUE "ProductVersion", "2.0.0.0\0" + END + END +END + +IDI_ICON1 ICON DISCARDABLE "images/jpegsnoop.ico" From fd48044fa3287ee2c4ef876e7aaa4743571dc772 Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Sun, 29 Jul 2018 00:27:21 -0700 Subject: [PATCH 07/14] Various fixes with image display - FIX: Crash during changing channel preview when no image decode enabled. Added ImgDecode->IsImgDecoded() - FIX: Change of image zoom (via menu) is not reflected in image viewer window title until following zoom change - FIX: Change of image channel causes viewer window title concatenation --- source/ImgDecode.cpp | 20 +++++++++++++++++++- source/ImgDecode.h | 2 ++ source/Viewer.cpp | 20 ++++++++++++++++---- source/mainwindow.cpp | 5 ++++- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/source/ImgDecode.cpp b/source/ImgDecode.cpp index 0cb02e9..095fcda 100644 --- a/source/ImgDecode.cpp +++ b/source/ImgDecode.cpp @@ -47,6 +47,7 @@ CimgDecode::CimgDecode(CDocLog *pLog, CwindowBuf *pWBuf, CSnoopConfig *pAppConfi m_bVerbose = false; m_pStatBar = 0; + m_bImgDecoded = false; // Image has not been decoded yet m_bDibTempReady = false; m_bPreviewIsJpeg = false; m_bDibHistRgbReady = false; @@ -148,6 +149,9 @@ void CimgDecode::Reset() m_bAvgYValid = false; m_nAvgY = 0; + // Image has not been decoded yet + m_bImgDecoded = false; + // If a DIB has been generated, release it! if(m_bDibTempReady) { @@ -823,6 +827,7 @@ void CimgDecode::setPreviewMode(QAction *action) { // Need to check to see if mode has changed. If so, we need to recalculate the temporary preview. m_nPreviewMode = action->data().toInt(); + qDebug() << QString("CimgDecode::setPreviewMode(%1)").arg(m_nPreviewMode); CalcChannelPreview(); emit updateImage(); } @@ -3303,7 +3308,7 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) // Set the decoded size and before scaling m_nImgSizeX = m_nMcuXMax * m_nMcuWidth; m_nImgSizeY = m_nMcuYMax * m_nMcuHeight; - + qDebug() << QString("CimgDecode::DecodeScanImg ImgSizeX=%1 ImgSizeY=%2").arg(m_nImgSizeX).arg(m_nImgSizeY); m_rectImgBase = QRect(QPoint(0, 0), QSize(m_nImgSizeX, m_nImgSizeY)); // Determine decoding range @@ -4214,6 +4219,9 @@ void CimgDecode::DecodeScanImg(uint32_t nStart, bool bDisplay, bool bQuiet) m_pLog->AddLine(""); } + // Set an indicator that we have completed an image decode + m_bImgDecoded = true; + // --------------------------------------------------------- // Now we can create the final preview. Since we have just finished @@ -5390,6 +5398,12 @@ void CimgDecode::CapRgbRange(uint32_t nMcuX, uint32_t nMcuY, PixelCc & sPix) // void CimgDecode::CalcChannelPreviewFull(QRect *, uint8_t *pTmp) { + qDebug() << QString("CimgDecode::CalcChannelPreviewFull"); + + if (!m_bImgDecoded) { + qDebug() << QString("CimgDecode::CalcChannelPreviewFull exit as image not decoded"); + return; + } PixelCc sPixSrc, sPixDst; QString strTmp; @@ -5461,6 +5475,7 @@ void CimgDecode::CalcChannelPreviewFull(QRect *, uint8_t *pTmp) // Determine pixel count nNumPixels = (nRngY2 - nRngY1 + 1) * (nRngX2 - nRngX1 + 1); + qDebug() << QString("CimgDecode::CalcChannelPreviewFull() new QImage X=%1 Y=%2").arg(m_nImgSizeX).arg(m_nImgSizeY); m_pDibTemp = new QImage(m_nImgSizeX, m_nImgSizeY, QImage::Format_RGB32); // Step through the image @@ -5775,6 +5790,7 @@ void CimgDecode::GetBitmapPtr(uint8_t *&pBitmap) // void CimgDecode::CalcChannelPreview() { + qDebug() << QString("CimgDecode::CalcChannelPreview"); uint8_t *pDibImgTmpBits = 0; //@@ pDibImgTmpBits = (uint8_t *) (m_pDibTemp.GetDIBBitArray()); @@ -5785,6 +5801,8 @@ void CimgDecode::CalcChannelPreview() // return; // } + qDebug() << QString("CimgDecode::CalcChannelPreview DibTempReady=%1").arg(m_bDibTempReady); + // If we need to do a YCC shift, then do full recalc into tmp array CalcChannelPreviewFull(0, pDibImgTmpBits); diff --git a/source/ImgDecode.h b/source/ImgDecode.h index 7c074bb..3d242fa 100644 --- a/source/ImgDecode.h +++ b/source/ImgDecode.h @@ -313,6 +313,7 @@ class CimgDecode : public QObject void ReportHistogramY(); void ReportColorStats(); + bool IsImgDecoded() {return m_bImgDecoded; } bool isYHistogramReady() {return m_bDibHistYReady; } bool isRgbHistogramReady() {return m_bDibHistRgbReady; } bool IsPreviewReady(); @@ -400,6 +401,7 @@ class CimgDecode : public QObject void PrintDcCumVal(uint32_t nMcuX, uint32_t nMcuY, int32_t nVal); void ReportDcRun(uint32_t nMcuX, uint32_t nMcuY, uint32_t nMcuLen); + bool m_bImgDecoded; bool m_bDibTempReady; QImage *m_pDibTemp; // Temporary version for display diff --git a/source/Viewer.cpp b/source/Viewer.cpp index e41d0ab..6d7fa93 100644 --- a/source/Viewer.cpp +++ b/source/Viewer.cpp @@ -49,7 +49,7 @@ Q_Viewer::Q_Viewer(CSnoopConfig *pAppConfig, CimgDecode *pImgDecoder, QWidget *_ loGrid->setContentsMargins(0, 0, 0, 0); setLayout(loGrid); - m_strPreview = "RGB"; + m_strPreview = "Image (RGB)"; setWindowTitle(m_strPreview + " " + m_strZoom); m_strZoom = QString("@ %1%").arg(scaleFactor * 100.0); @@ -79,9 +79,9 @@ void Q_Viewer::mouseMoved(QMouseEvent *e) mcuLabel->setText(QString("MCU [%1,%2]") .arg(p.x(), 4, 10, QChar('0')) .arg(p.y(), 4, 10, QChar('0'))); - m_pImgDecoder->LookupFilePosMcu(e->pos(), nByte, nBit); + m_pImgDecoder->LookupFilePosMcu(p, nByte, nBit); p = m_pImgDecoder->PixelToBlk(e->pos()); - m_pImgDecoder->LookupBlkYCC(e->pos(), nY, nCb, nCr); + m_pImgDecoder->LookupBlkYCC(p, nY, nCb, nCr); fileLabel->setText(QString("File 0x%1:%2").arg(nByte, 8, 16, QChar('0')).arg(nBit)); yccLabel->setText(QString("YCC DC=[%1,%2,%3]") .arg(nY, 5, 10, QChar('0')) @@ -92,6 +92,13 @@ void Q_Viewer::mouseMoved(QMouseEvent *e) void Q_Viewer::drawImage() { qDebug() << "Q_Viewer::drawImage"; + + // Ensure that image has been decoded already + if (!m_pImgDecoder->IsImgDecoded()) { + qDebug() << "Q_Viewer::drawImage exit as image not decoded"; + return; + } + setWindowTitle(m_strPreview + " " + m_strIdct + " " + m_strZoom); imageLabel->setPixmap(QPixmap::fromImage((*m_pImgDecoder->m_pDibTemp).scaledToWidth(static_cast(m_pImgDecoder->m_pDibTemp->width() * scaleFactor)))); scrollArea->setVisible(true); @@ -163,12 +170,16 @@ void Q_Viewer::zoom(QAction* action) break; } - drawImage(); m_strZoom = QString("@ %1%").arg(scaleFactor * 100.0); + drawImage(); } void Q_Viewer::setPreviewTitle(QAction *action) { + // TODO: Alter title depending on whether non-JPEG image displayed (eg. PSD) + // and indicate whether DC-only or DC+AC. See original CimgDecode::ViewOnDraw(). + + m_strPreview = "Image ("; switch(action->data().toInt()) { case PREVIEW_RGB: @@ -207,6 +218,7 @@ void Q_Viewer::setPreviewTitle(QAction *action) m_strPreview += "???"; break; } + m_strPreview += ")"; } void Q_Viewer::scanImageAc(bool b) diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index b14d584..4d416c0 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -702,8 +702,11 @@ void MainWindow::AnalyzeFileDo() yHisto->setPixmap(QPixmap::fromImage((*m_pImgDec->yHistogram()).scaled(yHisto->width(), h))); } + qDebug() << QString("MainWindow::AnalyzeFileDo() DibTempReady=%1 PreviewIsJpeg=%2") + .arg(m_pImgDec->m_bDibTempReady) + .arg(m_pImgDec->m_bPreviewIsJpeg); if(m_pImgDec->m_bDibTempReady & m_pImgDec->m_bPreviewIsJpeg) - { + { imgWindow->drawImage(); } From 782b6672ff1b43756a85a4fcfca3f9f9b5c00874 Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Sun, 29 Jul 2018 11:31:19 -0700 Subject: [PATCH 08/14] Corrected project name --- JPEGSnoop.qrc => JPEGsnoop.qrc | 0 JPEGSnoopQt.pro => JPEGsnoopQt.pro | 4 ++-- source/eula.cpp | 2 +- source/note.ui | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) rename JPEGSnoop.qrc => JPEGsnoop.qrc (100%) rename JPEGSnoopQt.pro => JPEGsnoopQt.pro (98%) diff --git a/JPEGSnoop.qrc b/JPEGsnoop.qrc similarity index 100% rename from JPEGSnoop.qrc rename to JPEGsnoop.qrc diff --git a/JPEGSnoopQt.pro b/JPEGsnoopQt.pro similarity index 98% rename from JPEGSnoopQt.pro rename to JPEGsnoopQt.pro index 6ce8743..6c712eb 100644 --- a/JPEGSnoopQt.pro +++ b/JPEGsnoopQt.pro @@ -8,7 +8,7 @@ QT += core gui printsupport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -TARGET = JPEGSnoopQt +TARGET = JPEGsnoopQt TEMPLATE = app gcc{ @@ -102,7 +102,7 @@ FORMS += \ source/note.ui \ source/eula.ui -RESOURCES = JPEGSnoop.qrc +RESOURCES = JPEGsnoop.qrc DISTFILES += \ win_res.rc diff --git a/source/eula.cpp b/source/eula.cpp index ba26ba8..515923b 100644 --- a/source/eula.cpp +++ b/source/eula.cpp @@ -25,7 +25,7 @@ void Q_Eula::okClicked() { if(!ui->cbAgreed->isChecked()) { - QMessageBox::warning(this, "JPEGSnoop", "You need to agree to the terms or else click Cancel", QMessageBox::Ok); + QMessageBox::warning(this, "JPEGsnoop", "You need to agree to the terms or else click Cancel", QMessageBox::Ok); } else { diff --git a/source/note.ui b/source/note.ui index 8f62c69..a8edf70 100644 --- a/source/note.ui +++ b/source/note.ui @@ -11,7 +11,7 @@ - JPEGSnoop - Note + JPEGsnoop - Note true @@ -32,7 +32,7 @@ QDialogButtonBox::Ok - + 10 From d82c86e985630ba1c0bfffc3c37867b4dc9c064b Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Tue, 31 Jul 2018 08:53:05 -0700 Subject: [PATCH 09/14] Disable warnings in Qt system files for Win --- JPEGsnoopQt.pro | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/JPEGsnoopQt.pro b/JPEGsnoopQt.pro index 6c712eb..9a459a8 100644 --- a/JPEGsnoopQt.pro +++ b/JPEGsnoopQt.pro @@ -12,32 +12,42 @@ TARGET = JPEGsnoopQt TEMPLATE = app gcc{ -QMAKE_CXXFLAGS += -std=c++11 + QMAKE_CXXFLAGS += -std=c++11 } +### +# Disable warnings in Qt system files +# TODO: Use include path variables instead of hardcoding macx{ -QMAKE_CXXFLAGS += -isystem /Users/bob/Qt/5.11.0/clang_64/lib/QtCore.framework/Versions/5/Headers -QMAKE_CXXFLAGS += -isystem /Users/bob/Qt/5.11.0/clang_64/lib/QtGui.framework/Versions/5/Headers -QMAKE_CXXFLAGS += -isystem /Users/bob/Qt/5.11.0/clang_64/lib/QtWidgets.framework/Versions/5/Headers + QMAKE_CXXFLAGS += -isystem /Users/bob/Qt/5.11.0/clang_64/lib/QtCore.framework/Versions/5/Headers + QMAKE_CXXFLAGS += -isystem /Users/bob/Qt/5.11.0/clang_64/lib/QtGui.framework/Versions/5/Headers + QMAKE_CXXFLAGS += -isystem /Users/bob/Qt/5.11.0/clang_64/lib/QtWidgets.framework/Versions/5/Headers } linux:!macx{ -QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtCore -QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtGui -QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtWidgets + QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtCore + QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtGui + QMAKE_CXXFLAGS += -isystem /usr/include/qt5/QtWidgets } +win32{ + QMAKE_CXXFLAGS += -isystem C:/Qt/5.11.1/mingw53_32/include/QtCore + QMAKE_CXXFLAGS += -isystem C:/Qt/5.11.1/mingw53_32/include/QtGui + QMAKE_CXXFLAGS += -isystem C:/Qt/5.11.1/mingw53_32/include/QtWidgets +} +### + gcc{ -QMAKE_CXXFLAGS += -fstrict-aliasing -Wextra -pedantic -Weffc++ -Wfloat-equal -Wswitch-default -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -QMAKE_CXXFLAGS += -Wdisabled-optimization -Wformat-nonliteral -Wformat-security -Wconversion -Wformat-nonliteral -Wformat-y2k -Wformat=2 -Wimport -QMAKE_CXXFLAGS += -Winit-self -Winline -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wold-style-cast -QMAKE_CXXFLAGS += -Wpacked -Wpointer-arith -Wredundant-decls -Wshadow -Wstack-protector -Wstrict-aliasing=2 -Wswitch-enum -Wunreachable-code -QMAKE_CXXFLAGS += -Wunused -Wvariadic-macros -Wwrite-strings + QMAKE_CXXFLAGS += -fstrict-aliasing -Wextra -pedantic -Weffc++ -Wfloat-equal -Wswitch-default -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment + QMAKE_CXXFLAGS += -Wdisabled-optimization -Wformat-nonliteral -Wformat-security -Wconversion -Wformat-nonliteral -Wformat-y2k -Wformat=2 -Wimport + QMAKE_CXXFLAGS += -Winit-self -Winline -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wold-style-cast + QMAKE_CXXFLAGS += -Wpacked -Wpointer-arith -Wredundant-decls -Wshadow -Wstack-protector -Wstrict-aliasing=2 -Wswitch-enum -Wunreachable-code + QMAKE_CXXFLAGS += -Wunused -Wvariadic-macros -Wwrite-strings } # Address C1228 for DbSigs msvc{ -QMAKE_CXXFLAGS += -bigobj + QMAKE_CXXFLAGS += -bigobj } win32{ From a8b0e387695667b1973f12729ddca0a5543af86f Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Tue, 31 Jul 2018 08:53:38 -0700 Subject: [PATCH 10/14] Fix warnings --- source/DbSigs.cpp | 8 +-- source/DecodePs.cpp | 18 +++---- source/DocLog.cpp | 4 +- source/JfifDecode.cpp | 108 +++++++++++++++++++++-------------------- source/SnoopConfig.cpp | 14 +++--- source/WindowBuf.cpp | 18 +++---- source/mainwindow.cpp | 2 +- 7 files changed, 88 insertions(+), 84 deletions(-) diff --git a/source/DbSigs.cpp b/source/DbSigs.cpp index 3d67b49..bab5d21 100644 --- a/source/DbSigs.cpp +++ b/source/DbSigs.cpp @@ -356,7 +356,7 @@ bool CDbSigs::BufWriteStr(unsigned char *pBuf,QString strIn,uint32_t nMaxBytes,b void CDbSigs::DatabaseExtraLoad() { - uint8_t * pBuf = NULL; + uint8_t * pBuf = nullptr; uint32_t nBufLenBytes = 0; uint32_t nBufOffset = 0; QString strError; @@ -620,7 +620,7 @@ void CDbSigs::DatabaseExtraLoad() if (pBuf) { delete [] pBuf; - pBuf = NULL; + pBuf = nullptr; } // If we did make changes to the database (trim), then rewrite it! @@ -667,7 +667,7 @@ CompSig CDbSigs::DatabaseExtraGet(uint32_t nInd) void CDbSigs::DatabaseExtraStore() { - uint8_t * pBuf = NULL; + uint8_t * pBuf = nullptr; //uint32_t nBufLenBytes = 0; uint32_t nBufOffset = 0; @@ -757,7 +757,7 @@ void CDbSigs::DatabaseExtraStore() if (pBuf) { delete [] pBuf; - pBuf = NULL; + pBuf = nullptr; } } diff --git a/source/DecodePs.cpp b/source/DecodePs.cpp index bdea2f9..48d88f2 100644 --- a/source/DecodePs.cpp +++ b/source/DecodePs.cpp @@ -357,7 +357,7 @@ bool CDecodePs::DecodePsd(uint32_t nPos, QImage * pDibTemp, int32_t &nWidth, int if(bDecOk) { - unsigned char *pDibBits = NULL; + unsigned char *pDibBits = nullptr; #ifdef PS_IMG_DEC_EN if((pDibTemp) && (m_bDisplayImage)) @@ -1760,7 +1760,7 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, QImage for(uint32_t nLayerInd = 0; (bDecOk) && (nLayerInd < nLayerCount); nLayerInd++) { // Clear the channel array - sLayerAllInfo.psLayers[nLayerInd].pnChanLen = NULL; + sLayerAllInfo.psLayers[nLayerInd].pnChanLen = nullptr; QString strTmp; strTmp = QString("Layer #%1").arg(nLayerInd); @@ -1785,7 +1785,7 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, QImage nWidth = sLayerAllInfo.psLayers[nLayerInd].nWidth; nHeight = sLayerAllInfo.psLayers[nLayerInd].nHeight; - unsigned char *pDibBits = NULL; + unsigned char *pDibBits = nullptr; #ifdef PS_IMG_DEC_EN if((pDibTemp) && (m_bDisplayLayer) && (nLayerInd == m_nDisplayLayerInd)) @@ -1866,14 +1866,14 @@ bool CDecodePs::PhotoshopParseLayerInfo(uint32_t &nPos, uint32_t nIndent, QImage for(uint32_t nChanInd = 0; (bDecOk) && (nChanInd < nNumChans); nChanInd++) { delete[]sLayerAllInfo.psLayers[nLayerInd].pnChanLen; - sLayerAllInfo.psLayers[nLayerInd].pnChanLen = NULL; + sLayerAllInfo.psLayers[nLayerInd].pnChanLen = nullptr; delete[]sLayerAllInfo.psLayers[nLayerInd].pnChanID; - sLayerAllInfo.psLayers[nLayerInd].pnChanID = NULL; + sLayerAllInfo.psLayers[nLayerInd].pnChanID = nullptr; } } delete[]sLayerAllInfo.psLayers; - sLayerAllInfo.psLayers = NULL; + sLayerAllInfo.psLayers = nullptr; } return bDecOk; @@ -1919,7 +1919,7 @@ bool CDecodePs::PhotoshopParseLayerRecord(uint32_t &nPos, uint32_t nIndent, tsLa //nChans = nNumChans; pLayerInfo->nNumChans = nNumChans; - Q_ASSERT(pLayerInfo->pnChanLen == NULL); + Q_ASSERT(pLayerInfo->pnChanLen == nullptr); pLayerInfo->pnChanLen = new uint32_t[nNumChans]; Q_ASSERT(pLayerInfo->pnChanLen); @@ -2163,7 +2163,7 @@ bool CDecodePs::PhotoshopParseChannelImageData(uint32_t &nPos, uint32_t nIndent, if(anRowLen) { delete[]anRowLen; - anRowLen = NULL; + anRowLen = nullptr; } } else if(nCompressionMethod == 0) @@ -2433,7 +2433,7 @@ bool CDecodePs::PhotoshopParseImageData(uint32_t &nPos, uint32_t nIndent, tsImag if(anRowLen) { delete[]anRowLen; - anRowLen = NULL; + anRowLen = nullptr; } } else if(nCompressionMethod == 0) diff --git a/source/DocLog.cpp b/source/DocLog.cpp index f81f3fb..55ac4d3 100644 --- a/source/DocLog.cpp +++ b/source/DocLog.cpp @@ -24,12 +24,12 @@ // CDocLog::CDocLog(void) { - m_pDoc = NULL; + m_pDoc = nullptr; } CDocLog::CDocLog(QPlainTextEdit *pDoc) { - m_pDoc = NULL; + m_pDoc = nullptr; m_pDoc = pDoc; } diff --git a/source/JfifDecode.cpp b/source/JfifDecode.cpp index 79a52c4..94dcc4c 100644 --- a/source/JfifDecode.cpp +++ b/source/JfifDecode.cpp @@ -41,6 +41,8 @@ // Maximum number of component values to extract into array for display static const uint32_t MAX_anValues = 64; +// Macro to avoid multi-character constant definitions +#define FOURC_INT(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d)) //----------------------------------------------------------------------------- // Initialize the JFIF decoder. Several class pointers are provided @@ -119,7 +121,7 @@ CjfifDecode::~CjfifDecode() { delete m_pPsDec; - m_pPsDec = NULL; + m_pPsDec = nullptr; } #ifdef SUPPORT_DICOM @@ -128,7 +130,7 @@ CjfifDecode::~CjfifDecode() { delete m_pDecDicom; - m_pDecDicom = NULL; + m_pDecDicom = nullptr; } #endif @@ -4374,6 +4376,7 @@ uint32_t CjfifDecode::DecodeApp13Ps() return 0; } + //----------------------------------------------------------------------------- // Start decoding a single ICC header segment @ nPos uint32_t CjfifDecode::DecodeIccHeader(uint32_t nPos) @@ -4485,25 +4488,26 @@ uint32_t CjfifDecode::DecodeIccHeader(uint32_t nPos) switch (nProfDevClass) { - case 'scnr': + //CAL! case 'scnr': + case FOURC_INT('s','c','n','r'): strTmp1 = "Input Device profile"; break; - case 'mntr': + case FOURC_INT('m','n','t','r'): strTmp1 = "Display Device profile"; break; - case 'prtr': + case FOURC_INT('p','r','t','r'): strTmp1 = "Output Device profile"; break; - case 'link': + case FOURC_INT('l','i','n','k'): strTmp1 = "DeviceLink Device profile"; break; - case 'spac': + case FOURC_INT('s','p','a','c'): strTmp1 = "ColorSpace Conversion profile"; break; - case 'abst': + case FOURC_INT('a','b','s','t'): strTmp1 = "Abstract profile"; break; - case 'nmcl': + case FOURC_INT('n','m','c','l'): strTmp1 = "Named colour profile"; break; default: @@ -4515,79 +4519,79 @@ uint32_t CjfifDecode::DecodeIccHeader(uint32_t nPos) switch (nDataColorSpace) { - case 'XYZ ': + case FOURC_INT('X','Y','Z',' '): strTmp1 = "XYZData"; break; - case 'Lab ': + case FOURC_INT('L','a','b',' '): strTmp1 = "labData"; break; - case 'Luv ': + case FOURC_INT('L','u','v',' '): strTmp1 = "lubData"; break; - case 'YCbr': + case FOURC_INT('Y','C','b','r'): strTmp1 = "YCbCrData"; break; - case 'Yxy ': + case FOURC_INT('Y','x','y',' '): strTmp1 = "YxyData"; break; - case 'RGB ': + case FOURC_INT('R','G','B',' '): strTmp1 = "rgbData"; break; - case 'GRAY': + case FOURC_INT('G','R','A','Y'): strTmp1 = "grayData"; break; - case 'HSV ': + case FOURC_INT('H','S','V',' '): strTmp1 = "hsvData"; break; - case 'HLS ': + case FOURC_INT('H','L','S',' '): strTmp1 = "hlsData"; break; - case 'CMYK': + case FOURC_INT('C','M','Y','K'): strTmp1 = "cmykData"; break; - case 'CMY ': + case FOURC_INT('C','M','Y',' '): strTmp1 = "cmyData"; break; - case '2CLR': + case FOURC_INT('2','C','L','R'): strTmp1 = "2colourData"; break; - case '3CLR': + case FOURC_INT('3','C','L','R'): strTmp1 = "3colourData"; break; - case '4CLR': + case FOURC_INT('4','C','L','R'): strTmp1 = "4colourData"; break; - case '5CLR': + case FOURC_INT('5','C','L','R'): strTmp1 = "5colourData"; break; - case '6CLR': + case FOURC_INT('6','C','L','R'): strTmp1 = "6colourData"; break; - case '7CLR': + case FOURC_INT('7','C','L','R'): strTmp1 = "7colourData"; break; - case '8CLR': + case FOURC_INT('8','C','L','R'): strTmp1 = "8colourData"; break; - case '9CLR': + case FOURC_INT('9','C','L','R'): strTmp1 = "9colourData"; break; - case 'ACLR': + case FOURC_INT('A','C','L','R'): strTmp1 = "10colourData"; break; - case 'BCLR': + case FOURC_INT('B','C','L','R'): strTmp1 = "11colourData"; break; - case 'CCLR': + case FOURC_INT('C','C','L','R'): strTmp1 = "12colourData"; break; - case 'DCLR': + case FOURC_INT('D','C','L','R'): strTmp1 = "13colourData"; break; - case 'ECLR': + case FOURC_INT('E','C','L','R'): strTmp1 = "14colourData"; break; - case 'FCLR': + case FOURC_INT('F','C','L','R'): strTmp1 = "15colourData"; break; default: @@ -4608,16 +4612,16 @@ uint32_t CjfifDecode::DecodeIccHeader(uint32_t nPos) switch (nPrimPlatSig) { - case 'APPL': + case FOURC_INT('A','P','P','L'): strTmp1 = "Apple Computer, Inc."; break; - case 'MSFT': + case FOURC_INT('M','S','F','T'): strTmp1 = "Microsoft Corporation"; break; - case 'SGI ': + case FOURC_INT('S','G','I',' '): strTmp1 = "Silicon Graphics, Inc."; break; - case 'SUNW': + case FOURC_INT('S','U','N','W'): strTmp1 = "Sun Microsystems, Inc."; break; default: @@ -8883,8 +8887,8 @@ void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString //static LPSTR astrAcceptTypes[2]={"*/*", NULL}; /* HINTERNET hINet = NULL; - HINTERNET hConnection = NULL; - HINTERNET hData = NULL; + HINTERNET hConnection = NULL; + HINTERNET hData = NULL; hINet = InternetOpen("JPEGsnoop/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ; if ( !hINet ) @@ -8956,14 +8960,14 @@ void CjfifDecode::SendSubmit(QString strExifMake, QString strExifModel, QString pFile->Close(); delete pFile; - pFile = NULL; + pFile = nullptr; } if(pConnection) { pConnection->Close(); delete pConnection; - pConnection = NULL; + pConnection = nullptr; } sSession.Close(); @@ -9873,7 +9877,7 @@ void CjfifDecode::ProcessFile(QFile *inFile) } #else // Don't attempt to display Photoshop image data - if(m_pPsDec->DecodePsd(nStartPos, NULL, nWidth, nHeight)) + if(m_pPsDec->DecodePsd(nStartPos, nullptr, nWidth, nHeight)) { return; } @@ -10225,7 +10229,7 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, msgBox.exec(); } - pFileOutput = NULL; + pFileOutput = nullptr; return false; } @@ -10243,7 +10247,7 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, { delete pFileOutput; - pFileOutput = NULL; + pFileOutput = nullptr; } return false; @@ -10267,7 +10271,7 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, if(pFileOutput) { delete pFileOutput; - pFileOutput = NULL; + pFileOutput = nullptr; } return false; @@ -10358,13 +10362,13 @@ bool CjfifDecode::ExportJpegDo(QString strFileIn, QString strFileOut, if(pBuf) { delete[]pBuf; - pBuf = NULL; + pBuf = nullptr; } if(pFileOutput) { delete pFileOutput; - pFileOutput = NULL; + pFileOutput = nullptr; } SetStatusText(""); @@ -10422,7 +10426,7 @@ bool CjfifDecode::ExportJpegDoRange(QString strFileIn, QString strFileOut, uint3 msgBox.exec(); } - pFileOutput = NULL; + pFileOutput = nullptr; return false; } @@ -10441,7 +10445,7 @@ bool CjfifDecode::ExportJpegDoRange(QString strFileIn, QString strFileOut, uint3 if(pFileOutput) { delete pFileOutput; - pFileOutput = NULL; + pFileOutput = nullptr; } return false; @@ -10478,13 +10482,13 @@ bool CjfifDecode::ExportJpegDoRange(QString strFileIn, QString strFileOut, uint3 if(pBuf) { delete[]pBuf; - pBuf = NULL; + pBuf = nullptr; } if(pFileOutput) { delete pFileOutput; - pFileOutput = NULL; + pFileOutput = nullptr; } SetStatusText(""); diff --git a/source/SnoopConfig.cpp b/source/SnoopConfig.cpp index 07a9a2c..df1bb1d 100644 --- a/source/SnoopConfig.cpp +++ b/source/SnoopConfig.cpp @@ -35,7 +35,7 @@ CSnoopConfig::CSnoopConfig(QObject *_parent) : QObject(_parent) { // Debug log strDebugLogFname = ".\\JPEGsnoop-debug.log"; - fpDebugLog = NULL; + fpDebugLog = nullptr; bDebugLogEnable = false; // Default to showing message dialogs @@ -478,7 +478,7 @@ bool CSnoopConfig::DebugLogCreate() return true; } - ASSERT(fpDebugLog == NULL); + ASSERT(fpDebugLog == nullptr); try { @@ -495,7 +495,7 @@ bool CSnoopConfig::DebugLogCreate() e->Delete(); strError.Format("ERROR: Couldn't open debug log file for write [%s]: [%s]", (LPCTSTR) strDebugLogFname, (LPCTSTR) msg); AfxMessageBox(strError); - fpDebugLog = NULL; + fpDebugLog = nullptr; return false; } @@ -512,7 +512,7 @@ bool CSnoopConfig::DebugLogCreate() fpDebugLog->Close(); delete fpDebugLog; - fpDebugLog = NULL; + fpDebugLog = nullptr; } // Extra code to record OS version @@ -564,7 +564,7 @@ bool CSnoopConfig::DebugLogAdd(QString strText) return false; } - ASSERT(fpDebugLog == NULL); + ASSERT(fpDebugLog == nullptr); try { @@ -582,7 +582,7 @@ bool CSnoopConfig::DebugLogAdd(QString strText) e->Delete(); strError.Format("ERROR: Couldn't open debug log file for append [%s]: [%s]", (LPCTSTR) strDebugLogFname, (LPCTSTR) msg); AfxMessageBox(strError); - fpDebugLog = NULL; + fpDebugLog = nullptr; return false; } @@ -619,7 +619,7 @@ bool CSnoopConfig::DebugLogAdd(QString strText) fpDebugLog->Close(); delete fpDebugLog; - fpDebugLog = NULL; + fpDebugLog = nullptr; } #endif diff --git a/source/WindowBuf.cpp b/source/WindowBuf.cpp index 962f670..c7e2bd1 100644 --- a/source/WindowBuf.cpp +++ b/source/WindowBuf.cpp @@ -37,7 +37,7 @@ CwindowBuf::CwindowBuf(CDocLog *pDocLog) : m_pDocLog(pDocLog) exit(1); } - m_pStatBar = NULL; + m_pStatBar = nullptr; Reset(); @@ -48,18 +48,18 @@ CwindowBuf::CwindowBuf(CDocLog *pDocLog) : m_pDocLog(pDocLog) for(uint32_t nInd = 0; nInd < NUM_OVERLAYS; nInd++) { - m_psOverlay[nInd] = NULL; + m_psOverlay[nInd] = nullptr; } } // Destructor deallocates buffers and overlays CwindowBuf::~CwindowBuf() { - if(m_pBuffer != NULL) + if(m_pBuffer != nullptr) { delete m_pBuffer; - m_pBuffer = NULL; + m_pBuffer = nullptr; m_bBufOK = false; } @@ -70,7 +70,7 @@ CwindowBuf::~CwindowBuf() { delete m_psOverlay[nInd]; - m_psOverlay[nInd] = NULL; + m_psOverlay[nInd] = nullptr; } } } @@ -81,7 +81,7 @@ void CwindowBuf::Reset() { // File handling m_bBufOK = false; // Initialize the buffer to not loaded yet - m_pBufFile = NULL; // No file open yet + m_pBufFile = nullptr; // No file open yet } // Accessor for m_bBufOk @@ -119,7 +119,7 @@ void CwindowBuf::BufFileSet(QFile * inFile) if(m_nPosEof == 0) { - m_pBufFile = NULL; + m_pBufFile = nullptr; msgBox.setText("ERROR: BufFileSet() File length zero"); msgBox.exec(); } @@ -137,7 +137,7 @@ void CwindowBuf::BufFileUnset() { if(m_pBufFile) { - m_pBufFile = NULL; + m_pBufFile = nullptr; } } @@ -677,7 +677,7 @@ void CwindowBuf::OverlayRemove() // Don't need to delete the overlay struct as we might as well reuse it m_psOverlay[m_nOverlayNum]->bEn = false; //delete m_psOverlay[m_nOverlayNum]; - //m_psOverlay[m_nOverlayNum] = NULL; + //m_psOverlay[m_nOverlayNum] = nullptr; } } diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index 4d416c0..c3ba32a 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -618,7 +618,7 @@ void MainWindow::AnalyzeFile() msgBox.exec(); } - m_pFile = NULL; + m_pFile = nullptr; } else { From f022c382a3b9a3821e16eedd5e9c58e3a9dff384 Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Wed, 8 Aug 2018 07:21:41 -0700 Subject: [PATCH 11/14] Fixed EULA dialog status --- source/SnoopConfig.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/SnoopConfig.cpp b/source/SnoopConfig.cpp index df1bb1d..7966376 100644 --- a/source/SnoopConfig.cpp +++ b/source/SnoopConfig.cpp @@ -209,8 +209,6 @@ void CSnoopConfig::RegistryLoad() docImageDirty(); } - bEulaAccepted = false; - if(!bEulaAccepted) { Q_Eula *eulaDlg = new Q_Eula; From ea21c9f2ea0f1dcb91fce01e9c7d3aa65909e82f Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Wed, 8 Aug 2018 07:34:13 -0700 Subject: [PATCH 12/14] Update file header comment --- source/DbSigs.cpp | 2 +- source/DbSigs.h | 2 +- source/DecodeDicom.h | 4 ++-- source/DecodePs.cpp | 2 +- source/DecodePs.h | 2 +- source/DocLog.cpp | 2 +- source/DocLog.h | 2 +- source/General.cpp | 2 +- source/General.h | 2 +- source/ImgDecode.cpp | 2 +- source/ImgDecode.h | 2 +- source/JfifDecode.cpp | 2 +- source/JfifDecode.h | 2 +- source/Md5.cpp | 2 +- source/Md5.h | 2 +- source/SnoopConfig.cpp | 2 +- source/SnoopConfig.h | 2 +- source/Viewer.cpp | 18 ++++++++++++++++++ source/Viewer.h | 18 ++++++++++++++++++ source/WindowBuf.cpp | 2 +- source/WindowBuf.h | 2 +- source/eula.cpp | 18 ++++++++++++++++++ source/eula.h | 18 ++++++++++++++++++ source/labelClick.cpp | 18 ++++++++++++++++++ source/labelClick.h | 18 ++++++++++++++++++ source/main.cpp | 18 ++++++++++++++++++ source/mainwindow.cpp | 18 ++++++++++++++++++ source/mainwindow.h | 18 ++++++++++++++++++ source/note.cpp | 18 ++++++++++++++++++ source/note.h | 18 ++++++++++++++++++ source/q_decodedetaildlg.cpp | 18 ++++++++++++++++++ source/q_decodedetaildlg.h | 18 ++++++++++++++++++ source/snoop.h | 2 +- source/snoopconfigdialog.cpp | 18 ++++++++++++++++++ source/snoopconfigdialog.h | 18 ++++++++++++++++++ 35 files changed, 291 insertions(+), 21 deletions(-) diff --git a/source/DbSigs.cpp b/source/DbSigs.cpp index bab5d21..97587f1 100644 --- a/source/DbSigs.cpp +++ b/source/DbSigs.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/DbSigs.h b/source/DbSigs.h index 8824c9a..1675840 100644 --- a/source/DbSigs.h +++ b/source/DbSigs.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/DecodeDicom.h b/source/DecodeDicom.h index 026ba5f..9822092 100644 --- a/source/DecodeDicom.h +++ b/source/DecodeDicom.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -149,4 +149,4 @@ class CDecodeDicom bool m_bJpegEncapOffsetNext; }; -#endif \ No newline at end of file +#endif diff --git a/source/DecodePs.cpp b/source/DecodePs.cpp index 48d88f2..a248d8c 100644 --- a/source/DecodePs.cpp +++ b/source/DecodePs.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/DecodePs.h b/source/DecodePs.h index 0bbfb09..f9d2027 100644 --- a/source/DecodePs.h +++ b/source/DecodePs.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/DocLog.cpp b/source/DocLog.cpp index 55ac4d3..e8defa8 100644 --- a/source/DocLog.cpp +++ b/source/DocLog.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/DocLog.h b/source/DocLog.h index a8a7d78..1d3b5ee 100644 --- a/source/DocLog.h +++ b/source/DocLog.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/General.cpp b/source/General.cpp index 32da729..172cf02 100644 --- a/source/General.cpp +++ b/source/General.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/General.h b/source/General.h index 8491bc5..91b6a43 100644 --- a/source/General.h +++ b/source/General.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/ImgDecode.cpp b/source/ImgDecode.cpp index 095fcda..4d304bc 100644 --- a/source/ImgDecode.cpp +++ b/source/ImgDecode.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/ImgDecode.h b/source/ImgDecode.h index 3d242fa..a549f28 100644 --- a/source/ImgDecode.h +++ b/source/ImgDecode.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/JfifDecode.cpp b/source/JfifDecode.cpp index 94dcc4c..9114292 100644 --- a/source/JfifDecode.cpp +++ b/source/JfifDecode.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/JfifDecode.h b/source/JfifDecode.h index 6e998a9..e5325ce 100644 --- a/source/JfifDecode.h +++ b/source/JfifDecode.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/Md5.cpp b/source/Md5.cpp index a2b789c..91d07ba 100644 --- a/source/Md5.cpp +++ b/source/Md5.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/Md5.h b/source/Md5.h index 452a567..c92abfa 100644 --- a/source/Md5.h +++ b/source/Md5.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/SnoopConfig.cpp b/source/SnoopConfig.cpp index 7966376..3da9571 100644 --- a/source/SnoopConfig.cpp +++ b/source/SnoopConfig.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/SnoopConfig.h b/source/SnoopConfig.h index 17dc6ff..fc0c92f 100644 --- a/source/SnoopConfig.h +++ b/source/SnoopConfig.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/Viewer.cpp b/source/Viewer.cpp index 6d7fa93..7201566 100644 --- a/source/Viewer.cpp +++ b/source/Viewer.cpp @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #include #include diff --git a/source/Viewer.h b/source/Viewer.h index 21a1c6b..700427d 100644 --- a/source/Viewer.h +++ b/source/Viewer.h @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #ifndef Q_VIEWER_H #define Q_VIEWER_H diff --git a/source/WindowBuf.cpp b/source/WindowBuf.cpp index c7e2bd1..b4304b3 100644 --- a/source/WindowBuf.cpp +++ b/source/WindowBuf.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/WindowBuf.h b/source/WindowBuf.h index 103c398..c0522e0 100644 --- a/source/WindowBuf.h +++ b/source/WindowBuf.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/eula.cpp b/source/eula.cpp index 515923b..0165ae8 100644 --- a/source/eula.cpp +++ b/source/eula.cpp @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #include #include "eula.h" diff --git a/source/eula.h b/source/eula.h index 03f457c..e3b02d6 100644 --- a/source/eula.h +++ b/source/eula.h @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #ifndef EULA_H #define EULA_H diff --git a/source/labelClick.cpp b/source/labelClick.cpp index 2cd8287..c16d9b1 100644 --- a/source/labelClick.cpp +++ b/source/labelClick.cpp @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #include #include "labelClick.h" diff --git a/source/labelClick.h b/source/labelClick.h index be53587..32f08c6 100644 --- a/source/labelClick.h +++ b/source/labelClick.h @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #ifndef LABELCLICK_H #define LABELCLICK_H diff --git a/source/main.cpp b/source/main.cpp index 453d7fd..5278ecf 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #include #include diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index c3ba32a..35f6405 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #include #include #include diff --git a/source/mainwindow.h b/source/mainwindow.h index ff9cfa3..ffa470f 100644 --- a/source/mainwindow.h +++ b/source/mainwindow.h @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #ifndef MAINWINDOW_H #define MAINWINDOW_H diff --git a/source/note.cpp b/source/note.cpp index 8981e88..697b2e1 100644 --- a/source/note.cpp +++ b/source/note.cpp @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #include "note.h" #include "ui_note.h" diff --git a/source/note.h b/source/note.h index d432f34..f4e613d 100644 --- a/source/note.h +++ b/source/note.h @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #ifndef NOTE_H #define NOTE_H diff --git a/source/q_decodedetaildlg.cpp b/source/q_decodedetaildlg.cpp index 8ae9e32..a51d3d2 100644 --- a/source/q_decodedetaildlg.cpp +++ b/source/q_decodedetaildlg.cpp @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #include "q_decodedetaildlg.h" #include "ui_q_decodedetaildlg.h" diff --git a/source/q_decodedetaildlg.h b/source/q_decodedetaildlg.h index f36922b..4bdf24c 100644 --- a/source/q_decodedetaildlg.h +++ b/source/q_decodedetaildlg.h @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #ifndef Q_DECODEDETAILDLG_H #define Q_DECODEDETAILDLG_H diff --git a/source/snoop.h b/source/snoop.h index 0389d0d..e6c3aef 100644 --- a/source/snoop.h +++ b/source/snoop.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/snoopconfigdialog.cpp b/source/snoopconfigdialog.cpp index b3872c6..d7f6f1e 100644 --- a/source/snoopconfigdialog.cpp +++ b/source/snoopconfigdialog.cpp @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #include #include diff --git a/source/snoopconfigdialog.h b/source/snoopconfigdialog.h index 9d82b68..a04d5cd 100644 --- a/source/snoopconfigdialog.h +++ b/source/snoopconfigdialog.h @@ -1,3 +1,21 @@ +// JPEGsnoop - JPEG Image Decoder & Analysis Utility +// Copyright (C) 2018 - Calvin Hass +// http://www.impulseadventure.com/photo/jpeg-snoop.html +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + #ifndef SNOOPCONFIGDIALOG_H #define SNOOPCONFIGDIALOG_H From d2a47a629750cbe591cf72b79e93ad438c9bca75 Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Wed, 8 Aug 2018 08:09:28 -0700 Subject: [PATCH 13/14] Update file header comment --- source/DecodeDicom.cpp | 2 +- source/FolderDlg.cpp | 360 ----------------------------------------- source/FolderDlg.h | 178 -------------------- source/Signatures.inl | 2 +- source/UrlString.cpp | 4 +- source/UrlString.h | 2 +- 6 files changed, 5 insertions(+), 543 deletions(-) delete mode 100644 source/FolderDlg.cpp delete mode 100644 source/FolderDlg.h diff --git a/source/DecodeDicom.cpp b/source/DecodeDicom.cpp index 081bf9c..dde5fd8 100644 --- a/source/DecodeDicom.cpp +++ b/source/DecodeDicom.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/FolderDlg.cpp b/source/FolderDlg.cpp deleted file mode 100644 index 2ffb697..0000000 --- a/source/FolderDlg.cpp +++ /dev/null @@ -1,360 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code is based on an example CFolderDialog class that appears in MSDN: -// -// Title: CFolderDialog (C++ at Work: Counting MDI Children, Browsing for Folders) -// Authors: Paul DiLascia -// URL: http://msdn.microsoft.com/en-us/magazine/cc163789.aspx -// Date: Jun 2005 -// ==================================================================================================== - - - -////////////////////////////////////////////////////////////////// -// MSDN Magazine -- June 2005 -// If this code works, it was written by Paul DiLascia. -// If not, I don't know who wrote it. -// Compiles with Visual Studio .NET 2003 (V7.1) on Windows XP. Tab size=3. -// -#include "stdafx.h" -#include "FolderDlg.h" -#include - -// You must link shlwapi.lib for StrRetToBuf -#pragma comment(lib, "shlwapi.lib") - -//CAL! Commented out the following to avoid issues with DEBUG_INTERFACE_NAME -#if 0 //CAL! -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -BOOL CFolderDialog::bTRACE=0; // controls tracing - -////////////////// -// For deugging: names of interfaces easier to read than GUIDs! -// -DEBUG_BEGIN_INTERFACE_NAMES() - DEBUG_INTERFACE_NAME(IFolderFilterSite) - DEBUG_INTERFACE_NAME(IFolderFilter) -DEBUG_END_INTERFACE_NAMES(); - -#endif - -IMPLEMENT_DYNAMIC(CFolderDialog, CCmdTarget); - -////////////////// -// ctor: initialize most stuff to NULL -// -CFolderDialog::CFolderDialog(CWnd* pWnd) -{ - pWnd; // Unreferenced param - - //CAL! Modified the following to allow us to call this - // routine without a parent window defined. This - // is a temporary workaround so that I can call - // CFolderDialog() from the JPEGsnoopDoc class. - -//CAL! ASSERT(pWnd); - memset(&m_brinfo,0,sizeof(m_brinfo)); -//CAL! m_brinfo.hwndOwner=pWnd->m_hWnd; // use parent window - m_bFilter = FALSE; // default: no filtering - SHGetDesktopFolder(&m_shfRoot); // get root IShellFolder - - //CAL! Add support for start path - m_strStartPath = ""; -} - -////////////////// -// dtor: detach browser window before it's destroyed! -// -CFolderDialog::~CFolderDialog() -{ -} - -////////////////// -// Browse for folder. Args are same as for SHBrowseForFolder, but with extra -// bFilter that tells whether to do custom filtering. Note this requires -// BIF_NEWDIALOGSTYLE, which is inconsistent with some other flags--be -// careful! -// -LPCITEMIDLIST CFolderDialog::BrowseForFolder(LPCTSTR title, UINT flags, - LPCITEMIDLIST root, BOOL bFilter) -{ - //BFTRACE(_T("CFolderDialog::BrowseForFolder\n")); - TCHAR* buf = m_sDisplayName.GetBuffer(MAX_PATH); - m_brinfo.pidlRoot = root; - m_brinfo.pszDisplayName = buf; - m_brinfo.lpszTitle = title; - m_brinfo.ulFlags = flags; - m_brinfo.lpfn = CallbackProc; - m_brinfo.lParam = (LPARAM)this; - - // filtering only supported for new-style dialogs - m_bFilter = bFilter; - ASSERT(!bFilter||(m_brinfo.ulFlags & BIF_NEWDIALOGSTYLE)); - - LPCITEMIDLIST pidl = SHBrowseForFolder(&m_brinfo); // do it - m_sDisplayName.ReleaseBuffer(); - - return pidl; -} - -////////////////// -// Handy function to get the string pathname from pidl. -// -CString CFolderDialog::GetPathName(LPCITEMIDLIST pidl) -{ - CString path; - TCHAR* buf = path.GetBuffer(MAX_PATH); - SHGetPathFromIDList(pidl, buf); - path.ReleaseBuffer(); - return path; -} - -//CAL! Added -void CFolderDialog::SetStartPath(CString strPath) -{ - m_strStartPath = strPath; -} - -////////////////// -// Handy function to get the display name from pidl. -// -CString CFolderDialog::GetDisplayNameOf(IShellFolder* psf, LPCITEMIDLIST pidl, - DWORD uFlags) -{ - CString dn; - STRRET strret; // special struct for GetDisplayNameOf - strret.uType = STRRET_CSTR; // get as CSTR - if (SUCCEEDED(psf->GetDisplayNameOf(pidl, uFlags, &strret))) { - StrRetToBuf(&strret, pidl, dn.GetBuffer(MAX_PATH), MAX_PATH); - dn.ReleaseBuffer(); - } - return dn; -} - -////////////////// -// Free PIDL using shell's IMalloc -// -void CFolderDialog::FreePIDL(LPCITEMIDLIST pidl) -{ - CComQIPtr iMalloc; // shell's IMalloc - HRESULT hr = SHGetMalloc(&iMalloc); - ASSERT(SUCCEEDED(hr)); - iMalloc->Free((void*)pidl); -} - -////////////////// -// Internal callback proc used for SHBrowseForFolder passes control to -// appropriate virtual function after attaching browser window. -// -int CALLBACK CFolderDialog::CallbackProc(HWND hwnd, - UINT msg, LPARAM lp, LPARAM lpData) -{ - CFolderDialog* pDlg = (CFolderDialog*)lpData; - ASSERT(pDlg); - if (pDlg->m_hWnd!=hwnd) { - if (pDlg->m_hWnd) - pDlg->UnsubclassWindow(); - pDlg->SubclassWindow(hwnd); - } - return pDlg->OnMessage(msg, lp); -} - -////////////////// -// Handle notification from browser window: parse args and pass to specific -// virtual handler function. -// -int CFolderDialog::OnMessage(UINT msg, LPARAM lp) -{ - switch (msg) { - case BFFM_INITIALIZED: - OnInitialized(); - //CAL! - // Add support for initial start directory - if (!m_strStartPath.IsEmpty()) { - LPARAM lpStartPath; - lpStartPath = (LPARAM)(m_strStartPath.GetBuffer(1)); - m_strStartPath.ReleaseBuffer(); - ::SendMessage(this->m_hWnd,BFFM_SETSELECTION,TRUE,lpStartPath); - } - //CAL! - return 0; - case BFFM_IUNKNOWN: - OnIUnknown((IUnknown*)lp); - return 0; - case BFFM_SELCHANGED: - OnSelChanged((LPCITEMIDLIST)lp); - return 0; - case BFFM_VALIDATEFAILED: - return OnValidateFailed((LPCTSTR)lp); - default: - TRACE(_T("***Warning: unknown message %d in CFolderDialog::OnMessage\n")); - } - return 0; -} - -///////////////// -// Browser window initialized. -// -void CFolderDialog::OnInitialized() -{ - //BFTRACE(_T("CFolderDialog::OnInitialized\n")); -} - -///////////////// -// Browser is notifying me with its IUnknown: use it to set filter if -// requested. Note this can be called with punk=NULL when shutting down! -// -void CFolderDialog::OnIUnknown(IUnknown* punk) -{ - //BFTRACE(_T("CFolderDialog::OnIUnknown: %p\n"), punk); - if (punk && m_bFilter) { - CComQIPtr iffs; - VERIFY(SUCCEEDED(punk->QueryInterface(IID_IFolderFilterSite, (void**)&iffs))); - iffs->SetFilter((IFolderFilter*)&m_xFolderFilter); - // smart pointer automatically Releases iffs, - // no longer needed once you call SetFilter - } -} - -////////////////// -// User selected a different folder. -// -void CFolderDialog::OnSelChanged(LPCITEMIDLIST pidl) -{ - pidl; // Unrefernced param - //BFTRACE(_T("CFolderDialog::OnSelChanged: %s\n"), - // GetDisplayNameOf(m_shfRoot, pidl, SHGDN_FORPARSING)); -} - -////////////////// -// User attempted to enter a name in the edit box that isn't a folder. -// -BOOL CFolderDialog::OnValidateFailed(LPCTSTR lpsz) -{ - lpsz; // Unreferenced param - //BFTRACE(_T("CFolderDialog::OnValidateFailed: %s\n"), lpsz); - return TRUE; // don't close dialog. -} - -////////////////// -// Used for custom filtering. You must override to specify filter flags. -// -HRESULT CFolderDialog::OnGetEnumFlags( - IShellFolder* psf, // this folder's IShellFolder - LPCITEMIDLIST pidlFolder, // folder's PIDL - DWORD *pgrfFlags) // [out] return flags you want to allow -{ - psf; // Unreferenced param - pidlFolder; // Unreferenced param - pgrfFlags; // Unreferenced param - //BFTRACE(_T("CFolderDialog::OnGetEnumFlags(%p): %s\n"), - // psf, GetPathName(pidlFolder)); - return S_OK; -} - -////////////////// -// Used for custom filtering. You must override to filter items. -// -HRESULT CFolderDialog::OnShouldShow( - IShellFolder* psf, // This folder's IShellFolder - LPCITEMIDLIST pidlFolder, // PIDL for folder containing item - LPCITEMIDLIST pidlItem) // PIDL for item -{ - psf; // Unreferenced param - pidlFolder; // Unreferenced param - pidlItem; // Unreferenced param - //BFTRACE(_T("CFolderDialog::OnShouldShow(%p): %s: %s\n"), psf, - // GetDisplayNameOf(psf,pidlFolder,SHGDN_NORMAL), - // GetDisplayNameOf(psf,pidlItem,SHGDN_NORMAL)); - return S_OK; -} - -//////////////// Standard MFC IUnknown -- nested classes call these //////////////// - -STDMETHODIMP_(ULONG) CFolderDialog::AddRef() -{ - //BFTRACE(_T("CFolderDialog(%p)::AddRef\n"),this); - return ExternalAddRef(); -} - -STDMETHODIMP_(ULONG) CFolderDialog::Release() -{ - //BFTRACE(_T("CFolderDialog(%p)::Release\n"), this); - return ExternalRelease(); -} - -STDMETHODIMP CFolderDialog::QueryInterface(REFIID iid, LPVOID* ppvRet) -{ - if (ppvRet==NULL) - return E_INVALIDARG; - //BFTRACE(_T("CFolderDialog(%p)::QueryInterface(%s)\n"),this,_TR(iid)); - HRESULT hr = ExternalQueryInterface(&iid, ppvRet); - //BFTRACE(_T(">CFolderDialog::QueryInterface returns %s, *ppv=%p\n"),_TR(hr),*ppvRet); - return hr; -} - -//////////////////////////////// IFolderFilter //////////////////////////////// -// -// Implementation passes control to parent class CFolderDialog (pThis) -// -BEGIN_INTERFACE_MAP(CFolderDialog, CCmdTarget) - INTERFACE_PART(CFolderDialog, IID_IFolderFilter, FolderFilter) -END_INTERFACE_MAP() - -STDMETHODIMP_(ULONG) CFolderDialog::XFolderFilter::AddRef() -{ - METHOD_PROLOGUE(CFolderDialog, FolderFilter); - return pThis->AddRef(); -} - -STDMETHODIMP_(ULONG) CFolderDialog::XFolderFilter::Release() -{ - METHOD_PROLOGUE(CFolderDialog, FolderFilter); - return pThis->Release(); -} - -STDMETHODIMP CFolderDialog::XFolderFilter::QueryInterface(REFIID iid, LPVOID* ppv) -{ - METHOD_PROLOGUE(CFolderDialog, FolderFilter); - return pThis->QueryInterface(iid, ppv); -} - -// Note: pHwnd is always NULL here as far as I can tell. -STDMETHODIMP CFolderDialog::XFolderFilter::GetEnumFlags(IShellFolder* psf, - LPCITEMIDLIST pidlFolder, HWND *pHwnd, DWORD *pgrfFlags) -{ - pHwnd; // Unreferenced param - METHOD_PROLOGUE(CFolderDialog, FolderFilter); - return pThis->OnGetEnumFlags(psf, pidlFolder, pgrfFlags); -} - -STDMETHODIMP CFolderDialog::XFolderFilter::ShouldShow(IShellFolder* psf, - LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlItem) -{ - METHOD_PROLOGUE(CFolderDialog, FolderFilter); - return pThis->OnShouldShow(psf, pidlFolder, pidlItem); -} \ No newline at end of file diff --git a/source/FolderDlg.h b/source/FolderDlg.h deleted file mode 100644 index af1038b..0000000 --- a/source/FolderDlg.h +++ /dev/null @@ -1,178 +0,0 @@ -// JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass -// http://www.impulseadventure.com/photo/jpeg-snoop.html -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -// ==================================================================================================== -// SOURCE CODE ACKNOWLEDGEMENT -// ==================================================================================================== -// The following code is based on an example CFolderDialog class that appears in MSDN: -// -// Title: CFolderDialog (C++ at Work: Counting MDI Children, Browsing for Folders) -// Authors: Paul DiLascia -// URL: http://msdn.microsoft.com/en-us/magazine/cc163789.aspx -// Date: Jun 2005 -// ==================================================================================================== - - -//////////////////////////////////////////////////////////////// -// MSDN Magazine -- June 2005 -// If this code works, it was written by Paul DiLascia. -// If not, I don't know who wrote it. -// Compiles with Visual Studio .NET 2003 (V7.1) on Windows XP. Tab size=3. -// -#pragma once -//#include "debug.h" // debugging tools - -////////////////// -// BRTRACEFN is like TRACEFN but only does anything if -// CFolderDialog::bTRACE is on. See Debug.h. -// -#ifdef _DEBUG -#define BFTRACE \ - if (CFolderDialog::bTRACE) \ - TRACE -#else -#define BFTRACE -#endif - -////////////////// -// Class to encapsulate SHBrowseForFolder. To use, instantiate in your app -// and call BrowseForFolder, which returns a PIDL. You can call GetPathName -// to get the path name from the PIDL. For example: -// -// CFolderDialog dlg(this); -// LPCITEMIDLIST pidl = dlg.BrowseForFolder(...); -// CString path = dlg.GetPathName(pidl); -// -// You can also derive your own class from CFolderDialog to override virtual -// message handler functions like OnInitialized and OnSelChanged to do stuff -// when various things happen. This replaces the callback mechanism for -// SHBrowseForFolder. You call various wrapper functions from your hanlers to -// send messages to the browser window. For example: -// -// int CMyFolderDialog::OnInitialized() -// { -// CFolderDialog::OnInitialized(); -// SetStatusText(_T("Nice day, isn't it?")); -// SetOKText(L"Choose Me!"); -// return 0; -// } -// -// You can set CFolderDialog::bTRACE=TRUE to turn on debugging TRACE -// diagnostics to help you understand what's going on. -// -class CFolderDialog : public CWnd { -public: - static bool bTRACE; // controls tracing - - CFolderDialog(CWnd* pWnd); - ~CFolderDialog(); - - LPCITEMIDLIST BrowseForFolder(LPCTSTR title, UINT flags, - LPCITEMIDLIST pidRoot=NULL, bool bFilter=FALSE); - - CString GetDisplayName() { return m_sDisplayName; } - - // helpers - static CString GetPathName(LPCITEMIDLIST pidl); - static CString GetDisplayNameOf(IShellFolder* psf, LPCITEMIDLIST pidl, DWORD uFlags); - static void FreePIDL(LPCITEMIDLIST pidl); - - void SetStartPath(CString strPath); //CAL! -private: - CString m_strStartPath; //CAL! - -protected: - BROWSEINFO m_brinfo; // internal structure for SHBrowseForFolder - CString m_sDisplayName; // display name of folder chosen - bool m_bFilter; // do custom filtering? - CComQIPtr m_shfRoot; // handy to have root folder - - static int CALLBACK CallbackProc(HWND hwnd, UINT msg, LPARAM lp, LPARAM lpData); - - virtual int OnMessage(UINT msg, LPARAM lp); // internal catch-all - - // Virtual message handlers: override these instead of using callback - virtual void OnInitialized(); - virtual void OnIUnknown(IUnknown* punk); - virtual void OnSelChanged(LPCITEMIDLIST pidl); - virtual bool OnValidateFailed(LPCTSTR lpsz); - - // Wrapper functions for folder dialog messages--call these only from - // virtual handler functions above! - - // Enable or disable the OK button - void EnableOK(bool bEnable) { - SendMessage(BFFM_ENABLEOK,0,bEnable); - } - - // The Microsoft documentation is wrong for this: text in LPARAM, not WPARAM! - void SetOKText(LPCWSTR lpText) { - SendMessage(BFFM_SETOKTEXT,0,(LPARAM)lpText); - } - - // Set selected item from string or PIDL. - // The documentation says lpText must be Unicode, but it can be LPCTSTR. - void SetSelection(LPCTSTR lpText) { - SendMessage(BFFM_SETSELECTION,TRUE,(LPARAM)lpText); - } - void SetSelection(LPCITEMIDLIST pidl) { - SendMessage(BFFM_SETSELECTION,FALSE,(LPARAM)pidl); - } - - // Expand item from string or PIDL - void SetExpanded(LPCWSTR lpText) { - SendMessage(BFFM_SETEXPANDED,TRUE,(LPARAM)lpText); - } - void SetExpanded(LPCITEMIDLIST pidl) { - SendMessage(BFFM_SETEXPANDED,FALSE,(LPARAM)pidl); - } - - // Set status window text - void SetStatusText(LPCTSTR pText) { - SendMessage(BFFM_SETSTATUSTEXT,0,(LPARAM)pText); - } - - // Override for custom filtering. You must call BrowseForFolder with bFilter=TRUE. - virtual HRESULT OnGetEnumFlags(IShellFolder* psf, - LPCITEMIDLIST pidlFolder, - DWORD *pgrfFlags); - virtual HRESULT OnShouldShow(IShellFolder* psf, - LPCITEMIDLIST pidlFolder, - LPCITEMIDLIST pidlItem); - - // COM interfaces. The only one currently is IFolderFilter - DECLARE_INTERFACE_MAP() - - // IUnknown--all nested interfaces call these - STDMETHOD_(ULONG, AddRef)(); - STDMETHOD_(ULONG, Release)(); - STDMETHOD(QueryInterface)(REFIID iid, LPVOID* ppvObj); - - // COM interface IFolderFilter, used to do custom filtering - BEGIN_INTERFACE_PART(FolderFilter, IFolderFilter) - STDMETHOD(GetEnumFlags) (IShellFolder* psf, - LPCITEMIDLIST pidlFolder, - HWND *pHwnd, - DWORD *pgrfFlags); - STDMETHOD(ShouldShow) (IShellFolder* psf, - LPCITEMIDLIST pidlFolder, - LPCITEMIDLIST pidlItem); - END_INTERFACE_PART(FolderFilter) - - DECLARE_DYNAMIC(CFolderDialog) -}; diff --git a/source/Signatures.inl b/source/Signatures.inl index 8c902ce..9f4d45e 100644 --- a/source/Signatures.inl +++ b/source/Signatures.inl @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify diff --git a/source/UrlString.cpp b/source/UrlString.cpp index 536018b..65b7c5b 100644 --- a/source/UrlString.cpp +++ b/source/UrlString.cpp @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify @@ -76,4 +76,4 @@ CString CUrlString::Decode(CString csEncoded) csDecoded.Replace(csCharEncoded, csCharDecoded); } return csDecoded; -} \ No newline at end of file +} diff --git a/source/UrlString.h b/source/UrlString.h index 57daef3..25a606c 100644 --- a/source/UrlString.h +++ b/source/UrlString.h @@ -1,5 +1,5 @@ // JPEGsnoop - JPEG Image Decoder & Analysis Utility -// Copyright (C) 2017 - Calvin Hass +// Copyright (C) 2018 - Calvin Hass // http://www.impulseadventure.com/photo/jpeg-snoop.html // // This program is free software: you can redistribute it and/or modify From 70204dc1d6ecfcd08f40783b014386a33ff1ce6f Mon Sep 17 00:00:00 2001 From: Calvin Hass Date: Wed, 8 Aug 2018 08:10:52 -0700 Subject: [PATCH 14/14] Minor dialog text updates --- JPEGsnoopQt.pro | 3 ++- source/eula.ui | 2 +- source/mainwindow.ui | 8 ++++---- source/note.ui | 2 +- source/q_decodedetaildlg.ui | 8 ++++---- source/snoopconfigdialog.ui | 4 ++-- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/JPEGsnoopQt.pro b/JPEGsnoopQt.pro index 9a459a8..2a534d5 100644 --- a/JPEGsnoopQt.pro +++ b/JPEGsnoopQt.pro @@ -110,7 +110,8 @@ FORMS += \ source/snoopconfigdialog.ui \ source/q_decodedetaildlg.ui \ source/note.ui \ - source/eula.ui + source/eula.ui \ + source/mainwindow.ui RESOURCES = JPEGsnoop.qrc diff --git a/source/eula.ui b/source/eula.ui index 247450b..3b74e50 100644 --- a/source/eula.ui +++ b/source/eula.ui @@ -106,7 +106,7 @@ - Automatically check for updates + Periodically check for updates You can always change this option later in Configuration diff --git a/source/mainwindow.ui b/source/mainwindow.ui index 63810e6..b612c3c 100644 --- a/source/mainwindow.ui +++ b/source/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 708 - 652 + 768 + 680 @@ -19,8 +19,8 @@ 0 0 - 708 - 22 + 768 + 21 diff --git a/source/note.ui b/source/note.ui index a8edf70..00bb467 100644 --- a/source/note.ui +++ b/source/note.ui @@ -58,7 +58,7 @@ - In the future, do not show this message + In the future, do not show this coach message true diff --git a/source/q_decodedetaildlg.ui b/source/q_decodedetaildlg.ui index c196b82..9cd8397 100644 --- a/source/q_decodedetaildlg.ui +++ b/source/q_decodedetaildlg.ui @@ -60,7 +60,7 @@ QGroupBox::title { true - + 10 @@ -178,7 +178,7 @@ QGroupBox::title { true - + 10 @@ -249,7 +249,7 @@ QGroupBox::title { Detailed Scan Decode will be reported in the next decode operation - + 329 @@ -262,7 +262,7 @@ QGroupBox::title { - Load X/Y/Len + Load X/Y & Len from last 2 clicks: diff --git a/source/snoopconfigdialog.ui b/source/snoopconfigdialog.ui index ada1849..724a3a0 100644 --- a/source/snoopconfigdialog.ui +++ b/source/snoopconfigdialog.ui @@ -7,7 +7,7 @@ 0 0 541 - 426 + 429 @@ -221,7 +221,7 @@ QGroupBox::title { 10 20 335 - 41 + 42