static const unsigned char * pam_binary_read_header(fz_context *ctx, struct info *pnm, const unsigned char *p, const unsigned char *e) { int token = TOKEN_UNKNOWN; pnm->width = 0; pnm->height = 0; pnm->depth = 0; pnm->maxval = 0; pnm->tupletype = 0; while (p < e && token != TOKEN_ENDHDR) { p = pnm_read_token(ctx, p, e, &token); p = pnm_read_white(ctx, p, e, 0); switch (token) { case TOKEN_WIDTH: p = pnm_read_number(ctx, p, e, &pnm->width); break; case TOKEN_HEIGHT: p = pnm_read_number(ctx, p, e, &pnm->height); break; case TOKEN_DEPTH: p = pnm_read_number(ctx, p, e, &pnm->depth); break; case TOKEN_MAXVAL: p = pnm_read_number(ctx, p, e, &pnm->maxval); break; case TOKEN_TUPLTYPE: p = pnm_read_tupletype(ctx, p, e, &pnm->tupletype); break; case TOKEN_ENDHDR: break; default: fz_throw(ctx, FZ_ERROR_GENERIC, "unknown header token in pnm image"); } if (token != TOKEN_ENDHDR) p = pnm_read_white(ctx, p, e, 0); } return p; }
static unsigned char * pam_binary_read_header(fz_context *ctx, struct info *pnm, unsigned char *p, unsigned char *e) { char *token = fz_strdup(ctx, ""); fz_try(ctx) { while (p < e && strcmp(token, "ENDHDR")) { fz_free(ctx, token); p = pnm_read_string(ctx, p, e, &token); p = pnm_read_white(ctx, p, e, 0); if (!strcmp(token, "WIDTH")) p = pnm_read_number(ctx, p, e, &pnm->width); else if (!strcmp(token, "HEIGHT")) p = pnm_read_number(ctx, p, e, &pnm->height); else if (!strcmp(token, "DEPTH")) p = pnm_read_number(ctx, p, e, &pnm->depth); else if (!strcmp(token, "MAXVAL")) p = pnm_read_number(ctx, p, e, &pnm->maxval); else if (!strcmp(token, "TUPLTYPE")) p = pnm_read_string(ctx, p, e, &pnm->tupletype); else if (strcmp(token, "ENDHDR")) fz_throw(ctx, FZ_ERROR_GENERIC, "unknown header token in pnm image"); if (strcmp(token, "ENDHDR")) p = pnm_read_white(ctx, p, e, 0); } } fz_always(ctx) { fz_free(ctx, token); } fz_catch(ctx) { fz_rethrow(ctx); } return p; }
static fz_pixmap * pnm_read_image(fz_context *ctx, struct info *pnm, unsigned char *p, size_t total, int onlymeta) { unsigned char *e = p + total; char signature[3] = { 0 }; p = pnm_read_signature(ctx, p, e, signature); p = pnm_read_white(ctx, p, e, 0); if (!strcmp(signature, "P1")) { if (!onlymeta) pnm->cs = fz_device_gray(ctx); return pnm_ascii_read_image(ctx, pnm, p, e, onlymeta, 1); } else if (!strcmp(signature, "P2")) { if (!onlymeta) pnm->cs = fz_device_gray(ctx); return pnm_ascii_read_image(ctx, pnm, p, e, onlymeta, 0); } else if (!strcmp(signature, "P3")) { if (!onlymeta) pnm->cs = fz_device_rgb(ctx); return pnm_ascii_read_image(ctx, pnm, p, e, onlymeta, 0); } else if (!strcmp(signature, "P4")) { if (!onlymeta) pnm->cs = fz_device_gray(ctx); return pnm_binary_read_image(ctx, pnm, p, e, onlymeta, 1); } else if (!strcmp(signature, "P5")) { if (!onlymeta) pnm->cs = fz_device_gray(ctx); return pnm_binary_read_image(ctx, pnm, p, e, onlymeta, 0); } else if (!strcmp(signature, "P6")) { if (!onlymeta) pnm->cs = fz_device_rgb(ctx); return pnm_binary_read_image(ctx, pnm, p, e, onlymeta, 0); } else if (!strcmp(signature, "P7")) return pam_binary_read_image(ctx, pnm, p, e, onlymeta); else fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported portable anymap signature (0x%02x, 0x%02x)", signature[0], signature[1]); }
static fz_pixmap * pnm_binary_read_image(fz_context *ctx, struct info *pnm, unsigned char *p, unsigned char *e, int onlymeta, int bitmap) { fz_pixmap *img = NULL; p = pnm_read_number(ctx, p, e, &pnm->width); p = pnm_read_white(ctx, p, e, 0); if (bitmap) { p = pnm_read_number(ctx, p, e, &pnm->height); p = pnm_read_white(ctx, p, e, 1); pnm->maxval = 1; } else { p = pnm_read_number(ctx, p, e, &pnm->height); p = pnm_read_white(ctx, p, e, 0); p = pnm_read_number(ctx, p, e, &pnm->maxval); p = pnm_read_white(ctx, p, e, 1); if (pnm->maxval < 0 || pnm->maxval >= 65536) fz_throw(ctx, FZ_ERROR_GENERIC, "maximum sample value of out range in pnm image: %d", pnm->maxval); } if (!onlymeta) { unsigned char *dp; int x, y, k; img = fz_new_pixmap(ctx, pnm->cs, pnm->width, pnm->height, 0); dp = img->samples; if (bitmap) { for (y = 0; y < pnm->height; y++) { for (x = 0; x < pnm->width; x++) { if (*p & (1 << (7 - (x & 0x7)))) *dp = 0x00; else *dp = 0xff; dp++; if ((x & 0x7) == 7) p++; } if (pnm->width & 0x7) p++; } } else { if (pnm->maxval == 255) { for (y = 0; y < pnm->height; y++) for (x = 0; x < pnm->width; x++) for (k = 0; k < img->colorspace->n; k++) *dp++ = *p++; } else if (pnm->maxval < 256) { for (y = 0; y < pnm->height; y++) for (x = 0; x < pnm->width; x++) for (k = 0; k < img->colorspace->n; k++) *dp++ = map_color(ctx, *p++, pnm->maxval, 255); } else { for (y = 0; y < pnm->height; y++) for (x = 0; x < pnm->width; x++) for (k = 0; k < img->colorspace->n; k++) { *dp++ = map_color(ctx, (p[0] << 8) | p[1], pnm->maxval, 255); p += 2; } } } } return img; }
static fz_pixmap * pnm_ascii_read_image(fz_context *ctx, struct info *pnm, unsigned char *p, unsigned char *e, int onlymeta, int bitmap) { fz_pixmap *img = NULL; p = pnm_read_number(ctx, p, e, &pnm->width); p = pnm_read_white(ctx, p, e, 0); if (bitmap) { p = pnm_read_number(ctx, p, e, &pnm->height); p = pnm_read_white(ctx, p, e, 1); pnm->maxval = 1; } else { p = pnm_read_number(ctx, p, e, &pnm->height); p = pnm_read_white(ctx, p, e, 0); p = pnm_read_number(ctx, p, e, &pnm->maxval); p = pnm_read_white(ctx, p, e, 0); if (pnm->maxval < 0 || pnm->maxval >= 65536) fz_throw(ctx, FZ_ERROR_GENERIC, "maximum sample value of out range in pnm image: %d", pnm->maxval); } if (!onlymeta) { unsigned char *dp; int x, y, k; img = fz_new_pixmap(ctx, pnm->cs, pnm->width, pnm->height, 0); dp = img->samples; if (bitmap) { for (y = 0; y < pnm->height; y++) { for (x = 0; x < pnm->width; x++) { int v = 0; p = pnm_read_number(ctx, p, e, &v); p = pnm_read_white(ctx, p, e, 0); if (v == 0) *dp = 0x00; else *dp = 0xff; dp++; } } } else { for (y = 0; y < pnm->height; y++) for (x = 0; x < pnm->width; x++) for (k = 0; k < img->colorspace->n; k++) { int v = 0; p = pnm_read_number(ctx, p, e, &v); p = pnm_read_white(ctx, p, e, 0); v = fz_clampi(v, 0, pnm->maxval); *dp++ = map_color(ctx, v, pnm->maxval, 255); } } } return img; }
static fz_pixmap * pnm_binary_read_image(fz_context *ctx, struct info *pnm, const unsigned char *p, const unsigned char *e, int onlymeta, int bitmap, const unsigned char **out) { fz_pixmap *img = NULL; pnm->width = 0; p = pnm_read_number(ctx, p, e, &pnm->width); p = pnm_read_white(ctx, p, e, 0); if (bitmap) { pnm->height = 0; p = pnm_read_number(ctx, p, e, &pnm->height); p = pnm_read_white(ctx, p, e, 1); pnm->maxval = 1; } else { pnm->height = 0; p = pnm_read_number(ctx, p, e, &pnm->height); p = pnm_read_white(ctx, p, e, 0); pnm->maxval = 0; p = pnm_read_number(ctx, p, e, &pnm->maxval); p = pnm_read_white(ctx, p, e, 1); } if (pnm->maxval <= 0 || pnm->maxval >= 65536) fz_throw(ctx, FZ_ERROR_GENERIC, "maximum sample value of out range in pnm image: %d", pnm->maxval); pnm->bitdepth = bitdepth_from_maxval(pnm->maxval); if (pnm->height <= 0) fz_throw(ctx, FZ_ERROR_GENERIC, "image height must be > 0"); if (pnm->width <= 0) fz_throw(ctx, FZ_ERROR_GENERIC, "image width must be > 0"); if ((unsigned int)pnm->height > UINT_MAX / pnm->width / fz_colorspace_n(ctx, pnm->cs) / (pnm->bitdepth / 8 + 1)) fz_throw(ctx, FZ_ERROR_GENERIC, "image too large"); if (onlymeta) { int w = pnm->width; int h = pnm->height; int n = fz_colorspace_n(ctx, pnm->cs); if (pnm->maxval == 255) p += n * w * h; else if (bitmap) p += ((w + 7) / 8) * h; else if (pnm->maxval < 255) p += n * w * h; else p += 2 * n * w * h; } else { unsigned char *dp; int x, y, k; int w, h, n; img = fz_new_pixmap(ctx, pnm->cs, pnm->width, pnm->height, NULL, 0); dp = img->samples; w = img->w; h = img->h; n = img->n; if (pnm->maxval == 255) { memcpy(dp, p, w * h * n); p += n * w * h; } else if (bitmap) { for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { *dp++ = (*p & (1 << (7 - (x & 0x7)))) ? 0x00 : 0xff; if ((x & 0x7) == 7) p++; } if (w & 0x7) p++; } } else if (pnm->maxval < 255) { for (y = 0; y < h; y++) for (x = 0; x < w; x++) for (k = 0; k < n; k++) *dp++ = map_color(ctx, *p++, pnm->maxval, 255); } else { for (y = 0; y < h; y++) for (x = 0; x < w; x++) for (k = 0; k < n; k++) { *dp++ = map_color(ctx, (p[0] << 8) | p[1], pnm->maxval, 255); p += 2; } } } if (out) *out = p; return img; }
static fz_pixmap * pnm_ascii_read_image(fz_context *ctx, struct info *pnm, const unsigned char *p, const unsigned char *e, int onlymeta, int bitmap, const unsigned char **out) { fz_pixmap *img = NULL; p = pnm_read_number(ctx, p, e, &pnm->width); p = pnm_read_white(ctx, p, e, 0); if (bitmap) { p = pnm_read_number(ctx, p, e, &pnm->height); p = pnm_read_white(ctx, p, e, 1); pnm->maxval = 1; } else { p = pnm_read_number(ctx, p, e, &pnm->height); p = pnm_read_white(ctx, p, e, 0); p = pnm_read_number(ctx, p, e, &pnm->maxval); p = pnm_read_white(ctx, p, e, 0); } if (pnm->maxval <= 0 || pnm->maxval >= 65536) fz_throw(ctx, FZ_ERROR_GENERIC, "maximum sample value of out range in pnm image: %d", pnm->maxval); pnm->bitdepth = bitdepth_from_maxval(pnm->maxval); if (pnm->height <= 0) fz_throw(ctx, FZ_ERROR_GENERIC, "image height must be > 0"); if (pnm->width <= 0) fz_throw(ctx, FZ_ERROR_GENERIC, "image width must be > 0"); if ((unsigned int)pnm->height > UINT_MAX / pnm->width / fz_colorspace_n(ctx, pnm->cs) / (pnm->bitdepth / 8 + 1)) fz_throw(ctx, FZ_ERROR_GENERIC, "image too large"); if (onlymeta) { int x, y, k; int w, h, n; w = pnm->width; h = pnm->height; n = fz_colorspace_n(ctx, pnm->cs); if (bitmap) { for (y = 0; y < h; y++) for (x = -1; x < w; x++) { p = pnm_read_number(ctx, p, e, NULL); p = pnm_read_white(ctx, p, e, 0); } } else { for (y = 0; y < h; y++) for (x = 0; x < w; x++) for (k = 0; k < n; k++) { p = pnm_read_number(ctx, p, e, NULL); p = pnm_read_white(ctx, p, e, 0); } } } else { unsigned char *dp; int x, y, k; int w, h, n; img = fz_new_pixmap(ctx, pnm->cs, pnm->width, pnm->height, NULL, 0); dp = img->samples; w = img->w; h = img->h; n = img->n; if (bitmap) { for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { int v = 0; p = pnm_read_number(ctx, p, e, &v); p = pnm_read_white(ctx, p, e, 0); *dp++ = v ? 0x00 : 0xff; } } } else { for (y = 0; y < h; y++) for (x = 0; x < w; x++) for (k = 0; k < n; k++) { int v = 0; p = pnm_read_number(ctx, p, e, &v); p = pnm_read_white(ctx, p, e, 0); v = fz_clampi(v, 0, pnm->maxval); *dp++ = map_color(ctx, v, pnm->maxval, 255); } } } if (out) *out = p; return img; }