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