diff options
-rw-r--r-- | pcl/pxl/pximage.c | 103 |
1 files changed, 56 insertions, 47 deletions
diff --git a/pcl/pxl/pximage.c b/pcl/pxl/pximage.c index d1ec1053c..707786377 100644 --- a/pcl/pxl/pximage.c +++ b/pcl/pxl/pximage.c | |||
@@ -84,6 +84,28 @@ px_purge_pattern_cache(px_state_t * pxs, pxePatternPersistence_t max_persist) | |||
84 | px_pattern_purge_proc, (void *)&max_persist); | 84 | px_pattern_purge_proc, (void *)&max_persist); |
85 | } | 85 | } |
86 | 86 | ||
87 | /* active decompression types */ | ||
88 | typedef enum | ||
89 | { | ||
90 | unset = 0, | ||
91 | nocomp = 1, | ||
92 | rle = 2, | ||
93 | jpeg = 4, | ||
94 | delta = 8, | ||
95 | } decomp_init_t; | ||
96 | |||
97 | static inline bool nocomp_init(uint comp) {return comp & nocomp;} | ||
98 | static inline bool rle_init(uint comp) {return comp & rle;} | ||
99 | static inline bool jpeg_init(uint comp) {return comp & jpeg;} | ||
100 | static inline bool delta_init(uint comp) {return comp & delta;} | ||
101 | |||
102 | static inline void nocomp_set(uint *comp) {*comp |= nocomp;} | ||
103 | static inline void rle_set(uint *comp) {*comp |= rle;} | ||
104 | static inline void jpeg_set(uint *comp) {*comp |= jpeg;} | ||
105 | static inline void delta_set(uint *comp) {*comp |= delta;} | ||
106 | |||
107 | static inline void comp_unset(uint *comp) {*comp = unset;} | ||
108 | |||
87 | /* pxl delta row decompression state machine states */ | 109 | /* pxl delta row decompression state machine states */ |
88 | typedef enum | 110 | typedef enum |
89 | { | 111 | { |
@@ -110,8 +132,7 @@ typedef struct px_bitmap_enum_s | |||
110 | { | 132 | { |
111 | gs_memory_t *mem; /* used only for the jpeg filter */ | 133 | gs_memory_t *mem; /* used only for the jpeg filter */ |
112 | uint data_per_row; /* ditto minus possible trailing padding */ | 134 | uint data_per_row; /* ditto minus possible trailing padding */ |
113 | bool initialized; | 135 | uint initialized; |
114 | pxeCompressMode_t compress_type; | ||
115 | stream_RLD_state rld_stream_state; /* decompressor states */ | 136 | stream_RLD_state rld_stream_state; /* decompressor states */ |
116 | stream_DCT_state dct_stream_state; | 137 | stream_DCT_state dct_stream_state; |
117 | jpeg_decompress_data jdd; | 138 | jpeg_decompress_data jdd; |
@@ -171,7 +192,7 @@ px_jpeg_init(px_bitmap_enum_t * benum, px_bitmap_params_t * params, px_args_t * | |||
171 | uint avail = par->source.available; | 192 | uint avail = par->source.available; |
172 | int code = 0; | 193 | int code = 0; |
173 | 194 | ||
174 | if (benum->initialized == false) { | 195 | if (!jpeg_init(benum->initialized)) { |
175 | s_init_state((stream_state *)ss, &s_DCTD_template, benum->mem); | 196 | s_init_state((stream_state *)ss, &s_DCTD_template, benum->mem); |
176 | ss->report_error = stream_error; | 197 | ss->report_error = stream_error; |
177 | s_DCTD_template.set_defaults((stream_state *)ss); | 198 | s_DCTD_template.set_defaults((stream_state *)ss); |
@@ -190,7 +211,7 @@ px_jpeg_init(px_bitmap_enum_t * benum, px_bitmap_params_t * params, px_args_t * | |||
190 | return_error(errorInsufficientMemory); | 211 | return_error(errorInsufficientMemory); |
191 | 212 | ||
192 | (*s_DCTD_template.init) ((stream_state *)ss); | 213 | (*s_DCTD_template.init) ((stream_state *)ss); |
193 | benum->initialized = true; | 214 | jpeg_set(&benum->initialized); |
194 | } | 215 | } |
195 | 216 | ||
196 | r.ptr = data - 1; | 217 | r.ptr = data - 1; |
@@ -207,11 +228,11 @@ px_jpeg_init(px_bitmap_enum_t * benum, px_bitmap_params_t * params, px_args_t * | |||
207 | used = r.ptr + 1 - data; | 228 | used = r.ptr + 1 - data; |
208 | par->source.data = r.ptr + 1; | 229 | par->source.data = r.ptr + 1; |
209 | par->source.available = avail - used; | 230 | par->source.available = avail - used; |
210 | 231 | ||
211 | /* Needs more data to complete reading the header */ | 232 | /* Needs more data to complete reading the header */ |
212 | if (ss->phase < 2) | 233 | if (ss->phase < 2) |
213 | return pxNeedData; | 234 | return pxNeedData; |
214 | 235 | ||
215 | params->width = jddp->dinfo.output_width; | 236 | params->width = jddp->dinfo.output_width; |
216 | params->height = jddp->dinfo.output_height; | 237 | params->height = jddp->dinfo.output_height; |
217 | { | 238 | { |
@@ -242,7 +263,7 @@ begin_bitmap(px_bitmap_params_t * params, px_bitmap_enum_t * benum, | |||
242 | int depth; | 263 | int depth; |
243 | int num_components; | 264 | int num_components; |
244 | px_gstate_t *pxgs = pxs->pxgs; | 265 | px_gstate_t *pxgs = pxs->pxgs; |
245 | 266 | ||
246 | benum->mem = pxs->memory; | 267 | benum->mem = pxs->memory; |
247 | benum->grayscale = false; | 268 | benum->grayscale = false; |
248 | if (is_jpeg) { | 269 | if (is_jpeg) { |
@@ -291,7 +312,7 @@ begin_rebuffered_bitmap(px_bitmap_params_t * params, px_bitmap_enum_t * benum, | |||
291 | 312 | ||
292 | if (code < 0 || code == pxNeedData) | 313 | if (code < 0 || code == pxNeedData) |
293 | return_error(code); | 314 | return_error(code); |
294 | 315 | ||
295 | if (params->width == 1 && params->height > 1) { | 316 | if (params->width == 1 && params->height > 1) { |
296 | benum->rebuffered_data_per_row = benum->data_per_row * params->height; | 317 | benum->rebuffered_data_per_row = benum->data_per_row * params->height; |
297 | benum->rebuffered = 1; | 318 | benum->rebuffered = 1; |
@@ -326,7 +347,7 @@ read_jpeg_bitmap_data(px_bitmap_enum_t * benum, byte ** pdata, | |||
326 | /* consumed all of the data */ | 347 | /* consumed all of the data */ |
327 | if ((par->source.position >= end_pos) && (ss->phase != 4) && (par->source.available == 0)) { | 348 | if ((par->source.position >= end_pos) && (ss->phase != 4) && (par->source.available == 0)) { |
328 | /* shutdown jpeg filter if necessary */ | 349 | /* shutdown jpeg filter if necessary */ |
329 | if (benum->initialized) | 350 | if (jpeg_init(benum->initialized)) |
330 | gs_jpeg_destroy((&benum->dct_stream_state)); | 351 | gs_jpeg_destroy((&benum->dct_stream_state)); |
331 | return 0; | 352 | return 0; |
332 | } | 353 | } |
@@ -334,9 +355,12 @@ read_jpeg_bitmap_data(px_bitmap_enum_t * benum, byte ** pdata, | |||
334 | if (last) | 355 | if (last) |
335 | return_error(errorIllegalDataLength); | 356 | return_error(errorIllegalDataLength); |
336 | 357 | ||
337 | if (!benum->initialized) { | 358 | if (!jpeg_init(benum->initialized)) { |
338 | jpeg_decompress_data *jddp = &(benum->jdd); | 359 | jpeg_decompress_data *jddp = &(benum->jdd); |
339 | 360 | ||
361 | /* we do not allow switching from other compression schemes to jpeg */ | ||
362 | if (benum->initialized != unset) | ||
363 | return_error(errorIllegalAttributeValue); | ||
340 | /* use the graphics library support for DCT streams */ | 364 | /* use the graphics library support for DCT streams */ |
341 | ss->memory = benum->mem; | 365 | ss->memory = benum->mem; |
342 | ss->templat = &s_DCTD_template; | 366 | ss->templat = &s_DCTD_template; |
@@ -354,7 +378,7 @@ read_jpeg_bitmap_data(px_bitmap_enum_t * benum, byte ** pdata, | |||
354 | return_error(errorInsufficientMemory); | 378 | return_error(errorInsufficientMemory); |
355 | (*s_DCTD_template.init) ((stream_state *) ss); | 379 | (*s_DCTD_template.init) ((stream_state *) ss); |
356 | jddp->templat = s_DCTD_template; | 380 | jddp->templat = s_DCTD_template; |
357 | benum->initialized = true; | 381 | jpeg_set(&benum->initialized); |
358 | } | 382 | } |
359 | r.ptr = data - 1; | 383 | r.ptr = data - 1; |
360 | r.limit = r.ptr + avail; | 384 | r.limit = r.ptr + avail; |
@@ -422,7 +446,7 @@ read_uncompressed_bitmap_data(px_bitmap_enum_t * benum, byte ** pdata, | |||
422 | 446 | ||
423 | if (last) | 447 | if (last) |
424 | return_error(errorIllegalDataLength); | 448 | return_error(errorIllegalDataLength); |
425 | 449 | ||
426 | if (avail >= data_per_row_padded && pos_in_row == 0) { | 450 | if (avail >= data_per_row_padded && pos_in_row == 0) { |
427 | /* Use the data directly from the input buffer. */ | 451 | /* Use the data directly from the input buffer. */ |
428 | *pdata = (byte *) data; | 452 | *pdata = (byte *) data; |
@@ -465,12 +489,12 @@ read_rle_bitmap_data(px_bitmap_enum_t * benum, byte ** pdata, px_args_t * par, b | |||
465 | 489 | ||
466 | if (last) | 490 | if (last) |
467 | return_error(errorIllegalDataLength); | 491 | return_error(errorIllegalDataLength); |
468 | 492 | ||
469 | if (!benum->initialized) { | 493 | if (!rle_init(benum->initialized)) { |
470 | ss->EndOfData = false; | 494 | ss->EndOfData = false; |
471 | ss->templat = &s_RLD_template; | 495 | ss->templat = &s_RLD_template; |
472 | s_RLD_init_inline(ss); | 496 | s_RLD_init_inline(ss); |
473 | benum->initialized = true; | 497 | rle_set(&benum->initialized); |
474 | } | 498 | } |
475 | r.ptr = data - 1; | 499 | r.ptr = data - 1; |
476 | r.limit = r.ptr + avail; | 500 | r.limit = r.ptr + avail; |
@@ -565,7 +589,7 @@ read_deltarow_bitmap_data(px_bitmap_enum_t * benum, byte ** pdata, | |||
565 | const byte *pout_start = pout; | 589 | const byte *pout_start = pout; |
566 | bool end_of_row = false; | 590 | bool end_of_row = false; |
567 | 591 | ||
568 | if (benum->initialized && deltarow->rowwritten == par->pv[1]->value.i) { | 592 | if (delta_init(benum->initialized) && deltarow->rowwritten == par->pv[1]->value.i) { |
569 | deltarow->rowwritten = 0; | 593 | deltarow->rowwritten = 0; |
570 | return 0; | 594 | return 0; |
571 | } | 595 | } |
@@ -574,7 +598,7 @@ read_deltarow_bitmap_data(px_bitmap_enum_t * benum, byte ** pdata, | |||
574 | return_error(errorIllegalDataLength); | 598 | return_error(errorIllegalDataLength); |
575 | 599 | ||
576 | /* initialize at begin of image */ | 600 | /* initialize at begin of image */ |
577 | if (!benum->initialized) { | 601 | if (!delta_init(benum->initialized)) { |
578 | /* zero seed row */ | 602 | /* zero seed row */ |
579 | deltarow->seedrow = | 603 | deltarow->seedrow = |
580 | gs_alloc_bytes(benum->mem, benum->data_per_row, | 604 | gs_alloc_bytes(benum->mem, benum->data_per_row, |
@@ -585,7 +609,7 @@ read_deltarow_bitmap_data(px_bitmap_enum_t * benum, byte ** pdata, | |||
585 | deltarow->short_offset = 0; | 609 | deltarow->short_offset = 0; |
586 | deltarow->state = next_is_bytecount; | 610 | deltarow->state = next_is_bytecount; |
587 | deltarow->rowwritten = 0; | 611 | deltarow->rowwritten = 0; |
588 | benum->initialized = true; | 612 | delta_set(&benum->initialized); |
589 | } | 613 | } |
590 | 614 | ||
591 | if (deltarow->row_byte_count == 0) { | 615 | if (deltarow->row_byte_count == 0) { |
@@ -701,13 +725,7 @@ read_deltarow_bitmap_data(px_bitmap_enum_t * benum, byte ** pdata, | |||
701 | static int | 725 | static int |
702 | read_bitmap(px_bitmap_enum_t * benum, byte ** pdata, px_args_t * par, bool last) | 726 | read_bitmap(px_bitmap_enum_t * benum, byte ** pdata, px_args_t * par, bool last) |
703 | { | 727 | { |
704 | /* Changing compression within an image is unimplemented */ | 728 | switch (par->pv[2]->value.i) { |
705 | /* but for now we return an error. */ | ||
706 | if ((benum->compress_type != par->pv[2]->value.i) && (par->pv[2]->value.i != eNoCompression)) | ||
707 | return_error(errorIllegalAttributeValue); | ||
708 | else | ||
709 | benum->compress_type = par->pv[2]->value.i; | ||
710 | switch (benum->compress_type) { | ||
711 | case eRLECompression: | 729 | case eRLECompression: |
712 | return read_rle_bitmap_data(benum, pdata, par, last); | 730 | return read_rle_bitmap_data(benum, pdata, par, last); |
713 | case eJPEGCompression: | 731 | case eJPEGCompression: |
@@ -781,7 +799,7 @@ pxBeginImage(px_args_t * par, px_state_t * pxs) | |||
781 | * revised depending on the color parameters in the JPEG data. | 799 | * revised depending on the color parameters in the JPEG data. |
782 | * We defer image set up until we read the image data. | 800 | * We defer image set up until we read the image data. |
783 | */ | 801 | */ |
784 | 802 | ||
785 | bi_args.mapping = par->pv[0]->value.i; | 803 | bi_args.mapping = par->pv[0]->value.i; |
786 | bi_args.depth = par->pv[1]->value.i; | 804 | bi_args.depth = par->pv[1]->value.i; |
787 | bi_args.width = par->pv[2]->value.i; | 805 | bi_args.width = par->pv[2]->value.i; |
@@ -791,9 +809,9 @@ pxBeginImage(px_args_t * par, px_state_t * pxs) | |||
791 | 809 | ||
792 | pxenum->bi_args = bi_args; | 810 | pxenum->bi_args = bi_args; |
793 | pxenum->enum_started = false; | 811 | pxenum->enum_started = false; |
794 | pxenum->benum.initialized = false; | 812 | comp_unset(&pxenum->benum.initialized); |
795 | pxs->image_enum = pxenum; | 813 | pxs->image_enum = pxenum; |
796 | 814 | ||
797 | return 0; | 815 | return 0; |
798 | } | 816 | } |
799 | 817 | ||
@@ -807,7 +825,7 @@ px_begin_image(px_state_t * pxs, bool is_jpeg, px_args_t * par) | |||
807 | px_image_enum_t *pxenum = pxs->image_enum; | 825 | px_image_enum_t *pxenum = pxs->image_enum; |
808 | px_bitmap_enum_t *pbenum = &pxenum->benum; | 826 | px_bitmap_enum_t *pbenum = &pxenum->benum; |
809 | int code; | 827 | int code; |
810 | 828 | ||
811 | if (gs_currentpoint(pgs, &origin) < 0) | 829 | if (gs_currentpoint(pgs, &origin) < 0) |
812 | return_error(errorCurrentCursorUndefined); | 830 | return_error(errorCurrentCursorUndefined); |
813 | /* | 831 | /* |
@@ -832,7 +850,7 @@ px_begin_image(px_state_t * pxs, bool is_jpeg, px_args_t * par) | |||
832 | code = begin_rebuffered_bitmap(¶ms, pbenum, &pxenum->bi_args, pxs, is_jpeg, par); | 850 | code = begin_rebuffered_bitmap(¶ms, pbenum, &pxenum->bi_args, pxs, is_jpeg, par); |
833 | if (code < 0 || code == pxNeedData) | 851 | if (code < 0 || code == pxNeedData) |
834 | return_error(code); | 852 | return_error(code); |
835 | 853 | ||
836 | pxenum->row = gs_alloc_byte_array(pxs->memory, 1, pbenum->rebuffered_data_per_row, | 854 | pxenum->row = gs_alloc_byte_array(pxs->memory, 1, pbenum->rebuffered_data_per_row, |
837 | "pxReadImage(row)"); | 855 | "pxReadImage(row)"); |
838 | if (pxenum->row == 0) | 856 | if (pxenum->row == 0) |
@@ -841,13 +859,13 @@ px_begin_image(px_state_t * pxs, bool is_jpeg, px_args_t * par) | |||
841 | code = | 859 | code = |
842 | px_image_color_space(&pxenum->image, ¶ms, | 860 | px_image_color_space(&pxenum->image, ¶ms, |
843 | (const gs_string *)&pxgs->palette, pgs); | 861 | (const gs_string *)&pxgs->palette, pgs); |
844 | 862 | ||
845 | if (code < 0) { | 863 | if (code < 0) { |
846 | gs_free_object(pxs->memory, pxenum->row, "pxReadImage(row)"); | 864 | gs_free_object(pxs->memory, pxenum->row, "pxReadImage(row)"); |
847 | gs_free_object(pxs->memory, pxenum, "pxReadImage(pxenum)"); | 865 | gs_free_object(pxs->memory, pxenum, "pxReadImage(pxenum)"); |
848 | return code; | 866 | return code; |
849 | } | 867 | } |
850 | 868 | ||
851 | /* Set up the image parameters. */ | 869 | /* Set up the image parameters. */ |
852 | pxenum->image.Width = pbenum->rebuffered_width; | 870 | pxenum->image.Width = pbenum->rebuffered_width; |
853 | pxenum->image.Height = pbenum->rebuffered_height; | 871 | pxenum->image.Height = pbenum->rebuffered_height; |
@@ -895,7 +913,7 @@ pxReadImage(px_args_t * par, px_state_t * pxs) | |||
895 | { | 913 | { |
896 | px_image_enum_t *pxenum = pxs->image_enum; | 914 | px_image_enum_t *pxenum = pxs->image_enum; |
897 | int code = 0; | 915 | int code = 0; |
898 | 916 | ||
899 | if (par->pv[1]->value.i == 0) | 917 | if (par->pv[1]->value.i == 0) |
900 | return 0; /* no data */ | 918 | return 0; /* no data */ |
901 | /* Make a quick check for the first call, when no data is available. */ | 919 | /* Make a quick check for the first call, when no data is available. */ |
@@ -903,7 +921,6 @@ pxReadImage(px_args_t * par, px_state_t * pxs) | |||
903 | return pxNeedData; | 921 | return pxNeedData; |
904 | if (!pxenum->enum_started) { | 922 | if (!pxenum->enum_started) { |
905 | bool is_jpeg = par->pv[2]->value.i == eJPEGCompression; | 923 | bool is_jpeg = par->pv[2]->value.i == eJPEGCompression; |
906 | pxenum->benum.compress_type = par->pv[2]->value.i; | ||
907 | code = px_begin_image(pxs, is_jpeg, par); | 924 | code = px_begin_image(pxs, is_jpeg, par); |
908 | if (code < 0 || code == pxNeedData) | 925 | if (code < 0 || code == pxNeedData) |
909 | return code; | 926 | return code; |
@@ -932,7 +949,7 @@ pxReadImage(px_args_t * par, px_state_t * pxs) | |||
932 | pxenum->benum.rebuffered_data_per_row, 1); | 949 | pxenum->benum.rebuffered_data_per_row, 1); |
933 | if (code < 0) | 950 | if (code < 0) |
934 | return code; | 951 | return code; |
935 | 952 | ||
936 | pxs->have_page = true; | 953 | pxs->have_page = true; |
937 | } | 954 | } |
938 | } | 955 | } |
@@ -946,7 +963,7 @@ pxEndImage(px_args_t * par, px_state_t * pxs) | |||
946 | int code = pl_end_image(pxs->pgs, pxenum->info, true); | 963 | int code = pl_end_image(pxs->pgs, pxenum->info, true); |
947 | 964 | ||
948 | gs_free_object(pxs->memory, pxenum->row, "pxEndImage(row)"); | 965 | gs_free_object(pxs->memory, pxenum->row, "pxEndImage(row)"); |
949 | if (pbenum->compress_type == eDeltaRowCompression) | 966 | if (delta_init(pxenum->benum.initialized)) |
950 | gs_free_object(pbenum->mem, pbenum->deltarow_state.seedrow, | 967 | gs_free_object(pbenum->mem, pbenum->deltarow_state.seedrow, |
951 | "pxEndImage(seedrow)"); | 968 | "pxEndImage(seedrow)"); |
952 | if (pxenum->image.ColorSpace) | 969 | if (pxenum->image.ColorSpace) |
@@ -996,14 +1013,14 @@ pxBeginRastPattern(px_args_t * par, px_state_t * pxs) | |||
996 | static const gs_memory_struct_type_t st_px_pattern = | 1013 | static const gs_memory_struct_type_t st_px_pattern = |
997 | { sizeof(px_pattern_t), "", 0, 0, 0, 0, 0 }; | 1014 | { sizeof(px_pattern_t), "", 0, 0, 0, 0, 0 }; |
998 | 1015 | ||
999 | 1016 | ||
1000 | bi_args.mapping = par->pv[0]->value.i; | 1017 | bi_args.mapping = par->pv[0]->value.i; |
1001 | bi_args.depth = par->pv[1]->value.i; | 1018 | bi_args.depth = par->pv[1]->value.i; |
1002 | bi_args.width = par->pv[2]->value.i; | 1019 | bi_args.width = par->pv[2]->value.i; |
1003 | bi_args.height = par->pv[3]->value.i; | 1020 | bi_args.height = par->pv[3]->value.i; |
1004 | bi_args.dest_width = real_value(par->pv[4], 0); | 1021 | bi_args.dest_width = real_value(par->pv[4], 0); |
1005 | bi_args.dest_height = real_value(par->pv[4], 1); | 1022 | bi_args.dest_height = real_value(par->pv[4], 1); |
1006 | 1023 | ||
1007 | 1024 | ||
1008 | code = begin_bitmap(¶ms, &benum, &bi_args, pxs, false, par); | 1025 | code = begin_bitmap(¶ms, &benum, &bi_args, pxs, false, par); |
1009 | 1026 | ||
@@ -1034,7 +1051,7 @@ pxBeginRastPattern(px_args_t * par, px_state_t * pxs) | |||
1034 | return_error(errorInsufficientMemory); | 1051 | return_error(errorInsufficientMemory); |
1035 | } | 1052 | } |
1036 | pxenum->benum = benum; | 1053 | pxenum->benum = benum; |
1037 | pxenum->benum.initialized = false; | 1054 | comp_unset(&pxenum->benum.initialized); |
1038 | pxenum->pattern_id = par->pv[5]->value.i; | 1055 | pxenum->pattern_id = par->pv[5]->value.i; |
1039 | pxenum->persistence = par->pv[6]->value.i; | 1056 | pxenum->persistence = par->pv[6]->value.i; |
1040 | pxenum->lines_rendered = 0; | 1057 | pxenum->lines_rendered = 0; |
@@ -1068,14 +1085,6 @@ pxReadRastPattern(px_args_t * par, px_state_t * pxs) | |||
1068 | if (par->source.available == 0) | 1085 | if (par->source.available == 0) |
1069 | pxenum->lines_rendered = 0; | 1086 | pxenum->lines_rendered = 0; |
1070 | 1087 | ||
1071 | { | ||
1072 | pxeCompressMode_t c = par->pv[2]->value.i; | ||
1073 | |||
1074 | if (!pxenum->benum.initialized) | ||
1075 | pxenum->benum.compress_type = c; | ||
1076 | |||
1077 | } | ||
1078 | |||
1079 | for (;;) { | 1088 | for (;;) { |
1080 | byte *data = pxenum->pattern->data + | 1089 | byte *data = pxenum->pattern->data + |
1081 | (par->pv[0]->value.i + pxenum->lines_rendered) * pxenum->benum.data_per_row; | 1090 | (par->pv[0]->value.i + pxenum->lines_rendered) * pxenum->benum.data_per_row; |