Сохранение визуального элемента WPF в формате JPEG

Эта вещь сводит меня с ума.

У меня есть диаграмма Visiblox. который я сейчас экспортирую как PNG, используя следующий код:

    var chart = this.CalibrationChartVisibility == Visibility.Visible ? this.calibrationChart : this.residualChart;


    var transform = chart.LayoutTransform;
    chart.LayoutTransform = null;

    var width = (int)chart.ActualWidth;
    var height = (int)chart.ActualHeight;

    var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
    rtb.Render(chart);

    var encoder = new PngBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(rtb));

    var stream = new MemoryStream();

    encoder.Save(stream);
    stream.Position = 0;

    chart.LayoutTransform = transform;
    return stream.ToArray();

и я получаю что-то вроде этого:диаграмма png

Но теперь мне нужно также экспортировать его в формате JPEG. Я думал, что это будет просто, просто измените кодировщик, но вот что я получаю:диаграмма jpg

Я попробовал это: http://social.msdn.microsoft.com/Forums/vstudio/en-US/31ac62d4-399b-4f2e-a9b9-749efe7528b6/rendertargetbitmap-to-file-problem?forum=wpf

и это: http://www.grumpydev.com/2009/01/03/taking-wpf-screenshots/

и это: получить растровое изображение из представления управления

и Эрви sugestion на этот пост: Как сохранить изображение с помощью JpegBitmapEncoder

или этот: сохранение WPF InkCanvas в JPG - изображение обрезается

и все остальное, что приходило мне в голову, но результат все тот же.

Должно быть, я что-то упускаю, но понятия не имею, что это такое.

2 ответа

Решение

Подводя итог комментариям, это кажется второстепенной проблемой, поскольку PNG, прикрепленный к этому вопросу, имеет все прозрачное, кроме линий диаграммы, а поскольку JPEG не поддерживает прозрачность, все прозрачное будет черным.

Самое простое решение - установить фон диаграммы на какой-нибудь цвет.

Отказ от ответственности: я предоставил этот ответ на вопрос System.Drawing.Image из ImageSource in Resources и собирался проголосовать, чтобы закрыть этот вопрос как дубликат другого, но не смог, потому что автор вопроса не принял ответ.

В WPF каждый элемент пользовательского интерфейса расширяет Visual Класс, обеспечивающий поддержку рендеринга в WPF. Также есть RenderTargetBitmap Класс, который имеет Render Метод, который принимает Visual Объект в качестве входного параметра. Так что вы можете установить свой ImageSource как Source свойство Image и просто сделать Image к Bitmap образ:

Image yourImageObject = new Image();
yourImageObject.Source = yourImageSource;

RenderTargetBitmap renderTargetBitmap = 
    new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
renderTargetBitmap.Render(yourImageObject);

// Save to .png file
PngBitmapEncoder pngBitmapEncoder = new PngBitmapEncoder();    
pngBitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));    
using (Stream stream = File.Create(filepath))    
{    
    pngBitmapEncoder.Save(stream);    
}

Поскольку это хорошо задокументировано в интернете, я не стану повторять здесь всю историю. Чтобы узнать подробности, ознакомьтесь с разделом " Как отобразить растровое изображение" или "Распечатать визуальную страницу в WPF" на веб-сайте Dot NET Tricks, который также поможет вам с вашими требованиями к печати.


ОБНОВЛЕНИЕ >>>

Итак, большая часть этого относится к вам точно так же, за исключением того, что вы хотите использоватьJpegBitmapEncoder объект вместо Этот пример со связанной страницы показывает другой способ сохранить изображение JPEG:

int width = 128;
int height = width;
int stride = width / 8;
byte[] pixels = new byte[height * stride];

// Define the image palette
BitmapPalette myPalette = BitmapPalettes.Halftone256;

// Creates a new empty image with the pre-defined palette
BitmapSource image = BitmapSource.Create(
    width,
    height,
    96,
    96,
    PixelFormats.Indexed1,
    myPalette,
    pixels,
    stride);

FileStream stream = new FileStream("new.jpg", FileMode.Create);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Codec Author is: " + encoder.CodecInfo.Author.ToString();
encoder.FlipHorizontal = true;
encoder.FlipVertical = false;
encoder.QualityLevel = 30;
encoder.Rotation = Rotation.Rotate90;
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);

Пожалуйста, дайте мне знать, если у вас есть какие-либо проблемы.

Другие вопросы по тегам