Issue with PictureBox control - c#

I have image file that i wanna crop and load to picturebox. When i download it remotely - all work fine, but when i load it from local machine - picturebox pic stretch...
var img = (Bitmap) Image.FromStream(new WebClient().OpenRead("https://i.snag.gy/MjJca5.jpg"));
img = CropImage(img);
BackgroundImage = img;
BackgroundImageLayout = ImageLayout.Zoom;
public Bitmap CropImage(Image img) {
// create a graphic path to hold the shape data
GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
var points = new Point[] {
new Point(85, 1111), new Point(934, 1111), new Point(934, 952), new Point(1642, 952),
new Point(1642, 2000), new Point(85, 2000), new Point(85, 1111)
};
GraphicsPath gp = new GraphicsPath();
gp.AddPolygon(points.ToArray());
Bitmap bmp1 = new Bitmap(2220, 2220);
using(Graphics G = Graphics.FromImage(bmp1)) {
G.Clip = new Region(gp);
G.DrawImage(img, 0, 0);
bmp1.Save("axi.jpeg");
return bmp1;
}
}
This code return this pic. All work correctly
but this code return this pic.
FileStream file = new FileStream(openFileDialog1.FileName, FileMode.Open);
var img = (Bitmap) Image.FromStream(file);
img = CropImage(img);
pictureBox1.BackgroundImage = img;
pictureBox1.BackgroundImageLayout = ImageLayout.Zoom;
...

Related

Capture screenshot of control with different DPI

I can capture screenshot of control for normal 100% DPI. But when the DPI changed to 125% then the screenshot is not proper. Please suggest approach so that the screenshot can be captured with any DPI. Following is the code
// Get absolute location on screen of upper left corner of button
System.Windows.Point locationFromScreen = this.sv.PointToScreen(new System.Windows.Point(0, 0));
// Transform screen point to WPF device independent point
PresentationSource source = PresentationSource.FromVisual(this);
System.Windows.Point targetPoints = source.CompositionTarget.TransformFromDevice.Transform(locationFromScreen);
var bmpScreenshot = new Bitmap((int)sv.ActualWidth,
(int)sv.ActualHeight,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
// Create a graphics object from the bitmap.
var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
gfxScreenshot.CopyFromScreen((int)targetPoints.X,
(int)targetPoints.Y,
0,
0,
new System.Drawing.Size((int)sv.ActualWidth, (int)sv.ActualHeight),
CopyPixelOperation.SourceCopy);
byte[] data;
using (var stream = new System.IO.MemoryStream())
{
bmpScreenshot.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
data = stream.ToArray();
}
var result = Convert.ToBase64String(data);
winObj = new Window1();
MemoryStream ms = new MemoryStream();
((System.Drawing.Bitmap)bmpScreenshot).Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
BitmapImage image = new BitmapImage();
image.BeginInit();
ms.Seek(0, SeekOrigin.Begin);
image.StreamSource = ms;
image.EndInit();
winObj.imageViewer.Source = image;
winObj.ShowDialog();
bmpScreenshot.Dispose();

Move dynamically created image to a new page

I can dynamically create a barcode using sample tutorials.
This block of code is in a loop and generates a number of images determined by user input. The image is in a place holder and is displayed on the same webpage.
I want the user to be able to have all the images on a separate page or file for them to print, but I'm not quite sure the best approach to do that. I tried placing it in a session, but I only get 1 image as opposed to the amount the user entered.
System.Web.UI.WebControls.Image imgBarCode = new System.Web.UI.WebControls.Image();
using (Bitmap bitMap = new Bitmap(barCode.Length * 27, 100))
{
using (Graphics graphics = Graphics.FromImage(bitMap))
{
Font oFont = new Font("IDAutomationHC39M", 16);
PointF point = new PointF(2f, .2f);
SolidBrush blackBrush = new SolidBrush(Color.Black);
SolidBrush whiteBrush = new SolidBrush(Color.White);
graphics.FillRectangle(whiteBrush, 0, 0, bitMap.Width, bitMap.Height);
graphics.DrawString("*" + barCode + "*", oFont, blackBrush, point);
}
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
bitMap.Save(ms, ImageFormat.Png);
byte[] byteImage = ms.ToArray();
Convert.ToBase64String(byteImage);
imgBarCode.ImageUrl = "data:image/png;base64," + Convert.ToBase64String(byteImage);
}
plBarCode.Controls.Add(imgBarCode);
}

Convert DrawingImage to BitmapImage

I want to draw large number of shapes (lines, ellipses and ...) and then save them as bitmap or png. I made the drawings and the question is: how can I convert a DrawingImage to BitmapImage in C#? the code is something like this:
DrawingGroup drawingGroup = new DrawingGroup();
using(DrawingContext context = drawingGroup.Open())
{
//make some drawing
}
DrawingImage drawingImage = new DrawingImage(drawingGroup)
// your suggestion? DrawingImage - > BitmapImage
You may put the ImageDrawing into an Image control and render that into a RenderTargetBitmap, which is a BitmapSource and can therefore be serialized by a BitmapEncoder (PngBitmapEncoder in this example).
public void SaveDrawingToFile(Drawing drawing, string fileName, double scale)
{
var drawingImage = new Image { Source = new DrawingImage(drawing) };
var width = drawing.Bounds.Width * scale;
var height = drawing.Bounds.Height * scale;
drawingImage.Arrange(new Rect(0, 0, width, height));
var bitmap = new RenderTargetBitmap((int)width, (int)height, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(drawingImage);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
using (var stream = new FileStream(fileName, FileMode.Create))
{
encoder.Save(stream);
}
}
Note that you don't actually need a BitmapImage for encoding, because BitmapSource (or any derived class like RenderTargetBitmap) will be accepted as argument to BitmapFrame.Create.
A slightly different solution would involve a DrawingVisual instead of a DrawingImage:
public void SaveDrawingToFile(Drawing drawing, string fileName, double scale)
{
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
{
drawingContext.PushTransform(new ScaleTransform(scale, scale));
drawingContext.PushTransform(new TranslateTransform(-drawing.Bounds.X, -drawing.Bounds.Y));
drawingContext.DrawDrawing(drawing);
}
var width = drawing.Bounds.Width * scale;
var height = drawing.Bounds.Height * scale;
var bitmap = new RenderTargetBitmap((int)width, (int)height, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(drawingVisual);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
using (var stream = new FileStream(fileName, FileMode.Create))
{
encoder.Save(stream);
}
}
I found it pretty easy this way:
public static BitmapSource ToBitmapSource(DrawingImage source)
{
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawImage(source, new Rect(new Point(0, 0), new Size(source.Width, source.Height)));
drawingContext.Close();
RenderTargetBitmap bmp = new RenderTargetBitmap((int)source.Width, (int)source.Height, 96, 96, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);
return bmp;
}
You may use it to get System.Drawing.Bitmap
using (MemoryStream ms = new MemoryStream())
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(ToBitmapSource(drawingImage)));
encoder.Save(ms);
using (System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(ms))
{
bmpOut = new System.Drawing.Bitmap(bmp);
}
}

How to preserve png transparency?

I created a function to allow uploaded transparent .png files to be inserted into a SQL Server database and the displayed on a web page via an HttpHandler.
While this all works, the png transparency changes to black when it's viewed on the web page. Is there a way of preserving the transparency?
Here's my image service which inserts into the database from the MVC controller:
public void AddImage(int productId, string caption, byte[] bytesOriginal)
{
string jpgpattern = ".jpg|.JPG";
string pngpattern = ".png|.PNG";
string pattern = jpgpattern;
ImageFormat imgFormat = ImageFormat.Jpeg;
if (caption.ToLower().EndsWith(".png"))
{
imgFormat = ImageFormat.Png;
pattern = pngpattern;
}
ProductImage productImage = new ProductImage();
productImage.ProductId = productId;
productImage.BytesOriginal = bytesOriginal;
productImage.BytesFull = Helpers.ResizeImageFile(bytesOriginal, 600, imgFormat);
productImage.BytesPoster = Helpers.ResizeImageFile(bytesOriginal, 198, imgFormat);
productImage.BytesThumb = Helpers.ResizeImageFile(bytesOriginal, 100, imgFormat);
productImage.Caption = Common.RegexReplace(caption, pattern, "");
productImageDao.Insert(productImage);
}
And here's the "ResizeImageFile" helper function:
public static byte[] ResizeImageFile(byte[] imageFile, int targetSize, ImageFormat imageFormat)
{
using (System.Drawing.Image oldImage = System.Drawing.Image.FromStream(new MemoryStream(imageFile)))
{
Size newSize = CalculateDimensions(oldImage.Size, targetSize);
using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format24bppRgb))
{
using (Graphics canvas = Graphics.FromImage(newImage))
{
canvas.SmoothingMode = SmoothingMode.AntiAlias;
canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));
MemoryStream m = new MemoryStream();
newImage.Save(m, imageFormat);
return m.GetBuffer();
}
}
}
}
What do I need to do to preserve the png transparency? Please show examples. I'm seriously not an expert with image manipulation.
Thanks.
Maybe try changing pixel format form PixelFormat.Format24bppRgb to PixelFormat.Format32bppRgb. You need the extra 8 bits to hold the alpha channel.
Using PixelFormat.Format32bppRgb didn't work for me. What worked however is using oldImage.PixelFormat when drawing the new image. So the corresponding line of code becomes:
using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, oldImage.PixelFormat))

How can I convert WriteableBitmap to BitmapImage?

BitmapImage bitmapImage = new BitmapImage(new Uri("arka_projects_as_logo.png", UriKind.Relative));
Image uiElement = new Image() { Source = bitmapImage };
ScaleTransform t = new ScaleTransform() { ScaleX = 0.2, ScaleY = 0.2 };
WriteableBitmap writeableBitmap = new WriteableBitmap(uiElement,t);
I want to insert the result of this conversions (writeableBitmap) into System.Windows.Controls.Image. When I do this:
Image arkaImage = new Image() { Source = writeableBitmap };
arkaImage isn't shown at all. What can be done to make it work?
WriteableBitmap wb = ..
using (MemoryStream ms = new MemoryStream())
{
wb.SaveJpeg(ms, (int)image1.Width, (int)image1.Height, 0, 100);
BitmapImage bmp = new BitmapImage();
bmp.SetSource(ms);
}
Why don't you just apply the ScaleTransform to the UIElement as well?

Categories