📄 jpg2.c
字号:
static void process_raw_data ( webimage2_jpeg j, int num_scanlines ){ int y; switch (j->yuv_mode) { case jpeg_yuv_422: for ( y = 0; y< num_scanlines; y++ ) { JSAMPLE *row_Y = j->component_array[0][y]; JSAMPLE *row_U = j->component_array[1][y]; JSAMPLE *row_V = j->component_array[2][y]; unsigned char *bufferptr = (unsigned char *)j->sink->buffer[y]; unsigned int count = j->cinfo.output_width/2; /* round to zero so will miss last pixel */ while(count--) { unsigned int U = *row_U++, V = *row_V++; *bufferptr++ = *row_Y++; *bufferptr++ = U; *bufferptr++ = V; *bufferptr++ = *row_Y++; *bufferptr++ = U; *bufferptr++ = V; } /* fixup any final odd pixel. U and V planes will be slightly enlarged to allow for this */ if ((j->cinfo.output_width & 1) !=0 ) { *bufferptr++ = *row_Y++; *bufferptr++ = *row_U++; *bufferptr++ = *row_V++; } } (*j->sink->put_pixel_rows)( &j->cinfo, j->sink, num_scanlines ); break; case jpeg_yuv_420: for ( y = 0; y< num_scanlines; y++ ) { JSAMPLE *row_Y = j->component_array[0][y]; JSAMPLE *row_U = j->component_array[1][y/2]; JSAMPLE *row_V = j->component_array[2][y/2]; unsigned char *bufferptr = (unsigned char *)j->sink->buffer[y]; unsigned int count = j->cinfo.output_width/2; /* round to zero so will miss last pixel */ while(count--) { unsigned int U = *row_U++, V = *row_V++; *bufferptr++ = *row_Y++; *bufferptr++ = U; *bufferptr++ = V; *bufferptr++ = *row_Y++; *bufferptr++ = U; *bufferptr++ = V; } /* fixup any final odd pixel. U and V planes will be slightly enlarged to allow for this */ if ((j->cinfo.output_width & 1) !=0 ) { *bufferptr++ = *row_Y++; *bufferptr++ = *row_U++; *bufferptr++ = *row_V++; } } (*j->sink->put_pixel_rows)( &j->cinfo, j->sink, num_scanlines ); break; case jpeg_yuv_111: for ( y = 0; y< num_scanlines; y++ ) { JSAMPLE *row_Y = j->component_array[0][y]; JSAMPLE *row_U = j->component_array[1][y]; JSAMPLE *row_V = j->component_array[2][y]; unsigned char *bufferptr = (unsigned char *)j->sink->buffer[y]; unsigned int count = j->cinfo.output_width; while(count--) { *bufferptr++ = *row_Y++; *bufferptr++ = *row_U++; *bufferptr++ = *row_V++; } } (*j->sink->put_pixel_rows)( &j->cinfo, j->sink, num_scanlines ); break; case jpeg_yuv_GREY: for ( y = 0; y< num_scanlines; y++ ) { JSAMPLE *row_Y = j->component_array[0][y]; unsigned char *bufferptr = (unsigned char *)j->sink->buffer[y]; unsigned int count = j->cinfo.output_width; while(count--) { *bufferptr++ = *row_Y++; *bufferptr++ = 0x80; /* 0 values for U,V in unsigned format */ *bufferptr++ = 0x80; } } (*j->sink->put_pixel_rows)( &j->cinfo, j->sink, num_scanlines ); break; default: ASSERT(0); /* in release builds we'll fall through to the jpeg_yuv_OTHER */ case jpeg_yuv_OTHER: /* generic code which ought to deal with any left-overs */ { /* divisors for rescaling each component */ unsigned int v_Y_divisor = j->max_v_samp_factor/j->sampling[0].v_samp_factor; unsigned int v_U_divisor = j->max_v_samp_factor/j->sampling[1].v_samp_factor; unsigned int v_V_divisor = j->max_v_samp_factor/j->sampling[2].v_samp_factor; unsigned int h_Y_divisor = j->max_h_samp_factor/j->sampling[0].h_samp_factor; unsigned int h_U_divisor = j->max_h_samp_factor/j->sampling[1].h_samp_factor; unsigned int h_V_divisor = j->max_h_samp_factor/j->sampling[2].h_samp_factor; for (y = 0; y<num_scanlines; y++) { JSAMPLE *row_Y = j->component_array[0][y/v_Y_divisor]; JSAMPLE *row_U = j->component_array[1][y/v_U_divisor]; JSAMPLE *row_V = j->component_array[2][y/v_V_divisor]; unsigned char *bufferptr = (unsigned char *)j->sink->buffer[y]; unsigned int x; for (x = 0; x<j->cinfo.output_width; x++ ) { *bufferptr++ = row_Y[x/h_Y_divisor]; *bufferptr++ = row_U[x/h_U_divisor]; *bufferptr++ = row_V[x/h_V_divisor]; } } (*j->sink->put_pixel_rows)( &j->cinfo, j->sink, num_scanlines ); } break; }}/* * This function works out the yuv mode. */static jpeg_yuv_mode get_yuv_mode ( webimage2_jpeg j ){ if ( j->sampling[0].v_samp_factor == 1 && j->sampling[1].v_samp_factor == 1 && j->sampling[2].v_samp_factor == 1 && j->sampling[0].h_samp_factor == 2 && j->sampling[1].h_samp_factor == 1 && j->sampling[2].h_samp_factor == 1 ) { WIDBGN(("JPEG %p is 4:2:2\n",j)); return jpeg_yuv_422; } else if (j->sampling[0].v_samp_factor == 2 && j->sampling[1].v_samp_factor == 1 && j->sampling[2].v_samp_factor == 1 && j->sampling[0].h_samp_factor == 2 && j->sampling[1].h_samp_factor == 1 && j->sampling[2].h_samp_factor == 1 ) { WIDBGN(("JPEG %p is 4:2:0\n",j)); return jpeg_yuv_420; } else if (j->sampling[0].v_samp_factor == 1 && j->sampling[1].v_samp_factor == 1 && j->sampling[2].v_samp_factor == 1 && j->sampling[0].h_samp_factor == 1 && j->sampling[1].h_samp_factor == 1 && j->sampling[2].h_samp_factor == 1 ) { WIDBGN(("JPEG %p is 1:1:1\n",j)); return jpeg_yuv_111; } else { WIDBGN(("JPEG %p is unknown YUV format\n",j)); return jpeg_yuv_OTHER; }}#endifstatic void call_changed_function( webimage2_jpeg j, int num_scanlines ){ /* call changed function if set */ if ( j->w->changed ) { layers_box changed;#if LAYERS_FB_32BITS switch ( j->rotate ) { case webimage_rotate_NONE: /* full width */ changed.x0 = 0; changed.x1 = j->cinfo.output_width; /* output_scanline has already been advanced so subtract the * number of lines to get start point */ changed.y0 = j->cinfo.output_scanline - num_scanlines; changed.y1 = j->cinfo.output_scanline; (*j->w->changed)( &changed, j->w->handle ); break; case webimage_rotate_LEFT_90: /* full width */ changed.y0 = 0; changed.y1 = j->cinfo.output_width; /* output_scanline has already been advanced so subtract the * number of lines to get start point */ changed.x0 = j->cinfo.output_scanline - num_scanlines; changed.x1 = j->cinfo.output_scanline; (*j->w->changed)( &changed, j->w->handle ); break; case webimage_rotate_LEFT_180: /* full width */ changed.x0 = 0; changed.x1 = j->cinfo.output_width; /* output_scanline has already been advanced so subtract the * number of lines to get start point */ changed.y1 = j->cinfo.output_height - (j->cinfo.output_scanline - num_scanlines); changed.y0 = j->cinfo.output_height - (j->cinfo.output_scanline); (*j->w->changed)( &changed, j->w->handle ); break; case webimage_rotate_LEFT_270: /* full width */ changed.y0 = 0; changed.y1 = j->cinfo.output_width; /* output_scanline has already been advanced so subtract the * number of lines to get start point */ changed.x1 = j->cinfo.output_height - (j->cinfo.output_scanline - num_scanlines); changed.x0 = j->cinfo.output_height - (j->cinfo.output_scanline); (*j->w->changed)( &changed, j->w->handle ); break; }#else /* full width */ changed.x0 = 0; changed.x1 = j->cinfo.output_width; /* output_scanline has already been advanced so subtract the * number of lines to get start point */ changed.y0 = j->cinfo.output_scanline - num_scanlines; changed.y1 = j->cinfo.output_scanline; (*j->w->changed)( &changed, j->w->handle );#endif }} /*=====================================* * Data feed/decoder state machine * *=====================================*//** The actual state machine is in a separate function as some compilers get * scared by the presence of setjmp/longjmp */static webimage2_rc webimage2__jpeg_state_machine( webimage2_jpeg j ){ BOOL deepsprite; djpeg_dest_ptr dest_mgr = j->sink; /* State machine for JPEG decoder. The states from jpegstate_START * to jpegstate_FINISHING are run through in order for non-progressive * JPEGs. A goto, halfway down, leaps into the sequence of states for * progressive JPEGs (state_PROGRESSIVE to state_PROGRESSIVE_IMAGE). * According to libjpeg.doc, the libjpeg calls that can suspend are: * jpeg_read_header * jpeg_start_decompress * jpeg_read_scanlines * jpeg_finish_decompress * jpeg_start_output * jpeg_finish_output */ WIDBG(("wi%p: Entering JPEG state machine in state %d\n", j->w, j->state )); switch ( j->state ) { case jpegstate_START: jpeg_create_decompress( &j->cinfo ); webimage2__src( &j->cinfo, j ); j->state = jpegstate_HEADER; /* drop through */ case jpegstate_HEADER: if ( jpeg_read_header( &j->cinfo, TRUE ) == JPEG_SUSPENDED ) return webimage2_OK; /* Suspension point */ deepsprite = (j->w->flags & webimage_DEEPSPRITE) != 0; /* set scaling factors and recalculate the output values */ j->cinfo.scale_num = j->w->scale_mag; j->cinfo.scale_denom = j->w->scale_div; jpeg_calc_output_dimensions(&j->cinfo); #ifdef JPEG_CUT_OFF_SIZE if (j->cinfo.output_width * j->cinfo.output_height >= JPEG_CUT_OFF_SIZE) deepsprite = FALSE; /* Don't do huge deepsprite jpegs */#endif if (j->cinfo.out_color_space == JCS_GRAYSCALE) {#if LAYERS_FB_32BITS if ( (j->w->flags & webimage_JPEGYUV422) != 0 ) { j->component_array[0] = (*j->cinfo.mem->alloc_sarray) ((j_common_ptr) &j->cinfo, JPOOL_IMAGE, j->cinfo.comp_info[0].downsampled_width*2, j->cinfo.comp_info[0].DCT_scaled_size ); j->cinfo.raw_data_out = TRUE; j->yuv_mode = jpeg_yuv_GREY; } else#endif /* LAYERS_FB_32BITS */ if (deepsprite) { j->cinfo.desired_number_of_colors = 256; j->cinfo.quantize_colors = TRUE; } else { j->cinfo.desired_number_of_colors = 16; j->cinfo.quantize_colors = TRUE; } }#if LAYERS_FB_32BITS else if ((j->w->flags & webimage_JPEGYUV422) != 0 && j->cinfo.jpeg_color_space == JCS_YCbCr ) { int i; jpeg_component_info *compptr; int min_h_samp_factor, min_v_samp_factor; /* allocate arrays and calculate new down-sampling factors * as the JPEg library does different things on each * components to best use of the data available */ j->max_h_samp_factor = 1; j->max_v_samp_factor = 1; min_h_samp_factor = INT_MAX; min_v_samp_factor = INT_MAX; for ( i = 0, compptr = j->cinfo.comp_info; i < 3; i++, compptr++ ) { j->component_array[i] = (*j->cinfo.mem->alloc_sarray) ((j_common_ptr) &j->cinfo, JPOOL_IMAGE, compptr->downsampled_width*2, (JDIMENSION) compptr->v_samp_factor*compptr->DCT_scaled_size); j->sampling[i].h_samp_factor = compptr->h_samp_factor * compptr->DCT_scaled_size / j->cinfo.min_DCT_scaled_size; j->sampling[i].v_samp_factor = compptr->v_samp_factor * compptr->DCT_scaled_size / j->cinfo.min_DCT_scaled_size; if ( j->max_h_samp_factor < j->sampling[i].h_samp_factor ) j->max_h_samp_factor = j->sampling[i].h_samp_factor; if ( j->max_v_samp_factor < j->sampling[i].v_samp_factor ) j->max_v_samp_factor = j->sampling[i].v_samp_factor; if ( min_h_samp_factor > j->sampling[i].h_samp_factor ) min_h_samp_factor = j->sampling[i].h_samp_factor; if ( min_v_samp_factor > j->sampling[i].v_samp_factor ) min_v_samp_factor = j->sampling[i].v_samp_factor; WIDBGN(("component %d: old sampling %dx%d, new sampling %dx%d\n", i, compptr->h_samp_factor, compptr->v_samp_factor, j->sampling[i].h_samp_factor, j->sampling[i].v_samp_factor)); } /* reduce the scaling factors */ for ( i = 0; i < 3; i++ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -