示例#1
0
myBMP * loadBMP(char *name)
{
FILE * inFile = NULL;
myBMP * mybm = NULL;
BITMAPINFOHEADER bmih;
BITMAPFILEHEADER bmfh;
ubyte bmpinfoheader[64];
ulong headerSize;
int mapentrysize = 0;		/* 0 indicates no colormap */
long bPad;
ulong my_row_bytes,bmp_row_bytes;

#define LBM_cleanUp(err) do { if ( inFile ) fclose(inFile); if ( mybm ) freeBMP(mybm); return( NULL); } while(0)

#define GET_2B(array,offset) ((uword) (ubyte)(array[offset+0]) + \
						 	(((uword) (ubyte)(array[offset+1])) << 8))
#define GET_4B(array,offset) ((ulong) (ubyte)(array[offset+0]) + \
						 	(((ulong) (ubyte)(array[offset+1])) << 8) + \
						 	(((ulong) (ubyte)(array[offset+2])) << 16) + \
						 	(((ulong) (ubyte)(array[offset+3])) << 24))
	
	if ( (inFile = fopen(name,"rb")) == NULL ) 
		LBM_cleanUp("fopen");

	/* Read and verify the bitmap file header */

	if (! FReadOk(inFile, &bmfh, sizeof(BITMAPFILEHEADER)))
		LBM_cleanUp("read short");

	if ( bmfh.bfType != BM_TAG )
		LBM_cleanUp("bmp sign");

	bPad = bmfh.bfOffBits;

	/* 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 (! FReadOk(inFile, bmpinfoheader, 4))
		LBM_cleanUp("read short");

	headerSize = (ulong) GET_4B(bmpinfoheader,0);

	if (headerSize < 12 || headerSize > 64)
		LBM_cleanUp("bad header size");

	if (! FReadOk(inFile, bmpinfoheader+4, headerSize-4))
		LBM_cleanUp("read short");

	if ( ( mybm = new(myBMP)) == NULL )
		LBM_cleanUp("malloc");

	memcpy((char *)(&(bmih)),bmpinfoheader,	min(sizeof(BITMAPINFOHEADER),headerSize));

	switch (bmih.biBitCount) 
	{
		case 8:			/* colormapped image */
			mapentrysize = 4;		/* Windows uses RGBQUAD colormap */
			if ( bmih.biClrUsed == 0 ) bmih.biClrUsed = 256;
			break;
		case 24:			/* RGB image */
			mapentrysize = 0;
			break;
		default:
			LBM_cleanUp("bad depth");
			break;
	}

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

	/* Read the colormap, if any */
	if (mapentrysize > 0 && bmih.biClrUsed > 0) 
	{
		RGBQUAD pal[256];
		int i;

		mybm->ncolors = bmih.biClrUsed;
		if ( mybm->ncolors > 256 ) mybm->ncolors  = 256;

		if ( (mybm->palette = malloc(256*3)) == NULL )
			LBM_cleanUp("malloc");

		if (! FReadOk(inFile, pal , (mapentrysize * mybm->ncolors)))
			LBM_cleanUp("read short");

		for(i=0;i<mybm->ncolors;i++) 
		{
			mybm->palette[i*3 + 0] = pal[i].R;
			mybm->palette[i*3 + 1] = pal[i].G;
			mybm->palette[i*3 + 2] = pal[i].B;
		}

		/* account for size of colormap */
		bPad -= mybm->ncolors * mapentrysize;
	}

	/* Skip any remaining pad bytes */
	if (bPad < 0)			/* incorrect bfOffBits value? */
		LBM_cleanUp("bad header length");
	else if ( bPad > 0 ) 
	{
		fseek(inFile,bPad,SEEK_CUR);
	}

	/* Compute row width in file, including padding to 4-byte boundary */
	if (bmih.biBitCount == 24)	my_row_bytes = bmih.biWidth * 3;
	else						my_row_bytes = bmih.biWidth;

	bmp_row_bytes = (my_row_bytes+3)&(~3) ;

	bmih.biSize = sizeof(BITMAPINFOHEADER);
	bmih.biSizeImage = bmp_row_bytes * abs(bmih.biHeight);

	mybm->width = bmih.biWidth;
	mybm->height = abs(bmih.biHeight);
	mybm->type = ( bmih.biBitCount == 24 ) ? MBTYPE_24BIT_RGB : MBTYPE_8BIT_PAL;

	mybm->dataBytes = my_row_bytes * mybm->height;

	if ( (mybm->data = malloc(mybm->dataBytes + bmp_row_bytes)) == NULL )
		LBM_cleanUp("malloc failed");

	{
	int step;
	ubyte * ptr;
	int y;
	ubyte garbage[4];

		if ( bmih.biHeight > 0 )
		{
			step = - (int)my_row_bytes;
			ptr = mybm->data + my_row_bytes * (mybm->height - 1);
		}
		else
		{
			step = my_row_bytes;
			ptr = mybm->data;
		}

		for(y=0;y<mybm->height;y++)
		{
			FRead(inFile,ptr,my_row_bytes);
			FRead(inFile,garbage,bmp_row_bytes - my_row_bytes);
			
			if (bmih.biBitCount == 24)
				swapBGRtoRGB(ptr,my_row_bytes);

			ptr += step;
		}
	}

	fclose(inFile); inFile = NULL;

return mybm;
}
示例#2
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;
}
示例#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;
}