Strange CBitmapRenderTarget::GetBitmap API - Direct2D MFC - mfc

I am completely confused by MFC wrapper for directd2d intefaces. Take a look at the following for example:-
BOOL CreateCompatibleRenderTarget(
CBitmapRenderTarget& bitmapTarget,
CD2DSizeF sizeDesired = CD2DSizeF(0.,
0.),
CD2DSizeU sizePixelDesired = CD2DSizeU(0,
0),
D2D1_PIXEL_FORMAT* desiredFormat = NULL,
D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options = D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE
);
bitmapTarget When this method returns, contains the address of a
pointer to a new bitmap render target. This parameter is passed
uninitialized.
I am completely puzzled by what I should pass to the the function. As on contrary to documentation it receives the object and not the pointer to the uninitialized as in Directd2d IDL. And the object must be initialized.
Now one can tell that CBitmapRenderTarget is an object created with default contstructor. However this is not working with the GetBimap member of the CBitmapRenderTarget which also follows the same patter in documentation:-
BOOL GetBitmap(
CD2DBitmap& bitmap
);
bitmap When this method returns, contains the valid bitmap for this
render target. This bitmap can be used for drawing operations.
However the CD2DBitmap DOES NOT HAVE the default ctor, so I cannot create the object in a first place. The question is how do I correctly call to GetBitmap of CBitmapRenderTarget API. How do I create the uninitialized CD2DBitmap object ???

I encountered same issue. Looking at the CD2DBitmap implementation, there's no constructor without argument, and one with the only the parent CRenderTarget* ans an argument, but it's protected so not usable from outside. So apparently the only way is to use one of the 3 public constructors which are only crating Bitmap from existing resources (from handle, resource id or file path).
On my case, as a workaround because my intent is to replace this bitbap by a new one (GetBitmap), I created the Bitamp from a PNG file stored on my resources :
CD2DBitmap bitmap(GetRenderTarget(), (UINT)IDB_LOGO_PETIT, _T("PNG"));
m_pTraceRenderTarget->GetBitmap(bitmap);
But you can use any other CD2DBitmap constructor:
CD2DBitmap(CRenderTarget* pParentTarget, UINT uiResID, LPCTSTR lpszType = NULL, CD2DSizeU sizeDest = CD2DSizeU(0, 0), BOOL bAutoDestroy = TRUE);
CD2DBitmap(CRenderTarget* pParentTarget, LPCTSTR lpszPath, CD2DSizeU sizeDest = CD2DSizeU(0, 0), BOOL bAutoDestroy = TRUE);
CD2DBitmap(CRenderTarget* pParentTarget, HBITMAP hbmpSrc, CD2DSizeU sizeDest = CD2DSizeU(0, 0), BOOL bAutoDestroy = TRUE);

Related

SDL2 - Why is a text flickering if my color is not initialized as a private variable?

I try to present text with the following code:
void Text::display(SDL_Renderer *renderer, int x, int y) {
// pos is an SDL_Rect and font is a TTF_Font
pos.x = pos.w = x;
pos.y = pos.h = y;
SDL_Surface *surface = TTF_RenderText_Solid(font, text.c_str(), color);
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_QueryTexture(texture, NULL, NULL, &pos.w, &pos.h);
SDL_RenderCopy(renderer, texture, NULL, &pos);
SDL_FreeSurface(surface);
SDL_DestroyTexture(texture);
}
In my Text class. At first I had an uninitialized SDL_Color color in my Text::display() method which let me present a text on the screen. (renderer is passed from main + coordinates x,y). But I decided to make my SDL_Color color a private variable in the class Text instead. And what is weird to me is that as a private variable the text was flickering once I presented it, but if I set it as a public variable or placed it in the method the text was not flickering. Or if I initialized it as a private variable (SDL_Color color = {255, 255, 255}).
My question is if there was only pure luck that it worked when color was uninitialized as a public or method variable or if they are treated differently? When I initialized color in the constructor it was also flickering if color was private.
My main method:
void fpsCap(Uint32 starting_tick) {
if ((1000 / fps) > SDL_GetTicks() - starting_tick) {
SDL_Delay(1000 / fps - (SDL_GetTicks() - starting_tick));
}
}
int main(int argv, char** args) {
// Create renderer, window, etc
while (true) {
SDL_RenderClear(renderer);
Text *txt = new Text("hello");
txt->display(gui->getRenderer(), 0, 0);
SDL_RenderPresent(renderer);
}
}
The value of the private member is not initialized, and so it gets random/garbage value. As you allocate new Text instance for every frame. You allocate on heap (every time in a new place), so it is sort of guaranteed to actually be garbage.
Why it didn't flicker in other cases?
Public member: my guess is that you also made it static? Static variables are zero-initialized (contrary to member variables).
Local variable: local variables are not zeroed and are considered to contain garbage, but as they are stack-allocated, they are likely to get identical piece of garbage every single time in the given place.
Private member assigned in the constructor: that is unexpected. Are you sure that it was the same constructor that is actually used? And that it was the same variable? Perhaps some name shadowing prevented the value from actually landing where our should?
Tangential:
You leak a Text instance every loop. You should delete every object created with new, or better, avoid using new altogether. Use unique_ptr/make_unique instead, or just local variables (much better in this case).
EDIT to answer questions about new:
In modern C++ you almost never need to use new.
If you have an object that is used only during the execution of the function, the natural thing to do is to keep it directly (i.e. not through a pointer), in this case defining the variable as
Text txt("hello");
This is a similar idiom to Java's Text txt = new Text("hello");, but the result variable is an instance itself, and not a reference to it.
If you want to create an instance that you immediately pass as an argument of type Text or const Text&, you can create it as temporary like SomeFunction(Text("hello")) (note the lack of new, it's just the class name).
If you need heap allocation, smart pointers (std::unique_ptr and std::shared_ptr) created with std::make_unique and std::make_shared are
strongly preferred, as they guard from many common pitfalls such as memory leaks and dangling pointers, at least as long as you keep hold of the smart pointer itself. std::shared_ptr is probably closest thing standard C++ has to Java reference, although it's not garbage collected, so if you make a cycle of them, they won't be ever freed.
You could replace your Text *txt = new Text("hello"); with
auto txt = std::make_unique<Text>("hello");
to get the same behavior, but with the Text getting destroyed and deallocated at the end of the block.

Can file mapping object and file object be used interchangeably?

Say I want to a generated a wrapper function to CreateFile function
This new function will not generate a real file on the disk but create file mapping object and return a handle to the new object.
I've looked at this example, Creating Named Shared Memory, and tried to implement my function:
#define BUF_SIZE 256
TCHAR szName[] = TEXT("Global\\MyFileMappingObject");
HANDLE MyCreateFile()
{
HANDLE hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
BUF_SIZE, // maximum object size (low-order DWORD)
szName); // name of mapping object
return hMapFile;
}
Problem
This looked OK to me, however, when tried using the returned HANDLE in ReadFile function I got error code 6 The handle is invalid.
Question
Can file mapping object and file object be used interchangeably? If so, then what is the issue with my code? If not, any idea how can such function be implemented?
The handle that CreateFileMapping returns is a file mapping object and not that of regular files. CreateFileMapping is part of a family of functions which allows access to files as if they are memory or array of bytes.
One way, would be to also call MapViewOfFile(with appropriate parameters) inside your MyCreateFile() function and let MyCreateFile() function return the pointer which is returned by MapViewOfFile. Now you can write your MyReadFile() and MyWriteFile() using this pointer.
It would be more nice if you can create a class and include all these functions inside it.
class CustomFile
{
private:
LPVOID *m_pData;
public:
//m_pData is initialized here via CreateFileMapping and
//MapViewOfFile.
CreateFile(...);
//m_pData is used here.
ReadFile(...);
WriteFile(...);
};

How to release the 'external' pixel data of a Bitmap properly in c++/cli

In my situation, the Drawing::Bitmap is created using a pointer to the pixel data. On the MSDN you can find a constructor doing exactly this:
Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0);
From the documentation it is clear this constructor creates just the header and required things around the provided data. It is also noted, the caller have to release the pixel data array.
The caller is responsible for allocating and freeing the block of memory specified by the scan0 parameter. However, the memory should
not be released until the related Bitmap is released.
My problem is, if I pass a Bitmap with linked pixel data to another class, then I'm not able to release the underlying data. See my example bellow:
Drawing::Image^ FirstClass::GetImage(std::string ImagePath)
{
IplImage* cvImg = cvLoadImage(ImagePath.c_str());
Drawing::Image^ ManagedImg = gcnew Bitmap(
cvImg->width,
cvImg->height,
cvImg->widthStep,
Drawing::Imaging::PixelFormat::Format24bppRgb,
(System::IntPtr)cvImg->imageData);
return ManagedImg;
}
Void SecondClass::RefreshImage()
{
// Release the last image first
if (MyImage!=nullptr)
{
???
}
MyImage = GetImage(...);
}
A simple workaround is to pass, the IplImage* to the SecondClass, create the managed Bitmap there and then call cvReleaseImage(&Native_MyImage); there. However this works, I really want to know how to do it properly without passing IplImage*.
You need to pass pointers to pixels in some way.
For me, a better way would be to wrap IplImage* and ManagedImg into a single class that manages both of them. The destructor of the class would be responsible for destroying ManagedImg and then for calling cvReleaseImage() for stored value of the IplImage*. And then your GetImage function could return a pointer to this wrapper class, not to Drawing::Image.

C++ *LPCSTR weird scope error

I currently have a class called TextureObject. In the creation function I create the texture, and assign a LPCSTR in the class to a parameter given in the function. When I return that LPCSTR later, it returns in an unexpected manner.
Some type names and functions are from DirectX 11, just ignore them.
Code:
The h File:
class TextureObject
{
public:
ID3D11ShaderResourceView *pTexture;
LPCSTR GetFilename() const { return *FFilename; }
bool IsNotNull;
void CreateTexture(ID3D11Device &dev,LPCSTR Filename);
void ReCreate(ID3D11Device &dev);
void Release();
int relativeId;
private:
LPCSTR *FFilename;
};
The cpp file:
void TextureObject::CreateTexture(ID3D11Device &dev,LPCSTR Filename)
{
D3DX11CreateShaderResourceViewFromFile(
&dev, // the Direct3D device
Filename, // load Wood.png in the local folder
NULL, // no additional information
NULL, // no multithreading
&pTexture, // address of the shader-resource-view
NULL); // no multithreading
FFilename = new LPCSTR(Filename);
IsNotNull = true;
}
void TextureObject::ReCreate(ID3D11Device &dev)
{
CreateTexture(dev, *FFilename);
}
When using vs 2012 debugger in the CreateTexture function, the Filename debugger values are:
0x0a06fed0 "C:\Users\Utilizador\Desktop\particle.png"
Which is perfect for me! When i assign the class's FFilename:
FFilename = new LPCSTR(Filename);
It's ok. When I check the value of FFilename within the scope of this function, it's the same value of the Filename. But when i use GetFilename, things start getting crazy:
= 0x0a06fed0 "îþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþîþü =I.C"
Mmm, I just met you, and this is crazy, but... Here's my value. mKay?
Well, please help me. Thank You
You are not copying the string. You are copying the pointer. I think you probably wanted to copy the string, because you cannot guarantee the caller's pointer will still reference valid data at a later time.
LPCSTR is just a const char*. There's probably a corresponding windows call, but I would just use strdup to copy the string.
Define FFilename as LPCSTR:
LPCSTR FFilename;
And then:
void TextureObject::CreateTexture(ID3D11Device &dev,LPCSTR Filename)
{
D3DX11CreateShaderResourceViewFromFile(
&dev, // the Direct3D device
Filename, // load Wood.png in the local folder
NULL, // no additional information
NULL, // no multithreading
&pTexture, // address of the shader-resource-view
NULL); // no multithreading
FFilename = strdup(Filename);
IsNotNull = true;
}
void TextureObject::ReCreate(ID3D11Device &dev)
{
CreateTexture(dev, FFilename);
}
Since you are using C++, you are free to use std::string instead, which will be cleaned up automatically when the object is destroyed.
When you create your pointer FFilename, you're initializing it with another pointer. That's not going to make a copy of the string, now you have two pointers pointing to the same thing. Presumably that thing is a temporary object, and when you go to look at it later it's no longer valid.
I'd suggest using std::string for this instead, it's much less error prone. The c_str method can get a LPCSTR at any time.
As marcin_j said, use std::[w]string. As for the line:
FFilename = new LPCSTR(Filename);
It just allocates 4 bytes for a pointer and initializes it to the filename string. It doesn't actually copy the string. So you can still use the string, but it is owned by whoever calls TextureObject::CreateTexture, and may be released while TextureObject is still referencing it.
Change the class to:
class TextureObject
{
public:
// ...all the same stuff as before...
private:
wstring FFilename; // it's better to store filenames as Unicode
};
And the methods to:
void TextureObject::CreateTexture(ID3D11Device* dev, const wstring& Filename)
{
D3DX11CreateShaderResourceViewFromFile(
dev, // the Direct3D device
Filename.c_str(), // load Wood.png in the local folder
NULL, // no additional information
NULL, // no multithreading
&pTexture, // address of the shader-resource-view
NULL); // no multithreading
FFilename = Filename;
IsNotNull = true;
}
void TextureObject::ReCreate(ID3D11Device* dev)
{
CreateTexture(dev, FFilename.c_str());
}

Fetching CBitmap out of CImageList

I inserted bitmaps in CImageList in one Function and needed to change some of the images later in another function. But I am unable to extract the CBitmap. The code goes something like this:
CBitmap GetIndividualBitmap(CImageList oImgList, int nBmpNo)
{
IMAGEINFO imgInfo;
imagelist.GetImageInfo(index,imgInfo);
CBitmap bmp;
bmp.FromHandle(imgInfo.hbmImage);
return bmp;
}
However all I get is a black screen. Could anyone please point out where I am going wrong?
Ok there are a number of errors in your code
1)You are passing the Image list by object which means it will copy it across. Passing it by reference is a far better plan.
2) You are not passing a pointer to the IMAGEINFO struct into the GetImageInfo.
3) You misunderstand how "FromHandle" works. FromHandle is a static function that returns a pointer to a Bitmap. In your code you are calling the function and then ignoring the CBitmap* returned and returning a copy of your newly constructed object (ie it contains nothing) which results in your black screen.
Taking all those into account you should have code that looks like this:
CBitmap* GetIndividualBitmap(CImageList& oImgList, int nBmpNo)
{
IMAGEINFO imgInfo;
oImgList.GetImageInfo( nBmpNo, &imgInfo );
return CBitmap::FromHandle( imgInfo.hbmImage );
}