c++ - 如何从 FLTK Fl__Image__Surface 获取具有透明背景的图像?
问题描述
我想绘制字符串或字符(离屏)并将其用作 Fl_Image 或 Fl_RGB_Image。基于此链接,我可以使用 Fl__Image__Surface 轻松完成此操作。Fl__Image__Surface 的问题是当我使用方法将其输出转换为图像(Fl_RGB_Image)时它不支持透明度image()
。那么有什么方法可以实现这一目标吗?我可以在带有 BufferedImage的 Java Swing 上执行此操作,也可以在带有Canvas的Android中执行此操作,方法是使用 Bitmap.Config.ARGB_8888创建位图。
解决方案
如果您更喜欢手动操作,可以尝试以下操作:
#include <FL/Enumerations.H>
#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Device.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Image.H>
#include <FL/Fl_Image_Surface.H>
#include <FL/fl_draw.H>
#include <cassert>
#include <vector>
Fl_RGB_Image *get_image(int w, int h) {
// draw image on surface
auto img_surf = new Fl_Image_Surface(w, h);
Fl_Surface_Device::push_current(img_surf);
// We'll use white to mask 255, 255, 255, see the loop
fl_color(FL_WHITE);
fl_rectf(0, 0, w, h);
fl_color(FL_BLACK);
fl_font(FL_HELVETICA_BOLD, 20);
fl_draw("Hello", 100, 100);
auto image = img_surf->image();
delete img_surf;
Fl_Surface_Device::pop_current();
return image;
}
Fl_RGB_Image *get_transparent_image(const Fl_RGB_Image *image) {
assert(image);
// make image transparent
auto data = (const unsigned char*)(*image->data());
auto len = image->w() * image->h() * image->d(); // the depth is by default 3
std::vector<unsigned char> temp;
for (size_t i = 0; i < len; i++) {
if (i > 0 && i % 3 == 0) {
// check if the last 3 vals are the rgb values of white, add a 0 alpha
if (data[i] == 255 && data[i - 1] == 255 && data[i - 2] == 255)
temp.push_back(0);
else
// add a 255 alpha, making the black opaque
temp.push_back(255);
temp.push_back(data[i]);
} else {
temp.push_back(data[i]);
}
}
temp.push_back(0);
assert(temp.size() == image->w() * image->h() * 4);
auto new_image_data = new unsigned char[image->w() * image->h() * 4];
memcpy(new_image_data, temp.data(), image->w() * image->h() * 4);
auto new_image = new Fl_RGB_Image(new_image_data, image->w(), image->h(), 4); // account for alpha
return new_image;
}
int main() {
auto win = new Fl_Double_Window(400, 300);
auto box = new Fl_Box(0, 0, 400, 300);
win->end();
win->show();
auto image = get_image(box->w(), box->h());
auto transparent_image = get_transparent_image(image);
delete image;
box->image(transparent_image);
box->redraw();
return Fl::run();
}
这个想法是 Fl_Image_Surface 给出了一个具有 3 个通道(r、g、b)的 Fl_RGB_Image,没有 alpha。我们通过创建一个临时向量来手动添加 alpha,查询数据(如果你知道你正在使用的颜色,可以通过仅检查来优化data[i] == 255
。向量是一个 RAII 类型,其生命在范围结束时结束,所以我们只是mempcy 将向量中的数据存储到一个长寿命的 unsigned char 数组中,我们将其传递给 Fl_RGB_Image,指定深度为 4,考虑 alpha。
另一种选择是使用像 CImg(单头库)这样的外部库将文本绘制到图像缓冲区中,然后将该缓冲区传递给 Fl_RGB_Image。
推荐阅读
- azure - 有没有为 Azure 安装设置路径?
- c++ - 如何从 C++ 文件中读取特定数量的字符?
- sql - 将 SQL 行值转换为列
- nginx - 如何在 nginx.conf 中获取请求 url 的上下文?
- mysql - 似乎无法使用 phpmyadmin 向我的数据库添加多个列
- reactjs - 创建 Google Maps Circle 并在 React 中设置其半径
- angular - 如何使用 login() 通过 nebular auth/login 库导航到主页?
- firebase - Firebase 实时数据库(根据 UID 获取其他用户信息)与 REST
- c++ - 如何从 C++ 调用动态库函数?
- javascript - 如何检查对象数组中的键是否为空?