How to display an image into an XCB window? - c++

I'm having trouble displaying an image (PNG extracted with libpng) into an XCB window, it is always entirely empty/white. I'm pretty sure the PNG extraction is correct since I can perfectly re-write it into another file.
I've tried everything I found (explanations, guides, documentation) and I'm running out of ideas:
Creating an xcb_pixmap_t calling xcb_create_pixmap_from_bitmap_data() with the data taken from the PNG, then calling xcb_copy_area() into the EXPOSE part of the event loop.
Creating an xcb_image_t* calling xcb_image_create_from_bitmap_data() then trying to map it to the window with xcb_image_put(). I've even tried to display each pixel with xcb_image_put_pixel(), but without success.
Code sample:
xcb_pixmap_t pixmap = xcb_create_pixmap_from_bitmap_data(
connection, // xcb_connect(0, 0) (type: xcb_connection_t*)
window, // xcb_generate_id(connection) (type: xcb_window_t)
img.getData(), // uint8_t*
img.getWidth(), // 128
img.getHeight(), // 128
img.getBitDepth(), // 8
screen->black_pixel, // screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data (type: xcb_screen_t*)
screen->white_pixel,
nullptr);
// "img" is an instance of my own custom class, result of PNG reading
xcb_image_t* image = xcb_image_create_from_bitmap_data(
img.getData(),
img.getWidth(),
img.getHeight()); // image->data seems fine
xcb_image_put(connection,
window,
graphicsContext,
image, 0, 0, 0); // This does nothing
for (unsigned int i = 0; i < screen->height_in_pixels; ++i)
for (unsigned int j = 0; j < screen->width_in_pixels; ++j)
xcb_image_put_pixel(image, j, i, 0); // Displays nothing
[...]
// Into event loop
case XCB_EXPOSE: {
xcb_expose_event_t* exposeEvent = reinterpret_cast<xcb_expose_event_t*>(event);
xcb_copy_area(connection,
pixmap,
window,
graphicsContext,
exposeEvent->x, exposeEvent->y, // Top left x & y coordinates of the source's region to copy
exposeEvent->x, exposeEvent->y, // Top left x & y coordinates of the destination's region to copy to
exposeEvent->width,
exposeEvent->height);
xcb_flush(connection);
break;
}
From the examples I found I saw that it didn't need a colormap, but could that be the case? Could anyone tell me where I've gone wrong?

I threw together a simple xcb image viewer about 4 years ago, but just noticed this question, so apologies for the necromancy.
It uses xcb_image, stb_image and nanosvg, but compiles to a relatively small static binary (with a musl or uclibc toolchain)
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
#define STBI_NO_HDR
#define STBI_NO_LINEAR
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define NANOSVG_IMPLEMENTATION
#include "nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"
int main(int argc, char **argv){
xcb_connection_t *c = xcb_connect(0, 0);
xcb_screen_t *s = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
int w, h, n,
depth = s->root_depth,
win_class = XCB_WINDOW_CLASS_INPUT_OUTPUT,
format = XCB_IMAGE_FORMAT_Z_PIXMAP;
xcb_colormap_t colormap = s->default_colormap;
xcb_drawable_t win = xcb_generate_id(c);
xcb_gcontext_t gc = xcb_generate_id(c);
xcb_pixmap_t pixmap = xcb_generate_id(c);
xcb_generic_event_t *ev;
xcb_image_t *image;
NSVGimage *shapes = NULL;
NSVGrasterizer *rast = NULL;
char *data = NULL;
unsigned *dp;
size_t i, len;
uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
value_mask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS,
values[] = { s->black_pixel, value_mask };
if (argc<2) return -1;
if ((data = stbi_load(argv[1], &w, &h, &n, 4)))
;
else if ((shapes = nsvgParseFromFile(argv[1], "px", 96.0f))) {
w = (int)shapes->width;
h = (int)shapes->height;
rast = nsvgCreateRasterizer();
data = malloc(w*h*4);
nsvgRasterize(rast, shapes, 0,0,1, data, w, h, w*4);
}else return -1;
for(i=0,len=w*h,dp=(unsigned *)data;i<len;i++) //rgba to bgra
dp[i]=dp[i]&0xff00ff00|((dp[i]>>16)&0xFF)|((dp[i]<<16)&0xFF0000);
xcb_create_window(c,depth,win,s->root,0,0,w,h,1,win_class,s->root_visual,mask,values);
xcb_create_pixmap(c,depth,pixmap,win,w,h);
xcb_create_gc(c,gc,pixmap,0,NULL);
image = xcb_image_create_native(c,w,h,format,depth,data,w*h*4,data);
xcb_image_put(c, pixmap, gc, image, 0, 0, 0);
xcb_image_destroy(image);
xcb_map_window(c, win);
xcb_flush(c);
while ((ev = xcb_wait_for_event(c))) {
switch (ev->response_type & ~0x80){
case XCB_EXPOSE: {
xcb_expose_event_t *x = (xcb_expose_event_t *)ev;
xcb_copy_area(c,pixmap,win,gc,x->x,x->y,x->x,x->y,x->width,x->height);
xcb_flush(c);
}break;
case XCB_BUTTON_PRESS: goto end;
default: break;
}
}
end:
xcb_free_pixmap(c, pixmap);
xcb_disconnect(c);
return 0;
}

Related

Changing the color of pixels using (MFC's) CImage::SetPixel()

I have a 32-bit png file with an alpha (transparent) layer. I want to change the color of some pixels on a per-pixel basis using MFC. Performance isn't an issue (although faster is better).
I wrote code to call CImage::GetPixel() tweak the returned COLORREF, and SetPixel() the new color, but the entire image was transparent. So I wrote the following block which simply gets and sets the original color. The resulting image is entirely transparent. I also tried simply using SetPixel(x, y, RGB(255, 0, 0)) to set all pixels to red. Any advice to resolve this?
CImage image;
if(image.Load(sFilename) == S_OK)
{
TRACE(L"IsTransparencySupported %d", image.IsTransparencySupported()); // Returns 1.
TRACE(L"IsDIBSection %d", image.IsDIBSection()); // Returns 1.
TRACE(L"Size %dx%d", image.GetWidth(), image.GetHeight()); // Displays 141x165.
TRACE(L"BPP %d", image.GetBPP()); // Returns 32.
TRACE(L"Pitch %d", image.GetPitch()); // Returns -564.
COLORREF color;
for(int x = 0; x < image.GetWidth(); x++)
{
for(int y = 0; y < image.GetHeight(); y++)
{
color = image.GetPixel(x, y);
image.SetPixel(x, y, color);
}
}
if(image.Save(sFilenameNew, Gdiplus::ImageFormatPNG) != S_OK)
TRACE(L"Error saving %s.", sFilenameNew);
}
else
TRACE(L"Error loading png %s.", sFilename);
Thanks!
CImage image;
for (int i=0;i<image.ImgHeight;i++)
{
for (int j=0;j<image.ImgWidth;j++)
{
int index = i*image.ImgWidth+j;
unsigned char* pucColor = reinterpret_cast<unsigned char *> (image.GetPixelAddress(j , i));
pucColor[0] = bValues[index];
pucColor[1] = gValues[index];
pucColor[2] = rValues[index];
}
}

Gtkmm - always same image when taking screenshot

I have a small c++ (c++11) program that screenshots the whole screen and save it in a file when a button is clicked
Here is my code:
#include <iostream>
#include <gtkmm.h>
using namespace Gtk;
class MainWindow : public Window
{
public:
MainWindow(): m_button("Take Screen Shot")
{
add(m_button);
m_button.signal_clicked().connect(std::bind(&MainWindow::on_mouse_clicked, this));
m_button.show();
}
virtual ~MainWindow() {};
protected:
void on_mouse_clicked()
{
auto root = Gdk::Window::get_default_root_window();
int height = root->get_height();
int width = root->get_width();
auto pixels = Gdk::Pixbuf::create(root, 0, 0, width, height);
pixels->save("s.png", "png");
}
Button m_button;
};
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv);
MainWindow mainapp;
return app->run(mainapp);
}
The problem is: i get always the same image! the state of the screen when the app is launched. I want to get always the current state of the screen
Got the same issue, but on few computers only. Don't know, why this happened, but seems to be gtk and/or display driver error (I've got this bug with Intel display driver).
Anywhere, the followin solution works to me, but only with native x11:
Display *dpy = XOpenDisplay(NULL);
Window rootWnd = DefaultRootWindow(dpy);
XWindowAttributes wa;
XGetWindowAttributes(dpy, rootWnd, &wa);
XImage *rootImg = XGetImage(dpy, rootWnd, 0, 0, wa.width, wa.height, AllPlanes, ZPixmap);
const unsigned long mRed = rootImg->red_mask,
mBlue = rootImg->blue_mask,
mGreen = rootImg->green_mask
;
for(int y = 0; y < wa.height; y++)
{
for(int x = 0; x < wa.width; x++)
{
const unsigned long bgrPixel = XGetPixel(rootImg, x, y);
const unsigned char blue = bgrPixel & mBlue,
green = (bgrPixel & mGreen) >> 8,
red = (bgrPixel & mRed) >> 16,
alpha = bgrPixel >> 24
;
const unsigned long rgbPixel = red | (green << 8) | (blue << 16) | (alpha << 24);
XPutPixel(rootImg, x, y, rgbPixel);
}
}
Glib::RefPtr<Gdk::Pixbuf> img = Gdk::Pixbuf::create_from_data(
(guint8 *)rootImg->data,
Gdk::Colorspace::COLORSPACE_RGB,
rootImg->bits_per_pixel == 32,
8,
rootImg->width,
rootImg->height,
rootImg->bytes_per_line
);
img->save("s.png", "png");
XDestroyImage(rootImg);
XCloseDisplay(dpy);
P.S.: Please, do not forget that Xlib works with BGR, but Gdk::Pixbuf with RGB pattern.

C++ SDL2, How to regularly update a renderered text? (ttf)

So I've been practicing/making a quick game for the past 6 hours, then something stumped me.
The game had an integer, Score, which would be added up with one every time an ammo hits an alien.
int Score;
stringstream sstr;
sstr << Score;
string str1 = sstr.str();
TTF_Font* Sans = NULL;
Sans = TTF_OpenFont("Sans.ttf", 24);
SDL_Color White = {255, 255, 255};
SDL_Surface* surfaceMessage = NULL;
surfaceMessage = TTF_RenderText_Solid(Sans, str1.c_str(), White);
SDL_Texture* Message = NULL;
Message = SDL_CreateTextureFromSurface(renderer, surfaceMessage);
SDL_Rect Message_rect;
Message_rect.x = 0;
Message_rect.y = 0;
Message_rect.w = 100;
Message_rect.h = 100;
//UPDATE/GAMELOOP AREA, I DIDN'T REALLY PASTE THE WHOLE PART
SDL_RenderCopy(renderer, Message, NULL, &Message_rect);
Now I've been trying different roundabouts as to how to update the texture, Message.
I made a cout check to check if I did hit an alien and what my current score is, it appears perfectly fine, but the rendered texture, Message won't move from 0.
I created a texture from the surface (the message) because I mostly prefer textures and I don't have any surface since in my current knowledge, you'd at least need a filled surface where you could blitz this
And another question, I'm planning to make a dialogue heavy game, is there another way of doing the texts? I've got a strong feeling that I'm doing it wrong.
Minimal runnable example
The counter gets updated every second.
Ubuntu 16.10, SDL 2.0.4:
sudo apt-get install libsdl2-dev libsdl2-ttf-dev
./main /path/to/my.ttf
This method is easy to integrate, but not very efficient as it re-rasters and re-creates textures all the time. If you also want efficiency, see: Rendering fonts and text with SDL2 efficiently I get 4k FPS, so it might be fine for simple applications.
GitHub upstream with a ttf file to test with: https://github.com/cirosantilli/cpp-cheat/blob/d36527fe4977bb9ef4b885b1ec92bd0cd3444a98/sdl/ttf.c:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
#define COMMON_COLOR_MAX 255
#define COMMON_WINDOW_WIDTH 500
#define COMMON_WINDOW_HEIGHT (COMMON_WINDOW_WIDTH)
double common_get_secs(void) {
struct timespec ts;
timespec_get(&ts, TIME_UTC);
return ts.tv_sec + (1e-9 * ts.tv_nsec);
}
const double COMMON_FPS_GRANULARITY_S = 0.5;
double common_fps_last_time_s;
unsigned int common_fps_nframes;
void common_fps_init() {
common_fps_nframes = 0;
common_fps_last_time_s = common_get_secs();
}
void common_fps_update_and_print() {
double dt, current_time_s;
current_time_s = common_get_secs();
common_fps_nframes++;
dt = current_time_s - common_fps_last_time_s;
if (dt > COMMON_FPS_GRANULARITY_S) {
printf("FPS = %f\n", common_fps_nframes / dt);
common_fps_last_time_s = current_time_s;
common_fps_nframes = 0;
}
}
#define MAX_STRING_LEN 4
/*
- x, y: upper left corner of string
- rect output Width and height contain rendered dimensions.
*/
void render_text(
SDL_Renderer *renderer,
int x,
int y,
const char *text,
TTF_Font *font,
SDL_Rect *rect,
SDL_Color *color
) {
SDL_Surface *surface;
SDL_Texture *texture;
surface = TTF_RenderText_Solid(font, text, *color);
texture = SDL_CreateTextureFromSurface(renderer, surface);
rect->x = x;
rect->y = y;
rect->w = surface->w;
rect->h = surface->h;
/* This is wasteful for textures that stay the same.
* But makes things less stateful and easier to use.
* Not going to code an atlas solution here... are we? */
SDL_FreeSurface(surface);
SDL_RenderCopy(renderer, texture, NULL, rect);
SDL_DestroyTexture(texture);
}
int main(int argc, char **argv) {
SDL_Color color;
SDL_Event event;
SDL_Rect rect;
SDL_Renderer *renderer;
SDL_Window *window;
char *font_path, text[MAX_STRING_LEN];
/* CLI arguments. */
if (argc == 1) {
font_path = "FreeSans.ttf";
} else if (argc == 2) {
font_path = argv[1];
} else {
fprintf(stderr, "error: too many arguments\n");
exit(EXIT_FAILURE);
}
/* initialize variables. */
color.r = COMMON_COLOR_MAX;
color.g = COMMON_COLOR_MAX;
color.b = COMMON_COLOR_MAX;
color.a = COMMON_COLOR_MAX;
/* Init window. */
SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(
COMMON_WINDOW_WIDTH,
COMMON_WINDOW_WIDTH,
0,
&window,
&renderer
);
/* Init TTF. */
TTF_Init();
TTF_Font *font = TTF_OpenFont(font_path, 24);
if (font == NULL) {
fprintf(stderr, "error: font not found\n");
exit(EXIT_FAILURE);
}
/* Main loop. */
common_fps_init();
while (1) {
if (SDL_PollEvent(&event) && event.type == SDL_QUIT) {
break;
}
/* Use TTF. */
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
render_text(renderer, 0, 0, "hello", font, &rect, &color);
render_text(renderer, 0, rect.y + rect.h, "world", font, &rect, &color);
snprintf(text, MAX_STRING_LEN, "%u", (unsigned int)(time(NULL) % 1000));
render_text(renderer, 0, rect.y + rect.h, text, font, &rect, &color);
SDL_RenderPresent(renderer);
common_fps_update_and_print();
}
/* Cleanup. */
TTF_Quit();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
Well, obviously you need to recreate texture from surface with new text each time your score changes. That is not very efficient for texts that change frequently (since you create/destroy a lot of surfaces/textures), but can be fine for small games (since modern computers are very powerful).
But generally, as mentioned in comments, for this case font atlases are used with combination of custom text renderers. The trick is to store all characters in one texture and render its regions multiple times to produce necessary text. The AngelCode BMFont is popuar tool for creating font atlases.
For maximum performance both approaches are used in combination: precreated textures for static text, and font atlases for dynamic text.

When i compile acode i have this error cannot open file X11/Xlib.h in c++

/* Sequential Mandelbrot program mandelbrot.c */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define X_RESN 800 /* x resolution */
#define Y_RESN 800 /* y resolution */
typedef struct complextype
{ float real, imag;
} Compl;
int main (int argc, char *argv[])
{ Window win; /* window initialization */
unsigned
int width, height, /* window size */
x, y, /* window position */
border_width, /* border width in pixels */
display_width,
display_height, /* size of screen */
screen; /* which screen */
char *window_name = "Mandelbrot Set", *display_name = NULL;
GC gc;
unsigned long valuemask = 0;
XGCValues values;
Display *display;
XSizeHints size_hints;
Pixmap bitmap;
XPoint points[800];
FILE *fp, *fopen ();
char str[100];
XSetWindowAttributes attr[1];
/* Mandlebrot variables */
int i, j, k;
Compl z, c;
float lengthsq, temp;
/* connect to Xserver */
if ( (display = XOpenDisplay (display_name)) == NULL )
{ fprintf (stderr, "drawon: cannot connect to X server %s\n",
XDisplayName (display_name) );
exit (-1);
}
/* get screen size */
screen = DefaultScreen (display);
display_width = DisplayWidth (display, screen);
display_height = DisplayHeight (display, screen);
/* set window size */
width = X_RESN;
height = Y_RESN;
/* set window position */
x = 0;
y = 0;
/* create opaque window */
border_width = 4;
win = XCreateSimpleWindow(display, RootWindow (display, screen),
x, y, width, height, border_width,
BlackPixel (display, screen), WhitePixel (display, screen));
size_hints.flags = USPosition|USSize;
size_hints.x = x;
size_hints.y = y;
size_hints.width = width;
size_hints.height = height;
size_hints.min_width = 300;
size_hints.min_height = 300;
XSetNormalHints (display, win, &size_hints);
XStoreName(display, win, window_name);
/* create graphics context */
gc = XCreateGC (display, win, valuemask, &values);
XSetBackground (display, gc, WhitePixel (display, screen));
XSetForeground (display, gc, BlackPixel (display, screen));
XSetLineAttributes (display,gc,1,LineSolid,CapRound,JoinRound);
attr[0].backing_store = Always;
attr[0].backing_planes = 1;
attr[0].backing_pixel = BlackPixel(display, screen);
XChangeWindowAttributes(display, win,
CWBackingStore | CWBackingPlanes | CWBackingPixel, attr);
XMapWindow (display, win);
XSync(display, 0);
/* Calculate and draw points */
for(i=0; i < X_RESN; i++)
{ for(j=0; j < Y_RESN; j++)
{ z.real = z.imag = 0.0; /* 800x800 scale factors */
c.real = ((float) j - 400.0)/200.0;
c.imag = ((float) i - 400.0)/200.0;
k = 0;
do
{ /* iterate for pixel color */
temp = z.real*z.real - z.imag*z.imag + c.real;
z.imag = 2.0*z.real*z.imag + c.imag;
z.real = temp;
lengthsq = z.real*z.real+z.imag*z.imag;
k++;
} while (lengthsq < 4.0 && k < 100);
if (k == 100) XDrawPoint (display, win, gc, j, i);
} }
XFlush (display);
sleep (30);
/* Program Finished */
}
Open up a command prompt and run the two commands:
find / -type f - name Xlib.h
find / -type d - name X11
That should help you locate that file and/or directory so you can see whether it's available.
If it is available (e.g., it's found at /usr/include/X_stuff/X11/Xlib.h), make sure your compiler command references it, like:
g++ -I/usr/include/X_stuff ...
If it's not there, install it.
Either you forgot to install the X development packages, or the directory containing the headers was not added to the includedir list.

Draw on webcam using OpenCV

I want to draw/paint on a webcam screen using OpenCV. Since I'm reading from a cam, the frames are constantly changing, so I'm trying to figure out a way to keep or save the drawing on the current frame and use it for the next frame. The code below allows you to draw on the screen but when it gets the next frame, the drawing is gone and it starts over.
Could someone please help me ... Thanks.
CvCapture *input;
input = cvCaptureFromCAM( 0 );
cvSetMouseCallback("Demo",&on_mouse, 0);
for(;;)
{
frame = cvQueryFrame(input);
if(!image)
{
image = cvCreateImage( cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);
screenBuffer = cvCreateImage( cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3);
}
cvCopy(frame, image, 0);
if(drawing) //drawing is a global variable
{
cvCircle(image, cvPoint(last_x,last_y), 10,CV_RGB(red,green,blue), -1, CV_AA, 0);
cvCopy(image, screenBuffer, 0);
}
cvShowImage( "Demo", screenBuffer );
}
void on_mouse( int event, int x, int y, int flags, void* param )
{
last_x = x;
last_y = y;
if(event==CV_EVENT_LBUTTONDOWN)
{
drawing = 1;
}
}
Draw into a separate image and then cvAdd() that to the video image immediately before dispalying it
I will not go into all the details why your approach is bad, but keep in mind that creating 2 extra frames for drawing is a little bit too much.
It's important that you realize that all this kinky stuff is being done on the same thread used to capture new frames. This means what exactly? It means that the extra code you are adding inside the loop will slow the process of capturing and displaying new frames. In other words, you are sabotaging yourself by lowering the framerate of your application. If you don't care, it's ok. If you do, my tip for you is that you stack the captured frames into a buffer and have another thread read, process and display them.
Ok, so you REALLY want to draw over the window that's displaying the captured frames. Well, the obvious thing you can't do (and you discovered this yourself) is that the drawing cannot be made on the captured frame because the frame it's replaced with new data on every loop. So what do you do? You create a 2nd frame to do the drawing. Let's call it the drawing_frame.
The only thing that will be on the drawing_frame are the circles that will appear when the mouse moves over the window, when the LBUTTON of the mouse is clicked (a 2nd click switches between ON/OFF).
After the drawing of the circle occurs, the drawing_frame is overlayed on top on the frame captured by the camera. This process is a little expensive on the CPU, and since we are doing it in the main thread of the application, it will also decrease the framerate.
I strongly suggest that everyone interested in adding/merging/overlaying transparent frames with OpenCV take a look at Transparent image overlays in OpenCV.
By the way, I'm using cvCaptureFromCAM(-1) becouse I'm on Linux. You probably should change that to whatever works for you. According to your post it's cvCaptureFromCAM(0).
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
int drawing = 0;
int last_x = 0;
int last_y = 0;
void on_mouse(int event, int x, int y, int flags, void* param)
{
last_x = x;
last_y = y;
if (event == CV_EVENT_LBUTTONDOWN)
{
// switches between On and Off
if (drawing)
drawing = 0;
else
drawing = 1;
}
}
int main()
{
CvCapture* capture = NULL;
if ((capture = cvCaptureFromCAM(-1)) == NULL)
{
fprintf(stderr, "ERROR: capture is NULL \n");
return -1;
}
cvNamedWindow("mywindow", CV_WINDOW_AUTOSIZE);
cvQueryFrame(capture); // Sometimes needed to get correct data
cvSetMouseCallback("mywindow",&on_mouse, 0);
IplImage* frame = NULL;
IplImage* drawing_frame = NULL;
while (1)
{
if ((frame = cvQueryFrame(capture)) == NULL)
{
fprintf( stderr, "ERROR: cvQueryFrame failed\n");
break;
}
if (frame == NULL)
{
fprintf( stderr, "WARNING: cvQueryFrame returned NULL, sleeping..\n");
usleep(100000);
continue;
}
if (!drawing_frame) // This frame is created only once
{
drawing_frame = cvCreateImage(cvSize(frame->width, frame->height), frame->depth, frame->nChannels);
cvZero(drawing_frame);
}
if (drawing)
{
cvCircle(drawing_frame, cvPoint(last_x,last_y), 10,CV_RGB(0, 255, 0), -1, CV_AA, 0);
// For overlaying (copying transparent images) in OpenCV
// http://www.aishack.in/2010/07/transparent-image-overlays-in-opencv/
for (int x = 0; x < frame->width; x++)
{
for (int y = 0; y < frame->height; y++)
{
CvScalar source = cvGet2D(frame, y, x);
CvScalar over = cvGet2D(drawing_frame, y, x);
CvScalar merged;
CvScalar S = { 1,1,1,1 };
CvScalar D = { 1,1,1,1 };
for(int i = 0; i < 4; i++)
merged.val[i] = (S.val[i] * source.val[i] + D.val[i] * over.val[i]);
cvSet2D(frame, y, x, merged);
}
}
}
cvShowImage("mywindow", frame);
int key = cvWaitKey(10);
if (key == 113) // q was pressed on the keyboard
break;
}
cvReleaseImage(&frame);
cvReleaseImage(&drawing_frame);
cvReleaseCapture(&capture);
cvDestroyWindow("mywindow");
return 0;
}
You usually will have problems of adding images (they will eventually saturate), so I guess thats why you start over. I see you have color images... if you use more powerful stuff like OpenGL for your drawing you could use the overlay for your drawings. Otherwise check this out:
http://aishack.in/tutorials/transparent-image-overlays-in-opencv/