- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-IL/src/il_rle.c

    00001 //-----------------------------------------------------------------------------
    00002 // Description: Functions for run-length encoding
    00003 //-----------------------------------------------------------------------------
    00004
    00005 // RLE code from TrueVision's TGA sample code available as Tgautils.zip at
    00006 //      ftp://ftp.truevision.com/pub/TGA.File.Format.Spec/PC.Version
    00007
    00008 #define IL_RLE_C
    00009
    00010 #include "il_internal.h"
    00011 #include "il_rle.h"
    00012
    00013 ILboolean ilRleCompressLine(ILubyte *p, ILuint n, ILubyte bpp,
    00014                         ILubyte *q, ILuint *DestWidth, ILenum CompressMode) {
    00015
    00016         ILint           DiffCount;              // pixel count until two identical
    00017         ILint           SameCount;              // number of identical adjacent pixels
    00018         ILint           RLEBufSize = 0; // count of number of bytes encoded
    00019         ILint           MaxRun;
    00020         const ILint bmp_pad_to_even = 1 - ((size_t)q - *DestWidth) % 2;
    00021
    00022         switch( CompressMode ) {
    00023                 case IL_TGACOMP:
    00024                         MaxRun = TGA_MAX_RUN;
    00025                         break;
    00026                 case IL_SGICOMP:
    00027                         MaxRun = SGI_MAX_RUN;
    00028                         break;
    00029                 case IL_BMPCOMP:
    00030                         MaxRun = BMP_MAX_RUN;
    00031                         break;
    00032                 default:
    00033                         ilSetError(IL_INVALID_PARAM);
    00034                         return IL_FALSE;
    00035         }
    00036
    00037         while( n > 0 ) {
    00038                 // Analyze pixels
    00039                 DiffCount = CountDiffPixels(p, bpp, (ILint)n > MaxRun ? MaxRun : n);
    00040                 SameCount = CountSamePixels(p, bpp, (ILint)n > MaxRun ? MaxRun : n);
    00041
    00042                 if( CompressMode == IL_BMPCOMP ) {
    00043                         ILint remaining_data = n - DiffCount - SameCount;
    00044                         if( remaining_data < 3  ) { // check if the run has gone near the end
    00045                                 // no absolute run can be done
    00046                                 // complete the line adding 0x01 + pixel, for each pixel
    00047                                 while( remaining_data > 0 ) {
    00048                                         *q++ = 0x01;
    00049                                         *q++ = *p++;
    00050                                         remaining_data--;
    00051                                 }
    00052                                 DiffCount = 0;
    00053                                 SameCount = 0;
    00054                                 n = 0;
    00055                         }
    00056                 }
    00057
    00058                 if( DiffCount > 0 ) { // create a raw packet (bmp absolute run)
    00059                         switch(CompressMode) {
    00060                                 case IL_TGACOMP:
    00061                                         *q++ = (ILbyte)(DiffCount - 1);
    00062                                         break;
    00063                                 case IL_BMPCOMP:
    00064                                         *q++ = 0x00; RLEBufSize++;
    00065                                         *q++ = (ILbyte)DiffCount;
    00066                                         break;
    00067                                 case IL_SGICOMP:
    00068                                         *q++ = (ILbyte)(DiffCount | 0x80);
    00069                                         break;
    00070                         }
    00071                         n -= DiffCount;
    00072                         RLEBufSize += (DiffCount * bpp) + 1;
    00073
    00074                         while( DiffCount > 0 ) {
    00075                                 switch(bpp) {
    00076                                         case 4: *q++ = *p++;
    00077                                         case 3: *q++ = *p++;
    00078                                         case 2: *q++ = *p++;
    00079                                         case 1: *q++ = *p++;
    00080                                 }
    00081                                 DiffCount--;
    00082                         }
    00083
    00084                         if( CompressMode == IL_BMPCOMP ) {
    00085                                 if( (size_t)q % 2 == bmp_pad_to_even ) {
    00086                                         *q++ = 0x00; // insert padding
    00087                                 }
    00088                         }
    00089                 }
    00090
    00091                 if( SameCount > 1 ) { // create a RLE packet
    00092                         switch(CompressMode) {
    00093                                 case IL_TGACOMP:
    00094                                         *q++ = (ILbyte)((SameCount - 1) | 0x80);
    00095                                         break;
    00096                                 case IL_SGICOMP:
    00097                                 case IL_BMPCOMP:
    00098                                         *q++ = (ILbyte)(SameCount);
    00099                                         break;
    00100                         }
    00101                         n -= SameCount;
    00102                         RLEBufSize += bpp + 1;
    00103                         p += (SameCount - 1) * bpp;
    00104                         *q++ = *p++;
    00105                         switch(bpp) {
    00106                                 case 4: *q++ = *p++;
    00107                                 case 3: *q++ = *p++;
    00108                                 case 2: *q++ = *p++;
    00109                                 case 1: *q++ = *p++;
    00110                         }
    00111                 }
    00112         }
    00113
    00114         // write line termination code
    00115         switch(CompressMode) {
    00116                 case IL_SGICOMP:
    00117                         ++RLEBufSize;
    00118                         *q++ = 0;
    00119                         break;
    00120                 case IL_BMPCOMP:
    00121                         *q++ = 0x00; RLEBufSize++;
    00122                         *q++ = 0x00; RLEBufSize++;
    00123                         break;
    00124         }
    00125         *DestWidth = RLEBufSize;
    00126
    00127         return IL_TRUE;
    00128 }
    00129
    00130
    00131 // Compresses an entire image using run-length encoding
    00132 ILuint ilRleCompress(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp,
    00133                 ILubyte *Dest, ILenum CompressMode, ILuint *ScanTable) {
    00134         ILuint DestW = 0, i, j, LineLen, Bps = Width * Bpp, SizeOfPlane = Width * Height * Bpp;
    00135
    00136         if( ScanTable )
    00137                 imemclear(ScanTable,Depth*Height*sizeof(ILuint));
    00138         for( j = 0; j < Depth; j++ ) {
    00139                 for( i = 0; i < Height; i++ ) {
    00140                         if( ScanTable )
    00141                                 *ScanTable++ = DestW;
    00142                         ilRleCompressLine(Data + j * SizeOfPlane + i * Bps, Width, Bpp, Dest + DestW, &LineLen, CompressMode);
    00143                         DestW += LineLen;
    00144                 }
    00145         }
    00146
    00147         if( CompressMode == IL_BMPCOMP ) { // add end of image
    00148                 *(Data+DestW) = 0x00; DestW++;
    00149                 *(Data+DestW) = 0x01; DestW++;
    00150         }
    00151
    00152         return DestW;
    00153 }