/****************************r * libdicom - MDC extensions * *****************************/ /* * $Id: decomp.c,v 1.4 2003/12/28 00:42:33 enlf Exp $ */ /* * Contributions by Jaslet Bertrand * * for handling encapsulated pixeldata: * * - RLE * * - LossLess JPEG */ #include "dicom.h" #ifdef MDC_SUPPORT_LJPG #include "jpeg.h" #include "jpegless.h" #endif #define MDC_MAX_RLE_SEGMENTS 4L /* max of 32 bits (ARGB) images supported */ /******* * RLE * *******/ static void mdc_dicom_decodeRLE_segment(U16 *, U8 *, U32, U32 , U32); /* * gets and decode an RLE pixel data element * return : the image */ S16 mdc_dicom_decomp_rle(FILE *fp, U16 *image16, U32 length) { U32 numberSegments, i; U8 *rle; long offset[MDC_MAX_RLE_SEGMENTS + 1], rlelen, skip; dicom_log(DEBUG,"mdc_dicom_decomp_rle()"); /* for each image we have: */ /* 0xFFFE 0xE000 length RLE_header RLE_segment1 RLE_segment2 ... */ /* length is 4 bits / image */ /* read 4 chars from the file = number of segments */ fread(&numberSegments,4,1,fp); if (dicom_check(-1)) { dicom_log(ERROR,"RLE - Failure numberSegments"); return -1; } dicom_swap(&numberSegments,4); if (numberSegments > MDC_MAX_RLE_SEGMENTS) { dicom_log(ERROR,"RLE - Maximum of 32 bits images supported"); return -1; /* allow 8, 16, 24 & 32 bits images, 8 bits per segment */ } /* read offset0, offset1, offset2, ... */ for (i=0; i < numberSegments; i++) { fread(&offset[i],4,1,fp); if (dicom_check(-1)) { dicom_log(ERROR,"RLE - Failure offsets"); return -1; } dicom_swap(&offset[i],4); } /* skip rest of header */ skip = 60 - (numberSegments * 4); fseek(fp, skip, SEEK_CUR); if (dicom_check(-1)) { dicom_log(ERROR,"RLE - Failure header skip"); return -1; } offset[numberSegments] = length; /* needed for offset last segment */ /* read all segments */ for (i=0; i < numberSegments; i++) { /* read rle image */ rlelen = offset[i+1] - offset[i]; rle = (U8*)malloc((U32)(rlelen + 10L)); if (rle) { /* extract the image from the file */ fread((void *)rle, (unsigned)rlelen, 1L, fp); if (ferror(fp)) { dicom_log(ERROR,"RLE - Failure image read"); return -2; } mdc_dicom_decodeRLE_segment(image16,rle ,(unsigned)rlelen,numberSegments,i); /* delete buffer */ free(rle); } else { dicom_log(ERROR,"RLE - Out of memory"); return -3; } } return 0; } /* * decode a RLE segment * image : pointer on real image (8 or 16 bits) * rle : pointer on rle buffer (8bits) * length : length of rle buffer * segtot : total number of segments * segnb : number of current segment (zero based !) */ void mdc_dicom_decodeRLE_segment(U16 *image, U8 *rle, U32 length,U32 segtot, U32 segnb) { U32 j, indj; U8 *pix, val; U16 code; /* prevent warning: actually signed char >=128) = (256-code) */ U16 ii, iimax; dicom_log(DEBUG,"mdc_dicom_decodeRLE_segment()"); /* convert rle into real image */ pix = (U8*) image; /* initial start number, zero based */ /* segment 1st=0, 2nd=1, 3rd=2, ... */ indj = segnb; for (j = 0L; j < length; ) { code = (U16) rle [j]; j++; /* yes, I know but do not move it */ /* sequence of different bytes */ if (code == 0) { if (j < length - 1) pix [indj] = rle [j++]; indj += segtot; } else if ((code > 0) && (code <= 127)) { for (ii = 0; ii < (code + 1); ii++) { if (j == length) break; pix [indj] = rle [j++]; indj += segtot; } } /* repetition of the same byte */ else if ((code <= 255) && (code > 128)) { val = rle [j++]; iimax = 256-code; for (ii = 0; ii <= iimax; ii++) { pix [indj] = val; indj += segtot; } } } /* for */ } /***************** * LossLess JPEG * *****************/ S16 mdc_dicom_decomp_ljpg(FILE *fp, U16 *image16, U32 length, U32 depth) { #if MDC_SUPPORT_LJPG return(JPEGLosslessDecodeImage(fp,image16,(signed)depth,(signed)length)); #else return(-1); #endif }