如何从 FLTK Fl__Image__Surface 获取透明背景的图像?
How to get image with transparent background from FLTK Fl__Image__Surface?
我想绘制字符串或字符(屏幕外)并将其用作 Fl_Image 或 Fl_RGB_Image。
基于 this link I can do that easily with Fl__Image__Surface. The problem with Fl__Image__Surface is that it does not support transparency when I convert its output to image (Fl_RGB_Image) using image()
method. So is there any way I can achieve this? I can do that on Java Swing with BufferedImage, also in Android with Canvas by creating Bitmap 和 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 给出一个 Fl_RGB_Image 具有 3 个通道(r、g、b),没有 alpha。我们通过创建一个临时向量手动添加 alpha,查询数据(如果您只通过检查 data[i] == 255
就知道您正在使用的颜色,则可以进行优化。该向量是一种 RAII 类型,其生命周期结束时作用域,所以我们只是将向量中的数据存储到 long-lived unsigned char 数组,我们将其传递给 Fl_RGB_Image,指定深度为 4,考虑 alpha。
另一种选择是使用外部库,如 CImg(单个 header 库)将文本绘制到图像缓冲区,然后将该缓冲区传递给 Fl_RGB_Image。
我想绘制字符串或字符(屏幕外)并将其用作 Fl_Image 或 Fl_RGB_Image。
基于 this link I can do that easily with Fl__Image__Surface. The problem with Fl__Image__Surface is that it does not support transparency when I convert its output to image (Fl_RGB_Image) using image()
method. So is there any way I can achieve this? I can do that on Java Swing with BufferedImage, also in Android with Canvas by creating Bitmap 和 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 给出一个 Fl_RGB_Image 具有 3 个通道(r、g、b),没有 alpha。我们通过创建一个临时向量手动添加 alpha,查询数据(如果您只通过检查 data[i] == 255
就知道您正在使用的颜色,则可以进行优化。该向量是一种 RAII 类型,其生命周期结束时作用域,所以我们只是将向量中的数据存储到 long-lived unsigned char 数组,我们将其传递给 Fl_RGB_Image,指定深度为 4,考虑 alpha。
另一种选择是使用外部库,如 CImg(单个 header 库)将文本绘制到图像缓冲区,然后将该缓冲区传递给 Fl_RGB_Image。