~ubuntu-branches/ubuntu/utopic/texlive-bin/utopic

« back to all changes in this revision

Viewing changes to texk/dvipdfmx/dvipdfmx-20120420/src/bmpimage.c

  • Committer: Package Import Robot
  • Author(s): Norbert Preining
  • Date: 2012-05-07 10:47:49 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20120507104749-p00ot5sajjbkp1hp
Tags: 2011.20120507-1
* new upstream checkout: uptex 1.10
* drop patches for config file inclusion in (x)dvipdfmx, included upstream
* add man page for etex
* include pmpost patches and build it
* adapt/unfuzzify patches for current sources
* disable mtx building, we have prepmx package in Debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  $Header: /home/cvsroot/dvipdfmx/src/bmpimage.c,v 1.2 2004/07/27 12:08:46 hirata Exp $
 
2
 
 
3
    This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
 
4
 
 
5
    Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
 
6
    the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
 
7
    
 
8
    Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
 
9
 
 
10
    This program is free software; you can redistribute it and/or modify
 
11
    it under the terms of the GNU General Public License as published by
 
12
    the Free Software Foundation; either version 2 of the License, or
 
13
    (at your option) any later version.
 
14
    
 
15
    This program is distributed in the hope that it will be useful,
 
16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
    GNU General Public License for more details.
 
19
    
 
20
    You should have received a copy of the GNU General Public License
 
21
    along with this program; if not, write to the Free Software
 
22
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 
23
*/
 
24
 
 
25
#if HAVE_CONFIG_H
 
26
#include "config.h"
 
27
#endif
 
28
 
 
29
/*
 
30
 * BMP SUPPORT:
 
31
 */
 
32
 
 
33
#include "system.h"
 
34
#include "error.h"
 
35
#include "mem.h"
 
36
 
 
37
#include "pdfobj.h"
 
38
 
 
39
#include "bmpimage.h"
 
40
 
 
41
#define DIB_FILE_HEADER_SIZE 14
 
42
#define DIB_CORE_HEADER_SIZE 14
 
43
#define DIB_INFO_HEADER_SIZE 40
 
44
 
 
45
#define DIB_COMPRESS_NONE 0
 
46
#define DIB_COMPRESS_RLE8 1
 
47
#define DIB_COMPRESS_RLE4 2
 
48
 
 
49
#define DIB_HEADER_SIZE_MAX (DIB_FILE_HEADER_SIZE+DIB_INFO_HEADER_SIZE)
 
50
 
 
51
static long read_raster_rle8 (unsigned char *data_ptr,
 
52
                              long width, long height, FILE *fp);
 
53
static long read_raster_rle4 (unsigned char *data_ptr,
 
54
                              long width, long height, FILE *fp);
 
55
 
 
56
int
 
57
check_for_bmp (FILE *fp)
 
58
{
 
59
 unsigned char sigbytes[2];
 
60
 
 
61
  if (!fp)
 
62
    return 0;
 
63
 
 
64
  rewind(fp);
 
65
  if (fread(sigbytes, 1, sizeof(sigbytes), fp) != sizeof(sigbytes) ||
 
66
      sigbytes[0] != 'B' || sigbytes[1] != 'M')
 
67
    return 0;
 
68
  else
 
69
    return 1;
 
70
  
 
71
  return 0;
 
72
}
 
73
 
 
74
int
 
75
bmp_include_image (pdf_ximage *ximage, FILE *fp)
 
76
{
 
77
  pdf_obj *stream, *stream_dict, *colorspace;
 
78
  ximage_info info;
 
79
  unsigned char  buf[DIB_HEADER_SIZE_MAX+4];
 
80
  unsigned char *p;
 
81
  long offset, fsize, hsize, compression;
 
82
  long psize; /* Bytes per palette color: 3 for OS2, 4 for Win */
 
83
  unsigned short bit_count; /* Bits per pix */
 
84
  int  num_palette, flip;
 
85
  int  i;
 
86
 
 
87
  pdf_ximage_init_image_info(&info);
 
88
 
 
89
  stream = stream_dict = colorspace = NULL;
 
90
  p = buf;
 
91
 
 
92
  rewind(fp);
 
93
  if (fread(buf, 1, DIB_FILE_HEADER_SIZE + 4, fp)
 
94
      != DIB_FILE_HEADER_SIZE + 4) {
 
95
    WARN("Could not read BMP file header...");
 
96
  }
 
97
 
 
98
  if (p[0] != 'B' || p[1] != 'M') {
 
99
    WARN("File not starting with \'B\' \'M\'... Not a BMP file?");
 
100
    return -1;
 
101
  }
 
102
  p += 2;
 
103
 
 
104
#define ULONG_LE(b)  ((b)[0] + ((b)[1] << 8) +\
 
105
                      ((b)[2] << 16) + ((b)[3] << 24))
 
106
#define USHORT_LE(b) ((b)[0] + ((b)[1] << 8))
 
107
 
 
108
  fsize  = ULONG_LE(p); p += 4;
 
109
  if (ULONG_LE(p) != 0) {
 
110
    WARN("Not a BMP file???");
 
111
    return -1;
 
112
  }
 
113
  p += 4;
 
114
  offset = ULONG_LE(p); p += 4;
 
115
 
 
116
  /* info header */
 
117
  hsize  = ULONG_LE(p); p += 4;
 
118
  if (fread(p, sizeof(char), hsize - 4, fp) != hsize - 4) {
 
119
    WARN("Could not read BMP file header...");
 
120
    return -1;
 
121
  }
 
122
  flip = 1;
 
123
  if (hsize == DIB_CORE_HEADER_SIZE) {
 
124
    info.width  = USHORT_LE(p); p += 2;
 
125
    info.height = USHORT_LE(p); p += 2;
 
126
    if (USHORT_LE(p) != 1) {
 
127
      WARN("Unknown bcPlanes value in BMP COREHEADER.");
 
128
      return -1;
 
129
    }
 
130
    p += 2;
 
131
    bit_count   = USHORT_LE(p); p += 2;
 
132
    compression = DIB_COMPRESS_NONE;
 
133
    psize = 3;
 
134
  } else if (hsize == DIB_INFO_HEADER_SIZE) {
 
135
    info.width  = ULONG_LE(p);  p += 4;
 
136
    info.height = ULONG_LE(p);  p += 4;
 
137
    if (USHORT_LE(p) != 1) {
 
138
      WARN("Unknown biPlanes value in BMP INFOHEADER.");
 
139
      return -1;
 
140
    }
 
141
    p += 2;
 
142
    bit_count   = USHORT_LE(p); p += 2;
 
143
    compression = ULONG_LE(p);  p += 4;
 
144
    if (info.height < 0) {
 
145
      info.height = -info.height;
 
146
      flip = 0;
 
147
    }
 
148
    psize = 4;
 
149
  } else {
 
150
    WARN("Unknown BMP header type.");
 
151
    return -1;
 
152
  }
 
153
 
 
154
  if (bit_count < 24) {
 
155
    if (bit_count != 1 &&
 
156
        bit_count != 4 && bit_count != 8) {
 
157
      WARN("Unsupported palette size: %ld", bit_count);
 
158
      return -1;
 
159
    }
 
160
    num_palette = (offset - hsize - DIB_FILE_HEADER_SIZE) / psize;
 
161
    info.bits_per_component = bit_count;
 
162
    info.num_components = 1;
 
163
  } else if (bit_count == 24) { /* full color */
 
164
    num_palette = 1; /* dummy */
 
165
    info.bits_per_component = 8;
 
166
    info.num_components = 3;
 
167
  } else {
 
168
    WARN("Unkown BMP bitCount: %ld", bit_count);
 
169
    return -1;
 
170
  }
 
171
 
 
172
  if (info.width == 0 || info.height == 0 || num_palette < 1) {
 
173
    WARN("Invalid BMP file: width=%ld, height=%ld, #palette=%d",
 
174
         info.width, info.height, num_palette);
 
175
    return -1;
 
176
  }
 
177
 
 
178
  stream      = pdf_new_stream(STREAM_COMPRESS);
 
179
  stream_dict = pdf_stream_dict(stream);
 
180
 
 
181
  if (bit_count < 24) {
 
182
    pdf_obj *lookup;
 
183
    unsigned char *palette, bgrq[4];
 
184
 
 
185
    palette = NEW(num_palette*3+1, unsigned char);
 
186
    for (i = 0; i < num_palette; i++) {
 
187
      if (fread(bgrq, 1,  psize, fp) != psize) {
 
188
        WARN("Reading file failed...");
 
189
        RELEASE(palette);
 
190
        return -1;
 
191
      }
 
192
      /* BGR data */
 
193
      palette[3*i  ] = bgrq[2];
 
194
      palette[3*i+1] = bgrq[1];
 
195
      palette[3*i+2] = bgrq[0];
 
196
    }
 
197
    lookup = pdf_new_string(palette, num_palette*3);
 
198
    RELEASE(palette);
 
199
 
 
200
    colorspace = pdf_new_array();
 
201
    pdf_add_array(colorspace, pdf_new_name("Indexed"));
 
202
    pdf_add_array(colorspace, pdf_new_name("DeviceRGB"));
 
203
    pdf_add_array(colorspace, pdf_new_number(num_palette-1));
 
204
    pdf_add_array(colorspace, lookup);
 
205
  } else {
 
206
    colorspace = pdf_new_name("DeviceRGB");
 
207
  }
 
208
  pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace);
 
209
 
 
210
  /* Raster data of BMP is four-byte aligned. */
 
211
  {
 
212
    long rowbytes, n;
 
213
    unsigned char *stream_data_ptr = NULL;
 
214
 
 
215
    rowbytes = (info.width * bit_count + 7) / 8;
 
216
 
 
217
    seek_absolute(fp, offset);
 
218
    if (compression == DIB_COMPRESS_NONE) {
 
219
      long dib_rowbytes;
 
220
      int  padding;
 
221
 
 
222
      padding = (rowbytes % 4) ? 4 - (rowbytes % 4) : 0;
 
223
      dib_rowbytes = rowbytes + padding;
 
224
      stream_data_ptr = NEW(rowbytes*info.height + padding,
 
225
                            unsigned char);
 
226
      for (n = 0; n < info.height; n++) {
 
227
        p = stream_data_ptr + n * rowbytes;
 
228
        if (fread(p, 1, dib_rowbytes, fp) != dib_rowbytes) {
 
229
          WARN("Reading BMP raster data failed...");
 
230
          pdf_release_obj(stream);
 
231
          RELEASE(stream_data_ptr);
 
232
          return -1;
 
233
        }
 
234
      }
 
235
    } else if (compression == DIB_COMPRESS_RLE8) {
 
236
      stream_data_ptr = NEW(rowbytes*info.height, unsigned char);
 
237
      if (read_raster_rle8(stream_data_ptr,
 
238
                           info.width, info.height, fp) < 0) {
 
239
        WARN("Reading BMP raster data failed...");
 
240
        pdf_release_obj(stream);
 
241
        RELEASE(stream_data_ptr);
 
242
        return -1;
 
243
      }
 
244
    } else if (compression == DIB_COMPRESS_RLE4) {
 
245
      stream_data_ptr = NEW(rowbytes*info.height, unsigned char);
 
246
      if (read_raster_rle4(stream_data_ptr,
 
247
                           info.width, info.height, fp) < 0) {
 
248
        WARN("Reading BMP raster data failed...");
 
249
        pdf_release_obj(stream);
 
250
        RELEASE(stream_data_ptr);
 
251
        return -1;
 
252
      }
 
253
    } else {
 
254
      pdf_release_obj(stream);
 
255
      return -1;
 
256
    }
 
257
 
 
258
    /* gbr --> rgb */
 
259
    if (bit_count == 24) {
 
260
      for (n = 0; n < info.width * info.height * 3; n += 3) {
 
261
        unsigned char g;
 
262
        g = stream_data_ptr[n];
 
263
        stream_data_ptr[n  ] = stream_data_ptr[n+2];
 
264
        stream_data_ptr[n+2] = g;
 
265
      }
 
266
    }
 
267
 
 
268
    if (flip) {
 
269
      for (n = info.height - 1; n >= 0; n--) {
 
270
        p = stream_data_ptr + n * rowbytes;
 
271
        pdf_add_stream(stream, p, rowbytes);
 
272
      }
 
273
    } else {
 
274
      pdf_add_stream(stream, stream_data_ptr, rowbytes*info.height);
 
275
    }
 
276
    RELEASE(stream_data_ptr);
 
277
  }
 
278
 
 
279
  pdf_ximage_set_image(ximage, &info, stream);
 
280
 
 
281
  return 0;
 
282
}
 
283
 
 
284
static long
 
285
read_raster_rle8 (unsigned char *data_ptr,
 
286
                  long width, long height, FILE *fp)
 
287
{
 
288
  long count = 0;
 
289
  unsigned char *p, b0, b1;
 
290
  long h, v, rowbytes;
 
291
  int  eol, eoi;
 
292
 
 
293
  p = data_ptr;
 
294
  rowbytes = width;
 
295
  memset(data_ptr, 0, rowbytes*height);
 
296
  for (v = 0, eoi = 0; v < height && !eoi; v++) {
 
297
    for (h = 0, eol = 0; h < width && !eol; ) {
 
298
 
 
299
      b0 = get_unsigned_byte(fp);
 
300
      b1 = get_unsigned_byte(fp);
 
301
      count += 2;
 
302
 
 
303
      p = data_ptr + v * rowbytes + h;
 
304
 
 
305
      if (b0 == 0x00) {
 
306
        switch (b1) {
 
307
        case 0x00: /* EOL */
 
308
          eol = 1;
 
309
          break;
 
310
        case 0x01: /* EOI */
 
311
          eoi = 1;
 
312
          break;
 
313
        case 0x02:
 
314
          h += get_unsigned_byte(fp);
 
315
          v += get_unsigned_byte(fp);
 
316
          count += 2;
 
317
          break;
 
318
        default:
 
319
          h += b1;
 
320
          if (h > width) {
 
321
            WARN("RLE decode failed...");
 
322
            return -1;
 
323
          }
 
324
          if (fread(p, 1, b1, fp) != b1)
 
325
            return -1;
 
326
          count += b1;
 
327
          if (b1 % 2) {
 
328
            get_unsigned_byte(fp);
 
329
            count++;
 
330
          }
 
331
          break;
 
332
        }
 
333
      } else {
 
334
        h += b0;
 
335
        if (h > width) {
 
336
          WARN("RLE decode failed...");
 
337
          return -1;
 
338
        }
 
339
        memset(p, b1, b0);
 
340
      }
 
341
    }
 
342
 
 
343
    /* Check for EOL and EOI marker */
 
344
    if (!eol && !eoi) {
 
345
      b0 = get_unsigned_byte(fp);
 
346
      b1 = get_unsigned_byte(fp);
 
347
      if (b0 != 0x00) {
 
348
        WARN("RLE decode failed...");
 
349
        return -1;
 
350
      } else if (b1 == 0x01) {
 
351
        eoi = 1;
 
352
      } else if (b1 != 0x00) {
 
353
        WARN("RLE decode failed...");
 
354
        return -1;
 
355
      }
 
356
    }
 
357
 
 
358
    /* next row ... */
 
359
  }
 
360
 
 
361
  return count;
 
362
}
 
363
 
 
364
static long
 
365
read_raster_rle4 (unsigned char *data_ptr,
 
366
                  long width, long height, FILE *fp)
 
367
{
 
368
  long count = 0;
 
369
  unsigned char *p, b0, b1, b;
 
370
  long h, v, rowbytes;
 
371
  int  eol, eoi, i, nbytes;
 
372
 
 
373
  p = data_ptr;
 
374
  rowbytes = (width + 1) / 2;
 
375
  memset(data_ptr, 0, rowbytes*height);
 
376
  for (v = 0, eoi = 0; v < height && !eoi; v++) {
 
377
    for (h = 0, eol = 0; h < width && !eol; ) {
 
378
 
 
379
      b0 = get_unsigned_byte(fp);
 
380
      b1 = get_unsigned_byte(fp);
 
381
      count += 2;
 
382
 
 
383
      p  = data_ptr + v * rowbytes + (h / 2);
 
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
          if (h + b1 > width) {
 
399
            WARN("RLE decode failed...");
 
400
            return -1;
 
401
          }
 
402
          nbytes = (b1 + 1)/2;
 
403
          if (h % 2) { /* starting at hi-nib */
 
404
            for (i = 0; i < nbytes; i++) {
 
405
              b = get_unsigned_byte(fp);
 
406
              *p++ |= (b >> 4) & 0x0f;
 
407
              *p    = (b << 4) & 0xf0;
 
408
            }
 
409
          } else {
 
410
            if (fread(p, 1, nbytes, fp) != nbytes) {
 
411
              return -1;
 
412
            }
 
413
          }
 
414
          h     += b1;
 
415
          count += nbytes;
 
416
          if (nbytes % 2) {
 
417
            get_unsigned_byte(fp);
 
418
            count++;
 
419
          }
 
420
          break;
 
421
        }
 
422
      } else {
 
423
        if (h + b0 > width) {
 
424
          WARN("RLE decode failed...");
 
425
          return -1;
 
426
        }
 
427
        if (h % 2) {
 
428
          *p++ = (b1 >> 4) & 0x0f;
 
429
          b1   = ((b1 << 4) & 0xf0)|((b1 >> 4) & 0x0f);
 
430
          b0--;
 
431
          h++;
 
432
        }
 
433
        nbytes = (b0 + 1)/2;
 
434
        memset(p, b1, nbytes);
 
435
        h += b0;
 
436
        if (h % 2)
 
437
          p[nbytes-1] &= 0xf0;
 
438
      }
 
439
    }
 
440
 
 
441
    /* Check for EOL and EOI marker */
 
442
    if (!eol && !eoi) {
 
443
      b0 = get_unsigned_byte(fp);
 
444
      b1 = get_unsigned_byte(fp);
 
445
      if (b0 != 0x00) {
 
446
        WARN("No EOL/EOI marker. RLE decode failed...");
 
447
        return -1;
 
448
      } else if (b1 == 0x01) {
 
449
        eoi = 1;
 
450
      } else if (b1 != 0x00) {
 
451
        WARN("No EOL/EOI marker. RLE decode failed...");
 
452
        return -1;
 
453
      }
 
454
    }
 
455
 
 
456
    /* next row ... */
 
457
  }
 
458
 
 
459
  return count;
 
460
}