Back to index

texmacs  1.0.7.15
Functions
bmpimage.h File Reference
#include "mfileio.h"
#include "pdfximage.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int bmp_include_image (pdf_ximage *ximage, FILE *file)
int check_for_bmp (FILE *file)

Function Documentation

int bmp_include_image ( pdf_ximage *  ximage,
FILE *  file 
)

Definition at line 75 of file bmpimage.c.

{
  pdf_obj *stream, *stream_dict, *colorspace;
  ximage_info info;
  unsigned char  buf[DIB_HEADER_SIZE_MAX+4];
  unsigned char *p;
  long offset, fsize, hsize, compression;
  long psize; /* Bytes per palette color: 3 for OS2, 4 for Win */
  unsigned short bit_count; /* Bits per pix */
  int  num_palette, flip;
  int  i;

  pdf_ximage_init_image_info(&info);

  stream = stream_dict = colorspace = NULL;
  p = buf;

  rewind(fp);
  if (fread(buf, 1, DIB_FILE_HEADER_SIZE + 4, fp)
      != DIB_FILE_HEADER_SIZE + 4) {
    WARN("Could not read BMP file header...");
  }

  if (p[0] != 'B' || p[1] != 'M') {
    WARN("File not starting with \'B\' \'M\'... Not a BMP file?");
    return -1;
  }
  p += 2;

#define ULONG_LE(b)  ((b)[0] + ((b)[1] << 8) +\
                    ((b)[2] << 16) + ((b)[3] << 24))
#define USHORT_LE(b) ((b)[0] + ((b)[1] << 8))

  fsize  = ULONG_LE(p); p += 4;
  if (ULONG_LE(p) != 0) {
    WARN("Not a BMP file???");
    return -1;
  }
  p += 4;
  offset = ULONG_LE(p); p += 4;

  /* info header */
  hsize  = ULONG_LE(p); p += 4;
  if (fread(p, sizeof(char), hsize - 4, fp) != hsize - 4) {
    WARN("Could not read BMP file header...");
    return -1;
  }
  flip = 1;
  if (hsize == DIB_CORE_HEADER_SIZE) {
    info.width  = USHORT_LE(p); p += 2;
    info.height = USHORT_LE(p); p += 2;
    if (USHORT_LE(p) != 1) {
      WARN("Unknown bcPlanes value in BMP COREHEADER.");
      return -1;
    }
    p += 2;
    bit_count   = USHORT_LE(p); p += 2;
    compression = DIB_COMPRESS_NONE;
    psize = 3;
  } else if (hsize == DIB_INFO_HEADER_SIZE) {
    info.width  = ULONG_LE(p);  p += 4;
    info.height = ULONG_LE(p);  p += 4;
    if (USHORT_LE(p) != 1) {
      WARN("Unknown biPlanes value in BMP INFOHEADER.");
      return -1;
    }
    p += 2;
    bit_count   = USHORT_LE(p); p += 2;
    compression = ULONG_LE(p);  p += 4;
    if (info.height < 0) {
      info.height = -info.height;
      flip = 0;
    }
    psize = 4;
  } else {
    WARN("Unknown BMP header type.");
    return -1;
  }

  if (bit_count < 24) {
    if (bit_count != 1 &&
       bit_count != 4 && bit_count != 8) {
      WARN("Unsupported palette size: %ld", bit_count);
      return -1;
    }
    num_palette = (offset - hsize - DIB_FILE_HEADER_SIZE) / psize;
    info.bits_per_component = bit_count;
    info.num_components = 1;
  } else if (bit_count == 24) { /* full color */
    num_palette = 1; /* dummy */
    info.bits_per_component = 8;
    info.num_components = 3;
  } else {
    WARN("Unkown BMP bitCount: %ld", bit_count);
    return -1;
  }

  if (info.width == 0 || info.height == 0 || num_palette < 1) {
    WARN("Invalid BMP file: width=%ld, height=%ld, #palette=%d",
        info.width, info.height, num_palette);
    return -1;
  }

  stream      = pdf_new_stream(STREAM_COMPRESS);
  stream_dict = pdf_stream_dict(stream);

  if (bit_count < 24) {
    pdf_obj *lookup;
    unsigned char *palette, bgrq[4];

    palette = NEW(num_palette*3+1, unsigned char);
    for (i = 0; i < num_palette; i++) {
      if (fread(bgrq, 1,  psize, fp) != psize) {
       WARN("Reading file failed...");
       RELEASE(palette);
       return -1;
      }
      /* BGR data */
      palette[3*i  ] = bgrq[2];
      palette[3*i+1] = bgrq[1];
      palette[3*i+2] = bgrq[0];
    }
    lookup = pdf_new_string(palette, num_palette*3);
    RELEASE(palette);

    colorspace = pdf_new_array();
    pdf_add_array(colorspace, pdf_new_name("Indexed"));
    pdf_add_array(colorspace, pdf_new_name("DeviceRGB"));
    pdf_add_array(colorspace, pdf_new_number(num_palette-1));
    pdf_add_array(colorspace, lookup);
  } else {
    colorspace = pdf_new_name("DeviceRGB");
  }
  pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace);

  /* Raster data of BMP is four-byte aligned. */
  {
    long rowbytes, n;
    unsigned char *stream_data_ptr = NULL;

    rowbytes = (info.width * bit_count + 7) / 8;

    seek_absolute(fp, offset);
    if (compression == DIB_COMPRESS_NONE) {
      long dib_rowbytes;
      int  padding;

      padding = (rowbytes % 4) ? 4 - (rowbytes % 4) : 0;
      dib_rowbytes = rowbytes + padding;
      stream_data_ptr = NEW(rowbytes*info.height + padding,
                         unsigned char);
      for (n = 0; n < info.height; n++) {
       p = stream_data_ptr + n * rowbytes;
       if (fread(p, 1, dib_rowbytes, fp) != dib_rowbytes) {
         WARN("Reading BMP raster data failed...");
         pdf_release_obj(stream);
         RELEASE(stream_data_ptr);
         return -1;
       }
      }
    } else if (compression == DIB_COMPRESS_RLE8) {
      stream_data_ptr = NEW(rowbytes*info.height, unsigned char);
      if (read_raster_rle8(stream_data_ptr,
                        info.width, info.height, fp) < 0) {
       WARN("Reading BMP raster data failed...");
       pdf_release_obj(stream);
       RELEASE(stream_data_ptr);
       return -1;
      }
    } else if (compression == DIB_COMPRESS_RLE4) {
      stream_data_ptr = NEW(rowbytes*info.height, unsigned char);
      if (read_raster_rle4(stream_data_ptr,
                        info.width, info.height, fp) < 0) {
       WARN("Reading BMP raster data failed...");
       pdf_release_obj(stream);
       RELEASE(stream_data_ptr);
       return -1;
      }
    } else {
      pdf_release_obj(stream);
      return -1;
    }

    /* gbr --> rgb */
    if (bit_count == 24) {
      for (n = 0; n < info.width * info.height * 3; n += 3) {
       unsigned char g;
       g = stream_data_ptr[n];
       stream_data_ptr[n  ] = stream_data_ptr[n+2];
       stream_data_ptr[n+2] = g;
      }
    }

    if (flip) {
      for (n = info.height - 1; n >= 0; n--) {
       p = stream_data_ptr + n * rowbytes;
       pdf_add_stream(stream, p, rowbytes);
      }
    } else {
      pdf_add_stream(stream, stream_data_ptr, rowbytes*info.height);
    }
    RELEASE(stream_data_ptr);
  }

  pdf_ximage_set_image(ximage, &info, stream);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int check_for_bmp ( FILE *  file)

Definition at line 57 of file bmpimage.c.

{
 unsigned char sigbytes[2];

  if (!fp)
    return 0;

  rewind(fp);
  if (fread(sigbytes, 1, sizeof(sigbytes), fp) != sizeof(sigbytes) ||
      sigbytes[0] != 'B' || sigbytes[1] != 'M')
    return 0;
  else
    return 1;
  
  return 0;
}

Here is the caller graph for this function: