Пример #1
0
void ImageBMP::ReadBMP(const uint8_t* data, unsigned len, bool transparent,
					   int& width, int& height, void*& pixels) {
	pixels = NULL;

	// BITMAPFILEHEADER structure
	//
	// 0	2	signature: 'B','M'
	// 2	4	file size
	// 6	2	reserved
	// 8	2	reserved
	// 10	4	offset to bitmap data
	static const unsigned BITMAPFILEHEADER_SIZE = 14;

	if (len < 64) {
		Output::Error("Not a valid BMP file.");
		return;
	}

	// file size is skipped because every program writes other data into
	// this field and not needed for correct decoding.

	const unsigned bits_offset = get_4(&data[10]);

	// BITMAPINFOHEADER structure (BMP 2.x and 3.x)
	//
	// 0	4	BITMAPINFOHEADER size
	// 4	4	width
	// 8	4	height (+ve => bottom-up, -ve => top-down)
	// 12	2	number of planes (must be 1)
	// 14	2	bits per pixel
	// 16	4	compression
	// 20	4	image size
	// 24	4	X pixels per meter
	// 28	4	Y pixels per meter
	// 32	4	number of palette colors used
	// 36	4	number of important palette colors
	// size ... palette (starts at 40 in BMP 2.x/3.x and 108 in BMP 4.x)


	width = (int) get_4(&data[BITMAPFILEHEADER_SIZE + 4]);
	height = (int) get_4(&data[BITMAPFILEHEADER_SIZE + 8]);

	// bitmap scan lines need to be aligned to 32 bit boundaries, add padding if needed
	int padding = (width % 4 != 0) ? 4 - width % 4 : 0;

	bool vflip = height > 0;
	if (!vflip)
		height = -height;

	const int planes = (int) get_2(&data[BITMAPFILEHEADER_SIZE + 12]);
	if (planes != 1) {
		Output::Error("BMP planes is not 1.");
		return;
	}

	const int depth = (int) get_2(&data[BITMAPFILEHEADER_SIZE + 14]);
	if (depth != 8) {
		Output::Error("BMP image is not 8-bit.");
		return;
	}

	const int compression = get_4(&data[BITMAPFILEHEADER_SIZE + 16]);
	static const int BI_RGB = 0;
	if (compression != BI_RGB) {
		Output::Error("BMP image is compressed.");
		return;
	}

	int num_colors = std::min(256U, get_4(&data[BITMAPFILEHEADER_SIZE + 32]));
	uint8_t (*palette)[4] = (uint8_t(*)[4]) &data[BITMAPFILEHEADER_SIZE +
		get_4(&data[BITMAPFILEHEADER_SIZE + 0])];
	const uint8_t* src_pixels = &data[bits_offset];

	// Ensure no palette entry is an exact duplicate of #0
	for (int i = 1; i < num_colors; i++) {
		if (palette[i][0] == palette[0][0] &&
			palette[i][1] == palette[0][1] &&
			palette[i][2] == palette[0][2]) {
			palette[i][0] ^= 1;
		}
	}

	pixels = malloc(width * height * 4);

	uint8_t* dst = (uint8_t*) pixels;
	for (int y = 0; y < height; y++) {
		const uint8_t* src = src_pixels + (vflip ? height - 1 - y : y) * (width + padding);
		for (int x = 0; x < width; x++) {
			const uint8_t& pix = *src++;
			const uint8_t* color = palette[pix];
			*dst++ = color[2];
			*dst++ = color[1];
			*dst++ = color[0];
			*dst++ = (transparent && pix == 0) ? 0 : 255;
		}
	}
}
Пример #2
0
static void
process_esd (bfd *abfd, struct ext_esd *esd, int pass)
{
  /* Read through the ext def for the est entries.  */
  int togo = esd->size - 2;
  bfd_vma size;
  bfd_vma start;
  asection *sec;
  char name[11];
  unsigned char *ptr = esd->esd_entries;
  unsigned char *end = ptr + togo;

  while (ptr < end)
    {
      int scn = *ptr & 0xf;
      int typ = (*ptr >> 4) & 0xf;

      /* Declare this section.  */
      sprintf (name, "%d", scn);
      sec = bfd_make_section_old_way (abfd, strdup (name));
      sec->target_index = scn;
      EDATA (abfd, scn).section = sec;
      ptr++;

      switch (typ)
	{
	default:
	  abort ();
	case ESD_XREF_SEC:
	case ESD_XREF_SYM:
	  {
	    int snum = VDATA (abfd)->ref_idx++;
	    get_10 (&ptr, name);
	    if (pass == 1)
	      VDATA (abfd)->stringlen += strlen (name) + 1;
	    else
	      {
		int esidx;
		asymbol *s;
		char *n = new_symbol_string (abfd, name);

		s = versados_new_symbol (abfd, snum, n, (bfd_vma) 0,
					 bfd_und_section_ptr);
		esidx = VDATA (abfd)->es_done++;
		RDATA (abfd, esidx - ES_BASE) = s;
	      }
	  }
	  break;

	case ESD_ABS:
	  size = get_4 (&ptr);
	  start = get_4 (&ptr);
	  break;
	case ESD_STD_REL_SEC:
	case ESD_SHRT_REL_SEC:
	  sec->size = get_4 (&ptr);
	  sec->flags |= SEC_ALLOC;
	  break;
	case ESD_XDEF_IN_ABS:
	  sec = (asection *) & bfd_abs_section;
	case ESD_XDEF_IN_SEC:
	  {
	    int snum = VDATA (abfd)->def_idx++;
	    bfd_vma val;

	    get_10 (&ptr, name);
	    val = get_4 (&ptr);
	    if (pass == 1)
	      /* Just remember the symbol.  */
	      VDATA (abfd)->stringlen += strlen (name) + 1;
	    else
	      {
		asymbol *s;
		char *n = new_symbol_string (abfd, name);

		s = versados_new_symbol (abfd, snum + VDATA (abfd)->nrefs, n,
					 val, sec);
		s->flags |= BSF_GLOBAL;
	      }
	  }
	  break;
	}
    }
}
Пример #3
0
static int read_bmp_header(const unsigned char *p)
{
    if (*p++ != 'B')
	return 0;
    if (*p++ != 'M')
	return 0;

    if (get_4(&p) != HEADER_SIZE + png.width * png.height * 4)
	return 0;

    get_4(&p);

    if (get_4(&p) != HEADER_SIZE)
	return 0;

    if (get_4(&p) != 40)
	return 0;

    if (get_4(&p) != png.width)
	return 0;
    if (get_4(&p) != -png.height)
	return 0;

    get_2(&p);
    if (get_2(&p) != 32)
	return 0;

    if (get_4(&p) != 0)
	return 0;
    if (get_4(&p) != png.width * png.height * 4)
	return 0;

    get_4(&p);
    get_4(&p);
    get_4(&p);
    get_4(&p);

    return 1;
}