void RescaleImage::Get(RGBA *tgt) { if(y < 0 || offsets >= vert.End()) { memset(tgt, 0, sizeof(RGBA) * tsz.cx); return; } offset += *offsets++; ASSERT(offset >= 0 && offset + segspan <= size.cy); if(bigseg) { row_proc(&row_buffers[0 * cx4], GetLine(offset + 0 * step), horz); row_proc(&row_buffers[1 * cx4], GetLine(offset + 1 * step), horz); row_proc(&row_buffers[2 * cx4], GetLine(offset + 2 * step), horz); row_proc(&row_buffers[3 * cx4], GetLine(offset + 3 * step), horz); BltAASet4Fix(tgt, &row_buffers[0 * cx4], &row_buffers[1 * cx4], &row_buffers[2 * cx4], &row_buffers[3 * cx4], tsz.cx); } else { int endoff = offset + segment; for(int next = first + full; next < endoff; next++) { if(full >= segment) first++; else full++; row_proc(&row_buffers[next % segment * cx4], GetLine(next), horz); } while(first > offset) { if(full < segment) full++; --first; row_proc(&row_buffers[first % segment * cx4], GetLine(first), horz); } ASSERT(offset >= first && endoff <= first + full); switch(segment) { case 1: BltAAFix2(tgt, &row_buffers[offset % segment * cx4], tsz.cx); offsets++; break; case 2: if(offsets[0] == 0) BltAAFix2(tgt, &row_buffers[(offset + 1) % segment * cx4], tsz.cx); else if(offsets[1] == 0) BltAAFix2(tgt, &row_buffers[offset % segment * cx4], tsz.cx); else BltAASet2Fix(tgt, &row_buffers[(offset + 0) % segment * cx4], offsets[0], &row_buffers[(offset + 1) % segment * cx4], offsets[1], tsz.cx); offsets += 2; break; case 3: BltAASet3Fix(tgt, &row_buffers[(offset + 0) % segment * cx4], offsets[0], &row_buffers[(offset + 1) % segment * cx4], offsets[1], &row_buffers[(offset + 2) % segment * cx4], offsets[2], tsz.cx); offsets += 3; break; default: NEVER(); break; } } }
bool GReadBitmapFromFile(const char path[], GBitmap* bitmap) { FILE* file = fopen(path, "rb"); if (NULL == file) { return always_false(); } GAutoFClose afc(file); uint8_t signature[SIGNATURE_BYTES]; if (SIGNATURE_BYTES != fread(signature, 1, SIGNATURE_BYTES, file)) { return always_false(); } if (png_sig_cmp(signature, 0, SIGNATURE_BYTES)) { return always_false(); } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (NULL == png_ptr) { return always_false(); } png_infop info_ptr = png_create_info_struct(png_ptr); if (NULL == info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return always_false(); } GAutoPNGReader reader(png_ptr, info_ptr); if (setjmp(png_jmpbuf(png_ptr))) { return always_false(); } png_init_io(png_ptr, file); png_set_sig_bytes(png_ptr, SIGNATURE_BYTES); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; int bitDepth, colorType; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitDepth, &colorType, NULL, NULL, NULL); if (8 != bitDepth) { return always_false(); // TODO: handle other formats } if (png_set_interlace_handling(png_ptr) > 1) { return always_false(); // TODO: support interleave } swizzle_row_proc row_proc = NULL; switch (colorType) { case PNG_COLOR_TYPE_RGB: row_proc = swizzle_rgb_row; break; case PNG_COLOR_TYPE_RGB_ALPHA: row_proc = swizzle_rgba_row; break; default: return always_false(); } png_read_update_info(png_ptr, info_ptr); GAutoFree rowStorage(malloc(png_get_rowbytes(png_ptr, info_ptr))); png_bytep srcRow = (png_bytep)rowStorage.get(); if (!srcRow) { return always_false(); } GAutoFree pixelStorage(malloc(height * width * 4)); GPixel* dstRow = (GPixel*)pixelStorage.get(); if (NULL == dstRow) { return always_false(); } for (int y = 0; y < height; y++) { uint8_t* tmp = srcRow; png_read_rows(png_ptr, &tmp, NULL, 1); row_proc(dstRow, srcRow, width); dstRow += width; } bitmap->fWidth = width; bitmap->fHeight = height; bitmap->fRowBytes = width * 4; bitmap->fPixels = (GPixel*)pixelStorage.detach(); return true; }