How to use stock-objects with GDI+ - c++

I was using the following pattern to record an enhanced meta-file for a later playback:
POINT pts[] = {
//.....
};
::SelectObject(hEnhDC, ::GetStockObject(LTGRAY_BRUSH));
::Polygon(hEnhDC, pts, _countof(pts));
Now I'm forced to use GDI+ to provide anti-aliasing, so I'm trying to convert that code sample:
Gdiplus::Point pts[] = {
//...
};
Gdiplus::Graphics grx(hEnhDC);
Gdiplus::Pen pen(Gdiplus::Color(255, GetRValue(clrPen), GetGValue(clrPen), GetBValue(clrPen)), PEN_THICKNESS);
grx.FillPolygon(&brush, pts, _countof(pts));
grx.DrawPolygon(&pen, pts, _countof(pts));
The issue is how do I convert a stock-object HBRUSH from ::GetStockObject(LTGRAY_BRUSH) to GDI+ Brush object?
EDIT: Guys, thank you for all your suggestions. And I apologize for not providing more details. This question is not about getting the RGB color triplet from the stock brush. I can do all that with the GetSysColor function, or with the LOGBRUSH like you showed below.
The trick lies in the first sentence above. I am recording an enhanced metafile that may be played on a separate computer, so I cannot hard-code colors into it.
Let me explain. Say, the first GDI example (let's simplify it down to a triangle with a gray fill):
POINT pts[] = {
{100, 100,},
{100, 120,},
{120, 100,},
};
::SelectObject(hEnhDC, ::GetStockObject(LTGRAY_BRUSH));
::Polygon(hEnhDC, pts, _countof(pts));
If I then call GetEnhMetaFileBits on that meta-file, I'll get the following data:
So as you see the EMR_SELECTOBJECT object in that recorded meta-file specifies the LTGRAY_BRUSH = 0x80000001, which will be properly substituted for the color when that meta-file is played on the target system.
And that's what I'm trying to achieve here with GDI+. For some reason it only seems to support hard-coded color triplets in its Brush class. That's why I asked.
Otherwise, one solution is to parse the enhanced meta-file's raw data. (For GDI+ it is a much more complex structure though, that also involves parsing EMR_GDICOMMENT objects.) And then substitute the needed color on the target system before the GDI+ meta-file is played. But it involves writing a lot of code, which I was trying to avoid at this stage ...

I’m afraid you can’t easily convert.
A simple workaround is create GDI+ solid brush with the same color.
See this spec for color values of GDI stock objects, that particular brush has color #C0C0C0

Related

How to use CImg functions with pixel data?

I am using Visual Studio and looking to find a useful image processing library that will take care of basic image processing functions such as rotation so that I don't have to keep coding them manually. I came across CImg and it supports this, as well as many other useful functions, along with interpolation.
However, all the examples I've seen show CImg being used by loading and using full images. I want to work with pixel data. So my loops are the typical:
for (x=0;x<width; x++)
for (y=0;y<height; y++)
I want to perform bilinear or bicubic rotation in this instance and I see CImg supports this. It provides a rotate() and get_rotate function, among others.
I can't find any examples online that show how to use this with pixel data. Ideally, I could simply pass it the pixel color, x, y, and interpolation method, and have it return the result.
Could anyone provide any helpful suggestions? If CImg is not the right library for this type of this, could anyone recommend a simple, light-weight, easy-to-use one?
Thank you!
You can copy pixel data to CImg class using iterators, and copy it back when you are done.
std::vector<uint8_t> pixels_src, pixels_dst;
size_t width, height, n_colors;
// Copy from pixel data
cimg_library::CImg<uint8_t> image(width, height, 1, n_colors);
std::copy(pixels_src.begin(), pixels_src.end(), image.begin());
// Do image processing
// Copy to pixel data
pixels_dst.resize(width * height * n_colors);
std::copy(image.begin(), image.end(), pixels_dst.begin());

Sprite::createWithTexture with Rect not working as expected

I'm trying to build a sprite from an image. Using Image and Texture2D class and then later creating a sprite from the texture2D.
The image I am loading is 512x512 and I expected both versions of the createWithTexture to behave the same but they don't. Here the code:
Image* image = new Image();
image->initWithImageFile(fileName);
Texture2D* texture = new Texture2D();
texture->initWithImage(image);
//If used this way everything works as expected
Sprite* spr= Sprite::createWithTexture(texture);
//If used with a Rect weird result occurrs.
Sprite* spr= Sprite::createWithTexture(texture,Rect(0,0,512,512));
spr->setAnchorPoint(Vec2(0,0));
spr->setPosition(Vec2(0,0));
spr->setScale(1.0f,1.0f);
this->addChild(spr);
Here the result of the first one using a Rect:
And here the Second version without a Rect:
Do anybody know what is happening? I need to use the method that uses the rect because I will be creating a bunch of sprites from this image in the future.
Edit1: After debugging both versions of the sprite. I have noticed that the one created without the Rect shows a rect of 0,0,240,240. Instead of 0,0,512,512 as I provided. Why 240?
Thanks in advance.
I managed to figure out what was happening. Cocos2D-x uses director->setContentScaleFactor and glview->setDesignResolutionSize as a way to make things easier for multi resolution/device games. When you build the Rect to get a part (or full) texture you must have into account the CC_CONTENT_SCALE_FACTOR() macro, in order to get correct target coordinates.
This can be checked at this link: http://www.cocos2d-x.org/wiki/Multi_resolution_support
Cheers.
If your vecSize is bigger than the image's size, the image will be out of shape.
So if you don't know the image's real size, don't set it.

Improving Grabcut in OpenCV

I just implemented the GrapCV-algorithm (OpenCV, C++, Visual Studio 12):
grabCut( *image, mask, rect, bgdModel, fgdModel, 1, GC_INIT_WITH_MASK
);
I used it to segment to following picture:
My result is this:
My question is: How i am able now to improve the algorithm, so that only the both players can be seen? My first idea was a change concerning the colors depth, but i don't know how to send it to "grabCut". Or are there other ways?
In the folder opencv2.4.6/samples/cpp, there are a lot of files that demonstrate the use of some classical algorithms. There is a file called grabcut.cpp which tells you how to apply this algorithm to your application in detail. So what you need to do is just embed this file into your program.
If you have any other questions, just debug with the grabcut.cpp and you would see how it works in detail. And if you wanna implement it by yourself. you need to change the function with new parameter GC_EVAL or GC_INIT_WITH_MASK.
grabCut(image, // input image
mask, // segmentation mask
rect,// rectangle containing foreground
bgModel,fgModel, // models
2, // number of iterations
GC_INIT_WITH_RECT); // use rectangle

Proper Measurement of Characters in Pixels

I'm writing a text box from scratch in order to optimize it for syntax highlighting. However, I need to get the width of characters in pixels, exactly, not the garbage Graphics::MeasureString gives me. I've found a lot of stuff on the web, specifially this, however, none of it seems to work, or does not account for tabs. I need the fastest way to measure the exact dimensions of a character in pixels, and tab spaces. I can't seem to figure this one out...
Should mention I'm using C++, CLR/CLI, and GDI+
Here is my measuring function. In another function the RectangleF it returns is drawn to the screen:
RectangleF TextEditor::MeasureStringWidth(String^ ch, Graphics^ g, int xDistance, int lineYval)
{
RectangleF measured;
Font^ currentFont = gcnew Font(m_font, (float)m_fontSize);
StringFormat^ stringFormat = gcnew StringFormat;
RectangleF layout = RectangleF(xDistance,lineYval,35,m_fontHeightPix);
array<CharacterRange>^ charRanges = {CharacterRange(0,1)};
array<Region^>^ strRegions;
stringFormat->FormatFlags = StringFormatFlags::DirectionVertical;
stringFormat->SetMeasurableCharacterRanges(charRanges);
strRegions = g->MeasureCharacterRanges(ch, currentFont, layout, stringFormat);
if(strRegions->Length >= 1)
measured = strRegions[0]->GetBounds(g);
else
measured = RectangleF(0,0,0,0);
return measured;
}
I don't really understand what MeasureCharacterRanges layoutRect parameter does. I modified the code from Microsofts example to only work with, or only measure, one character.
You should not be using Graphics for any text rendering.
Starting with .NET Framework 2.0 use of Graphics.MeasureString and Graphics.DrawString was deprecated in favor of a newly added helper class TextRenderer:
TextRenderer.MeasureText
TextRenderer.DrawText
The GDI+ text renderer has been abandoned, and hasn't gotten any improvements or fixes for over 10 years; as well as being software rendered.
GDI rendering (which TextRenderer is a simple wrapper of) is hardware accelerated, and continues to get rendering improvements (ligatures, Uniscribe, etc).
Note: GDI+ text rendering is wrapped by Graphics.DrawString and MeasureString
Here's a comparison of the measure results of Graphics and TextRenderer:
The GDI+ measurements aren't "wrong", they are doing exactly what they intend - return the size that the text would be if it were rendered as the original font author intended (which you can achieve using Anti-alias rendering):
But nobody really wants to look at text the way the font designer intended, because that causes stuff to not line-up on pixel boundaries - making the text too fuzzy (i.e. as you see on a Mac). Ideally the text should be snapped to line up on actual pixel boundaries (i.e. Windows' Grid Fitting)
Bonus Reading
See my answer over here, with more information.
There's MeasureCharacterRanges that is like MeasureString, but more powerful and more accurate (and also slower).

Converting image to pixmap using ImageMagic libraries

My assignment is to get "images read into pixmaps which you will then convert to texture maps". So for the pixmap part only, hear me out and tell me if I have the right idea and if there's an easier way. Library docs I'm using: http://www.imagemagick.org/Magick++/Documentation.html
Read in image:
Image myimage;
myimage.read( "myimage.gif" );
I think this is the pixmap I need to read 'image' into:
GLubyte pixmap[TextureSize][TextureSize][3];
So I think I need a loop that, for every 'pixmap' pixel index, assigns R,G,B values from the corresponding 'image' pixel indices. I'm thinking the loop body is like this:
pixmap[i][j][0] = myimage.pixelColor(i,j).redQuantum(void);
pixmap[i][j][1] = myimage.pixelColor(i,j).greenQuantum(void);
pixmap[i][j][2] = myimage.pixelColor(i,j).blueQuantum(void);
But I think the above functions return Quantums where I need GLubytes, so can anyone offer help here?
-- OR --
Perhaps I can take care of both the pixmap and texture map by using OpenIL (docs here: http://openil.sourceforge.net/tuts/tut_10/index.htm). Think I could simply call these in sequence?
ilutOglLoadImage(char *FileName);
ilutOglBindTexImage(ILvoid);
You can copy the quantum values returned by pixelColor(x,y) to ColorRGB and you will get normalized (0.0,1.0) color values.
If you don't have to stick with Magick++ maybe you can try OpenIL, which can load and convert your image to OpenGL texture maps without too much hassle.