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; } } }
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; } } }
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; }