A bitmap derives its appearance from the bitmap file that defines it in RGB pixels.
You can't change its colour as normal graphic objects.
You have to use a different bitmap of another colour or implement canvas rendering yourself.
How do I implement convas rendering?
You can , consult this example .
The broad description of this is :
- Open the bitmap
- Read the pixels
- Extract a mask
- Use that mask to change the color
The code looks sloppy i apologize in advance, i tried to explain as much as possible in the comments.
#property copyright "Read The Discussion" #property link "https://www.mql5.com/en/forum/440152" #property version "1.00" int OnInit() { //--- //you probably know which bitmap you are loading string filename="\\Files\\boxy.bmp"; //free the resource ResourceFree("MyBoxy"); //create a new resource from the file ResetLastError(); bool create_from_file=ResourceCreate("MyBoxy",filename); if(create_from_file){ uint pixels[],width=0,height=0; //this will send the pixel data to the array and the width height to width and height :P ResetLastError(); bool read_pixels=ResourceReadImage("::MyBoxy",pixels,width,height); if(read_pixels){ /* now you have the pixels so you can loop in them and read the "mask" of the file you can decide what the "mask" is . So your uint pixel values are Alpha , Red , Green , Blue Let's do a silly mask extraction , a naive one We will define a color that represents the void and any deviation from that color will be the intensity of the re-coloration So , i want black Red=0 Green=0 Blue=0 to be the void , and on top of that if the image is transparent i will adjust the intensity on top A color channel ranges between 0 and 255 with 0 being the lowest value and 255 being the maximum value So the uint of the pixels contains 4 channels which are 4 bytes which are 4 uchar values Nikolai Semko has a nice trick with colors where he uses a union type which turns your code into a lamborghini engine , but for now we will keep it simple. To extract all the channels from a uint we do this : (this may be corrected later) */ //lets take the first pixel uint full_color=pixels[0]; //alpha sits at the leftmost byte so if we move it to the right by 3 bytes (or 24 bits ) we get its value from 0->255 uchar alpha=(uchar)(full_color>>24); //if you recall typewriters what we just did is move the typewriter header across and threw the rest of the data out , leaving the alpha only //now the red we need to move 1 byte to the left to throw the alpha out and then again 3 bytes to the right uchar red=(uchar)((full_color<<8)>>24); //the green 2 bytes to the left 3 bytes to the right uchar green=(uchar)((full_color<<16)>>24); //the blue 3 bytes to the left 3 bytes to the right uchar blue=(uchar)((full_color<<24)>>24); //could this be done with subtractions ? Yes //so now that we know how to read colors lets create a map of intensity uchar map[]; //and lets resize it to the pixels (the # of pixels) ArrayResize(map,ArraySize(pixels),0); //and lets set its default value to 0 ArrayFill(map,0,ArraySize(map),0); //cool the map is also from 0 to 255 and this will be the alpha value on our output //let's define our void color levels uchar void_red=0,void_green=0,void_blue=0; //and let's grab the max red max green and max blue tp be able to adjust the alpha properly at the end uchar max_red=0,max_green=0,max_blue=0; for(int i=0;i<ArraySize(pixels);i++){ red=(uchar)((pixels[i]<<8)>>24); green=(uchar)((pixels[i]<<16)>>24); blue=(uchar)((pixels[i]<<24)>>24); if(red>max_red){max_red=red;} if(green>max_green){max_green=green;} if(blue>max_blue){max_blue=blue;} } //so lets scan the pixels for(int i=0;i<ArraySize(pixels);i++){ alpha=(uchar)(pixels[i]>>24); red=(uchar)((pixels[i]<<8)>>24); green=(uchar)((pixels[i]<<16)>>24); blue=(uchar)((pixels[i]<<24)>>24); //great , check one how far is this color from the void //! keep in mind this is not taking color theory into account /* we will calculate the deviation of each color channel from the void color , if you are a photographer you will cringe at this point but we are not photographers so : max deviation is 255 or in our channels case , their max we get the absolute distance of the current red from the void red and divide by the max distance : */ double red_deviation=MathAbs(red-void_red)/((double)max_red); double green_deviation=MathAbs(green-void_green)/((double)max_green); double blue_deviation=MathAbs(blue-void_blue)/((double)max_blue); /* we have 3 deviations , let's make photographers cringe more each one is 1 third of the total deviation */ double deviation=(red_deviation+green_deviation+blue_deviation)/3.00; //and this is our initial intensity which can only be curbed by the alpha channel /* how ? if the alpha is half transparent for instance it will be 127 , so that will result in an alpha curb of 0.5 which we will plaster all over our deviation . */ double alpha_curb=((double)alpha)/255.0; double intensity=alpha_curb*deviation; //and the map has values from 0-255 intensity*=255.0; map[i]=(uchar)(intensity); //this part is done } /*we exit the loop with a mask (map[]) that mask is telling us , go ahead and create a color with rgb and set the alpha to this value and you are good to go */ //so let's define our color uchar new_red=0,new_green=255,new_blue=0; //we could also use a base color //so loop into pixels and change them for(int i=0;i<ArraySize(pixels);i++){ //if we use a base color we can use this handy function of mql5 uint new_color=ColorToARGB(clrGreen,map[i]); //or if we use our channels we can new_color=(((uint)map[i])<<24)|(((uint)new_red)<<16)|(((uint)new_green)<<8)|((uint)new_blue); pixels[i]=new_color; } //done , now we need to update the resource ResourceFree("MyBoxy"); //recreate from pixels ResetLastError(); bool recreate=ResourceCreate("MyBoxy",pixels,width,height,0,0,width,COLOR_FORMAT_ARGB_NORMALIZE); if(recreate){ //create a bitmap label ObjectCreate(ChartID(),"MyBoxies1",OBJ_BITMAP_LABEL,0,0,0); ObjectSetInteger(ChartID(),"MyBoxies1",OBJPROP_XSIZE,width); ObjectSetInteger(ChartID(),"MyBoxies1",OBJPROP_YSIZE,height); ObjectSetString(ChartID(),"MyBoxies1",OBJPROP_BMPFILE,"::MyBoxy"); ChartRedraw(); }else{ Print("Cannot recreate resource "+IntegerToString(GetLastError())); } }else{Print("Cannot read resource pixels "+IntegerToString(GetLastError()));} }else{Print("Cannot create resource from file "+IntegerToString(GetLastError()));} //--- return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { ObjectsDeleteAll(ChartID(),"MyBoxies"); } void OnTick() { }
Use the custom graphics or canvas from the MQL5 Standard Library: Documentation on MQL5: Standard Library / Custom Graphics / CCanvas
However, from your screenshot you seem to be using MQL4 (you posted in the wrong section), which also has a Standard Library but it is much more limited and has not been updated for a long time. There is also no documentation for the MQL4 Standard Library, so you will have to rely on the MQL5 documentation which will not always match.
You will also find more information about it in Articles and CodeBase:
Articles: https://www.mql5.com/en/search#!keyword=ccanvas&module=mql5_module_articles
CodeBase: https://www.mql5.com/en/search#!keyword=CCanvas&module=mql5_module_codebase
Use the custom graphics or canvas from the MQL5 Standard Library: Documentation on MQL5: Standard Library / Custom Graphics / CCanvas
However, from your screenshot you seem to be using MQL4 (you posted in the wrong section), which also has a Standard Library but it is much more limited and has not been updated for a long time. There is also no documentation for the MQL4 Standard Library, so you will have to rely on the MQL5 documentation which will not always match.
You will also find more information about it in Articles and CodeBase:
Articles: https://www.mql5.com/en/search#!keyword=ccanvas&module=mql5_module_articles
CodeBase: https://www.mql5.com/en/search#!keyword=CCanvas&module=mql5_module_codebase
Thank you very much for your help.
You can , consult this example .
The broad description of this is :
- Open the bitmap
- Read the pixels
- Extract a mask
- Use that mask to change the color
The code looks sloppy i apologize in advance, i tried to explain as much as possible in the comments.
Thanks for you code, actually I could read the bitmap file using ResourceReadImage() function and I could change the size of it, but I could not change the file color no matter whatever I tried.
Ni I could not, I tried to use your code, but I could not figure it out, It gives some errors. But I managed to change the bitmap file size using below code, can you guide me how I can change the color? (Many thanks in advance)
#resource "\\Images\\Rect.bmp" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- create timer EventSetTimer(60); // Bitmap_Label(0,"name1",0,20,20,"::Resources\\rect1.bmp",NULL); // Bitmap_Label(0,"name2",0,100,120,"::Resources\\AAA.bmp",NULL); //you probably know which bitmap you are loading const string myIcons = "::Images\\Rect.bmp"; //icons resource name const string newIcon = "Files\\Rect_Small_new.bmp"; //new resource name uint data[]; //array to store image data int imageW = 0; //variable to store image data width int imageH = 0; //variable to store image height ResourceReadImage( myIcons, data, imageW, imageH ); //Read Image Data; //Print("imageW: ",imageW," imageH: ",imageH); ResourceCreate( newIcon, data, 100, 100, 15 , 15 , imageW, COLOR_FORMAT_ARGB_NORMALIZE ); //Create a new smaller image ResourceSave( newIcon,"Rect_Small_new.bmp" ); //Save the image to file //Rectangle_label(0,"resd",0,20,20,200,200); //--- return(INIT_SUCCEEDED); }The actual file size was like 150*150 . I changed it to 100*100. I must change the "data" from ResourceReadImage to change the file color, but I cannot figure it out how.
Ni I could not, I tried to use your code, but I could not figure it out, It gives some errors. But I managed to change the bitmap file size using below code, can you guide me how I can change the color? (Many thanks in advance)
What error did you get ?
If its an alpha channel ARGB bmp try this :
#resource "\\Files\\boxy.bmp"; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- uint getWidth=0,getHeight=0; if(reColorWithAlphaMask("Files\\boxy.bmp",clrCrimson,255,true,getWidth,getHeight)){ //create a bitmap label ObjectCreate(ChartID(),"MyBoxies1",OBJ_BITMAP_LABEL,0,0,0); ObjectSetInteger(ChartID(),"MyBoxies1",OBJPROP_XSIZE,getWidth); ObjectSetInteger(ChartID(),"MyBoxies1",OBJPROP_YSIZE,getHeight); ObjectSetString(ChartID(),"MyBoxies1",OBJPROP_BMPFILE,"::Files\\boxy.bmp"); ChartRedraw(); }else{ Print("Cannot recolor"); } //--- return(INIT_SUCCEEDED); } bool reColorWithAlphaMask(string _resource_name, color newColor, uchar maxOpacity, bool maintainOriginalAlpha, uint &_result_width, uint &_result_height){ //read image uint pixels[]; _result_width=0; _result_height=0; if(ResourceReadImage("::"+_resource_name,pixels,_result_width,_result_height)){ uchar max_alpha=255,min_alpha=0; //pass 1 : get min max if not original opacity if(!maintainOriginalAlpha){ max_alpha=0;min_alpha=255; for(int i=0;i<ArraySize(pixels);i++){ uchar this_alpha=(uchar)(pixels[i]>>24); if(this_alpha>max_alpha){max_alpha=this_alpha;} if(this_alpha<min_alpha){min_alpha=this_alpha;} if(max_alpha==255&&min_alpha==0){break;} } } //map it uchar map[]; ArrayResize(map,ArraySize(pixels),0); for(int i=0;i<ArraySize(pixels);i++){ uchar this_alpha=(uchar)(pixels[i]>>24); map[i]=(uchar)((((double)(this_alpha-min_alpha))/MathMax(1,max_alpha-min_alpha))*maxOpacity); } //recolor it for(int i=0;i<ArraySize(pixels);i++){ uint col=ColorToARGB(newColor,map[i]); pixels[i]=col; } //reresource ResourceFree(_resource_name); if(ResourceCreate(_resource_name,pixels,_result_width,_result_height,0,0,_result_width,COLOR_FORMAT_ARGB_NORMALIZE)){ return(true); } }else{ Print("reColor cannot read resource "+_resource_name); } return(false); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- ObjectsDeleteAll(ChartID(),"MyBoxies"); }
in your code
#resource "\\Images\\Rect.bmp" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- create timer EventSetTimer(60); // Bitmap_Label(0,"name1",0,20,20,"::Resources\\rect1.bmp",NULL); // Bitmap_Label(0,"name2",0,100,120,"::Resources\\AAA.bmp",NULL); //you probably know which bitmap you are loading const string myIcons = "::Images\\Rect.bmp"; //icons resource name const string newIcon = "Files\\Rect_Small_new.bmp"; //new resource name uint data[]; //array to store image data int imageW = 0; //variable to store image data width int imageH = 0; //variable to store image height ResourceReadImage( myIcons, data, imageW, imageH ); //Read Image Data; //Print("imageW: ",imageW," imageH: ",imageH); ResourceCreate( newIcon, data, 100, 100, 15 , 15 , imageW, COLOR_FORMAT_ARGB_NORMALIZE ); //Create a new smaller image uint getWidth=0,getHeight=0; reColorWithAlphaMask(newIcon,clrCrimson,255,true,getWidth,getHeight); ResourceSave( newIcon,"Rect_Small_new.bmp" ); //Save the image to file //Rectangle_label(0,"resd",0,20,20,200,200); //--- return(INIT_SUCCEEDED); }
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Thanks for you help in advance.