PPTX DOCX XLSX PDF ODP
Aspose.Imaging  для Python
WMF

Используйте Python для эффекта мультипликации WMF изображений

Применяйте эффект мультипликации WMF изображений и фотографий с использованием собственных Python приложений и серверных API

Как создать эффект мультипликации WMF изображения используя библиотеку для Python

Мы автоматически откликаемся на эффекты мультипликации (Cartoonify), поскольку они переносят нас в детство и создают атмосферу веселья и игры. В мире графического дизайна мультипликационные изображения играют важную роль и часто встречаются в маркетинговых статьях. Эффекты мультипликации включают в себя преобразование фотопортретов в нарисованные, настройка яркости, преобразование в черно-белое изображение, игры с цветами и смешивание различных методов редактирования для создания сложных графических эффектов. Ряд фильтров изображений, таких как «AdjustBrightness», «BinarizeFixed», «Filter», «ReplaceColor» и «ApplyMask», позволяют осуществлять эти трансформации. Они могут быть применены к загруженным изображениям исходного формата. Изображения в мультипликационном стиле подходят для иллюстративных целей на веб-страницах независимо от их тематики. Они придают научным статьям большую живость и делают материалы более привлекательными для пользователей, что в свою очередь увеличивает посещаемость сайта. Для создания мультипликационных эффектов с изображениями WMF будем использовать Aspose.Imaging for Python via .NET API, который представляет собой многофункциональный, мощный и простой в использовании API для обработки и преобразования изображений для платформы Python. Вы можете установить его, используя следующую команду из вашей системной командной консоли:

Системная командная строка

>> pip install aspose-imaging-python-net

Шаги по мультипликации WMF с помощью Python

Вам понадобится aspose-imaging-python-net , чтобы попробовать следующий рабочий процесс в вашей собственной среде.

  • Загрузить файлы WMF с помощью метода Image.Load
  • Применить эффект мультипликации для изображений и фотографий;
  • Сохранение сжатого изображения на диск в поддерживаемом Aspose.Imaging формате.

Системные Требования

Aspose.Imaging для Python поддерживается во всех основных операционных системах. Просто убедитесь, что у вас есть следующие предпосылки:

  • Microsoft Windows/Linux с .NET Core Runtime.
  • Менеджер пакетов Python и PyPi.
 

Эффект мультипликации изображений WMF - Python

using Aspose.Imaging;
using Aspose.Imaging.FileFormats.Png;
using Aspose.Imaging.ImageFilters.FilterOptions;
using Aspose.Imaging.ImageOptions;
using Aspose.Imaging.Masking;
using Aspose.Imaging.Masking.Options;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
string templatesFolder = @"c:\Users\USER\Downloads";
Cartoonify();
void Cartoonify()
{
FilterImages(image =>
{
using (var processedImage = new PngImage(image))
{
image.Resize(image.Width * 2, image.Height, ResizeType.LeftTopToLeftTop);
processedImage.Cartoonify();
var gr = new Graphics(image);
gr.DrawImage(processedImage, processedImage.Width, 0);
gr.DrawLine(new Pen(Color.DarkRed, 3), processedImage.Width, 0, processedImage.Width, image.Height);
}
}, "cartoonify");
}
string RasterizeVectorImage(string formatExt, string inputFile)
{
string outputFile = Path.Combine(templatesFolder, $"rasterized.{formatExt}.png");
using (var image = Image.Load(inputFile))
{
image.Save(outputFile, new PngOptions());
}
return outputFile;
}
void FilterImages(Action<RasterImage> doFilter, string filterName)
{
List<string> rasterFormats = new List<string>() { "jpg", "png", "bmp", "apng", "dicom",
"jp2", "j2k", "tga", "webp", "tif", "gif", "ico" };
List<string> vectorFormats = new List<string>() { "svg", "otg", "odg", "eps", "wmf", "emf", "wmz", "emz", "cmx", "cdr" };
List<string> allFormats = new List<string>(rasterFormats);
allFormats.AddRange(vectorFormats);
allFormats.ForEach(
formatExt =>
{
var inputFile = Path.Combine(templatesFolder, $"template.{formatExt}");
bool isVectorFormat = vectorFormats.IndexOf(formatExt) > -1;
//Need to rasterize vector formats before background remove
if (isVectorFormat)
{
inputFile = RasterizeVectorImage(formatExt, inputFile);
}
var outputFile = Path.Combine(templatesFolder, $"{filterName}_{formatExt}.png");
Console.WriteLine($"Processing {formatExt}");
using (var image = (RasterImage)Image.Load(inputFile))
{
doFilter(image);
//If image is multipage save each page to png to demonstrate results
if (image is IMultipageImage multiPage && multiPage.PageCount > 1)
{
for (var pageIndex = 0; pageIndex < multiPage.PageCount; pageIndex++)
{
string fileName = $"{filterName}_page{pageIndex}_{formatExt}.png";
multiPage.Pages[pageIndex].Save(templatesFolder + fileName, new PngOptions());
File.Delete(templatesFolder + fileName);
}
}
else
{
image.Save(outputFile, new PngOptions());
File.Delete(outputFile);
}
}
//Remove rasterized vector image
if (isVectorFormat)
{
File.Delete(inputFile);
}
}
);
}
static class ImageFilterExtensions
{
public static void Cartoonify(this RasterImage image)
{
using var outlines = image.DetectOutlines(Color.Black);
image.AdjustBrightness(30);
image.Filter(image.Bounds, new MedianFilterOptions(7));
var gr = new Graphics(image);
gr.DrawImage(outlines, Point.Empty);
}
public static RasterImage DetectOutlines(this RasterImage image, Color outlineColor)
{
var outlines = new PngImage(image);
outlines
.GetDataContext()
.ApplyConvolutionFilter(ConvolutionFilterOptions.Blur)
.ApplyConvolutionFilter(ConvolutionFilterOptions.Outline)
.ApplyData();
outlines.BinarizeFixed(30);
ImageMasking.ApplyMask(outlines, outlines, new MaskingOptions() { BackgroundReplacementColor = Color.Transparent });
outlines.ReplaceColor(Color.FromArgb(255, 255, 255), 0, outlineColor);
outlines.ApplyConvolutionFilter(ConvolutionFilterOptions.Blur);
return outlines;
}
public static RasterImage ApplyOperationToRasterImage(this RasterImage image, Action<RasterImage> operation)
{
if (image is IMultipageImage multipage)
{
foreach (var page in multipage.Pages)
{
operation.Invoke((RasterImage)page);
}
}
else
{
operation.Invoke(image);
}
return image;
}
public static RasterImage ApplyFilter(this RasterImage image, FilterOptionsBase filterOptions)
{
return image.ApplyOperationToRasterImage(img =>
{
img.Filter(img.Bounds, filterOptions);
});
}
public static RasterImage ApplyConvolutionFilter(this RasterImage image, ConvolutionFilterOptions filterOptions)
{
return image.ApplyOperationToRasterImage(img =>
{
var pixelsLoader = new ImagePixelsLoader(img.Bounds);
img.LoadPartialArgb32Pixels(img.Bounds, pixelsLoader);
var outBuffer = new PixelBuffer(img.Bounds, new int[img.Width * img.Height]);
ConvolutionFilter.DoFiltering(pixelsLoader.PixelsBuffer, outBuffer, filterOptions);
img.SaveArgb32Pixels(outBuffer.Rectangle, outBuffer.Pixels);
});
}
public static IImageDataContext GetDataContext(this RasterImage image)
{
IPixelBuffer GetImageBuffer(RasterImage img)
{
var pixelsLoader = new ImagePixelsLoader(img.Bounds);
img.LoadPartialArgb32Pixels(img.Bounds, pixelsLoader);
return pixelsLoader.PixelsBuffer;
}
if (image is IMultipageImage multipage)
{
return new MultipageDataContext(
multipage.Pages.Select(page => new ImageDataContext((RasterImage)page)
{
Buffer = GetImageBuffer((RasterImage)page)
}));
}
return new ImageDataContext(image)
{
Buffer = GetImageBuffer(image)
};
}
public static IImageDataContext ApplyToDataContext(this IImageDataContext dataContext,
Func<IPixelBuffer, IPixelBuffer> processor)
{
if (dataContext is MultipageDataContext multipage)
{
foreach (var context in multipage)
{
context.Buffer = processor.Invoke(context.Buffer);
}
}
if (dataContext is ImageDataContext imageDataContext)
{
imageDataContext.Buffer = processor.Invoke(imageDataContext.Buffer);
}
return dataContext;
}
public static IImageDataContext ApplyConvolutionFilter(this IImageDataContext dataContext,
ConvolutionFilterOptions filterOptions)
{
return dataContext.ApplyToDataContext(buffer =>
{
var outBuffer = new PixelBuffer(buffer.Rectangle, new int[buffer.Rectangle.Width * buffer.Rectangle.Height]);
ConvolutionFilter.DoFiltering(buffer, outBuffer, filterOptions);
return outBuffer;
});
}
}
class ConvolutionFilter
{
public static void DoFiltering(
IPixelBuffer inputBuffer,
IPixelBuffer outputBuffer,
ConvolutionFilterOptions options)
{
var factor = options.Factor;
var bias = options.Bias;
var kernel = options.Kernel;
var filterWidth = kernel.GetLength(1);
var filterCenter = (filterWidth - 1) / 2;
int x, y;
int filterX, filterY, filterPx, filterPy, filterYPos, pixel;
double r, g, b, kernelValue;
int top = inputBuffer.Rectangle.Top;
int bottom = inputBuffer.Rectangle.Bottom;
int left = inputBuffer.Rectangle.Left;
int right = inputBuffer.Rectangle.Right;
for (y = top; y < bottom; y++)
{
for (x = left; x < right; x++)
{
r = 0;
g = 0;
b = 0;
for (filterY = -filterCenter; filterY <= filterCenter; filterY++)
{
filterYPos = filterY + filterCenter;
filterPy = filterY + y;
if (filterPy >= top && filterPy < bottom)
{
for (filterX = -filterCenter; filterX <= filterCenter; filterX++)
{
filterPx = filterX + x;
if (filterPx >= left && filterPx < right)
{
kernelValue = kernel[filterYPos, filterX + filterCenter];
pixel = inputBuffer[filterPx, filterPy];
r += ((pixel >> 16) & 0xFF) * kernelValue;
g += ((pixel >> 8) & 0xFF) * kernelValue;
b += (pixel & 0xFF) * kernelValue;
}
}
}
}
r = (factor * r) + bias;
g = (factor * g) + bias;
b = (factor * b) + bias;
r = r > 255 ? 255 : (r < 0 ? 0 : r);
g = g > 255 ? 255 : (g < 0 ? 0 : g);
b = b > 255 ? 255 : (b < 0 ? 0 : b);
outputBuffer[x, y] = ((inputBuffer[x, y] >> 24) << 24) | ((byte)r << 16) | ((byte)g << 8) | (byte)b;
}
}
}
}
class ConvolutionFilterOptions
{
public double Factor { get; set; } = 1.0;
public int Bias { get; set; } = 0;
public double[,] Kernel { get; set; }
public static ConvolutionFilterOptions Blur
{
get
{
return new ConvolutionFilterOptions
{
Kernel = new double[,] { { 1, 2, 1 }, { 2, 4, 2 }, { 1, 2, 1 } },
Factor = 0.25 * 0.25
};
}
}
public static ConvolutionFilterOptions Sharpen
{
get
{
return new ConvolutionFilterOptions
{
Kernel = new double[,] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } }
};
}
}
public static ConvolutionFilterOptions Emboss
{
get
{
return new ConvolutionFilterOptions
{
Kernel = new double[,] { { -2, -1, 0 }, { -1, 1, 1 }, { 0, 1, 2 } }
};
}
}
public static ConvolutionFilterOptions Outline
{
get
{
return new ConvolutionFilterOptions
{
Kernel = new double[,] { { -1, -1, -1 }, { -1, 8, -1 }, { -1, -1, -1 } }
};
}
}
public static ConvolutionFilterOptions BottomSobel
{
get
{
return new ConvolutionFilterOptions
{
Kernel = new double[,] { { -1, -2, -1 }, { 0, 0, 0 }, { 1, 2, 1 } }
};
}
}
public static ConvolutionFilterOptions TopSobel
{
get
{
return new ConvolutionFilterOptions
{
Kernel = new double[,] { { 1, 2, 1 }, { 0, 0, 0 }, { -1, -2, -1 } }
};
}
}
public static ConvolutionFilterOptions LeftSobel
{
get
{
return new ConvolutionFilterOptions
{
Kernel = new double[,] { { 1, 0, -1 }, { 2, 0, -2 }, { 1, 0, -1 } }
};
}
}
public static ConvolutionFilterOptions RightSobel
{
get
{
return new ConvolutionFilterOptions
{
Kernel = new double[,] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } }
};
}
}
}
interface IImageDataContext
{
void ApplyData();
}
class ImageDataContext : IImageDataContext
{
public ImageDataContext(RasterImage image)
{
this.Image = image;
}
public RasterImage Image { get; }
public IPixelBuffer Buffer { get; set; }
public void ApplyData()
{
this.Buffer.SaveToImage(this.Image);
}
}
class MultipageDataContext : List<ImageDataContext>, IImageDataContext
{
public MultipageDataContext(IEnumerable<ImageDataContext> enumerable) : base(enumerable)
{
}
public void ApplyData()
{
foreach (var context in this)
{
context.ApplyData();
}
}
}
class ImagePixelsLoader : IPartialArgb32PixelLoader
{
public ImagePixelsLoader(Aspose.Imaging.Rectangle rectangle)
{
this.PixelsBuffer = new CompositePixelBuffer(rectangle);
}
public CompositePixelBuffer PixelsBuffer { get; }
public void Process(Aspose.Imaging.Rectangle pixelsRectangle, int[] pixels, Point start, Point end)
{
this.PixelsBuffer.AddPixels(pixelsRectangle, pixels);
}
}
interface IPixelBuffer
{
Aspose.Imaging.Rectangle Rectangle { get; }
int this[int x, int y]
{
get;
set;
}
void SaveToImage(RasterImage image);
}
class PixelBuffer : IPixelBuffer
{
public PixelBuffer(Aspose.Imaging.Rectangle rectangle, int[] pixels)
{
this.Rectangle = rectangle;
this.Pixels = pixels;
}
public Aspose.Imaging.Rectangle Rectangle { get; }
public int[] Pixels { get; }
public int this[int x, int y]
{
get => this.Pixels[this.GetIndex(x, y)];
set => this.Pixels[this.GetIndex(x, y)] = value;
}
public void SaveToImage(RasterImage image)
{
image.SaveArgb32Pixels(this.Rectangle, this.Pixels);
}
public bool Contains(int x, int y)
{
return this.Rectangle.Contains(x, y);
}
private int GetIndex(int x, int y)
{
x -= this.Rectangle.Left;
y -= this.Rectangle.Top;
return x + y * this.Rectangle.Width;
}
}
class CompositePixelBuffer : IPixelBuffer
{
private readonly List<PixelBuffer> _buffers = new List<PixelBuffer>();
public CompositePixelBuffer(Aspose.Imaging.Rectangle rectangle)
{
this.Rectangle = rectangle;
}
public Aspose.Imaging.Rectangle Rectangle { get; }
public int this[int x, int y]
{
get => this.GetBuffer(x, y)[x, y];
set => this.GetBuffer(x, y)[x, y] = value;
}
public void SaveToImage(RasterImage image)
{
foreach (var pixelBuffer in this._buffers)
{
pixelBuffer.SaveToImage(image);
}
}
public IEnumerable<PixelBuffer> Buffers => this._buffers;
public void AddPixels(Aspose.Imaging.Rectangle rectangle, int[] pixels)
{
if (this.Rectangle.IntersectsWith(rectangle))
{
this._buffers.Add(new PixelBuffer(rectangle, pixels));
}
}
private PixelBuffer GetBuffer(int x, int y)
{
return this._buffers.First(b => b.Contains(x, y));
}
}
 
  • Об Aspose.Imaging for Python API

    Aspose.Imaging API — это решение для обработки изображений, позволяющее создавать, изменять, рисовать или конвертировать изображения и фотографии в приложениях. Он предлагает: кросс-платформенную обработку изображений, включая, помимо прочего, преобразования между различными форматами изображений (включая единую многостраничную или многокадровую обработку изображений), модификации, такие как рисование, работа с графическими примитивами, преобразования (изменение размера, обрезка, отражение и поворот), бинаризация, оттенки серого, настройка яркости, контрастности, расширенные функции обработки изображений (фильтрация, дизеринг, маскирование, устранение перекоса) и стратегии оптимизации памяти. Это автономная библиотека, которая не зависит от какого-либо программного обеспечения для операций с изображениями. Можно легко добавить в проекты высокопроизводительные функции преобразования изображений с помощью собственных API. Это 100% частные локальные API, а изображения обрабатываются на ваших серверах.

    Cartoonify WMF через онлайн-приложение

    Оживите документы WMF эффектом мультипликации, посетив наш веб-сайт Live Demos . Online примеры имеют следующие преимущества

      Не нужно ничего скачивать или настраивать
      Нет необходимости писать какой-либо код
      Просто загрузите свои файлы WMF и нажмите кнопку "Cartoonify now".
      Мгновенно получить ссылку для скачивания результирующего файла

    WMF Чем является WMF формат

    Файлы с расширением WMF представляют собой метафайл Microsoft Windows (WMF) для хранения данных векторных и растровых изображений. Чтобы быть более точным, WMF принадлежит к категории форматов векторных файлов форматов графических файлов, которые не зависят от устройства. Интерфейс графических устройств Windows (GDI) использует функции, хранящиеся в файле WMF, для отображения изображения на экране. Более расширенная версия WMF, известная как Enhanced Meta Files (EMF), была опубликована позже, что делает формат более многофункциональным. Практически WMF похож на SVG.

    Читать далее

    Другие поддерживаемые форматы для эффекта мультипликации (Cartoonify)

    Используя Python, можно легко применять эффект мультипликации для различных форматов, в том числе:

    APNG (Анимированная портативная сетевая графика)
    BMP (Растровое изображение)
    ICO (Значок Windows)
    JPG (Объединенная группа экспертов по фотографии)
    JPEG (Объединенная группа экспертов по фотографии)
    DIB (Независимое от устройства растровое изображение)
    DICOM (Цифровая визуализация и связь)
    DJVU (Графический формат)
    DNG (Изображение цифровой камеры)
    EMF (Расширенный формат метафайла)
    EMZ (Сжатый расширенный метафайл Windows)
    GIF (Графический формат обмена)
    JP2 (JPEG 2000)
    J2K (Сжатое изображение вейвлета)
    PNG (Портативная сетевая графика)
    TIFF (Формат изображения с тегами)
    TIF (Формат изображения с тегами)
    WEBP (Растровое веб-изображение)
    WMZ (Сжатая оболочка проигрывателя Windows Media)
    TGA (Тарга Графика)
    SVG (Масштабируемая векторная графика)
    EPS (Инкапсулированный язык PostScript)
    CDR (Векторный рисунок изображения)
    CMX (Обмен изображениями Corel)
    OTG (Стандарт OpenDocument)
    ODG (Формат отрисовки Apache OpenOffice)