Load from resources, or draw them myself - c#

Are there any benefit in me drawing my own buttons (just rectangles) over loading 80 of them from resources?

It depends on the complexity of the drawn buttons..
"More complex drawings = more processing time .."
But images somehow have constant time loading
"Whatever the image looks like = nearly same processing time.."
Conculsion:
I will prefer drawing buttons if few simple operations are in
But in more complex cases (like color gradient or something) , I prefer stored images..
Also note that some UI must be done in gdi+ and can not be done otherwise..
for example circular buttons or animations..
Stored images don't have full flexibility of GDI+

Related

How to show an image in PictureBox if the picture can be from 10x10 to 500x500

Now I used next code to download picture from desctop to PictureBox
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "BMP|*.bmp";
if (openFileDialog.ShowDialog() != DialogResult.OK)
return;
pictureBox.Load(openFileDialog.FileName);
pictureBox.SizeMode=PictureBoxSizeMode.StretchImage;
pictureBox.BorderStyle = BorderStyle.Fixed3D;
If I used a normal picture(100x100) it looks nice(unfuzzy).
If I used a smal picture(15x15) it looks fuzzy.
I want to know how to make them unfuzzy( they can look like bricks, but they need to be unfuzzy);
Waiting result for small picture need to look like this
Waiting result for normal picture need to look like this
The fuzziness comes from image interpolation. To have your desired blocky look, you need to use nearest neighbour interpolation.
Thankfully, .NET has this build into. You can set to the interpolation mode to the GDI Graphics object which renders your PictureBox.
To do so I'd recommend exteding the PictureBox user control and adding an InterpolationMode parameter. Then, you can override the OnPaint method, and use your interpolation mode.
public class InterpolatingPictureBox : PictureBox
{
public InterpolationMode InterpolationMode { get; set; }
protected override void OnPaint(PaintEventArgs eventArgs)
{
eventArgs.Graphics.InterpolationMode = InterpolationMode;
base.OnPaint(eventArgs);
}
}
Here is a 16x16 image: , upscaled to 256x256 using
NearestNeighbour (left)
Bilinear (which is default, middle)
HighQualityBilinear (right)
All are rendered on the InterpolatingPictureBox control.
You have a SERIOUS problem. There is no easy solution.
I want to know how to make them unfuzzy
Impossible. Sharpening (which is what you want) of images to larger resolution is possible within reason, but this takes seriously advanced programs that run for quite some time. Not talking as programmer here - but this is a standard step in printing fine art photography. Photos have a relatively low resolution (mine come at up to 43 megapixel) and printers a much higher one.
There are some AA approaches that are easy, but 10x10 sized up t0 100x100 is going to challenge even the most advanced programs - 10x10 is nothing to work with. You talk of 10x starting with no data on the beginning.
You CAN turn off anti aliasing, resize the image in code (easy to do) with no anti aliasing - but this will turn real pictures looking UGLY. .NET has no real high level sharpening functionality and again, 10x10 is not enough to start working with.
The best you can do is not load them into a picture box. Load them into a bitmap, then draw that onto a new bitmap of optimal size (100x100). This at least gives you full control over the resizing.
The code for this you can find at
Scaling a System.Drawing.Bitmap to a given size while maintaining aspect ratio
while
Image resizing in .Net with Antialiasing
tells you how to select anti aliasing.
But again: expect quite little. Those anti aliasing modes are purely technical and not anything that you use for photos. Plus selecting the right one depends on the input image - so you can use a default or give the user a choice. I am probably overcomplicating things, but outside programming I actually DO deal with images that need to be scaled up with as little image loss as possible for large printing.

Photoshop like background on transparent image

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?
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:
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!

Silverlight - Is it possible to create UI elements on a background thread?

I'm building a line chart control in Silverlight using PolyLineSegment and points. It works just as expected, but the application freezes for a long time when there's too much data that needs to be visualized (too many points). I can't move my code on a separate thread for an obvious reason - it deals with UI elements directly, so when I try to call them from a separate thread it results in exception (even if UI elements are not yet rendered).
Is there any way to create UI elements dynamically on a background thread and then pass them to the UI thread to be rendered? And if not, what would be the possible solution? I'm thinking of creating an Bitmap image instead of actual controls, but there won't be much interactivity in this case.
It sounds like you need to get a faster way of rendering your points. If you have 800k samples and only say, 800 pixels to display them in you're wasting 1000 points per pixel of calculations if you just load it into a PolyLineSegment.
I would revisit 'interpolating' the points (this is really coalescing for your large dataset). You want to make sure you capture the dynamic range of the function in each pixel correctly:
Figure out how many pixels wide the graph should be
Determine how many points per pixel in the X direction
For each chunk of points:
Build a histogram of the points
Draw a vertical line from max->min on your graph at the X where these points will map to. This captures the full range represented in the chunk.
If your points/pixel gets close to 1 you'll want to switch to the easy rendering to give better visual results as well.
For displaying a waveform (in your case PCM audio data) with "millions of points" you would be better off writing directly to a WritableBitmap. You then have only one render object.
You have already said there is not much processing in your calculations. Trying to use individual UIElements is way too big an overhead (IMHO). Point display is trivial to a bitmap and there are plenty of line drawing algorithms out there, optimised for speed, to do any line segments.
You can plot your points on a background thread and them update an image's ImageSource at the end of the processing to display it.
You certainly can do your compute work on background thread(s) and pass the finished results up to the UI tread with
Deployment.Current.Dispatcher.BeginInvoke
which is discussed here

image processing in c#

before question think about for example photoshop. When you draw a rectangle on the picture.You can move it. And when you move it works very quickly and it doeasnt make some traces on the picture.
So my question is, how to do that in c# application?
This might be useful for you
Image Processing for Dummies with C# and GDI+ Part 1 - Per Pixel Filters
Image Processing for Dummies with C# and GDI+ Part 2 - Convolution Filters
Image Processing for Dummies with C# and GDI+ Part 3 - Edge Detection Filters
Image Processing for Dummies with C# and GDI+ Part 4 - Bilinear Filters and Resizing
Image Processing for Dummies with C# and GDI+ Part 5 - Displacement filters, including swirl
Image Processing for Dummies with C# and GDI+ Part 6 - The HSL color space
When you are moving the rectangle, Photoshop doesn't put it in the image and then draw the image, instead the image is drawn without the rectangle, and the rectangle is drawn on top of that on the screen. That way when you move the rectangle it can redraw the part of the image that previously was covered by the rectangle, and draw the rectangle at the new position.
I think you're asking about selection rectangles (or other temporary shapes) on top of the document image. This effect is sometimes known as “rubber banding”, especially when drawing a line from one point to another (it stretches like a rubber band).
Traditionally, this was done by using XOR drawing -- instead of overwriting the image with the selection shape, the colors in that area are inverted. Then, to remove the selection, it suffices to invert the colors again, returning to the same original image. Today, graphics rendering is fast enough that such tricks are not usually necessary; it suffices to simply repaint that part of the window (without the rectangle).
Either way, it is important to recognize that the document image — the image the user is editing — is not the same as the window image, which is just a copy to be remade whenever necessary. In the window, the document image is drawn and then selections, guide marks, and other such controls are drawn on top of it.
I'm not familiar with C#'s GUI facilities (and I understand there is more than one GUI framework you might be using), but it's probably got the usual structure of putting many "widgets", "views", or "controls" in the window (possibly nested inside each other). You can do a straightforward selection box — though not an optimally efficient one — by just putting an appropriately sized rectangle widget (with a solid border and a transparent background) on top of an image widget. This lets your GUI framework take care of the appropriate redrawing for you and is probably a good cheap way to start.

Rendering WPF DrawingGroup to single ImageSource

Currently I'm using a System.Windows.Media.DrawingGroup to store some tiled images (ImageDrawing) inside the Children-DrawingCollection property.
Well the problem is now, this method gets really slow if you display the entire DrawingGroup in an Image control, because my DrawingGroup can contain hundreds or even thousands of small images it can really mess up the performance.
So my first thought was to somehow render a single image from all the small ones inside the DrawingGroup and then only display that image, that would be much faster. But as you might have figured out I haven't found any solution so simply combine several images with WPF Imaging.
It would really be great if someone could help with this problem or tell me how i can improve the performance with the DrawingGroup or even use another approach.
One last thing, currently I'm using a RenderTargetBitmap to generate a single BitmapSource from the DrawingGroup, this approach isn't really faster, but it makes the scrolling and working on the Image control at least a little smoother.
I'm not sure this applies to your problem, but I'll post it here anyway since it might help someone:
If not all of the images in the drawing group is going to be visible at the same time, you could set the ClipGeometry property to whatever you want it to draw. This effectively tells WPF that the parts outside of the geometry is not needed and will be skipped during rendering.
A few other things you could experiment with are:
Freeze the drawinggroup before applying it to your image source. At least it couldn't hurt (unless you really need to modify the instance, but remember you could always just create a new one instead of modifying the old)
Try different ways to display your drawinggroup. For instance as a DrawingVisual (which is considered light weight) or as a DrawingBrush to paint e.g. a rectangle.
Combine the small images into smaller groups which you then combine to your bigger group. No idea if this improves or hurts performance, but it could be worth trying.
I'm working on a problem having to do with tiled images, with the added complication of having to display some images overlaid on others.
I haven't run into any performance issues (and likely won't since my images are rather small and relatively small in number, around 100 max.), but I did come across the Freeze method in a code sample for the DrawingImage class. The comment for it was "Freeze the DrawingImage for performance benefits."
The Freeze method also applies to the DrawingGroup class. Maybe give it a try?

Categories

Resources