bool readImage(SImage& image, MemChunk& data, int index) { // Get image info SImage::info_t info; FIBITMAP* bm = getFIInfo(data, info); // Check it created/read ok if (!bm) { Global::error = "Unable to read image data (unsupported format?)"; return false; } // Get image palette if it exists RGBQUAD* bm_pal = FreeImage_GetPalette(bm); Palette palette; if (bm_pal) { int a = 0; int b = FreeImage_GetColorsUsed(bm); if (b > 256) b = 256; for (; a < b; a++) palette.setColour(a, rgba_t(bm_pal[a].rgbRed, bm_pal[a].rgbGreen, bm_pal[a].rgbBlue, 255)); } // Create image if (info.has_palette) image.create(info, &palette); else image.create(info); uint8_t* img_data = imageData(image); // Convert to 32bpp & flip vertically FIBITMAP* rgba = FreeImage_ConvertTo32Bits(bm); if (!rgba) { LOG_MESSAGE(1, "FreeImage_ConvertTo32Bits failed for image data"); Global::error = "Error reading PNG data"; return false; } FreeImage_FlipVertical(rgba); // Load raw RGBA data uint8_t* bits_rgba = FreeImage_GetBits(rgba); int c = 0; for (int a = 0; a < info.width * info.height; a++) { img_data[c++] = bits_rgba[a * 4 + 2]; // Red img_data[c++] = bits_rgba[a * 4 + 1]; // Green img_data[c++] = bits_rgba[a * 4]; // Blue img_data[c++] = bits_rgba[a * 4 + 3]; // Alpha } // Free memory FreeImage_Unload(rgba); FreeImage_Unload(bm); return true; }
// ----------------------------------------------------------------------------- // Creates a mask texture of the brush to preview its effect // ----------------------------------------------------------------------------- void GfxCanvas::generateBrushShadow() { if (brush_ == nullptr) return; // Generate image SImage img; img.create(image_.width(), image_.height(), SImage::Type::RGBA); for (int i = -4; i < 5; ++i) for (int j = -4; j < 5; ++j) if (brush_->pixel(i, j)) { auto col = paint_colour_; if (editing_mode_ == EditMode::Translate && translation_) col = translation_->translate( image_.pixelAt(cursor_pos_.x + i, cursor_pos_.y + j, &palette_), &palette_); // Not sure what's the best way to preview cutting out // Mimicking the checkerboard pattern perhaps? // Cyan will do for now else if (editing_mode_ == EditMode::Erase) col = ColRGBA::CYAN; img.setPixel(cursor_pos_.x + i, cursor_pos_.y + j, col); } // Load it as a GL texture OpenGL::Texture::clear(tex_brush_); tex_brush_ = OpenGL::Texture::createFromImage(img); }
/* GfxCanvas::generateBrushShadow * Creates a mask texture of the brush to preview its effect *******************************************************************/ void GfxCanvas::generateBrushShadow() { if (brush == nullptr) return; // Generate image SImage img; img.create(image->getWidth(), image->getHeight(), SIType::RGBA); for (int i = -4; i < 5; ++i) for (int j = -4; j < 5; ++j) if (brush->getPixel(i, j)) { rgba_t col = paint_colour; if (editing_mode == 3 && translation) col = translation->translate(image->getPixel(cursor_pos.x + i, cursor_pos.y + j, getPalette()), getPalette()); // Not sure what's the best way to preview cutting out // Mimicking the checkerboard pattern perhaps? // Cyan will do for now else if (editing_mode == 2) col = COL_CYAN; img.setPixel(cursor_pos.x + i, cursor_pos.y + j, col); } // Load it as a GL texture tex_brush->loadImage(&img); }
bool readImage(SImage& image, MemChunk& data, int index) { // Get info SImage::info_t info = getInfo(data, index); // Create image from data image.create(info.width, info.height, PALMASK); data.read(imageData(image), info.width * info.height, 0); image.fillAlpha(255); return true; }