2

私はしばらくの間、PngLIB を使用してディスクから写真をロードしてきた GCC を使用して Linux でアプリケーションを作成しています。この拡張機能が提供するアンチエイリアシングとアルファ チャネルのプロパティを利用するために、標準の xlib から Xrender 拡張機能にジャンプしました。

ただし、この拡張機能では、プリミティブのセットが削減されています。たとえば、ディスクから読み込まれた画像を表示するために、pnglib で画像を読み込んでから、XRenderFillRectangle を呼び出して、幅と高さを 1 ピクセルにし、そのピクセルに必要な色を指定しました。ただし、ディスクからロードするアイコンと画像の数を増やすと、プリミティブ XRenderFillRectangle への数百万回の呼び出しに簡単に遭遇することは容易に理解できます。結論: 今のところ、アプリケーションはすべてのものをレンダリングするだけで約 20 秒かかりますが、それは私がレンダリングしたいものの半分にも満たないものです。

私が使用しているこのアプローチは完全に間違っていると確信しており、別の方法があるはずです! そして、カイロやJava2Dがそれを生成する方法ではないことも確信しています。

私の質問は次のとおりです。アプリケーションによって生成された Xrender の画像を準備して、Picture of Xrender に入れるにはどうすればよいですか? たとえば、ディスクからロードされた画像のように?

標準の XPutImage 関数を Xrender の画像に適用できますか? 画像を生成する前に、データを Pixmap に入れますか? 私のアプローチはこれまでうまくいきませんでした。

PS: Cairo や Qt などのよりリッチなライブラリを使用することはお勧めしません。残念ながら、この状況に関する投稿を見つけるたびに、ほとんどの人の答えは「カイロを使用してください」であるため、今ここでこの質問をしています。この X11 システムでは、できる限り低レベルにとどまる必要があります。どうもありがとうございました。

4

1 に答える 1

3

XRenderCreatePicture は、ピックスマップ (または任意のドローアブル) をパラメーターとして受け取ります。xrender を使用してピクセルを描画するには、次のものが必要です。

  • ピックスマップを作成
  • XPutImage を使用して画像データをサーバーに転送する
  • ピックスマップに関連付けられた Picture オブジェクトを作成します
  • ウィンドウに関連付けられた Picture オブジェクトを作成します
  • XRenderComposite を使用してそれらを構成します

ここでlibXRenderのドキュメントを参照してください

node-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);
    });
  });
});
于 2013-04-22T21:48:39.863 に答える