XCopyArea fails for X11 bitmap (Pixmap with depth 1) - c++

I want to do texture atlas with Xlib in X11. I Created a pixmap by loading pixel data from an image file which contains all sprites that will be used as texture. I can copy part of texture atlas pixmap (single spirit) to another pixmap created as off-screen drawable successfully.
Here comes the problem. I want the texture copied to the destination pixmap with partial transparent so that there will not be a background rectangle appears behind each spirit. To do that I created a pixmap with depth equals 1 for the whole texture atlas image(500 * 500).
The pMaskData is the pixel data with depth 1.
Pixmap texAtlasMask = XCreatePixmapFromBitmapData(kTheDisplay, kRootWindow,
(char*)pMaskData, 500, 500, 1, 0, 1);
Then I create a clip_mask pixmap for a single sprite, the size of the sprite is 16*16, by first creating a 1 depth pixmap:
Pixmap clipMask = XCreatePixmap(kTheDisplay, kRootWindow, 16, 16, 1);
then use the following call to fill the content of clipMask:
// Error occurs here
// reqest code: 62:X_CopyArea
// Error code: 8:BadMatch (invalid parameter attributes)
XCopyArea(kTheDisplay, texAtlasMask, clipMask, m_gc, 0, 0,16, 16, 0, 0);
After that:
XSetClipMask(kTheDisplay, m_gc, clipMask);
// Copy source spirit to backing store pixmap
XSetClipOrigin(kTheDisplay, m_gc, destX, destY);
XCopyArea(kTheDisplay, m_symAtlas, m_backStore, m_gc, srcLeft, srcTop,
width, height, destX, destY);
The m_symAtlas is the texture atlas pixmap, m_backStore is the destination pixmap we are drawing to.
As listed above error happens in the first call of XCopyArea. I tried XCopyPlane, but nothing changed.
And I play around with XCopyArea and found that as long as the pixmap 's depth is 32 the XCopyArea works fine, it fails when the depth is not 32. Any idea what is wrong?

Related

How to go from raw Bitmap data to SDL Surface or Texture?

I'm using a library called Awesomium and it has the following function:
void Awesomium::BitmapSurface::CopyTo ( unsigned char * dest_buffer, // output
int dest_row_span, // input that I can select
int dest_depth, // input that I can select
bool convert_to_rgba, // input that I can select
bool flip_y // input that I can select
) const
Copy this bitmap to a certain destination. Will also set the dirty bit to False.
Parameters
dest_buffer A pointer to the destination pixel buffer.
dest_row_span The number of bytes per-row of the destination.
dest_depth The depth (number of bytes per pixel, is usually 4 for BGRA surfaces and 3 for BGR surfaces).
convert_to_rgba Whether or not we should convert BGRA to RGBA.
flip_y Whether or not we should invert the bitmap vertically.
This is great because it gives me an unsigned char * dest_buffer which contains raw bitmap data. I've been trying for several hours to convert this raw bitmap data into some sort of usable format that I can use in SDL but I'm having trouble. =[ Is there any way I can load it into a SDL texture or surface? It would be ideal to have examples for both but if I only get one example (either texture or surface), that is sufficient and I will be very grateful. :) I tried to use SDL_LoadBMP_RW but that crashed. I'm not even sure if I should be using that method.
SDL_LoadBMP_RW is for loading an image in the BMP file format. And it expects an SDL_RWops*, which is a file stream, not a pixel buffer. The function you want is SDL_CreateRGBSurfaceFrom. I believe this call should work for your purposes:
SDL_Surface* surface =
SDL_CreateRGBSurfaceFrom(
pixels, // dest_buffer from CopyTo
width, // in pixels
height, // in pixels
depth, // in bits, so should be dest_depth * 8
pitch, // dest_row_span from CopyTo
Rmask, // RGBA masks, see docs
Gmask,
Bmask,
Amask
);

Rendering a Glyph to a bitmap image in C++ using SFML

I want to generate a bitmap image of a glyph so that I can compare it to pixel values of unknown letters in another image.
I'm using Visual Studio 2008, my project is in C++ and I'm using SFML. I can load in a font from a ttf file fine, and I tried to do something like:
sf::Font myFont;
myFont.loadFromFile("Path\\arial.ttf");
sf::Texture myTexture = myFont.getTexture(48);
sf::Image textureImage = myTexture.copyToImage();
sf::Glyph myGlyph = myFont.getGlyph(65, 12, false); // get the 'A' glyph
sf::Image glyphImage;
glyphImage.create(myGlyph.bounds.width, myGlyph.bounds.height, sf::Color::White);
glyphImage.copy(textureImage, 0, 0, myGlyph.textureRect);
I believe this doesn't work because I am just creating an image from the part of the texture where the glyph is located, rather than the pixel values of the glyph itself.
Can someone please help?
This works fine for me:
unsigned int size = 20;
sf::Glyph glyph = font.getGlyph('A', size, false);
sf::Texture bitmap = font.getTexture(size);
sf::Image image;
image.create(glyph.bounds.width, glyph.bounds.height);
image.copy(bitmap.copyToImage(), 0, 0, glyph.textureRect);
Note that in this sample the character size is the same when getGlyph and getTexture are called, which was not the case in your code above.
Also, instead of magic number like 65 use 'A' for readability.

How to create one bitmap from parts of many textures (C++, SDL 2)?

I have *.png files and I want to get different 8x8 px parts from textures and place them on bitmap (SDL_Surface, I guess, but maybe not), smth like this:
Now I'm rendering that without bitmap, i.e. I call each texture and draw part directly on screen each frame, and it's too slow. I guess I need to load each *.png to separate bitmap and use them passing video memory, then call just one big bitmap, but maybe I'm wrong. I need the fastest way of doing that, I need code of this (SDL 2, not SDL 1.3).
Also maybe I need to use clear OpenGL here?
Update:
Or maybe I need to load *.png's to int arrays somehow and use them just like usual numbers and place them to one big int array, and then convert it to SDL_Surface/SDL_Texture? It seems this is the best way, but how to write this?
Update 2:
Colors of pixels in each block are not the same as it presented at the picture and also can they be transparent. Picture is just an example.
Assumming you already have your bitmaps loaded up as SDL_Texture(s), composing them into a different texture is done via SDL_SetRenderTarget .
SDL_SetRenderTarget(renderer, target_texture);
SDL_RenderCopy(renderer, texture1, ...);
SDL_RenderCopy(renderer, texture2, ...);
...
SDL_SetRenderTarget(renderer, NULL);
Every render operation you perform between setting your Render Target and resetting it (by calling SDL_SetRenderTarget with a NULL texture parameter) will be renderer to the designated texture. You can then use this texture as you would use any other.
Ok so, when I asked about "solid colour", I meant - "in that 8x8 pixel area in the .png that you are copying from, do all 64 pixels have the same identical RGB value?" It looks that way in your diagram, so how about this:
How about creating an SDL_Surface, and directly painting 8x8 pixel areas of the memory pointed to by the pixels member of that SDL_Surface with the values read from the original .png.
And then when you're done, convert that surface to an SDL_Texture and render that?
You would avoid all the SDL_UpdateTexture() calls.
Anyway here is some example code. Let's say that you create a class called EightByEight.
class EightByEight
{
public:
EightByEight( SDL_Surface * pDest, Uint8 r, Uint8 g, Uint8 b):
m_pSurface(pDest),
m_red(r),
m_green(g),
m_blue(b){}
void BlitToSurface( int column, int row );
private:
SDL_Surface * m_pSurface;
Uint8 m_red;
Uint8 m_green;
Uint8 m_blue;
};
You construct an object of type EightByEight by passing it a pointer to an SDL_Surface and also some values for red, green and blue. This RGB corresponds to the RGB value taken from the particular 8x8 pixel area of the .png you are currently reading from. You will paint a particular 8x8 pixel area of the SDL_Surface pixels with this RGB value.
So now when you want to paint an area of the SDL_Surface, you use the function BlitToSurface() and pass in a column and row value. For example, if you divided the SDL_Surface into 8x8 pixel squares, BlitToSurface(3,5) means the paint the square at the 4th column, and 5th row with the RGB value that I set on construction.
The BlitToSurface() looks like this:
void EightByEight::BlitToSurface(int column, int row)
{
Uint32 * pixel = (Uint32*)m_pSurface->pixels+(row*(m_pSurface->pitch/4))+column;
// now pixel is pointing to the first pixel in the correct 8x8 pixel square
// of the Surface's pixel memory. Now you need to paint a 8 rows of 8 pixels,
// but be careful - you need to add m_pSurface->pitch - 8 each time
for(int y = 0; y < 8; y++)
{
// paint a row
for(int i = 0; i < 8; i++)
{
*pixel++ = SDL_MapRGB(m_pSurface->format, m_red, m_green, m_blue);
}
// advance pixel pointer by pitch-8, to get the next "row".
pixel += (m_pSurface->pitch - 8);
}
}
I'm sure you could probably speed things up further by pre-calculating an RGB value on construction. Or if you're reading a pixel from the texture, you could probably dispense with the SDL_MapRGB() (but it's just there in case the Surface has different pixel format to the .png).
memcpy is probably faster than 8 individual assignments to the RGB value - but I just want to demonstrate the technique. You could experiment.
So, all the EightByEight objects you create, all point to the same SDL_Surface.
And then, when you're done, you just convert that SDL_Surface to an SDL_Texture and blit that.
Thanks to everyone who took part, but we solved it with my friends. So here is an example (source code is too big and unnecessary here, I'll just describe the main idea):
int pitch, *pixels;
SDL_Texture *texture;
...
if (!SDL_LockTexture(texture, 0, (void **)&pixels, &pitch))
{
for (/*Conditions*/)
memcpy(/*Params*/);
SDL_UnlockTexture(texture);
}
SDL_RenderCopy(renderer, texture, 0, 0);

Display contents of OpenglES buffer

I want to display a yuv to rgb converted frame to the default display. Currently i am doing it with the following code where the yuv to rgb conversion is done by an assembly code which loads CPU. I have found some code to do the same with opengles.
Yuv420_to_RGB(ui8buf, buffer1, h1, w1); /* RGB data will be resulted in buffer1 */
window = ANativeWindow_fromSurface(env, surface);
ANativeWindow_acquire(window);
wid = ANativeWindow_getWidth(window);
hei = ANativeWindow_getHeight(window);
ANativeWindow_setBuffersGeometry(window,w1,h1,1)
if (ANativeWindow_lock(window, &buffer, NULL) == 0)
{
memcpy(buffer.bits, buffer1, (4* w1*h1));
ANativeWindow_unlockAndPost(window);
}
ANativeWindow_release(window);
I have the opengles routine ending with glDrawArrays. How can i display the result of opengles conversion?
Nothing of the code you posted does anything with OpenGL-ES. The typical method to implement color space conversion with OpenGL(-ES) is to load the image into a texture, load a fragment shader performing the color conversion and draw a (full viewport) textured quad (that's what glDrawArrays will do, if a quad's geometry has been loaded into the vertex arrays before).

opengl video freeze

I have an IDS ueye cam and proceed the capture via PBO to OpenGL (OpenTK). On my developer-pc it works great, but on slower machines the video freezes after some time.
Code for allocating memory via opengl and map to ueye, so camera saves processed images in here:
// Generate PBO and save id
GL.GenBuffers(1, out this.frameBuffer[i].BufferID);
// Define the type of the buffer.
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, this.frameBuffer[i].BufferID);
// Define buffer size.
GL.BufferData(BufferTarget.PixelUnpackBuffer, new IntPtr(width * height * depth), IntPtr.Zero, BufferUsageHint.StreamDraw);
// Get pointer to by openGL allocated buffer and
// lock global with uEye.
this.frameBuffer[i].PointerToNormalMemory = GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);
this.frameBuffer[i].PointerToLockedMemory = uEye.GlobalLock(this.frameBuffer[i].PointerToNormalMemory);
// Unmap PBO after use.
GL.UnmapBuffer(BufferTarget.PixelUnpackBuffer);
// Set selected PBO to none.
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
// Register buffer to uEye
this.Succeeded("SetAllocatedImageMem", this.cam.SetAllocatedImageMem(width, height, depth, this.frameBuffer[i].PointerToLockedMemory, ref this.frameBuffer[i].MemId));
// Add buffer to uEye-Ringbuffer
this.Succeeded("AddToSequence", this.cam.AddToSequence(this.frameBuffer[i].PointerToLockedMemory, this.frameBuffer[i].MemId));
To copy the image from pbo to an texture (Texture is created and ok):
// Select PBO with new video image
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, nextBufferId);
// Select videotexture as current
GL.BindTexture(TextureTarget.Texture2D, this.videoTextureId);
// Copy PBO to texture
GL.TexSubImage2D(
TextureTarget.Texture2D,
0,
0,
0,
nextBufferSize.Width,
nextBufferSize.Height,
OpenTK.Graphics.OpenGL.PixelFormat.Bgr,
PixelType.UnsignedByte,
IntPtr.Zero);
// Release Texture
GL.BindTexture(TextureTarget.Texture2D, 0);
// Release PBO
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
Maybe someone can see the mistake... After about 6 seconds the ueye events don't deliver any images any more. When I remove TexSubImage2D it works well, but of course no image appears.
Is there maybe a lock or something from opengl?
Thanks in advance - Thomas
it seems like a shared buffer problem. you may try to implement a simple queue mechanism to get rid of that problem.
sample code (not meant to be working):
queue< vector<BYTE> > frames;
...
frames.push(vector<BYTE>(frameBuffer, frameBuffer + frameSize));
...
// use frame here at GL.TexSubImage2D using frames.front()
frames.pop();
Found the failure by myself. Just replace in the code above StreamDraw with StreamRead.
GL.BufferData(BufferTarget.PixelUnpackBuffer, new IntPtr(width * height * depth), IntPtr.Zero, BufferUsageHint.StreamRead);