Center bitmap text to a rectangle with OpenGL - c++

I need to center a piece of text to a rectangle.
I found this example, but I'm struggling to understand what it does.
It is not too hard to achieve this, I just need to know how do I find the width and the height of the text after being drawn, but I cannot find this anywhere.
To draw the text, I do it char by char:
static void drawText(std::string str, float x, float y, float z) {
glRasterPos3f(x, y, z);
for (unsigned int i = 0; i < str.size(); i++) {
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, str[i]);
}
}
Not sure if this is the best way, but it is my first program using OpenGL.

Raster fonts are awful, this will not work in modern OpenGL just so you know - you need to use texture-mapped triangles to implement bitmap fonts now-a-days. If you are just starting out, legacy OpenGL may work for you, but you will find that things like raster pos are not supported in OpenGL ES and core OpenGL 3+.
That said you can sum up glutBitmapWidth (...) across all of the characters in your string, like this:
unsigned int str_pel_width = 0;
const unsigned int str_len = str.size ();
// Finding the string length can be expensive depending on implementation (e.g. in
// a C-string it requires looping through the entire string storage until the
// first null byte is found, each and every time you call this).
//
// The string has a constant-length, so move this out of the loop for better
// performance! You are using std::string, so this is not as big an issue, but
// you did ask for the "best way" of doing something.
for (unsigned int i = 0; i < str_len; i++)
str_pel_width += glutBitmapWidth (GLUT_BITMAP_HELVETICA_18, str [i]);
Now, to finish up this discussion, you should be aware that the height of each character is identical in a GLUT bitmap font. If I recall, 18 pt. Helvetica is probably 22 or 24 pixels high. The distinction between pt. size and pixel size is supposed to be for DPI scaling, but GLUT does not actually implement this.

Related

How to quickly scan and analyze large groups of pixels?

I am trying to build an autoclicker using C++ to beat a 2D videogame in which the following situation appears:
The main character is in the center of the screen, the background is completely black and enemies are coming from all directions. I want my program to be capable of clicking on enemies just as they appear on the screen.
What I came up at first is that the enemies have a minimum size of 15px, so I tried doing a search every 15 pixels and analyze if any pixel is different than the background's RGB, using GetPixel(). It looks something like this:
COLORREF color;
int R, G, B;
for(int i=0; i<SCREEN_SIZE_X; i+=15){ //These SCREEN_SIZE values are #defined with the ones of my screen
for(int j=0;j<SCREEN_SIZE_Y, j+=15){
//The following conditional excludes the center which is the player's position
if((i<PLAYER_MIN_EDGE_X or i>PLAYER_MAX_EDGE_X) and (j<PLAYER_MIN_EDGE_Y or j>PLAYER_MAX_EDGE_Y)){
color = GetPixel(GetDC(nullptr), i, j);
R = GetRValue(color);
G = GetGValue(color);
B = GetBValue(color);
if(R!=0 or G!=0 or B!=0) cout<<"Enemy Found"<<endl;
}
}
}
It turns out that, as expected, the GetPixel() function is extremely slow as it has to verify about 4000 pixels to cover just one screen scan. I was thinking about a way to solve this faster, and while looking at the keyboard I noticed the button "Pt Scr", and then realized that whatever that button is doing it is able to almost instantly save the information of millions of pixels.
I surely think there is a proper and different technic to approach this kind of problem.
What kind of theory or technic for pixel analyzing should I investigate and read about so that this can be considered respectable code, and to get it actually work, and much faster?
The GetPixel() routine is slow because it's fetching the data from the videocard (device) memory one by one. So to optimize your loop, you have to fetch the entire screen at once, and put it into an array of pixels. Then, you can iterate over that array of pixels much faster, because it'll be operating over the data in your RAM (host memory).
For a better optimization, I also recommend clearing the pixels of your player (in the center of the screen) after fetching the screen into your pixel array. This way, you can eliminate that if((i<PLAYER_MIN_EDGE_X or i>PLAYER_MAX_EDGE_X) and (j<PLAYER_MIN_EDGE_Y or j>PLAYER_MAX_EDGE_Y)) condition inside the loop.
CImage image;
//Save DC to image
int R, G, B;
BYTE *pRealData = (BYTE*)image.GetBits();
int pit = image.GetPitch();
int bitCount = image.GetBPP()/8;
int w=image.GetWidth();
int h=image.GetHeight();
for (int i=0;i<h;i++)
{
for (int j=0;j<w;j++)
{
B=*(pRealData + pit*i + j*bitCount);
G=*(pRealData + pit*i + j*bitCount +1);
R=*(pRealData + pit*i + j*bitCount +2);
}
}

FreeType 2 character exact size and exact position

Making some experiments with ttf fonts, and tried to use famous font rendering library FreeType, version 2.5.3.
My code:
#include "ft2build.h"
#include FT_FREETYPE_H
#define FONTPATH "<font path here>"
const char* fontfile=FONTPATH "<fontname here>.TTF";
const int w=25;
const int h=25;
char* outbitmap;
int main() {
outbitmap=new char[w*h];
memset(outbitmap,0,w*h);
FT_Library ftl;
FT_Error err=FT_Init_FreeType(&ftl);
FT_Face fface;
err=FT_New_Face(ftl,fontfile,0,&fface);
err=FT_Set_Pixel_Sizes(fface,w,h);
FT_UInt ch;
//ch=0x3042; //あ
//ch='_';
ch='|';
FT_UInt chridx=FT_Get_Char_Index(fface,ch);
err=FT_Load_Glyph(fface,chridx,FT_LOAD_DEFAULT);
err=FT_Render_Glyph(fface->glyph,FT_RENDER_MODE_NORMAL);
for(int y=0;y<fface->glyph->bitmap.rows;++y) {
int outy=fface->glyph->bitmap.rows-fface->glyph->bitmap_top+y; //???how to get baseline position
for(int x=0;x<fface->glyph->bitmap.width;++x) {
int outx=fface->glyph->bitmap_left+x;
outbitmap[outy*w+outx]=fface->glyph->bitmap.buffer[fface->glyph->bitmap.width*y+x];
}
}
delete[] outbitmap;
err=FT_Done_Face(fface);
err=FT_Done_FreeType(ftl);
return 0;
}
So I have some questions.
Assume that I need render one character to byte array with fixed size, in correct position.
Character size must be exactly size that fits in output bitmap, no clipping allowed.
It's OK to ignore kerning completely.
I specified character width=height=25. But for '|' it gives fface->glyph->bitmap.rows==26.
How should I set height to get exactly 25px output, not 26, for any normal font? If it isn't
possible, then is there any way to calculate output character height exactly in pixels before
FT_Render_Glyph. FT_Set_Pixel_Sizes doesn't work well enough, so I getting +1px sometimes.
How do I get baseline position for any given font? If I have baseline, I can place character
in exactly right position. I have no 1000x1000 screen, just one bitmap 25x25.
This is super late but I just found out how to do this:
(Getting the character height in pixels). From what I understand setting the font size (e.g. with FT_Set_Char_Size) really just defines a scaling between font units and pixel units (this explains more). I.e., 12pt font at 72dpi does not necessarily mean the glyph is 12 pixels high. You can, however, get a bounding box that I am pretty sure will enclose every single glyph in the chosen font. This is how I did it:
//12pt font
double font_size = 12.0;
//Resolution means DPI here
double pixel_size = font_size * resolution / 72;
//Font height and width in pixels
int font_height = round((face->bbox.yMax - face->bbox.yMin)*pixel_size / face->units_per_EM);
int font_width = round((face->bbox.xMax - face->bbox.xMin)*pixel_size / face->units_per_EM);
This is how I got a baseline height. It's just the maximum descent below the baseline of any glyph. When paired with the above code, drawing your glyph with the baseline at this position should guarantee that all glyphs will fit in the bounding box.
//Convert this to pixel_size if your DPI is not 72
double font_size = 12.0;
//Height in pixels (using a double for sub-pixel precision)
double baseline_height = abs(face->descender) * font_size / face->units_per_EM;
(Where face is the font you have loaded).
EDIT: forgot to account for DPI, in my application I was just using 72 so it canceled out
Nobody answered anything, so posting some more workarounds than answers I found by myself.
For question 1, I can probably live with that after applying following:
FT_Set_Pixel_Sizes(fface,w-1,h-1);
or maybe even
FT_Set_Pixel_Sizes(fface,w-w%2,h-h%2);
For question 2 I don't know yet ...

Vertically flipping an Char array: is there a more efficient way?

Lets start with some code:
QByteArray OpenGLWidget::modifyImage(QByteArray imageArray, const int width, const int height){
if (vertFlip){
/* Each pixel constist of four unisgned chars: Red Green Blue Alpha.
* The field is normally 640*480, this means that the whole picture is in fact 640*4 uChars wide.
* The whole ByteArray is onedimensional, this means that 640*4 is the red of the first pixel of the second row
* This function is EXTREMELY SLOW
*/
QByteArray tempArray = imageArray;
for (int h = 0; h < height; ++h){
for (int w = 0; w < width/2; ++w){
for (int i = 0; i < 4; ++i){
imageArray.data()[h*width*4 + 4*w + i] = tempArray.data()[h*width*4 + (4*width - 4*w) + i ];
imageArray.data()[h*width*4 + (4*width - 4*w) + i] = tempArray.data()[h*width*4 + 4*w + i];
}
}
}
}
return imageArray;
}
This is the code I use right now to vertically flip an image which is 640*480 (The image is actually not guaranteed to be 640*480, but it mostly is). The color encoding is RGBA, which means that the total array size is 640*480*4. I get the images with 30 FPS, and I want to show them on the screen with the same FPS.
On an older CPU (Athlon x2) this code is just too much: the CPU is racing to keep up with the 30 FPS, so the question is: can I do this more efficient?
I am also working with OpenGL, does that have a gimmic I am not aware of that can flip images with relativly low CPU/GPU usage?
According to this question, you can flip an image in OpenGL by scaling it by (1,-1,1). This question explains how to do transformations and scaling.
You can improve at least by doing it blockwise, making use of the cache architecture. In your example one of the accesses (either the read OR the write) will be off-cache.
For a start it can help to "capture scanlines" if you're using two loops to loop through the pixels of an image, like so:
for (int y = 0; y < height; ++y)
{
// Capture scanline.
char* scanline = imageArray.data() + y*width*4;
for (int x = 0; x < width/2; ++x)
{
const int flipped_x = width - x-1;
for (int i = 0; i < 4; ++i)
swap(scanline[x*4 + i], scanline[flipped_x*4 + i]);
}
}
Another thing to note is that I used swap instead of a temporary image. That'll tend to be more efficient since you can just swap using registers instead of loading pixels from a copy of the entire image.
But also it generally helps if you use a 32-bit integer instead of working one byte at a time if you're going to be doing anything like this. If you're working with pixels with 8-bit types but know that each pixel is 32-bits, e.g., as in your case, you can generally get away with a case to uint32_t*, e.g.
for (int y = 0; y < height; ++y)
{
uint32_t* scanline = (uint32_t*)imageArray.data() + y*width;
std::reverse(scanline, scanline + width);
}
At this point you might parellelize the y loop. Flipping an image horizontally (it should be "horizontal" if I understood your original code correctly) in this way is a little bit tricky with the access patterns, but you should be able to get quite a decent boost using the above techniques.
I am also working with OpenGL, does that have a gimmic I am not aware
of that can flip images with relativly low CPU/GPU usage?
Naturally the fastest way to flip images is to not touch their pixels at all and just save the flipping for the final part of the pipeline when you render the result. For this you might render a texture in OGL with negative scaling instead of modifying the pixels of a texture.
Another thing that's really useful in video and image processing is to represent an image to process like this for all your image operations:
struct Image32
{
uint32_t* pixels;
int32_t width;
int32_t height;
int32_t x_stride;
int32_t y_stride;
};
The stride fields are what you use to get from one scanline (row) of an image to the next vertically and one column to the next horizontally. When you use this representation, you can use negative values for the stride and offset the pixels accordingly. You can also use the stride fields to, say, render only every other scanline of an image for fast interactive half-res scanline previews by using y_stride=height*2 and height/=2. You can quarter-res an image by setting x stride to 2 and y stride to 2*width and then halving the width and height. You can render a cropped image without making your blit functions accept a boatload of parameters by just modifying these fields and keeping the y stride to width to get from one row of the cropped section of the image to the next:
// Using the stride representation of Image32, this can now
// blit a cropped source, a horizontally flipped source,
// a vertically flipped source, a source flipped both ways,
// a half-res source, a quarter-res source, a quarter-res
// source that is horizontally flipped and cropped, etc,
// and all without modifying the source image in advance
// or having to accept all kinds of extra drawing parameters.
void blit(int dst_x, int dst_y, Image32 dst, Image32 src);
// We don't have to do things like this (and I think I lost
// some capabilities with this version below but it hurts my
// brain too much to think about what capabilities were lost):
void blit_gross(int dst_x, int dst_y, int dst_w, int dst_h, uint32_t* dst,
int src_x, int src_y, int src_w, int src_h,
const uint32_t* src, bool flip_x, bool flip_y);
By using negative values and passing it to an image operation (ex: a blit operation), the result will naturally be flipped without having to actually flip the image. It'll end up being "drawn flipped", so to speak, just as with the case of using OGL with a negative scaling transformation matrix.

C++/SDL: Fading out a surface already having per-pixel alpha information

Suppose we have a 32-bit PNG file of some ghostly/incorporeal character, which is drawn in a semi-transparent fashion. It is not equally transparent in every place, so we need the per-pixel alpha information when loading it to a surface.
For fading in/out, setting the alpha value of an entire surface is a good way; but not in this case, as the surface already has the per-pixel information and SDL doesn't combine the two.
What would be an efficient workaround (instead of asking the artist to provide some awesome fade in/out animation for the character)?
I think the easiest way for you to achieve the result you want is to start by loading the source surface containing your character sprites, then, for every instance of your ghost create a working copy of the surface. What you'll want to do is every time the alpha value of an instance change, SDL_BlitSurface (doc) your source into your working copy and then apply your transparency (which you should probably keep as a float between 0 and 1) and then apply your transparency on every pixel's alpha channel.
In the case of a 32 bit surface, assuming that you initially loaded source and allocated working SDL_Surfaces you can probably do something along the lines of:
SDL_BlitSurface(source, NULL, working, NULL);
if(SDL_MUSTLOCK(working))
{
if(SDL_LockSurface(working) < 0)
{
return -1;
}
}
Uint8 * pixels = (Uint8 *)working->pixels;
pitch_padding = (working->pitch - (4 * working->w));
pixels += 3; // Big Endian will have an offset of 0, otherwise it's 3 (R, G and B)
for(unsigned int row = 0; row < working->h; ++row)
{
for(unsigned int col = 0; col < working->w; ++col)
{
*pixels = (Uint8)(*pixels * character_transparency); // Could be optimized but probably not worth it
pixels += 4;
}
pixels += pitch_padding;
}
if(SDL_MUSTLOCK(working))
{
SDL_UnlockSurface(working);
}
This code was inspired from SDL_gfx (here), but if you're doing only that, I wouldn't bother linking against a library just for that.

How to rescale an image with c/c++ in windows?

What's the shortest solution in c/c++?
You didn't give too much information so I will go with StretchBlt
For an example, see Scaling an Image.
I won't give you a demo, but try to do the following:
create destination bitmap that is of your desired size
select that bitmap into device context
StretchBlt original bitmap onto device context previously mentioned
unselect bitmap from the device context
That recipe above needs no any library then GDI that is already present in windows. And if you plan to draw something in c++, you should get familiarity with that library anyway.
Look here:
http://www.ucancode.net/Free-VC-Draw-Print-gdi-example-tutorial/GDI-Object-VC-MFC-Tutorial.htm
or here:
http://www.olivierlanglois.net/clover.html
if you don't plan to use MFC for the task.
One of the easiest rescale algorithms is nearest-neighbour. Suppose your are rescaling from an image in an array of size x1 y1 to another size x2 y2. The idea is to find the nearest integer offset in original array to each target array position. So your rescale algorithm ends for something like this:
const int x1 = 512;
const int y1 = 512;
const int x2 = 64;
const int y2 = 64;
unsigned char orig[x1*y1]; /* Original byte array */
unsigned char target[x2*y2] /* Target byte array */
for(int i=0;i<x2;i++)
{
for(int j=0;j<y2;j++)
{
xoff = (i*x2)/x1;
yoff = (j*y2)/y1;
target[i+j*x2] = orig[xoff+yoff*x1]
}
}
This will give a blocky resized image. For better results you can use average or any other fancier polynomial based interpolators.
What libraries are you using? How do you represent images? Most image libraries should already be able to do that, e.g. Qt has QPixmap with scaled() and GDI has StretchBlt.
Or you could code it yourself with bicubic interpolation.