在交易图表上通过资源驱动的双三次插值图像缩放技术创建动态 MQL5 图形界面·进阶篇
🖼️

在交易图表上通过资源驱动的双三次插值图像缩放技术创建动态 MQL5 图形界面·进阶篇

(2/3)· 最近邻太糙、双线性发虚?用资源位图加双三次插值让交易图表界面既清晰又可交互

含代码示例 第 2/3 篇
很多交易者给图表加logo或背景图时直接拉伸BMP,结果边缘锯齿、细节糊成一团。其实MQL5里用资源指令配合双三次插值,能在不同窗口尺寸下保持清晰且可锚定定位,只是多数人没走对加载流程。

◍ 把资源图按图表比例塞进MT5

想在MT5图表上叠加一张自定义图片(比如标注支撑区的底图),核心是先读资源、再按图表像素尺寸重算缩放,避免拉变形。下面这段函数直接从编译资源里读像素,并依据图表宽高比决定是「宽撑满」还是「高撑满」。 资源读取失败是最常见的坑:ResourceReadImage 若返回 false,多半是资源名没在 #resource 里正确声明,或图片格式不被终端支持。此时函数直接返回 false 并打印错误,调用方应当中断绘制而不是继续跑缩放逻辑。 缩放分支里用 image_aspect_ratio 与 chart_aspect_ratio 比较:图片更宽就令 scaled_image_width = 图表宽,高度按比值反推;反之高度撑满。若你开了 LimitToOriginalSize,还会用 MathMin 把尺寸钳在原始像素内,再二次校正一边以保持比例——这对高清屏上不想让logo被放糊的场景很实用。 调试时留意 PrintFormat 打出的三组数据:Original / Chart / Scaled。比如原图 800x600、图表 1200x700,则 chart 比值为1.714、image 为1.333,走「高撑满」分支,缩放后宽约933、高700,开限制则回退到 800x600。开MT5按F4编译挂到图表,看日志就能验证这套计算。

MQL5 / C++
class="type">bool DisplayImageOnChart() {
  class=class="str">"cmt">// Load the original image from the resource
  class="type">uint image_pixels[]; class=class="str">"cmt">//--- Declare an array to store image pixel data
  class="type">uint original_image_width, original_image_height; class=class="str">"cmt">//--- Declare variables for original image dimensions
  
  if (!ResourceReadImage(ORIGINAL_IMAGE_RESOURCE, image_pixels, original_image_width, original_image_height)) { class=class="str">"cmt">//--- Read the image resource into the pixel array
    Print("Error: Failed to read original image data from resource."); class=class="str">"cmt">//--- Log an error if reading the image fails
    class="kw">return false; class=class="str">"cmt">//--- Return false to indicate failure
  }
  
  class=class="str">"cmt">// Get chart dimensions
  class="type">int chart_pixel_width = (class="type">int)ChartGetInteger(class="num">0, CHART_WIDTH_IN_PIXELS); class=class="str">"cmt">//--- Retrieve the chart width in pixels
  class="type">int chart_pixel_height = (class="type">int)ChartGetInteger(class="num">0, CHART_HEIGHT_IN_PIXELS); class=class="str">"cmt">//--- Retrieve the chart height in pixels
  
  class=class="str">"cmt">// Calculate scaled dimensions while preserving aspect ratio
  class="type">class="kw">double image_aspect_ratio = (class="type">class="kw">double)original_image_width / original_image_height; class=class="str">"cmt">//--- Calculate the aspect ratio of the original image
  class="type">class="kw">double chart_aspect_ratio = (class="type">class="kw">double)chart_pixel_width / chart_pixel_height; class=class="str">"cmt">//--- Calculate the aspect ratio of the chart
  class="type">int scaled_image_width, scaled_image_height; class=class="str">"cmt">//--- Declare variables for scaled image dimensions
  
  if (image_aspect_ratio > chart_aspect_ratio) { class=class="str">"cmt">//--- Check if the image is wider relative to the chart
    scaled_image_width = chart_pixel_width; class=class="str">"cmt">//--- Set scaled width to match chart width
    scaled_image_height = (class="type">int)(chart_pixel_width / image_aspect_ratio); class=class="str">"cmt">//--- Calculate scaled height to maintain aspect ratio
  } else {
    scaled_image_height = chart_pixel_height; class=class="str">"cmt">//--- Set scaled height to match chart height
    scaled_image_width = (class="type">int)(chart_pixel_height * image_aspect_ratio); class=class="str">"cmt">//--- Calculate scaled width to maintain aspect ratio
  }
  
  class=class="str">"cmt">// Limit scaling to original size if enabled
  if (LimitToOriginalSize) { class=class="str">"cmt">//--- Check if the user has enabled limiting to original size
    scaled_image_width = MathMin(scaled_image_width, (class="type">int)original_image_width); class=class="str">"cmt">//--- Restrict width to original width
    scaled_image_height = MathMin(scaled_image_height, (class="type">int)original_image_height); class=class="str">"cmt">//--- Restrict height to original height
    class=class="str">"cmt">// Recalculate one dimension to maintain aspect ratio
    if (scaled_image_width < scaled_image_height * image_aspect_ratio) { class=class="str">"cmt">//--- Check if width is the limiting factor
      scaled_image_height = (class="type">int)(scaled_image_width / image_aspect_ratio); class=class="str">"cmt">//--- Adjust height to maintain aspect ratio
    } else {
      scaled_image_width = (class="type">int)(scaled_image_height * image_aspect_ratio); class=class="str">"cmt">//--- Adjust width to maintain aspect ratio
    }
  }
  
  class=class="str">"cmt">// Log dimensions for debugging
  PrintFormat(
    "Original: %dx%d, Chart: %dx%d, Scaled: %dx%d",
    original_image_width, original_image_height,
    chart_pixel_width, chart_pixel_height,

「双三次插值缩放像素阵列的实现细节」

把图表截图做无损放大时,直接拉伸像素会糊成马赛克;双三次插值靠周围 4×4 邻域加权,能在 MT5 里拿到更顺滑的缩略图。下面这段 ScaleImage 就是干这事的核心:先按目标宽高开新数组,再逐点映射回原图坐标做插值。 缩放映射的数学很直白——目标点 (x,y) 对应原图坐标 original_x = x * original_width / new_width,original_y 同理。new_width 若设为原宽 2 倍,则每个目标像素只跨越原图 0.5 个像素间距,插值权重决定它偏向哪个邻居。 BicubicInterpolateComponent 里那四个 weights_x 系数是关键:t 为分数位移,weight[1] 在 t=0 时等于 1、两侧随距离立方衰减。若把 -0.5 改成 -0.75(Catmull-Rom 之外更锐的核),边缘可能更清晰但噪点也会被放大,外汇 tick 图缩放时尤其要留意。 跑完双层循环后,代码用 ArrayResize 把原 pixels 改成新尺寸,再 ArrayCopy 覆写回去。你在 EA 里调用前,最好先 Print 原宽高和 new_width*new_height,确认数组没越界——MT5 对 uint[] 越界不会抛异常,只会静默截断。

MQL5 / C++
class="type">void ScaleImage(
  class="type">uint &pixels[], class="type">int original_width, class="type">int original_height,
  class="type">int new_width, class="type">int new_height
) {
  class="type">uint scaled_pixels[]; class=class="str">"cmt">//--- 声明存放缩放后像素的数组
  ArrayResize(scaled_pixels, new_width * new_height); class=class="str">"cmt">//--- 按目标尺寸重设数组大小

  for (class="type">int y = class="num">0; y < new_height; y++) { class=class="str">"cmt">//--- 遍历缩放图每一行
    for (class="type">int x = class="num">0; x < new_width; x++) { class=class="str">"cmt">//--- 遍历缩放图每一列
      class=class="str">"cmt">// 映射回原图坐标
      class="type">class="kw">double original_x = (class="type">class="kw">double)x * original_width / new_width; class=class="str">"cmt">//--- 计算对应原图 x 坐标
      class="type">class="kw">double original_y = (class="type">class="kw">double)y * original_height / new_height; class=class="str">"cmt">//--- 计算对应原图 y 坐标

      class=class="str">"cmt">// 应用双三次插值
      class="type">uint pixel = BicubicInterpolate(pixels, original_width, original_height, original_x, original_y); class=class="str">"cmt">//--- 插值得到像素值
      scaled_pixels[y * new_width + x] = pixel; class=class="str">"cmt">//--- 存入缩放数组
    }
  }

  ArrayResize(pixels, new_width * new_height); class=class="str">"cmt">//--- 把原数组改为新尺寸
  ArrayCopy(pixels, scaled_pixels); class=class="str">"cmt">//--- 将缩放结果拷回原数组
}

class="type">class="kw">double BicubicInterpolateComponent(class="type">uchar &components[], class="type">class="kw">double fractional_x, class="type">class="kw">double fractional_y) {
  class="type">class="kw">double weights_x[class="num">4]; class=class="str">"cmt">//--- 声明 x 方向权重数组
  class="type">class="kw">double t = fractional_x; class=class="str">"cmt">//--- 记录 x 方向小数部分
  weights_x[class="num">0] = (-class="num">0.5 * t * t * t + t * t - class="num">0.5 * t);       class=class="str">"cmt">//--- x-class="num">1 位置权重
  weights_x[class="num">1] = (class="num">1.5 * t * t * t - class="num">2.5 * t * t + class="num">1);       class=class="str">"cmt">//--- x 位置权重
  weights_x[class="num">2] = (-class="num">1.5 * t * t * t + class="num">2 * t * t + class="num">0.5 * t);  class=class="str">"cmt">//--- x+class="num">1 位置权重
  weights_x[class="num">3] = (class="num">0.5 * t * t * t - class="num">0.5 * t * t);           class=class="str">"cmt">//--- x+class="num">2 位置权重

  class="type">class="kw">double y_values[class="num">4]; class=class="str">"cmt">//--- 声明中间 y 值数组
  for (class="type">int j = class="num">0; j < class="num">4; j++) { class=class="str">"cmt">//--- 遍历邻域四行
    y_values[j] =

双立方插值的Y轴权重与像素拆包

上面这段把双立方插值收了尾:在X方向对每个Y行算出中间值后,再针对Y方向做四次多项式加权。Y权重用的仍是Catmull-Rom基函数,系数直接写死在表达式里——比如 weights_y[1] 的 1.5*t*t*t - 2.5*t*t + 1,就是中心采样点权重,t趋近0时它接近1,两侧点权重趋近0。 最终结果用 MathMax(0, MathMin(255, result)) 夹到0~255,这是ARGB单通道的有效区间,越界会直接咬死在边界而不是回绕。外汇或贵金属图表做自定义指标重采样时,这类夹值能避免渲染出噪点,但高频缩放下仍可能偏色,属正常误差。 GetArgb 函数把32位像素按位移拆成四个8位通道:alpha拿右移24位后的低8位,red是16位,green是8位,blue直接取低8位。注意MT5里 uint 像素是ABGR内存序,拆出来后若拿去画Canvas要确认端序,否则红蓝会反。 BicubicInterpolate 入口先取整和小数:x0=(int)x 丢掉小数部分,fractional_x = x - x0 留作权重计算的t。这一步若x为负或越界不会在此处理,调用前需自己保证坐标在 [1, width-2] 区间内,否则取 components 会越界读脏数据。

MQL5 / C++
    weights_x[class="num">0] * components[j * class="num">4 + class="num">0] +
    weights_x[class="num">1] * components[j * class="num">4 + class="num">1] +
    weights_x[class="num">2] * components[j * class="num">4 + class="num">2] +
    weights_x[class="num">3] * components[j * class="num">4 + class="num">3]; class=class="str">"cmt">//--- Perform interpolation in x for each y
   }

   class=class="str">"cmt">// Calculate cubic interpolation weights for y
   class="type">class="kw">double weights_y[class="num">4]; class=class="str">"cmt">//--- Declare an array for y interpolation weights
   t = fractional_y; class=class="str">"cmt">//--- Store the fractional y value
   weights_y[class="num">0] = (-class="num">0.5 * t * t * t + t * t - class="num">0.5 * t); class=class="str">"cmt">//--- Calculate weight for y-class="num">1
   weights_y[class="num">1] = (class="num">1.5 * t * t * t - class="num">2.5 * t * t + class="num">1); class=class="str">"cmt">//--- Calculate weight for y
   weights_y[class="num">2] = (-class="num">1.5 * t * t * t + class="num">2 * t * t + class="num">0.5 * t); class=class="str">"cmt">//--- Calculate weight for y+class="num">1
   weights_y[class="num">3] = (class="num">0.5 * t * t * t - class="num">0.5 * t * t); class=class="str">"cmt">//--- Calculate weight for y+class="num">2

   class=class="str">"cmt">// Interpolate in y
   class="type">class="kw">double result =
      weights_y[class="num">0] * y_values[class="num">0] +
      weights_y[class="num">1] * y_values[class="num">1] +
      weights_y[class="num">2] * y_values[class="num">2] +
      weights_y[class="num">3] * y_values[class="num">3]; class=class="str">"cmt">//--- Perform interpolation in y to get the final value

   class=class="str">"cmt">// Clamp the result to valid class="type">class="kw">color range [class="num">0, class="num">255]
   class="kw">return MathMax(class="num">0, MathMin(class="num">255, result)); class=class="str">"cmt">//--- Clamp the interpolated value to the valid class="type">class="kw">color range
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Extract ARGB components from a pixel                             |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void GetArgb(class="type">uint pixel, class="type">uchar &alpha, class="type">uchar &red, class="type">uchar &green, class="type">uchar &blue) {
   alpha = (class="type">uchar)((pixel >> class="num">24) & 0xFF); class=class="str">"cmt">//--- Extract the alpha channel from the pixel
   red = (class="type">uchar)((pixel >> class="num">16) & 0xFF);   class=class="str">"cmt">//--- Extract the red channel from the pixel
   green = (class="type">uchar)((pixel >> class="num">8) & 0xFF);  class=class="str">"cmt">//--- Extract the green channel from the pixel
   blue = (class="type">uchar)(pixel & 0xFF);          class=class="str">"cmt">//--- Extract the blue channel from the pixel
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Perform bicubic interpolation for a single pixel                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">uint BicubicInterpolate(
   class="type">uint &pixels[], class="type">int width, class="type">int height,
   class="type">class="kw">double x, class="type">class="kw">double y
) {
   class=class="str">"cmt">// Get integer and fractional parts
   class="type">int x0 = (class="type">int)x; class=class="str">"cmt">//--- Extract the integer part of the x-coordinate
   class="type">int y0 = (class="type">int)y; class=class="str">"cmt">//--- Extract the integer part of the y-coordinate
   class="type">class="kw">double fractional_x = x - x0; class=class="str">"cmt">//--- Calculate the fractional part of the x-coordinate

◍ 双三次插值的邻域取点与分量合成

在 MT5 里做图表图像缩放,双三次插值不会只盯一个像素,而是取目标坐标周围的 4x4 共 16 个点。代码里先用 x0、y0 算出整数基点,再用 fractional_x / fractional_y 保留小数部分,供后续曲线加权。 邻域索引做了夹取处理:MathMin(MathMax(x0+i,0),width-1) 保证越界时落在 [0, width-1] 内,避免读到图像外的脏内存。循环 i 从 -1 到 2,正好覆盖左上加右下共 4 行 4 列。

  • 个像素取出后,通过 GetArgb 拆成 alpha / red / green / blue 四个长度为 16 的数组。每个分量各自跑一遍 BicubicInterpolateComponent,再强转 uchar——这意味着单个通道的插值结果若算到 255.6 也会被截断,视觉上可能出现轻微色偏。
最后用位运算 (alpha<<24)(red<<16)(green<<8)blue 拼回一个 uint 像素值。调用 ScaleImage 后,用 '::ScaledImage'+计数器 生成唯一资源名交给 ResourceCreate,COLOR_FORMAT_ARGB_NORMALIZE 要求输入分量已归一化到 0–255。外汇与贵金属图表资源重绘属高频操作,实盘加载自定义资源存在内存与刷新延迟风险,建议先在策略测试器验证。
MQL5 / C++
  class="type">class="kw">double fractional_y = y - y0; class=class="str">"cmt">//--- Calculate the fractional part of the y-coordinate

  class=class="str">"cmt">// Define 4x4 neighborhood
  class="type">int x_indices[class="num">4], y_indices[class="num">4]; class=class="str">"cmt">//--- Declare arrays for x and y indices
  for (class="type">int i = -class="num">1; i <= class="num">2; i++) { class=class="str">"cmt">//--- Iterate over the 4x4 neighborhood
      x_indices[i + class="num">1] = MathMin(MathMax(x0 + i, class="num">0), width - class="num">1); class=class="str">"cmt">//--- Calculate clamped x-index
      y_indices[i + class="num">1] = MathMin(MathMax(y0 + i, class="num">0), height - class="num">1); class=class="str">"cmt">//--- Calculate clamped y-index
  }

  class=class="str">"cmt">// Get class="num">16 pixels in the 4x4 neighborhood
  class="type">uint neighborhood_pixels[class="num">16]; class=class="str">"cmt">//--- Declare an array for the 4x4 neighborhood pixels
  for (class="type">int j = class="num">0; j < class="num">4; j++) { class=class="str">"cmt">//--- Iterate over rows of the neighborhood
      for (class="type">int i = class="num">0; i < class="num">4; i++) { class=class="str">"cmt">//--- Iterate over columns of the neighborhood
          neighborhood_pixels[j * class="num">4 + i] = pixels[y_indices[j] * width + x_indices[i]]; class=class="str">"cmt">//--- Store the pixel value
      }
  }

  class=class="str">"cmt">// Extract ARGB components
  class="type">uchar alpha_components[class="num">16], red_components[class="num">16], green_components[class="num">16], blue_components[class="num">16]; class=class="str">"cmt">//--- Declare arrays for ARGB components
  for (class="type">int i = class="num">0; i < class="num">16; i++) { class=class="str">"cmt">//--- Iterate over the neighborhood pixels
      GetArgb(
          neighborhood_pixels[i],
          alpha_components[i], red_components[i],
          green_components[i], blue_components[i]
      ); class=class="str">"cmt">//--- Extract ARGB components for each pixel
  }

  class=class="str">"cmt">// Perform bicubic interpolation for each component
  class="type">uchar alpha_out = (class="type">uchar)BicubicInterpolateComponent(alpha_components, fractional_x, fractional_y); class=class="str">"cmt">//--- Interpolate the alpha component
  class="type">uchar red_out = (class="type">uchar)BicubicInterpolateComponent(red_components, fractional_x, fractional_y); class=class="str">"cmt">//--- Interpolate the red component
  class="type">uchar green_out = (class="type">uchar)BicubicInterpolateComponent(green_components, fractional_x, fractional_y); class=class="str">"cmt">//--- Interpolate the green component
  class="type">uchar blue_out = (class="type">uchar)BicubicInterpolateComponent(blue_components, fractional_x, fractional_y); class=class="str">"cmt">//--- Interpolate the blue component

  class=class="str">"cmt">// Combine components into a single pixel
  class="kw">return (alpha_out << class="num">24) | (red_out << class="num">16) | (green_out << class="num">8) | blue_out; class=class="str">"cmt">//--- Combine ARGB components into a single pixel value
}
class=class="str">"cmt">// Scale the image class="kw">using bicubic interpolation
ScaleImage(image_pixels, original_image_width, original_image_height, scaled_image_width, scaled_image_height); class=class="str">"cmt">//--- Scale the image to the calculated dimensions
class=class="str">"cmt">// Create a unique resource name for the scaled image
class="type">class="kw">string scaled_resource_name = "::ScaledImage" + IntegerToString(scaled_resource_counter++); class=class="str">"cmt">//--- Generate a unique resource name class="kw">using the counter
class=class="str">"cmt">// Create a new resource with the scaled image
if (!ResourceCreate(
   scaled_resource_name, image_pixels, scaled_image_width, scaled_image_height,
   class="num">0, class="num">0, scaled_image_width, COLOR_FORMAT_ARGB_NORMALIZE
)) { class=class="str">"cmt">//--- Create a new resource for the scaled image

「锚点偏移与位图标签的落地写法」

资源创建失败时直接返回 false 并打日志,是这套全图覆盖逻辑里最该先锁死的动作;否则后续坐标计算全建立在空资源上,MT5 图表只会静默空白。 定位策略分两条路:CenterImageDynamically 为 true 时,用图表像素宽高减去缩放图宽高再除 2,得到 x_offset 与 y_offset,图像居中。false 时走 AnchorCorner 枚举,TOP_LEFT 直接用用户输入偏移,TOP_RIGHT 需从 chart_pixel_width 扣掉图宽和偏移,BOTTOM 两组同理扣 chart_pixel_height,default 回退到左上角。 真正画图靠 CreateFullChartImage:先用 ObjectFind(0, object_name) 判存在,小于 0 才 ObjectCreate 一个 OBJ_BITMAP_LABEL;随后 ObjectSetString 把资源名写进 OBJPROP_BMPFILE。开 MT5 把这段代码塞进 EA,改 AnchorCorner 看四角贴图差异,能立刻验证你的偏移公式有没有算反。

MQL5 / C++
  Print("Error: Failed to create resource for scaled image: ", scaled_resource_name); class=class="str">"cmt">//--- Log an error if resource creation fails
  class="kw">return false; class=class="str">"cmt">//--- Return false to indicate failure
}
class=class="str">"cmt">// Determine image position based on user input
class="type">int x_offset, y_offset; class=class="str">"cmt">//--- Declare variables for x and y offsets
if (CenterImageDynamically) { class=class="str">"cmt">//--- Check if the user wants to center the image dynamically
  x_offset = (chart_pixel_width - scaled_image_width) / class="num">2; class=class="str">"cmt">//--- Calculate horizontal offset to center the image
  y_offset = (chart_pixel_height - scaled_image_height) / class="num">2; class=class="str">"cmt">//--- Calculate vertical offset to center the image
} else {
  class=class="str">"cmt">// Set base position based on chosen anchor corner
  class="kw">switch (AnchorCorner) { class=class="str">"cmt">//--- Select the anchor corner based on user input
    case TOP_LEFT: class=class="str">"cmt">//--- Handle Top-Left corner
      x_offset = XOffsetFromCorner; class=class="str">"cmt">//--- Use user-defined x-offset from top-left
      y_offset = YOffsetFromCorner; class=class="str">"cmt">//--- Use user-defined y-offset from top-left
      class="kw">break;
    case TOP_RIGHT: class=class="str">"cmt">//--- Handle Top-Right corner
      x_offset = chart_pixel_width - scaled_image_width - XOffsetFromCorner; class=class="str">"cmt">//--- Calculate x-offset from right edge
      y_offset = YOffsetFromCorner; class=class="str">"cmt">//--- Use user-defined y-offset from top
      class="kw">break;
    case BOTTOM_LEFT: class=class="str">"cmt">//--- Handle Bottom-Left corner
      x_offset = XOffsetFromCorner; class=class="str">"cmt">//--- Use user-defined x-offset from left
      y_offset = chart_pixel_height - scaled_image_height - YOffsetFromCorner; class=class="str">"cmt">//--- Calculate y-offset from bottom
      class="kw">break;
    case BOTTOM_RIGHT: class=class="str">"cmt">//--- Handle Bottom-Right corner
      x_offset = chart_pixel_width - scaled_image_width - XOffsetFromCorner; class=class="str">"cmt">//--- Calculate x-offset from right edge
      y_offset = chart_pixel_height - scaled_image_height - YOffsetFromCorner; class=class="str">"cmt">//--- Calculate y-offset from bottom
      class="kw">break;
    class="kw">default: class=class="str">"cmt">//--- Handle unexpected case
      x_offset = XOffsetFromCorner; class=class="str">"cmt">//--- Default to top-left x-offset
      y_offset = YOffsetFromCorner; class=class="str">"cmt">//--- Default to top-left y-offset
  }
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Create and position the chart image object                         |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void CreateFullChartImage(
  class="type">class="kw">string object_name, class="type">class="kw">string resource_name,
  class="type">int x_size, class="type">int y_size,
  class="type">int x_offset, class="type">int y_offset,
  class="type">bool is_background
) {
  class=class="str">"cmt">// Create the bitmap label object if it doesn&class="macro">#x27;t exist
  if (ObjectFind(class="num">0, object_name) < class="num">0) { class=class="str">"cmt">//--- Check if the object already exists
    ObjectCreate(class="num">0, object_name, OBJ_BITMAP_LABEL, class="num">0, class="num">0, class="num">0); class=class="str">"cmt">//--- Create a new bitmap label object
  }

  class=class="str">"cmt">// Set object properties
  ObjectSetString(class="num">0, object_name, OBJPROP_BMPFILE, resource_name); class=class="str">"cmt">//--- Set the resource file for the bitmap
把图像缩放诊断交给小布
这些资源加载与插值渲染的异常排查,小布盯盘的AIGC已内置对应检查逻辑,打开品种页即可看到实时提示,你只管调参数。

常见问题

最近邻会产生像素化硬边,双线性会模糊细节;双三次用4×4邻域三次多项式,渐变更平滑、边缘更锐,适合动态图表叠加。
需放入终端Data文件夹的Images目录,可通过导航器面板右键Images选打开文件夹粘贴,再用\Images\文件名形式声明。
可以,小布盯盘内置的AIGC检测会标记资源加载失败或插值卡顿,帮你快速定位图表界面掉帧原因。
应根据图表尺寸计算等比缩放系数,并以锚点(如角落或居中)为基准重采样,而非独立拉伸横纵轴。