📄 transupp.c
字号:
* *strptr is advanced over the digit string, and *result is set to its value. */LOCAL(boolean)jt_read_integer (const char ** strptr, JDIMENSION * result){ const char * ptr = *strptr; JDIMENSION val = 0; for (; isdigit(*ptr); ptr++) { val = val * 10 + (JDIMENSION) (*ptr - '0'); } *result = val; if (ptr == *strptr) return FALSE; /* oops, no digits */ *strptr = ptr; return TRUE;}/* Parse a crop specification (written in X11 geometry style). * The routine returns TRUE if the spec string is valid, FALSE if not. * * The crop spec string should have the format * <width>x<height>{+-}<xoffset>{+-}<yoffset> * where width, height, xoffset, and yoffset are unsigned integers. * Each of the elements can be omitted to indicate a default value. * (A weakness of this style is that it is not possible to omit xoffset * while specifying yoffset, since they look alike.) * * This code is loosely based on XParseGeometry from the X11 distribution. */GLOBAL(boolean)jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec){ info->crop = FALSE; info->crop_width_set = JCROP_UNSET; info->crop_height_set = JCROP_UNSET; info->crop_xoffset_set = JCROP_UNSET; info->crop_yoffset_set = JCROP_UNSET; if (isdigit(*spec)) { /* fetch width */ if (! jt_read_integer(&spec, &info->crop_width)) return FALSE; info->crop_width_set = JCROP_POS; } if (*spec == 'x' || *spec == 'X') { /* fetch height */ spec++; if (! jt_read_integer(&spec, &info->crop_height)) return FALSE; info->crop_height_set = JCROP_POS; } if (*spec == '+' || *spec == '-') { /* fetch xoffset */ info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; spec++; if (! jt_read_integer(&spec, &info->crop_xoffset)) return FALSE; } if (*spec == '+' || *spec == '-') { /* fetch yoffset */ info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS; spec++; if (! jt_read_integer(&spec, &info->crop_yoffset)) return FALSE; } /* We had better have gotten to the end of the string. */ if (*spec != '\0') return FALSE; info->crop = TRUE; return TRUE;}/* Trim off any partial iMCUs on the indicated destination edge */LOCAL(void)trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width){ JDIMENSION MCU_cols; MCU_cols = info->output_width / (info->max_h_samp_factor * DCTSIZE); if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == full_width / (info->max_h_samp_factor * DCTSIZE)) info->output_width = MCU_cols * (info->max_h_samp_factor * DCTSIZE);}LOCAL(void)trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height){ JDIMENSION MCU_rows; MCU_rows = info->output_height / (info->max_v_samp_factor * DCTSIZE); if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == full_height / (info->max_v_samp_factor * DCTSIZE)) info->output_height = MCU_rows * (info->max_v_samp_factor * DCTSIZE);}/* Request any required workspace. * * This routine figures out the size that the output image will be * (which implies that all the transform parameters must be set before * it is called). * * We allocate the workspace virtual arrays from the source decompression * object, so that all the arrays (both the original data and the workspace) * will be taken into account while making memory management decisions. * Hence, this routine must be called after jpeg_read_header (which reads * the image dimensions) and before jpeg_read_coefficients (which realizes * the source's virtual arrays). */GLOBAL(void)jtransform_request_workspace (j_decompress_ptr srcinfo, jpeg_transform_info *info){ jvirt_barray_ptr *coef_arrays = NULL; boolean need_workspace, transpose_it; jpeg_component_info *compptr; JDIMENSION xoffset, yoffset, width_in_iMCUs, height_in_iMCUs; JDIMENSION width_in_blocks, height_in_blocks; int ci, h_samp_factor, v_samp_factor; /* Determine number of components in output image */ if (info->force_grayscale && srcinfo->jpeg_color_space == JCS_YCbCr && srcinfo->num_components == 3) { /* We'll only process the first component */ info->num_components = 1; } else { /* Process all the components */ info->num_components = srcinfo->num_components; } /* If there is only one output component, force the iMCU size to be 1; * else use the source iMCU size. (This allows us to do the right thing * when reducing color to grayscale, and also provides a handy way of * cleaning up "funny" grayscale images whose sampling factors are not 1x1.) */ switch (info->transform) { case JXFORM_TRANSPOSE: case JXFORM_TRANSVERSE: case JXFORM_ROT_90: case JXFORM_ROT_270: info->output_width = srcinfo->image_height; info->output_height = srcinfo->image_width; if (info->num_components == 1) { info->max_h_samp_factor = 1; info->max_v_samp_factor = 1; } else { info->max_h_samp_factor = srcinfo->max_v_samp_factor; info->max_v_samp_factor = srcinfo->max_h_samp_factor; } break; default: info->output_width = srcinfo->image_width; info->output_height = srcinfo->image_height; if (info->num_components == 1) { info->max_h_samp_factor = 1; info->max_v_samp_factor = 1; } else { info->max_h_samp_factor = srcinfo->max_h_samp_factor; info->max_v_samp_factor = srcinfo->max_v_samp_factor; } break; } /* If cropping has been requested, compute the crop area's position and * dimensions, ensuring that its upper left corner falls at an iMCU boundary. */ if (info->crop) { /* Insert default values for unset crop parameters */ if (info->crop_xoffset_set == JCROP_UNSET) info->crop_xoffset = 0; /* default to +0 */ if (info->crop_yoffset_set == JCROP_UNSET) info->crop_yoffset = 0; /* default to +0 */ if (info->crop_xoffset >= info->output_width || info->crop_yoffset >= info->output_height) ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); if (info->crop_width_set == JCROP_UNSET) info->crop_width = info->output_width - info->crop_xoffset; if (info->crop_height_set == JCROP_UNSET) info->crop_height = info->output_height - info->crop_yoffset; /* Ensure parameters are valid */ if (info->crop_width <= 0 || info->crop_width > info->output_width || info->crop_height <= 0 || info->crop_height > info->output_height || info->crop_xoffset > info->output_width - info->crop_width || info->crop_yoffset > info->output_height - info->crop_height) ERREXIT(srcinfo, JERR_BAD_CROP_SPEC); /* Convert negative crop offsets into regular offsets */ if (info->crop_xoffset_set == JCROP_NEG) xoffset = info->output_width - info->crop_width - info->crop_xoffset; else xoffset = info->crop_xoffset; if (info->crop_yoffset_set == JCROP_NEG) yoffset = info->output_height - info->crop_height - info->crop_yoffset; else yoffset = info->crop_yoffset; /* Now adjust so that upper left corner falls at an iMCU boundary */ info->output_width = info->crop_width + (xoffset % (info->max_h_samp_factor * DCTSIZE)); info->output_height = info->crop_height + (yoffset % (info->max_v_samp_factor * DCTSIZE)); /* Save x/y offsets measured in iMCUs */ info->x_crop_offset = xoffset / (info->max_h_samp_factor * DCTSIZE); info->y_crop_offset = yoffset / (info->max_v_samp_factor * DCTSIZE); } else { info->x_crop_offset = 0; info->y_crop_offset = 0; } /* Figure out whether we need workspace arrays, * and if so whether they are transposed relative to the source. */ need_workspace = FALSE; transpose_it = FALSE; switch (info->transform) { case JXFORM_NONE: if (info->x_crop_offset != 0 || info->y_crop_offset != 0) need_workspace = TRUE; /* No workspace needed if neither cropping nor transforming */ break; case JXFORM_FLIP_H: if (info->trim) trim_right_edge(info, srcinfo->image_width); if (info->y_crop_offset != 0) need_workspace = TRUE; /* do_flip_h_no_crop doesn't need a workspace array */ break; case JXFORM_FLIP_V: if (info->trim) trim_bottom_edge(info, srcinfo->image_height); /* Need workspace arrays having same dimensions as source image. */ need_workspace = TRUE; break; case JXFORM_TRANSPOSE: /* transpose does NOT have to trim anything */ /* Need workspace arrays having transposed dimensions. */ need_workspace = TRUE; transpose_it = TRUE; break; case JXFORM_TRANSVERSE: if (info->trim) { trim_right_edge(info, srcinfo->image_height); trim_bottom_edge(info, srcinfo->image_width); } /* Need workspace arrays having transposed dimensions. */ need_workspace = TRUE; transpose_it = TRUE; break; case JXFORM_ROT_90: if (info->trim) trim_right_edge(info, srcinfo->image_height); /* Need workspace arrays having transposed dimensions. */ need_workspace = TRUE; transpose_it = TRUE; break; case JXFORM_ROT_180: if (info->trim) { trim_right_edge(info, srcinfo->image_width); trim_bottom_edge(info, srcinfo->image_height); } /* Need workspace arrays having same dimensions as source image. */ need_workspace = TRUE; break; case JXFORM_ROT_270: if (info->trim) trim_bottom_edge(info, srcinfo->image_width); /* Need workspace arrays having transposed dimensions. */ need_workspace = TRUE; transpose_it = TRUE; break; } /* Allocate workspace if needed. * Note that we allocate arrays padded out to the next iMCU boundary, * so that transform routines need not worry about missing edge blocks. */ if (need_workspace) { coef_arrays = (jvirt_barray_ptr *) (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, SIZEOF(jvirt_barray_ptr) * info->num_components); width_in_iMCUs = (JDIMENSION) jdiv_round_up((long) info->output_width, (long) (info->max_h_samp_factor * DCTSIZE)); height_in_iMCUs = (JDIMENSION) jdiv_round_up((long) info->output_height, (long) (info->max_v_samp_factor * DCTSIZE)); for (ci = 0; ci < info->num_components; ci++) { compptr = srcinfo->comp_info + ci; if (info->num_components == 1) { /* we're going to force samp factors to 1x1 in this case */ h_samp_factor = v_samp_factor = 1; } else if (transpose_it) { h_samp_factor = compptr->v_samp_factor; v_samp_factor = compptr->h_samp_factor; } else { h_samp_factor = compptr->h_samp_factor; v_samp_factor = compptr->v_samp_factor; } width_in_blocks = width_in_iMCUs * h_samp_factor; height_in_blocks = height_in_iMCUs * v_samp_factor; coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor); } } info->workspace_coef_arrays = coef_arrays;}/* Transpose destination image parameters */LOCAL(void)transpose_critical_parameters (j_compress_ptr dstinfo){ int tblno, i, j, ci, itemp; jpeg_component_info *compptr; JQUANT_TBL *qtblptr; UINT16 qtemp; /* Transpose sampling factors */ for (ci = 0; ci < dstinfo->num_components; ci++) { compptr = dstinfo->comp_info + ci; itemp = compptr->h_samp_factor; compptr->h_samp_factor = compptr->v_samp_factor; compptr->v_samp_factor = itemp; } /* Transpose quantization tables */ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { qtblptr = dstinfo->quant_tbl_ptrs[tblno]; if (qtblptr != NULL) { for (i = 0; i < DCTSIZE; i++) { for (j = 0; j < i; j++) { qtemp = qtblptr->quantval[i*DCTSIZE+j]; qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i]; qtblptr->quantval[j*DCTSIZE+i] = qtemp; } } } }}/* Adjust Exif image parameters. * * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible. */LOCAL(void)adjust_exif_parameters (JOCTET FAR * data, unsigned int length, JDIMENSION new_width, JDIMENSION new_height){ boolean is_motorola; /* Flag for byte order */ unsigned int number_of_tags, tagnum; unsigned int firstoffset, offset; JDIMENSION new_value; if (length < 12) return; /* Length of an IFD entry */ /* Discover byte order */ if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49) is_motorola = FALSE; else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -