[95] | 1 | /*
|
---|
| 2 | * File: ximapcx.cpp
|
---|
| 3 | * Purpose: Platform Independent PCX Image Class Loader and Writer
|
---|
| 4 | * 05/Jan/2002 Davide Pizzolato - www.xdp.it
|
---|
| 5 | * CxImage version 6.0.0 02/Feb/2008
|
---|
| 6 | *
|
---|
| 7 | * based on ppmtopcx.c - convert a portable pixmap to PCX
|
---|
| 8 | * Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
---|
| 9 | * based on ppmtopcx.c by Michael Davidson
|
---|
| 10 | */
|
---|
| 11 |
|
---|
| 12 | #include "ximapcx.h"
|
---|
| 13 |
|
---|
| 14 | #if CXIMAGE_SUPPORT_PCX
|
---|
| 15 |
|
---|
| 16 | #include "xmemfile.h"
|
---|
| 17 |
|
---|
| 18 | #define PCX_MAGIC 0X0A // PCX magic number
|
---|
| 19 | #define PCX_256_COLORS 0X0C // magic number for 256 colors
|
---|
| 20 | #define PCX_HDR_SIZE 128 // size of PCX header
|
---|
| 21 | #define PCX_MAXCOLORS 256
|
---|
| 22 | #define PCX_MAXPLANES 4
|
---|
| 23 | #define PCX_MAXVAL 255
|
---|
| 24 |
|
---|
| 25 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 26 | #if CXIMAGE_SUPPORT_DECODE
|
---|
| 27 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 28 | bool CxImagePCX::Decode(CxFile *hFile)
|
---|
| 29 | {
|
---|
| 30 | if (hFile == NULL) return false;
|
---|
| 31 |
|
---|
| 32 | PCXHEADER pcxHeader;
|
---|
| 33 | int i, x, y, y2, nbytes, count, Height, Width;
|
---|
| 34 | BYTE c, ColorMap[PCX_MAXCOLORS][3];
|
---|
| 35 | BYTE *pcximage = NULL, *lpHead1 = NULL, *lpHead2 = NULL;
|
---|
| 36 | BYTE *pcxplanes, *pcxpixels;
|
---|
| 37 |
|
---|
| 38 | cx_try
|
---|
| 39 | {
|
---|
| 40 | if (hFile->Read(&pcxHeader,sizeof(PCXHEADER),1)==0) cx_throw("Can't read PCX image");
|
---|
| 41 |
|
---|
| 42 | PCX_toh(&pcxHeader);
|
---|
| 43 |
|
---|
| 44 | if (pcxHeader.Manufacturer != PCX_MAGIC) cx_throw("Error: Not a PCX file");
|
---|
| 45 | // Check for PCX run length encoding
|
---|
| 46 | if (pcxHeader.Encoding != 1) cx_throw("PCX file has unknown encoding scheme");
|
---|
| 47 |
|
---|
| 48 | Width = (pcxHeader.Xmax - pcxHeader.Xmin) + 1;
|
---|
| 49 | Height = (pcxHeader.Ymax - pcxHeader.Ymin) + 1;
|
---|
| 50 | info.xDPI = pcxHeader.Hres;
|
---|
| 51 | info.yDPI = pcxHeader.Vres;
|
---|
| 52 |
|
---|
| 53 | if (info.nEscape == -1){
|
---|
| 54 | head.biWidth = Width;
|
---|
| 55 | head.biHeight= Height;
|
---|
| 56 | info.dwType = CXIMAGE_FORMAT_PCX;
|
---|
| 57 | return true;
|
---|
| 58 | }
|
---|
| 59 |
|
---|
| 60 | // Check that we can handle this image format
|
---|
| 61 | if (pcxHeader.ColorPlanes > 4)
|
---|
| 62 | cx_throw("Can't handle image with more than 4 planes");
|
---|
| 63 |
|
---|
| 64 | // Create the image
|
---|
| 65 | if (pcxHeader.ColorPlanes >= 3 && pcxHeader.BitsPerPixel == 8){
|
---|
| 66 | Create (Width, Height, 24, CXIMAGE_FORMAT_PCX);
|
---|
| 67 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
| 68 | if (pcxHeader.ColorPlanes==4) AlphaCreate();
|
---|
| 69 | #endif //CXIMAGE_SUPPORT_ALPHA
|
---|
| 70 | } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 1)
|
---|
| 71 | Create (Width, Height, 4, CXIMAGE_FORMAT_PCX);
|
---|
| 72 | else
|
---|
| 73 | Create (Width, Height, pcxHeader.BitsPerPixel, CXIMAGE_FORMAT_PCX);
|
---|
| 74 |
|
---|
| 75 | if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
|
---|
| 76 |
|
---|
| 77 | //Read the image and check if it's ok
|
---|
| 78 | nbytes = pcxHeader.BytesPerLine * pcxHeader.ColorPlanes * Height;
|
---|
| 79 | lpHead1 = pcximage = (BYTE*)malloc(nbytes);
|
---|
| 80 | while (nbytes > 0){
|
---|
| 81 | if (hFile == NULL || hFile->Eof()) cx_throw("corrupted PCX");
|
---|
| 82 |
|
---|
| 83 | hFile->Read(&c,1,1);
|
---|
| 84 | if ((c & 0XC0) != 0XC0){ // Repeated group
|
---|
| 85 | *pcximage++ = c;
|
---|
| 86 | --nbytes;
|
---|
| 87 | continue;
|
---|
| 88 | }
|
---|
| 89 | count = c & 0X3F; // extract count
|
---|
| 90 | hFile->Read(&c,1,1);
|
---|
| 91 | if (count > nbytes) cx_throw("repeat count spans end of image");
|
---|
| 92 |
|
---|
| 93 | nbytes -= count;
|
---|
| 94 | while (--count >=0) *pcximage++ = c;
|
---|
| 95 | }
|
---|
| 96 | pcximage = lpHead1;
|
---|
| 97 |
|
---|
| 98 | //store the palette
|
---|
| 99 | for (i = 0; i < 16; i++){
|
---|
| 100 | ColorMap[i][0] = pcxHeader.ColorMap[i][0];
|
---|
| 101 | ColorMap[i][1] = pcxHeader.ColorMap[i][1];
|
---|
| 102 | ColorMap[i][2] = pcxHeader.ColorMap[i][2];
|
---|
| 103 | }
|
---|
| 104 | if (pcxHeader.BitsPerPixel == 8 && pcxHeader.ColorPlanes == 1){
|
---|
| 105 | hFile->Read(&c,1,1);
|
---|
| 106 | if (c != PCX_256_COLORS) cx_throw("bad color map signature");
|
---|
| 107 |
|
---|
| 108 | for (i = 0; i < PCX_MAXCOLORS; i++){
|
---|
| 109 | hFile->Read(&ColorMap[i][0],1,1);
|
---|
| 110 | hFile->Read(&ColorMap[i][1],1,1);
|
---|
| 111 | hFile->Read(&ColorMap[i][2],1,1);
|
---|
| 112 | }
|
---|
| 113 | }
|
---|
| 114 | if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){
|
---|
| 115 | ColorMap[0][0] = ColorMap[0][1] = ColorMap[0][2] = 0;
|
---|
| 116 | ColorMap[1][0] = ColorMap[1][1] = ColorMap[1][2] = 255;
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | for (DWORD idx=0; idx<head.biClrUsed; idx++) SetPaletteColor((BYTE)idx,ColorMap[idx][0],ColorMap[idx][1],ColorMap[idx][2]);
|
---|
| 120 |
|
---|
| 121 | lpHead2 = pcxpixels = (BYTE *)malloc(Width + pcxHeader.BytesPerLine * 8);
|
---|
| 122 | // Convert the image
|
---|
| 123 | for (y = 0; y < Height; y++){
|
---|
| 124 |
|
---|
| 125 | if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
|
---|
| 126 |
|
---|
| 127 | y2=Height-1-y;
|
---|
| 128 | pcxpixels = lpHead2;
|
---|
| 129 | pcxplanes = pcximage + (y * pcxHeader.BytesPerLine * pcxHeader.ColorPlanes);
|
---|
| 130 |
|
---|
| 131 | if (pcxHeader.ColorPlanes == 3 && pcxHeader.BitsPerPixel == 8){
|
---|
| 132 | // Deal with 24 bit color image
|
---|
| 133 | for (x = 0; x < Width; x++){
|
---|
| 134 | SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x]));
|
---|
| 135 | }
|
---|
| 136 | continue;
|
---|
| 137 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
| 138 | } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 8){
|
---|
| 139 | for (x = 0; x < Width; x++){
|
---|
| 140 | SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x]));
|
---|
| 141 | AlphaSet(x,y2,pcxplanes[3*pcxHeader.BytesPerLine + x]);
|
---|
| 142 | }
|
---|
| 143 | continue;
|
---|
| 144 | #endif //CXIMAGE_SUPPORT_ALPHA
|
---|
| 145 | } else if (pcxHeader.ColorPlanes == 1) {
|
---|
| 146 | if (!PCX_UnpackPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel)){
|
---|
| 147 | cx_throw("PCX_UnpackPixels: Can't handle packed pixels with more than 1 plane");
|
---|
| 148 | }
|
---|
| 149 | } else {
|
---|
| 150 | if (!PCX_PlanesToPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel)){
|
---|
| 151 | cx_throw("PCX_PlanesToPixels: more than 4 planes or more than 1 bit per pixel");
|
---|
| 152 | }
|
---|
| 153 | }
|
---|
| 154 | for (x = 0; x < Width; x++) SetPixelIndex(x,y2,pcxpixels[x]);
|
---|
| 155 | }
|
---|
| 156 |
|
---|
| 157 | } cx_catch {
|
---|
| 158 | if (strcmp(message,"")) strncpy(info.szLastError,message,255);
|
---|
| 159 | if (lpHead1){ free(lpHead1); lpHead1 = NULL; }
|
---|
| 160 | if (lpHead2){ free(lpHead2); lpHead2 = NULL; }
|
---|
| 161 | return false;
|
---|
| 162 | }
|
---|
| 163 | if (lpHead1){ free(lpHead1); lpHead1 = NULL; }
|
---|
| 164 | if (lpHead2){ free(lpHead2); lpHead2 = NULL; }
|
---|
| 165 | return true;
|
---|
| 166 | }
|
---|
| 167 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 168 | #endif //CXIMAGE_SUPPORT_DECODE
|
---|
| 169 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 170 | #if CXIMAGE_SUPPORT_ENCODE
|
---|
| 171 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 172 | bool CxImagePCX::Encode(CxFile * hFile)
|
---|
| 173 | {
|
---|
| 174 | if (EncodeSafeCheck(hFile)) return false;
|
---|
| 175 |
|
---|
| 176 | cx_try
|
---|
| 177 | {
|
---|
| 178 | PCXHEADER pcxHeader;
|
---|
| 179 | memset(&pcxHeader,0,sizeof(pcxHeader));
|
---|
| 180 | pcxHeader.Manufacturer = PCX_MAGIC;
|
---|
| 181 | pcxHeader.Version = 5;
|
---|
| 182 | pcxHeader.Encoding = 1;
|
---|
| 183 | pcxHeader.Xmin = 0;
|
---|
| 184 | pcxHeader.Ymin = 0;
|
---|
| 185 | pcxHeader.Xmax = (WORD)head.biWidth-1;
|
---|
| 186 | pcxHeader.Ymax = (WORD)head.biHeight-1;
|
---|
| 187 | pcxHeader.Hres = (WORD)info.xDPI;
|
---|
| 188 | pcxHeader.Vres = (WORD)info.yDPI;
|
---|
| 189 | pcxHeader.Reserved = 0;
|
---|
| 190 | pcxHeader.PaletteType = head.biClrUsed==0;
|
---|
| 191 |
|
---|
| 192 | switch(head.biBitCount){
|
---|
| 193 | case 24:
|
---|
| 194 | case 8:
|
---|
| 195 | {
|
---|
| 196 | pcxHeader.BitsPerPixel = 8;
|
---|
| 197 | pcxHeader.ColorPlanes = head.biClrUsed==0 ? 3 : 1;
|
---|
| 198 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
| 199 | if (AlphaIsValid() && head.biClrUsed==0) pcxHeader.ColorPlanes =4;
|
---|
| 200 | #endif //CXIMAGE_SUPPORT_ALPHA
|
---|
| 201 | pcxHeader.BytesPerLine = (WORD)head.biWidth;
|
---|
| 202 | break;
|
---|
| 203 | }
|
---|
| 204 | default: //(4 1)
|
---|
| 205 | pcxHeader.BitsPerPixel = 1;
|
---|
| 206 | pcxHeader.ColorPlanes = head.biClrUsed==16 ? 4 : 1;
|
---|
| 207 | pcxHeader.BytesPerLine = (WORD)((head.biWidth * pcxHeader.BitsPerPixel + 7)>>3);
|
---|
| 208 | }
|
---|
| 209 |
|
---|
| 210 | if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){
|
---|
| 211 | pcxHeader.ColorMap[0][0] = pcxHeader.ColorMap[0][1] = pcxHeader.ColorMap[0][2] = 0;
|
---|
| 212 | pcxHeader.ColorMap[1][0] = pcxHeader.ColorMap[1][1] = pcxHeader.ColorMap[1][2] = 255;
|
---|
| 213 | }
|
---|
| 214 | if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 4){
|
---|
| 215 | RGBQUAD c;
|
---|
| 216 | for (int i = 0; i < 16; i++){
|
---|
| 217 | c=GetPaletteColor(i);
|
---|
| 218 | pcxHeader.ColorMap[i][0] = c.rgbRed;
|
---|
| 219 | pcxHeader.ColorMap[i][1] = c.rgbGreen;
|
---|
| 220 | pcxHeader.ColorMap[i][2] = c.rgbBlue;
|
---|
| 221 | }
|
---|
| 222 | }
|
---|
| 223 |
|
---|
| 224 | pcxHeader.BytesPerLine = (pcxHeader.BytesPerLine + 1)&(~1);
|
---|
| 225 |
|
---|
| 226 | PCX_toh(&pcxHeader);
|
---|
| 227 | if (hFile->Write(&pcxHeader, sizeof(pcxHeader), 1) == 0 )
|
---|
| 228 | cx_throw("cannot write PCX header");
|
---|
| 229 | PCX_toh(&pcxHeader);
|
---|
| 230 |
|
---|
| 231 | CxMemFile buffer;
|
---|
| 232 | buffer.Open();
|
---|
| 233 |
|
---|
| 234 | BYTE c,n;
|
---|
| 235 | long x,y;
|
---|
| 236 | if (head.biClrUsed==0){
|
---|
| 237 | for (y = head.biHeight-1; y >=0 ; y--){
|
---|
| 238 | for (int p=0; p<pcxHeader.ColorPlanes; p++){
|
---|
| 239 | c=n=0;
|
---|
| 240 | for (x = 0; x<head.biWidth; x++){
|
---|
| 241 | if (p==0)
|
---|
| 242 | PCX_PackPixels(BlindGetPixelColor(x,y).rgbRed,c,n,buffer);
|
---|
| 243 | else if (p==1)
|
---|
| 244 | PCX_PackPixels(BlindGetPixelColor(x,y).rgbGreen,c,n,buffer);
|
---|
| 245 | else if (p==2)
|
---|
| 246 | PCX_PackPixels(BlindGetPixelColor(x,y).rgbBlue,c,n,buffer);
|
---|
| 247 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
| 248 | else if (p==3)
|
---|
| 249 | PCX_PackPixels(BlindAlphaGet(x,y),c,n,buffer);
|
---|
| 250 | #endif //CXIMAGE_SUPPORT_ALPHA
|
---|
| 251 | }
|
---|
| 252 | PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer);
|
---|
| 253 | }
|
---|
| 254 | }
|
---|
| 255 |
|
---|
| 256 | hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1);
|
---|
| 257 |
|
---|
| 258 | } else if (head.biBitCount==8) {
|
---|
| 259 |
|
---|
| 260 | for (y = head.biHeight-1; y >=0 ; y--){
|
---|
| 261 | c=n=0;
|
---|
| 262 | for (x = 0; x<head.biWidth; x++){
|
---|
| 263 | PCX_PackPixels(GetPixelIndex(x,y),c,n,buffer);
|
---|
| 264 | }
|
---|
| 265 | PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer);
|
---|
| 266 | }
|
---|
| 267 |
|
---|
| 268 | hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1);
|
---|
| 269 |
|
---|
| 270 | if (head.biBitCount == 8){
|
---|
| 271 | hFile->PutC(0x0C);
|
---|
| 272 | BYTE* pal = (BYTE*)malloc(768);
|
---|
| 273 | RGBQUAD c;
|
---|
| 274 | for (int i=0;i<256;i++){
|
---|
| 275 | c=GetPaletteColor(i);
|
---|
| 276 | pal[3*i+0] = c.rgbRed;
|
---|
| 277 | pal[3*i+1] = c.rgbGreen;
|
---|
| 278 | pal[3*i+2] = c.rgbBlue;
|
---|
| 279 | }
|
---|
| 280 | hFile->Write(pal,768,1);
|
---|
| 281 | free(pal);
|
---|
| 282 | }
|
---|
| 283 | } else { //(head.biBitCount==4) || (head.biBitCount==1)
|
---|
| 284 |
|
---|
| 285 | RGBQUAD *rgb = GetPalette();
|
---|
| 286 | bool binvert = false;
|
---|
| 287 | if (CompareColors(&rgb[0],&rgb[1])>0) binvert=(head.biBitCount==1);
|
---|
| 288 |
|
---|
| 289 | BYTE* plane = (BYTE*)malloc(pcxHeader.BytesPerLine);
|
---|
| 290 | BYTE* raw = (BYTE*)malloc(head.biWidth);
|
---|
| 291 |
|
---|
| 292 | for(y = head.biHeight-1; y >=0 ; y--) {
|
---|
| 293 |
|
---|
| 294 | for( x = 0; x < head.biWidth; x++) raw[x] = (BYTE)GetPixelIndex(x,y);
|
---|
| 295 |
|
---|
| 296 | if (binvert) for( x = 0; x < head.biWidth; x++) raw[x] = 1-raw[x];
|
---|
| 297 |
|
---|
| 298 | for( x = 0; x < pcxHeader.ColorPlanes; x++ ) {
|
---|
| 299 | PCX_PixelsToPlanes(raw, head.biWidth, plane, x);
|
---|
| 300 | PCX_PackPlanes(plane, pcxHeader.BytesPerLine, buffer);
|
---|
| 301 | }
|
---|
| 302 | }
|
---|
| 303 |
|
---|
| 304 | free(plane);
|
---|
| 305 | free(raw);
|
---|
| 306 |
|
---|
| 307 | hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1);
|
---|
| 308 |
|
---|
| 309 | }
|
---|
| 310 |
|
---|
| 311 | } cx_catch {
|
---|
| 312 | if (strcmp(message,"")) strncpy(info.szLastError,message,255);
|
---|
| 313 | return false;
|
---|
| 314 | }
|
---|
| 315 | return true;
|
---|
| 316 | }
|
---|
| 317 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 318 | #endif // CXIMAGE_SUPPORT_ENCODE
|
---|
| 319 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 320 | // Convert multi-plane format into 1 pixel per byte
|
---|
| 321 | // from unpacked file data bitplanes[] into pixel row pixels[]
|
---|
| 322 | // image Height rows, with each row having planes image planes each
|
---|
| 323 | // bytesperline bytes
|
---|
| 324 | bool CxImagePCX::PCX_PlanesToPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel)
|
---|
| 325 | {
|
---|
| 326 | int i, j, npixels;
|
---|
| 327 | BYTE * p;
|
---|
| 328 | if (planes > 4) return false;
|
---|
| 329 | if (bitsperpixel != 1) return false;
|
---|
| 330 |
|
---|
| 331 | // Clear the pixel buffer
|
---|
| 332 | npixels = (bytesperline * 8) / bitsperpixel;
|
---|
| 333 | p = pixels;
|
---|
| 334 | while (--npixels >= 0) *p++ = 0;
|
---|
| 335 |
|
---|
| 336 | // Do the format conversion
|
---|
| 337 | for (i = 0; i < planes; i++){
|
---|
| 338 | int pixbit, bits, mask;
|
---|
| 339 | p = pixels;
|
---|
| 340 | pixbit = (1 << i); // pixel bit for this plane
|
---|
| 341 | for (j = 0; j < bytesperline; j++){
|
---|
| 342 | bits = *bitplanes++;
|
---|
| 343 | for (mask = 0X80; mask != 0; mask >>= 1, p++)
|
---|
| 344 | if (bits & mask) *p |= pixbit;
|
---|
| 345 | }
|
---|
| 346 | }
|
---|
| 347 | return true;
|
---|
| 348 | }
|
---|
| 349 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 350 | // convert packed pixel format into 1 pixel per byte
|
---|
| 351 | // from unpacked file data bitplanes[] into pixel row pixels[]
|
---|
| 352 | // image Height rows, with each row having planes image planes each
|
---|
| 353 | // bytesperline bytes
|
---|
| 354 | bool CxImagePCX::PCX_UnpackPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel)
|
---|
| 355 | {
|
---|
| 356 | register int bits;
|
---|
| 357 | if (planes != 1) return false;
|
---|
| 358 |
|
---|
| 359 | if (bitsperpixel == 8){ // 8 bits/pixels, no unpacking needed
|
---|
| 360 | while (bytesperline-- > 0) *pixels++ = *bitplanes++;
|
---|
| 361 | } else if (bitsperpixel == 4){ // 4 bits/pixel, two pixels per byte
|
---|
| 362 | while (bytesperline-- > 0){
|
---|
| 363 | bits = *bitplanes++;
|
---|
| 364 | *pixels++ = (BYTE)((bits >> 4) & 0X0F);
|
---|
| 365 | *pixels++ = (BYTE)((bits) & 0X0F);
|
---|
| 366 | }
|
---|
| 367 | } else if (bitsperpixel == 2){ // 2 bits/pixel, four pixels per byte
|
---|
| 368 | while (bytesperline-- > 0){
|
---|
| 369 | bits = *bitplanes++;
|
---|
| 370 | *pixels++ = (BYTE)((bits >> 6) & 0X03);
|
---|
| 371 | *pixels++ = (BYTE)((bits >> 4) & 0X03);
|
---|
| 372 | *pixels++ = (BYTE)((bits >> 2) & 0X03);
|
---|
| 373 | *pixels++ = (BYTE)((bits) & 0X03);
|
---|
| 374 | }
|
---|
| 375 | } else if (bitsperpixel == 1){ // 1 bits/pixel, 8 pixels per byte
|
---|
| 376 | while (bytesperline-- > 0){
|
---|
| 377 | bits = *bitplanes++;
|
---|
| 378 | *pixels++ = ((bits & 0X80) != 0);
|
---|
| 379 | *pixels++ = ((bits & 0X40) != 0);
|
---|
| 380 | *pixels++ = ((bits & 0X20) != 0);
|
---|
| 381 | *pixels++ = ((bits & 0X10) != 0);
|
---|
| 382 | *pixels++ = ((bits & 0X08) != 0);
|
---|
| 383 | *pixels++ = ((bits & 0X04) != 0);
|
---|
| 384 | *pixels++ = ((bits & 0X02) != 0);
|
---|
| 385 | *pixels++ = ((bits & 0X01) != 0);
|
---|
| 386 | }
|
---|
| 387 | }
|
---|
| 388 | return true;
|
---|
| 389 | }
|
---|
| 390 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 391 | /* PCX_PackPixels(const long p,BYTE &c, BYTE &n, long &l, CxFile &f)
|
---|
| 392 | * p = current pixel (-1 ends the line -2 ends odd line)
|
---|
| 393 | * c = previous pixel
|
---|
| 394 | * n = number of consecutive pixels
|
---|
| 395 | */
|
---|
| 396 | void CxImagePCX::PCX_PackPixels(const long p,BYTE &c, BYTE &n, CxFile &f)
|
---|
| 397 | {
|
---|
| 398 | if (p!=c && n){
|
---|
| 399 | if (n==1 && c<0xC0){
|
---|
| 400 | f.PutC(c);
|
---|
| 401 | } else {
|
---|
| 402 | f.PutC(0xC0|n);
|
---|
| 403 | f.PutC(c);
|
---|
| 404 | }
|
---|
| 405 | n=0;
|
---|
| 406 | }
|
---|
| 407 | if (n==0x3F) {
|
---|
| 408 | f.PutC(0xFF);
|
---|
| 409 | f.PutC(c);
|
---|
| 410 | n=0;
|
---|
| 411 | }
|
---|
| 412 | if (p==-2) f.PutC(0);
|
---|
| 413 | c=(BYTE)p;
|
---|
| 414 | n++;
|
---|
| 415 | }
|
---|
| 416 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 417 | void CxImagePCX::PCX_PackPlanes(BYTE* buff, const long size, CxFile &f)
|
---|
| 418 | {
|
---|
| 419 | BYTE *start,*end;
|
---|
| 420 | BYTE c, previous, count;
|
---|
| 421 |
|
---|
| 422 | start = buff;
|
---|
| 423 | end = buff + size;
|
---|
| 424 | previous = *start++;
|
---|
| 425 | count = 1;
|
---|
| 426 |
|
---|
| 427 | while (start < end) {
|
---|
| 428 | c = *start++;
|
---|
| 429 | if (c == previous && count < 63) {
|
---|
| 430 | ++count;
|
---|
| 431 | continue;
|
---|
| 432 | }
|
---|
| 433 |
|
---|
| 434 | if (count > 1 || (previous & 0xc0) == 0xc0) {
|
---|
| 435 | f.PutC( count | 0xc0 );
|
---|
| 436 | }
|
---|
| 437 | f.PutC(previous);
|
---|
| 438 | previous = c;
|
---|
| 439 | count = 1;
|
---|
| 440 | }
|
---|
| 441 |
|
---|
| 442 | if (count > 1 || (previous & 0xc0) == 0xc0) {
|
---|
| 443 | count |= 0xc0;
|
---|
| 444 | f.PutC(count);
|
---|
| 445 | }
|
---|
| 446 | f.PutC(previous);
|
---|
| 447 | }
|
---|
| 448 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 449 | void CxImagePCX::PCX_PixelsToPlanes(BYTE* raw, long width, BYTE* buf, long plane)
|
---|
| 450 | {
|
---|
| 451 | int cbit, x, mask;
|
---|
| 452 | unsigned char *cp = buf-1;
|
---|
| 453 |
|
---|
| 454 | mask = 1 << plane;
|
---|
| 455 | cbit = -1;
|
---|
| 456 | for( x = 0; x < width; x++ ) {
|
---|
| 457 | if( cbit < 0 ) {
|
---|
| 458 | cbit = 7;
|
---|
| 459 | *++cp = 0;
|
---|
| 460 | }
|
---|
| 461 | if( raw[x] & mask )
|
---|
| 462 | *cp |= (1<<cbit);
|
---|
| 463 | --cbit;
|
---|
| 464 | }
|
---|
| 465 | }
|
---|
| 466 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 467 | void CxImagePCX::PCX_toh(PCXHEADER* p)
|
---|
| 468 | {
|
---|
| 469 | p->Xmin = ntohs(p->Xmin);
|
---|
| 470 | p->Ymin = ntohs(p->Ymin);
|
---|
| 471 | p->Xmax = ntohs(p->Xmax);
|
---|
| 472 | p->Ymax = ntohs(p->Ymax);
|
---|
| 473 | p->Hres = ntohs(p->Hres);
|
---|
| 474 | p->Vres = ntohs(p->Vres);
|
---|
| 475 | p->BytesPerLine = ntohs(p->BytesPerLine);
|
---|
| 476 | p->PaletteType = ntohs(p->PaletteType);
|
---|
| 477 | }
|
---|
| 478 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 479 | #endif // CXIMAGE_SUPPORT_PCX
|
---|