tioga 1.17 → 1.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,9 +22,16 @@ This is the README for the Tioga kernel, version 1.14, June 10, 2011.
22
22
 
23
23
  << What's new >>
24
24
 
25
- Tioga 1.17 provides all the necessary fixes to have it run on
26
- windows, so now we also support the Redmond operating system (works
27
- with the ProTeXt LaTeX distribution).
25
+ Tioga 1.18 brings in a few new features. First, Dvector.fancy_read
26
+ is now able to extract pure text columns. Second, a jpg_info function
27
+ has been added that read the width and height from within a JPEG file,
28
+ for use with show_image: you now don't have to know the image size
29
+ beforehand. A load_png function was added that relies on pdflatex to
30
+ read PNG files (except those with a custom palette). Feed the return
31
+ value of load_png to show_image. It is now possible to reuse an image
32
+ over and over again by saving its reference and using itagain.Finally,
33
+ more control over the number of pdflatex executions is now available.
34
+ There are also a couple of bug fixes.
28
35
 
29
36
  << Quick Installation of Tioga >>
30
37
 
@@ -164,6 +171,10 @@ Bill Paxton
164
171
 
165
172
  Here are the old release messages:
166
173
 
174
+ Tioga 1.17 provides all the necessary fixes to have it run on
175
+ windows, so now we also support the Redmond operating system (works
176
+ with the ProTeXt LaTeX distribution).
177
+
167
178
  Tioga 1.16 brings in a bug fix by Josiah Schwab in handling some
168
179
  HLS triplets. It also provides facilities to extract the pdflatex
169
180
  errors.
@@ -5623,6 +5623,12 @@ static VALUE dvector_convolve(VALUE self, VALUE kernel, VALUE middle)
5623
5623
  return retval;
5624
5624
  }
5625
5625
 
5626
+ static VALUE marked_array()
5627
+ {
5628
+ VALUE v = rb_ary_new();
5629
+ rb_gc_register_mark_object(v);
5630
+ return v;
5631
+ }
5626
5632
 
5627
5633
  /*
5628
5634
  :call-seq:
@@ -5637,12 +5643,16 @@ static VALUE dvector_convolve(VALUE self, VALUE kernel, VALUE middle)
5637
5643
  * 'skip_first': skips that many lines before reading anything
5638
5644
  * 'index_col': if true, the first column returned contains the
5639
5645
  number of the line read
5640
- * 'remove_space': whether to remove spaces at the beginning of a line. *This
5641
- option is currently not implemented !*
5646
+ * 'remove_space': whether to remove spaces at the beginning of a line.
5642
5647
  * 'comment_out': this should be an array into which the comments
5643
5648
  will be dumped one by one.
5644
5649
  * 'default': what to put when nothing was found but a number must be used
5645
-
5650
+ * 'last_col': when this is specified, it represents the last column which
5651
+ is read and parsed as numbers (0-based, so the 3rd column is 2).
5652
+ The remaining is returned as text in one n+1 column
5653
+ * 'text_columns': if provided, it is an array of integers containing the
5654
+ 0-based indices of columns to be parsed as text rather than numbers.
5655
+
5646
5656
  In addition to these options that control the output, here are a few
5647
5657
  others to tune memory allocation; these can strongly improve the
5648
5658
  performance (or make it worse if you wish):
@@ -5666,11 +5676,65 @@ static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE options)
5666
5676
  VALUE comments = rb_hash_aref(options, rb_str_new2("comments"));
5667
5677
  VALUE comment_out = rb_hash_aref(options, rb_str_new2("comment_out"));
5668
5678
 
5679
+ /* Elements after that many columns */
5680
+ VALUE lc = rb_hash_aref(options, rb_str_new2("last_col"));
5681
+ long last_col = RTEST(lc) ? FIX2LONG(lc) : -1;
5682
+ VALUE text_columns = rb_hash_aref(options, rb_str_new2("text_columns"));
5683
+
5669
5684
  /* Then, some various variables: */
5670
5685
  VALUE line;
5671
5686
 
5672
5687
  ID chomp_id = rb_intern("chomp!");
5673
5688
  ID gets_id = rb_intern("gets");
5689
+ ID max_id = rb_intern("max");
5690
+ ID size_id = rb_intern("size");
5691
+
5692
+ /* We compute the maximum number of text columns */
5693
+ long last_text_col = last_col+1;
5694
+ VALUE mx = RTEST(text_columns) ? rb_funcall(text_columns, max_id, 0) : Qnil;
5695
+ if(RTEST(mx) && last_text_col < 0) { /* Only taking the max into
5696
+ account if the last col
5697
+ stuff is not on */
5698
+ long d = FIX2LONG(mx);
5699
+ last_text_col = d;
5700
+ }
5701
+
5702
+
5703
+ /* array of Ruby arrays containing the text objects of interest */
5704
+ VALUE * text_cols = NULL;
5705
+
5706
+ /*
5707
+ Handling of text columns.
5708
+
5709
+ The number and position of text columns has to be known in
5710
+ advance. For each of those, the value of text_columns isn't Qnil,
5711
+ and the corresponding column is NULL.
5712
+
5713
+ */
5714
+ if(last_text_col >= 0) {
5715
+ text_cols = ALLOC_N(VALUE, last_text_col + 1);
5716
+ int i;
5717
+ for(i = 0; i < last_text_col + 1; i++)
5718
+ text_cols[i] = Qnil;
5719
+ if(last_col >= 0) {
5720
+ text_cols[last_col+1] = marked_array();
5721
+ }
5722
+ if(RTEST(mx)) {
5723
+ /* Todo */
5724
+ int sz = RARRAY_LENINT(text_columns);
5725
+ int i;
5726
+ for(i = 0; i < sz; i++) {
5727
+ long idx = FIX2LONG(rb_ary_entry(text_columns, i));
5728
+ if(idx >= 0 && (last_col < 0 || idx < last_col)) {
5729
+ text_cols[idx] = marked_array();
5730
+ }
5731
+ }
5732
+ }
5733
+ }
5734
+
5735
+
5736
+
5737
+
5674
5738
  long line_number = 0;
5675
5739
 
5676
5740
  /*
@@ -5690,6 +5754,8 @@ static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE options)
5690
5754
 
5691
5755
 
5692
5756
  int i;
5757
+ for(i = 0; i < current_size; i++)
5758
+ vectors[i] = NULL;
5693
5759
 
5694
5760
  /* The return value */
5695
5761
  VALUE ary;
@@ -5742,47 +5808,76 @@ static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE options)
5742
5808
  pre = post;
5743
5809
  post = Qnil;
5744
5810
  }
5745
- a = StringValueCStr(pre);
5746
- double c = strtod(a, &b);
5747
- if(b == a)
5748
- c = def;
5749
- if(col >= nb_vectors) {
5750
- nb_vectors++;
5751
- /* We need to create a new vector */
5752
- if(col >= current_size) { /* Increase the available size */
5753
- current_size += 5;
5754
- REALLOC_N(vectors, double * , current_size);
5755
- }
5756
-
5757
- double * vals = vectors[col] = ALLOC_N(double, allocated_size);
5758
- /* Filling it with the default value */
5759
- for(i = 0; i < index; i++) {
5760
- vals[i] = def;
5761
- }
5811
+ if(text_cols && col <= last_text_col && RTEST(text_cols[col])) {
5812
+ rb_ary_push(text_cols[col], pre);
5813
+ if(col >= nb_vectors) {
5814
+ nb_vectors ++;
5815
+ if(col < current_size)
5816
+ vectors[col] = NULL;
5817
+ }
5818
+ }
5819
+ else {
5820
+ a = StringValueCStr(pre);
5821
+ double c = strtod(a, &b);
5822
+ if(b == a)
5823
+ c = def;
5824
+ if(col >= nb_vectors) {
5825
+ /* We need to create a new vector */
5826
+ if(col >= current_size) { /* Increase the available size */
5827
+ current_size = col + 5;
5828
+ REALLOC_N(vectors, double * , current_size);
5829
+ }
5830
+ for(; nb_vectors <= col; nb_vectors++)
5831
+ vectors[nb_vectors] = NULL; /* default to NULL */
5832
+
5833
+ double * vals = vectors[col] = ALLOC_N(double, allocated_size);
5834
+ /* Filling it with the default value */
5835
+ for(i = 0; i < index; i++) {
5836
+ vals[i] = def;
5837
+ }
5838
+ }
5839
+ vectors[col][index] = c;
5762
5840
  }
5763
- vectors[col][index] = c;
5764
5841
  col++;
5842
+ if(last_col >= 0 && col > last_col) {
5843
+ rb_ary_push(text_cols[last_col + 1], post);
5844
+ nb_vectors = col + 1;
5845
+ col++;
5846
+ break;
5847
+ }
5765
5848
  }
5766
5849
  /* Now, we finish the line */
5767
- for(; col < nb_vectors; col++)
5768
- vectors[col][index] = def;
5850
+ for(; col < nb_vectors; col++) {
5851
+ if(text_cols && col <= last_text_col && RTEST(text_cols[col]))
5852
+ rb_ary_push(text_cols[col], Qnil);
5853
+ else
5854
+ vectors[col][index] = def;
5855
+ }
5769
5856
  index++;
5770
5857
  /* Now, we reallocate memory if necessary */
5771
5858
  if(index >= allocated_size) {
5772
5859
  allocated_size *= 2; /* We double the size */
5773
- for(col = 0; col < nb_vectors; col++)
5774
- REALLOC_N(vectors[col], double, allocated_size);
5860
+ for(col = 0; col < nb_vectors; col++) {
5861
+ if(col < current_size && vectors[col])
5862
+ REALLOC_N(vectors[col], double, allocated_size);
5863
+ }
5775
5864
  }
5776
5865
  }
5777
5866
  /* Now, we make up the array */
5778
5867
  ary = rb_ary_new();
5779
5868
  for(i = 0; i < nb_vectors; i++) {
5780
5869
  /* We create a vector */
5781
- rb_ary_store(ary, i, make_dvector_from_data(cDvector, index, vectors[i]));
5782
- /* And free the memory */
5783
- free(vectors[i]);
5870
+ if(text_cols && i <= last_text_col && RTEST(text_cols[i]))
5871
+ rb_ary_store(ary, i, text_cols[i]);
5872
+ else {
5873
+ rb_ary_store(ary, i, make_dvector_from_data(cDvector, index, vectors[i]));
5874
+ /* And free the memory */
5875
+ free(vectors[i]);
5876
+ }
5784
5877
  }
5785
5878
  free(vectors);
5879
+ if(text_cols)
5880
+ free(text_cols);
5786
5881
  return ary;
5787
5882
  }
5788
5883
 
@@ -340,8 +340,12 @@ static char *Create_Label(double val, int scale, int prec,
340
340
  /* Exponential, i.e. 10^-1, 1, 10, 10^2, etc */
341
341
  double abs_diff = fabs(val - exponent);
342
342
  if (abs_diff > 0.1) snprintf(buff, sizeof(buff), (s->vertical)? "\\tiogayaxisnumericlabel{10^{%0.1f}}" : "\\tiogaxaxisnumericlabel{10^{%0.1f}}", val);
343
- else if (exponent == 0) strcpy(buff, "1");
344
- else if (exponent == 1) strcpy(buff, "10");
343
+ else if (exponent == 0) strcpy(buff, (s->vertical)?
344
+ "\\tiogayaxisnumericlabel{1}" :
345
+ "\\tiogaxaxisnumericlabel{1}");
346
+ else if (exponent == 1) strcpy(buff, (s->vertical)?
347
+ "\\tiogayaxisnumericlabel{10}" :
348
+ "\\tiogaxaxisnumericlabel{10}");
345
349
  else snprintf(buff, sizeof(buff), (s->vertical)? "\\tiogayaxisnumericlabel{10^{%d}}" : "\\tiogaxaxisnumericlabel{10^{%d}}", exponent);
346
350
  } else { /* Linear */
347
351
  double scale2;
@@ -74,7 +74,122 @@
74
74
  /Decode [1 0] means sample values of 1 are included in the output, values of 0 are excluded
75
75
 
76
76
  */
77
-
77
+
78
+ /*
79
+ Reads next byte, and set *eof on end of file
80
+ */
81
+ static int read_byte(FILE * file, int *eof)
82
+ {
83
+ int c = fgetc(file);
84
+ if(c == EOF)
85
+ *eof = 1;
86
+ else
87
+ *eof = 0;
88
+ return c;
89
+ }
90
+
91
+ /* Reads a 16 bits word */
92
+ static unsigned read_word(FILE * file, int *eof)
93
+ {
94
+ int v = fgetc(file);
95
+ int c = fgetc(file);
96
+ if(v == EOF || c == EOF)
97
+ *eof = 1;
98
+ else
99
+ *eof = 0;
100
+ return ((unsigned) v) << 8 | ((unsigned) c);
101
+ }
102
+
103
+ /* Reads until the next tag, and returns its code */
104
+ static int read_next_tag(FILE * file, int *eof)
105
+ {
106
+ int c;
107
+ *eof = 0;
108
+
109
+ /* Discard non 0xFF bytes */
110
+ do {
111
+ c = read_byte(file, eof);
112
+ if(*eof)
113
+ return 0xFF;
114
+ } while(c != 0xFF);
115
+
116
+ do {
117
+ c = read_byte(file, eof);
118
+ if(*eof)
119
+ return 0xFF;
120
+ } while (c == 0xFF);
121
+ return c;
122
+ }
123
+
124
+ static void skip_variable_length(FILE * file, int *eof)
125
+ {
126
+ *eof = 0;
127
+ int len = read_word(file, eof);
128
+ if(*eof)
129
+ return;
130
+ if(len < 2) {
131
+ *eof = 1;
132
+ return;
133
+ }
134
+ len -= 2;
135
+ while(len > 0) {
136
+ --len;
137
+ read_byte(file, eof);
138
+ if(*eof)
139
+ return;
140
+ }
141
+ }
142
+
143
+
144
+ /* Parses a JPEG file and extracts the resolution data from it, and
145
+ returns a newly allocated JPG_Info structure.
146
+ */
147
+ JPG_Info * Parse_JPG(const char * file)
148
+ {
149
+
150
+ FILE * f = fopen(file, "rb");
151
+ if(! f)
152
+ return NULL;
153
+
154
+ int eof = 0;
155
+ int tag = read_next_tag(f, &eof);
156
+ if(tag != 0xD8 || eof) {
157
+ fclose(f);
158
+ return NULL;
159
+ }
160
+
161
+ while(1) {
162
+ tag = read_next_tag(f, &eof);
163
+ if(eof) {
164
+ fclose(f);
165
+ return NULL;
166
+ }
167
+ switch(tag) {
168
+ case 0xC0: /* image data */
169
+ {
170
+ int len = read_word(f, &eof);
171
+ int bps = read_byte(f, &eof);
172
+ int y = read_word(f, &eof);
173
+ int x = read_word(f, &eof);
174
+ int cmps = read_byte(f, &eof);
175
+ fclose(f);
176
+ if(eof)
177
+ return NULL;
178
+
179
+ JPG_Info * val = (JPG_Info *)calloc(1, sizeof(JPG_Info));
180
+ val->filename = ALLOC_N_char(strlen(file)+1);
181
+ strcpy(val->filename, file);
182
+ val->width = x;
183
+ val->height = y;
184
+ return val;
185
+ }
186
+ default:
187
+ skip_variable_length(f, &eof);
188
+ }
189
+ }
190
+ }
191
+
192
+
78
193
 
79
194
  void
80
195
  Free_JPG(JPG_Info *xo)
@@ -88,6 +203,7 @@ Free_Sampled(Sampled_Info *xo)
88
203
  {
89
204
  if (xo->image_data != NULL) free(xo->image_data);
90
205
  if (xo->lookup != NULL) free(xo->lookup);
206
+ if (xo->filters != NULL) free(xo->filters);
91
207
  }
92
208
 
93
209
 
@@ -164,7 +280,7 @@ void
164
280
  Write_Sampled(Sampled_Info *xo, int *ierr)
165
281
  {
166
282
  fprintf(OF, "\n\t/Subtype /Image\n");
167
- fprintf(OF, "\t/Filter /FlateDecode\n\t/Interpolate %s\n",
283
+ fprintf(OF, "\t/Interpolate %s\n",
168
284
  (xo->interpolate)? "true":"false");
169
285
  fprintf(OF, "\t/Height %i\n", xo->height);
170
286
  fprintf(OF, "\t/Width %i\n", xo->width);
@@ -172,19 +288,20 @@ Write_Sampled(Sampled_Info *xo, int *ierr)
172
288
  unsigned long new_len;
173
289
  unsigned char *image_data;
174
290
  unsigned char *buffer;
291
+ unsigned char *wd;
175
292
  switch (xo->image_type) {
176
293
  case RGB_IMAGE:
177
294
  case HLS_IMAGE:
178
295
  fprintf(OF, "\t/ColorSpace /DeviceRGB\n");
179
- fprintf(OF, "\t/BitsPerComponent 8\n");
296
+ fprintf(OF, "\t/BitsPerComponent %d\n", xo->components);
180
297
  break;
181
298
  case CMYK_IMAGE:
182
299
  fprintf(OF, "\t/ColorSpace /DeviceCMYK\n");
183
- fprintf(OF, "\t/BitsPerComponent 8\n");
300
+ fprintf(OF, "\t/BitsPerComponent %d\n", xo->components);
184
301
  break;
185
302
  case GRAY_IMAGE:
186
303
  fprintf(OF, "\t/ColorSpace /DeviceGray\n");
187
- fprintf(OF, "\t/BitsPerComponent 8\n");
304
+ fprintf(OF, "\t/BitsPerComponent %d\n", xo->components);
188
305
  break;
189
306
  case MONO_IMAGE:
190
307
  fprintf(OF, "\t/ImageMask true\n");
@@ -202,7 +319,7 @@ Write_Sampled(Sampled_Info *xo, int *ierr)
202
319
  else fprintf(OF, "%x", c);
203
320
  }
204
321
  fprintf(OF, "> ]\n");
205
- fprintf(OF, "\t/BitsPerComponent 8\n");
322
+ fprintf(OF, "\t/BitsPerComponent %d\n", xo->components);
206
323
  }
207
324
  if (xo->mask_obj_num > 0) {
208
325
  if (xo->image_type == MONO_IMAGE) {
@@ -226,22 +343,35 @@ Write_Sampled(Sampled_Info *xo, int *ierr)
226
343
  } else {
227
344
  image_data = xo->image_data;
228
345
  }
229
-
230
- new_len = (xo->length * 11)/10 + 100;
231
- buffer = ALLOC_N_unsigned_char(new_len);
232
- if (do_flate_compress(buffer, &new_len, image_data, xo->length)
233
- != FLATE_OK) {
234
- free(buffer);
235
- RAISE_ERROR("Error compressing image data", ierr);
236
- return;
346
+
347
+ buffer = NULL;
348
+ wd = image_data;
349
+
350
+ if(xo->filters) {
351
+ new_len = xo->length;
352
+ fprintf(OF, "%s", xo->filters);
353
+ }
354
+ else {
355
+ fprintf(OF, "\t/Filter /FlateDecode\n");
356
+
357
+ new_len = (xo->length * 11)/10 + 100;
358
+ buffer = ALLOC_N_unsigned_char(new_len);
359
+ if (do_flate_compress(buffer, &new_len, image_data, xo->length)
360
+ != FLATE_OK) {
361
+ free(buffer);
362
+ RAISE_ERROR("Error compressing image data", ierr);
363
+ return;
364
+ }
365
+ wd = buffer;
237
366
  }
238
367
  fprintf(OF, "\t/Length %li\n", new_len);
239
368
  fprintf(OF, "\t>>\nstream\n");
240
- if (fwrite(buffer, 1, new_len, OF) < new_len) {
369
+ if (fwrite(wd, 1, new_len, OF) < new_len) {
241
370
  RAISE_ERROR("Error writing image data", ierr);
242
371
  return;
243
372
  }
244
- free(buffer);
373
+ if(buffer)
374
+ free(buffer);
245
375
  if (xo->image_type == HLS_IMAGE) free(image_data);
246
376
  fprintf(OF, "\nendstream\nendobj\n");
247
377
  }
@@ -258,8 +388,29 @@ Create_Transform_from_Points(double llx, double lly, double lrx, double lry,
258
388
  }
259
389
 
260
390
 
391
+ /* Read the image here ?*/
392
+ int
393
+ c_private_register_jpg(OBJ_PTR fmkr, FM *p, char *filename,
394
+ int width, int height,
395
+ int mask_obj_num, int *ierr)
396
+ {
397
+ JPG_Info *xo = (JPG_Info *)calloc(1,sizeof(JPG_Info));
398
+ xo->xobj_subtype = JPG_SUBTYPE;
399
+ xo->next = xobj_list;
400
+ xobj_list = (XObject_Info *)xo;
401
+ xo->xo_num = next_available_xo_number++;
402
+ xo->obj_num = next_available_object_number++;
403
+ xo->filename = ALLOC_N_char(strlen(filename)+1);
404
+ strcpy(xo->filename, filename);
405
+ xo->width = width;
406
+ xo->height = height;
407
+ xo->mask_obj_num = mask_obj_num;
408
+ return xo->obj_num;
409
+ }
410
+
411
+
261
412
  static void
262
- Get_Image_Dest(FM *p, OBJ_PTR image_destination, double *dest, int *ierr)
413
+ Expand_Array(OBJ_PTR image_destination, double *dest, int *ierr)
263
414
  {
264
415
  int len = Array_Len(image_destination,ierr);
265
416
  if (*ierr != 0) return;
@@ -272,58 +423,31 @@ Get_Image_Dest(FM *p, OBJ_PTR image_destination, double *dest, int *ierr)
272
423
  for (i = 0; i < 6; i++) {
273
424
  OBJ_PTR entry = Array_Entry(image_destination, i, ierr);
274
425
  if (*ierr != 0) return;
275
- if (i % 2 == 0)
276
- dest[i] = convert_figure_to_output_x(p,Number_to_double(entry, ierr));
277
- else
278
- dest[i] = convert_figure_to_output_y(p,Number_to_double(entry, ierr));
426
+ dest[i] = Number_to_double(entry, ierr);
279
427
  if (*ierr != 0) return;
280
428
  }
281
429
  }
282
430
 
283
-
284
- static void
285
- Show_JPEG(FM *p, char *filename, int width, int height, double *dest,
286
- int subtype, int mask_obj_num)
287
- {
288
- JPG_Info *xo = (JPG_Info *)calloc(1,sizeof(JPG_Info));
289
- xo->xobj_subtype = subtype;
290
- double llx = dest[0], lly = dest[1], lrx = dest[2], lry = dest[3],
291
- ulx = dest[4], uly = dest[5];
292
- double a, b, c, d, e, f; // the transform to position the image
293
- xo->next = xobj_list;
294
- xobj_list = (XObject_Info *)xo;
295
- xo->xo_num = next_available_xo_number++;
296
- xo->obj_num = next_available_object_number++;
297
- xo->filename = ALLOC_N_char(strlen(filename)+1);
298
- strcpy(xo->filename, filename);
299
- xo->width = width;
300
- xo->height = height;
301
- xo->mask_obj_num = mask_obj_num;
302
- Create_Transform_from_Points(llx, lly, lrx, lry, ulx, uly,
303
- &a, &b, &c, &d, &e, &f);
304
- fprintf(TF, "q %0.2f %0.2f %0.2f %0.2f %0.2f %0.2f cm /XObj%i Do Q\n",
305
- a, b, c, d, e, f, xo->xo_num);
306
- update_bbox(p, llx, lly);
307
- update_bbox(p, lrx, lry);
308
- update_bbox(p, ulx, uly);
309
- update_bbox(p, lrx+ulx-llx, lry+uly-lly);
310
- }
311
-
312
-
313
431
  void
314
432
  c_private_show_jpg(OBJ_PTR fmkr, FM *p, char *filename,
315
433
  int width, int height, OBJ_PTR image_destination,
316
434
  int mask_obj_num, int *ierr)
317
435
  {
318
436
  double dest[6];
437
+ int ref;
319
438
  if (constructing_path) {
320
439
  RAISE_ERROR("Sorry: must finish with current path before "
321
440
  "calling show_jpg", ierr);
322
441
  return;
323
442
  }
324
- Get_Image_Dest(p, image_destination, dest, ierr);
443
+ ref = c_private_register_jpg(fmkr, p, filename, width, height,
444
+ mask_obj_num, *ierr);
445
+ Expand_Array(image_destination, dest, ierr);
325
446
  if (*ierr != 0) return;
326
- Show_JPEG(p, filename, width, height, dest, JPG_SUBTYPE, mask_obj_num);
447
+
448
+ c_private_show_image_from_ref(fmkr, p, ref, dest[0], dest[1],
449
+ dest[2], dest[3], dest[4], dest[5],
450
+ ierr);
327
451
  }
328
452
 
329
453
 
@@ -465,7 +589,29 @@ c_private_show_image(OBJ_PTR fmkr, FM *p, int image_type, double llx,
465
589
  double uly, bool interpolate, bool reversed,
466
590
  int w, int h, unsigned char* data, long len,
467
591
  OBJ_PTR mask_min, OBJ_PTR mask_max, OBJ_PTR hivalue,
468
- OBJ_PTR lookup_data, int mask_obj_num, int *ierr)
592
+ OBJ_PTR lookup_data, int mask_obj_num, int components,
593
+ const char * filters,
594
+ int *ierr)
595
+ {
596
+ int ref = c_private_register_image(fmkr, p, image_type,
597
+ interpolate, reversed,
598
+ w, h, data, len, mask_min,
599
+ mask_max, hivalue, lookup_data,
600
+ mask_obj_num, components, filters, ierr);
601
+ if (mask_obj_num != -1)
602
+ c_private_show_image_from_ref(fmkr, p, ref, llx, lly,
603
+ lrx, lry, ulx, uly, ierr);
604
+ return Integer_New(ref);
605
+ }
606
+
607
+ int
608
+ c_private_register_image(OBJ_PTR fmkr, FM *p, int image_type,
609
+ bool interpolate, bool reversed,
610
+ int w, int h, unsigned char* data, long len,
611
+ OBJ_PTR mask_min, OBJ_PTR mask_max, OBJ_PTR hivalue,
612
+ OBJ_PTR lookup_data, int mask_obj_num, int components,
613
+ const char * filters,
614
+ int *ierr)
469
615
  {
470
616
  unsigned char *lookup = NULL;
471
617
  int value_mask_min = 256, value_mask_max = 256, lookup_len = 0, hival = 0;
@@ -483,12 +629,6 @@ c_private_show_image(OBJ_PTR fmkr, FM *p, int image_type, double llx,
483
629
  if (*ierr != 0) RETURN_NIL;
484
630
  }
485
631
 
486
- llx = convert_figure_to_output_x(p, llx);
487
- lly = convert_figure_to_output_y(p, lly);
488
- lrx = convert_figure_to_output_x(p, lrx);
489
- lry = convert_figure_to_output_y(p, lry);
490
- ulx = convert_figure_to_output_x(p, ulx);
491
- uly = convert_figure_to_output_y(p, uly);
492
632
 
493
633
  Sampled_Info *xo = (Sampled_Info *)calloc(1, sizeof(Sampled_Info));
494
634
  xo->xobj_subtype = SAMPLED_SUBTYPE;
@@ -502,8 +642,16 @@ c_private_show_image(OBJ_PTR fmkr, FM *p, int image_type, double llx,
502
642
  xo->length = len;
503
643
  xo->interpolate = interpolate;
504
644
  xo->reversed = reversed;
645
+ xo->components = components;
505
646
  memcpy(xo->image_data, data, len);
506
647
  xo->image_type = image_type;
648
+ if(filters) {
649
+ int len = strlen(filters) + 1;
650
+ xo->filters = calloc(1, len);
651
+ memcpy(xo->filters, filters, len);
652
+ }
653
+ else
654
+ xo->filters = NULL;
507
655
  if (image_type != COLORMAP_IMAGE) xo->lookup = NULL;
508
656
  else {
509
657
  if ((hival+1)*3 > lookup_len) {
@@ -523,17 +671,59 @@ c_private_show_image(OBJ_PTR fmkr, FM *p, int image_type, double llx,
523
671
  xo->value_mask_min = value_mask_min;
524
672
  xo->value_mask_max = value_mask_max;
525
673
  xo->mask_obj_num = mask_obj_num;
526
- if (mask_obj_num == -1)
527
- return Integer_New(xo->obj_num); // this image is being used as
528
- // an opacity mask
674
+ return xo->obj_num;
675
+ }
676
+
677
+ /* Goes through the xobject list and find the one whose object number
678
+ matches the one given, and returns the Xobject number. -1 if not
679
+ found. */
680
+
681
+ int Find_XObjRef(int ref)
682
+ {
683
+ XObject_Info * info = xobj_list;
684
+ while(1) {
685
+ if(info->obj_num == ref)
686
+ return info->xo_num;
687
+ info = info->next;
688
+ if(! info)
689
+ break;
690
+ }
691
+ return -1;
692
+ }
693
+
694
+ void
695
+ c_private_show_image_from_ref(OBJ_PTR fmkr, FM *p, int ref, double llx,
696
+ double lly, double lrx, double lry, double ulx,
697
+ double uly,
698
+ int *ierr)
699
+ {
700
+ if (constructing_path) {
701
+ RAISE_ERROR("Sorry: must finish with current path before calling "
702
+ "show_image", ierr);
703
+ return;
704
+ }
705
+
706
+ double a, b, c, d, e, f; // the transform to position the image
707
+ int xo_num = Find_XObjRef(ref);
708
+ if(xo_num < 0) {
709
+ RAISE_ERROR_i("Could not find image PDF object %d", ref,
710
+ ierr);
711
+ return;
712
+ }
713
+
714
+ llx = convert_figure_to_output_x(p, llx);
715
+ lly = convert_figure_to_output_y(p, lly);
716
+ lrx = convert_figure_to_output_x(p, lrx);
717
+ lry = convert_figure_to_output_y(p, lry);
718
+ ulx = convert_figure_to_output_x(p, ulx);
719
+ uly = convert_figure_to_output_y(p, uly);
720
+
529
721
  Create_Transform_from_Points(llx, lly, lrx, lry, ulx, uly,
530
722
  &a, &b, &c, &d, &e, &f);
531
723
  fprintf(TF, "q %0.2f %0.2f %0.2f %0.2f %0.2f %0.2f cm /XObj%i Do Q\n",
532
- a, b, c, d, e, f, xo->xo_num);
724
+ a, b, c, d, e, f, xo_num);
533
725
  update_bbox(p, llx, lly);
534
726
  update_bbox(p, lrx, lry);
535
727
  update_bbox(p, ulx, uly);
536
728
  update_bbox(p, lrx+ulx-llx, lry+uly-lly);
537
- return Integer_New(xo->obj_num);
538
729
  }
539
-