像透明图像上的 Photoshop 背景

Photoshop like background on transparent image

我正在为我的 class 项目制作一个图形编辑器,我想这样做,例如,当用户将图片加载到编辑器中或在 PictureBox 中绘制某些内容时,所有alpha 部分显示为棋盘状背景。

我的想法是,当我创建一个具有透明背景集的 PictureBox 时,我在它后面创建另一个,将其 BackColor 设置为白色并添加 50x50 的灰色图像,水平和垂直交替。这是解决问题的好方法吗?如果没有,您有什么建议吗?

例如,我在 Photoshop 中创建 1600x1600 的图像。当我缩放到某个级别时,它会缩小框并添加更多框来填充图像。如果您使用过类似程序的 Photoshop,您就会明白我的意思。现在,我将如何实现相同的效果?

创建 Photoshop-like 程序是一个有趣的项目。

一路上会有很多挑战,值得提前考虑一下..

以下是一份简短但不完整的清单,列出了需要牢记的事项:

  • 绘画动作
  • 撤消、重做、编辑
  • 多层
  • 缩放和滚动
  • 保存并打印

所以得到棋盘背景只是万里长征的开始..

使用 PictureBox 作为基础 canvas 是一个很好的选择,因为它的多层会有所帮助。这是一段代码,可以为您提供灵活的棋盘背景,即使您缩放真实图形也能保持其大小:

void setBackGround(PictureBox pb, int size, Color col)
{   
    if (size == 0 && pb.BackgroundImage != null)
    {
        pb.BackgroundImage.Dispose();
        pb.BackgroundImage = null;
        return;
    }
    Bitmap bmp = new Bitmap(size * 2, size * 2);
    using (SolidBrush brush = new SolidBrush(col))
    using (Graphics G = Graphics.FromImage(bmp) )
    {
        G.FillRectangle(brush, 0,0,size, size);
        G.FillRectangle(brush, size,size, size, size);
    }
    pb.BackgroundImage = bmp;
    pb.BackgroundImageLayout = ImageLayout.Tile;
}

加载一张图片进行测试,这就是您将得到的结果,左边是正常的,右边是放大的:

是的,为了保存这个背景应该被删除;正如您在代码中所见,传入 size = 0 即可。

接下来呢?让我给你一些关于如何从上面处理各种任务的提示:

  • 滚动:Picturebox无法滚动。而是将它放在 PanelAutoScroll = true 中,并根据需要使其变大。

  • 缩放:使用 SizeSizeMode 可以毫无问题地放大和缩小 ImageBackgroundImage 将保持未缩放,就像在 Photoshop 中一样。但是,您必须添加更多代码才能放大在 PB 顶部或图层上绘制的图形。这里的关键是使用 Graphics.MultiplyTransform(Matrix).

  • 缩放 Graphics 对象
  • 图层:图层是 PhotoShop(和其他优质程序)中最有用的功能。它们可以通过嵌套透明绘图 canvases 来实现。 Panels可以用,我比较喜欢Labels。如果每一个都坐在 里面 它下面的那个和底部的那个 Parent 有 PB,它们的所有内容将被合并显示。

    • 不要直接使用 Label 而是创建一个 subclass 来保存额外的数据和 know-how!
    • 改变它们的顺序并不难,只要牢记嵌套结构并保持完整!
    • 隐藏图层是通过设置标志并在绘画动作中检查该标志来完成的
    • 其他数据可以包括名称、不透明度,可能还有覆盖颜色..
    • 图层也应显示在图层面板中,最好是创建缩略图并在 FlowLayoutPanel
    • 中插入图层用户对象
  • 绘图操作:这些始终是 WinForms 中任何绘图的关键。使用鼠标绘制时,每个这样的 activity 都会创建一个您需要设计的 DrawAction class 对象,其中包含进行实际绘制所需的所有信息,例如:

    • 类型(矩形、填充矩形、线条、FreeHandLine(一系列点)、文本、etc.etc..)
    • 颜色
    • 积分
    • 宽度
    • 文字
    • 要绘制的图层
    • 甚至可能轮换

    与 LayerCanvas class 一起,DrawAction class 将是项目中最重要的 class,因此正确设计它值得做一些工作!

    只有最顶层会接收到鼠标事件。所以你需要跟踪哪一层是活动层并将动作添加到它的动作列表中。当然,活动图层也必须在图层面板中指明。

  • 由于所有绘图都存储在列表中,实现无限制的撤消和重做很简单。为了允许有效的绘图 撤消,也许一个共同的动作列表和每个图层的单独列表是最好的设计..

    • 撤消和重做只是删除最后一个列表元素并将其推入 redo-stack。
    • 也可以编辑动作,包括更改参数、将它们在动作列表中上下移动或从列表中间删除一个。它有助于显示动作调色板,例如 PhotoShop 中的 F9。
    • 要将两个或更多层拼合在一起,您只需合并它们的动作列表即可。
    • 要将所有图层展平到 Image 中,您只需要将它们绘制到 它们的 canvas 上,而是 图片。绘制控件或位图see here的区别!这里我们将 PictureBox.Image 作为 PB 结构的第二层,在 Background.Image 之上。 (第 3 个是 Control 表面,但是上面有多层我们真的不需要它..)
  • 可以通过 Image.Save() 在展平所有图层后或在关闭 BackgroundImage 后通过告诉 PB 将自己绘制成 Bitmap ( control.DrawToBitmap() ) 然后你可以保存。

玩得开心!