Permalink
Browse files

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
  • Loading branch information...
1 parent fa90de9 commit 2a31a4b4a91f09ae942bf9efaf112839e1afaa6a Tony Cook committed Apr 1, 2008
Showing with 147 additions and 64 deletions.
  1. +8 −0 imager.h
  2. +6 −32 jpeg.c
  3. +118 −0 paste.im
  4. +15 −32 pnm.c
View
@@ -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
View
38 jpeg.c
@@ -673,16 +673,19 @@ 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) {
/* jpeg_write_scanlines expects an array of pointers to scanlines.
* 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 */
View
118 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
View
47 pnm.c
@@ -753,49 +753,38 @@ 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;
}
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;

0 comments on commit 2a31a4b

Please sign in to comment.