Я делаю приложение для Linux с GCC, в котором уже некоторое время загружаю свои картинки с диска с помощью PngLIB. Я перепрыгнул со стандартного xlib на расширение Xrender, чтобы использовать свойства сглаживания и альфа-канала, предлагаемые этим расширением.
Однако это расширение предлагает сокращенный набор примитивов. Чтобы, например, отобразить изображение, загруженное с диска, я загружаю его с помощью pnglib, а затем вызываю XRenderFillRectangle с шириной и высотой 1 пиксель и желаемым цветом для этого пикселя. Однако по мере того, как я увеличиваю количество значков и картинок, загружаемых с диска, легко понять, что я легко сталкиваюсь с МИЛЛИОНАМИ обращений к примитиву XRenderFillRectangle. Вывод: приложению сейчас требуется около 20 секунд только для рендеринга всего материала, и это даже не половина того, что я хочу рендерить.
Я почти уверен, что этот подход, который я использую, совершенно неправильный, и должен быть другой путь! И я также почти уверен, что это не так, как Cairo или Java2D делают это для генерации материала.
Итак, мой вопрос: Как я могу подготовить и вставить в изображение Xrender изображения, сгенерированные приложением? Как, например, изображения загружаются с диска?
Можно ли применить стандартную функцию XPutImage к Picture of Xrender? Должен ли я поместить данные в Pixmap перед генерацией изображения? Мои подходы не сработали до сих пор.
PS: Пожалуйста, не рекомендуйте мне использовать Richer Library, такую как Cairo или Qt. Я задаю этот вопрос здесь и сейчас, потому что, к сожалению, каждый раз, когда я нахожу сообщение об этой ситуации, большинство людей ответит: Используйте Каир. Мне действительно нужно оставаться как можно более низким уровнем с этой системой X11. Большое спасибо.
XRenderCreatePicture принимает растровое изображение (или любой нарисованный) в качестве параметра.
Чтобы нарисовать пиксели, используя xrender, вам нужно:
Смотрите документацию libXRender Вот
Пример использования Узел-x11:
var x11 = require('x11');
var Exposure = x11.eventMask.Exposure;
var width = 300;
var height = 300;
var rgb = {
data:new Buffer(width*height*4),
width: width,
height: height
};
var index;
for (var x = 0; x < rgb.width; ++x)
{
for (var y = 0; y < rgb.height; ++y)
{
index = (x + y*rgb.width)*4;
rgb.data[index] = parseInt(Math.sin(13*x/rgb.width)*255);
rgb.data[index+1] = parseInt(Math.cos(15*y/rgb.height)*255);
rgb.data[index+2] = parseInt(Math.cos(16*y/rgb.height)*255);
}
}
x11.createClient(function(err, display)
{
var X = display.client;
X.require('render', function(Render) {
var root = display.screen[0].root;
var win, picWin, pic, gc;
win = X.AllocID();
X.CreateWindow(
win, root,
0, 0, rgb.width, rgb.height,
0, 0, 0, 0,
{ eventMask: Exposure }
);
X.MapWindow(win);
gc = X.AllocID();
X.CreateGC(gc, win);
var rgbPixmap = X.AllocID();
X.CreatePixmap(rgbPixmap, win, 24, rgb.width, rgb.height);
X.PutImage(2, rgbPixmap, gc, rgb.width, rgb.height, 0, 0, 0, 24, rgb.data);
var rgbPicture = X.AllocID();
Render.CreatePicture(rgbPicture, rgbPixmap, Render.rgb24);
var winPicture = X.AllocID();
Render.CreatePicture(winPicture, win, Render.rgb24);
X.on('event', function(ev) {
if (ev.name == 'Expose')
Render.Composite(3, rgbPicture, 0, winPicture, 0, 0, 0, 0, 0, 0, rgb.width, rgb.height);
});
});
});
Других решений пока нет …