Photoshop like background on transparent image

2019-01-20 19:23发布

I'm making a graphics editor for my class project and i want to make so that when, for example a user loads a picture in to the editor or or draw something in the PictureBox, all the alpha parts are shown the chessboard like background.

My idea is that when I create a PictureBox with transparent background set, I create another one behind it, set its BackColor to white and add grey images 50x50, alternately horizontally and vertically. Is that a good approach to the problem? If, not do You have any suggestions?

In Photoshop, for example, I create image 1600x1600. When I zoom to a certain level, it shrinks the boxes and adds more of them to fill the image. If You'we used Photoshop of similar program you know what I mean. Now, how would I go about achieving the same effect?

1条回答
可以哭但决不认输i
2楼-- · 2019-01-20 19:36

Creating a Photoshop-like program is a fun project.

There will be many challenges along your way and it is well worth thinking ahead a little..

Here is a short and incomplete list of things to keep in mind:

  • Draw- and paint actions
  • Undo, redo, edit
  • Multiple layers
  • Zooming and scrolling
  • Saving and printing

So getting a checkerboard background is only the start of a long journey..

Using a PictureBox as the base canvas is a very good choice, as its several layers will help. Here is a piece of code that will provide you with a flexible checkerboard background, that will keep its size even when you scale the real graphics:

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;
}

Load an Image for testing and this is what you'll get, left normal, right zoomed in:

enter image description hereenter image description here

Yes, for saving this background should be removed; as you can see in the code, passing in a size = 0 will do that.

What next? Let me give you a few hints on how to approach the various tasks from above:

  • Scrolling: Picturebox can't scroll. Instead place it in a Panel with AutoScroll = true and make it as large as needed.

  • Zooming: Playing with its Size and the SizeMode will let you zoom in and out the Image without problems. The BackgroundImage will stay unscaled, just as it does in Photoshop. You will have to add some more code however to zoom in on the graphics you draw on top of the PB or on the layers. The key here is scaling the Graphics object using a Graphics.MultiplyTransform(Matrix).

  • Layers: Layers are imo the single most useful feature in PhotoShop (and other quality programs). They can be achieved by nesting transparent drawing canvases. Panels can be used, I prefer Labels. If each is sitting inside the one below it and the one at the bottom has the PB as its Parent, all their contents will be shown combined.

    • Don't use the Label directly but create a subclass to hold additional data and know-how!
    • Changing their order is not very hard, just keep the nested structure in mind and intact!
    • Hiding a layer is done by setting a flag and checking that flag in the painting actions
    • Other data can include a Name, Opacity, maybe an overlay color..
    • The layers should also be shown in a Layers Palette, best by creating a thumbnail and inserting a layer userobject in a FlowLayoutPanel
  • Draw Actions: These are always the key to any drawing in WinForms. When using the mouse to draw, each such activity creates an object of a DrawAction class you need to design, which holds all info needed to do the actual drawing, like:

    • Type (Rectangle, filledRectangle, Line, FreeHandLine (a series of Points), Text, etc.etc..)
    • Colors
    • Points
    • Widths
    • Text
    • The layer to draw on
    • maybe even a rotation

    Along with the LayerCanvas class the DrawAction class will be the most important class in the project, so getting its design right is worth some work!

    Only the topmost layer will receive the mouse events. So you need to keep track which layer is the active one and add the action to its actions list. Of course the active layer must also be indicated in the Layers Palette.

  • Since all drawing is stored in List(s), implementing a unlimited undo and redo is simple. To allow for effective drawing and undo, maybe a common action list and an individual list for each layer is the best design..

    • Undo and Redo are just matter of removing the last list element and pushing it onto a redo-stack.
    • Editing actions is also possible, including changing the parameters, moving them up or down the actions list or removing one from the middle of the list. It help to show an Actions Palette, like F9 in PhotoShop.
    • To flatten two or more layers together all you need is to combine their action lists.
    • To flatten all layers into the Image you only need to draw them not onto their canvas but into the Image. For the difference of drawing onto a control or into a Bitmap see here! Here we have the PictureBox.Image as the second level of a PB's structure above the Background.Image. (The 3rd is the Control surface, but with the multiple layers on top we don't really need it..)
  • Saving can be done by either by Image.Save() after flattening all Layers or after you have switched off the BackgroundImage by telling the PB to draw itself into a Bitmap ( control.DrawToBitmap() ) which you can then save.

Have fun!

查看更多
登录 后发表回答