1 /******************************************************************************
2  * $Id: nitfaridpcm.cpp 27745 2014-09-27 16:38:57Z goatbar $
3  *
4  * Project:  NITF Read/Write Library
5  * Purpose:  ARIDPCM reading code.
6  * Author:   Frank Warmerdam, warmerdam@pobox.com
7  *
8  **********************************************************************
9  * Copyright (c) 2007, Frank Warmerdam
10  * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  ****************************************************************************/
30 
31 #include "gdal.h"
32 #include "nitflib.h"
33 #include "cpl_conv.h"
34 
35 CPL_CVSID("$Id: nitfaridpcm.cpp 27745 2014-09-27 16:38:57Z goatbar $");
36 
37 static const int neighbourhood_size_75[4] = { 23, 47, 74, 173 };
38 static const int bits_per_level_by_busycode_75[4/*busy code*/][4/*level*/] = {
39     { 8, 5, 0, 0 }, // BC = 00
40     { 8, 5, 2, 0 }, // BC = 01
41     { 8, 6, 4, 0 }, // BC = 10
42     { 8, 7, 4, 2 }};// BC = 11
43 
44 #define CR075  1
45 
46 // Level for each index value.
47 static const int level_index_table[64] =
48 { 0,
49   1, 1, 1,
50   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
51   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
52   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
53   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
54 
55 // List of i,j to linear index macros mappings.
56 // Note that i is vertical and j is horizontal and progression is
57 // right to left, bottom to top.
58 
59 #define IND(i,j) (ij_index[i+j*8]-1)
60 
61 static const int ij_index[64] = {
62 
63      1, // 0, 0
64     18, // 1, 0
65      6, // 2, 0
66     30, // 3, 0
67      3, // 4, 0
68     42, // 5, 0
69     12, // 6, 0
70     54, // 7, 0
71 
72     17, // 0, 1
73     19, // 1, 1
74     29, // 2, 1
75     31, // 3, 1
76     41, // 4, 1
77     43, // 5, 1
78     53, // 6, 1
79     55, // 7, 1
80 
81      5, // 0, 2
82     21, // 1, 2
83      7, // 2, 2
84     33, // 3, 2
85     11, // 4, 2
86     45, // 5, 2
87     13, // 6, 2
88     57, // 7, 2
89 
90     20, // 0, 3
91     22, // 1, 3
92     32, // 2, 3
93     34, // 3, 3
94     44, // 4, 3
95     46, // 5, 3
96     56, // 6, 3
97     58, // 7, 3
98 
99      2, // 0, 4
100     24, // 1, 4
101      9, // 2, 4
102     36, // 3, 4
103      4, // 4, 4
104     48, // 5, 4
105     15, // 6, 4
106     60, // 7, 4
107 
108     23, // 0, 5
109     25, // 1, 5
110     35, // 2, 5
111     37, // 3, 5
112     47, // 4, 5
113     49, // 5, 5
114     59, // 6, 5
115     61, // 7, 5
116 
117      8, // 0, 6
118     27, // 1, 6
119     10, // 2, 6
120     39, // 3, 6
121     14, // 4, 6
122     51, // 5, 6
123     16, // 6, 6
124     63, // 7, 6
125 
126     26, // 0, 7
127     28, // 1, 7
128     38, // 2, 7
129     40, // 3, 7
130     50, // 4, 7
131     52, // 5, 7
132     62, // 6, 7
133     64};// 7, 7
134 
135 static const int delta_075_level_2_bc_0[32] =
136 {-71, -49, -38, -32, -27, -23, -20, -17, -14, -12, -10, -8, -6, -4, -3, -1,
137  1, 2, 4, 6, 8, 12, 14, 16, 19, 22, 26, 31, 37, 46, 72 };
138 static const int delta_075_level_2_bc_1[32] =
139 {-71, -49, -38, -32, -27, -23, -20, -17, -14, -12, -10, -8, -6, -4, -3, -1,
140  1, 2, 4, 6, 8, 12, 14, 16, 19, 22, 26, 31, 37, 46, 72 };
141 static const int delta_075_level_2_bc_2[64] =
142 { -109, -82, -68, -59, -52, -46, -41, -37, -33, -30, -27, -25, -22, -20,
143   -18, -16, -15, -13, -11, -10, -9, -8, -7, -6, -5,
144   -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,
145   13,14,15,16,17,18,19,20,21,24,26,28,31,35,38,
146   42,47,52,60,69,85,118};
147 static const int delta_075_level_2_bc_3[128] =
148 {-159,-134,-122,-113,-106,-100,-94,-88,-83,-79,-76,-72,-69,-66,-63,-61,
149  -58,-56,-54,-52,-50,-48,-47,-45,-43,-42,-40,-39,-37,-36,-35,-33,-32,-31,
150  -30,-29,-28,-27,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,
151  -13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,
152  12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
153  35,36,37,38,39,40,41,42,43,45,48,52,56,60,64,68,73,79,85,92,100,109,
154  118,130,144,159,177,196,217,236};
155 static const int *delta_075_level_2[4] =
156 { delta_075_level_2_bc_0, delta_075_level_2_bc_1,
157   delta_075_level_2_bc_2, delta_075_level_2_bc_3 };
158 
159 
160 static const int delta_075_level_3_bc_1[4] = { -24, -6, 6, 24 };
161 static const int delta_075_level_3_bc_2[16] =
162 {-68,-37,-23,-15, -9, -6, -3, -1, 1, 4, 7,10,16,24,37,70 };
163 static const int delta_075_level_3_bc_3[16] =
164 {-117,-72, -50, -36, -25, -17, -10, -5,-1, 3, 7,14,25,45,82,166};
165 static const int *delta_075_level_3[4] =
166 { NULL, delta_075_level_3_bc_1,
167   delta_075_level_3_bc_2, delta_075_level_3_bc_3 };
168 
169 static const int delta_075_level_4_bc_3[4] = {-47,-8,4,43};
170 static const int *delta_075_level_4[4] = { NULL, NULL, NULL, delta_075_level_4_bc_3 };
171 
172 static const int **delta_075_by_level_by_bc[4] =
173 { NULL, delta_075_level_2, delta_075_level_3, delta_075_level_4 };
174 
175 /************************************************************************/
176 /*                              get_bits()                              */
177 /************************************************************************/
178 
179 static int
get_bits(unsigned char * buffer,int first_bit,int num_bits)180 get_bits( unsigned char *buffer, int first_bit, int num_bits )
181 
182 {
183     int i;
184     int total =0;
185 
186     for( i = first_bit; i < first_bit+num_bits; i++ )
187     {
188         total = total * 2;
189         if( buffer[i>>3] & (0x80 >> (i&7)) )
190             total++;
191     }
192 
193     return total;
194 }
195 
196 /************************************************************************/
197 /*                             get_delta()                              */
198 /*                                                                      */
199 /*      Compute the delta value for a particular (i,j) location.        */
200 /************************************************************************/
201 static int
get_delta(unsigned char * srcdata,int nInputBytes,int busy_code,CPL_UNUSED int comrat,int block_offset,CPL_UNUSED int block_size,int i,int j,int * pbError)202 get_delta( unsigned char *srcdata,
203            int nInputBytes,
204            int busy_code,
205            CPL_UNUSED int comrat,
206            int block_offset,
207            CPL_UNUSED int block_size,
208            int i,
209            int j,
210            int *pbError )
211 
212 {
213     CPLAssert( comrat == CR075 );
214     int pixel_index = IND(i,j);
215     int level_index = level_index_table[pixel_index];
216     const int *bits_per_level = bits_per_level_by_busycode_75[busy_code];
217     int delta_bits = bits_per_level[level_index];
218     int delta_offset = 0;
219 
220     *pbError = FALSE;
221 
222     if( delta_bits == 0 )
223         return 0;
224 
225     if( level_index == 3 )
226         delta_offset = bits_per_level[0] + bits_per_level[1] * 3
227             + bits_per_level[2] * 12 + (pixel_index - 16) * bits_per_level[3];
228     else if( level_index == 2 )
229         delta_offset = bits_per_level[0] + bits_per_level[1] * 3
230             + (pixel_index - 4) * bits_per_level[2];
231     else if( level_index == 1 )
232         delta_offset = bits_per_level[0] + (pixel_index-1)*bits_per_level[1];
233 
234     if (nInputBytes * 8 < block_offset+delta_offset + delta_bits)
235     {
236         CPLError( CE_Failure, CPLE_AppDefined, "Input buffer too small");
237         *pbError = TRUE;
238         return 0;
239     }
240 
241     int delta_raw = get_bits( srcdata, block_offset+delta_offset, delta_bits );
242     int delta = delta_raw;
243 
244     /* Should not happen as delta_075_by_level_by_bc[level_index] == NULL if and
245        only if level_index == 0, which means that pixel_index == 0, which means
246        (i, j) = (0, 0). That cannot happen as we are never called with those
247        values
248     */
249     CPLAssert( delta_075_by_level_by_bc[level_index] != NULL );
250     const int *lookup_table = delta_075_by_level_by_bc[level_index][busy_code];
251 
252     CPLAssert( lookup_table != NULL );
253     delta = lookup_table[delta_raw];
254 
255     return delta;
256 }
257 
258 /************************************************************************/
259 /*                            decode_block()                            */
260 /*                                                                      */
261 /*      Decode one 8x8 block.  The 9x9 L buffer is pre-loaded with      */
262 /*      the left and top values from previous blocks.                   */
263 /************************************************************************/
264 static int
decode_block(unsigned char * srcdata,int nInputBytes,int busy_code,int comrat,int block_offset,int block_size,int left_side,int top_side,int L[9][9])265 decode_block( unsigned char *srcdata, int nInputBytes,
266               int busy_code, int comrat,
267               int block_offset, int block_size,
268               int left_side, int top_side, int L[9][9] )
269 
270 {
271     int i, j;
272     int bError;
273 
274     // Level 2
275     L[0][4] = (L[0][0] + L[0][8])/2
276         + get_delta(srcdata,nInputBytes,busy_code,comrat,block_offset,block_size,0,4,&bError);
277     if (bError) return FALSE;
278     L[4][0] = (L[0][0] + L[8][0])/2
279         + get_delta(srcdata,nInputBytes,busy_code,comrat,block_offset,block_size,4,0,&bError);
280     if (bError) return FALSE;
281     L[4][4] = (L[0][0] + L[8][0] + L[0][8] + L[8][8])/4
282         + get_delta(srcdata,nInputBytes,busy_code,comrat,block_offset,block_size,4,4,&bError);
283     if (bError) return FALSE;
284 
285     if( left_side )
286         L[4][8] = L[4][0];
287     if( top_side )
288         L[8][4] = L[0][4];
289 
290     // Level 3
291     for( i = 0; i < 8; i += 4 )
292     {
293         for( j = 0; j < 8; j += 4 )
294         {
295             // above
296             L[i+2][j] = (L[i][j]+L[i+4][j])/2
297                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
298                             block_offset,block_size,i+2,j,&bError);
299             if (bError) return FALSE;
300             // left
301             L[i][j+2] = (L[i][j]+L[i][j+4])/2
302                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
303                             block_offset,block_size,i,j+2,&bError);
304             if (bError) return FALSE;
305             // up-left
306             L[i+2][j+2] = (L[i][j]+L[i][j+4]+L[i+4][j]+L[i+4][j+4])/4
307                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
308                             block_offset,block_size,i+2,j+2,&bError);
309             if (bError) return FALSE;
310         }
311     }
312 
313     if( left_side )
314     {
315         L[2][8] = L[2][0];
316         L[6][8] = L[6][0];
317     }
318     if( top_side )
319     {
320         L[8][2] = L[0][2];
321         L[8][6] = L[0][6];
322     }
323 
324     // Level 4
325     for( i = 0; i < 8; i += 2 )
326     {
327         for( j = 0; j < 8; j += 2 )
328         {
329             // above
330             L[i+1][j] = (L[i][j]+L[i+2][j])/2
331                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
332                             block_offset,block_size,i+1,j,&bError);
333             if (bError) return FALSE;
334             // left
335             L[i][j+1] = (L[i][j]+L[i][j+2])/2
336                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
337                             block_offset,block_size,i,j+1,&bError);
338             if (bError) return FALSE;
339             // up-left
340             L[i+1][j+1] = (L[i][j]+L[i][j+2]+L[i+2][j]+L[i+2][j+2])/4
341                 + get_delta(srcdata,nInputBytes,busy_code,comrat,
342                             block_offset,block_size,i+1,j+1,&bError);
343             if (bError) return FALSE;
344         }
345     }
346 
347     return TRUE;
348 }
349 
350 /************************************************************************/
351 /*                       NITFUncompressARIDPCM()                        */
352 /************************************************************************/
353 
NITFUncompressARIDPCM(NITFImage * psImage,GByte * pabyInputData,int nInputBytes,GByte * pabyOutputImage)354 int NITFUncompressARIDPCM( NITFImage *psImage,
355                            GByte *pabyInputData,
356                            int nInputBytes,
357                            GByte *pabyOutputImage )
358 
359 {
360 
361 /* -------------------------------------------------------------------- */
362 /*      First, verify that we are a COMRAT 0.75 image, which is all     */
363 /*      we currently support.                                           */
364 /* -------------------------------------------------------------------- */
365     if( !EQUAL(psImage->szCOMRAT,"0.75") )
366     {
367         CPLError( CE_Failure, CPLE_AppDefined,
368                   "COMRAT=%s ARIDPCM is not supported.\n"
369                   "Currently only 0.75 is supported.",
370                   psImage->szCOMRAT );
371         return FALSE;
372     }
373 
374 /* -------------------------------------------------------------------- */
375 /*      Setup up the various info we need for each 8x8 neighbourhood    */
376 /*      (which we call blocks in this context).                         */
377 /* -------------------------------------------------------------------- */
378     int blocks_x = (psImage->nBlockWidth + 7) / 8;
379     int blocks_y = (psImage->nBlockHeight + 7) / 8;
380     int block_count = blocks_x * blocks_y;
381     int  rowlen = blocks_x * 8;
382 
383     if( psImage->nBlockWidth > 1000 || /* to detect int overflow above */
384         psImage->nBlockHeight > 1000 ||
385         block_count > 1000 )
386     {
387         CPLError( CE_Failure, CPLE_AppDefined, "Block too large to be decoded");
388         return FALSE;
389     }
390 
391     int block_offset[1000];
392     int block_size[1000];
393     int busy_code[1000];
394     int busy_code_table_size = blocks_x * blocks_y * 2;
395     unsigned char L00[1000];
396 
397 /* -------------------------------------------------------------------- */
398 /*      We allocate a working copy of the full image that may be a      */
399 /*      bit larger than the output buffer if the width or height is     */
400 /*      not divisible by 8.                                             */
401 /* -------------------------------------------------------------------- */
402     GByte *full_image = (GByte *) CPLMalloc(blocks_x * blocks_y * 8 * 8 );
403 
404 /* -------------------------------------------------------------------- */
405 /*      Scan through all the neighbourhoods determining the busyness    */
406 /*      code, and the offset to each's data as well as the L00 value.   */
407 /* -------------------------------------------------------------------- */
408     int i, j, total = busy_code_table_size;
409 
410     for( i = 0; i < blocks_x * blocks_y; i++ )
411     {
412         if (nInputBytes * 8 < i * 2 + 2)
413         {
414             CPLError( CE_Failure, CPLE_AppDefined, "Input buffer too small");
415             CPLFree(full_image);
416             return FALSE;
417         }
418         busy_code[i] = get_bits( pabyInputData, i*2, 2 );
419 
420         block_offset[i] = total;
421         block_size[i] = neighbourhood_size_75[busy_code[i]];
422 
423         if (nInputBytes * 8 < block_offset[i] + 8)
424         {
425             CPLError( CE_Failure, CPLE_AppDefined, "Input buffer too small");
426             CPLFree(full_image);
427             return FALSE;
428         }
429         L00[i] = (unsigned char) get_bits( pabyInputData, block_offset[i], 8 );
430 
431         total += block_size[i];
432     }
433 
434 /* -------------------------------------------------------------------- */
435 /*      Process all the blocks, forming into a final image.             */
436 /* -------------------------------------------------------------------- */
437     int iX, iY;
438 
439     for( iY = 0; iY < blocks_y; iY++ )
440     {
441         for( iX = 0; iX < blocks_x; iX++ )
442         {
443             int iBlock = iX + iY * blocks_x;
444             int L[9][9];
445             unsigned char *full_tl = full_image + iX * 8 + iY * 8 * rowlen;
446 
447             L[0][0] = L00[iBlock];
448             if( iX > 0 )
449             {
450                 L[0][8] = full_tl[rowlen * 7 - 1];
451                 L[2][8] = full_tl[rowlen * 5 - 1];
452                 L[4][8] = full_tl[rowlen * 3 - 1];
453                 L[6][8] = full_tl[rowlen * 1 - 1];
454             }
455             else
456             {
457                 L[0][8] = L[0][0];
458                 L[2][8] = L[0][8]; // need to reconstruct the rest!
459                 L[4][8] = L[0][8];
460                 L[6][8] = L[0][8];
461             }
462 
463             if( iY > 0 )
464             {
465                 L[8][0] = full_tl[7 - rowlen];
466                 L[8][2] = full_tl[5 - rowlen];
467                 L[8][4] = full_tl[3 - rowlen];
468                 L[8][6] = full_tl[1 - rowlen];
469             }
470             else
471             {
472                 L[8][0] = L[0][0];
473                 L[8][2] = L[0][0]; // Need to reconstruct the rest!
474                 L[8][4] = L[0][0];
475                 L[8][5] = L[0][0];
476             }
477 
478             if( iX == 0 || iY == 0 )
479                 L[8][8] = L[0][0];
480             else
481                 L[8][8] = full_tl[-1-rowlen];
482 
483             if (!(decode_block( pabyInputData, nInputBytes, busy_code[iBlock], CR075,
484                           block_offset[iBlock], block_size[iBlock],
485                           iX == 0, iY == 0, L )))
486             {
487                 CPLFree( full_image );
488                 return FALSE;
489             }
490 
491             // Assign to output matrix.
492             for( i = 0; i < 8; i++ )
493             {
494                 for( j = 0; j < 8; j++ )
495                 {
496                     int value = L[i][j];
497                     if( value < 0 )
498                         value = 0;
499                     if( value > 255 )
500                         value = 255;
501 
502                     full_tl[8-j-1 + (8-i-1) * rowlen] = (unsigned char) value;
503                 }
504             }
505         }
506     }
507 
508 /* -------------------------------------------------------------------- */
509 /*      Copy full image back into target buffer, and free.              */
510 /* -------------------------------------------------------------------- */
511     for( iY = 0; iY < psImage->nBlockHeight; iY++ )
512     {
513         memcpy( pabyOutputImage + iY * psImage->nBlockWidth,
514                 full_image + iY * rowlen,
515                 psImage->nBlockWidth );
516     }
517 
518     CPLFree( full_image );
519 
520     return TRUE;
521 }
522