If you replace the function LoadFromFile() by the fixed code, you will also be able to load images that were stored as resources. But you must not set the Top-Down-row-order flag, it won´t work.
This way you don´t need to copy the bitmaps into the files folder of any clients.
Enjoy.
Doerk
//+------------------------------------------------------------------+ //| Load data from file | //+------------------------------------------------------------------+ bool CCanvas::LoadFromFile(const string filename) { struct BitmapHeader { ushort type; uint size; uint reserv; uint offbits; uint imgSSize; uint imgWidth; uint imgHeight; ushort imgPlanes; ushort imgBitCount; uint imgCompression; uint imgSizeImage; uint imgXPelsPerMeter; uint imgYPelsPerMeter; uint imgClrUsed; uint imgClrImportant; } header; bool result=true; CFileBin file; int x,y; uchar a,r,g,b; uchar tmp[]; uint img_size; bool no_alpha,no_flip=false; //--- open file if(file.Open(filename,FILE_READ)==INVALID_HANDLE) { //--- Modified by Doerk if (!ResourceReadImage(filename,m_pixels,m_width,m_height)) return(false); else return (true); } //--- read header if(file.ReadStruct(header)!=sizeof(header)) { Print("Failed to read file header"); file.Close(); return(false); } m_width =(int)header.imgWidth; m_height=(int)header.imgHeight; if(m_height<0) { m_height=-m_height; no_flip=true; } //--- process depending on color depth if(header.imgBitCount==32) { no_alpha=true; img_size=file.ReadArray(m_pixels); //--- flip image if(!no_flip) for(y=0;y<m_height/2;y++) { ArrayCopy(tmp,m_pixels,0,m_width*y,m_width); ArrayCopy(m_pixels,m_pixels,m_width*y,m_width*(m_height-y-1),m_width); ArrayCopy(m_pixels,tmp,m_width*(m_height-y-1),0,m_width); } //--- check if at least one pixel has alpha channel //--- then leave image as is (consider it as premultiplied ARGB) uint i; for(i=0;i<img_size;i++) { //--- there is alpha channel if(GETRGBA(m_pixels[i])!=0) { no_alpha=false; break; } } //--- no alpha channel if(no_alpha) { //--- consider image as nontransparent, add alpha channel as 0xFF for(i=0;i<img_size;i++) m_pixels[i]|=0xFF000000; } else { if(m_format==COLOR_FORMAT_ARGB_RAW) { //--- color components are not processed by terminal (they should be correctly specified by user) //--- convert image to premultiplied ARGB for(i=0;i<img_size;i++) { switch(a=GETRGBA(m_pixels[i])) { case 0xFF: break; case 0x00: m_pixels[i]=0; break; default: r=GETRGBR(m_pixels[i])*a/255; g=GETRGBG(m_pixels[i])*a/255; b=GETRGBB(m_pixels[i])*a/255; m_pixels[i]=ARGB(a,r,g,b); break; } } } } } else { //--- 24 bits - change image color depth to 32 bits int byte_width; //--- allocate memory for pixels if(ArrayResize(m_pixels,m_width*m_height)!=-1) { //--- the number of bytes that define a line of pixels must be multiple of 4 byte_width=m_width*3; // number of bytes in line of pixels byte_width=(byte_width+3)&~3; // align line to the 4 byte boundary for(y=0;y<m_height;y++) { if(file.ReadArray(tmp,0,byte_width)!=byte_width) { result=false; break; } int k,p; for(x=0,k=0,p=m_width*(m_height-y-1);x<m_width;x++,p++,k+=3) { r=tmp[k+2]; g=tmp[k+1]; b=tmp[k]; m_pixels[p]=XRGB(r,g,b); } } } else result=false; } //--- succeed file.Close(); return(result); }
Hallo and thank you for this publication,
I have tried the functions. The function to cerate ab BitmapLabel is running, but the image is not load.
I can see the Object in the Properties on chart and I can select it.
Now I controlled the File to the bmp and copy it for test in same Folder "Expert"
The bmp ist 32bit and I used Pixelformer and same format too.
I hope someone can help me... thank you.
#include "Canvas.mqh"
CCanvas canvas();
canvas.CreateBitmapLabel(0,0,"testbild",50,50,50,50,COLOR_FORMAT_ARGB_RAW);canvas.LoadFromFile("testbild.bmp");
//string test = canvas.LoadFromFile("testbild.bmp");
//Alert (test); ///////////------------------->>>>>>>>>>>>>>>>>>>OUTPUT IS "FALSE"
canvas.Update();
ChartRedraw(); >>>>>>>>>>> ONLY FOR TESTHallo and thank you for this publication,
I have tried the functions. The function to cerate ab BitmapLabel is running, but the image is not load...
Canvas #include is not necessary for bitmap image with alpha channel.
Bitmaps with alpha channel require #resource followed by path to image or they will not display. This is not found in MQL4 documentation but it's the only way it will work.
Example - If your image is located inside the folder /MQL4/Files/, then you would use the following: #resource"\\Files\\testbild.bmp";
Then add the image to the chart using whatever code you've created then use "::Files\\testbild.bmp" for your path.
Canvas #include is not necessary for bitmap image with alpha channel.
Bitmaps with alpha channel require #resource followed by path to image or they will not display. This is not found in MQL4 documentation but it's the only way it will work.
Example - If your image is located inside the folder /MQL4/Files/, then you would use the following: #resource"\\Files\\testbild.bmp";
Then add the image to the chart using whatever code you've created then use "::Files\\testbild.bmp" for your path.
This is not working on MT4.
CCanvas::LoadFromFile("::images\long.bmp")
returns always false. The bitmap defintely is there, because CreateBitmap works.
The ressource is declared as described:
#resource "\\Images\\long.bmp"
The bitmaps is 24 bit, without alpha channel. When setting it to 32 bit, the script has a compiler error.
So can't use it at all.
It seems tranparent bitmaps are not possible with MT4.
I'll leave the links here.
Implemented work with PNG (2023)
MT5 - https://www.mql5.com/en/code/45439
MT4 - https://www.mql5.com/ru/forum/227736/page84#comment_49544536
Thanks Nikolai Semko
- www.mql5.com
PNG can be embedded inside the code (for example in the MQH file) and already work with it
Working example - https://www.mql5.com/ru/forum/227736/page86#comment_49668436
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
This is just some information, rather than a question, but I thought I'd share it since I've been wondering how to do this for some time.
The standard BITMAP and BITMAP_LABEL objects allow us to load bitmap images on to the chart, but do not support 32-bit images (with alpha channel).
This means if you want to load an image that has a transparent background, you have to first paint the background of the image the same colour as the background of your chart in a drawing program. This subsequently means if you are coding an indicator that you want to share with others, if they have a different background colour to their chart than you, it's going to show up as an ugly square of the incorrect colour.
By way of an example:
Original image with transparent background
Painted with my chart's background colour
How it looks on my chart
How it looks on someone else's chart with a white background
Not to mention that if the image ends up in front of candles even on my chart, it still looks ugly
This is where the Canvas class can come to the rescue. It had a method called LoadFromFile, which supports 32-bit bitmaps.
The syntax is simple:
CCanvas canvas(); canvas.CreateBitmapLabel(chartId, subwindowId, chartObjectName, x, y, width, height, COLOR_FORMAT_ARGB_RAW); canvas.LoadFromFile(file); canvas.Update();
First however we must convert our bitmap to 32-bit alpha format.
There is a free program called Pixelformer which enables us to do this easily. Images can be imported in PNG format with transparency, and exported as 32-bit bitmaps. There is one small caveat - in order to display properly in MT4, the bitmap must be exported from Pixelformer with the "top-down row order" option selected. If this is not checked, only the top half of the bitmap shows up when you try to display it in MT4 (I think this is down to a bug in the section of the Canvas code which tries to flip an image when handling 32-bit format).
Once this has been done, the result can be seen as follows:
Arrow displays correctly on dark background
And against a light background
And can be superimposed in front of candles without obscuring them