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

« back to all changes in this revision

Viewing changes to texk/dvipdfmx/dvipdfmx-20110311/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
 
}