PNM loader: add read support for PAM #3
|
@ -3,11 +3,17 @@
|
|||
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DBG_PFX "LDR-pnm"
|
||||
|
||||
static const char *const _formats[] = { "pnm", "ppm", "pgm", "pbm", "pam" };
|
||||
|
||||
typedef enum
|
||||
{ BW_RAW_PACKED, BW_RAW, BW_PLAIN, GRAY_RAW, GRAY_PLAIN, RGB_RAW, RGB_PLAIN,
|
||||
XV332
|
||||
} px_type;
|
||||
|
||||
static struct {
|
||||
const unsigned char *data, *dptr;
|
||||
unsigned int size;
|
||||
|
@ -78,6 +84,7 @@ mm_getu(unsigned int *pui)
|
|||
bool comment;
|
||||
|
||||
/* Strip whitespace and comments */
|
||||
|
||||
for (comment = false;;)
|
||||
{
|
||||
ch = mm_getc();
|
||||
|
@ -114,70 +121,202 @@ mm_getu(unsigned int *pui)
|
|||
return 0; /* Ok */
|
||||
}
|
||||
|
||||
static int
|
||||
mm_parse_pam_header(unsigned *w, unsigned *h, unsigned *v, px_type * pxt,
|
||||
char *alpha)
|
||||
{
|
||||
char tuple_type[32] = { 0 };
|
||||
unsigned tti = 0, d;
|
||||
|
||||
for (int ch;;)
|
||||
{
|
||||
if ((ch = mm_getc()) == -1)
|
||||
return -1;
|
||||
if (ch == '#')
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((ch = mm_getc()) == -1)
|
||||
return -1;
|
||||
}
|
||||
while (ch != '\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
char key[9] = { 0 }; /* max key size per spec: 8 */
|
||||
for (unsigned ki = 0; !isspace(ch) && ki < sizeof(key) - 1; ++ki)
|
||||
{
|
||||
key[ki] = (char)ch;
|
||||
if ((ch = mm_getc()) == -1)
|
||||
return -1;
|
||||
}
|
||||
if (!strcmp(key, "ENDHDR"))
|
||||
break;
|
||||
|
||||
unsigned int *p = NULL;
|
||||
|
||||
if (!strcmp(key, "HEIGHT"))
|
||||
p = h;
|
||||
else if (!strcmp(key, "WIDTH"))
|
||||
p = w;
|
||||
else if (!strcmp(key, "DEPTH"))
|
||||
p = &d;
|
||||
else if (!strcmp(key, "MAXVAL"))
|
||||
p = v;
|
||||
else if (!strcmp(key, "TUPLTYPE"))
|
||||
{
|
||||
while (isspace(ch))
|
||||
{
|
||||
if ((ch = mm_getc()) == -1)
|
||||
return -1;
|
||||
}
|
||||
if (tti != 0) /* not the first TUPLE_TYPE header */
|
||||
{
|
||||
if (tti < sizeof(tuple_type) - 1)
|
||||
tuple_type[tti++] = ' ';
|
||||
}
|
||||
while (ch != '\n' && tti < sizeof(tuple_type) - 1)
|
||||
{
|
||||
tuple_type[tti++] = ch;
|
||||
if ((ch = mm_getc()) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else /* unknown header */
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (p)
|
||||
{
|
||||
if (mm_getu(p) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*alpha = (tti >= 6 && !strcmp(tuple_type + tti - 6, "_ALPHA"));
|
||||
|
||||
if (!strncmp(tuple_type, "BLACKANDWHITE", 13))
|
||||
{
|
||||
*pxt = BW_RAW;
|
||||
/* assert(d == *alpha + 1);
|
||||
* assert(*v == 1); */
|
||||
}
|
||||
else if (!strncmp(tuple_type, "GRAYSCALE", 9))
|
||||
{
|
||||
*pxt = GRAY_RAW;
|
||||
/* assert(d == *alpha + 1); */
|
||||
}
|
||||
else if (!strncmp(tuple_type, "RGB", 3))
|
||||
{
|
||||
*pxt = RGB_RAW;
|
||||
/* assert(d == *alpha + 3); */
|
||||
}
|
||||
else /* unknown tuple type */
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_load(ImlibImage * im, int load_data)
|
||||
{
|
||||
int rc;
|
||||
int c, p;
|
||||
int w, h, v, numbers, count;
|
||||
int p;
|
||||
unsigned int w, h, v, hlen;
|
||||
uint8_t *data = NULL; /* for the binary versions */
|
||||
uint8_t *ptr = NULL;
|
||||
int *idata = NULL; /* for the ASCII versions */
|
||||
uint32_t *ptr2, rval, gval, bval;
|
||||
int i, j, x, y;
|
||||
unsigned i, j, x, y;
|
||||
px_type pxt;
|
||||
|
||||
rc = LOAD_FAIL;
|
||||
|
||||
mm_init(im->fi->fdata, im->fi->fsize);
|
||||
|
||||
/* read the header info */
|
||||
|
||||
c = mm_getc();
|
||||
if (c != 'P')
|
||||
if (mm_getc() != 'P')
|
||||
goto quit;
|
||||
|
||||
numbers = 3;
|
||||
p = mm_getc();
|
||||
if (p == '1' || p == '4')
|
||||
numbers = 2; /* bitimages don't have max value */
|
||||
|
||||
if ((p < '1') || (p > '8'))
|
||||
goto quit;
|
||||
|
||||
/* read numbers */
|
||||
w = h = 0;
|
||||
v = 255;
|
||||
for (count = i = 0; count < numbers; i++)
|
||||
hlen = 3;
|
||||
switch (p)
|
||||
{
|
||||
if (mm_getu(&gval))
|
||||
goto quit;
|
||||
|
||||
if (p == '7' && i == 0)
|
||||
case '1':
|
||||
pxt = BW_PLAIN;
|
||||
hlen = 2;
|
||||
break;
|
||||
case '2':
|
||||
pxt = GRAY_PLAIN;
|
||||
break;
|
||||
case '3':
|
||||
pxt = RGB_PLAIN;
|
||||
break;
|
||||
case '4':
|
||||
pxt = BW_RAW_PACKED;
|
||||
hlen = 2;
|
||||
break;
|
||||
case '5':
|
||||
pxt = GRAY_RAW;
|
||||
break;
|
||||
case '6':
|
||||
pxt = RGB_RAW;
|
||||
break;
|
||||
case '7':
|
||||
if (mm_getc() != '\n')
|
||||
{
|
||||
if (gval != 332)
|
||||
if (mm_getu(&gval) || gval != 332) /* XV thumbnail format */
|
||||
goto quit;
|
||||
else
|
||||
continue;
|
||||
pxt = XV332;
|
||||
}
|
||||
|
||||
count++;
|
||||
switch (count)
|
||||
else
|
||||
{
|
||||
case 1: /* width */
|
||||
w = gval;
|
||||
break;
|
||||
case 2: /* height */
|
||||
h = gval;
|
||||
break;
|
||||
case 3: /* max value, only for color and greyscale */
|
||||
v = gval;
|
||||
break;
|
||||
if (mm_parse_pam_header(&w, &h, &v, &pxt, &im->has_alpha))
|
||||
goto quit;
|
||||
hlen = 0;
|
||||
}
|
||||
break;
|
||||
case '8': /* not in netpbm, unknown format provenance (Imlib2 specific?) */
|
||||
pxt = RGB_RAW;
|
||||
im->has_alpha = 1;
|
||||
break;
|
||||
default:
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* read header for non-PAM formats */
|
||||
if (hlen != 0)
|
||||
{
|
||||
w = h = 0;
|
||||
v = 255;
|
||||
for (i = 0; i < hlen; i++)
|
||||
{
|
||||
if (mm_getu(&gval))
|
||||
goto quit;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0: /* width */
|
||||
w = gval;
|
||||
break;
|
||||
case 1: /* height */
|
||||
h = gval;
|
||||
break;
|
||||
case 2: /* max value, only for color and greyscale */
|
||||
v = gval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((v < 0) || (v > 255))
|
||||
|
||||
if (v > 255)
|
||||
goto quit;
|
||||
|
||||
D("P%c: WxH=%dx%d V=%d\n", p, w, h, v);
|
||||
D("P%c: pxtype=%d WxH=%ux%u V=%u A=%s\n",
|
||||
p, pxt, w, h, v, im->has_alpha ? "YES" : "NO");
|
||||
|
||||
rc = LOAD_BADIMAGE; /* Format accepted */
|
||||
|
||||
|
@ -186,8 +325,6 @@ _load(ImlibImage * im, int load_data)
|
|||
if (!IMAGE_DIMENSIONS_OK(w, h))
|
||||
goto quit;
|
||||
|
||||
im->has_alpha = p == '8';
|
||||
|
||||
if (!load_data)
|
||||
QUIT_WITH_RC(LOAD_SUCCESS);
|
||||
|
||||
|
@ -198,25 +335,27 @@ _load(ImlibImage * im, int load_data)
|
|||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
/* start reading the data */
|
||||
switch (p)
|
||||
switch (pxt)
|
||||
{
|
||||
case '1': /* ASCII monochrome */
|
||||
case BW_PLAIN: /* ASCII monochrome */
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
i = mm_get01();
|
||||
if (i < 0)
|
||||
int px = mm_get01();
|
||||
|
||||
if (px < 0)
|
||||
goto quit;
|
||||
|
||||
*ptr2++ = i ? 0xff000000 : 0xffffffff;
|
||||
*ptr2++ = px ? 0xff000000 : 0xffffffff;
|
||||
}
|
||||
|
||||
if (im->lc && __imlib_LoadProgressRows(im, y, 1))
|
||||
goto quit_progress;
|
||||
}
|
||||
break;
|
||||
case '2': /* ASCII greyscale */
|
||||
|
||||
case GRAY_PLAIN: /* ASCII greyscale */
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
|
@ -231,7 +370,8 @@ _load(ImlibImage * im, int load_data)
|
|||
else
|
||||
{
|
||||
*ptr2++ =
|
||||
0xff000000 | (((gval * 255) / v) << 16) |
|
||||
0xff000000 |
|
||||
(((gval * 255) / v) << 16) |
|
||||
(((gval * 255) / v) << 8) | ((gval * 255) / v);
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +380,8 @@ _load(ImlibImage * im, int load_data)
|
|||
goto quit_progress;
|
||||
}
|
||||
break;
|
||||
case '3': /* ASCII RGB */
|
||||
|
||||
case RGB_PLAIN: /* ASCII RGB */
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
|
@ -269,7 +410,8 @@ _load(ImlibImage * im, int load_data)
|
|||
goto quit_progress;
|
||||
}
|
||||
break;
|
||||
case '4': /* binary 1bit monochrome */
|
||||
|
||||
case BW_RAW_PACKED: /* binary 1bit monochrome */
|
||||
data = malloc((w + 7) / 8 * sizeof(uint8_t));
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
@ -299,36 +441,49 @@ _load(ImlibImage * im, int load_data)
|
|||
goto quit_progress;
|
||||
}
|
||||
break;
|
||||
case '5': /* binary 8bit grayscale GGGGGGGG */
|
||||
data = malloc(1 * sizeof(uint8_t) * w);
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
ptr2 = im->data;
|
||||
for (y = 0; y < h; y++)
|
||||
case BW_RAW: /* binary 1byte monochrome */
|
||||
if (im->has_alpha)
|
||||
{
|
||||
if (mm_read(data, w * 1))
|
||||
goto quit;
|
||||
data = malloc(2 * sizeof(uint8_t) * w);
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
ptr = data;
|
||||
if (v == 0 || v == 255)
|
||||
ptr2 = im->data;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
if (mm_read(data, w * 2))
|
||||
goto quit;
|
||||
|
||||
ptr = data;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
0xff000000 | (ptr[0] << 16) | (ptr[0] << 8) | ptr[0];
|
||||
(ptr[1] ? 0xff000000 : 0) | (ptr[0] ? 0xffffff : 0);
|
||||
ptr2++;
|
||||
ptr++;
|
||||
ptr += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (im->lc && __imlib_LoadProgressRows(im, y, 1))
|
||||
goto quit_progress;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = malloc(1 * sizeof(uint8_t) * w);
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
ptr2 = im->data;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
if (mm_read(data, w * 1))
|
||||
goto quit;
|
||||
|
||||
ptr = data;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
0xff000000 |
|
||||
(((ptr[0] * 255) / v) << 16) |
|
||||
(((ptr[0] * 255) / v) << 8) | ((ptr[0] * 255) / v);
|
||||
*ptr2 = 0xff000000 | (ptr[0] ? 0xffffff : 0);
|
||||
ptr2++;
|
||||
ptr++;
|
||||
}
|
||||
|
@ -338,46 +493,180 @@ _load(ImlibImage * im, int load_data)
|
|||
goto quit_progress;
|
||||
}
|
||||
break;
|
||||
case '6': /* 24bit binary RGBRGBRGB */
|
||||
data = malloc(3 * sizeof(uint8_t) * w);
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
ptr2 = im->data;
|
||||
for (y = 0; y < h; y++)
|
||||
case GRAY_RAW: /* binary 8bit grayscale GGGGGGGG */
|
||||
if (im->has_alpha)
|
||||
{
|
||||
if (mm_read(data, w * 3))
|
||||
goto quit;
|
||||
data = malloc(2 * sizeof(uint8_t) * w);
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
ptr = data;
|
||||
if (v == 0 || v == 255)
|
||||
ptr2 = im->data;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
0xff000000 | (ptr[0] << 16) | (ptr[1] << 8) | ptr[2];
|
||||
ptr2++;
|
||||
ptr += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
0xff000000 |
|
||||
(((ptr[0] * 255) / v) << 16) |
|
||||
(((ptr[1] * 255) / v) << 8) | ((ptr[2] * 255) / v);
|
||||
ptr2++;
|
||||
ptr += 3;
|
||||
}
|
||||
}
|
||||
if (mm_read(data, w * 2))
|
||||
goto quit;
|
||||
|
||||
if (im->lc && __imlib_LoadProgressRows(im, y, 1))
|
||||
goto quit_progress;
|
||||
ptr = data;
|
||||
if (v == 0 || v == 255)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
(ptr[1] << 24) | (ptr[0] << 16) | (ptr[0] << 8) |
|
||||
ptr[0];
|
||||
ptr2++;
|
||||
ptr += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
(((ptr[1] * 255) / v) << 24) |
|
||||
(((ptr[0] * 255) / v) << 16) |
|
||||
(((ptr[0] * 255) / v) << 8) | ((ptr[0] * 255) /
|
||||
v);
|
||||
ptr2++;
|
||||
ptr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (im->lc && __imlib_LoadProgressRows(im, y, 1))
|
||||
goto quit_progress;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data = malloc(1 * sizeof(uint8_t) * w);
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
ptr2 = im->data;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
if (mm_read(data, w * 1))
|
||||
goto quit;
|
||||
|
||||
ptr = data;
|
||||
if (v == 0 || v == 255)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
0xff000000 | (ptr[0] << 16) | (ptr[0] << 8) |
|
||||
ptr[0];
|
||||
ptr2++;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
0xff000000 |
|
||||
(((ptr[0] * 255) / v) << 16) |
|
||||
(((ptr[0] * 255) / v) << 8) | ((ptr[0] * 255) /
|
||||
v);
|
||||
ptr2++;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
if (im->lc && __imlib_LoadProgressRows(im, y, 1))
|
||||
goto quit_progress;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '7': /* XV's 8bit 332 format */
|
||||
|
||||
case RGB_RAW: /* 24bit binary RGBRGBRGB */
|
||||
if (im->has_alpha)
|
||||
{
|
||||
data = malloc(4 * sizeof(uint8_t) * w);
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
ptr2 = im->data;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
if (mm_read(data, w * 4))
|
||||
goto quit;
|
||||
|
||||
ptr = data;
|
||||
if (v == 0 || v == 255)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 = PIXEL_ARGB(ptr[3], ptr[0], ptr[1], ptr[2]);
|
||||
ptr2++;
|
||||
ptr += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
PIXEL_ARGB((ptr[3] * 255) / v,
|
||||
(ptr[0] * 255) / v,
|
||||
(ptr[1] * 255) / v,
|
||||
(ptr[2] * 255) / v);
|
||||
ptr2++;
|
||||
ptr += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (im->lc && __imlib_LoadProgressRows(im, y, 1))
|
||||
goto quit_progress;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data = malloc(3 * sizeof(uint8_t) * w);
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
ptr2 = im->data;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
if (mm_read(data, w * 3))
|
||||
goto quit;
|
||||
|
||||
ptr = data;
|
||||
if (v == 0 || v == 255)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
0xff000000 | (ptr[0] << 16) | (ptr[1] << 8) |
|
||||
ptr[2];
|
||||
ptr2++;
|
||||
ptr += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
0xff000000 |
|
||||
(((ptr[0] * 255) / v) << 16) |
|
||||
(((ptr[1] * 255) / v) << 8) | ((ptr[2] * 255) /
|
||||
v);
|
||||
ptr2++;
|
||||
ptr += 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (im->lc && __imlib_LoadProgressRows(im, y, 1))
|
||||
goto quit_progress;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XV332: /* XV's 8bit 332 format */
|
||||
data = malloc(1 * sizeof(uint8_t) * w);
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
@ -409,44 +698,7 @@ _load(ImlibImage * im, int load_data)
|
|||
goto quit_progress;
|
||||
}
|
||||
break;
|
||||
case '8': /* 24bit binary RGBARGBARGBA */
|
||||
data = malloc(4 * sizeof(uint8_t) * w);
|
||||
if (!data)
|
||||
QUIT_WITH_RC(LOAD_OOM);
|
||||
|
||||
ptr2 = im->data;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
if (mm_read(data, w * 4))
|
||||
goto quit;
|
||||
|
||||
ptr = data;
|
||||
if (v == 0 || v == 255)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 = PIXEL_ARGB(ptr[3], ptr[0], ptr[1], ptr[2]);
|
||||
ptr2++;
|
||||
ptr += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
PIXEL_ARGB((ptr[3] * 255) / v,
|
||||
(ptr[0] * 255) / v,
|
||||
(ptr[1] * 255) / v, (ptr[2] * 255) / v);
|
||||
ptr2++;
|
||||
ptr += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (im->lc && __imlib_LoadProgressRows(im, y, 1))
|
||||
goto quit_progress;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto quit;
|
||||
quit_progress:
|
||||
|
|
Loading…
Reference in New Issue