Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
  15.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  18.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24.  * POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26. /////////////////////////////////////////////////////////////////////////////
  27. // Name:        imagjpeg2000.cpp
  28. // Purpose:     wxImage JPEG 2000 family file format handler
  29. // Author:      Giuseppe Baruffa - based on imagjpeg.cpp, Vaclav Slavik
  30. // RCS-ID:      $Id: imagjpeg2000.cpp,v 0.00 2008/01/31 10:58:00 MW Exp $
  31. // Copyright:   (c) Giuseppe Baruffa
  32. // Licence:     wxWindows licence
  33. /////////////////////////////////////////////////////////////////////////////
  34.  
  35. // For compilers that support precompilation, includes "wx.h".
  36. #include "wx/wxprec.h"
  37.  
  38. #ifdef __BORLANDC__
  39.     #pragma hdrstop
  40. #endif
  41.  
  42. #if wxUSE_IMAGE && wxUSE_LIBOPENJPEG
  43.  
  44. #include "imagjpeg2000.h"
  45.  
  46. #ifndef WX_PRECOMP
  47.     #include "wx/log.h"
  48.     #include "wx/app.h"
  49.     #include "wx/intl.h"
  50.     #include "wx/bitmap.h"
  51.     #include "wx/module.h"
  52. #endif
  53.  
  54. #include "libopenjpeg/openjpeg.h"
  55.  
  56. #include "wx/filefn.h"
  57. #include "wx/wfstream.h"
  58.  
  59. // ----------------------------------------------------------------------------
  60. // types
  61. // ----------------------------------------------------------------------------
  62.  
  63.  
  64. //-----------------------------------------------------------------------------
  65. // wxJPEG2000Handler
  66. //-----------------------------------------------------------------------------
  67.  
  68. IMPLEMENT_DYNAMIC_CLASS(wxJPEG2000Handler,wxImageHandler)
  69.  
  70. #if wxUSE_STREAMS
  71.  
  72. //------------- JPEG 2000 Data Source Manager
  73.  
  74. #define J2K_CFMT 0
  75. #define JP2_CFMT 1
  76. #define JPT_CFMT 2
  77. #define MJ2_CFMT 3
  78. #define PXM_DFMT 0
  79. #define PGX_DFMT 1
  80. #define BMP_DFMT 2
  81. #define YUV_DFMT 3
  82.  
  83. #define MAX_MESSAGE_LEN 200
  84.  
  85. /* check file type */
  86. int
  87. jpeg2000familytype(unsigned char *hdr, int hdr_len)
  88. {
  89.         // check length
  90.     if (hdr_len < 24)
  91.         return -1;
  92.  
  93.         // check format
  94.         if (hdr[0] == 0x00 &&
  95.                         hdr[1] == 0x00 &&
  96.                         hdr[2] == 0x00 &&
  97.                         hdr[3] == 0x0C &&
  98.                         hdr[4] == 0x6A &&
  99.                         hdr[5] == 0x50 &&
  100.                         hdr[6] == 0x20 &&
  101.                         hdr[7] == 0x20 &&
  102.                         hdr[20] == 0x6A &&
  103.                         hdr[21] == 0x70 &&
  104.                         hdr[22] == 0x32)
  105.                 // JP2 file format
  106.                 return JP2_CFMT;
  107.         else if (hdr[0] == 0x00 &&
  108.                         hdr[1] == 0x00 &&
  109.                         hdr[2] == 0x00 &&
  110.                         hdr[3] == 0x0C &&
  111.                         hdr[4] == 0x6A &&
  112.                         hdr[5] == 0x50 &&
  113.                         hdr[6] == 0x20 &&
  114.                         hdr[7] == 0x20 &&
  115.                         hdr[20] == 0x6D &&
  116.                         hdr[21] == 0x6A &&
  117.                         hdr[22] == 0x70 &&
  118.                         hdr[23] == 0x32)
  119.                 // MJ2 file format
  120.                 return MJ2_CFMT;
  121.         else if (hdr[0] == 0xFF &&
  122.                         hdr[1] == 0x4F)
  123.                 // J2K file format
  124.                 return J2K_CFMT;
  125.         else
  126.                 // unknown format
  127.                 return -1;
  128.  
  129. }
  130.  
  131. /* we have to use this to avoid GUI-noGUI threads crashing */
  132. void printevent(const char *msg)
  133. {
  134. #ifndef __WXGTK__
  135.         wxMutexGuiEnter();
  136. #endif /* __WXGTK__ */
  137.         wxLogMessage(wxT("%s"), msg);
  138. #ifndef __WXGTK__
  139.     wxMutexGuiLeave();
  140. #endif /* __WXGTK__ */
  141. }
  142.  
  143. /* sample error callback expecting a FILE* client object */
  144. void jpeg2000_error_callback(const char *msg, void *client_data) {
  145.         char mess[MAX_MESSAGE_LEN + 20];
  146.         int message_len = strlen(msg);
  147.  
  148.         if (message_len > MAX_MESSAGE_LEN)
  149.                 message_len = MAX_MESSAGE_LEN;
  150.        
  151.         if (msg[message_len - 1] == '\n')
  152.                 message_len--;
  153.  
  154.         sprintf(mess, "[ERROR] %.*s", message_len, msg);
  155.         printevent(mess);
  156. }
  157.  
  158. /* sample warning callback expecting a FILE* client object */
  159. void jpeg2000_warning_callback(const char *msg, void *client_data) {
  160.         char mess[MAX_MESSAGE_LEN + 20];
  161.         int message_len = strlen(msg);
  162.  
  163.         if (message_len > MAX_MESSAGE_LEN)
  164.                 message_len = MAX_MESSAGE_LEN;
  165.        
  166.         if (msg[message_len - 1] == '\n')
  167.                 message_len--;
  168.  
  169.         sprintf(mess, "[WARNING] %.*s", message_len, msg);
  170.         printevent(mess);
  171. }
  172.  
  173. /* sample debug callback expecting no client object */
  174. void jpeg2000_info_callback(const char *msg, void *client_data) {
  175.         char mess[MAX_MESSAGE_LEN + 20];
  176.         int message_len = strlen(msg);
  177.  
  178.         if (message_len > MAX_MESSAGE_LEN)
  179.                 message_len = MAX_MESSAGE_LEN;
  180.        
  181.         if (msg[message_len - 1] == '\n')
  182.                 message_len--;
  183.  
  184.         sprintf(mess, "[INFO] %.*s", message_len, msg);
  185.         printevent(mess);
  186. }
  187.  
  188. /* macro functions */
  189. /* From little endian to big endian, 2 and 4 bytes */
  190. #define BYTE_SWAP2(X)   ((X & 0x00FF) << 8) | ((X & 0xFF00) >> 8)
  191. #define BYTE_SWAP4(X)   ((X & 0x000000FF) << 24) | ((X & 0x0000FF00) << 8) | ((X & 0x00FF0000) >> 8) | ((X & 0xFF000000) >> 24)
  192.  
  193. #ifdef __WXGTK__
  194. #define BYTE_SWAP8(X)   ((X & 0x00000000000000FFULL) << 56) | ((X & 0x000000000000FF00ULL) << 40) | \
  195.                         ((X & 0x0000000000FF0000ULL) << 24) | ((X & 0x00000000FF000000ULL) << 8) | \
  196.                                                 ((X & 0x000000FF00000000ULL) >> 8)  | ((X & 0x0000FF0000000000ULL) >> 24) | \
  197.                                                 ((X & 0x00FF000000000000ULL) >> 40) | ((X & 0xFF00000000000000ULL) >> 56)
  198. #else
  199. #define BYTE_SWAP8(X)   ((X & 0x00000000000000FF) << 56) | ((X & 0x000000000000FF00) << 40) | \
  200.                         ((X & 0x0000000000FF0000) << 24) | ((X & 0x00000000FF000000) << 8) | \
  201.                                                 ((X & 0x000000FF00000000) >> 8)  | ((X & 0x0000FF0000000000) >> 24) | \
  202.                                                 ((X & 0x00FF000000000000) >> 40) | ((X & 0xFF00000000000000) >> 56)
  203. #endif
  204.  
  205. /* From codestream to int values */
  206. #define STREAM_TO_UINT32(C, P)  (((unsigned long int) (C)[(P) + 0] << 24) + \
  207.                                                                 ((unsigned long int) (C)[(P) + 1] << 16) + \
  208.                                                                 ((unsigned long int) (C)[(P) + 2] << 8) + \
  209.                                                                 ((unsigned long int) (C)[(P) + 3] << 0))
  210.  
  211. #define STREAM_TO_UINT16(C, P)  (((unsigned long int) (C)[(P) + 0] << 8) + \
  212.                                                                 ((unsigned long int) (C)[(P) + 1] << 0))
  213.  
  214. /* defines */
  215. #define SHORT_DESCR_LEN        32
  216. #define LONG_DESCR_LEN         256
  217.  
  218. /* enumeration for file formats */
  219. #define JPEG2000FILENUM              4
  220. typedef enum {
  221.  
  222.         JP2_FILE,
  223.         J2K_FILE,
  224.                 MJ2_FILE,
  225.                 UNK_FILE
  226.  
  227. } jpeg2000filetype;
  228.  
  229. /* enumeration for the box types */
  230. #define JPEG2000BOXNUM                23
  231. typedef enum {
  232.  
  233.                         FILE_BOX,
  234.                         JP_BOX,
  235.                         FTYP_BOX,
  236.                         JP2H_BOX,
  237.                         IHDR_BOX,
  238.                         COLR_BOX,
  239.                         JP2C_BOX,
  240.                         JP2I_BOX,
  241.                         XML_BOX,
  242.                         UUID_BOX,
  243.                         UINF_BOX,
  244.                         MOOV_BOX,
  245.                         MVHD_BOX,
  246.                         TRAK_BOX,
  247.                         TKHD_BOX,
  248.                         MDIA_BOX,
  249.                         MINF_BOX,
  250.                         STBL_BOX,
  251.                         STSD_BOX,
  252.                         MJP2_BOX,
  253.                         MDAT_BOX,
  254.                         ANY_BOX,
  255.                         UNK_BOX
  256.  
  257. } jpeg2000boxtype;
  258.  
  259. /* jpeg2000 family box signatures */
  260. #define FILE_SIGN           ""
  261. #define JP_SIGN             "jP\040\040"
  262. #define FTYP_SIGN           "ftyp"
  263. #define JP2H_SIGN           "jp2h"
  264. #define IHDR_SIGN           "ihdr"
  265. #define COLR_SIGN           "colr"
  266. #define JP2C_SIGN           "jp2c"
  267. #define JP2I_SIGN           "jp2i"
  268. #define XML_SIGN            "xml\040"
  269. #define UUID_SIGN           "uuid"
  270. #define UINF_SIGN           "uinf"
  271. #define MOOV_SIGN           "moov"
  272. #define MVHD_SIGN           "mvhd"
  273. #define TRAK_SIGN           "trak"
  274. #define TKHD_SIGN           "tkhd"
  275. #define MDIA_SIGN           "mdia"
  276. #define MINF_SIGN           "minf"
  277. #define VMHD_SIGN           "vmhd"
  278. #define STBL_SIGN           "stbl"
  279. #define STSD_SIGN           "stsd"
  280. #define MJP2_SIGN           "mjp2"
  281. #define MDAT_SIGN           "mdat"
  282. #define ANY_SIGN                        ""
  283. #define UNK_SIGN            ""
  284.  
  285. /* the box structure itself */
  286. struct jpeg2000boxdef {
  287.  
  288.         char                  value[5];                 /* hexadecimal value/string*/
  289.                 char                  name[SHORT_DESCR_LEN];    /* short description       */
  290.                 char                  descr[LONG_DESCR_LEN];    /* long  description       */
  291.                 int                   sbox;                     /* is it a superbox?       */
  292.                 int                   req[JPEG2000FILENUM];     /* mandatory box           */
  293.                 jpeg2000boxtype       ins;                      /* contained in box...     */
  294.  
  295. };
  296.  
  297. /* the possible boxes */
  298. struct jpeg2000boxdef jpeg2000box[] =
  299. {
  300. /* sign */      {FILE_SIGN,
  301. /* short */     "placeholder for nothing",
  302. /* long */      "Nothing to say",
  303. /* sbox */      0,
  304. /* req */       {1, 1, 1},
  305. /* ins */       FILE_BOX},
  306.  
  307. /* sign */      {JP_SIGN,
  308. /* short */     "JPEG 2000 Signature box",
  309. /* long */      "This box uniquely identifies the file as being part of the JPEG 2000 family of files",
  310. /* sbox */      0,
  311. /* req */       {1, 1, 1},
  312. /* ins */       FILE_BOX},
  313.  
  314. /* sign */      {FTYP_SIGN,
  315. /* short */     "File Type box",
  316. /* long */      "This box specifies file type, version and compatibility information, including specifying if this file "
  317.                         "is a conforming JP2 file or if it can be read by a conforming JP2 reader",
  318. /* sbox */      0,
  319. /* req */       {1, 1, 1},
  320. /* ins */       FILE_BOX},
  321.  
  322. /* sign */      {JP2H_SIGN,
  323. /* short */     "JP2 Header box",
  324. /* long */      "This box contains a series of boxes that contain header-type information about the file",
  325. /* sbox */      1,
  326. /* req */       {1, 1, 1},
  327. /* ins */       FILE_BOX},
  328.  
  329. /* sign */      {IHDR_SIGN,
  330. /* short */     "Image Header box",
  331. /* long */      "This box specifies the size of the image and other related fields",
  332. /* sbox */      0,
  333. /* req */       {1, 1, 1},
  334. /* ins */       JP2H_BOX},
  335.  
  336. /* sign */      {COLR_SIGN,
  337. /* short */     "Colour Specification box",
  338. /* long */      "This box specifies the colourspace of the image",
  339. /* sbox */      0,
  340. /* req */       {1, 1, 1},
  341. /* ins */       JP2H_BOX},
  342.  
  343. /* sign */      {JP2C_SIGN,
  344. /* short */     "Contiguous Codestream box",
  345. /* long */      "This box contains the codestream as defined by Annex A",
  346. /* sbox */      0,
  347. /* req */       {1, 1, 1},
  348. /* ins */       FILE_BOX},
  349.  
  350. /* sign */      {JP2I_SIGN,
  351. /* short */     "Intellectual Property box",
  352. /* long */      "This box contains intellectual property information about the image",
  353. /* sbox */      0,
  354. /* req */       {0, 0, 0},
  355. /* ins */       FILE_BOX},
  356.  
  357. /* sign */      {XML_SIGN,
  358. /* short */     "XML box",
  359. /* long */      "This box provides a tool by which vendors can add XML formatted information to a JP2 file",
  360. /* sbox */      0,
  361. /* req */       {0, 0, 0},
  362. /* ins */       FILE_BOX},
  363.  
  364. /* sign */      {UUID_SIGN,
  365. /* short */     "UUID box",
  366. /* long */      "This box provides a tool by which vendors can add additional information to a file "
  367.                         "without risking conflict with other vendors",
  368. /* sbox */      0,
  369. /* req */       {0, 0, 0},
  370. /* ins */       FILE_BOX},
  371.  
  372. /* sign */      {UINF_SIGN,
  373. /* short */     "UUID Info box",
  374. /* long */      "This box provides a tool by which a vendor may provide access to additional information associated with a UUID",
  375. /* sbox */      0,
  376. /* req */       {0, 0, 0},
  377. /* ins */       FILE_BOX},
  378.  
  379. /* sign */      {MOOV_SIGN,
  380. /* short */     "Movie box",
  381. /* long */      "This box contains the media data. In video tracks, this box would contain JPEG2000 video frames",
  382. /* sbox */      1,
  383. /* req */       {1, 1, 1},
  384. /* ins */       FILE_BOX},
  385.  
  386. /* sign */      {MVHD_SIGN,
  387. /* short */     "Movie Header box",
  388. /* long */      "This box defines overall information which is media-independent, and relevant to the entire presentation "
  389.                         "considered as a whole",
  390. /* sbox */      0,
  391. /* req */       {1, 1, 1},
  392. /* ins */       MOOV_BOX},
  393.  
  394. /* sign */      {TRAK_SIGN,
  395. /* short */     "Track box",
  396. /* long */      "This is a container box for a single track of a presentation. A presentation may consist of one or more tracks",
  397. /* sbox */      1,
  398. /* req */       {1, 1, 1},
  399. /* ins */       MOOV_BOX},
  400.  
  401. /* sign */      {TKHD_SIGN,
  402. /* short */     "Track Header box",
  403. /* long */      "This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track",
  404. /* sbox */      0,
  405. /* req */       {1, 1, 1},
  406. /* ins */       TRAK_BOX},
  407.  
  408. /* sign */      {MDIA_SIGN,
  409. /* short */     "Media box",
  410. /* long */      "The media declaration container contains all the objects which declare information about the media data "
  411.                         "within a track",
  412. /* sbox */      1,
  413. /* req */       {1, 1, 1},
  414. /* ins */       TRAK_BOX},
  415.  
  416. /* sign */      {MINF_SIGN,
  417. /* short */     "Media Information box",
  418. /* long */      "This box contains all the objects which declare characteristic information of the media in the track",
  419. /* sbox */      1,
  420. /* req */       {1, 1, 1},
  421. /* ins */       MDIA_BOX},
  422.  
  423. /* sign */      {STBL_SIGN,
  424. /* short */     "Sample Table box",
  425. /* long */      "The sample table contains all the time and data indexing of the media samples in a track",
  426. /* sbox */      1,
  427. /* req */       {1, 1, 1},
  428. /* ins */       MINF_BOX},
  429.  
  430. /* sign */      {STSD_SIGN,
  431. /* short */     "Sample Description box",
  432. /* long */      "The sample description table gives detailed information about the coding type used, and any initialization "
  433.                         "information needed for that coding",
  434. /* sbox */      0,
  435. /* req */       {1, 1, 1},
  436. /* ins */       MINF_BOX},
  437.  
  438. /* sign */      {MJP2_SIGN,
  439. /* short */     "MJP2 Sample Description box",
  440. /* long */      "The MJP2 sample description table gives detailed information about the coding type used, and any initialization "
  441.                         "information needed for that coding",
  442. /* sbox */      0,
  443. /* req */       {1, 1, 1},
  444. /* ins */       MINF_BOX},
  445.  
  446. /* sign */      {MDAT_SIGN,
  447. /* short */     "Media Data box",
  448. /* long */      "The meta-data for a presentation is stored in the single Movie Box which occurs at the top-level of a file",
  449. /* sbox */      1,
  450. /* req */       {1, 1, 1},
  451. /* ins */       FILE_BOX},
  452.  
  453. /* sign */      {ANY_SIGN,
  454. /* short */     "Any box",
  455. /* long */      "All the existing boxes",
  456. /* sbox */      0,
  457. /* req */       {0, 0, 0},
  458. /* ins */       FILE_BOX},
  459.  
  460. /* sign */      {UNK_SIGN,
  461. /* short */     "Unknown Type box",
  462. /* long */      "The signature is not recognised to be that of an existing box",
  463. /* sbox */      0,
  464. /* req */       {0, 0, 0},
  465. /* ins */       ANY_BOX}
  466.  
  467. };
  468.  
  469. /* declaration */
  470. int
  471. jpeg2000_box_handler_function(jpeg2000boxtype boxtype, wxInputStream& stream, unsigned long int filepoint,
  472.                                                           unsigned long int filelimit, int level, char *scansign,
  473.                                                           unsigned long int *scanpoint);
  474.  
  475. #ifdef __WXMSW__
  476. typedef unsigned __int64 int8byte;
  477. #endif // __WXMSW__
  478.  
  479. #ifdef __WXGTK__
  480. typedef unsigned long long int8byte;
  481. #endif // __WXGTK__
  482.  
  483. /* internal mini-search for a box signature */
  484. int
  485. jpeg2000_file_parse(wxInputStream& stream, unsigned long int filepoint, unsigned long int filelimit, int level,
  486.                                         char *scansign, unsigned long int *scanpoint)
  487. {
  488.         unsigned long int       LBox = 0x00000000;
  489.         char                    TBox[5] = "\0\0\0\0";
  490.         int8byte                XLBox = 0x0000000000000000;
  491.         unsigned long int       box_length = 0;
  492.         int                     last_box = 0, box_num = 0;
  493.         int                     box_type = ANY_BOX;
  494.         unsigned char           fourbytes[4];
  495.         int                     box_number = 0;
  496.  
  497.         /* cycle all over the file */
  498.         box_num = 0;
  499.         last_box = 0;
  500.         while (!last_box) {
  501.  
  502.                 /* do not exceed file limit */
  503.                 if (filepoint >= filelimit)
  504.                         return (0);
  505.  
  506.                 /* seek on file */
  507.                 if (stream.SeekI(filepoint, wxFromStart) == wxInvalidOffset)
  508.                         return (-1);
  509.  
  510.                 /* read the mandatory LBox, 4 bytes */
  511.                 if (!stream.Read(fourbytes, 4)) {
  512.                         wxLogError(wxT("Problem reading LBox from the file (file ended?)"));
  513.                         return -1;
  514.                 };
  515.                 LBox = STREAM_TO_UINT32(fourbytes, 0);
  516.  
  517.                 /* read the mandatory TBox, 4 bytes */
  518.                 if (!stream.Read(TBox, 4)) {
  519.                         wxLogError(wxT("Problem reading TBox from the file (file ended?)"));
  520.                         return -1;
  521.                 };
  522.  
  523.                 /* look if scansign is got */
  524.                 if ((scansign != NULL) && (memcmp(TBox, scansign, 4) == 0)) {
  525.                         /* hack/exploit */
  526.                         // stop as soon as you find the level-th codebox
  527.                         if (box_number == level) {
  528.                                 memcpy(scansign, "    ", 4);
  529.                                 *scanpoint = filepoint;
  530.                                 return (0);
  531.                         } else
  532.                                 box_number++;
  533.  
  534.                 };
  535.  
  536.                 /* determine the box type */
  537.                 for (box_type = JP_BOX; box_type < UNK_BOX; box_type++)
  538.                         if (memcmp(TBox, jpeg2000box[box_type].value, 4) == 0)
  539.                                 break; 
  540.  
  541.                 /* read the optional XLBox, 8 bytes */
  542.                 if (LBox == 1) {
  543.  
  544.                         if (!stream.Read(&XLBox, 8)) {
  545.                                 wxLogError(wxT("Problem reading XLBox from the file (file ended?)"));
  546.                                 return -1;
  547.                         };
  548.                         box_length = (unsigned long int) BYTE_SWAP8(XLBox);
  549.  
  550.                 } else if (LBox == 0x00000000) {
  551.  
  552.                         /* last box in file */
  553.                         last_box = 1;
  554.                         box_length = filelimit - filepoint;
  555.  
  556.                 } else
  557.  
  558.                         box_length = LBox;
  559.  
  560.  
  561.                 /* go deep in the box */
  562.                 jpeg2000_box_handler_function((jpeg2000boxtype) box_type,
  563.                         stream, (LBox == 1) ? (filepoint + 16) : (filepoint + 8),
  564.                         filepoint + box_length, level, scansign, scanpoint);
  565.  
  566.                 /* if it's a superbox go inside it */
  567.                 if (jpeg2000box[box_type].sbox)
  568.                         jpeg2000_file_parse(stream, (LBox == 1) ? (filepoint + 16) : (filepoint + 8), filepoint + box_length,
  569.                                 level, scansign, scanpoint);
  570.  
  571.                 /* increment box number and filepoint*/
  572.                 box_num++;
  573.                 filepoint += box_length;
  574.  
  575.         };
  576.  
  577.         /* all good */
  578.         return (0);
  579. }
  580.  
  581. // search first contiguos codestream box in an mj2 file
  582. unsigned long int
  583. searchjpeg2000c(wxInputStream& stream, unsigned long int fsize, int number)
  584. {
  585.         char scansign[] = "jp2c";
  586.         unsigned long int scanpoint = 0L;
  587.  
  588.         wxLogMessage(wxT("Searching jp2c box... "));
  589.  
  590.         /* do the parsing */
  591.         if (jpeg2000_file_parse(stream, 0, fsize, number, scansign, &scanpoint) < 0)           
  592.                 wxLogMessage(wxT("Unrecoverable error during JPEG 2000 box parsing: stopping"));
  593.  
  594.         if (strcmp(scansign, "    "))
  595.                 wxLogMessage(wxT("Box not found"));
  596.         else {
  597.  
  598.                 wxLogMessage(wxString::Format(wxT("Box found at byte %d"), scanpoint));
  599.  
  600.         };
  601.  
  602.         return (scanpoint);
  603. }
  604.  
  605. // search the jp2h box in the file
  606. unsigned long int
  607. searchjpeg2000headerbox(wxInputStream& stream, unsigned long int fsize)
  608. {
  609.         char scansign[] = "jp2h";
  610.         unsigned long int scanpoint = 0L;
  611.  
  612.         wxLogMessage(wxT("Searching jp2h box... "));
  613.  
  614.         /* do the parsing */
  615.         if (jpeg2000_file_parse(stream, 0, fsize, 0, scansign, &scanpoint) < 0)        
  616.                 wxLogMessage(wxT("Unrecoverable error during JPEG 2000 box parsing: stopping"));
  617.  
  618.         if (strcmp(scansign, "    "))
  619.                 wxLogMessage(wxT("Box not found"));
  620.         else
  621.                 wxLogMessage(wxString::Format(wxT("Box found at byte %d"), scanpoint));
  622.  
  623.         return (scanpoint);
  624. }
  625.  
  626. /* handling functions */
  627. #define ITEM_PER_ROW    10
  628.  
  629. /* Box handler function */
  630. int
  631. jpeg2000_box_handler_function(jpeg2000boxtype boxtype, wxInputStream& stream, unsigned long int filepoint,
  632.                                                           unsigned long int filelimit, int level,
  633.                                                           char *scansign, unsigned long int *scanpoint)
  634. {
  635.         switch (boxtype) {
  636.  
  637.         /* Sample Description box */
  638.         case (STSD_BOX):
  639.                 jpeg2000_file_parse(stream, filepoint + 8, filelimit, level, scansign, scanpoint);
  640.                 break;
  641.  
  642.         /* MJP2 Sample Description box */
  643.         case (MJP2_BOX):
  644.                 jpeg2000_file_parse(stream, filepoint + 78, filelimit, level, scansign, scanpoint);
  645.                 break;
  646.                
  647.         /* not yet implemented */
  648.         default:
  649.                 break;
  650.  
  651.         };
  652.  
  653.         return (0);
  654. }
  655.  
  656. // the jP and ftyp parts of the header
  657. #define jpeg2000headSIZE        32
  658. unsigned char jpeg2000head[jpeg2000headSIZE] = {
  659.                 0x00, 0x00, 0x00, 0x0C,  'j',  'P',  ' ',  ' ',
  660.                 0x0D, 0x0A, 0x87, 0x0A, 0x00, 0x00, 0x00, 0x14,
  661.                  'f',  't',  'y',  'p',  'j',  'p',  '2',  ' ',
  662.                 0x00, 0x00, 0x00, 0x00,  'j',  'p',  '2',  ' '                 
  663. };
  664.  
  665. /////////////////////////////////////////////////
  666. /////////////////////////////////////////////////
  667.  
  668. // load the jpeg2000 file format
  669. bool wxJPEG2000Handler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index)
  670. {
  671.         opj_dparameters_t parameters;   /* decompression parameters */
  672.         opj_event_mgr_t event_mgr;              /* event manager */
  673.         opj_image_t *opjimage = NULL;
  674.         unsigned char *src = NULL;
  675.     unsigned char *ptr;
  676.         int file_length, jp2c_point, jp2h_point;
  677.         unsigned long int jp2hboxlen, jp2cboxlen;
  678.         opj_codestream_info_t cstr_info;  /* Codestream information structure */
  679.     unsigned char hdr[24];
  680.         int jpfamform;
  681.  
  682.         // destroy the image
  683.     image->Destroy();
  684.  
  685.         /* read the beginning of the file to check the type */
  686.     if (!stream.Read(hdr, WXSIZEOF(hdr)))
  687.         return false;
  688.         if ((jpfamform = jpeg2000familytype(hdr, WXSIZEOF(hdr))) < 0)
  689.                 return false;
  690.         stream.SeekI(0, wxFromStart);
  691.  
  692.         /* handle to a decompressor */
  693.         opj_dinfo_t* dinfo = NULL;     
  694.         opj_cio_t *cio = NULL;
  695.  
  696.         /* configure the event callbacks */
  697.         memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
  698.         event_mgr.error_handler = jpeg2000_error_callback;
  699.         event_mgr.warning_handler = jpeg2000_warning_callback;
  700.         event_mgr.info_handler = jpeg2000_info_callback;
  701.  
  702.         /* set decoding parameters to default values */
  703.         opj_set_default_decoder_parameters(&parameters);
  704.  
  705.         /* prepare parameters */
  706.         strncpy(parameters.infile, "", sizeof(parameters.infile) - 1);
  707.         strncpy(parameters.outfile, "", sizeof(parameters.outfile) - 1);
  708.         parameters.decod_format = jpfamform;
  709.         parameters.cod_format = BMP_DFMT;
  710.         if (m_reducefactor)
  711.                 parameters.cp_reduce = m_reducefactor;
  712.         if (m_qualitylayers)
  713.                 parameters.cp_layer = m_qualitylayers;
  714.         /*if (n_components)
  715.                 parameters. = n_components;*/
  716.  
  717.         /* JPWL only */
  718. #ifdef USE_JPWL
  719.         parameters.jpwl_exp_comps = m_expcomps;
  720.         parameters.jpwl_max_tiles = m_maxtiles;
  721.         parameters.jpwl_correct = m_enablejpwl;
  722. #endif /* USE_JPWL */
  723.  
  724.         /* get a decoder handle */
  725.         if (jpfamform == JP2_CFMT || jpfamform == MJ2_CFMT)
  726.                 dinfo = opj_create_decompress(CODEC_JP2);
  727.         else if (jpfamform == J2K_CFMT)
  728.                 dinfo = opj_create_decompress(CODEC_J2K);
  729.         else
  730.                 return false;
  731.  
  732.         /* find length of the stream */
  733.         stream.SeekI(0, wxFromEnd);
  734.         file_length = (int) stream.TellI();
  735.  
  736.         /* it's a movie */
  737.         if (jpfamform == MJ2_CFMT) {
  738.                 /* search for the first codestream box and the movie header box  */
  739.                 jp2c_point = searchjpeg2000c(stream, file_length, m_framenum);
  740.                 jp2h_point = searchjpeg2000headerbox(stream, file_length);
  741.  
  742.                 // read the jp2h box and store it
  743.                 stream.SeekI(jp2h_point, wxFromStart);
  744.                 stream.Read(&jp2hboxlen, sizeof(unsigned long int));
  745.                 jp2hboxlen = BYTE_SWAP4(jp2hboxlen);
  746.  
  747.                 // read the jp2c box and store it
  748.                 stream.SeekI(jp2c_point, wxFromStart);
  749.                 stream.Read(&jp2cboxlen, sizeof(unsigned long int));
  750.                 jp2cboxlen = BYTE_SWAP4(jp2cboxlen);
  751.  
  752.                 // malloc memory source
  753.                 src = (unsigned char *) malloc(jpeg2000headSIZE + jp2hboxlen + jp2cboxlen);
  754.  
  755.                 // copy the jP and ftyp
  756.                 memcpy(src, jpeg2000head, jpeg2000headSIZE);
  757.  
  758.                 // copy the jp2h
  759.                 stream.SeekI(jp2h_point, wxFromStart);
  760.                 stream.Read(&src[jpeg2000headSIZE], jp2hboxlen);
  761.  
  762.                 // copy the jp2c
  763.                 stream.SeekI(jp2c_point, wxFromStart);
  764.                 stream.Read(&src[jpeg2000headSIZE + jp2hboxlen], jp2cboxlen);
  765.         } else  if (jpfamform == JP2_CFMT || jpfamform == J2K_CFMT) {
  766.                 /* It's a plain image */
  767.                 /* get data */
  768.                 stream.SeekI(0, wxFromStart);
  769.                 src = (unsigned char *) malloc(file_length);
  770.                 stream.Read(src, file_length);
  771.         } else
  772.                 return false;
  773.  
  774.         /* catch events using our callbacks and give a local context */
  775.         opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
  776.  
  777.         /* setup the decoder decoding parameters using user parameters */
  778.         opj_setup_decoder(dinfo, &parameters);
  779.  
  780.         /* open a byte stream */
  781.         if (jpfamform == MJ2_CFMT)
  782.                 cio = opj_cio_open((opj_common_ptr)dinfo, src, jpeg2000headSIZE + jp2hboxlen + jp2cboxlen);
  783.         else if (jpfamform == JP2_CFMT || jpfamform == J2K_CFMT)
  784.                 cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
  785.         else {
  786.                 free(src);
  787.                 return false;
  788.         }
  789.  
  790.         /* decode the stream and fill the image structure */
  791.         opjimage = opj_decode_with_info(dinfo, cio, &cstr_info);
  792.         if (!opjimage) {
  793.                 wxMutexGuiEnter();
  794.                 wxLogError(wxT("JPEG 2000 failed to decode image!"));
  795.                 wxMutexGuiLeave();
  796.                 opj_destroy_decompress(dinfo);
  797.                 opj_cio_close(cio);
  798.                 free(src);
  799.                 return false;
  800.         }
  801.  
  802.         /* close the byte stream */
  803.         opj_cio_close(cio);
  804.  
  805.         /*
  806.  
  807.         - At this point, we have the structure "opjimage" that is filled with decompressed
  808.           data, as processed by the OpenJPEG decompression engine
  809.  
  810.         - We need to fill the class "image" with the proper pixel sample values
  811.  
  812.         */
  813.         {
  814.                 int shiftbpp;
  815.                 int c, tempcomps;
  816.  
  817.                 // check components number
  818.                 if (m_components > opjimage->numcomps)
  819.                         m_components = opjimage->numcomps;
  820.  
  821.                 // check image depth (only on the first one, for now)
  822.                 if (m_components)
  823.                         shiftbpp = opjimage->comps[m_components - 1].prec - 8;
  824.                 else
  825.                         shiftbpp = opjimage->comps[0].prec - 8;
  826.  
  827.                 // prepare image size
  828.                 if (m_components)
  829.                         image->Create(opjimage->comps[m_components - 1].w, opjimage->comps[m_components - 1].h, true);
  830.                 else
  831.                         image->Create(opjimage->comps[0].w, opjimage->comps[0].h, true);
  832.  
  833.                 // access image raw data
  834.                 image->SetMask(false);
  835.                 ptr = image->GetData();
  836.  
  837.                 // workaround for components different from 1 or 3
  838.                 if ((opjimage->numcomps != 1) && (opjimage->numcomps != 3)) {
  839. #ifndef __WXGTK__
  840.                         wxMutexGuiEnter();
  841. #endif /* __WXGTK__ */
  842.                         wxLogMessage(wxT("JPEG2000: weird number of components"));
  843. #ifndef __WXGTK__
  844.                         wxMutexGuiLeave();
  845. #endif /* __WXGTK__ */
  846.                         tempcomps = 1;
  847.                 } else
  848.                         tempcomps = opjimage->numcomps;
  849.  
  850.                 // workaround for subsampled components
  851.                 for (c = 1; c < tempcomps; c++) {
  852.                         if ((opjimage->comps[c].w != opjimage->comps[c - 1].w) || (opjimage->comps[c].h != opjimage->comps[c - 1].h)) {
  853.                                 tempcomps = 1;
  854.                                 break;
  855.                         }
  856.                 }
  857.  
  858.                 // workaround for different precision components
  859.                 for (c = 1; c < tempcomps; c++) {
  860.                         if (opjimage->comps[c].bpp != opjimage->comps[c - 1].bpp) {
  861.                                 tempcomps = 1;
  862.                                 break;
  863.                         }
  864.                 }
  865.  
  866.                 // only one component selected
  867.                 if (m_components)
  868.                         tempcomps = 1;
  869.  
  870.                 // RGB color picture
  871.                 if (tempcomps == 3) {
  872.                         int row, col;
  873.                         int *r = opjimage->comps[0].data;
  874.                         int *g = opjimage->comps[1].data;
  875.                         int *b = opjimage->comps[2].data;
  876.                         if (shiftbpp > 0) {
  877.                                 for (row = 0; row < opjimage->comps[0].h; row++) {
  878.                                         for (col = 0; col < opjimage->comps[0].w; col++) {
  879.                                                
  880.                                                 *(ptr++) = (*(r++)) >> shiftbpp;
  881.                                                 *(ptr++) = (*(g++)) >> shiftbpp;
  882.                                                 *(ptr++) = (*(b++)) >> shiftbpp;
  883.  
  884.                                         }
  885.                                 }
  886.  
  887.                         } else if (shiftbpp < 0) {
  888.                                 for (row = 0; row < opjimage->comps[0].h; row++) {
  889.                                         for (col = 0; col < opjimage->comps[0].w; col++) {
  890.                                                
  891.                                                 *(ptr++) = (*(r++)) << -shiftbpp;
  892.                                                 *(ptr++) = (*(g++)) << -shiftbpp;
  893.                                                 *(ptr++) = (*(b++)) << -shiftbpp;
  894.  
  895.                                         }
  896.                                 }
  897.                                
  898.                         } else {
  899.                                 for (row = 0; row < opjimage->comps[0].h; row++) {
  900.                                         for (col = 0; col < opjimage->comps[0].w; col++) {
  901.  
  902.                                                 *(ptr++) = *(r++);
  903.                                                 *(ptr++) = *(g++);
  904.                                                 *(ptr++) = *(b++);
  905.                                        
  906.                                         }
  907.                                 }
  908.                         }
  909.                 }
  910.  
  911.                 // B/W picture
  912.                 if (tempcomps == 1) {
  913.                         int row, col;
  914.                         int selcomp;
  915.  
  916.                         if (m_components)
  917.                                 selcomp = m_components - 1;
  918.                         else
  919.                                 selcomp = 0;
  920.  
  921.                         int *y = opjimage->comps[selcomp].data;
  922.                         if (shiftbpp > 0) {
  923.                                 for (row = 0; row < opjimage->comps[selcomp].h; row++) {
  924.                                         for (col = 0; col < opjimage->comps[selcomp].w; col++) {
  925.                                                
  926.                                                 *(ptr++) = (*(y)) >> shiftbpp;
  927.                                                 *(ptr++) = (*(y)) >> shiftbpp;
  928.                                                 *(ptr++) = (*(y++)) >> shiftbpp;
  929.  
  930.                                         }
  931.                                 }
  932.                         } else if (shiftbpp < 0) {
  933.                                 for (row = 0; row < opjimage->comps[selcomp].h; row++) {
  934.                                         for (col = 0; col < opjimage->comps[selcomp].w; col++) {
  935.                                                
  936.                                                 *(ptr++) = (*(y)) << -shiftbpp;
  937.                                                 *(ptr++) = (*(y)) << -shiftbpp;
  938.                                                 *(ptr++) = (*(y++)) << -shiftbpp;
  939.  
  940.                                         }
  941.                                 }
  942.                         } else {
  943.                                 for (row = 0; row < opjimage->comps[selcomp].h; row++) {
  944.                                         for (col = 0; col < opjimage->comps[selcomp].w; col++) {
  945.                                                
  946.                                                 *(ptr++) = *(y);
  947.                                                 *(ptr++) = *(y);
  948.                                                 *(ptr++) = *(y++);
  949.  
  950.                                         }
  951.                                 }
  952.                         }
  953.                 }
  954.  
  955.  
  956.         }
  957.  
  958.     wxMutexGuiEnter();
  959.     wxLogMessage(wxT("JPEG 2000 image loaded."));
  960.     wxMutexGuiLeave();
  961.  
  962.         /* close openjpeg structs */
  963.         opj_destroy_decompress(dinfo);
  964.         opj_image_destroy(opjimage);
  965.         free(src);
  966.  
  967.         if (!image->Ok())
  968.                 return false;
  969.         else
  970.                 return true;
  971.  
  972. }
  973.  
  974. #define CINEMA_24_CS 1302083    /* Codestream length for 24fps */
  975. #define CINEMA_48_CS 651041             /* Codestream length for 48fps */
  976. #define COMP_24_CS 1041666              /* Maximum size per color component for 2K & 4K @ 24fps */
  977. #define COMP_48_CS 520833               /* Maximum size per color component for 2K @ 48fps */
  978.  
  979. // save the j2k codestream
  980. bool wxJPEG2000Handler::SaveFile( wxImage *wimage, wxOutputStream& stream, bool verbose )
  981. {
  982.         opj_cparameters_t parameters;   /* compression parameters */
  983.         opj_event_mgr_t event_mgr;              /* event manager */
  984.         opj_image_t *oimage = NULL;
  985.         opj_image_cmptparm_t *cmptparm;
  986.         opj_cio_t *cio = NULL;
  987.         opj_codestream_info_t cstr_info;
  988.         int codestream_length;
  989.         bool bSuccess;
  990.         int i;
  991.         char indexfilename[OPJ_PATH_LEN] = "";  /* index file name */
  992.  
  993.         /*
  994.         configure the event callbacks (not required)
  995.         setting of each callback is optionnal
  996.         */
  997.         memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
  998.         event_mgr.error_handler = jpeg2000_error_callback;
  999.         event_mgr.warning_handler = jpeg2000_warning_callback;
  1000.         event_mgr.info_handler = jpeg2000_info_callback;
  1001.  
  1002.         /* set encoding parameters to default values */
  1003.         opj_set_default_encoder_parameters(&parameters);
  1004.  
  1005.         /* load parameters */
  1006.         parameters.cp_cinema = OFF;
  1007.  
  1008.         /* subsampling */
  1009.         if (sscanf(m_subsampling.ToAscii(), "%d,%d", &(parameters.subsampling_dx), &(parameters.subsampling_dy)) != 2) {
  1010.                 wxLogError(wxT("Wrong sub-sampling encoder setting: dx,dy"));
  1011.                 return false;
  1012.         }
  1013.  
  1014.         /* compression rates */
  1015.         if ((m_rates != wxT("")) && (!m_enablequality)) {
  1016.                 const char *s1 = m_rates.ToAscii();
  1017.                 wxLogMessage(wxT("rates %s"), s1);
  1018.                 while (sscanf(s1, "%f", &(parameters.tcp_rates[parameters.tcp_numlayers])) == 1) {
  1019.                         parameters.tcp_numlayers++;
  1020.                         while (*s1 && *s1 != ',') {
  1021.                                 s1++;
  1022.                         }
  1023.                         if (!*s1)
  1024.                                 break;
  1025.                         s1++;
  1026.                 }
  1027.                 wxLogMessage(wxT("%d layers"), parameters.tcp_numlayers);
  1028.                 parameters.cp_disto_alloc = 1;
  1029.         }
  1030.  
  1031.         /* image quality, dB */
  1032.         if ((m_quality != wxT("")) && (m_enablequality)) {
  1033.                 const char *s2 = m_quality.ToAscii();
  1034.                 wxLogMessage(wxT("qualities %s"), s2);
  1035.                 while (sscanf(s2, "%f", &parameters.tcp_distoratio[parameters.tcp_numlayers]) == 1) {
  1036.                         parameters.tcp_numlayers++;
  1037.                         while (*s2 && *s2 != ',') {
  1038.                                 s2++;
  1039.                         }
  1040.                         if (!*s2)
  1041.                                 break;
  1042.                         s2++;
  1043.                 }
  1044.                 wxLogMessage(wxT("%d layers"), parameters.tcp_numlayers);
  1045.                 parameters.cp_fixed_quality = 1;
  1046.         }
  1047.  
  1048.         /* image origin */
  1049.         if (sscanf(m_origin.ToAscii(), "%d,%d", &parameters.image_offset_x0, &parameters.image_offset_y0) != 2) {
  1050.                 wxLogError(wxT("bad coordinate of the image origin: x0,y0"));
  1051.                 return false;
  1052.         }
  1053.                                
  1054.         /* Create comment for codestream */
  1055.         if(m_enablecomm) {
  1056.                 parameters.cp_comment = (char *) malloc(strlen(m_comment.ToAscii()) + 1);
  1057.                 if(parameters.cp_comment) {
  1058.                         strcpy(parameters.cp_comment, m_comment.ToAscii());
  1059.                 }
  1060.         } else {
  1061.                 parameters.cp_comment = NULL;
  1062.         }
  1063.  
  1064.         /* indexing file */
  1065.         if (m_enableidx) {
  1066.                 strncpy(indexfilename, m_index.ToAscii(), OPJ_PATH_LEN);
  1067.                 wxLogMessage(wxT("index file is %s"), indexfilename);
  1068.         }
  1069.  
  1070.         /* if no rate entered, lossless by default */
  1071.         if (parameters.tcp_numlayers == 0) {
  1072.                 parameters.tcp_rates[0] = 0;    /* MOD antonin : losslessbug */
  1073.                 parameters.tcp_numlayers++;
  1074.                 parameters.cp_disto_alloc = 1;
  1075.         }
  1076.  
  1077.         /* irreversible transform */
  1078.         parameters.irreversible = (m_irreversible == true) ? 1 : 0;
  1079.  
  1080.         /* resolutions */
  1081.         parameters.numresolution = m_resolutions;
  1082.  
  1083.         /* codeblocks size */
  1084.         if (m_cbsize != wxT("")) {
  1085.                 int cblockw_init = 0, cblockh_init = 0;
  1086.                 sscanf(m_cbsize.ToAscii(), "%d,%d", &cblockw_init, &cblockh_init);
  1087.                 if (cblockw_init * cblockh_init > 4096 || cblockw_init > 1024 || cblockw_init < 4 || cblockh_init > 1024 || cblockh_init < 4) {
  1088.                         wxLogError(wxT("!! Size of code_block error !! Restrictions:\n  width*height<=4096\n  4<=width,height<= 1024"));
  1089.                         return false;
  1090.                 }
  1091.                 parameters.cblockw_init = cblockw_init;
  1092.                 parameters.cblockh_init = cblockh_init;
  1093.         }
  1094.  
  1095.         /* precincts size */
  1096.         if (m_prsize != wxT("")) {
  1097.                 char sep;
  1098.                 int res_spec = 0;
  1099.                 char *s = (char *) m_prsize.c_str();
  1100.                 do {
  1101.                         sep = 0;
  1102.                         sscanf(s, "[%d,%d]%c", &parameters.prcw_init[res_spec], &parameters.prch_init[res_spec], &sep);
  1103.                         parameters.csty |= 0x01;
  1104.                         res_spec++;
  1105.                         s = strpbrk(s, "]") + 2;
  1106.                 } while (sep == ',');
  1107.                 parameters.res_spec = res_spec;
  1108.         }
  1109.  
  1110.         /* tiles */
  1111.         if (m_tsize != wxT("")) {
  1112.                 sscanf(m_tsize.ToAscii(), "%d,%d", &parameters.cp_tdx, &parameters.cp_tdy);
  1113.                 parameters.tile_size_on = true;
  1114.         }
  1115.  
  1116.         /* tile origin */
  1117.         if (sscanf(m_torigin.ToAscii(), "%d,%d", &parameters.cp_tx0, &parameters.cp_ty0) != 2) {
  1118.                 wxLogError(wxT("tile offset setting error: X0,Y0"));
  1119.                 return false;
  1120.         }
  1121.  
  1122.         /* use SOP */
  1123.         if (m_enablesop)
  1124.                 parameters.csty |= 0x02;
  1125.  
  1126.         /* use EPH */
  1127.         if (m_enableeph)
  1128.                 parameters.csty |= 0x04;
  1129.  
  1130.         /* multiple component transform */
  1131.         if (m_multicomp)
  1132.                 parameters.tcp_mct = 1;
  1133.         else
  1134.                 parameters.tcp_mct = 0;
  1135.  
  1136.         /* mode switch */
  1137.         parameters.mode = (m_enablebypass ? 1 : 0) + (m_enablereset ? 2 : 0)
  1138.                 + (m_enablerestart ? 4 : 0) + (m_enablevsc ? 8 : 0)
  1139.                 + (m_enableerterm ? 16 : 0) + (m_enablesegmark ? 32 : 0);
  1140.  
  1141.         /* progression order */
  1142.         switch (m_progression) {
  1143.  
  1144.                 /* LRCP */
  1145.         case 0:
  1146.                 parameters.prog_order = LRCP;
  1147.                 break;
  1148.  
  1149.                 /* RLCP */
  1150.         case 1:
  1151.                 parameters.prog_order = RLCP;
  1152.                 break;
  1153.  
  1154.                 /* RPCL */
  1155.         case 2:
  1156.                 parameters.prog_order = RPCL;
  1157.                 break;
  1158.  
  1159.                 /* PCRL */
  1160.         case 3:
  1161.                 parameters.prog_order = PCRL;
  1162.                 break;
  1163.  
  1164.                 /* CPRL */
  1165.         case 4:
  1166.                 parameters.prog_order = CPRL;
  1167.                 break;
  1168.  
  1169.                 /* DCI2K24 */
  1170.         case 5:
  1171.                 parameters.cp_cinema = CINEMA2K_24;
  1172.                 parameters.cp_rsiz = CINEMA2K;
  1173.                 break;
  1174.  
  1175.                 /* DCI2K48 */
  1176.         case 6:
  1177.                 parameters.cp_cinema = CINEMA2K_48;
  1178.                 parameters.cp_rsiz = CINEMA2K;
  1179.                 break;
  1180.  
  1181.                 /* DCI4K */
  1182.         case 7:
  1183.                 parameters.cp_cinema = CINEMA4K_24;
  1184.                 parameters.cp_rsiz = CINEMA4K;
  1185.                 break;
  1186.  
  1187.         default:
  1188.                 break;
  1189.         }
  1190.  
  1191.         /* check cinema */
  1192.         if (parameters.cp_cinema) {
  1193.  
  1194.                 /* set up */
  1195.                 parameters.tile_size_on = false;
  1196.                 parameters.cp_tdx=1;
  1197.                 parameters.cp_tdy=1;
  1198.                
  1199.                 /*Tile part*/
  1200.                 parameters.tp_flag = 'C';
  1201.                 parameters.tp_on = 1;
  1202.  
  1203.                 /*Tile and Image shall be at (0,0)*/
  1204.                 parameters.cp_tx0 = 0;
  1205.                 parameters.cp_ty0 = 0;
  1206.                 parameters.image_offset_x0 = 0;
  1207.                 parameters.image_offset_y0 = 0;
  1208.  
  1209.                 /*Codeblock size= 32*32*/
  1210.                 parameters.cblockw_init = 32;  
  1211.                 parameters.cblockh_init = 32;
  1212.                 parameters.csty |= 0x01;
  1213.  
  1214.                 /*The progression order shall be CPRL*/
  1215.                 parameters.prog_order = CPRL;
  1216.  
  1217.                 /* No ROI */
  1218.                 parameters.roi_compno = -1;
  1219.  
  1220.                 parameters.subsampling_dx = 1;
  1221.                 parameters.subsampling_dy = 1;
  1222.  
  1223.                 /* 9-7 transform */
  1224.                 parameters.irreversible = 1;
  1225.  
  1226.         }                              
  1227.  
  1228.         /* convert wx image into opj image */
  1229.         cmptparm = (opj_image_cmptparm_t*) malloc(3 * sizeof(opj_image_cmptparm_t));
  1230.  
  1231.         /* initialize opj image components */  
  1232.         memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t));
  1233.         for(i = 0; i < 3; i++) {               
  1234.                 cmptparm[i].prec = 8;
  1235.                 cmptparm[i].bpp = 8;
  1236.                 cmptparm[i].sgnd = false;
  1237.                 cmptparm[i].dx = parameters.subsampling_dx;
  1238.                 cmptparm[i].dy = parameters.subsampling_dy;
  1239.                 cmptparm[i].w = wimage->GetWidth();
  1240.                 cmptparm[i].h = wimage->GetHeight();
  1241.         }
  1242.  
  1243.         /* create the image */
  1244.         oimage = opj_image_create(3, &cmptparm[0], CLRSPC_SRGB);
  1245.         if(!oimage) {
  1246.                 if (cmptparm)
  1247.                         free(cmptparm);
  1248.                 return false;
  1249.         }
  1250.  
  1251.         /* set image offset and reference grid */
  1252.         oimage->x0 = parameters.image_offset_x0;
  1253.         oimage->y0 = parameters.image_offset_y0;
  1254.         oimage->x1 = parameters.image_offset_x0 + (wimage->GetWidth() - 1) * 1 + 1;
  1255.         oimage->y1 = parameters.image_offset_y0 + (wimage->GetHeight() - 1) * 1 + 1;
  1256.  
  1257.         /* load image data */
  1258.         unsigned char *value = wimage->GetData();
  1259.         int area = wimage->GetWidth() * wimage->GetHeight();
  1260.         for (i = 0; i < area; i++) {
  1261.                         oimage->comps[0].data[i] = *(value++);
  1262.                         oimage->comps[1].data[i] = *(value++);
  1263.                         oimage->comps[2].data[i] = *(value++);
  1264.         }
  1265.  
  1266.         /* check cinema again */
  1267.         if (parameters.cp_cinema) {
  1268.                 int i;
  1269.                 float temp_rate;
  1270.                 opj_poc_t *POC = NULL;
  1271.  
  1272.                 switch (parameters.cp_cinema) {
  1273.  
  1274.                 case CINEMA2K_24:
  1275.                 case CINEMA2K_48:
  1276.                         if (parameters.numresolution > 6) {
  1277.                                 parameters.numresolution = 6;
  1278.                         }
  1279.                         if (!((oimage->comps[0].w == 2048) | (oimage->comps[0].h == 1080))) {
  1280.                                 wxLogWarning(wxT("Image coordinates %d x %d is not 2K compliant. JPEG Digital Cinema Profile-3 "
  1281.                                         "(2K profile) compliance requires that at least one of coordinates match 2048 x 1080"),
  1282.                                         oimage->comps[0].w, oimage->comps[0].h);
  1283.                                 parameters.cp_rsiz = STD_RSIZ;
  1284.                         }
  1285.                 break;
  1286.                
  1287.                 case CINEMA4K_24:
  1288.                         if (parameters.numresolution < 1) {
  1289.                                         parameters.numresolution = 1;
  1290.                         } else if (parameters.numresolution > 7) {
  1291.                                         parameters.numresolution = 7;
  1292.                         }
  1293.                         if (!((oimage->comps[0].w == 4096) | (oimage->comps[0].h == 2160))) {
  1294.                                 wxLogWarning(wxT("Image coordinates %d x %d is not 4K compliant. JPEG Digital Cinema Profile-4"
  1295.                                         "(4K profile) compliance requires that at least one of coordinates match 4096 x 2160"),
  1296.                                         oimage->comps[0].w, oimage->comps[0].h);
  1297.                                 parameters.cp_rsiz = STD_RSIZ;
  1298.                         }
  1299.                         parameters.POC[0].tile  = 1;
  1300.                         parameters.POC[0].resno0  = 0;
  1301.                         parameters.POC[0].compno0 = 0;
  1302.                         parameters.POC[0].layno1  = 1;
  1303.                         parameters.POC[0].resno1  = parameters.numresolution - 1;
  1304.                         parameters.POC[0].compno1 = 3;
  1305.                         parameters.POC[0].prg1 = CPRL;
  1306.                         parameters.POC[1].tile  = 1;
  1307.                         parameters.POC[1].resno0  = parameters.numresolution - 1;
  1308.                         parameters.POC[1].compno0 = 0;
  1309.                         parameters.POC[1].layno1  = 1;
  1310.                         parameters.POC[1].resno1  = parameters.numresolution;
  1311.                         parameters.POC[1].compno1 = 3;
  1312.                         parameters.POC[1].prg1 = CPRL;
  1313.                         parameters.numpocs = 2;
  1314.                         break;
  1315.                 }
  1316.  
  1317.                 switch (parameters.cp_cinema) {
  1318.                 case CINEMA2K_24:
  1319.                 case CINEMA4K_24:
  1320.                         for (i = 0 ; i < parameters.tcp_numlayers; i++) {
  1321.                                 temp_rate = 0;
  1322.                                 if (parameters.tcp_rates[i] == 0) {
  1323.                                         parameters.tcp_rates[0] = ((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
  1324.                                         (CINEMA_24_CS * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
  1325.                                 }else{
  1326.                                         temp_rate = ((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
  1327.                                                 (parameters.tcp_rates[i] * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
  1328.                                         if (temp_rate > CINEMA_24_CS ) {
  1329.                                                 parameters.tcp_rates[i]= ((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
  1330.                                                 (CINEMA_24_CS * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
  1331.                                         } else {
  1332.                                                 /* do nothing */
  1333.                                         }
  1334.                                 }
  1335.                         }
  1336.                         parameters.max_comp_size = COMP_24_CS;
  1337.                         break;
  1338.                        
  1339.                 case CINEMA2K_48:
  1340.                         for (i = 0; i < parameters.tcp_numlayers; i++) {
  1341.                                 temp_rate = 0 ;
  1342.                                 if (parameters.tcp_rates[i] == 0) {
  1343.                                         parameters.tcp_rates[0] = ((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
  1344.                                         (CINEMA_48_CS * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
  1345.                                 }else{
  1346.                                         temp_rate =((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
  1347.                                                 (parameters.tcp_rates[i] * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
  1348.                                         if (temp_rate > CINEMA_48_CS ){
  1349.                                                 parameters.tcp_rates[0]= ((float) (oimage->numcomps * oimage->comps[0].w * oimage->comps[0].h * oimage->comps[0].prec)) /
  1350.                                                 (CINEMA_48_CS * 8 * oimage->comps[0].dx * oimage->comps[0].dy);
  1351.                                         }else{
  1352.                                                 /* do nothing */
  1353.                                         }
  1354.                                 }
  1355.                         }
  1356.                         parameters.max_comp_size = COMP_48_CS;
  1357.                         break;
  1358.                 }
  1359.  
  1360.                 parameters.cp_disto_alloc = 1;
  1361.         }
  1362.        
  1363.         /* get a J2K compressor handle */
  1364.         opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
  1365.  
  1366.         /* catch events using our callbacks and give a local context */
  1367.         opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
  1368.  
  1369.         /* setup the encoder parameters using the current image and user parameters */
  1370.         opj_setup_encoder(cinfo, &parameters, oimage);
  1371.  
  1372.         /* open a byte stream for writing */
  1373.         /* allocate memory for all tiles */
  1374.         cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
  1375.  
  1376.         /* encode the image */
  1377.         bSuccess = opj_encode_with_info(cinfo, cio, oimage, &cstr_info);
  1378.         if (!bSuccess) {
  1379.  
  1380.                 opj_cio_close(cio);
  1381.                 opj_destroy_compress(cinfo);
  1382.                 opj_image_destroy(oimage);
  1383.                 if (cmptparm)
  1384.                         free(cmptparm);
  1385.                 if(parameters.cp_comment)
  1386.                         free(parameters.cp_comment);
  1387.                 if(parameters.cp_matrice)
  1388.                         free(parameters.cp_matrice);
  1389.  
  1390. #ifndef __WXGTK__
  1391.     wxMutexGuiEnter();
  1392. #endif /* __WXGTK__ */
  1393.  
  1394.                 wxLogError(wxT("failed to encode image"));
  1395.  
  1396. #ifndef __WXGTK__
  1397.     wxMutexGuiLeave();
  1398. #endif /* __WXGTK__ */
  1399.  
  1400.                 return false;
  1401.         }
  1402.         codestream_length = cio_tell(cio);
  1403.         wxLogMessage(wxT("Codestream: %d bytes"), codestream_length);
  1404.  
  1405.         /* write the buffer to stream */
  1406.         stream.Write(cio->buffer, codestream_length);
  1407.  
  1408.         /* close and free the byte stream */
  1409.         opj_cio_close(cio);
  1410.  
  1411.         /* Write the index to disk */
  1412.         if (*indexfilename) {
  1413.                 if (write_index_file(&cstr_info, indexfilename)) {
  1414.                         wxLogError(wxT("Failed to output index file"));
  1415.                 }
  1416.         }
  1417.  
  1418.         /* free remaining compression structures */
  1419.         opj_destroy_compress(cinfo);
  1420.  
  1421.         /* free image data */
  1422.         opj_image_destroy(oimage);
  1423.  
  1424.         if (cmptparm)
  1425.                 free(cmptparm);
  1426.         if(parameters.cp_comment)
  1427.                 free(parameters.cp_comment);
  1428.         if(parameters.cp_matrice)
  1429.                 free(parameters.cp_matrice);
  1430.  
  1431. #ifndef __WXGTK__
  1432.     wxMutexGuiEnter();
  1433. #endif /* __WXGTK__ */
  1434.  
  1435.     wxLogMessage(wxT("J2K: Image encoded!"));
  1436.  
  1437. #ifndef __WXGTK__
  1438.     wxMutexGuiLeave();
  1439. #endif /* __WXGTK__ */
  1440.  
  1441.     return true;
  1442. }
  1443.  
  1444. #ifdef __VISUALC__
  1445.     #pragma warning(default:4611)
  1446. #endif /* VC++ */
  1447.  
  1448. // recognize the JPEG 2000 family starting box or the 0xFF4F JPEG 2000 SOC marker
  1449. bool wxJPEG2000Handler::DoCanRead(wxInputStream& stream)
  1450. {
  1451.     unsigned char hdr[24];
  1452.         int jpfamform;
  1453.  
  1454.     if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
  1455.         return false;
  1456.  
  1457.         jpfamform = jpeg2000familytype(hdr, WXSIZEOF(hdr));
  1458.  
  1459.         return ((jpfamform == JP2_CFMT) || (jpfamform == MJ2_CFMT) || (jpfamform == J2K_CFMT));
  1460. }
  1461.  
  1462. #endif   // wxUSE_STREAMS
  1463.  
  1464. #endif   // wxUSE_LIBOPENJPEG
  1465.