Rounded corners with C++ - c++

I'm looking for some c++ drawing graphics library to create rounded corners with anti-aliasing option for dynamic keyboard key creator. I've already tested OpenCV and Magick++ functions but the result was not so good. Can anyone help me with this?
This is a sample of one code to create a rounded corner with Magick++ library
void create_rounded_image (int size, int border) {
Magick::Image image_bk (Magick::Geometry (size, size), Magick::Color ("black"));
image_bk.strokeColor ("white");
image_bk.fillColor ("white");
image_bk.strokeWidth(1);
image_bk.draw (DrawableCircle(size, size, size*0.3, size*0.3));
image_bk.write ("rounded.png");
}
This is the result I'm getting
This is the result I'm looking for

Googling some online documentation, I found:
strokeAntiAlias - bool - Enable or disable anti-aliasing when drawing object outlines.
I suggest:
image_bk.strokeAntiAlias(true);

Expanding on Lamar's answer. Magick::Image.strokeAntiAlias and Magick::DrawableStrokeAntiAlias is what you want. But I would suggest using std::list<Drawable> to generate a context stack. This would allow your application to manage what-will-be-drawn independently of image i/o.
using namespace Magick;
size_t size = 405;
size_t border = 6;
std::list<Drawable> ctx;
ctx.push_back(DrawableStrokeAntialias(MagickTrue));
ctx.push_back(DrawableStrokeColor("#CAF99B"));
ctx.push_back(DrawableStrokeWidth(border));
ctx.push_back(DrawableFillColor("#68C77B"));
ctx.push_back(DrawableCircle(size*0.75, size*0.25, size*0.33, size*0.66));
Image image_bk( Geometry(size, size), Color("white"));
image_bk.draw(ctx);

Related

Antialiasing of existing texture

I have a lot of pre-generated images (same size) that consist of curved lines and a colorful fill. The problem is that these lines are not smooth:
Questions: using a shader, how to make all curves more smoother in a given texture?
Sorry for not offering my own solution, I'm very new to shaders and haven't been able to solve this problem yet. I import pictures (textures) into the shader from p5.js.
let img, theShader, pg;
function preload() {
img = loadImage('texture.jpg');
}
function setup() {
createCanvas(600,800);
pixelDensity(1);
pg = createGraphics(600, 800);
pg.pixelDensity(1);
theShader = pg.createShader(vert, frag);
pg.texture(img);
**
}
function draw() {
**
pg.shader(theShader);
theShader.setUniform('u_resolution', [pg.width, pg.height]);
theShader.setUniform('u_texture', pg);
pg.rectMode(CENTER);
pg.noStroke();
pg.rect(0, 0, pg.width, pg.height);
image(pg, 0,0, width, height);
**
}
You can try to apply some FXAA to reduce jagged edges but you can't just change arbitrary features (like line width) in a pregenerated image without writing some rather sophisticated custom filtering. This is basically the worst step in the pipeline to try to increase image quality, if at all possible you should try to get better source material: a higher resolution render, vector image format (svg) or straight up recreate the output.

C++ Get GDI raw text from another Win32 application

I'm using the UI Automation C++ library to get text data from another GUI application.
If the GUI application is developed using a framework that support UI Automation (WinForm, WPF, ...), it is very easy to get the text.
This is an example using the Inspect tool of UI Automation SDK:
Here, test with CCleaner Free application, it can get the text "Microsoft Edge"
We can also using Win32 API to send some message (Send Message) to get text, example: WM_GETTEXT, LVM_GETITEMTEXT, ...
But, I can't get the text from following element:
The whole header area is just an element only, and I can't get the text inside it.
First, I think it is just an image, but it is not. This is the result of using Ranorex Spy:
The plugin that Ranorex using to get text is GDI RawText Plug-In:
For some older technologies like VB6.0, Delphi or MFC based
applications, Ranorex has only limited support in addressing UI
elements in a robust way. With the GDI RawText Plug-In Ranorex
increases object recognition for controls which use the Windows GDI
drawing mechanism to display text on screen.
So, is there any tutorial about getting text from Windows GDI drawing in another application? Currently, I can't found any resource about it
PS: First, I think it use some OCR library to recognize text from image, but it get the text very fast, not look like using OCR library.
Ranorex is a commercial tool, so I think they will not let me know what library that they implement the plugin if I ask them
Update 1:
I capture the header bar of CCleaner application to Paint, and use Ranorex Spy to get text from the image (if it use some OCR library):
There is no RawText inside the selected element, so it does not use OCR to get the text
Update 2:
I write some simple MFC application to test:
void CMFCApplication1Dlg::OnPaint()
{
CPaintDC dc(this);
CRect rcText(20, 20, 300, 300);
wchar_t text[36];
wsprintf(text, L"Hello world");
dc.SetBkColor(RGB(255, 255, 255));
dc.DrawText(text, &rcText, DT_LEFT);
CDialogEx::OnPaint();
}
Using Spy++:
Using Inspect:
Using Ranorex Spy:
Update 3
Try set background color to black as well:
void CMFCApplication1Dlg::OnPaint()
{
CPaintDC dc(this);
CRect rcText(20, 20, 300, 300);
wchar_t text[36];
wsprintf(text, L"Hello world");
dc.SetBkColor(RGB(0, 0, 0));
dc.DrawText(text, &rcText, DT_LEFT);
CDialogEx::OnPaint();
}
So, no OCR engine can be used here. But this is the result of using Ranorex Spy:
Here's how you can quickly figure out if Ranorex uses OCR. Take a screenshot of CCleanerFree and paste it to mspaint and then run Ranorex on mspaint window to see if it can read text.
Here's how to detect if Ranorex uses winapi hooks for DrawText to see what text some app is drawing. Create a simple windows app and DrawText manually (preferably draw black text on black background to eliminate OCR possibility). If Ranorex reads it then they use winapi hooks to read your text.
Here's how read text with OCR.
OCR is pretty fast, it doesn't take seconds to process simple screen text. You could take screenshot of that window and process specific area of interest for you. I used ocrad for similar task and it worked out great.
Here's sample code you could try:
#include <stdint.h>
#include <string>
#include "ocradlib.h"
std::string image_to_text(uint8_t *data, int width, int height)
{
OCRAD_Pixmap pixmap = { 0 };
pixmap.data = data;
pixmap.width = width;
pixmap.height = height;
pixmap.mode = OCRAD_greymap; // OCRAD_greymap --> 1 byte per pixel; 256 level greymap
std::string ret;
OCRAD_Descriptor * const ocrdes = OCRAD_open();
if (!ocrdes || OCRAD_get_errno(ocrdes) != OCRAD_ok)
{
OCRAD_close(ocrdes);
fprintf(stderr, "not enough memory.\n");
return ret;
}
if (OCRAD_set_image(ocrdes, &pixmap, false) < 0)
{
const OCRAD_Errno ocr_errno = OCRAD_get_errno(ocrdes);
OCRAD_close(ocrdes);
return ret;
}
if (OCRAD_set_threshold(ocrdes, -1) < 0 || // auto threshold
OCRAD_recognize(ocrdes, false) < 0) // no layout
{
const OCRAD_Errno ocr_errno = OCRAD_get_errno(ocrdes);
OCRAD_close(ocrdes);
return ret;
}
const int blocks = OCRAD_result_blocks(ocrdes);
for (int b = 0; b < blocks; ++b)
{
const int lines = OCRAD_result_lines(ocrdes, b);
for (int l = 0; l < lines; ++l)
{
const char * s = OCRAD_result_line(ocrdes, b, l);
if (s && s[0])
ret += s;
}
if (b + 1 < blocks)
ret += '\n';
}
OCRAD_close(ocrdes);
return ret;
}
note that this code uses grayscale pixmap, e.g. 1 byte per pixel rectangle. You can try to change the code to use other image types:
/* OCRAD_Pixmap.data is a pointer to image data formed by "height" rows
of "width" pixels each.
The format for each pixel depends on mode like this:
OCRAD_bitmap --> 1 byte per pixel; 0 = white, 1 = black
OCRAD_greymap --> 1 byte per pixel; 256 level greymap (0 = black)
OCRAD_colormap --> 3 bytes per pixel; 16777216 colors RGB (0,0,0 = black) */
enum OCRAD_Pixmap_Mode { OCRAD_bitmap, OCRAD_greymap, OCRAD_colormap };
There are also other libraries that may provide better quality for more complex images, but for simple text like that ocrad was perfect for me.
To read text using WinAPI hooks
Read some tutorials to understand how that works. For example Hooks Overview on MSDN.
Here's a tutorial that shows how that can be done using EasyHook: EasyHook - Installing a remote hook using EasyHook with C++. Note that there are multiple functions that draw text in WinAPI, perhaps you'll need to hook one or all of them depending on your needs: DrawText, TextOut, ExtTextOut, ExtTextOutWarp (and others).

Change the unit for setting position in TextOut, C++

I'm currently working on a printing plugin with C++, and starting working with TextOut to print the text I want. It works great, but apparently, the positions that TextOut uses as params are in pixels. Is there a way to set them to be in cm or mm? or any other?.
Well, it's pretty simple. The coordinates are not in pixels, but they are in the coordinates of your mapping mode. It just so happens that the default mapping mode of a DC is MM_TEXT which has each coordinate unit to be one pixel on the device.
Change your mapping mode using SetMapMode() to the coordinate system you prefer to use. You can also play with window extents, viewport extents, and origins to customize it however you want. You might want to look at the documentation for SetMapMode() and the MM_LOMETRIC (or MM_HIMETRIC) mapping mode.
There should be special handling implemented for printing. Basically, you need to perform conversion based on HIMETRIC units. The paper size is in HIMETRIC units.
Here is the code that will help you get started (MFC-based):
if (pDC->IsPrinting())
{
// printable area in millimeters
int nWidth = pDC->GetDeviceCaps(HORZSIZE);
int nHeight = pDC->GetDeviceCaps(VERTSIZE);
CDC ScreenDC;
ScreenDC.CreateIC(_T("DISPLAY"), NULL, NULL, NULL);
int nPixelsPerInchX = ScreenDC.GetDeviceCaps(LOGPIXELSX);
int nPixelsPerInchY = ScreenDC.GetDeviceCaps(LOGPIXELSY);
// paper size is in HIMETRIC units. we need to convert
CSize PaperSize(MulDiv(nWidth,nPixelsPerInchX*100,HIMETRIC_PER_INCH),
MulDiv(nHeight,nPixelsPerInchY*100,HIMETRIC_PER_INCH));
// now we need to calculate zoom ratio so the layer content fits on page
double fZoomX = (double)PaperSize.cx/(double)m_DocSize.cx;
double fZoomY = (double)PaperSize.cy/(double)m_DocSize.cy;
m_PrintZoom = min(fZoomX, fZoomY);
ResetViewSize(TRUE);
if (pDC->IsKindOf(RUNTIME_CLASS(CPreviewDC)))
{
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(nPixelsPerInchX, nPixelsPerInchY);
pDC->SetViewportExt(pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSY));
pDC->SetViewportOrg(0,0);
pDC->SetWindowOrg(0,0);
}
}

Issue with texture loading using the DevIl library

I am working with the DevIl library and trying to use it to load a texture to OpenGL to apply to a sprite. The code is directly out of the C# Game Programming for Serious Game Design book (if that helps). The problem I'm having is with the Il.ilLoadImage call. Even when I pass it null, it doesn't throw an image not found error, and the sprite just shows up dark grey (instead of white) when the form pops up.
public void LoadTexture(string textureId, string path)
{
int devilId = 0;
Il.ilGenImages(1, out devilId);
Il.ilBindImage(devilId);
if (!Il.ilLoadImage(path))
{
System.Diagnostics.Debug.Assert(false, "Could not open file [" + path + "].");
}
//Flip the files before passing them to OpenGl
Ilu.iluFlipImage();
int width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH);
int height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT);
int openGLId = Ilut.ilutGLBindTexImage();
System.Diagnostics.Debug.Assert(openGLId != 0);
Il.ilDeleteImages(1, ref devilId);
_textureDatabase.Add(textureId, new Texture(openGLId, width, height));
}
DevIL is, rather nonsensically, based on OpenGL's API and general structure. As such, the typical way that errors are reported is with ilGetError. If you want to make sure a function succeeded or not, you should use 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.