salvare WPF InkCanvas in un JPG - l'immagine viene ritagliata
Domanda
Ho un controllo InkCanvas di WPF che sto usando per acquisire una firma nella mia applicazione. Il controllo è simile al seguente: 700x300
Tuttavia, quando lo salvo come JPG, l'immagine risultante appare così, anche 700x300
Il codice che sto usando per salvare
sigPath = System.IO.Path.GetTempFileName();
MemoryStream ms = new MemoryStream();
FileStream fs = new FileStream(sigPath, FileMode.Create);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)inkSig.Width, (int)inkSig.Height, 96d, 96d, PixelFormats.Default);
rtb.Render(inkSig);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
encoder.Save(fs);
fs.Close();
Questa è la XAML che sto usando:
<Window x:Class="Consent.Client.SigPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent" Topmost="True" AllowsTransparency="True"
Title="SigPanel" Left="0" Top="0" Height="1024" Width="768" WindowStyle ="None" ShowInTaskbar="False" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" >
<Border BorderThickness="1" BorderBrush="Black" Background='#FFFFFFFF' x:Name='DocumentRoot' Width='750' Height='400' CornerRadius='10'>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Name="txtLabel" FontSize="24" HorizontalAlignment="Center" >Label</TextBlock>
<InkCanvas Opacity="1" Background="Beige" Name="inkSig" Width="700" Height="300" />
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Button FontSize="24" Margin="10" Width="150" Name="btnSave" Click="btnSave_Click">Save</Button>
<Button FontSize="24" Margin="10" Width="150" Name="btnCancel" Click="btnCancel_Click">Cancel</Button>
<Button FontSize="24" Margin="10" Width="150" Name="btnClear" Click="btnClear_Click">Clear</Button>
</StackPanel>
</StackPanel>
</Border>
In passato ha funzionato perfettamente. Non riesco a capire cosa è cambiato che sta causando lo spostamento dell'immagine quando viene salvata.
Soluzione
Aha! Il problema è TextBlock txtLabel che si trova direttamente sopra InkCanvas. Quando lo rimuovi, la linea nera scompare.
Per quanto riguarda il motivo per cui ciò accade, non ne sono ancora del tutto sicuro.
Altri suggerimenti
Ho avuto lo stesso problema che ho fatto in questo modo ... Ha funzionato qui ..
private void Button_Click(object sender, RoutedEventArgs e)
{
double width = inkSig.ActualWidth;
double height = inkSig.ActualHeight;
RenderTargetBitmap bmpCopied = new RenderTargetBitmap((int)Math.Round(width), (int)Math.Round(height), 96, 96, PixelFormats.Default);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(inkSig);
dc.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), new System.Windows.Size(width, height)));
}
bmpCopied.Render(dv);
System.Drawing.Bitmap bitmap;
using (MemoryStream outStream = new MemoryStream())
{
// from System.Media.BitmapImage to System.Drawing.Bitmap
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bmpCopied));
enc.Save(outStream);
bitmap = new System.Drawing.Bitmap(outStream);
}
EncoderParameter qualityParam =
new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 85L);
// Jpeg image codec
ImageCodecInfo jpegCodec = getEncoderInfo("image/jpeg");
if (jpegCodec == null)
return;
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = qualityParam;
Bitmap btm = new Bitmap(bitmap);
bitmap.Dispose();
btm.Save("C:\\Users\\Pd\\Desktop\\dfe12.jpg", jpegCodec, encoderParams);
btm.Dispose();
}
private ImageCodecInfo getEncoderInfo(string mimeType)
{
// Get image codecs for all image formats
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
// Find the correct image codec
for (int i = 0; i < codecs.Length; i++)
if (codecs[i].MimeType == mimeType)
return codecs[i];
return null;
}
La mia classe salva l'immagine
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
public void ExportToJpeg(String path, InkCanvas surface)
{
double
x1 = surface.Margin.Left,
x2 = surface.Margin.Top,
x3 = surface.Margin.Right,
x4 = surface.Margin.Bottom;
if (path == null) return;
surface.Margin = new Thickness(0, 0, 0, 0);
Size size = new Size(surface.Width, surface.Height);
surface.Measure(size);
surface.Arrange(new Rect(size));
RenderTargetBitmap renderBitmap =
new RenderTargetBitmap(
(int)size.Width,
(int)size.Height,
96,
96,
PixelFormats.Default);
renderBitmap.Render(surface);
using (FileStream fs = File.Open(path, FileMode.Create))
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
encoder.Save(fs);
}
surface.Margin = new Thickness(x1, x2, x3, x4);
}
e surface.Margin = new Thickness (55,40,96,5); http://img519.imageshack.us/img519/7499/mynewimage.png
Jason, ho risolto questo problema.
Scusa per il mio inglese. Sono russo.
È necessario impostare la proprietà inkCanvas.Margin
su 0,0,0,0
con:
surface.Margin = new Thickness(0, 0, 0, 0);
dopo aver salvato il margine impostato nella tua posizione.
Esempio: http://img189.imageshack.us/img189/7499/mynewimage.png
var size = new Size(inkCanvas.ActualWidth, inkCanvas.ActualHeight);
inkCanvas.Margin = new Thickness(0, 0, 0, 0);
inkCanvas.Measure(size);
inkCanvas.Arrange(new Rect(size));
var encoder = new PngBitmapEncoder();
var bitmapTarget = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Default);
bitmapTarget.Render(inkCanvas);
encoder.Frames.Add(BitmapFrame.Create(bitmapTarget));
encoder.Save(ms);
Ho cercato in tutta la rete una risposta a questo problema e ho provato la maggior parte delle opinioni senza alcuna gioia. Poi ho provato questo e ha funzionato!
<Canvas x:Name="editCanvas" Background="Transparent" ClipToBounds="True">
<InkCanvas EditingMode="Select" x:Name="inkCanvas" Background="Transparent" Height="562" Width="866">
</InkCanvas>
</Canvas>