cairo draw_text and dangling pointer on itemized lines? - c

I try to use cairo to draw_text on screen but mac Os X instrument tells me that I have dangling pointer cause by pango_layout_get_pixel_size or pango_layout_get_baseline .. actuelly the first function which needs to have PangoLines and store them in Layout variable.
In every code show on the documentation and example you juste have to g_object_unref(layout) at the end ... but still ... those pointers allocate by itemized_state_init (inside pango_layout_get_pixel_size for ex) are not freed.
Am I doing something wrong ?
double posX = somevalue;
double posY = somevalue;
cairo_save (CurCairoState);
PangoLayout *layout = pango_cairo_create_layout (CurCairoState);
pango_layout_set_text (layout, text, -1);
pango_layout_set_font_description (layout, curCairoContext->font);
int width, height;
pango_layout_get_pixel_size (layout, &width, &height);
int b = (int)(pango_layout_get_baseline (layout) / PANGO_SCALE);
/* applying alignment attribute */
switch (curCairoContext->textAnchor) {
case GMiddle:
posX = posX - (width / 2.0);
break;
case GEnd:
posX = posX - width;
break;
}
cairo_move_to (CurCairoState, posX, posY - b);
pango_cairo_show_layout (CurCairoState, layout);
g_object_unref (layout);
cairo_restore (CurCairoState);
and the result of the allocation in Instrument
thanx to any reply !
EDIT:
here is the new screenshot after using G_SLICE=always-malloc G_DEBUG=gc-friendly.
Thoses dangling pointers became leaks for "instrument"
EDIT (no solution found) :
I downloaded the sources of pango-1.40.3, compiled it and installed it with markers of my own and I don't understand why I'have got those dangling pointers on MacOS because I'm going through : pango_layout_finalize and pango_layout_clear_lines and layout->ref_count=0 when I call g_obejct_unref (layout)

Related

how to charge a map in Csfml

I am making a game in CSFML for the purpose of a school exercise
In order to fit all the requirement I must a game who follows the rule of a finite runne suc as geometry dash. It does everything except a major feature: get a map from a file that will be like:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXX2XXXXXXXXX2XXXXXXXXXXXXXXE
111111111111111111111111111111111111
X representing nothing (they will be a background that is displayed)
2 is spike
1 is the ground
E is the end, it will stop the program after displaying a victory screen
(each character will be replace by the texture who is assigned except X who represent empty space)
I had only access to few C functions ( write, free, malloc, rand, open, read,getline)
I was thinking about just reading the file and storing it as a char*, but the thing is I don't know how to make spikes appear on the screen one by one, when they must.
You need to choose a size for all of your blocks.
Each blocks (X, 2, 1, E) need to have the same size.
Example (with block 64*64px)
void display_map(char **map)
{
char *image = NULL;
int size_block = 64;
for (int i = 0; map[i] != NULL; i++) {
for (int j = 0; map[i][j] != '\0'; j++) {
switch (map[i][j]) {
case 'X':
image = "nothing";
break;
case '2':
image = "pike";
break;
// ....
}
display_at_position(i * size_block, j * size_block, image);
}
}
}

Comparing images in which some parts are variable, but should not matter

I am concerned about to find dissimilarities between images as shown in the samples underneath with the black oval shape.
My problem is that some part of image is also variable, but I do not want to consider this part when finding dissimilarities. To overcome this problem I want to make "transparent" that area which is now marked with red color: the variable part Date/Time and the Date/Time edit field should be excluded from comparison as can be seen from image below:
One way is:
I can use a “transparent” color to mark image areas that should not be compared. To do this, I need to modify the baseline copy of an image in the following manner:
Open the baseline image in an image editor (for instance, in MSPaint).
Select the color that you will use as the “transparent” color.
Change the color of the top-left pixel to the “transparent” color.
Use the “transparent” color to fill image areas that you want to exclude from comparison.
How to do automate above manual work through coding? I want to implement above behavior in C code.
My suggestion is:
First implement the solution as a command line with ImageMagick.
Once this works, port this command line over to ImageMagick's C API.
Here are a few answers about comparing images using ImageMagick compare. They may not apply to your precise question, but thy provide enough theoretical background with practical examples to get you started:
ImageMagick compare executable: unrecognized option -metric
Can we programatically compare different images of same resolutions?
ImageMagick: “Diff” an Image
ImageMagick compare: Disregard white matches from the PSNR result
If I understand your question correctly, you do want to compare only some parts of two images, any you want to exclude other parts from the comparison where you already know there are (uninteresting) differences. Right?
Taking these two images as an example:
BTW, these two images have been born as PDFs, and I could apply the procedure described below to PDF pages too (without a need to convert them to image files first).
You do not necessarily need a transparent mask -- you can use a black (or any color) one too.
Create a green mask of 280x20 pixels size:
convert -size 280x20 xc:green greenmask-280x20.png
Now use composite to place the mask on top of each of the images:
convert \
http://i.stack.imgur.com/Q1pyC.png \
greenmask-280x20.png \
-geometry +32+35 \
-compose over \
-composite \
c.png
convert \
http://i.stack.imgur.com/JVije.png \
greenmask-280x20.png \
-geometry +32+35 \
-compose over \
-composite \
r.png
The -geometry +32+35 parameter maybe requires some explanation: it tells ImageMagick to place the top left corner of the greenmask 32 pixels to the right and 35 pixels to the bottom of the top left corner of the original image.
The resulting images are here:
An answer that discusses the different compose methods known to ImageMagick is here:
Superpose two sets of images
Now your images are ready for either statistical or visual comparison, provided by ImageMagick's compare command:
compare c.png r.png -compose src delta.png
The delta.png shows all pixels in red which are different, the rest is white:
Or, using the most simple compare command, where the reference image serves as a pale background with red delta pixels on top:
compare c.png r.png delta2.png
If you are providing a rectangle to colour in, why not just ignore a rectangular area in the first place? Here is some pseudo code
int compareimages (char *im1, char* im2, int wid, int dep, int x0, int y0, int x1, int y1) {
int x, y;
for (y=0; y<dep; y++)
for (x=0; x<wid; x++)
if (x<x0 || x>x1 || y<y0 || y>y1) // if outside rectangle
if im1[y*wid+x] != im2[y*wid+x] // compare pixels
return 0;
return 1;
}
UPDATE for several areas to be ignored, which may overlap.
Still not hard: just provide an array of rectangles. It is still going to be easier than going to the trouble of painting out areas when you can check them in the first place.
#include <stdio.h>
#define WID 200
#define DEP 600
typedef struct {
int left;
int top;
int right;
int bot;
} rect;
char image1[WID*DEP];
char image2[WID*DEP];
int inrect (int x, int y, rect r) {
if (x<r.left || x>r.right || y<r.top || y>r.bot)
return 0;
return 1;
}
int compareimages (char *im1, char* im2, int wid, int dep, rect *rarr, int rects) {
int x, y, n, ignore;
for (y=0; y<dep; y++)
for (x=0; x<wid; x++) {
ignore = 0;
for (n=0; n<rects; n++)
ignore |= inrect (x, y, rarr[n]);
if (!ignore)
if (im1[y*wid+x] != im2[y*wid+x]) // compare pixels
return 0;
}
return 1;
}
int main(void) {
rect rectarr[2] = { {10, 10, 50, 50}, { 40, 40, 90, 90 }};
// ... load images ...
// put pixel in one of the rectangles
image1[20*WID+20] = 1;
if (compareimages (image1, image2, WID, DEP, rectarr, 2))
printf ("Same\n");
else
printf ("Different\n");
// put pixel outside any rectangles
image1[0] = 1;
if (compareimages (image1, image2, WID, DEP, rectarr, 2))
printf ("Same\n");
else
printf ("Different\n");
return 0;
}
Program output:
Same
Different
EDIT added another version of the function, comparing 4 pixel components.
int compareimages (char *im1, char* im2, int wid, int dep, rect *rarr, int rects) {
int x, y, n, ignore;
for (y=0; y<dep; y++)
for (x=0; x<wid; x++) {
ignore = 0;
for (n=0; n<rects; n++)
ignore |= inrect (x, y, rarr[n]);
if (!ignore) {
if (im1[y*wid*4+x] != im2[y*wid*4+x]) // compare pixels
return 0;
if (im1[y*wid*4+x+1] != im2[y*wid*4+x+1])
return 0;
if (im1[y*wid*4+x+2] != im2[y*wid*4+x+2])
return 0;
if (im1[y*wid*4+x+3] != im2[y*wid*4+x+3])
return 0;
}
}
return 1;
}
Normally, such an 'image' as is used in the example is NOT a single image.
Rather it is a large number of images overlaying each other.
Most likely, the 'image' is made of:
the background
the outside border (which has 4 parts)
the upper left icon
the upper border clickable button( three of them)
the text field: Date/Time:
the input field: (for the date/time)
the text field: 'Table:'
the input multi line field/ with initial text 'Customers'
etc etc etc
I.E. that is not a single image but rather many images
that overlay each other
a single image would be something like a .bmp or .tif or .jpg file

openCV k-means call assertion failed

I'm have read c++ sample from samples folder of openCV source distribution, and, if omit random picture generation, kmeans call looks pretty simple – author even doesn't allocate centers/labels arrays (you can find it here). However, I can't do the same in C. If I don't allocate labels, I get assertion error:
OpenCV Error: Assertion failed (labels.isContinuous() && labels.type()
== CV_32S && (labels.cols == 1 || labels.rows == 1) && labels.cols + labels.rows - 1 == data.rows) in cvKMeans2, file
/tmp/opencv-xiht/opencv-2.4.9/modules/core/src/matrix.cpp, line 3094
Ok, I tried to create empty labels matrix, but assertion message don't changes at all.
IplImage* image = cvLoadImage("test.jpg", -1);
IplImage* normal = cvCreateImage(cvGetSize(image), IPL_DEPTH_32F, image->nChannels);
cvConvertScale(image, normal, 1/255.0, 0);
CvMat* points = cvCreateMat(image->width, image->height, CV_32F);
points->data.fl = normal->imageData;
CvMat* labels = cvCreateMat(1, points->cols, CV_32S);
CvMat* centers = NULL;
CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0);
// KMEANS_PP_CENTERS is undefined
int KMEANS_PP_CENTERS = 2;
cvKMeans2(points, 4, labels, criteria, 3, NULL, KMEANS_PP_CENTERS, centers, 0);
The thing that drives me nuts:
CvMat* labels = cvCreateMat(1, points->cols, CV_32S);
int good = labels->type == CV_32S; // FALSE here
It's obviously one (not sure if the only) issue that causes assertion fail. How this supposed to work? I can't use С++ API since whole application is in plain C.
the assertion tells you:
type must be CV_32S which seems to be the case in your code, maybe your if-statement is false because the type is changed to CV_32SC1 automatically? no idea...
you can either place each point in a row or in a column, so rows/cols is set to 1 and the other dimension must be set to data.rows which indicates that data holds the points you want to cluster in the format that each point is placed in a row, leading to #points rows. So your error seems to be CvMat* labels = cvCreateMat(1, points->cols, CV_32S); which should be CvMat* labels = cvCreateMat(1, points->rows, CV_32S); instead, to make the assertion go away, but your use of points seems to be conceptually wrong.
You probably have to hold your points (you want to cluster) in a cvMat with n rows and 2 cols of type CV_32FC1 or 1 col and type CV_32FC2 (maybe both versions work, maybe only one, or maybe I'm wrong there at all).
edit: I've written a short code snippet that works for me:
// here create the data array where your input points will be hold:
CvMat* points = cvCreateMat( numberOfPoints , 2 /* 2D points*/ , CV_32F);
// this is a float array of the
float* pointsDataPtr = points->data.fl;
// fill the mat:
for(unsigned int r=0; r<samples.size(); ++r)
{
pointsDataPtr[2*r] = samples.at(r).x; // this is the x coordinate of your r-th point
pointsDataPtr[2*r+1] = samples.at(r).y; // this is the y coordinate of your r-th point
}
// this is the data array for the labels, which will be the output of the method.
CvMat* labels = cvCreateMat(1, points->rows, CV_32S);
// this is the quit criteria, which I did neither check nor modify, just used your version here.
CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0);
// call the method for 2 cluster
cvKMeans2(points, 2, labels, criteria);
// now labels holds numberOfPoints labels which have either value 0 or 1 since we searched for 2 cluster
int* labelData = labels->data.i; // array to the labels
for(unsigned int r=0; r<samples.size(); ++r)
{
int labelOfPointR = labelData[r]; // this is the value of the label of point number r
// here I use c++ API to draw the points, do whatever else you want to do with the label information (in C API). I choose different color for different labels.
cv::Scalar outputColor;
switch(labelOfPointR)
{
case 0: outputColor = cv::Scalar(0,255,0); break;
case 1: outputColor = cv::Scalar(0,0,255); break;
default: outputColor = cv::Scalar(255,0,255); break; // this should never happen for 2 clusters...
}
cv::circle(outputMat, samples.at(r), 2, outputColor);
}
giving me this result for some generated point data:
Maybe you need the centers too, the C API gives you the option to return them, but didnt check how it works.

Unexpected result when drawing bmp from buffer

The last time i had problem with this was because i swapped WIDTH and HEIGHT in the wrong way. After that i have been told for correct way and i fixed it. However.. today i noticed that the function isn't working as it was expected on some bmp images.
I am rendering the image from a buffer that has all the image's byte data.
And there is the function to render:
void bmp_bdraw (BYTE* BUFF)
{
word WIDTH, HEIGHT, W, H; // word - unsigned short
BYTE R, G, B; // BYTE - unsigned char
(!BUFF || !BUFF[COUNT-1]) ? // debug1
(error("Error in function 'bmp_bdraw'. There is no data to read from.")) : ;
WIDTH = BUFF[18] + BUFF[19] * 256;
HEIGHT = BUFF[22] + BUFF[23] * 256;
ofs = 54;
if(BUFF[0] != 'B' | BUFF[1] != 'M') error // debug2
("Warning: Data identifier error in function 'bmp_bdraw' occurred. Invalid BMP file loaded.");
for(H=HEIGHT-1; H>=0; H--)
{
for(W=0; W<WIDTH; W++)
{
B = sgetc(BUFF); // fgetc-like function but from buff
G = sgetc(BUFF);
R = sgetc(BUFF);
setpen(R, G, B, 0, 1); // sets the color, transparancy and size of the pen
putpixel(W, H); // and puts the pixel at the right location
}
}
if(W != WIDTH || H > 1) // debug3
error("Error in function 'bmp_bdraw'. Rendering failed. The file might be damaged.");
if(real_fps < 11)
error("Too low fps rate."); // debug4
}
If your input data here (BUFF buffer) is correct then
I am sharing my observation with you so you can debug further more.
You are rendering from (H(max),w(0)) to (H(0),w(max)). So in beging everything is good. Image is good but when your H(max) get decrease output image gets bad.
In simple term in bottom part of image output is good when in top part output is bad. It seems like pixel get strinked in top part.
I do not understand how setpen() works. and after processing you should paint that pixel at same position or not?
I think As H(max) decrease with that you should decrease your W value in putpixel(W, H); I think this will remove that inclined vertical line and bad image issue.

Texture management / pointer question

I'm working on a texture management and animation solution for a small side project of mine. Although the project uses Allegro for rendering and input, my question mostly revolves around C and memory management. I wanted to post it here to get thoughts and insight into the approach, as I'm terrible when it comes to pointers.
Essentially what I'm trying to do is load all of my texture resources into a central manager (textureManager) - which is essentially an array of structs containing ALLEGRO_BITMAP objects. The textures stored within the textureManager are mostly full sprite sheets.
From there, I have an anim(ation) struct, which contains animation-specific information (along with a pointer to the corresponding texture within the textureManager).
To give you an idea, here's how I setup and play the players 'walk' animation:
createAnimation(&player.animations[0], "media/characters/player/walk.png", player.w, player.h);
playAnimation(&player.animations[0], 10);
Rendering the animations current frame is just a case of blitting a specific region of the sprite sheet stored in textureManager.
For reference, here's the code for anim.h and anim.c. I'm sure what I'm doing here is probably a terrible approach for a number of reasons. I'd like to hear about them! Am I opening myself to any pitfalls? Will this work as I'm hoping?
anim.h
#ifndef ANIM_H
#define ANIM_H
#define ANIM_MAX_FRAMES 10
#define MAX_TEXTURES 50
struct texture {
bool active;
ALLEGRO_BITMAP *bmp;
};
struct texture textureManager[MAX_TEXTURES];
typedef struct tAnim {
ALLEGRO_BITMAP **sprite;
int w, h;
int curFrame, numFrames, frameCount;
float delay;
} anim;
void setupTextureManager(void);
int addTexture(char *filename);
int createAnimation(anim *a, char *filename, int w, int h);
void playAnimation(anim *a, float delay);
void updateAnimation(anim *a);
#endif
anim.c
void setupTextureManager() {
int i = 0;
for(i = 0; i < MAX_TEXTURES; i++) {
textureManager[i].active = false;
}
}
int addTextureToManager(char *filename) {
int i = 0;
for(i = 0; i < MAX_TEXTURES; i++) {
if(!textureManager[i].active) {
textureManager[i].bmp = al_load_bitmap(filename);
textureManager[i].active = true;
if(!textureManager[i].bmp) {
printf("Error loading texture: %s", filename);
return -1;
}
return i;
}
}
return -1;
}
int createAnimation(anim *a, char *filename, int w, int h) {
int textureId = addTextureToManager(filename);
if(textureId > -1) {
a->sprite = textureManager[textureId].bmp;
a->w = w;
a->h = h;
a->numFrames = al_get_bitmap_width(a->sprite) / w;
printf("Animation loaded with %i frames, given resource id: %i\n", a->numFrames, textureId);
} else {
printf("Texture manager full\n");
return 1;
}
return 0;
}
void playAnimation(anim *a, float delay) {
a->curFrame = 0;
a->frameCount = 0;
a->delay = delay;
}
void updateAnimation(anim *a) {
a->frameCount ++;
if(a->frameCount >= a->delay) {
a->frameCount = 0;
a->curFrame ++;
if(a->curFrame >= a->numFrames) {
a->curFrame = 0;
}
}
}
You may want to consider a more flexible Animation structure that contains an array of Frame structures. Each frame structure could contain the frame delay, an x/y hotspot offset, etc. This way different frames of the same animation could be different sizes and delays. But if you don't need those features, then what you're doing is fine.
I assume you'll be running the logic at a fixed frame rate (constant # of logical frames per second)? If so, then the delay parameters should work out well.
A quick comment regarding your code:
textureManager[i].active = true;
You probably shouldn't mark it as active until after you've checked if the bitmap loaded.
Also note that Allegro 4.9/5.0 is fully backed by OpenGL or D3D textures and, as such, large bitmaps will fail to load on some video cards! This could be a problem if you are generating large sprite sheets. As of the current version, you have to work around it yourself.
You could do something like:
al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
ALLEGRO_BITMAP *sprite_sheet = al_load_bitmap("sprites.png");
al_set_new_bitmap_flags(0);
if (!sprite_sheet) return -1; // error
// loop over sprite sheet, creating new video bitmaps for each frame
for (i = 0; i < num_sprites; ++i)
{
animation.frame[i].bmp = al_create_bitmap( ... );
al_set_target_bitmap(animation.frame[i].bmp);
al_draw_bitmap_region( sprite_sheet, ... );
}
al_destroy_bitmap(sprite_sheet);
al_set_target_bitmap(al_get_backbuffer());
To be clear: this is a video card limitation. So a large sprite sheet may work on your computer but fail to load on another. The above approach loads the sprite sheet into a memory bitmap (essentially guaranteed to succeed) and then creates a new, smaller hardware accelerated video bitmap per frame.
Are you sure you need a pointer to pointer for ALLEGRO_BITMAP **sprite; in anim?
IIRC Allegro BITMAP-handles are pointers already, so there is no need double-reference them, since you seem to only want to store one Bitmap per animation.
You ought to use ALLEGRO_BITMAP *sprite; in anim.
I do not see any other problems with your code.

Resources