I've been trying to set a background image on a gtk widget without success, even after trying 4 different approaches.
The following program contains 3 approaches (the 4th approach involves no code). I compiled it using MinGW (g++ 4.5.0) and gtkmm 2.4. The APPROACH macro can be set to 1, 2 or 3 in order to choose which approach to compile. I've also added references in the comments, so you can find out where I got the ideas from.
#include <iostream>
#include <gtkmm/main.h>
#include <gtkmm/alignment.h>
#include <gtkmm/box.h>
#include <gtkmm/entry.h>
#include <gtkmm/eventbox.h>
#include <gtkmm/frame.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
#include <gtkmm/table.h>
#include <gtkmm/window.h>
// Set this to 1, 2 or 3 to try different ways of drawing the background
// Set to 0 to load no background at all
#define APPROACH (0)
// Making this alignment global in order to modify it from drawBackground
Gtk::Alignment* alignment;
bool drawBackground(GdkEventExpose* event) {
std::cout << "Draw background" << std::endl;
// Load background image
Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_file("background.jpg");
Glib::RefPtr<Gdk::Pixmap> pixmap;
Glib::RefPtr<Gdk::Bitmap> mask;
pixbuf->render_pixmap_and_mask(pixmap, mask,0);
{
// Test that pixbuf was created correctly
Glib::RefPtr<Gdk::Pixbuf> back_to_pixbuf = Gdk::Pixbuf::create((Glib::RefPtr<Gdk::Drawable>)pixmap, 0, 0, pixbuf->get_width(), pixbuf->get_height());
back_to_pixbuf->save("back_to_pixbuf.png", "png");
}
#if APPROACH == 1
// Approach 1: draw_pixbuf
// Ref: http://islascruz.org/html/index.php/blog/show/Image-as-background-in-a-Gtk-Application..html
Glib::RefPtr<Gtk::Style> style = alignment->get_style();
alignment->get_window()->draw_pixbuf(style->get_bg_gc(Gtk::STATE_NORMAL), pixbuf, 0, 0, 0, 200, pixbuf->get_width(), pixbuf->get_height(), Gdk::RGB_DITHER_NONE, 0, 0);
#endif
#if APPROACH == 2
// Approach 2: set_back_pixmap
// Ref: http://www.gtkforums.com/viewtopic.php?t=446
// http://stackoverflow.com/questions/3150706/gtk-drawing-set-background-image
alignment->get_window()->set_back_pixmap(pixmap);
#endif
}
int main (int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
Gtk::Window w;
Gtk::VBox mainBox;
// Top image
Gtk::Image topImage("header.jpg");
mainBox.pack_start(topImage,false,false,0);
// Middle alignment
alignment = Gtk::manage(new Gtk::Alignment);
mainBox.pack_start(*alignment,true,true,0);
// Create widget
Gtk::Alignment mywidget(0.5, 0.5, 0.1, 0.9);
Gtk::Table table;
Gtk::Label label1("Username"); table.attach(label1,0,1,0,1);
Gtk::Label label2("Password"); table.attach(label2,0,1,1,2);
Gtk::Entry entry1; table.attach(entry1,1,2,0,1);
Gtk::Entry entry2; table.attach(entry2,1,2,1,2);
Gtk::Button button("Login"); table.attach(button,1,2,2,3);
mywidget.add(table);
// Put widget in middle alignment
alignment->add(mywidget);
// Try to change the background
#if APPROACH == 1 || APPROACH == 2
alignment->signal_expose_event().connect(sigc::ptr_fun(&drawBackground), true);
#endif
#if APPROACH == 3
// Approach 3: modify the style using code
// Ref: http://www.gtkforums.com/viewtopic.php?t=446
// Load background image
Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_file("background.jpg");
Glib::RefPtr<Gdk::Pixmap> pixmap;
Glib::RefPtr<Gdk::Bitmap> mask;
pixbuf->render_pixmap_and_mask(pixmap, mask,0);
Glib::RefPtr<Gtk::Style> style = alignment->get_style()->copy();
style->set_bg_pixmap(Gtk::STATE_NORMAL,pixmap);
style->set_bg_pixmap(Gtk::STATE_ACTIVE,pixmap);
style->set_bg_pixmap(Gtk::STATE_PRELIGHT,pixmap);
style->set_bg_pixmap(Gtk::STATE_SELECTED,pixmap);
style->set_bg_pixmap(Gtk::STATE_INSENSITIVE,pixmap);
alignment->set_style(style);
#endif
// Approach 4: modify share\themes\MS-Windows\gtk-2.0
// adding the following line
// bg_pixmap[NORMAL] = "D:\\path\\to\\file\\background.jpg"
// in the style "msw-default" section
// Ref: http://lists.ximian.com/pipermail/gtk-sharp-list/2005-August/006324.html
// Show the window
w.add(mainBox);
w.show_all();
kit.run(w);
return 0;
}
Links to images I used: header.jpg background.jpg
The layout mimics that of my actual program. The main window contains a Gtk::VBox with a header image on top and an Gtk::Alignment at the bottom. The contents of this alignment will change over time but I want it to have a background image always visible.
When loading no background at all, the header image loads correctly and the window looks like this:
Approach 1 is the one that is closer to work, though it hides the labels and the buttons:
Approaches 2 and 3 look the same as loading no background. Besides, approach 2 gives me the following error message:
(test-img-fondo.exe:1752): Gdk-CRITICAL **: gdk_window_set_back_pixmap: assertion `pixmap == NULL || !parent_relative' failed
Finally, in approach 4, I attempt to modify share\themes\MS-Windows\gtk-2.0 by adding the following line
bg_pixmap[NORMAL] = "D:\\path\\to\\file\\background.jpg"
in the style "msw-default" section. It doesn't work either.
So, has anyone succesfully drawn a background image on a Gtk widget? Is this possible at all? Any changes in my code that would make this work? Any workarounds?
All help is greatly appreciated.
I think I've solved it myself. Use approach 1 but change this line
alignment->signal_expose_event().connect(sigc::ptr_fun(&drawBackground), true);
for this:
alignment->signal_expose_event().connect(sigc::ptr_fun(&drawBackground), false);
This way, the call to drawBackground occurs before gtk calls its own handlers.
I should also point out that, in a real program, the images should be loaded once outside of drawBackground.
Related
I'm using Gtk2 to make a small tool, it works like this:
Several Scales and Spinboxes control parameters of an algorithm.
When parameter changes, the algorithm will execute, and the updated result is rendered as a picture, shown in UI.
As the algorithm's workload is heavy, I don't want it run frequently during frequent parameter change. Specifically, during Scales are dragged or Spinbox's arrows buttons are pressed. Instead, I want the algorithm to be run "after" users have determined the parameters.
Currently, I listened the button-release event of the Scales, so the algorithm will run only on Scale dragging is done. However, this not fit for the Spinboxes, as they have separate entry and button sub-area. If I listen to Spinbox's button-release, it would behave weirdly.
So what event (or events) should I listen to obtain the occation that a continuous value update is finished for a Spinbox?
Could I see the code you have? The button-release works great for me. However, depending on your algorithm, you may be getting 'feedback'. Are you sure the rest of the code is not updating your spinbutton in some way?
I'd use a deferred computation, independent from the device you use to modify the data. In this way you can also input the numbers with the keyboard or copy and paste their content and the program will still work as expected.
A way to do this in GTK+ is by leveraging the main loop and using a timeout GSource, e.g.:
#include <gtk/gtk.h>
typedef struct {
guint event;
GSourceFunc callback;
GtkWidget *spin_button;
} Algorithm;
static gboolean your_callback(Algorithm *algorithm)
{
g_print("Your heavy computations go here...\n");
/* ... */
algorithm->event = 0;
return FALSE;
}
static void postpone(Algorithm *algorithm)
{
if (algorithm->event > 0) {
g_source_remove(algorithm->event);
}
/* Default delay is 1 second (1000 milliseconds) */
algorithm->event = g_timeout_add(1000, algorithm->callback, algorithm);
}
int main(int argc, char **argv)
{
GtkWidget *window, *spin_button;
Algorithm algorithm;
gtk_init(&argc, &argv);
spin_button = gtk_spin_button_new_with_range(0, 100, 0.1);
g_signal_connect_swapped(spin_button, "value-changed",
G_CALLBACK(postpone), &algorithm);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), spin_button);
algorithm.event = 0;
algorithm.callback = (GSourceFunc) your_callback;
algorithm.spin_button = spin_button;
gtk_widget_show_all(window);
gtk_main();
return 0;
}
I use a goocanvas and use signals for mouse events connected to some graphical items. If I use a dialog from a signal handler, all signals are broken after closing the dialog. Is this a bug of gtkmm/goocanvas or is this some kind of misuse in my program?
The wrong behavior is:
You can click somewhere in the canvas area, nothing is happen which is correct. If you click on the circle the signal handler starts the dialog which is also expected. After closing the dialog ( OK button ) you can click somewhere on the canvas and the signal handler is called which is wrong.
In my real program the signal handlers are sometimes never called and sometimes called on wrong areas and so on. A bit strange behavior. I hope someone can find the problem.
#include <gtkmm.h>
#include <goocanvasmm.h>
#include <sigc++/sigc++.h>
bool ShowDialog( const Glib::RefPtr<Goocanvas::Item>& item, GdkEventButton* ev)
{
enum { OK };
Gtk::Dialog dialog;
dialog.add_button( Gtk::Stock::OK, OK);
dialog.show_all_children();
dialog.run();
return false;
}
int main(int argc, char* argv[])
{
Gtk::Main app(&argc, &argv);
Goocanvas::init("example", "0.1", argc, argv);
Gtk::Window win;
Goocanvas::Canvas m_canvas;
m_canvas.set_size_request(640, 480);
m_canvas.set_bounds(0, 0, 800, 800);
Glib::RefPtr<Goocanvas::Item> root = m_canvas.get_root_item();
Glib::RefPtr<Goocanvas::Ellipse> outer = Goocanvas::Ellipse::create( 100,100,20,20);
outer->property_line_width() = 5;
outer->property_stroke_color() = "red";
outer->property_fill_color()="blue";
root->add_child( outer );
sigc::connection conn2= outer->signal_button_press_event().connect( sigc::ptr_fun(&ShowDialog));
win.add(m_canvas);
win.show_all_children();
Gtk::Main::run(win);
return 0;
}
I am trying to make Open CV project sample for Template Matching as explained here .
Steps i did so far includes :
Downloaded and imported Open CV framework in my project changed the .m extension files to .mm and in the .pch file i have included the code
#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
I have also downloaded and imported the MatchTemplate_Demo.cpp file from the link.
But here having library linking issue
ld: warning: directory not found for option '-L/Users/G1/Desktop/Xcode'
ld: warning: directory not found for option '-Lprojects/FirstOpenCv/opencv/lib/debug'
ld: library not found for -lopencv_calib3d
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I followed the same step to include the library as given here.
2) Add $(SRCROOT)/opencv to header search path and $(SRCROOT)/opencv/lib/debug for library search path for debug configuration and $(SRCROOT)/opencv/lib/release for release build.
3) Add OpenCV libs to linker input by modifying "Other Linker Flags" option with "-lopencv_calib3d -lzlib -lopencv_contrib -lopencv_legacy -lopencv_features2d -lopencv_imgproc -lopencv_video -lopencv_core".
Now can please any one tell me how should i make the project run.
I have taken the source and template image and imported in the project.
I have basically ViewController.h and ViewController.mm file now i don't know what should i code in these files to see the result.
Also Step 2 :
I need to scan the image in real time using camera view (so that when i place my camera over the source image it should scan and find the template).
On following this link i got Linker error while importing the .cpp file :
ld: 1 duplicate symbol for architecture i386 clang:
error: linker command failed with exit code 1 (use -v to see invocation)
Please can any one suggest me how should i implement it.
You have three interrelated questions here:
1/ how to get openCV framework to run in an iOS project
2/ how to get the Template Matching c++ sample code to run in an iOS project
3/ how to do live template matching with the camera view
1/ how to get openCV framework to run in an iOS project
Download and import the openCV framework as you describe
Change the .pch file as you describe
check that c++ standard library is set to libc++ in your target build settings (this is the default for new projects)
Don't just import demo.cpp without making changes as described below (it is a 'raw' c++ progam with it's own main function, and needs alterations to work as part of an iOS/Cocoa project).
Don't mess with header search paths, other linker flags etc, this isn't necessary if you have imported the prebuilt framework from openCV.org.
Don't change your .m files to .mm unless you know that you need to. My advice is to keep your c++ code separate from your objective-C code as far as practicable, so most of you files should be .m files (objective-C) or .cpp files (c++). You only need .mm prefixes for "objective-C++" where you intend to mix objective-C and c++ in the same file.
2/ how to get the Template Matching c++ sample code to run in an iOS project
We are going to set this up so that your iOS viewController - and the bulk of your iOS code - does not need to know that the image is processed using openCV/C++, and likewise the C++ code doesn't need to know where it's input or output image data is being routed to. We do this by making a small wrapper class between the two that translates objective-C method calls to c++ class member functions and back. We will also set up a category on UIImage to translate image formats from iOS-friendly UIImage to openCV-native cv::Mat.
UIImage+OpenCV Category
You need some utility methods to convert from UIImage to cv::Mat and back. A good place to put these is in a UIImage category. In XCode: File>New FIle>Cocoa Touch>Objective-C category will set you up. Call the category OpenCV and make it a category on UIImage. This .m file you will want to change to .mm as it will need to understand c++ types from the openCV framework.
The header should look something like this:
#import <UIKit/UIKit.h>
#interface UIImage (OpenCV)
//cv::Mat to UIImage
+ (UIImage *)imageWithCVMat:(const cv::Mat&)cvMat;
//UIImage to cv::Mat
- (cv::Mat)cvMat;
#end
The .mm file should implement these methods by closely following this openCV.org code sample adapted to work as category methods (eg you don't pass a UIImage into the instance method, but refer to it using self).
You can use the category methods as if they are UIImage class and instance methods like this:
UIImage* image = [UIImage imageWithCVMat:matImage]; //class method
cv::Mat matImage = [image cvMat]; //instance method
openCV wrapper class
Make a wrapper class to convert your objective-C method (called from a viewController) to a c++ function
header something like this
// CVWrapper.h
#import <Foundation/Foundation.h>
#interface CVWrapper : NSObject
+ (NSImage*) templateMatchImage:(UIImage*)image
patch:(UIImage*)patch
method:(int)method;
#end
We send in the template image, patch image and template matching method, and get back an image showing the match
implementation (.mm file)
// CVWrapper.mm
#import "CVWrapper.h"
#import "CVTemplateMatch.h"
#import "UIImage+OpenCV.h"
#implementation CVWrapper
+ (UIImage*) templateMatchImage:(UIImage *)image
patch:(UIImage *)patch
method:(int)method
{
cv::Mat imageMat = [image cvMat];
cv::Mat patchMat = [patch cvMat];
cv::Mat matchImage =
CVTemplateMatch::matchImage(imageMat,
patchMat,
method);
UIImage* result = [UIImage imageWithCVMat:matchImage];
return result;
}
We are effectively taking a standard objective-C method and UIImage types and translating them into a call to a C++ member function with c++(openCV framework) types, and translating the result back to a UIImage.
C++ TemplateMatch class
Header:
// TemplateMatch.h
#ifndef __CVOpenTemplate__CVTemplateMatch__
#define __CVOpenTemplate__CVTemplateMatch__
class CVTemplateMatch
{
public:
static cv::Mat matchImage (cv::Mat imageMat,
cv::Mat patchMat,
int method);
};
#endif /* defined(__CVOpenTemplate__CVTemplateMatch__) */
#end
Implementation:
This is the Template Match openCV example code, reworked as a class implementation:
// TemplateMatch.cpp
/*
Alterations for use in iOS project
[1] remove GUI code (iOS supplies the GUI)
[2] change main{} to static member function
with appropriate inputs and return value
[3] change MatchingMethod{} signature
to return Mat value
*/
#include "CVTemplateMatch.h"
//[1] #include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
/// Global Variables
Mat img; Mat templ; Mat result;
//[1] char* image_window = "Source Image";
//[1] char* result_window = "Result window";
int match_method;
//[1] int max_Trackbar = 5;
/// Function Headers
Mat MatchingMethod( int, void* ); //[3] (added return value to function)
// [2] /** #function main */
// [2] int main( int argc, char** argv )
Mat CVTemplateMatch::matchImage (Mat image,Mat patch, int method)
// [2]
{
/// Load image and template
//[2] img = imread( argv[1], 1 );
//[2] templ = imread( argv[2], 1 );
img = image; //[2]
templ = patch; //[2]
match_method = method; //[2]
/// Create windows
//[1] namedWindow( image_window, CV_WINDOW_AUTOSIZE );
//[1] namedWindow( result_window, CV_WINDOW_AUTOSIZE );
/// Create Trackbar
//[1] char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
//[1] createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );
Mat result = MatchingMethod( 0, 0 );
//[1] waitKey(0);
//[2] return 0;
return result; //[2]
}
//[3] void MatchingMethod( int, void* )
Mat MatchingMethod( int, void* )
{
/// Source image to display
Mat img_display;
img.copyTo( img_display );
/// Create the result matrix
int result_cols = img.cols - templ.cols + 1;
int result_rows = img.rows - templ.rows + 1;
result.create( result_cols, result_rows, CV_32FC1 );
/// Do the Matching and Normalize
matchTemplate( img, templ, result, match_method );
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
/// Localizing the best match with minMaxLoc
double minVal; double maxVal; Point minLoc; Point maxLoc;
Point matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
{ matchLoc = minLoc; }
else
{ matchLoc = maxLoc; }
/// Show me what you got
rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
//[1] imshow( image_window, img_display );
//[1] imshow( result_window, result );
return img_display; //[3] add return value
}
Now in your viewController you just need to call this method:
UIImage* matchedImage =
[CVWrapper templateMatchImage:self.imageView.image
patch:self.patchView.image
method:0];
with no c++ in sight.
3/ Template Matching with live camera view
The short answer: matchTemplate is not going to work too well in a live camera context. The algorithm is looking for a match in the image with the same scale and orientation as the patch: it slides the patch tile across the image at it's original orientation and size comparing for best match. This is not going to yield great results if the image is perspective-skewed, a different size or rotated to a different orientation.
You could look instead at OpenCV's Feature Detection algorithms, some of which have been moved to non-free. Here is a nice description of SIFT to give you the idea. For video capture you might also want to look at cap_ios.h in opencv2/highgui: here is a tutorial.
Actually you have downloaded already compiled library so no need to follow the steps that you have mentioned in your question and this the issues(i.e. you have followed incorrect steps) because that steps are to compile the source code into static library.
Follow the below steps and it will be done
Unzip the downloaded framework. You can see folder with name "opencv2.framework"
Drag that folder directly into project(Note. When you drag that folder into xcode, xcode will prompt you dialog there will be a tick mark to actually copy this into folder. please tick that check box)
In you .pch file import openCV like you have mentioned in your question is correct way
Now compile. One thing more wherever you want to use function of openCV that file should have .mm extension(i.e. Objective C++ source) It will run perfectly.
Help link:
I'd like to write my own stereo image viewer, because there are certain features I need which are missing from the one bundled with my NVidia/EVGA GTX 580.
I can't figure out how to program the card to enter "shutterglass" mode where every other frame (at 120 HZ) alternates left and right.
I've looked at the OpenGL, Direct3D, and XNA APIs, as well as information from NVIDIA, and can't figure out how to get started. How do I set separate left and right images, how do I tell the screen to display it, and how to I tell the driver to activate the shutterglass transmitter?
(Another disconcerting thing is that whenever I use the bundled software to view stereo images and video in shutterglass mode, it's in fullscreen, and the screen blinks when entering that mode--even though I run the screen at 120Hz in 2D. Is there a way to have a 3D surface in a window without upsetting the rest of the screen on the NVidia "gamer" cards that are 3D capable (570, 580)?
I'm a bit late to this, but I just got the stereoscopic 3D to work using nothing but a GTX 580 and OpenGL. No need for a quadro card or DirectX.
I have the nVidia 3D Vision driver and IR emitter and simply set the emitter to "Always on" in the nVidia control panel.
In my game engine, I switched to a full screen mode with 120Hz and render the scene twice with a slight frustum offset (as per nVidia's own documentation PDF on the manual implementation "2010_GTC2010.pdf").
No quad buffers or any other tricks needed, it works great. Plus, I am in control of all the settings, like convergence etc.
For the NVidia 3Dvision with the GEForce range you need to write a full screen directX surface twice the width of the display with the left image on the left,right on the right (duh).
Then you need to write a magic value into the bottom left of the image which the NVision driver picks up and turns on the glasses, you don't need the nvapi.dll
With the Nvidia pro glasses and a Quadra card you can use the regular OpenGL stereo API.
ps.I did find some sample code that manages to do this with a normal window.
Edit - it was a low level USB code talking to the xmitter that I could never get to build, I think it eventually became this http://sourceforge.net/projects/libnvstusb/
Here is some sample code for full screen with the NVision glasses.
I'm not a DirectX expert so some of this might be less than optimal.
My app is also based on Qt, there might be some Qt bits left in the code
-----------------------------------------------------------------
// header
void create3D();
void set3D();
IDirect3D9 *_d3d;
IDirect3DDevice9 *_d3ddev;
QSize _size; // full screen size
IDirect3DSurface9 *_imageBuf; //Source stereo image
IDirect3DSurface9 *_backBuf;
--------------------------------------------------------
// the code
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <strsafe.h>
#pragma comment (lib, "d3d9.lib")
#define NVSTEREO_IMAGE_SIGNATURE 0x4433564e //NV3D
typedef struct _Nv_Stereo_Image_Header
{
unsigned int dwSignature;
unsigned int dwWidth;
unsigned int dwHeight;
unsigned int dwBPP;
unsigned int dwFlags;
} NVSTEREOIMAGEHEADER, *LPNVSTEREOIMAGEHEADER;
// ORedflags in the dwFlagsfielsof the _Nv_Stereo_Image_Headerstructure above
#define SIH_SWAP_EYES 0x00000001
#define SIH_SCALE_TO_FIT 0x00000002
// call at start to set things up
void DisplayWidget::create3D()
{
_size = QSize(1680,1050); //resolution of my Samsung 2233z
_d3d = Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface
D3DPRESENT_PARAMETERS d3dpp; // create a struct to hold various device information
ZeroMemory(&d3dpp, sizeof(d3dpp)); // clear out the struct for use
d3dpp.Windowed = FALSE; // program fullscreen
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // discard old frames
d3dpp.hDeviceWindow = winId(); // set the window to be used by Direct3D
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; // set the back buffer format to 32 bit // or D3DFMT_R8G8B8
d3dpp.BackBufferWidth = _size.width();
d3dpp.BackBufferHeight = _size.height();
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
d3dpp.BackBufferCount = 1;
// create a device class using this information and information from the d3dpp stuct
_d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
winId(),
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&_d3ddev);
//3D VISION uses a single surface 2x images wide and image high
// create the surface
_d3ddev->CreateOffscreenPlainSurface(_size.width()*2, _size.height(), D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &_imageBuf, NULL);
set3D();
}
// call to put 3d signature in image
void DisplayWidget::set3D()
{
// Lock the stereo image
D3DLOCKED_RECT lock;
_imageBuf->LockRect(&lock,NULL,0);
// write stereo signature in the last raw of the stereo image
LPNVSTEREOIMAGEHEADER pSIH = (LPNVSTEREOIMAGEHEADER)(((unsigned char *) lock.pBits) + (lock.Pitch * (_size.height()-1)));
// Update the signature header values
pSIH->dwSignature = NVSTEREO_IMAGE_SIGNATURE;
pSIH->dwBPP = 32;
//pSIH->dwFlags = SIH_SWAP_EYES; // Src image has left on left and right on right, thats why this flag is not needed.
pSIH->dwFlags = SIH_SCALE_TO_FIT;
pSIH->dwWidth = _size.width() *2;
pSIH->dwHeight = _size.height();
// Unlock surface
_imageBuf->UnlockRect();
}
// call in display loop
void DisplayWidget::paintEvent()
{
// clear the window to a deep blue
//_d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
_d3ddev->BeginScene(); // begins the 3D scene
// do 3D rendering on the back buffer here
RECT destRect;
destRect.left = 0;
destRect.top = 0;
destRect.bottom = _size.height();
destRect.right = _size.width();
// Get the Backbuffer then Stretch the Surface on it.
_d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &_backBuf);
_d3ddev->StretchRect(_imageBuf, NULL, _backBuf, &destRect, D3DTEXF_NONE);
_backBuf->Release();
_d3ddev->EndScene(); // ends the 3D scene
_d3ddev->Present(NULL, NULL, NULL, NULL); // displays the created frame
}
// my images come from a camera
// _left and _right are QImages but it should be obvious what the functions do
void DisplayWidget::getImages()
{
RECT srcRect;
srcRect.left = 0;
srcRect.top = 0;
srcRect.bottom = _size.height();
srcRect.right = _size.width();
RECT destRect;
destRect.top = 0;
destRect.bottom = _size.height();
if ( isOdd() ) {
destRect.left = _size.width();
destRect.right = _size.width()*2;
// get camera data for _left here, code not shown
D3DXLoadSurfaceFromMemory(_imageBuf, NULL, &destRect,_right.bits(),D3DFMT_A8R8G8B8,_right.bytesPerLine(),NULL,&srcRect,D3DX_DEFAULT,0);
} else {
destRect.left = 0;
destRect.right = _size.width();
// get camera data for _right here, code not shown
D3DXLoadSurfaceFromMemory(_imageBuf, NULL, &destRect,_left.bits(),D3DFMT_A8R8G8B8,_left.bytesPerLine(),NULL,&srcRect,D3DX_DEFAULT,0);
}
set3D(); // add NVidia signature
}
DisplayWidget::~DisplayWidget()
{
_d3ddev->Release(); // close and release the 3D device
_d3d->Release(); // close and release Direct3D
}
I am in the process of adding drag and drop support to an existing Mono/C#/GTK# application. I was wondering whether it was possible to use RGBA transparency on the icons that appear under the mouse pointer when I start dragging an object.
So far, I realized the following:
I can set the bitmap in question by calling the Gtk.Drag.SourceSetIconPixbuf() method. However, no luck with alpha transparency: pixels that are not fully opaque would get 100% transparent this way.
I also tried calling RenderPixmapAndMask() on the GdkPixbuf so that I could use Gtk.Drag.SourceSetIcon() with an RGBA colormap of my Screen. It didn't work either: whenever I started dragging, I got the following error:
[Gdk] IA__gdk_window_set_back_pixmap: assertion 'pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap)' failed.
This way, the pixmap doesn't even get copied, only a white shape (presumably set by the mask argument of SetSourceIcon()) shows up on dragging.
I'd like to ask if there's a way to make these icons have alpha transparency, despite the fact that I failed to do so. In case it's impossible, answers discussing the reasons of the lack of this feature would also be helpful. Thank you.
(Compositing is - of course - enabled on my desktop (Ubuntu/10.10, Compiz/0.8.6-0ubuntu9).)
Ok, finally I solved it. You should create a new Gtk.Window of POPUP type, set its Colormap to your screen's RGBA colormap, have the background erased by Cairo to a transparent color, draw whatever you'd like on it and finally pass it on to Gtk.Drag.SetIconWidget().
Sample code (presumably you'll want to use this inside OnDragBegin, or at a point where you have a valid drag context to be passed to SetIconWidget()):
Gtk.Window window = new Gtk.Window (Gtk.WindowType.Popup);
window.Colormap = window.Screen.RgbaColormap;
window.AppPaintable = true;
window.Decorated = false;
window.Resize (/* specify width, height */);
/* The cairo context can only be created when the window is being drawn by the
* window manager, so wrap drawing code into an ExposeEvent delegate. */
window.ExposeEvent += delegate {
Context ctx = Gdk.CairoHelper.Create (window.GdkWindow);
/* Erase the background */
ctx.SetSourceRGBA (0, 0, 0, 0);
ctx.Operator = Operator.Source;
ctx.Paint ();
/* Draw whatever you'd like to here, and then clean up by calling
Dispose() on the context's target. */
(ctx.Target as IDisposable).Dispose ();
};
Gtk.Drag.SetIconWidget(drag_context, window, 10, 10);