123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- #define JPEG_INTERNALS
- #include "jinclude.h"
- #include "jpeglib.h"
- #include "jsimd.h"
- typedef void (*downsample1_ptr) (j_compress_ptr cinfo,
- jpeg_component_info *compptr,
- JSAMPARRAY input_data,
- JSAMPARRAY output_data);
- typedef struct {
- struct jpeg_downsampler pub;
-
- downsample1_ptr methods[MAX_COMPONENTS];
- } my_downsampler;
- typedef my_downsampler *my_downsample_ptr;
- METHODDEF(void)
- start_pass_downsample(j_compress_ptr cinfo)
- {
-
- }
- LOCAL(void)
- expand_right_edge(JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols,
- JDIMENSION output_cols)
- {
- register JSAMPROW ptr;
- register JSAMPLE pixval;
- register int count;
- int row;
- int numcols = (int)(output_cols - input_cols);
- if (numcols > 0) {
- for (row = 0; row < num_rows; row++) {
- ptr = image_data[row] + input_cols;
- pixval = ptr[-1];
- for (count = numcols; count > 0; count--)
- *ptr++ = pixval;
- }
- }
- }
- METHODDEF(void)
- sep_downsample(j_compress_ptr cinfo, JSAMPIMAGE input_buf,
- JDIMENSION in_row_index, JSAMPIMAGE output_buf,
- JDIMENSION out_row_group_index)
- {
- my_downsample_ptr downsample = (my_downsample_ptr)cinfo->downsample;
- int ci;
- jpeg_component_info *compptr;
- JSAMPARRAY in_ptr, out_ptr;
- for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
- ci++, compptr++) {
- in_ptr = input_buf[ci] + in_row_index;
- out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);
- (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
- }
- }
- METHODDEF(void)
- int_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
- {
- int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
- JDIMENSION outcol, outcol_h;
- JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
- JSAMPROW inptr, outptr;
- JLONG outvalue;
- h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
- v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
- numpix = h_expand * v_expand;
- numpix2 = numpix / 2;
-
- expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width,
- output_cols * h_expand);
- inrow = 0;
- for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
- outptr = output_data[outrow];
- for (outcol = 0, outcol_h = 0; outcol < output_cols;
- outcol++, outcol_h += h_expand) {
- outvalue = 0;
- for (v = 0; v < v_expand; v++) {
- inptr = input_data[inrow + v] + outcol_h;
- for (h = 0; h < h_expand; h++) {
- outvalue += (JLONG)GETJSAMPLE(*inptr++);
- }
- }
- *outptr++ = (JSAMPLE)((outvalue + numpix2) / numpix);
- }
- inrow += v_expand;
- }
- }
- METHODDEF(void)
- fullsize_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
- {
-
- jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor,
- cinfo->image_width);
-
- expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width,
- compptr->width_in_blocks * DCTSIZE);
- }
- METHODDEF(void)
- h2v1_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
- {
- int outrow;
- JDIMENSION outcol;
- JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
- register JSAMPROW inptr, outptr;
- register int bias;
-
- expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width,
- output_cols * 2);
- for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
- outptr = output_data[outrow];
- inptr = input_data[outrow];
- bias = 0;
- for (outcol = 0; outcol < output_cols; outcol++) {
- *outptr++ =
- (JSAMPLE)((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + bias) >> 1);
- bias ^= 1;
- inptr += 2;
- }
- }
- }
- METHODDEF(void)
- h2v2_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
- {
- int inrow, outrow;
- JDIMENSION outcol;
- JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
- register JSAMPROW inptr0, inptr1, outptr;
- register int bias;
-
- expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width,
- output_cols * 2);
- inrow = 0;
- for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
- outptr = output_data[outrow];
- inptr0 = input_data[inrow];
- inptr1 = input_data[inrow + 1];
- bias = 1;
- for (outcol = 0; outcol < output_cols; outcol++) {
- *outptr++ =
- (JSAMPLE)((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
- GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + bias) >> 2);
- bias ^= 3;
- inptr0 += 2; inptr1 += 2;
- }
- inrow += 2;
- }
- }
- #ifdef INPUT_SMOOTHING_SUPPORTED
- METHODDEF(void)
- h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
- {
- int inrow, outrow;
- JDIMENSION colctr;
- JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
- register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
- JLONG membersum, neighsum, memberscale, neighscale;
-
- expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
- cinfo->image_width, output_cols * 2);
-
- memberscale = 16384 - cinfo->smoothing_factor * 80;
- neighscale = cinfo->smoothing_factor * 16;
- inrow = 0;
- for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
- outptr = output_data[outrow];
- inptr0 = input_data[inrow];
- inptr1 = input_data[inrow + 1];
- above_ptr = input_data[inrow - 1];
- below_ptr = input_data[inrow + 2];
-
- membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
- GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
- neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
- GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
- GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
- GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
- neighsum += neighsum;
- neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
- GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
- membersum = membersum * memberscale + neighsum * neighscale;
- *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
- inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
- for (colctr = output_cols - 2; colctr > 0; colctr--) {
-
- membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
- GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
-
- neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
- GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
- GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
- GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
-
- neighsum += neighsum;
-
- neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
- GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
-
- membersum = membersum * memberscale + neighsum * neighscale;
-
- *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
- inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
- }
-
- membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
- GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
- neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
- GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
- GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
- GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
- neighsum += neighsum;
- neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
- GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
- membersum = membersum * memberscale + neighsum * neighscale;
- *outptr = (JSAMPLE)((membersum + 32768) >> 16);
- inrow += 2;
- }
- }
- METHODDEF(void)
- fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr,
- JSAMPARRAY input_data, JSAMPARRAY output_data)
- {
- int outrow;
- JDIMENSION colctr;
- JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
- register JSAMPROW inptr, above_ptr, below_ptr, outptr;
- JLONG membersum, neighsum, memberscale, neighscale;
- int colsum, lastcolsum, nextcolsum;
-
- expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
- cinfo->image_width, output_cols);
-
- memberscale = 65536L - cinfo->smoothing_factor * 512L;
- neighscale = cinfo->smoothing_factor * 64;
- for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
- outptr = output_data[outrow];
- inptr = input_data[outrow];
- above_ptr = input_data[outrow - 1];
- below_ptr = input_data[outrow + 1];
-
- colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
- GETJSAMPLE(*inptr);
- membersum = GETJSAMPLE(*inptr++);
- nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
- GETJSAMPLE(*inptr);
- neighsum = colsum + (colsum - membersum) + nextcolsum;
- membersum = membersum * memberscale + neighsum * neighscale;
- *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
- lastcolsum = colsum; colsum = nextcolsum;
- for (colctr = output_cols - 2; colctr > 0; colctr--) {
- membersum = GETJSAMPLE(*inptr++);
- above_ptr++; below_ptr++;
- nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
- GETJSAMPLE(*inptr);
- neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
- membersum = membersum * memberscale + neighsum * neighscale;
- *outptr++ = (JSAMPLE)((membersum + 32768) >> 16);
- lastcolsum = colsum; colsum = nextcolsum;
- }
-
- membersum = GETJSAMPLE(*inptr);
- neighsum = lastcolsum + (colsum - membersum) + colsum;
- membersum = membersum * memberscale + neighsum * neighscale;
- *outptr = (JSAMPLE)((membersum + 32768) >> 16);
- }
- }
- #endif
- GLOBAL(void)
- jinit_downsampler(j_compress_ptr cinfo)
- {
- my_downsample_ptr downsample;
- int ci;
- jpeg_component_info *compptr;
- boolean smoothok = TRUE;
- downsample = (my_downsample_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
- sizeof(my_downsampler));
- cinfo->downsample = (struct jpeg_downsampler *)downsample;
- downsample->pub.start_pass = start_pass_downsample;
- downsample->pub.downsample = sep_downsample;
- downsample->pub.need_context_rows = FALSE;
- if (cinfo->CCIR601_sampling)
- ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
-
- for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
- ci++, compptr++) {
- if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
- compptr->v_samp_factor == cinfo->max_v_samp_factor) {
- #ifdef INPUT_SMOOTHING_SUPPORTED
- if (cinfo->smoothing_factor) {
- downsample->methods[ci] = fullsize_smooth_downsample;
- downsample->pub.need_context_rows = TRUE;
- } else
- #endif
- downsample->methods[ci] = fullsize_downsample;
- } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
- compptr->v_samp_factor == cinfo->max_v_samp_factor) {
- smoothok = FALSE;
- if (jsimd_can_h2v1_downsample())
- downsample->methods[ci] = jsimd_h2v1_downsample;
- else
- downsample->methods[ci] = h2v1_downsample;
- } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
- compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {
- #ifdef INPUT_SMOOTHING_SUPPORTED
- if (cinfo->smoothing_factor) {
- #if defined(__mips__)
- if (jsimd_can_h2v2_smooth_downsample())
- downsample->methods[ci] = jsimd_h2v2_smooth_downsample;
- else
- #endif
- downsample->methods[ci] = h2v2_smooth_downsample;
- downsample->pub.need_context_rows = TRUE;
- } else
- #endif
- {
- if (jsimd_can_h2v2_downsample())
- downsample->methods[ci] = jsimd_h2v2_downsample;
- else
- downsample->methods[ci] = h2v2_downsample;
- }
- } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
- (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {
- smoothok = FALSE;
- downsample->methods[ci] = int_downsample;
- } else
- ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
- }
- #ifdef INPUT_SMOOTHING_SUPPORTED
- if (cinfo->smoothing_factor && !smoothok)
- TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
- #endif
- }
|