gximage2.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
  2. This file is part of AFPL Ghostscript.
  3. AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
  4. distributor accepts any responsibility for the consequences of using it, or
  5. for whether it serves any particular purpose or works at all, unless he or
  6. she says so in writing. Refer to the Aladdin Free Public License (the
  7. "License") for full details.
  8. Every copy of AFPL Ghostscript must include a copy of the License, normally
  9. in a plain ASCII text file named PUBLIC. The License grants you the right
  10. to copy, modify and redistribute AFPL Ghostscript, but only under certain
  11. conditions described in the License. Among other things, the License
  12. requires that the copyright notice and this notice be preserved on all
  13. copies.
  14. */
  15. /*$Id: gximage2.c,v 1.2 2000/09/19 19:00:38 lpd Exp $ */
  16. /* ImageType 2 image implementation */
  17. #include "math_.h"
  18. #include "memory_.h"
  19. #include "gx.h"
  20. #include "gserrors.h"
  21. #include "gsmatrix.h" /* for gscoord.h */
  22. #include "gscoord.h"
  23. #include "gscspace.h"
  24. #include "gscpixel.h"
  25. #include "gsdevice.h"
  26. #include "gsiparm2.h"
  27. #include "gxgetbit.h"
  28. #include "gxiparam.h"
  29. #include "gxpath.h"
  30. /* Forward references */
  31. private dev_proc_begin_typed_image(gx_begin_image2);
  32. private image_proc_source_size(gx_image2_source_size);
  33. /* Structure descriptor */
  34. private_st_gs_image2();
  35. /* Define the image type for ImageType 2 images. */
  36. const gx_image_type_t gs_image_type_2 = {
  37. &st_gs_image2, gx_begin_image2, gx_image2_source_size,
  38. gx_image_no_sput, gx_image_no_sget, gx_image_default_release, 2
  39. };
  40. /* Initialize an ImageType 2 image. */
  41. void
  42. gs_image2_t_init(gs_image2_t * pim)
  43. {
  44. pim->type = &gs_image_type_2;
  45. pim->UnpaintedPath = 0;
  46. pim->PixelCopy = false;
  47. }
  48. /*
  49. * Compute the device space coordinates and source data size for an
  50. * ImageType 2 image. This procedure fills in
  51. * image.{Width,Height,ImageMatrix}.
  52. */
  53. typedef struct image2_data_s {
  54. gs_point origin;
  55. gs_int_rect bbox;
  56. gs_image1_t image;
  57. } image2_data_t;
  58. private int
  59. image2_set_data(const gs_image2_t * pim, image2_data_t * pid)
  60. {
  61. gs_state *pgs = pim->DataSource;
  62. gs_matrix smat;
  63. gs_rect sbox, dbox;
  64. gs_transform(pgs, pim->XOrigin, pim->YOrigin, &pid->origin);
  65. sbox.q.x = (sbox.p.x = pim->XOrigin) + pim->Width;
  66. sbox.q.y = (sbox.p.y = pim->YOrigin) + pim->Height;
  67. gs_currentmatrix(pgs, &smat);
  68. gs_bbox_transform(&sbox, &smat, &dbox);
  69. pid->bbox.p.x = (int)floor(dbox.p.x);
  70. pid->bbox.p.y = (int)floor(dbox.p.y);
  71. pid->bbox.q.x = (int)ceil(dbox.q.x);
  72. pid->bbox.q.y = (int)ceil(dbox.q.y);
  73. pid->image.Width = pid->bbox.q.x - pid->bbox.p.x;
  74. pid->image.Height = pid->bbox.q.y - pid->bbox.p.y;
  75. pid->image.ImageMatrix = pim->ImageMatrix;
  76. return 0;
  77. }
  78. /* Compute the source size of an ImageType 2 image. */
  79. private int
  80. gx_image2_source_size(const gs_imager_state * pis, const gs_image_common_t * pim,
  81. gs_int_point * psize)
  82. {
  83. image2_data_t idata;
  84. image2_set_data((const gs_image2_t *)pim, &idata);
  85. psize->x = idata.image.Width;
  86. psize->y = idata.image.Height;
  87. return 0;
  88. }
  89. /* Begin an ImageType 2 image. */
  90. /* Note that since ImageType 2 images don't have any source data, */
  91. /* this procedure does all the work. */
  92. private int
  93. gx_begin_image2(gx_device * dev,
  94. const gs_imager_state * pis, const gs_matrix * pmat,
  95. const gs_image_common_t * pic, const gs_int_rect * prect,
  96. const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
  97. gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
  98. {
  99. const gs_image2_t *pim = (const gs_image2_t *)pic;
  100. gs_state *pgs = pim->DataSource;
  101. gx_device *sdev = gs_currentdevice(pgs);
  102. int depth = sdev->color_info.depth;
  103. /****** ONLY HANDLE depth <= 8 FOR PixelCopy ******/
  104. bool pixel_copy = pim->PixelCopy && depth <= 8 &&
  105. !memcmp(&dev->color_info, &sdev->color_info,
  106. sizeof(dev->color_info));
  107. bool has_alpha;
  108. bool direct_copy;
  109. image2_data_t idata;
  110. byte *row;
  111. uint row_size, source_size;
  112. gx_image_enum_common_t *info;
  113. gs_matrix smat, dmat;
  114. gs_color_space cs;
  115. const gs_color_space *pcs;
  116. int code;
  117. gs_image_t_init_rgb(&idata.image, pis);
  118. /* Add Decode entries for K and alpha */
  119. idata.image.Decode[6] = idata.image.Decode[8] = 0.0;
  120. idata.image.Decode[7] = idata.image.Decode[9] = 1.0;
  121. if (pmat == 0) {
  122. gs_currentmatrix((const gs_state *)pis, &dmat);
  123. pmat = &dmat;
  124. } else
  125. dmat = *pmat;
  126. gs_currentmatrix(pgs, &smat);
  127. code = image2_set_data(pim, &idata);
  128. if (code < 0)
  129. return code;
  130. /****** ONLY HANDLE SIMPLE CASES FOR NOW ******/
  131. if (idata.bbox.p.x != floor(idata.origin.x))
  132. return_error(gs_error_rangecheck);
  133. if (!(idata.bbox.p.y == floor(idata.origin.y) ||
  134. idata.bbox.q.y == ceil(idata.origin.y))
  135. )
  136. return_error(gs_error_rangecheck);
  137. source_size = (idata.image.Width * depth + 7) >> 3;
  138. row_size = max(3 * idata.image.Width, source_size);
  139. row = gs_alloc_bytes(mem, row_size, "gx_begin_image2");
  140. if (row == 0)
  141. return_error(gs_error_VMerror);
  142. if (pixel_copy &&
  143. (pcpath == NULL ||
  144. gx_cpath_includes_rectangle(pcpath,
  145. int2fixed(idata.bbox.p.x),
  146. int2fixed(idata.bbox.p.y),
  147. int2fixed(idata.bbox.q.x),
  148. int2fixed(idata.bbox.q.y)))
  149. ) {
  150. gs_matrix mat;
  151. idata.image.BitsPerComponent = depth;
  152. gs_cspace_init_DevicePixel(&cs, depth);
  153. pcs = &cs;
  154. /*
  155. * Figure 7.2 of the Adobe 3010 Supplement says that we should
  156. * compute CTM x ImageMatrix here, but I'm almost certain it
  157. * should be the other way around. Also see gdevx.c.
  158. */
  159. gs_matrix_multiply(&idata.image.ImageMatrix, &smat, &mat);
  160. direct_copy =
  161. (is_xxyy(&dmat) || is_xyyx(&dmat)) &&
  162. #define eqe(e) mat.e == dmat.e
  163. eqe(xx) && eqe(xy) && eqe(yx) && eqe(yy);
  164. #undef eqe
  165. has_alpha = false; /* no separate alpha channel */
  166. } else {
  167. pixel_copy = false;
  168. idata.image.BitsPerComponent = 8;
  169. /* Always use RGB source color for now. */
  170. pcs = gs_cspace_DeviceRGB(pis);
  171. direct_copy = false;
  172. /*
  173. * The source device has alpha if the same RGB values with
  174. * different alphas map to different pixel values.
  175. ****** THIS IS NOT GOOD ENOUGH: WE WANT TO SKIP TRANSFERRING
  176. ****** ALPHA IF THE SOURCE IS CAPABLE OF HAVING ALPHA BUT
  177. ****** DOESN'T CURRENTLY HAVE ANY ACTUAL ALPHA VALUES DIFFERENT
  178. ****** FROM 1.
  179. */
  180. /*
  181. * Since the default implementation of map_rgb_alpha_color
  182. * premultiplies the color towards white, we can't just test
  183. * whether changing alpha has an effect on the color.
  184. */
  185. {
  186. gx_color_index trans_black =
  187. (*dev_proc(sdev, map_rgb_alpha_color))
  188. (sdev, (gx_color_value) 0, (gx_color_value) 0,
  189. (gx_color_value) 0, (gx_color_value) 0);
  190. has_alpha =
  191. trans_black != (*dev_proc(sdev, map_rgb_alpha_color))
  192. (sdev, (gx_color_value) 0, (gx_color_value) 0,
  193. (gx_color_value) 0, gx_max_color_value) &&
  194. trans_black != (*dev_proc(sdev, map_rgb_alpha_color))
  195. (sdev, gx_max_color_value, gx_max_color_value,
  196. gx_max_color_value, gx_max_color_value);
  197. }
  198. }
  199. idata.image.ColorSpace = pcs;
  200. idata.image.Alpha =
  201. (has_alpha ? gs_image_alpha_last : gs_image_alpha_none);
  202. if (smat.yy < 0) {
  203. /*
  204. * The source Y axis is reflected. Reflect the mapping from
  205. * user space to source data.
  206. */
  207. idata.image.ImageMatrix.ty += idata.image.Height *
  208. idata.image.ImageMatrix.yy;
  209. idata.image.ImageMatrix.xy = -idata.image.ImageMatrix.xy;
  210. idata.image.ImageMatrix.yy = -idata.image.ImageMatrix.yy;
  211. }
  212. if (!direct_copy)
  213. code = (*dev_proc(dev, begin_typed_image))
  214. (dev, pis, pmat, (const gs_image_common_t *)&idata.image, NULL,
  215. pdcolor, pcpath, mem, &info);
  216. if (code >= 0) {
  217. int y;
  218. gs_int_rect rect;
  219. gs_get_bits_params_t params;
  220. const byte *data;
  221. uint offset = row_size - source_size;
  222. rect = idata.bbox;
  223. for (y = 0; code >= 0 && y < idata.image.Height; ++y) {
  224. gs_int_rect *unread = 0;
  225. int num_unread;
  226. /****** y COMPUTATION IS ROUNDED -- WRONG ******/
  227. rect.q.y = rect.p.y + 1;
  228. /* Insist on x_offset = 0 to simplify the conversion loop. */
  229. params.options =
  230. GB_ALIGN_ANY | (GB_RETURN_COPY | GB_RETURN_POINTER) |
  231. GB_OFFSET_0 | (GB_RASTER_STANDARD | GB_RASTER_ANY) |
  232. GB_PACKING_CHUNKY;
  233. if (pixel_copy) {
  234. params.options |= GB_COLORS_NATIVE;
  235. params.data[0] = row + offset;
  236. code = (*dev_proc(sdev, get_bits_rectangle))
  237. (sdev, &rect, &params, &unread);
  238. if (code < 0)
  239. break;
  240. num_unread = code;
  241. data = params.data[0];
  242. if (direct_copy) {
  243. /*
  244. * Copy the pixels directly to the destination.
  245. * We know that the transformation is only a translation,
  246. * but we must handle an inverted destination Y axis.
  247. */
  248. code = (*dev_proc(dev, copy_color))
  249. (dev, data, 0, row_size, gx_no_bitmap_id,
  250. (int)(dmat.tx - idata.image.ImageMatrix.tx),
  251. (int)(dmat.ty - idata.image.ImageMatrix.ty +
  252. (dmat.yy < 0 ? ~y : y)),
  253. idata.image.Width, 1);
  254. continue;
  255. }
  256. } else {
  257. /*
  258. * Convert the pixels to pure colors. This may be very
  259. * slow and painful. Eventually we will use indexed color for
  260. * narrow pixels.
  261. */
  262. /* Always use RGB source color for now. */
  263. params.options |=
  264. GB_COLORS_RGB | GB_DEPTH_8 |
  265. (has_alpha ? GB_ALPHA_LAST : GB_ALPHA_NONE);
  266. params.data[0] = row;
  267. code = (*dev_proc(sdev, get_bits_rectangle))
  268. (sdev, &rect, &params, &unread);
  269. if (code < 0)
  270. break;
  271. num_unread = code;
  272. data = params.data[0];
  273. }
  274. if (num_unread > 0 && pim->UnpaintedPath) {
  275. /* Add the rectangle(s) to the unpainted path. */
  276. int i;
  277. for (i = 0; code >= 0 && i < num_unread; ++i)
  278. code = gx_path_add_rectangle(pim->UnpaintedPath,
  279. int2fixed(unread[i].p.x),
  280. int2fixed(unread[i].p.y),
  281. int2fixed(unread[i].q.x),
  282. int2fixed(unread[i].q.y));
  283. gs_free_object(dev->memory, unread, "UnpaintedPath unread");
  284. }
  285. code = gx_image_data(info, &data, 0, row_size, 1);
  286. rect.p.y = rect.q.y;
  287. }
  288. if (!direct_copy) {
  289. if (code >= 0)
  290. code = gx_image_end(info, true);
  291. else
  292. discard(gx_image_end(info, false));
  293. }
  294. }
  295. gs_free_object(mem, row, "gx_begin_image2");
  296. return (code < 0 ? code : 1);
  297. }