This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository legacy-imlib2.
View the commit online.
commit 27db42330ee33bed7dfee1ebeb89a067e7ef4252
Author: q3cpma <q3c...@posteo.net>
AuthorDate: Wed Jan 11 19:32:11 2023 +0100
PNM loader: add read support for PAM
---
src/modules/loaders/loader_pnm.c | 508 +++++++++++++++++++++++++++++----------
1 file changed, 380 insertions(+), 128 deletions(-)
diff --git a/src/modules/loaders/loader_pnm.c b/src/modules/loaders/loader_pnm.c
index b6f06b6..2f20688 100644
--- a/src/modules/loaders/loader_pnm.c
+++ b/src/modules/loaders/loader_pnm.c
@@ -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 = "" /* 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 (mm_getu(&gval) || gval != 332) /* XV thumbnail format */
+ goto quit;
+ pxt = XV332;
+ }
+ else
{
- if (gval != 332)
+ if (mm_parse_pam_header(&w, &h, &v, &pxt, &im->has_alpha))
goto quit;
- else
- continue;
+ hlen = 0;
}
+ break;
+ case '8': /* not in netpbm, unknown format provenance (Imlib2 specific?) */
+ pxt = RGB_RAW;
+ im->has_alpha = 1;
+ break;
+ default:
+ goto quit;
+ }
- count++;
- switch (count)
+ /* read header for non-PAM formats */
+ if (hlen != 0)
+ {
+ w = h = 0;
+ v = 255;
+ for (i = 0; i < hlen; i++)
{
- 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_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 = "" + 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 = "" * 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 = "" * 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 = "" * 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 = "" * 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 = "" * 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++)
+ if (mm_read(data, w * 2))
+ goto quit;
+
+ ptr = data;
+ if (v == 0 || v == 255)
{
- *ptr2 =
- 0xff000000 | (ptr[0] << 16) | (ptr[1] << 8) | ptr[2];
- ptr2++;
- ptr += 3;
+ 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
+ }
+ else
+ {
+ data = "" * sizeof(uint8_t) * w);
+ if (!data)
+ QUIT_WITH_RC(LOAD_OOM);
+
+ ptr2 = im->data;
+ for (y = 0; y < h; y++)
{
- for (x = 0; x < w; x++)
+ if (mm_read(data, w * 1))
+ goto quit;
+
+ ptr = data;
+ if (v == 0 || v == 255)
{
- *ptr2 =
- 0xff000000 |
- (((ptr[0] * 255) / v) << 16) |
- (((ptr[1] * 255) / v) << 8) | ((ptr[2] * 255) / v);
- ptr2++;
- ptr += 3;
+ 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;
- if (im->lc && __imlib_LoadProgressRows(im, y, 1))
- goto quit_progress;
+ case RGB_RAW: /* 24bit binary RGBRGBRGB */
+ if (im->has_alpha)
+ {
+ data = "" * 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 = "" * 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 '7': /* XV's 8bit 332 format */
+
+ case XV332: /* XV's 8bit 332 format */
data = "" * 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 = "" * 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:
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.