当前位置: 首页 > article >正文

使用 C# 制作图像的特写窗口

许多网站都会显示一个特写窗口,其中显示放大的图像部分,以便您可以看到更多细节。您在主图像上移动鼠标,它会在单独的图片中显示特写。此示例执行的操作类似。(示例使用的一些数学运算非常棘手,因此您可能需要仔细查看才能了解其工作原理。)

特写图实际上只是原始图像的全尺寸副本。(“主”图像是较小比例的相同图像。)要显示特写图,程序会在名为picCloseup的PictureBox中显示全尺寸图像。该控件位于名为panCloseup的Panel内。通过在panCloseup内移动picCloseup,程序可以显示全尺寸图像的不同部分。

以下代码使程序准备启动。

// Save the original image.
private Bitmap OriginalImage, ShadedImage;
private int SmallWidth, SmallHeight;
private float ScaleX, ScaleY;
private void Form1_Load(object sender, EventArgs e)
{
    OriginalImage = picWhole.Image as Bitmap;
    picCloseup.Image = OriginalImage;
    picCloseup.SizeMode = PictureBoxSizeMode.AutoSize;

    // Make a shaded version of the image.
    ShadedImage = new Bitmap(OriginalImage);
    using (Graphics gr = Graphics.FromImage(ShadedImage))
    {
        using (Brush br =
            new SolidBrush(Color.FromArgb(128, 255, 255, 255)))
        {
            Rectangle rect = new Rectangle(0, 0,
                ShadedImage.Width, ShadedImage.Height);
            gr.FillRectangle(br, rect);
        }
    }

    // Get scale factors to map from big scale to small scale.
    ScaleX = (float)panCloseup.ClientSize.Width /
        OriginalImage.Width;
    ScaleY = (float)panCloseup.ClientSize.Height /
        OriginalImage.Height;

    // See how big the closeup is on the small scale.
    SmallWidth = (int)(ScaleX * picWhole.ClientSize.Width);
    SmallHeight = (int)(ScaleY * picWhole.ClientSize.Height);
}

此代码保存原始图像并制作该图像的亮化版本。要制作亮化版本,它会复制原始图像,然后用半透明的白色矩形填充它。这将成为您将鼠标移到其上的主图像。

当鼠标移入或移出主图像时,将执行以下代码。

// Use the shaded background image.
private void picWhole_MouseEnter(object sender, EventArgs e)
{
    picWhole.Image = ShadedImage;
    panCloseup.Visible = true;
}

// Use the regular image.
private void picWhole_MouseLeave(object sender, EventArgs e)
{
    picWhole.Image = OriginalImage;
    panCloseup.Visible = false;
}

当鼠标位于主图像之外时,程序显示正常的非亮化版本。当鼠标进入图像时,程序切换为显示亮化图像。

当鼠标在主图像上移动时,以下代码会显示鼠标周围区域的特写。

// Display a closeup of this area.
private Rectangle ViewingRectangle;
private void picWhole_MouseMove(object sender, MouseEventArgs e)
{
    // Position picCloseup inside its parent Panel.
    float x = (float)e.X / picWhole.ClientSize.Width *
        OriginalImage.Width -
        (float)panCloseup.ClientSize.Width / 2;
    float y = (float)e.Y / picWhole.ClientSize.Height *
        OriginalImage.Height -
        (float)panCloseup.ClientSize.Height / 2;
    if (x < 0) x = 0;
    if (y < 0) y = 0;
    if (x > OriginalImage.Width - panCloseup.ClientSize.Width)
        x = OriginalImage.Width - panCloseup.ClientSize.Width;
    if (y > OriginalImage.Height - panCloseup.ClientSize.Height)
        y = OriginalImage.Height - panCloseup.ClientSize.Height;
    picCloseup.Location = new Point(-(int)x, -(int)y);

    // Record the position we are viewing.
    ViewingRectangle = new Rectangle((int)x, (int)y,
        panCloseup.ClientSize.Width, 
        panCloseup.ClientSize.Height);

    // Draw the closeup area.
    picWhole.Invalidate();
}

首先,代码决定鼠标周围的区域在哪里。如果该区域部分位于主图像之外,则代码会调整其 X 和 Y 坐标,使该区域位于主图像内。这样可以让特写显示尽可能多的图像。

代码将picCloseup移动到panCloseup内,以显示全尺寸图像的正确部分。然后,它将在变量ViewingRectangle中记录主图像上将显示的区域,并使主图像无效以使其重绘。以下代码显示了主图片的Paint事件处理程序,该处理程序处理该重绘。

// Draw the viewing area.
private void picWhole_Paint(object sender, PaintEventArgs e)
{
    // Scale so we can draw in the full scale coordinates.
    e.Graphics.ScaleTransform(ScaleX, ScaleY);

    // Draw the viewing area using the original image.
    e.Graphics.DrawImage(OriginalImage, ViewingRectangle, 
        ViewingRectangle, GraphicsUnit.Pixel);
    //e.Graphics.DrawRectangle(Pens.Red, ViewingRectangle);
}

此代码使用变换,因此它可以使用全尺寸图像的坐标而不是主图像(您可能还记得,主图像是缩小比例的)的坐标进行绘制。然后,它将原始全尺寸图像的一部分复制到主图像上,以显示鼠标周围的区域。结果是主图像除了此区域外都被阴影化,此区域以原始亮度绘制。取消注释此方法中的最后一行,以在主图像的特写区域周围绘制一个红色矩形。

我承认这是一个令人困惑的例子,但它的效果非常酷,所以我鼓励你下载并尝试一下。如果你对代码进行一些实验,你就能弄清楚它是如何工作的。(土卫二是一颗特别奇怪的卫星!)


http://www.kler.cn/a/504141.html

相关文章:

  • WEB攻防-通用漏洞_XSS跨站_权限维持_捆绑钓鱼_浏览器漏洞
  • 学英语学Elasticsearch:04 Elastic integrations 工具箱实现对第三方数据源的采集、存储、可视化,开箱即用
  • 如何选择Ubuntu版本
  • 【Spring Boot 应用开发】-04-01 自动配置-数据源-连接池
  • String.intern是什么
  • 认识机器学习中的经验风险最小化准则
  • Linux 查看磁盘的 I/O 读写情况(随手记)
  • 【2025 Rust学习 --- 14 迭代器创建和使用】
  • qt QLabel QPushButton 控件重写paintEvent后 控件消失
  • 【Ubuntu与Linux操作系统:六、软件包管理】
  • 忘记了PDF文件的密码,怎么办?
  • Linux操作系统分析实验一:多线程与内核模块编程
  • 【深度学习】论文画图
  • MySQL学习笔记5【SQL优化/视图/存储过程/触发器】
  • 使用Axios实现无刷新信息验证:提升用户体验
  • 基于Piquasso的光量子计算机的模拟与编程
  • 电梯系统的UML文档02
  • 62_Redis服务器集群优化
  • 从零搭建一个Vue3 + Typescript的脚手架——day1
  • Redis快速入门店铺营业状态设置
  • px、em 和 rem 的区别:深入理解 CSS 中的单位
  • 【ArcGIS初学】产生随机点计算混淆矩阵
  • 【树莓派3B】香瓜树莓派3B之语音识别机器人
  • 2025年  生活公报计划
  • 见微知著:Tripo 开创 3D 生成新时代
  • 无人机反制设备十大应用场景详解