gtk#Mono中的gdk.Pixbuf问题
我正在Mono gtk中创建一个小型绘图程序,并使用Cairo图形库。我正在MacOs X系统上编码和编译。我有一个可绘制的对象,我在某个时间将其放入Pixbuf中,然后将其检索到可绘制的对象中!其想法是在可绘制的图像上拍摄一张“快照”,然后在其上绘制 问题是,当我把Pixbuf放回绘图板时,它看起来模糊不清,全是带条纹的黄色,看起来图像的一部分丢失了 更新:我在我的linux和windows机器上运行了这个程序,在那里它可以完美地工作!所以这个错误只在MacOs X上出现。 代码如下:gtk#Mono中的gdk.Pixbuf问题,mono,gtk#,cairo,gdk,pixbuf,Mono,Gtk#,Cairo,Gdk,Pixbuf,我正在Mono gtk中创建一个小型绘图程序,并使用Cairo图形库。我正在MacOs X系统上编码和编译。我有一个可绘制的对象,我在某个时间将其放入Pixbuf中,然后将其检索到可绘制的对象中!其想法是在可绘制的图像上拍摄一张“快照”,然后在其上绘制 问题是,当我把Pixbuf放回绘图板时,它看起来模糊不清,全是带条纹的黄色,看起来图像的一部分丢失了 更新:我在我的linux和windows机器上运行了这个程序,在那里它可以完美地工作!所以这个错误只在MacOs X上出现。 代码如下: //
// use: gmcs -pkg:gtk-sharp-2.0 -pkg:mono-cairo ttv1.cs
using Gtk;
using Cairo;
using System;
public class Draw : Window
{
DrawingArea canvas;
public Gdk.Pixbuf pixbuf;
public Draw() : base("teikniteink")
{
canvas = new DrawingArea();
canvas.ExposeEvent += canvasExposed;
DeleteEvent += delegate { Application.Quit();};
KeyPressEvent += onKey;
SetDefaultSize(400,400);
SetPosition(WindowPosition.Center);
Add(canvas);
ShowAll();
}
private void onKey(object o, KeyPressEventArgs args)
{
switch (args.Event.Key)
{
case Gdk.Key.w:
Console.WriteLine("Key Pressed {0}", args.Event.Key);
// Send to Pixbuf
pixbuf = Gdk.Pixbuf.FromDrawable(canvas.GdkWindow, Gdk.Colormap.System,0,0,0,0,400,400);
// Save to output.png
pixbuf.Save ("output.png", "png");
break;
case Gdk.Key.e:
Console.WriteLine("Key Pressed {0}", args.Event.Key);
Gdk.GC g = new Gdk.GC(canvas.GdkWindow);
// Retrive from pixbuf
canvas.GdkWindow.DrawPixbuf (g,pixbuf,0,0,0,0,-1,-1,Gdk.RgbDither.Normal,0,0);
break;
}
}
private void canvasExposed(object o, ExposeEventArgs args)
{
using (Cairo.Context ctx = Gdk.CairoHelper.Create(canvas.GdkWindow))
{
PointD start = new PointD(100,100);
PointD end = new PointD(300,300);
double width = Math.Abs(start.X - end.X);
double height = Math.Abs(start.Y - end.Y);
double xcenter = start.X + (end.X - start.X) / 2.0;
double ycenter = start.Y + (end.Y - start.Y) / 2.0;
ctx.Save();
ctx.Translate(xcenter, ycenter);
ctx.Scale(width/2.0, height/2.0);
ctx.Arc(0.0, 0.0, 1.0, 0.0, 2*Math.PI);
ctx.Restore();
ctx.Stroke();
}
}
public static void Main()
{
Application.Init();
new Draw();
Application.Run();
}
}
如果有人知道这里发生了什么,并能为我指出解决问题的正确方向,我们将不胜感激。我以这种方式触发了相同的问题:
gw = gtk_widget_get_window(GTK_WIDGET(GLOBALS->mainwindow));
if(gw)
{
gdk_drawable_get_size(gw, &w, &h);
cm = gdk_drawable_get_colormap(gw);
if(cm)
{
dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, w, h);
if(dest)
{
dest2 = gdk_pixbuf_get_from_drawable(dest, gw, cm, 0, 0, 0, 0, w, h);
if(dest2)
{
succ = gdk_pixbuf_save (dest2, *GLOBALS->fileselbox_text, "png", &err, NULL);
}
}
}
}
当源drawable为Quartz窗口时,gdk_pixbuf_get_from_drawable()函数存在问题,特别是在如何将_gdk_Quartz_image_copy_复制到_image()服务方面。简而言之,转换256位垂直条带,但转换例程假定像素为24位RGB而不是32位RGBA。以下修补程序修复了我的问题:
--- gtk+/gdk/quartz/gdkimage-quartz.c 2011-12-03 14:24:03.000000000 -0600
+++ gtk+664894/gdk/quartz/gdkimage-quartz.c 2013-10-15 18:52:24.000000000 -0500
@@ -150,6 +150,10 @@ _gdk_quartz_image_copy_to_image (GdkDraw
data = [rep bitmapData];
size = [rep size];
+ int bpr = [rep bytesPerRow];
+ int wid = size.width;
+ int bpx = bpr/wid;
+
for (y = 0; y < size.height; y++)
{
guchar *src = data + y * [rep bytesPerRow];
@@ -158,12 +162,15 @@ _gdk_quartz_image_copy_to_image (GdkDraw
{
gint32 pixel;
+ if (bpx == 4) // fix gdk_pixbuf_get_from_drawable "yellow stripes"
+ pixel = src[0] << 16 | src[1] << 8 | src[2];
+ else
if (image->byte_order == GDK_LSB_FIRST)
pixel = src[0] << 8 | src[1] << 16 |src[2] << 24;
else
pixel = src[0] << 16 | src[1] << 8 |src[2];
- src += 3;
+ src += bpx;
gdk_image_put_pixel (image, dest_x + x, dest_y + y, pixel);
}
——gtk+/gdk/quartz/gdkimage quartz.c 2011-12-03 14:24:03.000000000-0600
+++gtk+664894/gdk/quartz/gdkimage quartz.c 2013-10-15 18:52:24.000000000-0500
@@-150,6+150,10@@@u gdk\u石英图像\u复制到图像(GdkDraw
数据=[rep bitmapData];
大小=[代表大小];
+int bpr=[rep bytesPerRow];
+int wid=size.width;
+int bpx=bpr/wid;
+
对于(y=0;y +pixel=src[0]听起来您可能采取了错误的方法,但我不能确定;您试图实现的最终目标是什么?@ptomto目标是制作一个简单的涂鸦程序!用户可以在彼此上方绘制矩形、直线和圆,然后保存图像(并加载图像)。我计划在onMouseRelease事件上设置pixbuf,并在ExposeeEvent上从pixbuf读取可绘制的内容,因此用户当前绘制的内容将显示在图像的顶部。我对gtk和cairo是新手,所以我可能会像你说的那样采取错误的方法!如果你在其他平台上运行它并成功,那么原因是肯定的你应该在bugzilla.gnome.org上提交一个bug,上面说,这里有一个链接指向一个稍微过时的C语言GTK教程,它正是你想要做的:;看起来他们直接在后台存储中绘制,然后将更新排队到可绘制的。谢谢@ptomto,这个教程似乎已经从我的谷歌上滑了下来-寻找手指。