/* Return gs_error_undefinedresult if the matrix is not invertible. */ int gs_point_transform_inverse(floatp x, floatp y, const gs_matrix * pmat, gs_point * ppt) { if (is_xxyy(pmat)) { if (is_fzero(pmat->xx) || is_fzero(pmat->yy)) return_error(gs_error_undefinedresult); ppt->x = (x - pmat->tx) / pmat->xx; ppt->y = (y - pmat->ty) / pmat->yy; return 0; } else if (is_xyyx(pmat)) { if (is_fzero(pmat->xy) || is_fzero(pmat->yx)) return_error(gs_error_undefinedresult); ppt->x = (y - pmat->ty) / pmat->xy; ppt->y = (x - pmat->tx) / pmat->yx; return 0; } else { /* There are faster ways to do this, */ /* but we won't implement one unless we have to. */ gs_matrix imat; int code = gs_matrix_invert(pmat, &imat); if (code < 0) return code; return gs_point_transform(x, y, &imat, ppt); } }
/* This is the second half of gs_screen_init_accurate. */ int gs_screen_enum_init_memory(gs_screen_enum * penum, const gx_ht_order * porder, gs_state * pgs, const gs_screen_halftone * phsp, gs_memory_t * mem) { penum->pgs = pgs; /* ensure clean for GC */ if (&penum->order != porder) /* Pacify Valgrind */ penum->order = *porder; penum->halftone.rc.memory = mem; penum->halftone.type = ht_type_screen; penum->halftone.params.screen = *phsp; penum->x = penum->y = 0; if (porder->wse == NULL) { penum->strip = porder->num_levels / porder->width; penum->shift = porder->shift; /* * We want a transformation matrix that maps the parallelogram * (0,0), (U,V), (U-V',V+U'), (-V',U') to the square (+/-1, +/-1). * If the coefficients are [a b c d e f] and we let * u = U = M/R, v = V = N/R, * r = -V' = -N'/R', s = U' = M'/R', * then we just need to solve the equations: * a*0 + c*0 + e = -1 b*0 + d*0 + f = -1 * a*u + c*v + e = 1 b*u + d*v + f = 1 * a*r + c*s + e = -1 b*r + d*s + f = 1 * This has the following solution: * Q = 2 / (M*M' + N*N') * a = Q * R * M' * b = -Q * R' * N * c = Q * R * N' * d = Q * R' * M * e = -1 * f = -1 */ { const int M = porder->params.M, N = porder->params.N, R = porder->params.R; const int M1 = porder->params.M1, N1 = porder->params.N1, R1 = porder->params.R1; double Q = 2.0 / ((long)M * M1 + (long)N * N1); penum->mat.xx = Q * (R * M1); penum->mat.xy = Q * (-R1 * N); penum->mat.yx = Q * (R * N1); penum->mat.yy = Q * (R1 * M); penum->mat.tx = -1.0; penum->mat.ty = -1.0; gs_matrix_invert(&penum->mat, &penum->mat_inv); } if_debug7('h', "[h]Screen: (%dx%d)/%d [%f %f %f %f]\n", porder->width, porder->height, porder->params.R, penum->mat.xx, penum->mat.xy, penum->mat.yx, penum->mat.yy); } return 0; }
static int ctm_set_inverse(gs_state * pgs) { int code = gs_matrix_invert(&ctm_only(pgs), &pgs->ctm_inverse); print_inverse(pgs); if (code < 0) return code; pgs->ctm_inverse_valid = true; return 0; }
RELOC_PTRS_END static int is_image_visible(const gs_image_common_t * pic, gs_state * pgs, gx_clip_path *pcpath) { /* HACK : We need the source image size here, but gs_image_common_t doesn't pass it. We would like to move Width, Height to gs_image_common, but gs_image2_t appears to have those fields of double type. */ if (pic->type->begin_typed_image == gx_begin_image1) { gs_image1_t *pim = (gs_image1_t *) pic; gs_rect image_rect = {{0, 0}, {0, 0}}; gs_rect device_rect; gs_int_rect device_int_rect; gs_matrix mat; int code; image_rect.q.x = pim->Width; image_rect.q.y = pim->Height; if (pic->ImageMatrix.xx == ctm_only(pgs).xx && pic->ImageMatrix.xy == ctm_only(pgs).xy && pic->ImageMatrix.yx == ctm_only(pgs).yx && pic->ImageMatrix.yy == ctm_only(pgs).yy) { /* Handle common special case separately to accept singular matrix */ mat.xx = mat.yy = 1.; mat.yx = mat.xy = 0.; mat.tx = ctm_only(pgs).tx - pic->ImageMatrix.tx; mat.ty = ctm_only(pgs).ty - pic->ImageMatrix.ty; } else { code = gs_matrix_invert(&pic->ImageMatrix, &mat); if (code < 0) return code; code = gs_matrix_multiply(&mat, &ctm_only(pgs), &mat); if (code < 0) return code; } code = gs_bbox_transform(&image_rect, &mat, &device_rect); if (code < 0) return code; device_int_rect.p.x = (int)floor(device_rect.p.x); device_int_rect.p.y = (int)floor(device_rect.p.y); device_int_rect.q.x = (int)ceil(device_rect.q.x); device_int_rect.q.y = (int)ceil(device_rect.q.y); if (!gx_cpath_rect_visible(pcpath, &device_int_rect)) return 0; } return 1; }
/* <matrix> <inv_matrix> invertmatrix <inv_matrix> */ static int zinvertmatrix(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_matrix m; int code; if ((code = read_matrix(imemory, op - 1, &m)) < 0 || (code = gs_matrix_invert(&m, &m)) < 0 || (code = write_matrix(op, &m)) < 0 ) return code; op[-1] = *op; pop(1); return code; }
static int vu_begin_image(px_state_t * pxs) { px_vendor_state_t *v_state = pxs->vendor_state; gs_image_t image = v_state->image; px_bitmap_params_t params; gs_point origin; int code; if (v_state->color_space == eGraySub) params.color_space = eGray; else params.color_space = eSRGB; params.width = params.dest_width = v_state->SourceWidth; params.height = params.dest_height = v_state->BlockHeight; params.depth = 8; params.indexed = false; code = px_image_color_space(&image, ¶ms, (const gs_string *)&pxs->pxgs->palette, pxs->pgs); if (code < 0) { return code; } /* Set up the image parameters. */ if (gs_currentpoint(pxs->pgs, &origin) < 0) return_error(errorCurrentCursorUndefined); image.Width = v_state->SourceWidth; image.Height = v_state->BlockHeight; { gs_matrix imat, dmat; gs_make_scaling(image.Width, image.Height, &imat); gs_make_translation(origin.x, origin.y + v_state->StartLine, &dmat); gs_matrix_scale(&dmat, image.Width, image.Height, &dmat); /* The ImageMatrix is dmat' * imat. */ gs_matrix_invert(&dmat, &dmat); gs_matrix_multiply(&dmat, &imat, &image.ImageMatrix); } image.CombineWithColor = true; image.Interpolate = pxs->interpolate; code = pl_begin_image(pxs->pgs, &image, &v_state->info); if (code < 0) return code; return 0; }
static int bbox_image_begin(const gs_imager_state * pis, const gs_matrix * pmat, const gs_image_common_t * pic, const gs_int_rect * prect, const gx_clip_path * pcpath, gs_memory_t * memory, bbox_image_enum ** ppbe) { int code; gs_matrix mat; bbox_image_enum *pbe; if (pmat == 0) pmat = &ctm_only(pis); if ((code = gs_matrix_invert(&pic->ImageMatrix, &mat)) < 0 || (code = gs_matrix_multiply(&mat, pmat, &mat)) < 0 ) return code; pbe = gs_alloc_struct(memory, bbox_image_enum, &st_bbox_image_enum, "bbox_image_begin"); if (pbe == 0) return_error(gs_error_VMerror); pbe->memory = memory; pbe->matrix = mat; pbe->pcpath = pcpath; pbe->target_info = 0; /* in case no target */ pbe->params_are_const = false; /* check the first time */ if (prect) { pbe->x0 = prect->p.x, pbe->x1 = prect->q.x; pbe->y = prect->p.y, pbe->height = prect->q.y - prect->p.y; } else { gs_int_point size; int code = (*pic->type->source_size) (pis, pic, &size); if (code < 0) { gs_free_object(memory, pbe, "bbox_image_begin"); return code; } pbe->x0 = 0, pbe->x1 = size.x; pbe->y = 0, pbe->height = size.y; } *ppbe = pbe; return 0; }
int gx_begin_image3_generic(gx_device * dev, const gs_imager_state *pis, const gs_matrix *pmat, const gs_image_common_t *pic, const gs_int_rect *prect, const gx_drawing_color *pdcolor, const gx_clip_path *pcpath, gs_memory_t *mem, image3_make_mid_proc_t make_mid, image3_make_mcde_proc_t make_mcde, gx_image_enum_common_t **pinfo) { const gs_image3_t *pim = (const gs_image3_t *)pic; gx_image3_enum_t *penum; gs_int_rect mask_rect, data_rect; gx_device *mdev = 0; gx_device *pcdev = 0; gs_image_t i_pixel, i_mask; gs_matrix mi_pixel, mi_mask, mat; gs_rect mrect; gs_int_point origin; int code; /* Validate the parameters. */ if (pim->Height <= 0 || pim->MaskDict.Height <= 0) return_error(gs_error_rangecheck); switch (pim->InterleaveType) { default: return_error(gs_error_rangecheck); case interleave_chunky: if (pim->MaskDict.Width != pim->Width || pim->MaskDict.Height != pim->Height || pim->MaskDict.BitsPerComponent != pim->BitsPerComponent || pim->format != gs_image_format_chunky ) return_error(gs_error_rangecheck); break; case interleave_scan_lines: if (pim->MaskDict.Height % pim->Height != 0 && pim->Height % pim->MaskDict.Height != 0 ) return_error(gs_error_rangecheck); /* falls through */ case interleave_separate_source: if (pim->MaskDict.BitsPerComponent != 1) return_error(gs_error_rangecheck); } if (!check_image3_extent(pim->ImageMatrix.xx, pim->MaskDict.ImageMatrix.xx) || !check_image3_extent(pim->ImageMatrix.xy, pim->MaskDict.ImageMatrix.xy) || !check_image3_extent(pim->ImageMatrix.yx, pim->MaskDict.ImageMatrix.yx) || !check_image3_extent(pim->ImageMatrix.yy, pim->MaskDict.ImageMatrix.yy) ) return_error(gs_error_rangecheck); if ((code = gs_matrix_invert(&pim->ImageMatrix, &mi_pixel)) < 0 || (code = gs_matrix_invert(&pim->MaskDict.ImageMatrix, &mi_mask)) < 0 ) return code; if (fabs(mi_pixel.tx - mi_mask.tx) >= 0.5 || fabs(mi_pixel.ty - mi_mask.ty) >= 0.5 ) return_error(gs_error_rangecheck); #ifdef DEBUG { /* Although the PLRM says that the Mask and Image *must* be the same size, */ /* Adobe CPSI (and other RIPS) ignore this and process anyway. Note that we */ /* are not compatible if the Mask Height than the Data (pixel) Height. CPSI */ /* de-interleaves the mask from the data image and stops at the Mask Height */ /* Problem detected with Genoa 468-03 (part of file 468-01.ps) */ /***** fixme: When Data Image Height > Mask Height *****/ gs_point ep, em; if ((code = gs_point_transform(pim->Width, pim->Height, &mi_pixel, &ep)) < 0 || (code = gs_point_transform(pim->MaskDict.Width, pim->MaskDict.Height, &mi_mask, &em)) < 0 ) return code; if (fabs(ep.x - em.x) >= 0.5 || fabs(ep.y - em.y) >= 0.5) code = gs_error_rangecheck; /* leave the check in for debug breakpoint */ } #endif /* DEBUG */ penum = gs_alloc_struct(mem, gx_image3_enum_t, &st_image3_enum, "gx_begin_image3"); if (penum == 0) return_error(gs_error_VMerror); penum->num_components = gs_color_space_num_components(pim->ColorSpace); gx_image_enum_common_init((gx_image_enum_common_t *) penum, (const gs_data_image_t *)pim, &image3_enum_procs, dev, 1 + penum->num_components, pim->format); /* Initialize pointers now in case we bail out. */ penum->mask_data = 0; penum->pixel_data = 0; if (prect) { long lmw = pim->MaskDict.Width, lmh = pim->MaskDict.Height; data_rect = *prect; mask_rect.p.x = (int)(data_rect.p.x * lmw / pim->Width); mask_rect.p.y = (int)(data_rect.p.y * lmh / pim->Height); mask_rect.q.x = (int)((data_rect.q.x + pim->Width - 1) * lmw / pim->Width); mask_rect.q.y = (int)((data_rect.q.y + pim->Height - 1) * lmh / pim->Height); } else { mask_rect.p.x = mask_rect.p.y = 0; mask_rect.q.x = pim->MaskDict.Width; mask_rect.q.y = pim->MaskDict.Height; data_rect.p.x = data_rect.p.y = 0; data_rect.q.x = pim->Width; data_rect.q.y = pim->Height; } penum->mask_width = mask_rect.q.x - mask_rect.p.x; penum->mask_height = mask_rect.q.y - mask_rect.p.y; penum->mask_full_height = pim->MaskDict.Height; penum->mask_y = 0; penum->mask_skip = 0; penum->pixel_width = data_rect.q.x - data_rect.p.x; penum->pixel_height = data_rect.q.y - data_rect.p.y; penum->pixel_full_height = pim->Height; penum->pixel_y = 0; penum->mask_info = 0; penum->pixel_info = 0; if (pim->InterleaveType == interleave_chunky) { /* Allocate row buffers for the mask and pixel data. */ penum->pixel_data = gs_alloc_bytes(mem, (penum->pixel_width * pim->BitsPerComponent * penum->num_components + 7) >> 3, "gx_begin_image3(pixel_data)"); penum->mask_data = gs_alloc_bytes(mem, (penum->mask_width + 7) >> 3, "gx_begin_image3(mask_data)"); if (penum->pixel_data == 0 || penum->mask_data == 0) { code = gs_note_error(gs_error_VMerror); goto out1; } }