Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright (c) 2001-2003, David Janssens
  3.  * Copyright (c) 2002-2003, Yannick Verschueren
  4.  * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe
  5.  * Copyright (c) 2005, Hervé Drolon, FreeImage Team
  6.  * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
  7.  * Copyright (c) 2006, Mónica Díez García, Image Processing Laboratory, University of Valladolid, Spain
  8.  * All rights reserved.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
  20.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  23.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29.  * POSSIBILITY OF SUCH DAMAGE.
  30.  */
  31. #ifndef __J3D_H
  32. #define __J3D_H
  33. /**
  34. @file j3d.h
  35. @brief The JPEG-2000 Codestream Reader/Writer (J3D)
  36.  
  37. The functions in J3D.C have for goal to read/write the several parts of the codestream: markers and data.
  38. */
  39.  
  40. /** @defgroup J3D J3D - JPEG-2000 codestream reader/writer */
  41. /*@{*/
  42.  
  43. #define J3D_CP_CSTY_PRT 0x01
  44. #define J3D_CP_CSTY_SOP 0x02
  45. #define J3D_CP_CSTY_EPH 0x04
  46. #define J3D_CCP_CSTY_PRT 0x01
  47. /** Table A-8 */
  48. #define J3D_CCP_CBLKSTY_LAZY 0x01        /* Selective arithmetic coding bypass */
  49. #define J3D_CCP_CBLKSTY_RESET 0x02   /* Reset context probabilities on coding pass boundaries */
  50. #define J3D_CCP_CBLKSTY_TERMALL 0x04 /* Termination on each coding pass */
  51. #define J3D_CCP_CBLKSTY_VSC 0x08         /* Vertically causal context, add also hook for switching off and on 3D context models */     
  52. #define J3D_CCP_CBLKSTY_PTERM 0x10       /* Predictable termination */
  53. #define J3D_CCP_CBLKSTY_SEGSYM 0x20      /* Segmentation symbols are used */
  54. #define J3D_CCP_CBLKSTY_3DCTXT 0x40  /* 3D context models (3D-EBCOT) vs 2D context models */
  55.  
  56. #define J3D_CCP_QNTSTY_NOQNT 0  /* Quantization style : no quantization */
  57. #define J3D_CCP_QNTSTY_SIQNT 1  /* Quantization style : scalar derived (values signalled only in LLL subband) */
  58. #define J3D_CCP_QNTSTY_SEQNT 2  /* Quantization style : scalar expounded (values signalled for each subband) */
  59.  
  60. /* ----------------------------------------------------------------------- */
  61.  
  62. #define J3D_MS_SOC 0xff4f       /**< SOC marker value */
  63. #define J3D_MS_SOT 0xff90       /**< SOT marker value */
  64. #define J3D_MS_SOD 0xff93       /**< SOD marker value */
  65. #define J3D_MS_EOC 0xffd9       /**< EOC marker value */
  66. #define J3D_MS_CAP 0xff50       /**< CAP marker value */
  67. #define J3D_MS_SIZ 0xff51       /**< SIZ marker value */
  68. #define J3D_MS_ZSI 0xff54       /**< ZSI marker value */
  69. #define J3D_MS_COD 0xff52       /**< COD marker value */
  70. #define J3D_MS_COC 0xff53       /**< COC marker value */
  71. #define J3D_MS_RGN 0xff5e       /**< RGN marker value */
  72. #define J3D_MS_QCD 0xff5c       /**< QCD marker value */
  73. #define J3D_MS_QCC 0xff5d       /**< QCC marker value */
  74. #define J3D_MS_POC 0xff5f       /**< POC marker value */
  75. #define J3D_MS_TLM 0xff55       /**< TLM marker value */
  76. #define J3D_MS_PLM 0xff57       /**< PLM marker value */
  77. #define J3D_MS_PLT 0xff58       /**< PLT marker value */
  78. #define J3D_MS_PPM 0xff60       /**< PPM marker value */
  79. #define J3D_MS_PPT 0xff61       /**< PPT marker value */
  80. #define J3D_MS_SOP 0xff91       /**< SOP marker value */
  81. #define J3D_MS_EPH 0xff92       /**< EPH marker value */
  82. #define J3D_MS_CRG 0xff63       /**< CRG marker value */
  83. #define J3D_MS_COM 0xff64       /**< COM marker value */
  84. //15444-2
  85. #define J3D_MS_DCO 0xff70       /**< DCO marker value */
  86. #define J3D_MS_VMS 0xff71   /**< VMS marker value */
  87. #define J3D_MS_DFS 0xff72       /**< DFS marker value */
  88. #define J3D_MS_ADS 0xff73       /**< ADS marker value */
  89. #define J3D_MS_ATK 0xff79       /**< ATK marker value */
  90. #define J3D_MS_CBD 0xff78       /**< CBD marker value */
  91. #define J3D_MS_MCT 0xff74       /**< MCT marker value */
  92. #define J3D_MS_MCC 0xff75       /**< MCC marker value */
  93. #define J3D_MS_MCO 0xff77       /**< MCO marker value */
  94. #define J3D_MS_NLT 0xff76       /**< NLT marker value */
  95. #define J3D_MS_QPD 0xff5a       /**< QPD marker value */
  96. #define J3D_MS_QPC 0xff5b       /**< QPC marker value */
  97.  
  98. /* ----------------------------------------------------------------------- */
  99. /* Capability RSIZ parameter, extended */
  100. #define J3D_RSIZ_BASIC 0x0000
  101.  
  102. #define J3D_RSIZ_DCO   0x8001 /* Required */
  103. #define J3D_RSIZ_VSQNT 0x8002
  104. #define J3D_RSIZ_TCQNT 0x8004
  105. #define J3D_RSIZ_VMASK 0x8008
  106. #define J3D_RSIZ_SSOVL 0x8010
  107. #define J3D_RSIZ_ADECS 0x8020
  108. #define J3D_RSIZ_ATK   0x8040 /*Required*/
  109. #define J3D_RSIZ_SSYMK 0x8080
  110. #define J3D_RSIZ_MCT   0x8100 /*Not compatible with DCO*/
  111. #define J3D_RSIZ_NLT   0x8200 /*Required*/
  112. #define J3D_RSIZ_ASHAP 0x8400
  113. #define J3D_RSIZ_PRQNT 0x8800
  114.  
  115. #define J3D_CAP_10              0x00400000
  116. /* Arbitrary transformation kernel, 15444-2 */
  117. #define J3D_ATK_IRR 0
  118. #define J3D_ATK_REV 1
  119. #define J3D_ATK_ARB 0
  120. #define J3D_ATK_WS 1
  121. #define J3D_ATK_CON 0
  122. /* ----------------------------------------------------------------------- */
  123.  
  124. /**
  125. Values that specify the status of the decoding process when decoding the main header.
  126. These values may be combined with a | operator.
  127. */
  128. typedef enum J3D_STATUS {
  129.         /**< a SOC marker is expected */
  130.         J3D_STATE_MHSOC  = 0x0001,
  131.         /**< a SIZ marker is expected */
  132.         J3D_STATE_MHSIZ  = 0x0002,
  133.         /**< the decoding process is in the main header */
  134.         J3D_STATE_MH     = 0x0004,
  135.         /**< the decoding process is in a tile part header and expects a SOT marker */
  136.         J3D_STATE_TPHSOT = 0x0008,
  137.         /**< the decoding process is in a tile part header */
  138.         J3D_STATE_TPH    = 0x0010,
  139.         /**< the EOC marker has just been read */
  140.         J3D_STATE_MT     = 0x0020,
  141.         /**< the decoding process must not expect a EOC marker because the codestream is truncated */
  142.         J3D_STATE_NEOC   = 0x0040  
  143. } J3D_STATUS;
  144.  
  145.  
  146.  
  147. /**
  148. Arbitrary transformation kernel
  149. */
  150. typedef struct opj_atk {
  151. /** index of wavelet kernel */
  152.         int index;
  153. /** Numerical type of scaling factor and lifting step parameters */
  154.         int coeff_typ;         
  155. /** Wavelet filter category */
  156.         int filt_cat;          
  157. /** Wavelet transformation type (REV/IRR) */
  158.         int wt_typ;                    
  159. /** Initial odd/even subsequence */
  160.         int minit;                     
  161. /** Boundary extension method (constant CON / whole-sample symmetric WS) */
  162.         int exten;                     
  163. /** Scaling factor. Only for wt_typ=IRR */
  164.         double Katk;                   
  165. /** Number of lifting steps */
  166.         int Natk;                      
  167. /** Offset for lifting step s. Only for filt_cat=ARB */
  168.         int Oatk[256];         
  169. /** Base 2 scaling exponent for lifting step s. Only for wt_typ=REV */
  170.         int Eatk[256];         
  171. /** Additive residue for lifting step s. Only for wt_typ=REV */
  172.         int Batk[256];         
  173. /** Number of lifting coefficients signaled for lifting step s  */
  174.         int LCatk[256];
  175. /** Lifting coefficient k for lifting step s */
  176.         double Aatk[256][256]; 
  177. } opj_atk_t;
  178.  
  179.  
  180. /**
  181. Quantization stepsize
  182. */
  183. typedef struct opj_stepsize {
  184. /** exponent */
  185.         int expn;      
  186. /** mantissa */
  187.         int mant;      
  188. } opj_stepsize_t;
  189.  
  190. /**
  191. Tile-component coding parameters
  192. */
  193. typedef struct opj_tccp {
  194.         /** coding style */
  195.         int csty;                                                      
  196.         /** number of resolutions of x, y and z-axis */
  197.         int numresolution[3];  
  198.         /** code-blocks width height & depth*/
  199.         int cblk[3];                   
  200.         /** code-block coding style */
  201.         int cblksty;                   
  202.         /** 0: no ATK (only 9-7 or 5-3) 1: ATK defined WT*/
  203.         int atk_wt[3];                         
  204.         /** Arbitrary transformation kernel (15444-2)*/
  205.         opj_atk_t *atk;                
  206.         /** DWT identifier for x, y and z-axis (0:WT9-7 1:WT5-3 >1:WT-atk->index) */
  207.         int dwtid[3];
  208.         /** reversible/irreversible wavelet transfomation (0:irrev 1:reversible)*/     
  209.         int reversible;                
  210.         /** quantisation style */
  211.         int qntsty;                            
  212.         /** stepsizes used for quantization */
  213.         opj_stepsize_t stepsizes[J3D_MAXBANDS];
  214.         /** number of guard bits. Table A28 de 15444-1*/
  215.         int numgbits;                  
  216.         /** Region Of Interest shift */
  217.         int roishift;                  
  218.         /** precinct width heigth & depth*/
  219.         int prctsiz[3][J3D_MAXRLVLS];          
  220. } opj_tccp_t;
  221.  
  222. /**
  223. Tile coding parameters : coding/decoding parameters common to all tiles
  224. (information like COD, COC in main header)
  225. */
  226. typedef struct opj_tcp {
  227. /** 1 : first part-tile of a tile */
  228.         int first;                             
  229.         /** coding style */
  230.         int csty;                              
  231.         /** progression order */
  232.         OPJ_PROG_ORDER prg;            
  233.         /** number of layers */
  234.         int numlayers;                 
  235.         /** multi-component transform identifier */
  236.         int mct;                               
  237.         /** rates of layers */
  238.         float rates[100];                      
  239.         /** number of progression order changes */
  240.         int numpocs;                   
  241.         /** indicates if a POC marker has been used O:NO, 1:YES */
  242.         int POC;                               
  243.         /** progression order changes */
  244.         opj_poc_t pocs[J3D_MAXRLVLS - 1];
  245.         /** add fixed_quality */
  246.         float distoratio[100];
  247.         /** tile-component coding parameters */
  248.         opj_tccp_t *tccps;             
  249. /** packet header store there for futur use in t2_decode_packet */
  250.         unsigned char *ppt_data;               
  251.         /** pointer remaining on the first byte of the first header if ppt is used */
  252.         unsigned char *ppt_data_first; 
  253.         /** If ppt == 1 --> there was a PPT marker for the present tile */
  254.         int ppt;               
  255.         /** used in case of multiple marker PPT (number of info already stored) */
  256.         int ppt_store; 
  257.         int ppt_len;   
  258. } opj_tcp_t;
  259.  
  260. /**
  261. Coding parameters
  262. */
  263. typedef struct opj_cp {
  264. /** transform format 0: 2DWT, 1: 2D1P, 2: 3DWT, 3: 3RLS */
  265.         OPJ_TRANSFORM transform_format;        
  266.         /** entropy coding format 0: 2EB, 1: 3EB, 2: 2GR, 3: 3GR, 4: GRI*/
  267.         OPJ_ENTROPY_CODING encoding_format;    
  268.         /** allocation by rate/distortion */
  269.         int disto_alloc;       
  270.         /** allocation by fixed layer */
  271.         int fixed_alloc;       
  272.         /** add fixed_quality */
  273.         int fixed_quality;     
  274.         /** Rsiz: capabilities */
  275.         int rsiz;                      
  276.         /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, volume is decoded to the full resolution */
  277.         int reduce[3];         
  278.         /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */
  279.         int layer;                     
  280.         /** 0 = no index || 1 = index */
  281.         int index_on;          
  282.         /** Big-Endian/Little-endian order */
  283.         int bigendian;
  284.         /** XTOsiz */
  285.         int tx0;       
  286.         /** YTOsiz */
  287.         int ty0;               
  288.         /** ZTOsiz */
  289.         int tz0;       
  290.         /** XTsiz */
  291.         int tdx;       
  292.         /** YTsiz */
  293.         int tdy;       
  294.         /** ZTsiz */
  295.         int tdz;       
  296.         /** comment for coding */
  297.         char *comment;         
  298.         /** number of tiles in width, heigth and depth */
  299.         int tw;        
  300.         int th;
  301.         int tl;
  302.         /** ID number of the tiles present in the codestream */
  303.         int *tileno;   
  304.         /** size of the vector tileno */
  305.         int tileno_size;
  306.         /** tile coding parameters */
  307.         opj_tcp_t *tcps;
  308.         /** fixed layer */
  309.         int *matrice;          
  310.  
  311.         /** packet header store there for futur use in t2_decode_packet */
  312.         unsigned char *ppm_data;               
  313.         /** pointer remaining on the first byte of the first header if ppm is used */
  314.         unsigned char *ppm_data_first; 
  315.         /** if ppm == 1 --> there was a PPM marker for the present tile */
  316.         int ppm;                       
  317.         /** use in case of multiple marker PPM (number of info already store) */
  318.         int ppm_store;         
  319.         /** use in case of multiple marker PPM (case on non-finished previous info) */
  320.         int ppm_previous;      
  321.         int ppm_len;           
  322. } opj_cp_t;
  323.  
  324. /**
  325. Information concerning a packet inside tile
  326. */
  327. typedef struct opj_packet_info {
  328.         /** start position */
  329.         int start_pos; 
  330.         /** end position */
  331.         int end_pos;   
  332.         /** distorsion introduced */
  333.         double disto;  
  334. } opj_packet_info_t;
  335.  
  336. /**
  337. Index structure : information regarding tiles inside volume
  338. */
  339. typedef struct opj_tile_info {
  340.         /** value of thresh for each layer by tile cfr. Marcela   */
  341.         double *thresh;        
  342.         /** number of tile */
  343.         int num_tile;          
  344.         /** start position */
  345.         int start_pos;         
  346.         /** end position of the header */
  347.         int end_header;        
  348.         /** end position */
  349.         int end_pos;           
  350.         /** precinct number for each resolution level (width, heigth and depth) */
  351.         int prctno[3][J3D_MAXRLVLS];   
  352.         /** precinct size (in power of 2), in X for each resolution level */
  353.         int prctsiz[3][J3D_MAXRLVLS];  
  354.         /** information concerning packets inside tile */
  355.         opj_packet_info_t *packet;             
  356.        
  357.         /** add fixed_quality */
  358.         int nbpix;                     
  359.         /** add fixed_quality */
  360.         double distotile;      
  361. } opj_tile_info_t;
  362.  
  363. /**
  364. Index structure
  365. */
  366. typedef struct opj_volume_info {
  367.        
  368.         /** transform format 0: 2DWT, 1: 2D1P, 2: 3DWT, 3: 3RLS */
  369.         OPJ_TRANSFORM transform_format;        
  370.         /** output file format 0: 2EB, 1: 3EB, 2: 2GR, 3: 3GR, 4: GRI*/
  371.         OPJ_ENTROPY_CODING encoding_format;     /** 0 = no index || 1 = index */
  372.         int index_on;  
  373.         /** 0 = wt 9-7 || 1 = wt 5-3 || >=2 wt atk defined */
  374.         int dwtid[3];  
  375.         /** maximum distortion reduction on the whole volume (add for Marcela) */
  376.         double D_max;  
  377.         /** packet number */
  378.         int num;               
  379.         /** writing the packet in the index with t2_encode_packets */
  380.         int index_write;       
  381.         /** volume width, height and depth */
  382.         int volume_w;  
  383.         int volume_h;
  384.         int volume_l;
  385.         /** progression order */
  386.         OPJ_PROG_ORDER prog;   
  387.         /** tile size in x, y and z */
  388.         int tile_x;            
  389.         int tile_y;
  390.         int tile_z;
  391.         /** tile origin in x, y and z */
  392.         int tile_Ox;   
  393.         int tile_Oy;
  394.         int tile_Oz;
  395.         /** number of tiles in X, Y and Z */
  396.         int tw;                
  397.         int th;
  398.         int tl;
  399.         /** component numbers */
  400.         int comp;                              
  401.         /** number of layer */
  402.         int layer;                             
  403.         /** number of decomposition in X, Y and Z*/
  404.         int decomposition[3];  
  405.         /** DC offset (15444-2) */
  406.         int dcoffset;  
  407.         /** main header position */
  408.         int main_head_end;             
  409.         /** codestream's size */
  410.         int codestream_size;   
  411.         /** information regarding tiles inside volume */
  412.         opj_tile_info_t *tile; 
  413. } opj_volume_info_t;
  414.  
  415. /**
  416. JPEG-2000 codestream reader/writer
  417. */
  418. typedef struct opj_j3d {
  419.         /** codec context */
  420.         opj_common_ptr cinfo;  
  421.         /** locate in which part of the codestream the decoder is (main header, tile header, end) */
  422.         int state;                             
  423.         /** number of the tile curently concern by coding/decoding */
  424.         int curtileno;                 
  425.         /** locate the position of the end of the tile in the codestream, used to detect a truncated codestream (in j3d_read_sod)       */
  426.         unsigned char *eot;    
  427.         /**     locate the start position of the SOT marker of the current coded tile:  */
  428.         int sot_start;         
  429.         /*  after encoding the tile, a jump (in j3d_write_sod) is done to the SOT marker to store the value of its length. */
  430.         int sod_start;         
  431.         /**     as the J3D-file is written in several parts during encoding, it enables to make the right correction in position return by cio_tell     */
  432.         int pos_correction;    
  433.         /** array used to store the data of each tile */
  434.         unsigned char **tile_data;     
  435.         /** array used to store the length of each tile */
  436.         int *tile_len;                         
  437.  
  438.         /** decompression only : store decoding parameters common to all tiles */
  439.         opj_tcp_t *default_tcp;        
  440.         /** pointer to the encoded / decoded volume */
  441.         opj_volume_t *volume;          
  442.         /** pointer to the coding parameters */
  443.         opj_cp_t *cp;                          
  444.         /** helper used to write the index file */
  445.         opj_volume_info_t *volume_info;
  446.         /** pointer to the byte i/o stream */
  447.     opj_cio_t *cio;                                            
  448. } opj_j3d_t;
  449.  
  450. /** @name Funciones generales */
  451. /*@{*/
  452. /* ----------------------------------------------------------------------- */
  453. /**
  454. Creates a J3D decompression structure
  455. @param cinfo Codec context info
  456. @return Returns a handle to a J3D decompressor if successful, returns NULL otherwise
  457. */
  458. opj_j3d_t* j3d_create_decompress(opj_common_ptr cinfo);
  459. /**
  460. Destroy a J3D decompressor handle
  461. @param j3d J3D decompressor handle to destroy
  462. */
  463. void j3d_destroy_decompress(opj_j3d_t *j3d);
  464. /**
  465. Setup the decoder decoding parameters using user parameters.
  466. Decoding parameters are returned in j3d->cp.
  467. @param j3d J3D decompressor handle
  468. @param parameters decompression parameters
  469. */
  470. void j3d_setup_decoder(opj_j3d_t *j3d, opj_dparameters_t *parameters);
  471. /**
  472. Decode an volume from a JPEG-2000 codestream
  473. @param j3d J3D decompressor handle
  474. @param cio Input buffer stream
  475. @return Returns a decoded volume if successful, returns NULL otherwise
  476. */
  477. opj_volume_t* j3d_decode(opj_j3d_t *j3d, opj_cio_t *cio);
  478. /**
  479. Decode an volume form a JPT-stream (JPEG 2000, JPIP)
  480. @param j3d J3D decompressor handle
  481. @param cio Input buffer stream
  482. @return Returns a decoded volume if successful, returns NULL otherwise
  483. */
  484. opj_volume_t* j3d_decode_jpt_stream(opj_j3d_t *j3d, opj_cio_t *cio);
  485. /**
  486. Creates a J3D compression structure
  487. @param cinfo Codec context info
  488. @return Returns a handle to a J3D compressor if successful, returns NULL otherwise
  489. */
  490. opj_j3d_t* j3d_create_compress(opj_common_ptr cinfo);
  491. /**
  492. Destroy a J3D compressor handle
  493. @param j3d J3D compressor handle to destroy
  494. */
  495. void j3d_destroy_compress(opj_j3d_t *j3d);
  496. /**
  497. Setup the encoder parameters using the current volume and using user parameters.
  498. Coding parameters are returned in j3d->cp.
  499. @param j3d J3D compressor handle
  500. @param parameters compression parameters
  501. @param volume input filled volume
  502. */
  503. void j3d_setup_encoder(opj_j3d_t *j3d, opj_cparameters_t *parameters, opj_volume_t *volume);
  504. /**
  505. Encode an volume into a JPEG-2000 codestream
  506. @param j3d J3D compressor handle
  507. @param cio Output buffer stream
  508. @param volume Volume to encode
  509. @param index Name of the index file if required, NULL otherwise
  510. @return Returns true if successful, returns false otherwise
  511. */
  512. bool j3d_encode(opj_j3d_t *j3d, opj_cio_t *cio, opj_volume_t *volume, char *index);
  513. /* ----------------------------------------------------------------------- */
  514. /*@}*/
  515.  
  516. /*@}*/
  517.  
  518. #endif /* __J3D_H */
  519.