Beispiel #1
0
start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
  bmp_source_ptr source = (bmp_source_ptr) sinfo;
  U_CHAR bmpfileheader[14];
  U_CHAR bmpinfoheader[64];
#define GET_2B(array,offset)  ((unsigned int) UCH(array[offset]) + \
			       (((unsigned int) UCH(array[offset+1])) << 8))
#define GET_4B(array,offset)  ((INT32) UCH(array[offset]) + \
			       (((INT32) UCH(array[offset+1])) << 8) + \
			       (((INT32) UCH(array[offset+2])) << 16) + \
			       (((INT32) UCH(array[offset+3])) << 24))
  INT32 bfOffBits;
  INT32 headerSize;
  INT32 biWidth;
  INT32 biHeight;
  unsigned int biPlanes;
  INT32 biCompression;
  INT32 biXPelsPerMeter,biYPelsPerMeter;
  INT32 biClrUsed = 0;
  int mapentrysize = 0;		/* 0 indicates no colormap */
  INT32 bPad;
  JDIMENSION row_width;

  /* Read and verify the bitmap file header */
  if (! ReadOK(source->pub.input_file, bmpfileheader, 14))
    ERREXIT(cinfo, JERR_INPUT_EOF);
  if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */
    ERREXIT(cinfo, JERR_BMP_NOT);
  bfOffBits = (INT32) GET_4B(bmpfileheader,10);
  /* We ignore the remaining fileheader fields */

  /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows),
   * or 64 bytes (OS/2 2.x).  Check the first 4 bytes to find out which.
   */
  if (! ReadOK(source->pub.input_file, bmpinfoheader, 4))
    ERREXIT(cinfo, JERR_INPUT_EOF);
  headerSize = (INT32) GET_4B(bmpinfoheader,0);
  if (headerSize < 12 || headerSize > 64)
    ERREXIT(cinfo, JERR_BMP_BADHEADER);
  if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4))
    ERREXIT(cinfo, JERR_INPUT_EOF);

  switch ((int) headerSize) {
  case 12:
    /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
    biWidth = (INT32) GET_2B(bmpinfoheader,4);
    biHeight = (INT32) GET_2B(bmpinfoheader,6);
    biPlanes = GET_2B(bmpinfoheader,8);
    source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10);

    switch (source->bits_per_pixel) {
    case 8:			/* colormapped image */
      mapentrysize = 3;		/* OS/2 uses RGBTRIPLE colormap */
      TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
      break;
    case 24:			/* RGB image */
      TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight);
      break;
    default:
      ERREXIT(cinfo, JERR_BMP_BADDEPTH);
      break;
    }
    break;
  case 40:
  case 64:
    /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */
    /* or OS/2 2.x header, which has additional fields that we ignore */
    biWidth = GET_4B(bmpinfoheader,4);
    biHeight = GET_4B(bmpinfoheader,8);
    biPlanes = GET_2B(bmpinfoheader,12);
    source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14);
    biCompression = GET_4B(bmpinfoheader,16);
    biXPelsPerMeter = GET_4B(bmpinfoheader,24);
    biYPelsPerMeter = GET_4B(bmpinfoheader,28);
    biClrUsed = GET_4B(bmpinfoheader,32);
    /* biSizeImage, biClrImportant fields are ignored */

    switch (source->bits_per_pixel) {
    case 8:			/* colormapped image */
      mapentrysize = 4;		/* Windows uses RGBQUAD colormap */
      TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
      break;
    case 24:			/* RGB image */
      TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
      break;
    case 32:			/* RGB image + Alpha Channel */
      TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
      break;
    default:
      ERREXIT(cinfo, JERR_BMP_BADDEPTH);
      break;
    }
    if (biCompression != 0)
      ERREXIT(cinfo, JERR_BMP_COMPRESSED);

    if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
      /* Set JFIF density parameters from the BMP data */
      cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */
      cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
      cinfo->density_unit = 2;	/* dots/cm */
    }
    break;
  default:
    ERREXIT(cinfo, JERR_BMP_BADHEADER);
    return;
  }

  if (biWidth <= 0 || biHeight <= 0)
    ERREXIT(cinfo, JERR_BMP_EMPTY);
  if (biPlanes != 1)
    ERREXIT(cinfo, JERR_BMP_BADPLANES);

  /* Compute distance to bitmap data --- will adjust for colormap below */
  bPad = bfOffBits - (headerSize + 14);

  /* Read the colormap, if any */
  if (mapentrysize > 0) {
    if (biClrUsed <= 0)
      biClrUsed = 256;		/* assume it's 256 */
    else if (biClrUsed > 256)
      ERREXIT(cinfo, JERR_BMP_BADCMAP);
    /* Allocate space to store the colormap */
    source->colormap = (*cinfo->mem->alloc_sarray)
      ((j_common_ptr) cinfo, JPOOL_IMAGE,
       (JDIMENSION) biClrUsed, (JDIMENSION) 3);
    /* and read it from the file */
    read_colormap(source, (int) biClrUsed, mapentrysize);
    /* account for size of colormap */
    bPad -= biClrUsed * mapentrysize;
  }

  /* Skip any remaining pad bytes */
  if (bPad < 0)			/* incorrect bfOffBits value? */
    ERREXIT(cinfo, JERR_BMP_BADHEADER);
  while (--bPad >= 0) {
    (void) read_byte(source);
  }

  /* Compute row width in file, including padding to 4-byte boundary */
  if (source->bits_per_pixel == 24)
    row_width = (JDIMENSION) (biWidth * 3);
  else if (source->bits_per_pixel == 32)
    row_width = (JDIMENSION) (biWidth * 4);
  else
    row_width = (JDIMENSION) biWidth;
  while ((row_width & 3) != 0) row_width++;
  source->row_width = row_width;

  /* Allocate space for inversion array, prepare for preload pass */
  source->whole_image = (*cinfo->mem->request_virt_sarray)
    ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
     row_width, (JDIMENSION) biHeight, (JDIMENSION) 1);
  source->pub.get_pixel_rows = preload_image;
  if (cinfo->progress != NULL) {
    cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
    progress->total_extra_passes++; /* count file input as separate pass */
  }

  /* Allocate one-row buffer for returned data */
  source->pub.buffer = (*cinfo->mem->alloc_sarray)
    ((j_common_ptr) cinfo, JPOOL_IMAGE,
     (JDIMENSION) (biWidth * 3), (JDIMENSION) 1);
  source->pub.buffer_height = 1;

  cinfo->in_color_space = JCS_RGB;
  cinfo->input_components = 3;
  cinfo->data_precision = 8;
  cinfo->image_width = (JDIMENSION) biWidth;
  cinfo->image_height = (JDIMENSION) biHeight;
}
Beispiel #2
0
start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
  tga_source_ptr source = (tga_source_ptr) sinfo;
  U_CHAR targaheader[18];
  int idlen, cmaptype, subtype, flags, interlace_type, components;
  unsigned int width, height, maplen;
  boolean is_bottom_up;

#define GET_2B(offset)	((unsigned int) UCH(targaheader[offset]) + \
			 (((unsigned int) UCH(targaheader[offset+1])) << 8))

  if (! ReadOK(source->pub.input_file, targaheader, 18))
    ERREXIT(cinfo, JERR_INPUT_EOF);

  /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
  if (targaheader[16] == 15)
    targaheader[16] = 16;

  idlen = UCH(targaheader[0]);
  cmaptype = UCH(targaheader[1]);
  subtype = UCH(targaheader[2]);
  maplen = GET_2B(5);
  width = GET_2B(12);
  height = GET_2B(14);
  source->pixel_size = UCH(targaheader[16]) >> 3;
  flags = UCH(targaheader[17]);	/* Image Descriptor byte */

  is_bottom_up = ((flags & 0x20) == 0);	/* bit 5 set => top-down */
  interlace_type = flags >> 6;	/* bits 6/7 are interlace code */

  if (cmaptype > 1 ||		/* cmaptype must be 0 or 1 */
      source->pixel_size < 1 || source->pixel_size > 4 ||
      (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
      interlace_type != 0)	/* currently don't allow interlaced image */
    ERREXIT(cinfo, JERR_TGA_BADPARMS);
  
  if (subtype > 8) {
    /* It's an RLE-coded file */
    source->read_pixel = read_rle_pixel;
    source->block_count = source->dup_pixel_count = 0;
    subtype -= 8;
  } else {
    /* Non-RLE file */
    source->read_pixel = read_non_rle_pixel;
  }

  /* Now should have subtype 1, 2, or 3 */
  components = 3;		/* until proven different */
  cinfo->in_color_space = JCS_RGB;

  switch (subtype) {
  case 1:			/* Colormapped image */
    if (source->pixel_size == 1 && cmaptype == 1)
      source->get_pixel_rows = get_8bit_row;
    else
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
    TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
    break;
  case 2:			/* RGB image */
    switch (source->pixel_size) {
    case 2:
      source->get_pixel_rows = get_16bit_row;
      break;
    case 3:
      source->get_pixel_rows = get_24bit_row;
      break;
    case 4:
      source->get_pixel_rows = get_32bit_row;
      break;
    default:
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
      break;
    }
    TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
    break;
  case 3:			/* Grayscale image */
    components = 1;
    cinfo->in_color_space = JCS_GRAYSCALE;
    if (source->pixel_size == 1)
      source->get_pixel_rows = get_8bit_gray_row;
    else
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
    TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
    break;
  default:
    ERREXIT(cinfo, JERR_TGA_BADPARMS);
    break;
  }

  if (is_bottom_up) {
    /* Create a virtual array to buffer the upside-down image. */
    source->whole_image = (*cinfo->mem->request_virt_sarray)
      ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
       (JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1);
    if (cinfo->progress != NULL) {
      cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
      progress->total_extra_passes++; /* count file input as separate pass */
    }
    /* source->pub.buffer will point to the virtual array. */
    source->pub.buffer_height = 1; /* in case anyone looks at it */
    source->pub.get_pixel_rows = preload_image;
  } else {
    /* Don't need a virtual array, but do need a one-row input buffer. */
    source->whole_image = NULL;
    source->pub.buffer = (*cinfo->mem->alloc_sarray)
      ((j_common_ptr) cinfo, JPOOL_IMAGE,
       (JDIMENSION) width * components, (JDIMENSION) 1);
    source->pub.buffer_height = 1;
    source->pub.get_pixel_rows = source->get_pixel_rows;
  }
  
  while (idlen--)		/* Throw away ID field */
    (void) read_byte(source);

  if (maplen > 0) {
    if (maplen > 256 || GET_2B(3) != 0)
      ERREXIT(cinfo, JERR_TGA_BADCMAP);
    /* Allocate space to store the colormap */
    source->colormap = (*cinfo->mem->alloc_sarray)
      ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3);
    /* and read it from the file */
    read_colormap(source, (int) maplen, UCH(targaheader[7]));
  } else {
    if (cmaptype)		/* but you promised a cmap! */
      ERREXIT(cinfo, JERR_TGA_BADPARMS);
    source->colormap = NULL;
  }

  cinfo->input_components = components;
  cinfo->data_precision = 8;
  cinfo->image_width = width;
  cinfo->image_height = height;
}
Beispiel #3
0
///////////////////////////////////////
//////////READ BMP/////////////////////
CONVERT_IMAGERESULT
start_input_bmp (CONVERT_IMG_INFO *p_imageinfo, CONVERT_IMGCONTEXT *p_inputparam)
{
    CONVERT_IMAGERESULT t_err;
    U_CHAR bmpfileheader[14];
    U_CHAR bmpinfoheader[64];
#define GET_2B(array,offset)  ((uint16) UCH(array[offset]) + \
			       (((uint16) UCH(array[offset+1])) << 8))
#define GET_4B(array,offset)  ((int32) UCH(array[offset]) + \
			       (((int32) UCH(array[offset+1])) << 8) + \
			       (((int32) UCH(array[offset+2])) << 16) + \
			       (((int32) UCH(array[offset+3])) << 24))
    int32 bfOffBits;
    int32 headerSize;
    int32 biWidth = 0;		/* initialize to avoid compiler warning */
    int32 biHeight = 0;
    uint16 biPlanes;
    int32 biCompression;
    int32 biXPelsPerMeter,biYPelsPerMeter;
    int32 biClrUsed = 0;
    int16 mapentrysize = 0;		/* 0 indicates no colormap */
    DWORD t_index=0;/*index to stream*/
    int32 bPad;
    uint16 row_width;
    if (p_inputparam->m_stream.m_type==CONVERT_FILE)
    {
        if (!read_param(&p_inputparam->m_stream,bmpfileheader,14))
        {   /*cant read fileheader*/
            return CONVERR_INVALIDFILEHEADER;
        }
        p_imageinfo->m_image_size+=14;
        /* Read and verify the bitmap file header */
        if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */
            return CONVERR_INVALIDFILEHEADER;
        bfOffBits = (int32) GET_4B(bmpfileheader,10);
    }
    if (! read_param(&p_inputparam->m_stream, bmpinfoheader, 4))
        return CONVERR_INVALIDIMAGEHEADER;//cant read 4 bytes
    p_imageinfo->m_image_size+=4;
    headerSize = (int32) GET_4B(bmpinfoheader,0);
    if (headerSize < 12 || headerSize > 64)
        return CONVERR_INVALIDIMAGEHEADER;
    if (! read_param(
                &p_inputparam->m_stream,
                bmpinfoheader+4,
                (int16)(headerSize-4))) /*casting here is ok beacause of check for >64 above*/
        return CONVERR_INVALIDIMAGEHEADER;
    p_imageinfo->m_image_size+=headerSize-4;
    switch ((int16) headerSize) {
    case 12:
        /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
        biWidth = (int32) GET_2B(bmpinfoheader,4);
        biHeight = (int32) GET_2B(bmpinfoheader,6);
        biPlanes = GET_2B(bmpinfoheader,8);
        p_imageinfo->m_bitsperpixel = (int16) GET_2B(bmpinfoheader,10);

        switch (p_imageinfo->m_bitsperpixel) {
        case 8:			/* colormapped image */
            mapentrysize = 3;		/* OS/2 uses RGBTRIPLE colormap */
            break;
        case 16:
        case 24:			/* RGB image */
            break;
        default:
            return CONVERR_INVALIDBITDEPTH;
            break;
        }
        if (biPlanes != 1)
            return CONVERR_INVALIDBITDEPTH;
        break;
    case 40:
    case 64:
        /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */
        /* or OS/2 2.x header, which has additional fields that we ignore */
        biWidth = GET_4B(bmpinfoheader,4);
        biHeight = GET_4B(bmpinfoheader,8);
        biPlanes = GET_2B(bmpinfoheader,12);
        p_imageinfo->m_bitsperpixel = (int16) GET_2B(bmpinfoheader,14);
        biCompression = GET_4B(bmpinfoheader,16);
        biXPelsPerMeter = GET_4B(bmpinfoheader,24);
        biYPelsPerMeter = GET_4B(bmpinfoheader,28);
        biClrUsed = GET_4B(bmpinfoheader,32);
        /* biSizeImage, biClrImportant fields are ignored */
        switch (p_imageinfo->m_bitsperpixel) {
        case 1:
            if (!biClrUsed)/* 0 denotes maximum usage of colors*/
                biClrUsed=2;
        case 4:
            if (!biClrUsed)/* 0 denotes maximum usage of colors*/
                biClrUsed=16;
        case 8:			/* colormapped images */
            if (!biClrUsed)/* 0 denotes maximum usage of colors*/
                biClrUsed=256;
            mapentrysize = 4;		/* Windows uses RGBQUAD colormap */
            break;
        case 24:			/* RGB image */
            break;
        case 16:
        case 32:			/* RGB image with masks*/
            if (biCompression==3) /*BI_BITFIELDS*/
            {
                biClrUsed=3; /*need to get masks for RGB*/
                mapentrysize = 4;		/* Windows uses RGBQUAD colormap */
            }
            break;
        default:
            return CONVERR_INVALIDBITDEPTH;
            break;
        }

        if (biPlanes != 1)
            return FALSE;
        if (biCompression != 0)
            if (3!=biCompression)
                return CONVERR_COMPRESSED;//cant handle compressed bitmaps

        if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
            /* Set JFIF density parameters from the BMP data */
            p_imageinfo->m_X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */
            p_imageinfo->m_Y_density = (UINT16) (biYPelsPerMeter/100);
            p_imageinfo->m_density_unit = 2;	/* dots/cm */
        }
        break;
    default:
        return CONVERR_INVALIDIMAGEHEADER;
        break;
    }

    /* Compute distance to bitmap data --- will adjust for colormap below */
    bPad = bfOffBits - (headerSize + 14);

    /* Read the colormap, if any */
    if (mapentrysize > 0) {
        if (biClrUsed <= 0)
            biClrUsed = 256;		/* assume it's 256 */
        else if (biClrUsed > 256)
            return CONVERR_INVALIDCOLORMAP;
        /* Allocate space to store the colormap */
        p_imageinfo->m_colormap = (BYTE *)malloc(biClrUsed*3);
        /* and read it from the file */
        t_err=read_colormap_bmp(p_inputparam,p_imageinfo->m_colormap, (int16) biClrUsed, mapentrysize);
        if (t_err!=CONV_OK)
            return t_err;
        p_imageinfo->m_image_size+=biClrUsed*mapentrysize;/*mapentrysize for windows bitmaps*/
        /* account for size of colormap */
        bPad -= biClrUsed * mapentrysize;
    }

    if (CONVERT_FILE==p_inputparam->m_stream.m_type)/* Skip any remaining pad bytes */
    {
        if (bPad < 0)			/* incorrect bfOffBits value? */
            return CONVERR_INVALIDIMAGEHEADER;
        while (--bPad >= 0)
        {
            (void) read_param_byte(&p_inputparam->m_stream);
            p_imageinfo->m_image_size++;
        }
    }
    /* Compute row width in file, including padding to 4-byte boundary */
    switch (p_imageinfo->m_bitsperpixel)
    {
    case 1:
        row_width = biWidth/8;
        if (biWidth&7)
            row_width++;
        break;
    case 4:
        row_width = biWidth/2;
        if (biWidth&1)
            row_width++;
        break;
    case 8:
        row_width = (uint16) biWidth;
        break;
    case 16:
        row_width = (uint16) (biWidth * 2);
        break;
    case 24:
        row_width = (uint16) (biWidth * 3);
        break;
    case 32:
        row_width = (uint16) (biWidth * 4);
        break;
    default:
        return CONVERR_INVALIDBITDEPTH;
    }
    p_imageinfo->m_stride=row_width;
    while ((row_width & 3) != 0)
        row_width++;
    p_imageinfo->m_row_width = row_width;
    p_imageinfo->m_stride=p_imageinfo->m_row_width-p_imageinfo->m_stride;//difference

    /* p_imageinfo->m_in_color_space = JCS_RGB;*/
    /* in color space is ignored. was only for JPEG PAL format*/
    p_imageinfo->m_input_components = 3;
    p_imageinfo->m_data_precision = 8;
    p_imageinfo->m_image_width = (uint16) biWidth;
    p_imageinfo->m_image_height = (uint16) biHeight;
    p_imageinfo->m_numcolorentries=(short)biClrUsed;
    return CONV_OK;
}