diff options
Diffstat (limited to 'source/fitz/output-pnm.c')
-rw-r--r-- | source/fitz/output-pnm.c | 154 |
1 files changed, 112 insertions, 42 deletions
diff --git a/source/fitz/output-pnm.c b/source/fitz/output-pnm.c index 9bc5e6aa..598d66f6 100644 --- a/source/fitz/output-pnm.c +++ b/source/fitz/output-pnm.c @@ -15,6 +15,9 @@ pnm_write_header(fz_context *ctx, fz_band_writer *writer, const fz_colorspace *c if (writer->s != 0) fz_throw(ctx, FZ_ERROR_GENERIC, "PNM writer cannot cope with spot colors"); + if (alpha) + fz_throw(ctx, FZ_ERROR_GENERIC, "PNM writer cannot cope with alpha"); + n -= alpha; if (n != 1 && n != 3) fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pnm"); @@ -34,12 +37,10 @@ pnm_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_sta int w = writer->w; int h = writer->h; int n = writer->n; - int alpha = writer->alpha; - char buffer[2*3*4*5*6]; /* Buffer must be a multiple of 2 and 3 at least. */ int len; int end = band_start + band_height; - if (n-alpha != 1 && n-alpha != 3) + if (n != 1 && n != 3) fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pnm"); if (!out) @@ -67,44 +68,10 @@ pnm_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_sta fz_write_data(ctx, out, p, num_written); p += num_written; break; - case 2: - { - char *o = buffer; - int count; - - if (num_written > sizeof(buffer)) - num_written = sizeof(buffer); - - for (count = num_written; count; count--) - { - *o++ = *p; - p += 2; - } - fz_write_data(ctx, out, buffer, num_written); - break; - } case 3: fz_write_data(ctx, out, p, num_written*3); p += num_written*3; break; - case 4: - { - char *o = buffer; - int count; - - if (num_written > sizeof(buffer)/3) - num_written = sizeof(buffer)/3; - - for (count = num_written; count; count--) - { - *o++ = p[0]; - *o++ = p[1]; - *o++ = p[2]; - p += n; - } - fz_write_data(ctx, out, buffer, num_written * 3); - break; - } } len -= num_written; } @@ -191,7 +158,7 @@ pam_write_header(fz_context *ctx, fz_band_writer *writer, const fz_colorspace *c else if (n == 3 && !alpha) fz_write_printf(ctx, out, "TUPLTYPE RGB\n"); else if (n == 3 && alpha) fz_write_printf(ctx, out, "TUPLTYPE RGB_ALPHA\n"); else if (n == 4 && !alpha) fz_write_printf(ctx, out, "TUPLTYPE CMYK\n"); - else if (n == 5) fz_write_printf(ctx, out, "TUPLTYPE CMYK_ALPHA\n"); + else if (n == 4 && alpha) fz_write_printf(ctx, out, "TUPLTYPE CMYK_ALPHA\n"); fz_write_printf(ctx, out, "ENDHDR\n"); } @@ -202,7 +169,8 @@ pam_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_sta int w = writer->w; int h = writer->h; int n = writer->n; - int y; + int alpha = writer->alpha; + int x, y; int end = band_start + band_height; if (!out) @@ -212,11 +180,113 @@ pam_write_band(fz_context *ctx, fz_band_writer *writer, int stride, int band_sta end = h; end -= band_start; - for (y = 0; y < end; y++) + if (alpha) { - fz_write_data(ctx, out, sp, w * n); - sp += stride; + /* Buffer must be a multiple of 2, 3 and 5 at least. */ + /* Also, for the generic case, it must be bigger than FZ_MAX_COLORS */ + char buffer[2*3*4*5*6]; + char *b = buffer; + stride -= n * w; + switch (n) + { + case 2: + for (y = 0; y < end; y++) + { + for (x = 0; x < w; x++) + { + int a = sp[1]; + *b++ = a ? (sp[0] * 255 + (a>>1))/a : 0; + *b++ = a; + sp += 2; + if (b == &buffer[sizeof(buffer)]) + { + fz_write_data(ctx, out, buffer, sizeof(buffer)); + b = buffer; + } + } + sp += stride; + } + if (b != buffer) + fz_write_data(ctx, out, buffer, b - buffer); + break; + case 4: + for (y = 0; y < end; y++) + { + for (x = 0; x < w; x++) + { + int a = sp[3]; + int inva = a ? 256 * 255 / a : 0; + *b++ = (sp[0] * inva + 128)>>8; + *b++ = (sp[1] * inva + 128)>>8; + *b++ = (sp[2] * inva + 128)>>8; + *b++ = a; + sp += 4; + if (b == &buffer[sizeof(buffer)]) + { + fz_write_data(ctx, out, buffer, sizeof(buffer)); + b = buffer; + } + } + sp += stride; + } + if (b != buffer) + fz_write_data(ctx, out, buffer, b - buffer); + break; + case 5: + for (y = 0; y < end; y++) + { + for (x = 0; x < w; x++) + { + int a = sp[4]; + int inva = a ? 256 * 255 / a : 0; + *b++ = (sp[0] * inva + 128)>>8; + *b++ = (sp[1] * inva + 128)>>8; + *b++ = (sp[2] * inva + 128)>>8; + *b++ = (sp[3] * inva + 128)>>8; + *b++ = a; + sp += 5; + if (b == &buffer[sizeof(buffer)]) + { + fz_write_data(ctx, out, buffer, sizeof(buffer)); + b = buffer; + } + } + sp += stride; + } + if (b != buffer) + fz_write_data(ctx, out, buffer, b - buffer); + break; + default: + for (y = 0; y < end; y++) + { + for (x = 0; x < w; x++) + { + int a = sp[n-1]; + int inva = a ? 256 * 255 / a : 0; + int k; + for (k = 0; k < n-1; k++) + *b++ = (*sp++ * inva + 128)>>8; + *b++ = a; + sp++; + if (b >= &buffer[sizeof(buffer)] - n) + { + fz_write_data(ctx, out, buffer, b - buffer); + b = buffer; + } + } + sp += stride; + } + if (b != buffer) + fz_write_data(ctx, out, buffer, b - buffer); + break; + } } + else + for (y = 0; y < end; y++) + { + fz_write_data(ctx, out, sp, w * n); + sp += stride; + } } fz_band_writer *fz_new_pam_band_writer(fz_context *ctx, fz_output *out) |