Coverage Report

Created: 2026-01-10 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeimage-svn/FreeImage/trunk/Source/FreeImage/PluginPCX.cpp
Line
Count
Source
1
// ==========================================================
2
// PCX Loader
3
//
4
// Design and implementation by
5
// - Floris van den Berg (flvdberg@wxs.nl)
6
// - Jani Kajala (janik@remedy.fi)
7
// - Markus Loibl (markus.loibl@epost.de)
8
// - Hervé Drolon (drolon@infonie.fr)
9
// - Juergen Riecker (j.riecker@gmx.de)
10
//
11
// This file is part of FreeImage 3
12
//
13
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
14
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
15
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
16
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
17
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
18
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
19
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
20
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
21
// THIS DISCLAIMER.
22
//
23
// Use at your own risk!
24
// ==========================================================
25
26
#include "FreeImage.h"
27
#include "Utilities.h"
28
29
// ----------------------------------------------------------
30
//   Constants + headers
31
// ----------------------------------------------------------
32
33
0
#define PCX_IO_BUF_SIZE 2048
34
35
// ----------------------------------------------------------
36
37
#ifdef _WIN32
38
#pragma pack(push, 1)
39
#else
40
#pragma pack(1)
41
#endif
42
43
/**
44
PCX header
45
*/
46
typedef struct tagPCXHEADER {
47
  BYTE  manufacturer;   // Magic number (0x0A = ZSoft Z)
48
  BYTE  version;      // Version  0 == 2.5
49
              //          2 == 2.8 with palette info
50
              //          3 == 2.8 without palette info
51
              //          5 == 3.0 with palette info
52
  BYTE  encoding;     // Encoding: 0 = uncompressed, 1 = PCX bIsRLE compressed
53
  BYTE  bpp;        // Bits per pixel per plane (only 1 or 8)
54
  WORD  window[4];    // left, upper, right,lower pixel coord.
55
  WORD  hdpi;       // Horizontal resolution
56
  WORD  vdpi;       // Vertical resolution
57
  BYTE  color_map[48];  // Colormap for 16-color images
58
  BYTE  reserved;
59
  BYTE  planes;     // Number of planes (1, 3 or 4)
60
  WORD  bytes_per_line; // Bytes per row (always even)
61
  WORD  palette_info;   // Palette information (1 = color or b&w; 2 = gray scale)
62
  WORD  h_screen_size;
63
  WORD  v_screen_size;
64
  BYTE  filler[54];   // Reserved filler
65
} PCXHEADER;
66
    
67
#ifdef _WIN32
68
#pragma pack(pop)
69
#else
70
#pragma pack()
71
#endif
72
73
// ==========================================================
74
// Internal functions
75
// ==========================================================
76
77
/**
78
Try to validate a PCX signature.
79
Note that a PCX file cannot be trusted by its signature. 
80
We use other information from the PCX header to improve the trust we have with this file.
81
@return Returns TRUE if PCX signature is OK, returns FALSE otherwise
82
*/
83
static BOOL 
84
12.2k
pcx_validate(FreeImageIO *io, fi_handle handle) {
85
12.2k
  BYTE pcx_signature = 0x0A;
86
12.2k
  BYTE signature[4] = { 0, 0, 0, 0 };
87
88
12.2k
  if(io->read_proc(&signature, 1, 4, handle) != 4) {
89
0
    return FALSE;
90
0
  }
91
  // magic number (0x0A = ZSoft Z)
92
12.2k
  if(signature[0] == pcx_signature) {
93
    // version
94
0
    if(signature[1] <= 5) {
95
      // encoding
96
0
      if((signature[2] == 0) || (signature[2] == 1)) {
97
        // bits per pixel per plane
98
0
        if((signature[3] == 1) || (signature[3] == 8)) {
99
0
          return TRUE;
100
0
        }
101
0
      }
102
0
    }
103
0
  }
104
105
12.2k
  return FALSE;
106
12.2k
}
107
108
/**
109
Read either run-length encoded or normal image data
110
111
THIS IS HOW RUNTIME LENGTH ENCODING WORKS IN PCX:
112
1) If the upper 2 bits of a byte are set, the lower 6 bits specify the count for the next byte
113
2) If the upper 2 bits of the byte are clear, the byte is actual data with a count of 1
114
115
Note that a scanline always has an even number of bytes
116
117
@param io FreeImage IO
118
@param handle FreeImage handle
119
@param buffer
120
@param length
121
@param bIsRLE
122
@param ReadBuf
123
@param ReadPos
124
@return
125
*/
126
static unsigned
127
0
readLine(FreeImageIO *io, fi_handle handle, BYTE *buffer, unsigned length, BOOL bIsRLE, BYTE * ReadBuf, int * ReadPos) {
128
0
  BYTE count = 0;
129
0
  BYTE value = 0;
130
0
  unsigned written = 0;
131
132
0
  if (bIsRLE) {
133
    // run-length encoded read
134
135
0
    while (length--) {
136
0
      if (count == 0) {
137
0
        if (*ReadPos >= PCX_IO_BUF_SIZE - 1 ) {
138
0
          if (*ReadPos == PCX_IO_BUF_SIZE - 1) {
139
            // we still have one BYTE, copy it to the start pos
140
0
            *ReadBuf = ReadBuf[PCX_IO_BUF_SIZE - 1];
141
0
            io->read_proc(ReadBuf + 1, 1, PCX_IO_BUF_SIZE - 1, handle);
142
0
          } else {
143
            // read the complete buffer
144
0
            io->read_proc(ReadBuf, 1, PCX_IO_BUF_SIZE, handle);
145
0
          }
146
147
0
          *ReadPos = 0;
148
0
        }
149
150
0
        value = *(ReadBuf + (*ReadPos)++);
151
152
0
        if ((value & 0xC0) == 0xC0) {
153
0
          count = value & 0x3F;
154
0
          value = *(ReadBuf + (*ReadPos)++);
155
0
        } else {
156
0
          count = 1;
157
0
        }
158
0
      }
159
160
0
      count--;
161
162
0
      *(buffer + written++) = value;
163
0
    }
164
165
0
  } else {
166
    // normal read
167
168
0
    written = io->read_proc(buffer, length, 1, handle);
169
0
  }
170
171
0
  return written;
172
0
}
173
174
#ifdef FREEIMAGE_BIGENDIAN
175
static void
176
SwapHeader(PCXHEADER *header) {
177
  SwapShort(&header->window[0]);
178
  SwapShort(&header->window[1]);
179
  SwapShort(&header->window[2]);
180
  SwapShort(&header->window[3]);
181
  SwapShort(&header->hdpi);
182
  SwapShort(&header->vdpi);
183
  SwapShort(&header->bytes_per_line);
184
  SwapShort(&header->palette_info);
185
  SwapShort(&header->h_screen_size);
186
  SwapShort(&header->v_screen_size);
187
}
188
#endif
189
190
// ==========================================================
191
// Plugin Interface
192
// ==========================================================
193
194
static int s_format_id;
195
196
// ==========================================================
197
// Plugin Implementation
198
// ==========================================================
199
200
/*!
201
    Returns the format string for the plugin. Each plugin,
202
  both internal in the DLL and external in a .fip file, must have
203
  a unique format string to be addressable.
204
*/
205
206
static const char * DLL_CALLCONV
207
2
Format() {
208
2
  return "PCX";
209
2
}
210
211
/*!
212
    Returns a description string for the plugin. Though a
213
  description is not necessary per-se,
214
  it is advised to return an unique string in order to tell the
215
  user what type of bitmaps this plugin will read and/or write.
216
*/
217
218
static const char * DLL_CALLCONV
219
0
Description() {
220
0
  return "Zsoft Paintbrush";
221
0
}
222
223
/*!
224
    Returns a comma separated list of file
225
  extensions indicating what files this plugin can open. The
226
  list, being used by FreeImage_GetFIFFromFilename, is usually
227
  used as a last resort in finding the type of the bitmap we
228
  are dealing with. Best is to check the first few bytes on
229
  the low-level bits level first and compare them with a known
230
  signature . If this fails, FreeImage_GetFIFFromFilename can be
231
  used.
232
*/
233
234
static const char * DLL_CALLCONV
235
0
Extension() {
236
0
  return "pcx";
237
0
}
238
239
/*!
240
    Returns an (optional) regular expression to help
241
  software identifying a bitmap type. The
242
  expression can be applied to the first few bytes (header) of
243
  the bitmap. FreeImage is not capable of processing regular expression itself,
244
  but FreeImageQt, the FreeImage Trolltech support library, can. If RegExpr
245
  returns NULL, FreeImageQt will automatically bypass Trolltech's regular
246
  expression support and use its internal functions to find the bitmap type.
247
*/
248
249
static const char * DLL_CALLCONV
250
0
RegExpr() {
251
0
  return NULL;
252
0
}
253
254
static const char * DLL_CALLCONV
255
0
MimeType() {
256
0
  return "image/x-pcx";
257
0
}
258
259
/*!
260
    Validates a bitmap by reading the first few bytes
261
  and comparing them with a known bitmap signature.
262
  TRUE is returned if the bytes match the signature, FALSE otherwise.
263
  The Validate function is used by using FreeImage_GetFileType.
264
  
265
  Note: a plugin can safely read data any data from the bitmap without seeking back
266
  to the original entry point; the entry point is stored prior to calling this
267
  function and restored after.
268
269
    Note: because of FreeImage's io redirection support, the header for the bitmap
270
  must be on the start of the bitmap or at least on a known part in the bitmap. It is
271
  forbidden to seek to the end of the bitmap or to a point relative to the end of a bitmap,
272
  because the end of the bitmap is not always known.
273
*/
274
275
static BOOL DLL_CALLCONV
276
12.2k
Validate(FreeImageIO *io, fi_handle handle) {
277
12.2k
  return pcx_validate(io, handle);
278
12.2k
}
279
280
/*!
281
    This function is used to 'ask' the plugin if it can write
282
  a bitmap in a certain bitdepth. Different bitmap types have different
283
  capabilities, for example not all formats allow writing in palettized mode.
284
  This function is there provide an uniform interface to the plugin's
285
  capabilities. SupportsExportDepth returns TRUE if the plugin support writing
286
  in the asked bitdepth, or FALSE if it doesn't. The function also
287
  returns FALSE if bitmap saving is not supported by the plugin at all.
288
*/
289
290
static BOOL DLL_CALLCONV
291
0
SupportsExportDepth(int depth) {
292
0
  return FALSE;
293
0
}
294
295
static BOOL DLL_CALLCONV 
296
0
SupportsExportType(FREE_IMAGE_TYPE type) {
297
0
  return FALSE;
298
0
}
299
300
static BOOL DLL_CALLCONV
301
0
SupportsNoPixels() {
302
0
  return TRUE;
303
0
}
304
305
// ----------------------------------------------------------
306
307
/*!
308
    Loads a bitmap into memory. On entry it is assumed that
309
  the bitmap to be loaded is of the correct type. If the bitmap
310
  is of an incorrect type, the plugin might not gracefully fail but
311
  crash or enter an endless loop. It is also assumed that all
312
  the bitmap data is available at one time. If the bitmap is not complete,
313
  for example because it is being downloaded while loaded, the plugin
314
  might also not gracefully fail.
315
316
  The Load function has the following parameters:
317
318
    The first parameter (FreeImageIO *io) is a structure providing
319
  function pointers in order to make use of FreeImage's IO redirection. Using
320
  FreeImage's file i/o functions instead of standard ones it is garantueed
321
  that all bitmap types, both current and future ones, can be loaded from
322
  memory, file cabinets, the internet and more. The second parameter (fi_handle handle)
323
  is a companion of FreeImageIO and can be best compared with the standard FILE* type,
324
  in a generalized form.
325
326
  The third parameter (int page) indicates wether we will be loading a certain page
327
  in the bitmap or if we will load the default one. This parameter is only used if
328
  the plugin supports multi-paged bitmaps, e.g. cabinet bitmaps that contain a series
329
  of images or pages. If the plugin does support multi-paging, the page parameter
330
  can contain either a number higher or equal to 0 to load a certain page, or -1 to 
331
  load the default page. If the plugin does not support multi-paging,
332
  the page parameter is always -1.
333
  
334
  The fourth parameter (int flags) manipulates the load function to load a bitmap
335
  in a certain way. Every plugin has a different flag parameter with different meanings.
336
337
  The last parameter (void *data) can contain a special data block used when
338
  the file is read multi-paged. Because not every plugin supports multi-paging
339
  not every plugin will use the data parameter and it will be set to NULL.However,
340
  when the plugin does support multi-paging the parameter contains a pointer to a
341
  block of data allocated by the Open function.
342
*/
343
344
static FIBITMAP * DLL_CALLCONV
345
0
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
346
0
  FIBITMAP *dib = NULL;
347
0
  BYTE *bits;       // Pointer to dib data
348
0
  RGBQUAD *pal;     // Pointer to dib palette
349
0
  BYTE *line = NULL;   // PCX raster line
350
0
  BYTE *ReadBuf = NULL; // buffer;
351
0
  BOOL bIsRLE;      // True if the file is run-length encoded
352
353
0
  if(!handle) {
354
0
    return NULL;
355
0
  }
356
357
0
  BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
358
359
0
  try {
360
    // check PCX identifier
361
    // (note: should have been already validated using FreeImage_GetFileType but check again)
362
0
    {
363
0
      long start_pos = io->tell_proc(handle);
364
0
      BOOL bValidated = pcx_validate(io, handle);
365
0
      io->seek_proc(handle, start_pos, SEEK_SET);
366
0
      if(!bValidated) {
367
0
        throw FI_MSG_ERROR_MAGIC_NUMBER;
368
0
      }
369
0
    }
370
    
371
0
    PCXHEADER header;
372
373
    // process the header
374
0
    if(io->read_proc(&header, sizeof(PCXHEADER), 1, handle) != 1) {
375
0
      throw FI_MSG_ERROR_PARSING;
376
0
    }
377
#ifdef FREEIMAGE_BIGENDIAN
378
    SwapHeader(&header);
379
#endif
380
381
    // process the window
382
0
    const WORD *window = header.window; // left, upper, right,lower pixel coord.
383
0
    const int left    = window[0];
384
0
    const int top   = window[1];
385
0
    const int right   = window[2];
386
0
    const int bottom  = window[3];
387
388
    // check image size
389
0
    if((left >= right) || (top >= bottom)) {
390
0
      throw FI_MSG_ERROR_PARSING;
391
0
    }
392
393
0
    const unsigned width = right - left + 1;
394
0
    const unsigned height = bottom - top + 1;
395
0
    const unsigned bitcount = header.bpp * header.planes;
396
397
    // allocate a new dib
398
0
    switch(bitcount) {
399
0
      case 1:
400
0
      case 4:
401
0
      case 8:
402
0
        dib = FreeImage_AllocateHeader(header_only, width, height, bitcount);
403
0
        break;
404
0
      case 24:
405
0
        dib = FreeImage_AllocateHeader(header_only, width, height, bitcount, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
406
0
        break;
407
0
      default:
408
0
        throw FI_MSG_ERROR_DIB_MEMORY;
409
0
        break;
410
0
    }
411
412
    // if the dib couldn't be allocated, throw an error
413
0
    if (!dib) {
414
0
      throw FI_MSG_ERROR_DIB_MEMORY;
415
0
    }
416
417
    // metrics handling code
418
419
0
    FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)header.hdpi) / 0.0254000 + 0.5));
420
0
    FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)header.vdpi) / 0.0254000 + 0.5));
421
422
    // Set up the palette if needed
423
    // ----------------------------
424
425
0
    switch(bitcount) {
426
0
      case 1:
427
0
      {
428
0
        pal = FreeImage_GetPalette(dib);
429
0
        pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
430
0
        pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
431
0
        break;
432
0
      }
433
434
0
      case 4:
435
0
      {
436
0
        pal = FreeImage_GetPalette(dib);
437
438
0
        BYTE *pColormap = &header.color_map[0];
439
440
0
        for (int i = 0; i < 16; i++) {
441
0
          pal[i].rgbRed   = pColormap[0];
442
0
          pal[i].rgbGreen = pColormap[1];
443
0
          pal[i].rgbBlue  = pColormap[2];
444
0
          pColormap += 3;
445
0
        }
446
447
0
        break;
448
0
      }
449
450
0
      case 8:
451
0
      {
452
0
        BYTE palette_id;
453
454
0
        io->seek_proc(handle, -769L, SEEK_END);
455
0
        io->read_proc(&palette_id, 1, 1, handle);
456
457
0
        if (palette_id == 0x0C) {
458
0
          BYTE *cmap = (BYTE*)malloc(768 * sizeof(BYTE));
459
460
0
          if(cmap) {
461
0
            io->read_proc(cmap, 768, 1, handle);
462
463
0
            pal = FreeImage_GetPalette(dib);
464
0
            BYTE *pColormap = &cmap[0];
465
466
0
            for(int i = 0; i < 256; i++) {
467
0
              pal[i].rgbRed   = pColormap[0];
468
0
              pal[i].rgbGreen = pColormap[1];
469
0
              pal[i].rgbBlue  = pColormap[2];
470
0
              pColormap += 3;
471
0
            }
472
473
0
            free(cmap);
474
0
          }
475
476
0
        }
477
478
        // wrong palette ID, perhaps a gray scale is needed ?
479
480
0
        else if (header.palette_info == 2) {
481
0
          pal = FreeImage_GetPalette(dib);
482
483
0
          for(int i = 0; i < 256; i++) {
484
0
            pal[i].rgbRed   = (BYTE)i;
485
0
            pal[i].rgbGreen = (BYTE)i;
486
0
            pal[i].rgbBlue  = (BYTE)i;
487
0
          }
488
0
        }
489
490
0
        io->seek_proc(handle, (long)sizeof(PCXHEADER), SEEK_SET);
491
0
      }
492
0
      break;
493
0
    }
494
495
0
    if(header_only) {
496
      // header only mode
497
0
      return dib;
498
0
    }
499
500
    // calculate the line length for the PCX and the dib
501
502
    // length of raster line in bytes
503
0
    const unsigned lineLength = header.bytes_per_line * header.planes;
504
    // length of dib line (rounded to DWORD) in bytes
505
0
    const unsigned pitch = FreeImage_GetPitch(dib);
506
507
    // run-length encoding ?
508
509
0
    bIsRLE = (header.encoding == 1) ? TRUE : FALSE;
510
511
    // load image data
512
    // ---------------
513
514
0
    line = (BYTE*)malloc(MAX(lineLength, width * header.bpp) * sizeof(BYTE)); //< # header.bytes_per_line might be corrupted (too small)
515
0
    if(!line) {
516
0
      throw FI_MSG_ERROR_MEMORY;
517
0
    }
518
    
519
0
    ReadBuf = (BYTE*)malloc(PCX_IO_BUF_SIZE * sizeof(BYTE));
520
0
    if(!ReadBuf) {
521
0
      throw FI_MSG_ERROR_MEMORY;
522
0
    }
523
    
524
0
    bits = FreeImage_GetScanLine(dib, height - 1);
525
526
0
    int ReadPos = PCX_IO_BUF_SIZE;
527
528
0
    if ((header.planes == 1) && ((header.bpp == 1) || (header.bpp == 8))) {
529
0
      BYTE skip;
530
0
      unsigned written;
531
532
0
      for (unsigned y = 0; y < height; y++) {
533
        // do a safe copy of the scanline into 'line'
534
0
        written = readLine(io, handle, line, lineLength, bIsRLE, ReadBuf, &ReadPos);
535
        // sometimes (already encountered), PCX images can have a lineLength > pitch
536
0
        memcpy(bits, line, MIN(pitch, lineLength));
537
538
        // skip trailing garbage at the end of the scanline
539
540
0
        for (unsigned count = written; count < lineLength; count++) {
541
0
          if (ReadPos < PCX_IO_BUF_SIZE) {
542
0
            ReadPos++;
543
0
          } else {
544
0
            io->read_proc(&skip, sizeof(BYTE), 1, handle);
545
0
          }
546
0
        }
547
548
0
        bits -= pitch;
549
0
      }
550
0
    } else if ((header.planes == 4) && (header.bpp == 1)) {
551
0
      BYTE bit,  mask, skip;
552
0
      unsigned index;
553
0
      BYTE *buffer;
554
555
0
      buffer = (BYTE*)malloc(width * sizeof(BYTE));
556
0
      if(!buffer) {
557
0
        throw FI_MSG_ERROR_MEMORY;
558
0
      }
559
560
0
      for (unsigned y = 0; y < height; y++) {
561
0
        unsigned written = readLine(io, handle, line, lineLength, bIsRLE, ReadBuf, &ReadPos);
562
563
        // build a nibble using the 4 planes
564
565
0
        memset(buffer, 0, width * sizeof(BYTE));
566
567
0
        for(int plane = 0; plane < 4; plane++) {
568
0
          bit = (BYTE)(1 << plane);
569
570
0
          for (unsigned x = 0; x < width; x++) {
571
0
            index = (unsigned)((x / 8) + plane * header.bytes_per_line);
572
0
            mask = (BYTE)(0x80 >> (x & 0x07));
573
0
            buffer[x] |= (line[index] & mask) ? bit : 0;
574
0
          }
575
0
        }
576
577
        // then write the dib row
578
579
0
        for (unsigned x = 0; x < width / 2; x++) {
580
0
          bits[x] = (buffer[2*x] << 4) | buffer[2*x+1];
581
0
        }
582
583
        // skip trailing garbage at the end of the scanline
584
585
0
        for (unsigned count = written; count < lineLength; count++) {
586
0
          if (ReadPos < PCX_IO_BUF_SIZE) {
587
0
            ReadPos++;
588
0
          } else {
589
0
            io->read_proc(&skip, sizeof(BYTE), 1, handle);
590
0
          }
591
0
        }
592
593
0
        bits -= pitch;
594
0
      }
595
596
0
      free(buffer);
597
598
0
    } else if((header.planes == 3) && (header.bpp == 8)) {
599
0
      BYTE *pLine;
600
601
0
      for (unsigned y = 0; y < height; y++) {
602
0
        readLine(io, handle, line, lineLength, bIsRLE, ReadBuf, &ReadPos);
603
604
        // convert the plane stream to BGR (RRRRGGGGBBBB -> BGRBGRBGRBGR)
605
        // well, now with the FI_RGBA_x macros, on BIGENDIAN we convert to RGB
606
607
0
        pLine = line;
608
0
        unsigned x;
609
610
0
        for (x = 0; x < width; x++) {
611
0
          bits[x * 3 + FI_RGBA_RED] = pLine[x];           
612
0
        }
613
0
        pLine += header.bytes_per_line;
614
615
0
        for (x = 0; x < width; x++) {
616
0
          bits[x * 3 + FI_RGBA_GREEN] = pLine[x];
617
0
        }
618
0
        pLine += header.bytes_per_line;
619
620
0
        for (x = 0; x < width; x++) {
621
0
          bits[x * 3 + FI_RGBA_BLUE] = pLine[x];
622
0
        }
623
0
        pLine += header.bytes_per_line;
624
625
0
        bits -= pitch;
626
0
      }
627
0
    } else {
628
0
      throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
629
0
    }
630
631
0
    free(line);
632
0
    free(ReadBuf);
633
634
0
    return dib;
635
636
0
  } catch (const char *text) {
637
    // free allocated memory
638
639
0
    if (dib != NULL) {
640
0
      FreeImage_Unload(dib);
641
0
    }
642
0
    if (line != NULL) {
643
0
      free(line);
644
0
    }
645
0
    if (ReadBuf != NULL) {
646
0
      free(ReadBuf);
647
0
    }
648
649
0
    FreeImage_OutputMessageProc(s_format_id, text);
650
0
  }
651
  
652
0
  return NULL;
653
0
}
654
655
// ==========================================================
656
//   Init
657
// ==========================================================
658
659
/*!
660
    Initialises the plugin. The first parameter (Plugin *plugin)
661
  contains a pointer to a pre-allocated Plugin structure
662
  wherein pointers to the available plugin functions
663
  has to be stored. The second parameter (int format_id) is an identification
664
  number that the plugin may use to show plugin specific warning messages
665
  or other information to the user. The plugin number
666
  is generated by FreeImage and can differ everytime the plugin is
667
  initialised.
668
669
    If you want to create your own plugin you have to take some
670
  rules into account. Plugin functions have to be compiled
671
  __stdcall using the multithreaded c runtime libraries. Throwing
672
  exceptions in plugin functions is allowed, as long as those exceptions
673
  are being caught inside the same plugin. It is forbidden for a plugin
674
  function to directly call FreeImage functions or to allocate memory
675
  and pass it to the main DLL. Exception to this rule is the special file data
676
  block that may be allocated the Open function. Allocating a FIBITMAP inside a
677
  plugin can be using the function allocate_proc in the FreeImage structure,
678
  which will allocate the memory using the DLL's c runtime library.
679
*/
680
681
void DLL_CALLCONV
682
2
InitPCX(Plugin *plugin, int format_id) {
683
2
  s_format_id = format_id;
684
685
2
  plugin->format_proc = Format;
686
2
  plugin->description_proc = Description;
687
2
  plugin->extension_proc = Extension;
688
2
  plugin->regexpr_proc = RegExpr;
689
2
  plugin->open_proc = NULL;
690
2
  plugin->close_proc = NULL;
691
2
  plugin->pagecount_proc = NULL;
692
2
  plugin->pagecapability_proc = NULL;
693
2
  plugin->load_proc = Load;
694
2
  plugin->save_proc = NULL;
695
2
  plugin->validate_proc = Validate;
696
2
  plugin->mime_proc = MimeType;
697
2
  plugin->supports_export_bpp_proc = SupportsExportDepth;
698
2
  plugin->supports_export_type_proc = SupportsExportType;
699
  plugin->supports_icc_profiles_proc = NULL;
700
2
  plugin->supports_no_pixels_proc = SupportsNoPixels;
701
2
}