Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
il_pcx.c
Package: devil-1.7.99.tar.gz [view]
Upload User: wmy0603
Upload Date: 2022-05-02
Package Size: 1808k
Code Size: 17k
Category:
Compress-Decompress algrithms
Development Platform:
Visual C++
- //-----------------------------------------------------------------------------
- //
- // ImageLib Sources
- // Copyright (C) 2000-2009 by Denton Woods
- // Last modified: 03/07/2009
- //
- // Filename: src-IL/src/il_pcx.c
- //
- // Description: Reads and writes from/to a .pcx file.
- //
- //-----------------------------------------------------------------------------
- #include "il_internal.h"
- #ifndef IL_NO_PCX
- #include "il_pcx.h"
- #include "il_manip.h"
- //! Checks if the file specified in FileName is a valid .pcx file.
- ILboolean ilIsValid_PCX(ILconst_string FileName)
- {
- ILHANDLE PcxFile;
- ILboolean bPcx = IL_FALSE;
- if (!iCheckExtension(FileName, IL_TEXT("pcx"))) {
- ilSetError(IL_INVALID_EXTENSION);
- return bPcx;
- }
- PcxFile = iopenr(FileName);
- if (PcxFile == NULL) {
- ilSetError(IL_COULD_NOT_OPEN_FILE);
- return bPcx;
- }
- bPcx = ilIsValidF_PCX(PcxFile);
- icloser(PcxFile);
- return bPcx;
- }
- //! Checks if the ILHANDLE contains a valid .pcx file at the current position.
- ILboolean ilIsValidF_PCX(ILHANDLE File)
- {
- ILuint FirstPos;
- ILboolean bRet;
- iSetInputFile(File);
- FirstPos = itell();
- bRet = iIsValidPcx();
- iseek(FirstPos, IL_SEEK_SET);
- return bRet;
- }
- //! Checks if Lump is a valid .pcx lump.
- ILboolean ilIsValidL_PCX(const void *Lump, ILuint Size)
- {
- iSetInputLump(Lump, Size);
- return iIsValidPcx();
- }
- // Internal function obtain the .pcx header from the current file.
- ILboolean iGetPcxHead(PCXHEAD *Head)
- {
- Head->Manufacturer = igetc();
- Head->Version = igetc();
- Head->Encoding = igetc();
- Head->Bpp = igetc();
- Head->Xmin = GetLittleUShort();
- Head->Ymin = GetLittleUShort();
- Head->Xmax = GetLittleUShort();
- Head->Ymax = GetLittleUShort();
- Head->HDpi = GetLittleUShort();
- Head->VDpi = GetLittleUShort();
- iread(Head->ColMap, 1, 48);
- Head->Reserved = igetc();
- Head->NumPlanes = igetc();
- Head->Bps = GetLittleUShort();
- Head->PaletteInfo = GetLittleUShort();
- Head->HScreenSize = GetLittleUShort();
- Head->VScreenSize = GetLittleUShort();
- iread(Head->Filler, 1, 54);
- return IL_TRUE;
- }
- // Internal function to get the header and check it.
- ILboolean iIsValidPcx()
- {
- PCXHEAD Head;
- if (!iGetPcxHead(&Head))
- return IL_FALSE;
- iseek(-(ILint)sizeof(PCXHEAD), IL_SEEK_CUR);
- return iCheckPcx(&Head);
- }
- // Internal function used to check if the HEADER is a valid .pcx header.
- // Should we also do a check on Header->Bpp?
- ILboolean iCheckPcx(PCXHEAD *Header)
- {
- ILuint Test;
- // Got rid of the Reserved check, because I've seen some .pcx files with invalid values in it.
- if (Header->Manufacturer != 10 || Header->Encoding != 1/* || Header->Reserved != 0*/)
- return IL_FALSE;
- // Try to support all pcx versions, as they only differ in allowed formats...
- // Let's hope it works.
- if(Header->Version != 5 && Header->Version != 0 && Header->Version != 2 &&
- Header->VDpi != 3 && Header->VDpi != 4)
- return IL_FALSE;
- // See if the padding size is correct
- Test = Header->Xmax - Header->Xmin + 1;
- if (Header->Bpp >= 8) {
- if (Test & 1) {
- if (Header->Bps != Test + 1)
- return IL_FALSE;
- }
- else {
- if (Header->Bps != Test) // No padding
- return IL_FALSE;
- }
- }
- /* for (i = 0; i < 54; i++) { useless check
- if (Header->Filler[i] != 0)
- return IL_FALSE;
- } */
- return IL_TRUE;
- }
- //! Reads a .pcx file
- ILboolean ilLoad_PCX(ILconst_string FileName)
- {
- ILHANDLE PcxFile;
- ILboolean bPcx = IL_FALSE;
- PcxFile = iopenr(FileName);
- if (PcxFile == NULL) {
- ilSetError(IL_COULD_NOT_OPEN_FILE);
- return bPcx;
- }
- bPcx = ilLoadF_PCX(PcxFile);
- icloser(PcxFile);
- return bPcx;
- }
- //! Reads an already-opened .pcx file
- ILboolean ilLoadF_PCX(ILHANDLE File)
- {
- ILuint FirstPos;
- ILboolean bRet;
- iSetInputFile(File);
- FirstPos = itell();
- bRet = iLoadPcxInternal();
- iseek(FirstPos, IL_SEEK_SET);
- return bRet;
- }
- //! Reads from a memory "lump" that contains a .pcx
- ILboolean ilLoadL_PCX(const void *Lump, ILuint Size)
- {
- iSetInputLump(Lump, Size);
- return iLoadPcxInternal();
- }
- // Internal function used to load the .pcx.
- ILboolean iLoadPcxInternal()
- {
- PCXHEAD Header;
- ILboolean bPcx = IL_FALSE;
- if (iCurImage == NULL) {
- ilSetError(IL_ILLEGAL_OPERATION);
- return bPcx;
- }
- if (!iGetPcxHead(&Header))
- return IL_FALSE;
- if (!iCheckPcx(&Header)) {
- ilSetError(IL_INVALID_FILE_HEADER);
- return IL_FALSE;
- }
- bPcx = iUncompressPcx(&Header);
- if (!bPcx)
- return IL_FALSE;
- return ilFixImage();
- }
- // Internal function to uncompress the .pcx (all .pcx files are rle compressed)
- ILboolean iUncompressPcx(PCXHEAD *Header)
- {
- //changed decompression loop 2003-09-01
- //From the pcx spec: "There should always
- //be a decoding break at the end of each scan line.
- //But there will not be a decoding break at the end of
- //each plane within each scan line."
- //This is now handled correctly (hopefully ;) )
- ILubyte ByteHead, Colour, *ScanLine /* For all planes */;
- ILuint ScanLineSize;
- ILuint c, i, x, y;
- if (Header->Bpp < 8) {
- /*ilSetError(IL_FORMAT_NOT_SUPPORTED);
- return IL_FALSE;*/
- return iUncompressSmall(Header);
- }
- if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL))
- return IL_FALSE;
- iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
- switch (iCurImage->Bpp)
- {
- case 1:
- iCurImage->Format = IL_COLOUR_INDEX;
- iCurImage->Pal.PalType = IL_PAL_RGB24;
- iCurImage->Pal.PalSize = 256 * 3; // Need to find out for sure...
- iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
- if (iCurImage->Pal.Palette == NULL) {
- return IL_FALSE;
- }
- break;
- //case 2: // No 16-bit images in the pcx format!
- case 3:
- iCurImage->Format = IL_RGB;
- iCurImage->Pal.Palette = NULL;
- iCurImage->Pal.PalSize = 0;
- iCurImage->Pal.PalType = IL_PAL_NONE;
- break;
- case 4:
- iCurImage->Format = IL_RGBA;
- iCurImage->Pal.Palette = NULL;
- iCurImage->Pal.PalSize = 0;
- iCurImage->Pal.PalType = IL_PAL_NONE;
- break;
- default:
- ilSetError(IL_ILLEGAL_FILE_VALUE);
- return IL_FALSE;
- }
- ScanLineSize = iCurImage->Bpp*Header->Bps;
- ScanLine = (ILubyte*)ialloc(ScanLineSize);
- if (ScanLine == NULL) {
- return IL_FALSE;
- }
- //changed 2003-09-01
- //having the decoding code twice is error-prone,
- //so I made iUnCache() smart enough to grasp
- //if iPreCache() wasn't called and call it
- //anyways.
- if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
- iPreCache(iCurImage->SizeOfData / 4);
- for (y = 0; y < iCurImage->Height; y++) {
- x = 0;
- //read scanline
- while (x < ScanLineSize) {
- if (iread(&ByteHead, 1, 1) != 1) {
- iUnCache();
- goto file_read_error;
- }
- if ((ByteHead & 0xC0) == 0xC0) {
- ByteHead &= 0x3F;
- if (iread(&Colour, 1, 1) != 1) {
- iUnCache();
- goto file_read_error;
- }
- if (x + ByteHead > ScanLineSize) {
- iUnCache();
- goto file_read_error;
- }
- for (i = 0; i < ByteHead; i++) {
- ScanLine[x++] = Colour;
- }
- }
- else {
- ScanLine[x++] = ByteHead;
- }
- }
- //convert plane-separated scanline into index, rgb or rgba pixels.
- //there might be a padding byte at the end of each scanline...
- for (x = 0; x < iCurImage->Width; x++) {
- for(c = 0; c < iCurImage->Bpp; c++) {
- iCurImage->Data[y * iCurImage->Bps + x * iCurImage->Bpp + c] =
- ScanLine[x + c * Header->Bps];
- }
- }
- }
- iUnCache();
- // Read in the palette
- if (Header->Version == 5 && iCurImage->Bpp == 1) {
- x = itell();
- if (iread(&ByteHead, 1, 1) == 0) { // If true, assume that we have a luminance image.
- ilGetError(); // Get rid of the IL_FILE_READ_ERROR.
- iCurImage->Format = IL_LUMINANCE;
- if (iCurImage->Pal.Palette)
- ifree(iCurImage->Pal.Palette);
- iCurImage->Pal.PalSize = 0;
- iCurImage->Pal.PalType = IL_PAL_NONE;
- }
- else {
- if (ByteHead != 12) // Some Quake2 .pcx files don't have this byte for some reason.
- iseek(-1, IL_SEEK_CUR);
- if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize)
- goto file_read_error;
- }
- }
- ifree(ScanLine);
- return IL_TRUE;
- file_read_error:
- ifree(ScanLine);
- //added 2003-09-01
- ilSetError(IL_FILE_READ_ERROR);
- return IL_FALSE;
- }
- ILboolean iUncompressSmall(PCXHEAD *Header)
- {
- ILuint i = 0, j, k, c, d, x, y, Bps;
- ILubyte HeadByte, Colour, Data = 0, *ScanLine;
- if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) {
- return IL_FALSE;
- }
- iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
- switch (Header->NumPlanes)
- {
- case 1:
- iCurImage->Format = IL_LUMINANCE;
- break;
- case 4:
- iCurImage->Format = IL_COLOUR_INDEX;
- break;
- default:
- ilSetError(IL_ILLEGAL_FILE_VALUE);
- return IL_FALSE;
- }
- if (Header->NumPlanes == 1 && Header->Bpp == 1) {
- for (j = 0; j < iCurImage->Height; j++) {
- i = 0; //number of written pixels
- while (i < iCurImage->Width) {
- if (iread(&HeadByte, 1, 1) != 1)
- return IL_FALSE;
- if (HeadByte >= 192) {
- HeadByte -= 192;
- if (iread(&Data, 1, 1) != 1)
- return IL_FALSE;
- for (c = 0; c < HeadByte; c++) {
- k = 128;
- for (d = 0; d < 8 && i < iCurImage->Width; d++) {
- iCurImage->Data[j * iCurImage->Width + i++] = ((Data & k) != 0 ? 255 : 0);
- k >>= 1;
- }
- }
- }
- else {
- k = 128;
- for (c = 0; c < 8 && i < iCurImage->Width; c++) {
- iCurImage->Data[j * iCurImage->Width + i++] = ((HeadByte & k) != 0 ? 255 : 0);
- k >>= 1;
- }
- }
- }
- //if(Data != 0)
- //changed 2003-09-01:
- //There has to be an even number of bytes per line in a pcx.
- //One byte can hold up to 8 bits, so Width/8 bytes
- //are needed to hold a 1 bit per pixel image line.
- //If Width/8 is even no padding is needed,
- //one pad byte has to be read otherwise.
- //(let's hope the above is true ;-))
- if(!((iCurImage->Width >> 3) & 0x1))
- igetc(); // Skip pad byte
- }
- }
- else if (Header->NumPlanes == 4 && Header->Bpp == 1){ // 4-bit images
- //changed decoding 2003-09-10 (was buggy)...could need a speedup
- Bps = Header->Bps * Header->NumPlanes * 8;
- iCurImage->Pal.Palette = (ILubyte*)ialloc(16 * 3); // Size of palette always (48 bytes).
- ScanLine = (ILubyte*)ialloc(Bps);
- if (iCurImage->Pal.Palette == NULL || ScanLine == NULL) {
- ifree(ScanLine);
- ifree(iCurImage->Pal.Palette);
- return IL_FALSE;
- }
- memcpy(iCurImage->Pal.Palette, Header->ColMap, 16 * 3);
- iCurImage->Pal.PalSize = 16 * 3;
- iCurImage->Pal.PalType = IL_PAL_RGB24;
- memset(iCurImage->Data, 0, iCurImage->SizeOfData);
- if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
- iPreCache(iCurImage->SizeOfData / 4);
- for (y = 0; y < iCurImage->Height; y++) {
- x = 0;
- while (x < Bps) {
- if (iread(&HeadByte, 1, 1) != 1) {
- iUnCache();
- ifree(ScanLine);
- return IL_FALSE;
- }
- if ((HeadByte & 0xC0) == 0xC0) {
- HeadByte &= 0x3F;
- if (iread(&Colour, 1, 1) != 1) {
- iUnCache();
- ifree(ScanLine);
- return IL_FALSE;
- }
- for (i = 0; i < HeadByte; i++) {
- k = 128;
- for (j = 0; j < 8 && x < Bps; j++) {
- ScanLine[x++] = (Colour & k)?1:0;
- k >>= 1;
- }
- }
- }
- else {
- k = 128;
- for (j = 0; j < 8 && x < Bps; j++) {
- ScanLine[x++] = (HeadByte & k)?1:0;
- k >>= 1;
- }
- }
- }
- for (x = 0; x < iCurImage->Width; x++) { // 'Cleverly' ignores the pad bytes. ;)
- for(c = 0; c < Header->NumPlanes; c++)
- iCurImage->Data[y * iCurImage->Width + x] |= ScanLine[x + c*Header->Bps*8] << c;
- }
- }
- iUnCache();
- ifree(ScanLine);
- }
- else {
- ilSetError(IL_FORMAT_NOT_SUPPORTED);
- return IL_FALSE;
- }
- return IL_TRUE;
- }
- //! Writes a .pcx file
- ILboolean ilSave_PCX(const ILstring FileName)
- {
- ILHANDLE PcxFile;
- ILuint PcxSize;
- if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
- if (iFileExists(FileName)) {
- ilSetError(IL_FILE_ALREADY_EXISTS);
- return IL_FALSE;
- }
- }
- PcxFile = iopenw(FileName);
- if (PcxFile == NULL) {
- ilSetError(IL_COULD_NOT_OPEN_FILE);
- return IL_FALSE;
- }
- PcxSize = ilSaveF_PCX(PcxFile);
- iclosew(PcxFile);
- if (PcxSize == 0)
- return IL_FALSE;
- return IL_TRUE;
- }
- //! Writes a .pcx to an already-opened file
- ILuint ilSaveF_PCX(ILHANDLE File)
- {
- ILuint Pos;
- iSetOutputFile(File);
- Pos = itellw();
- if (iSavePcxInternal() == IL_FALSE)
- return 0; // Error occurred
- return itellw() - Pos; // Return the number of bytes written.
- }
- //! Writes a .pcx to a memory "lump"
- ILuint ilSaveL_PCX(void *Lump, ILuint Size)
- {
- ILuint Pos;
- iSetOutputLump(Lump, Size);
- Pos = itellw();
- if (iSavePcxInternal() == IL_FALSE)
- return 0; // Error occurred
- return itellw() - Pos; // Return the number of bytes written.
- }
- // Internal function used to save the .pcx.
- ILboolean iSavePcxInternal()
- {
- ILuint i, c, PalSize;
- ILpal *TempPal;
- ILimage *TempImage = iCurImage;
- ILubyte *TempData;
- if (iCurImage == NULL) {
- ilSetError(IL_ILLEGAL_OPERATION);
- return IL_FALSE;
- }
- switch (iCurImage->Format)
- {
- case IL_LUMINANCE:
- TempImage = iConvertImage(iCurImage, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE);
- if (TempImage == NULL)
- return IL_FALSE;
- break;
- case IL_BGR:
- TempImage = iConvertImage(iCurImage, IL_RGB, IL_UNSIGNED_BYTE);
- if (TempImage == NULL)
- return IL_FALSE;
- break;
- case IL_BGRA:
- TempImage = iConvertImage(iCurImage, IL_RGBA, IL_UNSIGNED_BYTE);
- if (TempImage == NULL)
- return IL_FALSE;
- break;
- default:
- if (iCurImage->Bpc > 1) {
- TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE);
- if (TempImage == NULL)
- return IL_FALSE;
- }
- }
- if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) {
- TempData = iGetFlipped(TempImage);
- if (TempData == NULL) {
- if (TempImage != iCurImage) {
- ilCloseImage(TempImage);
- }
- return IL_FALSE;
- }
- }
- else {
- TempData = TempImage->Data;
- }
- iputc(0xA); // Manufacturer - always 10
- iputc(0x5); // Version Number - always 5
- iputc(0x1); // Encoding - always 1
- iputc(0x8); // Bits per channel
- SaveLittleUShort(0); // X Minimum
- SaveLittleUShort(0); // Y Minimum
- SaveLittleUShort((ILushort)(iCurImage->Width - 1));
- SaveLittleUShort((ILushort)(iCurImage->Height - 1));
- SaveLittleUShort(0);
- SaveLittleUShort(0);
- // Useless palette info?
- for (i = 0; i < 48; i++) {
- iputc(0);
- }
- iputc(0x0); // Reserved - always 0
- iputc(iCurImage->Bpp); // Number of planes - only 1 is supported right now
- SaveLittleUShort((ILushort)(iCurImage->Width & 1 ? iCurImage->Width + 1 : iCurImage->Width)); // Bps
- SaveLittleUShort(0x1); // Palette type - ignored?
- // Mainly filler info
- for (i = 0; i < 58; i++) {
- iputc(0x0);
- }
- // Output data
- for (i = 0; i < TempImage->Height; i++) {
- for (c = 0; c < TempImage->Bpp; c++) {
- encLine(TempData + TempImage->Bps * i + c, TempImage->Width, (ILubyte)(TempImage->Bpp - 1));
- }
- }
- // Automatically assuming we have a palette...dangerous!
- // Also assuming 3 bpp palette
- iputc(0xC); // Pad byte must have this value
- // If the current image has a palette, take care of it
- if (TempImage->Format == IL_COLOUR_INDEX) {
- // If the palette in .pcx format, write it directly
- if (TempImage->Pal.PalType == IL_PAL_RGB24) {
- iwrite(TempImage->Pal.Palette, 1, TempImage->Pal.PalSize);
- }
- else {
- TempPal = iConvertPal(&TempImage->Pal, IL_PAL_RGB24);
- if (TempPal == NULL) {
- if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
- ifree(TempData);
- if (TempImage != iCurImage)
- ilCloseImage(TempImage);
- return IL_FALSE;
- }
- iwrite(TempPal->Palette, 1, TempPal->PalSize);
- ifree(TempPal->Palette);
- ifree(TempPal);
- }
- }
- // If the palette is not all 256 colours, we have to pad it.
- PalSize = 768 - iCurImage->Pal.PalSize;
- for (i = 0; i < PalSize; i++) {
- iputc(0x0);
- }
- if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
- ifree(TempData);
- if (TempImage != iCurImage)
- ilCloseImage(TempImage);
- return IL_TRUE;
- }
- // Routine used from ZSoft's pcx documentation
- ILuint encput(ILubyte byt, ILubyte cnt)
- {
- if (cnt) {
- if ((cnt == 1) && (0xC0 != (0xC0 & byt))) {
- if (IL_EOF == iputc(byt))
- return(0); /* disk write error (probably full) */
- return(1);
- }
- else {
- if (IL_EOF == iputc((ILubyte)((ILuint)0xC0 | cnt)))
- return (0); /* disk write error */
- if (IL_EOF == iputc(byt))
- return (0); /* disk write error */
- return (2);
- }
- }
- return (0);
- }
- // This subroutine encodes one scanline and writes it to a file.
- // It returns number of bytes written into outBuff, 0 if failed.
- ILuint encLine(ILubyte *inBuff, ILint inLen, ILubyte Stride)
- {
- ILubyte _this, last;
- ILint srcIndex, i;
- ILint total;
- ILubyte runCount; // max single runlength is 63
- total = 0;
- runCount = 1;
- last = *(inBuff);
- // Find the pixel dimensions of the image by calculating
- //[XSIZE = Xmax - Xmin + 1] and [YSIZE = Ymax - Ymin + 1].
- //Then calculate how many bytes are in a "run"
- for (srcIndex = 1; srcIndex < inLen; srcIndex++) {
- inBuff += Stride;
- _this = *(++inBuff);
- if (_this == last) { // There is a "run" in the data, encode it
- runCount++;
- if (runCount == 63) {
- if (! (i = encput(last, runCount)))
- return (0);
- total += i;
- runCount = 0;
- }
- }
- else { // No "run" - _this != last
- if (runCount) {
- if (! (i = encput(last, runCount)))
- return(0);
- total += i;
- }
- last = _this;
- runCount = 1;
- }
- } // endloop
- if (runCount) { // finish up
- if (! (i = encput(last, runCount)))
- return (0);
- if (inLen % 2)
- iputc(0);
- return (total + i);
- }
- else {
- if (inLen % 2)
- iputc(0);
- }
- return (total);
- }
- #endif//IL_NO_PCX