From: Tony Cook Date: Tue, 1 Apr 2008 09:24:17 +0000 (+0000) Subject: add i_gsamp_bg/i_gsampf_bg functions, sample based versions of X-Git-Tag: Imager-0.63~7 X-Git-Url: http://git.imager.perl.org/imager.git/commitdiff_plain/2a31a4b4a91f09ae942bf9efaf112839e1afaa6a?ds=sidebyside add i_gsamp_bg/i_gsampf_bg functions, sample based versions of i_adapt_colors() revert the pnm/jpeg writing code to closer to the older version, using i_gsamp_bg() to avoid the extra steps --- diff --git a/imager.h b/imager.h index 24fd57ec..de45b786 100644 --- a/imager.h +++ b/imager.h @@ -599,4 +599,12 @@ extern void i_adapt_fcolors_bg(int dest_channels, int src_channels, i_fcolor *colors, size_t count, i_fcolor const *bg); +extern int +i_gsamp_bg(i_img *im, int l, int r, int y, i_sample_t *samples, + int out_channels, i_color const *bg); + +extern int +i_gsampf_bg(i_img *im, int l, int r, int y, i_fsample_t *samples, + int out_channels, i_fcolor const *bg); + #endif diff --git a/jpeg.c b/jpeg.c index 38566f51..f886df25 100644 --- a/jpeg.c +++ b/jpeg.c @@ -673,7 +673,10 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) { (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); } } - else if (im->channels == want_channels) { + else { + i_color bg; + + i_get_file_background(im, &bg); data = mymalloc(im->xsize * im->channels); if (data) { while (cinfo.next_scanline < cinfo.image_height) { @@ -681,8 +684,8 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) { * Here the array is only one element long, but you could pass * more than one scanline at a time if that's more convenient. */ - i_gsamp(im, 0, im->xsize, cinfo.next_scanline, data, - NULL, im->channels); + i_gsamp_bg(im, 0, im->xsize, cinfo.next_scanline, data, + want_channels, &bg); row_pointer[0] = data; (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); } @@ -694,35 +697,6 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) { return 0; /* out of memory? */ } } - else { - i_color bg; - int x; - int ch; - i_color const *linep; - unsigned char * datap; - - line_buf = mymalloc(sizeof(i_color) * im->xsize); - - i_get_file_background(im, &bg); - - data = mymalloc(im->xsize * want_channels); - while (cinfo.next_scanline < cinfo.image_height) { - i_glin(im, 0, im->xsize, cinfo.next_scanline, line_buf); - i_adapt_colors_bg(want_channels, im->channels, line_buf, im->xsize, &bg); - datap = data; - linep = line_buf; - for (x = 0; x < im->xsize; ++x) { - for (ch = 0; ch < want_channels; ++ch) { - *datap++ = linep->channel[ch]; - } - ++linep; - } - row_pointer[0] = data; - (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); - } - myfree(line_buf); - myfree(data); - } /* Step 6: Finish compression */ diff --git a/paste.im b/paste.im index 669c6ca9..ef7d1445 100644 --- a/paste.im +++ b/paste.im @@ -325,7 +325,125 @@ i_adapt_fcolors_bg } break; } +} + +/* +=item i_gsamp_bg(im, l, r, y, samples, out_channels, bg) + +=item i_gsampf_bg(im, l, r, y, samples, out_channels, bg) + +This is similar to i_adapt_colors_bg() except it can only strip an +alpha channel. It cannot be used to convert a source RGB image to +greyscale. + +The samples parameter MUST include enough space for all samples of the +source image. + +=cut +*/ +int +#ifdef IM_EIGHT_BIT +i_gsamp_bg +#else +i_gsampf_bg +#endif +(i_img *im, int l, int r, int y, IM_SAMPLE_T *samples, + int out_channels, IM_COLOR const *bg) { + if (out_channels == im->channels) + return IM_GSAMP(im, l, r, y, samples, NULL, im->channels); + + switch (out_channels) { + case 1: + switch (im->channels) { + case 2: + { + int x; + IM_SAMPLE_T *inp = samples, *outp = samples; + IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg)); + int count; + + count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels); + if (!count) + return 0; + + for (x = l; x < r; ++x) { + *outp++ = ( inp[0] * inp[1] + + grey_bg * (IM_SAMPLE_MAX - inp[1])) / IM_SAMPLE_MAX; + inp += 2; + } + + return count; + } + break; + + default: + i_fatal(0, "i_gsamp_bg() can only remove alpha channels"); + break; + } + break; + case 3: + switch (im->channels) { + case 1: + { + int channels[3] = { 0, 0, 0 }; + return IM_GSAMP(im, l, r, y, samples, channels, out_channels); + } + case 2: + { + int x, ch; + IM_SAMPLE_T *inp = samples, *outp = samples; + int count; + int channels[4] = { 0, 0, 0, 1 }; + + count = IM_GSAMP(im, l, r, y, samples, channels, im->channels); + if (!count) + return 0; + + for (x = l; x < r; ++x) { + IM_WORK_T alpha = inp[3]; + for (ch = 0; ch < 3; ++ch) { + *outp++ = ( *inp++ * alpha + + bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX; + } + ++inp; + } + + return count; + } + + case 4: + { + int x, ch; + IM_SAMPLE_T *inp = samples, *outp = samples; + int count; + + count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels); + if (!count) + return 0; + + for (x = l; x < r; ++x) { + IM_WORK_T alpha = inp[3]; + for (ch = 0; ch < 3; ++ch) { + *outp++ = ( *inp++ * alpha + + bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX; + } + ++inp; + } + + return count; + } + break; + default: + i_fatal(0, "i_gsamp_bg() can only remove alpha channels"); + break; + } + break; + + default: + i_fatal(0, "i_gsamp_bg() can only remove alpha channels"); + } + return 0; } #/code diff --git a/pnm.c b/pnm.c index 609fbbc6..ca35437d 100644 --- a/pnm.c +++ b/pnm.c @@ -753,38 +753,23 @@ static int write_ppm_data_8(i_img *im, io_glue *ig, int want_channels) { int write_size = im->xsize * want_channels; - i_color *line_buf = mymalloc(sizeof(i_color) * im->xsize); - unsigned char *data = mymalloc(write_size); + int buf_size = im->xsize * im->channels; + unsigned char *data = mymalloc(buf_size); int y = 0; - int x; - int ch; int rc = 1; i_color bg; i_get_file_background(im, &bg); while (y < im->ysize && rc >= 0) { - i_color *linep = line_buf; - unsigned char *datap = data; - - i_glin(im, 0, im->xsize, y, line_buf); - i_adapt_colors_bg(want_channels, im->channels, line_buf, im->xsize, &bg); - for (x = 0; x < im->xsize; ++x) { - for (ch = 0; ch < want_channels; ++ch) { - *datap++ = linep->channel[ch]; - } - ++linep; - } + i_gsamp_bg(im, 0, im->xsize, y, data, want_channels, &bg); if (i_io_write(ig, data, write_size) != write_size) { i_push_error(errno, "could not write ppm data"); - myfree(data); - myfree(line_buf); rc = 0; break; } ++y; } myfree(data); - myfree(line_buf); return rc; } @@ -792,10 +777,14 @@ write_ppm_data_8(i_img *im, io_glue *ig, int want_channels) { static int write_ppm_data_16(i_img *im, io_glue *ig, int want_channels) { + int line_size = im->channels * im->xsize * sizeof(i_fsample_t); int sample_count = want_channels * im->xsize; int write_size = sample_count * 2; - i_fcolor *line_buf = mymalloc(sizeof(i_fcolor) * im->xsize); + i_fsample_t *line_buf = mymalloc(line_size); + i_fsample_t *samplep; unsigned char *write_buf = mymalloc(write_size); + unsigned char *writep; + int sample_num; int y = 0; int x, ch; int rc = 1; @@ -804,20 +793,14 @@ write_ppm_data_16(i_img *im, io_glue *ig, int want_channels) { i_get_file_backgroundf(im, &bg); while (y < im->ysize) { - i_fcolor *linep = line_buf; - unsigned char *writep = write_buf; - - i_glinf(im, 0, im->xsize, y, line_buf); - i_adapt_fcolors_bg(want_channels, im->channels, line_buf, im->xsize, &bg); - for (x = 0; x < im->xsize; ++x) { - for (ch = 0; ch < want_channels; ++ch) { - unsigned sample16 = SampleFTo16(linep->channel[ch]); - *writep++ = sample16 >> 8; - *writep++ = sample16 & 0xFF; - } - ++linep; + i_gsampf_bg(im, 0, im->xsize, y, line_buf, want_channels, &bg); + samplep = line_buf; + writep = write_buf; + for (sample_num = 0; sample_num < sample_count; ++sample_num) { + unsigned sample16 = SampleFTo16(*samplep++); + *writep++ = sample16 >> 8; + *writep++ = sample16 & 0xFF; } - if (i_io_write(ig, write_buf, write_size) != write_size) { i_push_error(errno, "could not write ppm data"); rc = 0;