how draw an image?

ok... these question isn't the first time and i have some problems: why the image isn't drawed?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class image
{

    public:
    BITMAP bitmap;
    HBITMAP hBitmap;
    HDC hdcMem;
    HDC oldBitmap;

    image()
    {
        hdcMem = CreateCompatibleDC(GetDC(NULL));
        oldBitmap =(HDC) SelectObject(hdcMem, hBitmap);
    }

    ~image()
    {
        SelectObject(hdcMem, oldBitmap);
        DeleteDC(hdcMem);
    }

    void FromFile(string strFile)
    {
        hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL),
        strFile.c_str(),IMAGE_BITMAP,LR_DEFAULTSIZE,LR_DEFAULTSIZE,LR_LOADFROMFILE);
         oldBitmap =(HDC) SelectObject(hdcMem, hBitmap);
         GetObject(hBitmap, sizeof(bitmap), &bitmap);

    }

    void DrawImage(HDC DestinationHDC)
    {
         BitBlt(DestinationHDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight,hdcMem, 0, 0, SRCCOPY);
         MessageBox(NULL,"error: BITBLT", to_string(GetLastError()).c_str(), MB_OK);

    }
};

//how i use it:
image img;
    img.FromFile("C:\\Users\\Joaquim\\Pictures\\sample_640×426.bmp");
//inside a loop:
img.DrawImage(WindowHDC);

//how i get the HDC:
HDC WindowHDC=GetDC(GetConsoleWindow());

i test the erro message and it's '87':
1
2
3
4
5
void DrawImage(HDC DestinationHDC)
    {
         BitBlt(DestinationHDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight,hdcMem, 0, 0, SRCCOPY);
         MessageBox(NULL,"error: BITBLT", to_string(GetLastError()).c_str(), MB_OK);
    }

error id:
"ERROR_INVALID_PARAMETER

87 (0x57)

The parameter is incorrect."
what i'm doing wrong?

Works OK here if you proceed to a main().
I put the bitmap dimensions in void FromFile.
...
strFile.c_str(),IMAGE_BITMAP,500,500,LR_LOADFROMFILE);
...
and my main
//how i use it:
int main()
{
HDC WindowHDC=GetDC(GetConsoleWindow());
image img;
img.FromFile("circles.bmp");
//inside a loop:
img.DrawImage(WindowHDC);
cin.get();

//how i get the HDC:

}

64 bit g++

Happy New Year.
Last edited on
Happy New Year
i belive why was not working on my pc and worked on yours: the bmp file maybe wasn't compatible. so i use GDIPlus:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include <iostream>
#include <string>
#include <string.h>
#include <windows.h>
#include <math.h>
#include <vector>
#include <gdiplus.h>


using namespace Gdiplus;
using namespace std;

std::string getGdiplusStatusMessage(Status status)
{
    std::string msg = "";

    switch ( status )
    {
    case Ok:
    msg = "Ok: Indicates that the method call was successful.";
    break;
    case GenericError:
    msg = "GenericError: Indicates that there was an error on the method call, which is identified as something other than those defined by the other elements of this enumeration.";
    break;
    case InvalidParameter:
    msg = "InvalidParameter: Indicates that one of the arguments passed to the method was not valid.";
    break;
    case OutOfMemory:
    msg = "OutOfMemory: Indicates that the operating system is out of memory and could not allocate memory to process the method call.";
    break;
    case ObjectBusy:
    msg = "ObjectBusy: Indicates that one of the arguments specified in the API call is already in use in another thread.";
    break;
    case InsufficientBuffer:
    msg = "InsufficientBuffer: Indicates that a buffer specified as an argument in the API call is not large enough to hold the data to be received.";
    break;
    case NotImplemented:
    msg = "NotImplemented: Indicates that the method is not implemented.";
    break;
    case Win32Error:
    msg = "Win32Error: Indicates that the method generated a Win32 error.";
    break;
    case WrongState:
    msg = "WrongState: Indicates that the object is in an invalid state to satisfy the API call. For example, calling Pen::GetColor from a pen that is not a single, solid color results in a WrongState status.";
    break;
    case Aborted:
    msg = "Aborted: Indicates that the method was aborted.";
    break;
    case FileNotFound:
    msg = "FileNotFound: Indicates that the specified image file or metafile cannot be found.";
    break;
    case ValueOverflow:
    msg = "ValueOverflow: Indicates that the method performed an arithmetic operation that produced a numeric overflow.";
    break;
    case AccessDenied:
    msg = "AccessDenied: Indicates that a write operation is not allowed on the specified file.";
    break;
    case UnknownImageFormat:
    msg = "UnknownImageFormat: Indicates that the specified image file format is not known.";
    break;
    case FontFamilyNotFound:
    msg = "FontFamilyNotFound: Indicates that the specified font family cannot be found. Either the font family name is incorrect or the font family is not installed.";
    break;
    case FontStyleNotFound:
    msg = "FontStyleNotFound: Indicates that the specified style is not available for the specified font family.";
    break;
    case NotTrueTypeFont:
    msg = "NotTrueTypeFont: Indicates that the font retrieved from an HDC or LOGFONT is not a TrueType font and cannot be used with GDI+.";
    break;
    case UnsupportedGdiplusVersion:
    msg = "UnsupportedGdiplusVersion: Indicates that the version of GDI+ that is installed on the system is incompatible with the version with which the application was compiled.";
    break;
    case GdiplusNotInitialized:
    msg = "GdiplusNotInitialized: Indicates that the GDI+ API is not in an initialized state. To function, all GDI+ objects require that GDI+ be in an initialized state. Initialize GDI+ by calling GdiplusStartup.";
    break;
    case PropertyNotFound:
    msg = "PropertyNotFound: Indicates that the specified property does not exist in the image.";
    break;
    case PropertyNotSupported:
    msg = "PropertyNotSupported: Indicates that the specified property is not supported by the format of the image and, therefore, cannot be set.";
    break;
    #if (GDIPVER >= 0x0110)
    case ProfileNotFound:
    msg = "ProfileNotFound: Indicates that the color profile required to save an image in CMYK format was not found.";
    break;
    #endif //(GDIPVER >= 0x0110)
    default :
    msg = "Invalid status: Indicates an unknown status was returned.";
    break;
    }
    return msg;
}

std::wstring towstring(const std::string& v)
{
    std::wstring out(v.size()+1,L'\0');

    int size = MultiByteToWideChar(CP_UTF8, 0, v.c_str(), -1, &out[0], out.size());

    out.resize(size-1);
    return out;
}

class image
{
    public:
    BITMAP bitmap;
    HBITMAP hBitmap=NULL;
    HDC hdcimage=CreateCompatibleDC(NULL);
    HBITMAP oldBitmap=NULL;
    ULONG_PTR m_gdiplusToken=NULL;
    Gdiplus::GdiplusStartupInput gdiplusStartupInput=nullptr;
    Image *img=nullptr;
    Gdiplus::Graphics *graphic=nullptr;

public:
    operator HDC()
    {
        return hdcimage;
    }

    operator HBITMAP()
    {
        return hBitmap;
    }

    image()
    {
        if(hBitmap==NULL)
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        hBitmap=CreateCompatibleBitmap(hdcimage,1,1);
        oldBitmap=(HBITMAP)SelectObject(hdcimage, hBitmap);
    }

    image(int Width, int Height)
    {
        if(hBitmap==NULL)
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        hBitmap=CreateCompatibleBitmap(hdcimage,Width,Height);
        oldBitmap=(HBITMAP)SelectObject(hdcimage, hBitmap);
    }

    void Dispose()
    {
        //clear all objects for avoid memory leaks:
        Gdiplus::GdiplusShutdown(m_gdiplusToken);
        SelectObject(hdcimage, oldBitmap);
        DeleteDC(hdcimage);
        DeleteObject(hBitmap);
        if(img!=nullptr) delete img;
        if(graphic!=nullptr) delete graphic;
    }

    ~image()
    {
        Dispose();
    }

    void FromFile(string strFile)
    {
        if(hBitmap==NULL)
            Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
        img=new Image(towstring(strFile).c_str());
        if(img->GetLastStatus()>0)
            MessageBox( NULL,getGdiplusStatusMessage( img->GetLastStatus() ).c_str(),"error message",MB_OK);
        hBitmap=CreateBitmap(img->GetWidth(),img->GetHeight(),1,32,NULL);
        GetObject(hBitmap, sizeof(bitmap), &bitmap);
        SelectObject(hdcimage, hBitmap);
        graphic=new Graphics(hdcimage);
        graphic->DrawImage(img, 0, 0, img->GetWidth(), img->GetHeight());

    }

    void DrawImage(HDC DestinationHDC)
    {
        //Gdiplus::Graphics graphics2(DestinationHDC);
        //graphics2.DrawImage(img, 800, 0, img->GetWidth(), img->GetHeight());
        BitBlt(DestinationHDC, 800,0,img->GetWidth(), img->GetHeight(),hdcimage,0,0,SRCCOPY);
    }
};

the GDIPlus is for only read the file and draw it on HDC.
now i need fix 1 error: if i use 'new', i must 'delete', right?
so why, when i exit the program, i get an error?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Dispose()
    {
        //clear all objects for avoid memory leaks:
        Gdiplus::GdiplusShutdown(m_gdiplusToken);
        SelectObject(hdcimage, oldBitmap);
        DeleteDC(hdcimage);
        DeleteObject(hBitmap);
        if(img!=nullptr) delete img;
        if(graphic!=nullptr) delete graphic;
    }

    ~image()
    {
        Dispose();
    }

error code, on exit: "Process returned -1073741819 (0xC0000005) execution time : 3.916 s
Press any key to continue."
why these error?
delete of null is safe, no need to check that.

does it work if you get rid of the deletes? In that case, one of two things is happening:
- it was already deleted
or
- it was used after deleted.

you will have to run down which it was.

If it does not work with the deletes removed, then that isn't the issue :)
if i remove these 2 lines:
1
2
if(img!=nullptr) delete img;
        if(graphic!=nullptr) delete graphic;

the error don't happens.. tested ;)
the image class is for get the image and use the HDC.. then i can draw the image line a line and pixel a pixel.
why pixel a pixel? for we redraw the image to any angle ;)
Last edited on
Try replacing those 2 lines with these and see what now breaks! Where it now fails is where you're using the memory after delete!

1
2
3
4
5
6
7
8
9
if (img != nullptr) { 
    delete img;
    img = nullptr;
}

if (graphic != nullptr) {
    delete graphic;
    graphic = nullptr;
}

@seeplus (3819) same error:
Process returned -1073741819 (0xC0000005) execution time : 3.359 s
Press any key to continue.
If it 'works' with these lines removed and fails with them in, then you're using one or both after they have been deleted. You'll need to track this down.
maybe is because i have several loops?
what i mean is:
1 - on main() i have 1 loop. these loops end's when i press escape;
2 - on image i have 2 loops for draw the image dot a dot.
when i press the escape, the draw image loop can be working?
or:
the image(graphic ) variable is created inside the main(), so it can be destroyed when exit the program and i'm destroy it again?
if i remove these 2 lines, the error don't happens

I messed about for ages to get this working.
A pixel by pixel picture to screen.
The picture can be .bmp, .png, .jpeg, .giff, .tiff and perhaps a few others.
It is not of great value, but at least I got it working.
The console is set to a little larger than the image (optional of course).
command switches for g++
-std=c++17 -l Gdi32 -l Gdiplus
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <windows.h>
#include<Gdiplus.h>
#include<iostream>
using namespace std;

int Picload(HDC WindowHDC, wchar_t * Picture,int dx=0,int dy=0)
{
   ULONG_PTR TMP; 
   COLORREF colour;
   Gdiplus::GdiplusStartupInput gdiplusStartupInput;
   Gdiplus::GdiplusStartup(&TMP,&gdiplusStartupInput,0);
   Gdiplus::GpImage* Img;
   if (Gdiplus::DllExports::GdipLoadImageFromFile((Picture),&Img)>0) return 0;
   float w,h;
    Gdiplus::DllExports::GdipGetImageDimension(static_cast<Gdiplus::GpBitmap*>(Img),&w,&h);
   if (w*h==0) return 0;
   Gdiplus::BitmapData Pdata;
   Gdiplus::GpRect R={0,0,w-1,h-1};
   Gdiplus::DllExports::GdipBitmapLockBits(static_cast<Gdiplus::GpBitmap*>(Img),&R,Gdiplus::ImageLockModeRead,PixelFormat32bppARGB,&Pdata);
   for (int y = 0;y<h-1;y++)
   {
      for (int x= 0;x<w-1;x++)
      {
      	colour=static_cast<COLORREF *>(Pdata.Scan0)[int(y*w+x)] -4278190080;
      		SetPixel(WindowHDC,x+dx,y+dy,RGB(GetBValue(colour),GetGValue(colour),GetRValue(colour)));
  }
}
return w*h;
}

void getsize(wchar_t * Picture,float &w,float &h)
{
   ULONG_PTR TMP; 
   Gdiplus::GdiplusStartupInput gdiplusStartupInput;
   Gdiplus::GdiplusStartup(&TMP,&gdiplusStartupInput,0);
   Gdiplus::GpImage* Img;
   if (Gdiplus::DllExports::GdipLoadImageFromFile((Picture),&Img)>0) return;
   Gdiplus::DllExports::GdipGetImageDimension(static_cast<Gdiplus::GpBitmap*>(Img),&w,&h);
}

void resizeconsole(int w,int h)
{
  HWND console = GetConsoleWindow();
  RECT ConsoleRect;
  GetWindowRect(console, &ConsoleRect); 
  MoveWindow(console, ConsoleRect.left, ConsoleRect.top,w,h, TRUE);
}

int main()

{
	float w,h;
	HDC WHDC=GetDC(GetConsoleWindow());
	wchar_t * p= L"bob.jpg";
	getsize(p,w,h);
	resizeconsole(w+90,h+90);
	Picload(WHDC,p,30,30);
	
	cin.get();
}

 


Topic archived. No new replies allowed.