w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

bmpimage.c
Go to the documentation of this file.
1 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
2 
3  Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata,
4  the dvipdfmx project team.
5 
6  Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 /*
28  * BMP SUPPORT: Not fully supported.
29  * Unsupported features: Transparency, etc.
30  */
31 
32 #include "system.h"
33 #include "error.h"
34 #include "mem.h"
35 
36 #include "dpxconf.h"
37 
38 #include "pdfobj.h"
39 
40 #include "bmpimage.h"
41 
42 #define DIB_FILE_HEADER_SIZE 14
43 #define DIB_CORE_HEADER_SIZE 12
44 #define DIB_INFO_HEADER_SIZE 40
45 #define DIB_INFO_HEADER_SIZE2 64
46 #define DIB_INFO_HEADER_SIZE4 108
47 #define DIB_INFO_HEADER_SIZE5 124
48 
49 #define DIB_COMPRESS_NONE 0
50 #define DIB_COMPRESS_RLE8 1
51 #define DIB_COMPRESS_RLE4 2
52 
53 #define DIB_HEADER_SIZE_MAX (DIB_FILE_HEADER_SIZE+DIB_INFO_HEADER_SIZE5)
54 
55 struct hdr_info {
56  unsigned int offset;
57  unsigned int hsize;
58  unsigned int width;
59  int height;
60  int compression;
61  unsigned short bit_count; /* Bits per pix */
62  int psize; /* Bytes per palette color: 3 for OS2, 4 for Win */
63  unsigned int x_pix_per_meter;
64  unsigned int y_pix_per_meter;
65 };
66 
67 static int read_header (FILE *fp, struct hdr_info *hdr);
68 static int read_raster_rle8 (unsigned char *data_ptr,
69  int width, int height, FILE *fp);
70 static int read_raster_rle4 (unsigned char *data_ptr,
71  int width, int height, FILE *fp);
72 
73 int
75 {
76  unsigned char sigbytes[2];
77 
78  if (!fp)
79  return 0;
80 
81  rewind(fp);
82  if (fread(sigbytes, 1, sizeof(sigbytes), fp) != sizeof(sigbytes) ||
83  sigbytes[0] != 'B' || sigbytes[1] != 'M')
84  return 0;
85  return 1;
86 }
87 
88 static void
89 get_density (double *xdensity, double *ydensity, struct hdr_info *hdr)
90 {
92  *xdensity = *ydensity = 72.0 / 100.0;
93  else if (hdr->x_pix_per_meter > 0 && hdr->y_pix_per_meter > 0) { /* 0 for undefined. FIXME */
94  *xdensity = 72.0 / (hdr->x_pix_per_meter * 0.0254);
95  *ydensity = 72.0 / (hdr->y_pix_per_meter * 0.0254);
96  } else {
97  *xdensity = 1.0;
98  *ydensity = 1.0;
99  }
100 }
101 
102 int
104  double *xdensity, double *ydensity)
105 {
106  int r;
107  struct hdr_info hdr;
108 
109  rewind(fp);
110  r = read_header(fp, &hdr);
111 
112  *width = hdr.width;
113  *height = hdr.height < 0 ? -hdr.height : hdr.height;
114  get_density(xdensity, ydensity, &hdr);
115 
116  return r;
117 }
118 
119 
120 int
122 {
123  pdf_obj *stream, *stream_dict, *colorspace;
125  struct hdr_info hdr;
126  int num_palette, flip;
127  int i;
128 
130 
131  stream = stream_dict = colorspace = NULL;
132 
133  rewind(fp);
134  if (read_header(fp, &hdr) < 0)
135  return -1;
136 
137  get_density(&info.xdensity, &info.ydensity, &hdr);
138  info.width = hdr.width;
139  info.height = hdr.height;
140  if (info.height < 0) {
141  info.height = -info.height;
142  flip = 0;
143  } else {
144  flip = 1;
145  }
146 
147 
148  if (hdr.bit_count < 24) {
149  if (hdr.bit_count != 1 &&
150  hdr.bit_count != 4 && hdr.bit_count != 8) {
151  WARN("Unsupported palette size: %ld", hdr.bit_count);
152  return -1;
153  }
154  num_palette = (hdr.offset - hdr.hsize - DIB_FILE_HEADER_SIZE) / hdr.psize;
155  info.bits_per_component = hdr.bit_count;
156  info.num_components = 1;
157  } else if (hdr.bit_count == 24) { /* full color */
158  num_palette = 1; /* dummy */
159  info.bits_per_component = 8;
160  info.num_components = 3;
161  } else {
162  WARN("Unkown/Unsupported BMP bitCount value: %ld", hdr.bit_count);
163  return -1;
164  }
165 
166  if (info.width == 0 || info.height == 0 || num_palette < 1) {
167  WARN("Invalid BMP file: width=%ld, height=%ld, #palette=%d",
168  info.width, info.height, num_palette);
169  return -1;
170  }
171 
172  /* Start reading raster data */
174  stream_dict = pdf_stream_dict(stream);
175 
176  /* Color space: Indexed or DeviceRGB */
177  if (hdr.bit_count < 24) {
178  pdf_obj *lookup;
179  unsigned char *palette, bgrq[4];
180 
181  palette = NEW(num_palette*3+1, unsigned char);
182  for (i = 0; i < num_palette; i++) {
183  if (fread(bgrq, 1, hdr.psize, fp) != hdr.psize) {
184  WARN("Reading file failed...");
185  RELEASE(palette);
186  return -1;
187  }
188  /* BGR data */
189  palette[3*i ] = bgrq[2];
190  palette[3*i+1] = bgrq[1];
191  palette[3*i+2] = bgrq[0];
192  }
193  lookup = pdf_new_string(palette, num_palette*3);
194  RELEASE(palette);
195 
196  colorspace = pdf_new_array();
197  pdf_add_array(colorspace, pdf_new_name("Indexed"));
198  pdf_add_array(colorspace, pdf_new_name("DeviceRGB"));
199  pdf_add_array(colorspace, pdf_new_number(num_palette-1));
200  pdf_add_array(colorspace, lookup);
201  } else {
202  colorspace = pdf_new_name("DeviceRGB");
203  }
204  pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace);
205 
206  /* Raster data of BMP is four-byte aligned. */
207  {
208  int rowbytes, n;
209  unsigned char *p, *stream_data_ptr = NULL;
210 
211  rowbytes = (info.width * hdr.bit_count + 7) / 8;
212 
213  seek_absolute(fp, hdr.offset);
214  if (hdr.compression == DIB_COMPRESS_NONE) {
215  int dib_rowbytes;
216  int padding;
217 
218  padding = (rowbytes % 4) ? 4 - (rowbytes % 4) : 0;
219  dib_rowbytes = rowbytes + padding;
220  stream_data_ptr = NEW(rowbytes*info.height + padding, unsigned char);
221  for (n = 0; n < info.height; n++) {
222  p = stream_data_ptr + n * rowbytes;
223  if (fread(p, 1, dib_rowbytes, fp) != dib_rowbytes) {
224  WARN("Reading BMP raster data failed...");
226  RELEASE(stream_data_ptr);
227  return -1;
228  }
229  }
230  } else if (hdr.compression == DIB_COMPRESS_RLE8) {
231  stream_data_ptr = NEW(rowbytes*info.height, unsigned char);
232  if (read_raster_rle8(stream_data_ptr, info.width, info.height, fp) < 0) {
233  WARN("Reading BMP raster data failed...");
235  RELEASE(stream_data_ptr);
236  return -1;
237  }
238  } else if (hdr.compression == DIB_COMPRESS_RLE4) {
239  stream_data_ptr = NEW(rowbytes*info.height, unsigned char);
240  if (read_raster_rle4(stream_data_ptr, info.width, info.height, fp) < 0) {
241  WARN("Reading BMP raster data failed...");
243  RELEASE(stream_data_ptr);
244  return -1;
245  }
246  } else {
247  WARN("Unknown/Unsupported compression type for BMP image: %ld", hdr.compression);
249  return -1;
250  }
251 
252  /* gbr --> rgb */
253  if (hdr.bit_count == 24) {
254  for (n = 0; n < info.width * info.height * 3; n += 3) {
255  unsigned char g;
256  g = stream_data_ptr[n];
257  stream_data_ptr[n ] = stream_data_ptr[n+2];
258  stream_data_ptr[n+2] = g;
259  }
260  }
261 
262  if (flip) {
263  for (n = info.height - 1; n >= 0; n--) {
264  p = stream_data_ptr + n * rowbytes;
265  pdf_add_stream(stream, p, rowbytes);
266  }
267  } else {
268  pdf_add_stream(stream, stream_data_ptr, rowbytes*info.height);
269  }
270  RELEASE(stream_data_ptr);
271  }
272 
273  /* Predictor is usually not so efficient for indexed images. */
274  if (hdr.bit_count >= 24 && info.bits_per_component >= 8 &&
275  info.height > 64) {
277  info.bits_per_component, info.num_components);
278  }
279  pdf_ximage_set_image(ximage, &info, stream);
280 
281  return 0;
282 }
283 
284 
285 static int
287 {
288  unsigned char buf[DIB_HEADER_SIZE_MAX+4];
289  unsigned char *p;
290 
291  p = buf;
292  if (fread(buf, 1, DIB_FILE_HEADER_SIZE + 4, fp)
293  != DIB_FILE_HEADER_SIZE + 4) {
294  WARN("Could not read BMP file header...");
295  return -1;
296  }
297 
298  if (p[0] != 'B' || p[1] != 'M') {
299  WARN("File not starting with \'B\' \'M\'... Not a BMP file?");
300  return -1;
301  }
302  p += 2;
303 
304 #define ULONG_LE(b) ((b)[0] + ((b)[1] << 8) +\
305  ((b)[2] << 16) + ((b)[3] << 24))
306 #define USHORT_LE(b) ((b)[0] + ((b)[1] << 8))
307 
308  /* fsize = ULONG_LE(p); */ p += 4;
309  if (ULONG_LE(p) != 0) {
310  WARN("Not a BMP file???");
311  return -1;
312  }
313  p += 4;
314  hdr->offset = ULONG_LE(p); p += 4;
315 
316  /* info header */
317  hdr->hsize = ULONG_LE(p); p += 4;
318  if (fread(p, sizeof(char), hdr->hsize - 4, fp) != hdr->hsize - 4) {
319  WARN("Could not read BMP file header...");
320  return -1;
321  }
322  switch (hdr->hsize) {
324  hdr->width = USHORT_LE(p); p += 2;
325  hdr->height = USHORT_LE(p); p += 2;
326  hdr->x_pix_per_meter = 0; /* undefined. FIXME */
327  hdr->y_pix_per_meter = 0; /* undefined. FIXME */
328  if (USHORT_LE(p) != 1) {
329  WARN("Unknown bcPlanes value in BMP COREHEADER.");
330  return -1;
331  }
332  p += 2;
333  hdr->bit_count = USHORT_LE(p); p += 2;
334  hdr->compression = DIB_COMPRESS_NONE;
335  hdr->psize = 3;
336  break;
337  case DIB_INFO_HEADER_SIZE :
341  hdr->width = ULONG_LE(p); p += 4;
342  hdr->height = ULONG_LE(p); p += 4;
343  if (USHORT_LE(p) != 1) {
344  WARN("Unknown biPlanes value in BMP INFOHEADER.");
345  return -1;
346  }
347  p += 2;
348  hdr->bit_count = USHORT_LE(p); p += 2;
349  hdr->compression = ULONG_LE(p); p += 4;
350  /* ignore biSizeImage */ p += 4;
351  hdr->x_pix_per_meter = ULONG_LE(p); p += 4;
352  hdr->y_pix_per_meter = ULONG_LE(p); p += 4;
353  hdr->psize = 4;
354  break;
355  default:
356  WARN("Unknown BMP header type.");
357  return -1;
358  }
359 
360  return 0;
361 }
362 
363 static int
364 read_raster_rle8 (unsigned char *data_ptr,
365  int width, int height, FILE *fp)
366 {
367  int count = 0;
368  unsigned char *p, b0, b1;
369  int h, v, rowbytes;
370  int eol, eoi;
371 
372  p = data_ptr;
373  rowbytes = width;
374  memset(data_ptr, 0, rowbytes*height);
375  for (v = 0, eoi = 0; v < height && !eoi; v++) {
376  for (h = 0, eol = 0; h < width && !eol; ) {
377 
380  count += 2;
381 
382  p = data_ptr + v * rowbytes + h;
383 
384  if (b0 == 0x00) {
385  switch (b1) {
386  case 0x00: /* EOL */
387  eol = 1;
388  break;
389  case 0x01: /* EOI */
390  eoi = 1;
391  break;
392  case 0x02:
393  h += get_unsigned_byte(fp);
394  v += get_unsigned_byte(fp);
395  count += 2;
396  break;
397  default:
398  h += b1;
399  if (h > width) {
400  WARN("RLE decode failed...");
401  return -1;
402  }
403  if (fread(p, 1, b1, fp) != b1)
404  return -1;
405  count += b1;
406  if (b1 % 2) {
408  count++;
409  }
410  break;
411  }
412  } else {
413  h += b0;
414  if (h > width) {
415  WARN("RLE decode failed...");
416  return -1;
417  }
418  memset(p, b1, b0);
419  }
420  }
421 
422  /* Check for EOL and EOI marker */
423  if (!eol && !eoi) {
426  if (b0 != 0x00) {
427  WARN("RLE decode failed...");
428  return -1;
429  } else if (b1 == 0x01) {
430  eoi = 1;
431  } else if (b1 != 0x00) {
432  WARN("RLE decode failed...");
433  return -1;
434  }
435  }
436 
437  /* next row ... */
438  }
439 
440  return count;
441 }
442 
443 static int
444 read_raster_rle4 (unsigned char *data_ptr,
445  int width, int height, FILE *fp)
446 {
447  int count = 0;
448  unsigned char *p, b0, b1, b;
449  int h, v, rowbytes;
450  int eol, eoi, i, nbytes;
451 
452  p = data_ptr;
453  rowbytes = (width + 1) / 2;
454  memset(data_ptr, 0, rowbytes*height);
455  for (v = 0, eoi = 0; v < height && !eoi; v++) {
456  for (h = 0, eol = 0; h < width && !eol; ) {
457 
460  count += 2;
461 
462  p = data_ptr + v * rowbytes + (h / 2);
463  if (b0 == 0x00) {
464  switch (b1) {
465  case 0x00: /* EOL */
466  eol = 1;
467  break;
468  case 0x01: /* EOI */
469  eoi = 1;
470  break;
471  case 0x02:
472  h += get_unsigned_byte(fp);
473  v += get_unsigned_byte(fp);
474  count += 2;
475  break;
476  default:
477  if (h + b1 > width) {
478  WARN("RLE decode failed...");
479  return -1;
480  }
481  nbytes = (b1 + 1)/2;
482  if (h % 2) { /* starting at hi-nib */
483  for (i = 0; i < nbytes; i++) {
485  *p++ |= (b >> 4) & 0x0f;
486  *p = (b << 4) & 0xf0;
487  }
488  } else {
489  if (fread(p, 1, nbytes, fp) != nbytes) {
490  return -1;
491  }
492  }
493  h += b1;
494  count += nbytes;
495  if (nbytes % 2) {
497  count++;
498  }
499  break;
500  }
501  } else {
502  if (h + b0 > width) {
503  WARN("RLE decode failed...");
504  return -1;
505  }
506  if (h % 2) {
507  *p++ = (b1 >> 4) & 0x0f;
508  b1 = ((b1 << 4) & 0xf0)|((b1 >> 4) & 0x0f);
509  b0--;
510  h++;
511  }
512  nbytes = (b0 + 1)/2;
513  memset(p, b1, nbytes);
514  h += b0;
515  if (h % 2)
516  p[nbytes-1] &= 0xf0;
517  }
518  }
519 
520  /* Check for EOL and EOI marker */
521  if (!eol && !eoi) {
524  if (b0 != 0x00) {
525  WARN("No EOL/EOI marker. RLE decode failed...");
526  return -1;
527  } else if (b1 == 0x01) {
528  eoi = 1;
529  } else if (b1 != 0x00) {
530  WARN("No EOL/EOI marker. RLE decode failed...");
531  return -1;
532  }
533  }
534 
535  /* next row ... */
536  }
537 
538  return count;
539 }
int lookup(const char *)
#define width(a)
Definition: aptex-macros.h:198
#define count(a)
Definition: aptex-macros.h:781
#define height(a)
Definition: aptex-macros.h:200
int flip
Definition: axohelp.c:116
#define n
Definition: t4ht.c:1290
#define b
Definition: jpegint.h:372
int v
Definition: dviconv.c:10
int h
Definition: dviconv.c:9
#define fread
Definition: xxstdio.h:25
#define info
Definition: dviinfo.c:42
unsigned nbytes
Definition: in_pcx.cpp:355
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
#define NEW
Definition: gdkanji.c:77
static char * eol(char *s)
Definition: writet1.c:426
int bmp_include_image(pdf_ximage *ximage, FILE *fp)
Definition: bmpimage.c:121
int check_for_bmp(FILE *fp)
Definition: bmpimage.c:74
int bmp_get_bbox(FILE *fp, int *width, int *height, double *xdensity, double *ydensity)
Definition: bmpimage.c:103
struct _dpx_conf dpx_conf
Definition: dpxconf.c:33
@ dpx_mode_compat_mode
Definition: dpxconf.h:28
#define buf
#define RELEASE(p)
Definition: mem.h:39
void seek_absolute(FILE *file, int32_t pos)
Definition: mfileio.c:78
unsigned char get_unsigned_byte(FILE *file)
Definition: numbers.c:32
pdf_obj * pdf_new_array(void)
Definition: pdfobj.c:1421
pdf_obj * pdf_new_name(const char *name)
Definition: pdfobj.c:1330
pdf_obj * pdf_new_number(double value)
Definition: pdfobj.c:1076
pdf_obj * pdf_new_stream(int flags)
Definition: pdfobj.c:1863
void pdf_release_obj(pdf_obj *object)
Definition: pdfobj.c:3217
void pdf_stream_set_predictor(pdf_obj *stream, int predictor, int32_t columns, int bpc, int colors)
Definition: pdfobj.c:1894
pdf_obj * pdf_stream_dict(pdf_obj *stream)
Definition: pdfobj.c:2374
void pdf_add_stream(pdf_obj *stream, const void *stream_data, int length)
Definition: pdfobj.c:2424
pdf_obj * pdf_new_string(const void *str, unsigned length)
Definition: pdfobj.c:1131
void pdf_add_array(pdf_obj *array, pdf_obj *object)
Definition: pdfobj.c:1511
int pdf_add_dict(pdf_obj *dict, pdf_obj *key, pdf_obj *value)
Definition: pdfobj.c:1680
#define STREAM_COMPRESS
Definition: pdfobj.h:45
void pdf_ximage_set_image(pdf_ximage *I, void *image_info, pdf_obj *resource)
Definition: pdfximage.c:602
void pdf_ximage_init_image_info(ximage_info *info)
Definition: pdfximage.c:590
static unsigned char sigbytes[4]
Definition: pngimage.c:38
#define b0
Definition: texmfmem.h:168
#define b1
Definition: texmfmem.h:169
#define fp
int g
Definition: ppmqvga.c:68
int r
Definition: ppmqvga.c:68
bstring c int memset(void *s, int c, int length)
struct stream_s stream
Definition: pts_fax.h:93
#define DIB_COMPRESS_RLE8
Definition: bmpimage.c:50
static int read_header(FILE *fp, struct hdr_info *hdr)
Definition: bmpimage.c:286
#define ULONG_LE(b)
#define USHORT_LE(b)
#define DIB_COMPRESS_RLE4
Definition: bmpimage.c:51
#define DIB_HEADER_SIZE_MAX
Definition: bmpimage.c:53
static int read_raster_rle8(unsigned char *data_ptr, int width, int height, FILE *fp)
Definition: bmpimage.c:364
#define DIB_FILE_HEADER_SIZE
Definition: bmpimage.c:42
#define DIB_COMPRESS_NONE
Definition: bmpimage.c:49
#define DIB_INFO_HEADER_SIZE2
Definition: bmpimage.c:45
#define DIB_INFO_HEADER_SIZE4
Definition: bmpimage.c:46
#define DIB_CORE_HEADER_SIZE
Definition: bmpimage.c:43
static int read_raster_rle4(unsigned char *data_ptr, int width, int height, FILE *fp)
Definition: bmpimage.c:444
#define DIB_INFO_HEADER_SIZE
Definition: bmpimage.c:44
#define DIB_INFO_HEADER_SIZE5
Definition: bmpimage.c:47
static void get_density(double *xdensity, double *ydensity, struct hdr_info *hdr)
Definition: bmpimage.c:89
static void WARN(const char *fmt,...)
Definition: bmpimage.c:73
enum dpx_mode compat_mode
Definition: dpxconf.h:36
unsigned int hsize
Definition: bmpimage.c:57
unsigned int y_pix_per_meter
Definition: bmpimage.c:64
int compression
Definition: bmpimage.c:60
unsigned int x_pix_per_meter
Definition: bmpimage.c:63
unsigned int offset
Definition: bmpimage.c:56
unsigned short bit_count
Definition: bmpimage.c:61
int psize
Definition: bmpimage.c:62
unsigned int width
Definition: bmpimage.c:58
int height
Definition: bmpimage.c:59
Definition: zic.c:306
Definition: pdfobj.c:63
#define FILE
Definition: t1stdio.h:34
Definition: alloca.c:152