il_rle.c
Upload User: wmy0603
Upload Date: 2022-05-02
Package Size: 1808k
Code Size: 4k
Development Platform:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // Description: Functions for run-length encoding
  3. //-----------------------------------------------------------------------------
  4. // RLE code from TrueVision's TGA sample code available as Tgautils.zip at
  5. // ftp://ftp.truevision.com/pub/TGA.File.Format.Spec/PC.Version
  6. #define IL_RLE_C
  7. #include "il_internal.h"
  8. #include "il_rle.h"
  9. ILboolean ilRleCompressLine(ILubyte *p, ILuint n, ILubyte bpp,
  10. ILubyte *q, ILuint *DestWidth, ILenum CompressMode) {
  11. ILint DiffCount; // pixel count until two identical
  12. ILint SameCount; // number of identical adjacent pixels
  13. ILint RLEBufSize = 0; // count of number of bytes encoded
  14. ILint MaxRun;
  15. const ILint bmp_pad_to_even = 1 - ((ILint)q - *DestWidth) % 2;
  16. switch( CompressMode ) {
  17. case IL_TGACOMP:
  18. MaxRun = TGA_MAX_RUN;
  19. break;
  20. case IL_SGICOMP:
  21. MaxRun = SGI_MAX_RUN;
  22. break;
  23. case IL_BMPCOMP:
  24. MaxRun = BMP_MAX_RUN;
  25. break;
  26. default:
  27. ilSetError(IL_INVALID_PARAM);
  28. return IL_FALSE;
  29. }
  30. while( n > 0 ) {
  31. // Analyze pixels
  32. DiffCount = CountDiffPixels(p, bpp, (ILint)n > MaxRun ? MaxRun : n);
  33. SameCount = CountSamePixels(p, bpp, (ILint)n > MaxRun ? MaxRun : n);
  34. if( CompressMode == IL_BMPCOMP ) {
  35. ILint remaining_data = n - DiffCount - SameCount;
  36. if( remaining_data < 3  ) { // check if the run has gone near the end
  37. // no absolute run can be done
  38. // complete the line adding 0x01 + pixel, for each pixel
  39. while( remaining_data > 0 ) {
  40. *q++ = 0x01;
  41. *q++ = *p++;
  42. remaining_data--;
  43. }
  44. DiffCount = 0;
  45. SameCount = 0;
  46. n = 0;
  47. }
  48. }
  49. if( DiffCount > 0 ) { // create a raw packet (bmp absolute run)
  50. switch(CompressMode) {
  51. case IL_TGACOMP:
  52. *q++ = (ILbyte)(DiffCount - 1);
  53. break;
  54. case IL_BMPCOMP:
  55. *q++ = 0x00; RLEBufSize++;
  56. *q++ = (ILbyte)DiffCount;
  57. break;
  58. case IL_SGICOMP:
  59. *q++ = (ILbyte)(DiffCount | 0x80);
  60. break;
  61. }
  62. n -= DiffCount;
  63. RLEBufSize += (DiffCount * bpp) + 1;
  64. while( DiffCount > 0 ) {
  65. switch(bpp) {
  66. case 4: *q++ = *p++;
  67. case 3: *q++ = *p++;
  68. case 2: *q++ = *p++;
  69. case 1: *q++ = *p++;
  70. }
  71. DiffCount--;
  72. }
  73. if( CompressMode == IL_BMPCOMP ) {
  74. if( (size_t)q % 2 == bmp_pad_to_even ) {
  75. *q++ = 0x00; // insert padding
  76. }
  77. }
  78. }
  79. if( SameCount > 1 ) { // create a RLE packet
  80. switch(CompressMode) {
  81. case IL_TGACOMP:
  82. *q++ = (ILbyte)((SameCount - 1) | 0x80);
  83. break;
  84. case IL_SGICOMP:
  85. case IL_BMPCOMP:
  86. *q++ = (ILbyte)(SameCount);
  87. break;
  88. }
  89. n -= SameCount;
  90. RLEBufSize += bpp + 1;
  91. p += (SameCount - 1) * bpp;
  92. *q++ = *p++;
  93. switch(bpp) {
  94. case 4: *q++ = *p++;
  95. case 3: *q++ = *p++;
  96. case 2: *q++ = *p++;
  97. case 1: *q++ = *p++;
  98. }
  99. }
  100. }
  101. // write line termination code
  102. switch(CompressMode) {
  103. case IL_SGICOMP:
  104. ++RLEBufSize;
  105. *q++ = 0;
  106. break;
  107. case IL_BMPCOMP: 
  108. *q++ = 0x00; RLEBufSize++;
  109. *q++ = 0x00; RLEBufSize++;
  110. break;
  111. }
  112. *DestWidth = RLEBufSize;
  113. return IL_TRUE;
  114. }
  115. // Compresses an entire image using run-length encoding
  116. ILuint ilRleCompress(ILubyte *Data, ILuint Width, ILuint Height, ILuint Depth, ILubyte Bpp,
  117. ILubyte *Dest, ILenum CompressMode, ILuint *ScanTable) {
  118. ILuint DestW = 0, i, j, LineLen, Bps = Width * Bpp, SizeOfPlane = Width * Height * Bpp;
  119. if( ScanTable )
  120. imemclear(ScanTable,Depth*Height*sizeof(ILuint));
  121. for( j = 0; j < Depth; j++ ) {
  122. for( i = 0; i < Height; i++ ) {
  123. if( ScanTable )
  124. *ScanTable++ = DestW;
  125. ilRleCompressLine(Data + j * SizeOfPlane + i * Bps, Width, Bpp, Dest + DestW, &LineLen, CompressMode);
  126. DestW += LineLen;
  127. }
  128. }
  129. if( CompressMode == IL_BMPCOMP ) { // add end of image
  130. *(Data+DestW) = 0x00; DestW++;
  131. *(Data+DestW) = 0x01; DestW++;
  132. }
  133. return DestW;
  134. }