1 /*****************************
2  * libdicom - MDC extensions *
3  *****************************/
4 /*
5  *
6  */
7 
8 /*
9  * Contributions by Jaslet Bertrand
10  *
11  * for handling encapsulated pixeldata:
12  *
13  *  - RLE
14  *
15  *  - LossLess JPEG
16  */
17 
18 #include "dicom.h"
19 
20 #ifdef MDC_SUPPORT_LJPG
21  #include "jpeg.h"
22  #include "jpegless.h"
23 #endif
24 
25 #define MDC_MAX_RLE_SEGMENTS  4L   /* max of 32 bits (ARGB) images supported */
26 
27 /*******
28  * RLE *
29  *******/
30 
31 static void mdc_dicom_decodeRLE_segment(U16 *, U8 *, U32, U32 , U32);
32 
33 /*
34  * gets and decode an RLE pixel data element
35  * return : the image
36  */
mdc_dicom_decomp_rle(FILE * fp,U16 * image16,U32 length)37 S16 mdc_dicom_decomp_rle(FILE *fp, U16 *image16, U32 length)
38 {
39   U32 	numberSegments, i;
40   U8	*rle;
41   long	offset[MDC_MAX_RLE_SEGMENTS + 1], rlelen, skip;
42   int	r;
43 
44   dicom_log(DEBUG,"mdc_dicom_decomp_rle()");
45 
46   /* for each image we have:                                       */
47   /* 0xFFFE 0xE000 length RLE_header RLE_segment1 RLE_segment2 ... */
48   /* length is 4 bits / image                                      */
49 
50   /* read 4 chars from the file = number of segments */
51   r = fread(&numberSegments,4,1,fp);
52   if (r != 1) {
53     dicom_check(-1);
54     dicom_log(ERROR,"RLE - Failure numberSegments");
55     return -1;
56   }
57   dicom_swap(&numberSegments,4);
58   if (numberSegments > MDC_MAX_RLE_SEGMENTS)
59   {
60     dicom_log(ERROR,"RLE - Maximum of 32 bits images supported");
61     return -1; /* allow 8, 16, 24 & 32 bits images, 8 bits per segment */
62   }
63 
64   /* read offset0, offset1, offset2, ... */
65   for (i=0; i < numberSegments; i++) {
66      r = fread(&offset[i],4,1,fp);
67      if (r != 1) {
68        dicom_check(-1);
69        dicom_log(ERROR,"RLE - Failure offsets");
70        return -1;
71      }
72      dicom_swap(&offset[i],4);
73   }
74   /* skip rest of header */
75   skip = 60 - (numberSegments * 4);
76   fseek(fp, skip, SEEK_CUR);
77   if (dicom_check(-1))
78   {
79     dicom_log(ERROR,"RLE - Failure header skip");
80     return -1;
81   }
82 
83   offset[numberSegments] = length; /* needed for offset last segment */
84 
85   /* read all segments */
86   for (i=0; i < numberSegments; i++)
87   {
88     /* read rle image */
89     rlelen = offset[i+1] - offset[i];
90     rle	   = (U8*)malloc((U32)(rlelen + 10L));
91     if (rle)
92     {
93       /* extract the image from the file  */
94       r = fread((void *)rle, (unsigned)rlelen, 1L, fp);
95       if (r != 1) {
96       	dicom_check(-1);
97         dicom_log(ERROR,"RLE - Failure image read");
98         return -2;
99       }
100       mdc_dicom_decodeRLE_segment(image16,rle
101                                          ,(unsigned)rlelen,numberSegments,i);
102       /* delete buffer */
103       free(rle);
104     }
105     else
106     {
107       dicom_log(ERROR,"RLE - Out of memory");
108       return -3;
109     }
110   }
111 
112   return 0;
113 
114 }
115 
116 /*
117  *  decode a RLE segment
118  *  image  : pointer on real image (8 or 16 bits)
119  *  rle    : pointer on rle buffer (8bits)
120  *  length : length of rle buffer
121  *  segtot : total number of segments
122  *  segnb  : number of current segment (zero based !)
123  */
mdc_dicom_decodeRLE_segment(U16 * image,U8 * rle,U32 length,U32 segtot,U32 segnb)124 void mdc_dicom_decodeRLE_segment(U16 *image, U8 *rle, U32 length,U32 segtot, U32 segnb)
125 {
126   U32  j, indj;
127   U8   *pix, val;
128   U16  code; /* prevent warning: actually signed char >=128) = (256-code) */
129   U16  ii, iimax;
130 
131   dicom_log(DEBUG,"mdc_dicom_decodeRLE_segment()");
132 
133   /* convert rle into real image      */
134   pix  = (U8*) image;
135   /* initial start number, zero based */
136   /* segment 1st=0, 2nd=1, 3rd=2, ... */
137   indj = segnb;
138   for (j = 0L; j < length; )
139   {
140     code = (U16) rle [j];
141     j++; /* yes, I know but do not move it */
142     /* sequence of different bytes */
143     if (code == 0)
144     {
145       if (j < length - 1)
146         pix [indj] = rle [j++];
147       indj += segtot;
148     }
149     else if ((code > 0) && (code <= 127))
150     {
151       for (ii = 0; ii < (code + 1); ii++)
152       {
153          if (j == length) break;
154          pix [indj] = rle [j++];
155          indj += segtot;
156       }
157     }
158     /* repetition of the same byte */
159     else if ((code <= 255) && (code > 128))
160     {
161       val = rle [j++];
162       iimax = 256-code;
163       for (ii = 0; ii <= iimax; ii++)
164       {
165         pix [indj] = val;
166         indj += segtot;
167       }
168     }
169   } /* for */
170 }
171 
172 /*****************
173  * LossLess JPEG *
174  *****************/
175 
mdc_dicom_decomp_ljpg(FILE * fp,U16 * image16,U32 length,U32 depth)176 S16 mdc_dicom_decomp_ljpg(FILE *fp, U16 *image16, U32 length, U32 depth)
177 {
178 #if MDC_SUPPORT_LJPG
179   return(JPEGLosslessDecodeImage(fp,image16,(signed)depth,(signed)length));
180 #else
181   return(-1);
182 #endif
183 }
184