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

Visual C++

  1. //-----------------------------------------------------------------------------
  2. //
  3. // ImageLib Sources
  4. // Copyright (C) 2000-2009 by Denton Woods
  5. // Last modified: 03/07/2009
  6. //
  7. // Filename: src-IL/src/il_pcx.c
  8. //
  9. // Description: Reads and writes from/to a .pcx file.
  10. //
  11. //-----------------------------------------------------------------------------
  12. #include "il_internal.h"
  13. #ifndef IL_NO_PCX
  14. #include "il_pcx.h"
  15. #include "il_manip.h"
  16. //! Checks if the file specified in FileName is a valid .pcx file.
  17. ILboolean ilIsValid_PCX(ILconst_string FileName)
  18. {
  19. ILHANDLE PcxFile;
  20. ILboolean bPcx = IL_FALSE;
  21. if (!iCheckExtension(FileName, IL_TEXT("pcx"))) {
  22. ilSetError(IL_INVALID_EXTENSION);
  23. return bPcx;
  24. }
  25. PcxFile = iopenr(FileName);
  26. if (PcxFile == NULL) {
  27. ilSetError(IL_COULD_NOT_OPEN_FILE);
  28. return bPcx;
  29. }
  30. bPcx = ilIsValidF_PCX(PcxFile);
  31. icloser(PcxFile);
  32. return bPcx;
  33. }
  34. //! Checks if the ILHANDLE contains a valid .pcx file at the current position.
  35. ILboolean ilIsValidF_PCX(ILHANDLE File)
  36. {
  37. ILuint FirstPos;
  38. ILboolean bRet;
  39. iSetInputFile(File);
  40. FirstPos = itell();
  41. bRet = iIsValidPcx();
  42. iseek(FirstPos, IL_SEEK_SET);
  43. return bRet;
  44. }
  45. //! Checks if Lump is a valid .pcx lump.
  46. ILboolean ilIsValidL_PCX(const void *Lump, ILuint Size)
  47. {
  48. iSetInputLump(Lump, Size);
  49. return iIsValidPcx();
  50. }
  51. // Internal function obtain the .pcx header from the current file.
  52. ILboolean iGetPcxHead(PCXHEAD *Head)
  53. {
  54. Head->Manufacturer = igetc();
  55. Head->Version = igetc();
  56. Head->Encoding = igetc();
  57. Head->Bpp = igetc();
  58. Head->Xmin = GetLittleUShort();
  59. Head->Ymin = GetLittleUShort();
  60. Head->Xmax = GetLittleUShort();
  61. Head->Ymax = GetLittleUShort();
  62. Head->HDpi = GetLittleUShort();
  63. Head->VDpi = GetLittleUShort();
  64. iread(Head->ColMap, 1, 48);
  65. Head->Reserved = igetc();
  66. Head->NumPlanes = igetc();
  67. Head->Bps = GetLittleUShort();
  68. Head->PaletteInfo = GetLittleUShort();
  69. Head->HScreenSize = GetLittleUShort();
  70. Head->VScreenSize = GetLittleUShort();
  71. iread(Head->Filler, 1, 54);
  72. return IL_TRUE;
  73. }
  74. // Internal function to get the header and check it.
  75. ILboolean iIsValidPcx()
  76. {
  77. PCXHEAD Head;
  78. if (!iGetPcxHead(&Head))
  79. return IL_FALSE;
  80. iseek(-(ILint)sizeof(PCXHEAD), IL_SEEK_CUR);
  81. return iCheckPcx(&Head);
  82. }
  83. // Internal function used to check if the HEADER is a valid .pcx header.
  84. // Should we also do a check on Header->Bpp?
  85. ILboolean iCheckPcx(PCXHEAD *Header)
  86. {
  87. ILuint Test;
  88. // Got rid of the Reserved check, because I've seen some .pcx files with invalid values in it.
  89. if (Header->Manufacturer != 10 || Header->Encoding != 1/* || Header->Reserved != 0*/)
  90. return IL_FALSE;
  91. // Try to support all pcx versions, as they only differ in allowed formats...
  92. // Let's hope it works.
  93. if(Header->Version != 5 && Header->Version != 0 && Header->Version != 2 &&
  94.  Header->VDpi != 3 && Header->VDpi != 4)
  95. return IL_FALSE;
  96. // See if the padding size is correct
  97. Test = Header->Xmax - Header->Xmin + 1;
  98. if (Header->Bpp >= 8) {
  99. if (Test & 1) {
  100. if (Header->Bps != Test + 1)
  101. return IL_FALSE;
  102. }
  103. else {
  104. if (Header->Bps != Test)  // No padding
  105. return IL_FALSE;
  106. }
  107. }
  108. /* for (i = 0; i < 54; i++) { useless check
  109. if (Header->Filler[i] != 0)
  110. return IL_FALSE;
  111. } */
  112. return IL_TRUE;
  113. }
  114. //! Reads a .pcx file
  115. ILboolean ilLoad_PCX(ILconst_string FileName)
  116. {
  117. ILHANDLE PcxFile;
  118. ILboolean bPcx = IL_FALSE;
  119. PcxFile = iopenr(FileName);
  120. if (PcxFile == NULL) {
  121. ilSetError(IL_COULD_NOT_OPEN_FILE);
  122. return bPcx;
  123. }
  124. bPcx = ilLoadF_PCX(PcxFile);
  125. icloser(PcxFile);
  126. return bPcx;
  127. }
  128. //! Reads an already-opened .pcx file
  129. ILboolean ilLoadF_PCX(ILHANDLE File)
  130. {
  131. ILuint FirstPos;
  132. ILboolean bRet;
  133. iSetInputFile(File);
  134. FirstPos = itell();
  135. bRet = iLoadPcxInternal();
  136. iseek(FirstPos, IL_SEEK_SET);
  137. return bRet;
  138. }
  139. //! Reads from a memory "lump" that contains a .pcx
  140. ILboolean ilLoadL_PCX(const void *Lump, ILuint Size)
  141. {
  142. iSetInputLump(Lump, Size);
  143. return iLoadPcxInternal();
  144. }
  145. // Internal function used to load the .pcx.
  146. ILboolean iLoadPcxInternal()
  147. {
  148. PCXHEAD Header;
  149. ILboolean bPcx = IL_FALSE;
  150. if (iCurImage == NULL) {
  151. ilSetError(IL_ILLEGAL_OPERATION);
  152. return bPcx;
  153. }
  154. if (!iGetPcxHead(&Header))
  155. return IL_FALSE;
  156. if (!iCheckPcx(&Header)) {
  157. ilSetError(IL_INVALID_FILE_HEADER);
  158. return IL_FALSE;
  159. }
  160. bPcx = iUncompressPcx(&Header);
  161. if (!bPcx)
  162. return IL_FALSE;
  163. return ilFixImage();
  164. }
  165. // Internal function to uncompress the .pcx (all .pcx files are rle compressed)
  166. ILboolean iUncompressPcx(PCXHEAD *Header)
  167. {
  168. //changed decompression loop 2003-09-01
  169. //From the pcx spec: "There should always
  170. //be a decoding break at the end of each scan line.
  171. //But there will not be a decoding break at the end of
  172. //each plane within each scan line."
  173. //This is now handled correctly (hopefully ;) )
  174. ILubyte ByteHead, Colour, *ScanLine /* For all planes */;
  175. ILuint ScanLineSize;
  176. ILuint c, i, x, y;
  177. if (Header->Bpp < 8) {
  178. /*ilSetError(IL_FORMAT_NOT_SUPPORTED);
  179. return IL_FALSE;*/
  180. return iUncompressSmall(Header);
  181. }
  182. if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL))
  183. return IL_FALSE;
  184. iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
  185. switch (iCurImage->Bpp)
  186. {
  187. case 1:
  188. iCurImage->Format = IL_COLOUR_INDEX;
  189. iCurImage->Pal.PalType = IL_PAL_RGB24;
  190. iCurImage->Pal.PalSize = 256 * 3;  // Need to find out for sure...
  191. iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
  192. if (iCurImage->Pal.Palette == NULL) {
  193. return IL_FALSE;
  194. }
  195. break;
  196. //case 2:  // No 16-bit images in the pcx format!
  197. case 3:
  198. iCurImage->Format = IL_RGB;
  199. iCurImage->Pal.Palette = NULL;
  200. iCurImage->Pal.PalSize = 0;
  201. iCurImage->Pal.PalType = IL_PAL_NONE;
  202. break;
  203. case 4:
  204. iCurImage->Format = IL_RGBA;
  205. iCurImage->Pal.Palette = NULL;
  206. iCurImage->Pal.PalSize = 0;
  207. iCurImage->Pal.PalType = IL_PAL_NONE;
  208. break;
  209. default:
  210. ilSetError(IL_ILLEGAL_FILE_VALUE);
  211. return IL_FALSE;
  212. }
  213. ScanLineSize = iCurImage->Bpp*Header->Bps;
  214. ScanLine = (ILubyte*)ialloc(ScanLineSize);
  215. if (ScanLine == NULL) {
  216. return IL_FALSE;
  217. }
  218. //changed 2003-09-01
  219. //having the decoding code twice is error-prone,
  220. //so I made iUnCache() smart enough to grasp
  221. //if iPreCache() wasn't called and call it
  222. //anyways.
  223. if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
  224. iPreCache(iCurImage->SizeOfData / 4);
  225. for (y = 0; y < iCurImage->Height; y++) {
  226. x = 0;
  227. //read scanline
  228. while (x < ScanLineSize) {
  229. if (iread(&ByteHead, 1, 1) != 1) {
  230. iUnCache();
  231. goto file_read_error;
  232. }
  233. if ((ByteHead & 0xC0) == 0xC0) {
  234. ByteHead &= 0x3F;
  235. if (iread(&Colour, 1, 1) != 1) {
  236. iUnCache();
  237. goto file_read_error;
  238. }
  239. if (x + ByteHead > ScanLineSize) {
  240. iUnCache();
  241. goto file_read_error;
  242. }
  243. for (i = 0; i < ByteHead; i++) {
  244. ScanLine[x++] = Colour;
  245. }
  246. }
  247. else {
  248. ScanLine[x++] = ByteHead;
  249. }
  250. }
  251. //convert plane-separated scanline into index, rgb or rgba pixels.
  252. //there might be a padding byte at the end of each scanline...
  253. for (x = 0; x < iCurImage->Width; x++) {
  254. for(c = 0; c < iCurImage->Bpp; c++) {
  255. iCurImage->Data[y * iCurImage->Bps + x * iCurImage->Bpp + c] =
  256. ScanLine[x + c * Header->Bps];
  257. }
  258. }
  259. }
  260. iUnCache();
  261. // Read in the palette
  262. if (Header->Version == 5 && iCurImage->Bpp == 1) {
  263. x = itell();
  264. if (iread(&ByteHead, 1, 1) == 0) {  // If true, assume that we have a luminance image.
  265. ilGetError();  // Get rid of the IL_FILE_READ_ERROR.
  266. iCurImage->Format = IL_LUMINANCE;
  267. if (iCurImage->Pal.Palette)
  268. ifree(iCurImage->Pal.Palette);
  269. iCurImage->Pal.PalSize = 0;
  270. iCurImage->Pal.PalType = IL_PAL_NONE;
  271. }
  272. else {
  273. if (ByteHead != 12)  // Some Quake2 .pcx files don't have this byte for some reason.
  274. iseek(-1, IL_SEEK_CUR);
  275. if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize)
  276. goto file_read_error;
  277. }
  278. }
  279. ifree(ScanLine);
  280. return IL_TRUE;
  281. file_read_error:
  282. ifree(ScanLine);
  283. //added 2003-09-01
  284. ilSetError(IL_FILE_READ_ERROR);
  285. return IL_FALSE;
  286. }
  287. ILboolean iUncompressSmall(PCXHEAD *Header)
  288. {
  289. ILuint i = 0, j, k, c, d, x, y, Bps;
  290. ILubyte HeadByte, Colour, Data = 0, *ScanLine;
  291. if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) {
  292. return IL_FALSE;
  293. }
  294. iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
  295. switch (Header->NumPlanes)
  296. {
  297. case 1:
  298. iCurImage->Format = IL_LUMINANCE;
  299. break;
  300. case 4:
  301. iCurImage->Format = IL_COLOUR_INDEX;
  302. break;
  303. default:
  304. ilSetError(IL_ILLEGAL_FILE_VALUE);
  305. return IL_FALSE;
  306. }
  307. if (Header->NumPlanes == 1 && Header->Bpp == 1) {
  308. for (j = 0; j < iCurImage->Height; j++) {
  309. i = 0; //number of written pixels
  310. while (i < iCurImage->Width) {
  311. if (iread(&HeadByte, 1, 1) != 1)
  312. return IL_FALSE;
  313. if (HeadByte >= 192) {
  314. HeadByte -= 192;
  315. if (iread(&Data, 1, 1) != 1)
  316. return IL_FALSE;
  317. for (c = 0; c < HeadByte; c++) {
  318. k = 128;
  319. for (d = 0; d < 8 && i < iCurImage->Width; d++) {
  320. iCurImage->Data[j * iCurImage->Width + i++] = ((Data & k) != 0 ? 255 : 0);
  321. k >>= 1;
  322. }
  323. }
  324. }
  325. else {
  326. k = 128;
  327. for (c = 0; c < 8 && i < iCurImage->Width; c++) {
  328. iCurImage->Data[j * iCurImage->Width + i++] = ((HeadByte & k) != 0 ? 255 : 0);
  329. k >>= 1;
  330. }
  331. }
  332. }
  333. //if(Data != 0)
  334. //changed 2003-09-01:
  335. //There has to be an even number of bytes per line in a pcx.
  336. //One byte can hold up to 8 bits, so Width/8 bytes
  337. //are needed to hold a 1 bit per pixel image line.
  338. //If Width/8 is even no padding is needed,
  339. //one pad byte has to be read otherwise.
  340. //(let's hope the above is true ;-))
  341. if(!((iCurImage->Width >> 3) & 0x1))
  342. igetc(); // Skip pad byte
  343. }
  344. }
  345. else if (Header->NumPlanes == 4 && Header->Bpp == 1){   // 4-bit images
  346. //changed decoding 2003-09-10 (was buggy)...could need a speedup
  347. Bps = Header->Bps * Header->NumPlanes * 8;
  348. iCurImage->Pal.Palette = (ILubyte*)ialloc(16 * 3);  // Size of palette always (48 bytes).
  349. ScanLine = (ILubyte*)ialloc(Bps);
  350. if (iCurImage->Pal.Palette == NULL || ScanLine == NULL) {
  351. ifree(ScanLine);
  352. ifree(iCurImage->Pal.Palette);
  353. return IL_FALSE;
  354. }
  355. memcpy(iCurImage->Pal.Palette, Header->ColMap, 16 * 3);
  356. iCurImage->Pal.PalSize = 16 * 3;
  357. iCurImage->Pal.PalType = IL_PAL_RGB24;
  358. memset(iCurImage->Data, 0, iCurImage->SizeOfData);
  359. if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
  360. iPreCache(iCurImage->SizeOfData / 4);
  361. for (y = 0; y < iCurImage->Height; y++) {
  362. x = 0;
  363. while (x < Bps) {
  364. if (iread(&HeadByte, 1, 1) != 1) {
  365. iUnCache();
  366. ifree(ScanLine);
  367. return IL_FALSE;
  368. }
  369. if ((HeadByte & 0xC0) == 0xC0) {
  370. HeadByte &= 0x3F;
  371. if (iread(&Colour, 1, 1) != 1) {
  372. iUnCache();
  373. ifree(ScanLine);
  374. return IL_FALSE;
  375. }
  376. for (i = 0; i < HeadByte; i++) {
  377. k = 128;
  378. for (j = 0; j < 8 && x < Bps; j++) {
  379. ScanLine[x++] = (Colour & k)?1:0;
  380. k >>= 1;
  381. }
  382. }
  383. }
  384. else {
  385. k = 128;
  386. for (j = 0; j < 8 && x < Bps; j++) {
  387. ScanLine[x++] = (HeadByte & k)?1:0;
  388. k >>= 1;
  389. }
  390. }
  391. }
  392. for (x = 0; x < iCurImage->Width; x++) {  // 'Cleverly' ignores the pad bytes. ;)
  393. for(c = 0; c < Header->NumPlanes; c++)
  394. iCurImage->Data[y * iCurImage->Width + x] |= ScanLine[x + c*Header->Bps*8] << c;
  395. }
  396. }
  397. iUnCache();
  398. ifree(ScanLine);
  399. }
  400. else {
  401. ilSetError(IL_FORMAT_NOT_SUPPORTED);
  402. return IL_FALSE;
  403. }
  404. return IL_TRUE;
  405. }
  406. //! Writes a .pcx file
  407. ILboolean ilSave_PCX(const ILstring FileName)
  408. {
  409. ILHANDLE PcxFile;
  410. ILuint PcxSize;
  411. if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
  412. if (iFileExists(FileName)) {
  413. ilSetError(IL_FILE_ALREADY_EXISTS);
  414. return IL_FALSE;
  415. }
  416. }
  417. PcxFile = iopenw(FileName);
  418. if (PcxFile == NULL) {
  419. ilSetError(IL_COULD_NOT_OPEN_FILE);
  420. return IL_FALSE;
  421. }
  422. PcxSize = ilSaveF_PCX(PcxFile);
  423. iclosew(PcxFile);
  424. if (PcxSize == 0)
  425. return IL_FALSE;
  426. return IL_TRUE;
  427. }
  428. //! Writes a .pcx to an already-opened file
  429. ILuint ilSaveF_PCX(ILHANDLE File)
  430. {
  431. ILuint Pos;
  432. iSetOutputFile(File);
  433. Pos = itellw();
  434. if (iSavePcxInternal() == IL_FALSE)
  435. return 0;  // Error occurred
  436. return itellw() - Pos;  // Return the number of bytes written.
  437. }
  438. //! Writes a .pcx to a memory "lump"
  439. ILuint ilSaveL_PCX(void *Lump, ILuint Size)
  440. {
  441. ILuint Pos;
  442. iSetOutputLump(Lump, Size);
  443. Pos = itellw();
  444. if (iSavePcxInternal() == IL_FALSE)
  445. return 0;  // Error occurred
  446. return itellw() - Pos;  // Return the number of bytes written.
  447. }
  448. // Internal function used to save the .pcx.
  449. ILboolean iSavePcxInternal()
  450. {
  451. ILuint i, c, PalSize;
  452. ILpal *TempPal;
  453. ILimage *TempImage = iCurImage;
  454. ILubyte *TempData;
  455. if (iCurImage == NULL) {
  456. ilSetError(IL_ILLEGAL_OPERATION);
  457. return IL_FALSE;
  458. }
  459. switch (iCurImage->Format)
  460. {
  461. case IL_LUMINANCE:
  462. TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE);
  463. if (TempImage == NULL)
  464. return IL_FALSE;
  465. break;
  466. case IL_BGR:
  467. TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
  468. if (TempImage == NULL)
  469. return IL_FALSE;
  470. break;
  471. case IL_BGRA:
  472. TempImage = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE);
  473. if (TempImage == NULL)
  474. return IL_FALSE;
  475. break;
  476. default:
  477. if (iCurImage->Bpc > 1) {
  478. TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE);
  479. if (TempImage == NULL)
  480. return IL_FALSE;
  481. }
  482. }
  483. if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) {
  484. TempData = iGetFlipped(TempImage);
  485. if (TempData == NULL) {
  486. if (TempImage != iCurImage) {
  487. ilCloseImage(TempImage);
  488. }
  489. return IL_FALSE;
  490. }
  491. }
  492. else {
  493. TempData = TempImage->Data;
  494. }
  495. iputc(0xA);  // Manufacturer - always 10
  496. iputc(0x5);  // Version Number - always 5
  497. iputc(0x1);  // Encoding - always 1
  498. iputc(0x8);  // Bits per channel
  499. SaveLittleUShort(0);  // X Minimum
  500. SaveLittleUShort(0);  // Y Minimum
  501. SaveLittleUShort((ILushort)(iCurImage->Width - 1));
  502. SaveLittleUShort((ILushort)(iCurImage->Height - 1));
  503. SaveLittleUShort(0);
  504. SaveLittleUShort(0);
  505. // Useless palette info?
  506. for (i = 0; i < 48; i++) {
  507. iputc(0);
  508. }
  509. iputc(0x0);  // Reserved - always 0
  510. iputc(iCurImage->Bpp);  // Number of planes - only 1 is supported right now
  511. SaveLittleUShort((ILushort)(iCurImage->Width & 1 ? iCurImage->Width + 1 : iCurImage->Width));  // Bps
  512. SaveLittleUShort(0x1);  // Palette type - ignored?
  513. // Mainly filler info
  514. for (i = 0; i < 58; i++) {
  515. iputc(0x0);
  516. }
  517. // Output data
  518. for (i = 0; i < TempImage->Height; i++) {
  519. for (c = 0; c < TempImage->Bpp; c++) {
  520. encLine(TempData + TempImage->Bps * i + c, TempImage->Width, (ILubyte)(TempImage->Bpp - 1));
  521. }
  522. }
  523. // Automatically assuming we have a palette...dangerous!
  524. // Also assuming 3 bpp palette
  525. iputc(0xC);  // Pad byte must have this value
  526. // If the current image has a palette, take care of it
  527. if (TempImage->Format == IL_COLOUR_INDEX) {
  528. // If the palette in .pcx format, write it directly
  529. if (TempImage->Pal.PalType == IL_PAL_RGB24) {
  530. iwrite(TempImage->Pal.Palette, 1, TempImage->Pal.PalSize);
  531. }
  532. else {
  533. TempPal = iConvertPal(&TempImage->Pal, IL_PAL_RGB24);
  534. if (TempPal == NULL) {
  535. if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
  536. ifree(TempData);
  537. if (TempImage != iCurImage)
  538. ilCloseImage(TempImage);
  539. return IL_FALSE;
  540. }
  541. iwrite(TempPal->Palette, 1, TempPal->PalSize);
  542. ifree(TempPal->Palette);
  543. ifree(TempPal);
  544. }
  545. }
  546. // If the palette is not all 256 colours, we have to pad it.
  547. PalSize = 768 - iCurImage->Pal.PalSize;
  548. for (i = 0; i < PalSize; i++) {
  549. iputc(0x0);
  550. }
  551. if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
  552. ifree(TempData);
  553. if (TempImage != iCurImage)
  554. ilCloseImage(TempImage);
  555. return IL_TRUE;
  556. }
  557. // Routine used from ZSoft's pcx documentation
  558. ILuint encput(ILubyte byt, ILubyte cnt)
  559. {
  560. if (cnt) {
  561. if ((cnt == 1) && (0xC0 != (0xC0 & byt))) {
  562. if (IL_EOF == iputc(byt))
  563. return(0);     /* disk write error (probably full) */
  564. return(1);
  565. }
  566. else {
  567. if (IL_EOF == iputc((ILubyte)((ILuint)0xC0 | cnt)))
  568. return (0);      /* disk write error */
  569. if (IL_EOF == iputc(byt))
  570. return (0);      /* disk write error */
  571. return (2);
  572. }
  573. }
  574. return (0);
  575. }
  576. // This subroutine encodes one scanline and writes it to a file.
  577. //  It returns number of bytes written into outBuff, 0 if failed.
  578. ILuint encLine(ILubyte *inBuff, ILint inLen, ILubyte Stride)
  579. {
  580. ILubyte _this, last;
  581. ILint srcIndex, i;
  582. ILint total;
  583. ILubyte runCount;     // max single runlength is 63
  584. total = 0;
  585. runCount = 1;
  586. last = *(inBuff);
  587. // Find the pixel dimensions of the image by calculating 
  588. //[XSIZE = Xmax - Xmin + 1] and [YSIZE = Ymax - Ymin + 1].  
  589. //Then calculate how many bytes are in a "run"
  590. for (srcIndex = 1; srcIndex < inLen; srcIndex++) {
  591. inBuff += Stride;
  592. _this = *(++inBuff);
  593. if (_this == last) {  // There is a "run" in the data, encode it
  594. runCount++;
  595. if (runCount == 63) {
  596. if (! (i = encput(last, runCount)))
  597. return (0);
  598. total += i;
  599. runCount = 0;
  600. }
  601. }
  602. else {  // No "run"  -  _this != last
  603. if (runCount) {
  604. if (! (i = encput(last, runCount)))
  605. return(0);
  606. total += i;
  607. }
  608. last = _this;
  609. runCount = 1;
  610. }
  611. }  // endloop
  612. if (runCount) {  // finish up
  613. if (! (i = encput(last, runCount)))
  614. return (0);
  615. if (inLen % 2)
  616. iputc(0);
  617. return (total + i);
  618. }
  619. else {
  620. if (inLen % 2)
  621. iputc(0);
  622. }
  623. return (total);
  624. }
  625. #endif//IL_NO_PCX