static int read_logical_screen_descriptor(Gif_Stream *gfs, Gif_Reader *grr) /* returns 0 on memory error */ { uint8_t packed; /* we don't care about logical screen width or height */ gfs->screen_width = gifgetunsigned(grr); gfs->screen_height = gifgetunsigned(grr); packed = gifgetbyte(grr); gfs->background = gifgetbyte(grr); /* don't care about pixel aspect ratio */ gifgetbyte(grr); if (packed & 0x80) { /* have a global color table */ int ncol = 1 << ((packed & 0x07) + 1); gfs->global = read_color_table(ncol, grr); if (!gfs->global) return 0; gfs->global->refcount = 1; } return 1; }
void BmpReader::init(FILE* f, size_t& w, size_t& h) { my_file = f; my_pixel_offset = read_file_header(f); size_t bpp, table_num; read_image_header(f, w, h, bpp, table_num); if(bpp == 8) read_color_table(f, my_color_table, table_num); else if(bpp != 24) throw InvalidFormat("unexpected bits per pixel in BMP image header"); }
void gif_process_image(FILE *fp, image_t *img) { logical_screen_descriptor_t lsd; color_table_t gct; graphic_control_extension_t gce = {0,0,0,0, false}; bool data_left = true; lsd = read_header(&fp); (*img).width = lsd.w; (*img).height = lsd.h; (*img).frames = 1; (*img).animate = false; (*img).canvas = malloc(sizeof(rgba_t)); // init one frame right now (*img).canvas[0] = malloc(lsd.w * lsd.h * sizeof(rgba_t)); // setup first frame if(check_nth_bit(lsd.meta, 0)) { gct.active = true; gct.size = ((0x07&lsd.meta)+1); gct.size = gct.size * gct.size; read_color_table(&fp, &gct); } else { gct.active = false; } while(data_left) { unsigned char bt; fread(&bt, 1, 1, fp); switch(bt) { case 0x21: // extension fread(&bt, 1, 1, fp); if(bt == 0xF9) { fread(&gce, 1, sizeof(graphic_control_extension_t), fp); gce.set = true; } break; case 0x2c: // image process_image_block(&fp, &gct, (*img).canvas[0], &gce); gce.set = false; // no need to overwrite, just ignore break; case 0x3b: // trailer data_left = false; break; }; } if(gct.active) { close_color_table(&gct); } }
void process_image_block(FILE **fp, color_table_t *gct, rgba_t *canvas, graphic_control_extension_t *gce) { image_descriptor_t id; color_table_t lct; color_table_t *ct; unsigned char code_size; unsigned char block_size; fread(&id, 1, sizeof(image_descriptor_t), *fp); if(check_nth_bit(id.meta, 0)) { lct.active = true; lct.size = ((0x07&id.meta)+1); lct.size = lct.size * lct.size; read_color_table(fp, &lct); ct = &lct; } else { lct.active = false; ct = gct; } fread(&code_size, 1, 1, *fp); printf("Processing Image block...\n"); do { fread(&block_size, 1, 1, *fp); if(block_size != 0x00) { unsigned char *raw_data; unsigned char *processed_data; raw_data = malloc(sizeof(unsigned char)*block_size); for(int i = 0; i < block_size; ++i) { fread(&raw_data[i], 1, 1, *fp); } processed_data = malloc(id.w * id.h); decompress(code_size, raw_data, block_size, processed_data); for(int i = 0; i < (id.w * id.h); ++i) { canvas[i] = (*ct).table[processed_data[i]]; } free(raw_data); free(processed_data); } } while(block_size != 0x00); printf("Block process complete.\n"); if(lct.active) { close_color_table(&lct); } }
static int read_image(Gif_Reader *grr, Gif_Context *gfc, Gif_Image *gfi, int read_flags) /* returns 0 on memory error */ { uint8_t packed; gfi->left = gifgetunsigned(grr); gfi->top = gifgetunsigned(grr); gfi->width = gifgetunsigned(grr); gfi->height = gifgetunsigned(grr); packed = gifgetbyte(grr); GIF_DEBUG(("<%ux%u>", gfi->width, gfi->height)); if (packed & 0x80) { /* have a local color table */ int ncol = 1 << ((packed & 0x07) + 1); gfi->local = read_color_table(ncol, grr); if (!gfi->local) return 0; gfi->local->refcount = 1; } gfi->interlace = (packed & 0x40) != 0; /* Keep the compressed data if asked */ if (read_flags & GIF_READ_COMPRESSED) { if (!read_compressed_image(gfi, grr, read_flags)) return 0; if (read_flags & GIF_READ_UNCOMPRESSED) { Gif_Reader new_grr; make_data_reader(&new_grr, gfi->compressed, gfi->compressed_len); if (!uncompress_image(gfc, gfi, &new_grr)) return 0; } } else if (read_flags & GIF_READ_UNCOMPRESSED) { if (!uncompress_image(gfc, gfi, grr)) return 0; } else { /* skip over the image */ uint8_t buffer[GIF_MAX_BLOCK]; int i = gifgetbyte(grr); while (i > 0) { gifgetblock(buffer, i, grr); i = gifgetbyte(grr); } } return 1; }
static int read_image(Gif_Reader *grr, Gif_Context *gfc, Gif_Image *gfi, int read_flags) /* returns 0 on memory error */ { uint8_t packed; gfi->left = gifgetunsigned(grr); gfi->top = gifgetunsigned(grr); gfi->width = gifgetunsigned(grr); gfi->height = gifgetunsigned(grr); /* Mainline GIF processors (Firefox, etc.) process missing width (height) as screen_width (screen_height). */ if (gfi->width == 0) gfi->width = gfc->stream->screen_width; if (gfi->height == 0) gfi->height = gfc->stream->screen_height; /* If still zero, error. */ if (gfi->width == 0 || gfi->height == 0) { gif_read_error(gfc, 1, "image has zero width and/or height"); Gif_MakeImageEmpty(gfi); read_flags = 0; } /* If position out of range, error. */ if ((unsigned) gfi->left + (unsigned) gfi->width > 0xFFFF || (unsigned) gfi->top + (unsigned) gfi->height > 0xFFFF) { gif_read_error(gfc, 1, "image position and/or dimensions out of range"); Gif_MakeImageEmpty(gfi); read_flags = 0; } GIF_DEBUG(("<%ux%u>", gfi->width, gfi->height)); packed = gifgetbyte(grr); if (packed & 0x80) { /* have a local color table */ int ncol = 1 << ((packed & 0x07) + 1); gfi->local = read_color_table(ncol, grr); if (!gfi->local) return 0; gfi->local->refcount = 1; } gfi->interlace = (packed & 0x40) != 0; /* Keep the compressed data if asked */ if (read_flags & GIF_READ_COMPRESSED) { if (!read_compressed_image(gfi, grr, read_flags)) return 0; if (read_flags & GIF_READ_UNCOMPRESSED) { Gif_Reader new_grr; make_data_reader(&new_grr, gfi->compressed, gfi->compressed_len); if (!uncompress_image(gfc, gfi, &new_grr)) return 0; } } else if (read_flags & GIF_READ_UNCOMPRESSED) { if (!uncompress_image(gfc, gfi, grr)) return 0; } else { /* skip over the image */ uint8_t buffer[GIF_MAX_BLOCK]; int i = gifgetbyte(grr); while (i > 0) { gifgetblock(buffer, i, grr); i = gifgetbyte(grr); } } return 1; }
static Bitmap read_bmp_or_throw(const FilePath& filePath){ BinaryReader in(filePath); if (!in.good()){ throw ReadBmpError(error_open_file_read(filePath)); } auto bitmapFileHeader = read_struct_or_throw_bmp<BitmapFileHeader>(in); if (bitmapFileHeader.fileType != BITMAP_SIGNATURE){ throw ReadBmpError(error_bitmap_signature(bitmapFileHeader.fileType)); } auto bitmapInfoHeader = read_struct_or_throw_bmp<BitmapInfoHeader>(in); if (invalid_header_length(bitmapInfoHeader.headerLen)){ throw ReadBmpError(error_truncated_bmp_header(bitmapInfoHeader.headerLen)); } if (bitmapInfoHeader.compression != Compression::BI_RGB){ throw ReadBmpError(error_compression(bitmapInfoHeader.compression)); } if (bitmapInfoHeader.colorPlanes != 1){ throw ReadBmpError(error_color_planes(bitmapInfoHeader.colorPlanes)); } auto bmpSize = get_size_and_order(bitmapInfoHeader); if (bitmapInfoHeader.paletteColors != 0){ if (bitmapInfoHeader.bitsPerPixel != 8){ // Fixme: Maybe support? throw ReadBmpError("Palette for non 8-bpp bitmaps unsupported by Faint."); } auto colorList = or_throw(read_color_table(in, bitmapInfoHeader.paletteColors), "Failed reading color table."); in.seekg(bitmapFileHeader.dataOffset); auto alphaMap = or_throw(read_8bipp_BI_RGB(in, bmpSize), "Failed reading 8-bits-per-pixel data"); return bitmap_from_indexed_colors(alphaMap, colorList); } else{ // No palette in.seekg(bitmapFileHeader.dataOffset); if (bitmapInfoHeader.bitsPerPixel == 8){ auto alphaMap = or_throw(read_8bipp_BI_RGB(in, bmpSize), "Failed reading 8-bits-per-pixel data"); return bitmap_from_indexed_colors(alphaMap, grayscale_color_table()); } else if (bitmapInfoHeader.bitsPerPixel == 24){ return or_throw(read_24bipp_BI_RGB(in, bmpSize), "Failed reading 24-bits-per-pixel data."); } else if (bitmapInfoHeader.bitsPerPixel == 32){ return or_throw(read_32bipp_BI_RGB(in, bmpSize), "Failed reading 32-bits-per-pixel data."); } } throw ReadBmpError(Sentence("Unsupported bits-per-pixel", bracketed(str_int(bitmapInfoHeader.bitsPerPixel)))); }