PPTX DOCX XLSX PDF ODP
Aspose.Imaging  สำหรับ Python
WMF

ใช้ Python สำหรับ WMF รูปภาพที่เป็นการ์ตูน

สร้างแอป Python เพื่อสร้างการ์ตูน WMF รูปภาพและรูปภาพผ่าน Server API

วิธีทำให้รูปภาพและรูปถ่ายเป็นการ์ตูน WMF ด้วย Python

เราจะตอบสนองต่อภาพการ์ตูนโดยอัตโนมัติเนื่องจากความสามารถในการปลุกเร้าความคิดถึง ภายในขอบเขตของการออกแบบกราฟิก รูปภาพสไตล์การ์ตูนทำหน้าที่เป็นองค์ประกอบสำคัญที่มักพบเห็นในบทความทางการตลาด เอฟเฟกต์ Cartoonify นี้เกี่ยวข้องกับการแปลงภาพถ่ายบุคคลให้เป็นภาพที่วาดด้วยมือ การปรับความสว่าง การแปลงเป็นขาวดำ การเล่นกับจานสี และการผสมผสานเทคนิคการแก้ไขต่าง ๆ เข้าด้วยกันเพื่อสร้างเอฟเฟกต์ภาพที่ซับซ้อน ชุดฟิลเตอร์รูปภาพ รวมถึง ‘AdjustBrightness’, ‘BinarizeFixed’, ‘Filter’, ‘ReplaceColor’ และ ‘ApplyMask’ ช่วยให้ผู้ใช้บรรลุการเปลี่ยนแปลงเหล่านี้ได้ ตัวกรองเหล่านี้สามารถใช้กับภาพและภาพถ่ายรูปแบบต้นฉบับที่ดาวน์โหลดได้ ภาพสไตล์การ์ตูนเหมาะสำหรับวัตถุประสงค์ในการอธิบายบนหน้าเว็บที่หลากหลาย เพิ่มความมีชีวิตชีวาให้กับบทความทางวิทยาศาสตร์ และทำให้เนื้อหาน่าสนใจยิ่งขึ้นสำหรับผู้ใช้ ต่อมาได้เพิ่มการเข้าชมไซต์ ในการสร้างเอฟเฟกต์การ์ตูนโดยใช้รูปภาพ WMF เราจะจ้าง Aspose.Imaging สำหรับ Python ผ่าน .NET API ซึ่งเป็น API การจัดการรูปภาพและการแปลงที่มีคุณลักษณะหลากหลาย ทรงพลัง และใช้งานง่ายสำหรับแพลตฟอร์ม Python คุณสามารถติดตั้งได้โดยใช้คำสั่งต่อไปนี้จากคำสั่งระบบของคุณ

บรรทัดคำสั่งของระบบ

>> pip install aspose-imaging-python-net

ขั้นตอนในการ การ์ตูน WMFs ผ่าน 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 สำหรับ Python API

    Aspose.Imaging API เป็นโซลูชันการประมวลผลรูปภาพเพื่อสร้าง แก้ไข วาดหรือแปลงรูปภาพ (ภาพถ่าย) ภายในแอปพลิเคชัน นำเสนอ: การประมวลผลภาพข้ามแพลตฟอร์ม รวมถึงแต่ไม่จำกัดเพียงการแปลงระหว่างรูปแบบภาพต่างๆ (รวมถึงการประมวลผลภาพแบบหลายหน้าหรือหลายเฟรมแบบเดียวกัน) การปรับเปลี่ยน เช่น การวาด การทำงานกับภาพกราฟิกดั้งเดิม การแปลงภาพ (ปรับขนาด ครอบตัด พลิกและหมุน , ไบนารี, ระดับสีเทา, ปรับ), คุณสมบัติการจัดการภาพขั้นสูง (การกรอง, การแยกสี, การปิดบัง, การเดสก์) และกลยุทธ์การปรับหน่วยความจำให้เหมาะสม เป็นไลบรารีแบบสแตนด์อโลนและไม่ขึ้นกับซอฟต์แวร์ใด ๆ สำหรับการทำงานของรูปภาพ คุณสามารถเพิ่มคุณสมบัติการแปลงรูปภาพประสิทธิภาพสูงด้วย API ดั้งเดิมภายในโปรเจ็กต์ได้อย่างง่ายดาย สิ่งเหล่านี้เป็น API ภายในองค์กรที่เป็นส่วนตัว 100% และอิมเมจได้รับการประมวลผลที่เซิร์ฟเวอร์ของคุณ

    การ์ตูน WMFs ผ่านแอปออนไลน์

    การ์ตูน WMF เอกสารโดยไปที่ เว็บไซต์ Live Demos การสาธิตสดมีประโยชน์ดังต่อไปนี้

      ไม่จำเป็นต้องดาวน์โหลดหรือตั้งค่าอะไรเลย
      ไม่ต้องเขียนโค้ดใดๆ
      เพียงอัปโหลดไฟล์ WMF ของคุณและกดปุ่ม การ์ตูน
      รับลิงค์ดาวน์โหลดทันทีสำหรับไฟล์ผลลัพธ์

    WMF คืออะไร WMF รูปแบบไฟล์

    ไฟล์ที่มีนามสกุล WMF แสดงถึง Microsoft Windows Metafile (WMF) สำหรับการจัดเก็บข้อมูลเวกเตอร์และรูปแบบบิตแมป เพื่อให้แม่นยำยิ่งขึ้น WMF อยู่ในหมวดหมู่รูปแบบไฟล์เวกเตอร์ของรูปแบบไฟล์กราฟิกที่ไม่ขึ้นกับอุปกรณ์ Windows Graphical Device Interface (GDI) ใช้ฟังก์ชันที่จัดเก็บไว้ในไฟล์ WMF เพื่อแสดงภาพบนหน้าจอ WMF เวอร์ชันที่ได้รับการปรับปรุงมากขึ้น หรือที่เรียกว่า Enhanced Meta Files (EMF) ได้รับการเผยแพร่ในภายหลัง ซึ่งทำให้รูปแบบมีคุณลักษณะที่สมบูรณ์ยิ่งขึ้น ในทางปฏิบัติ WMF จะคล้ายกับ SVG

    อ่านเพิ่มเติม

    รูปแบบ การ์ตูน อื่น ๆ ที่รองรับ

    การใช้ Python จะทำให้สร้างการ์ตูนในรูปแบบต่างๆ ได้อย่างง่ายดาย เช่น

    APNG (กราฟิกเครือข่ายแบบพกพาแบบเคลื่อนไหว)
    BMP (รูปภาพบิตแมป)
    ICO (ไอคอน Windows)
    JPG (กลุ่มผู้เชี่ยวชาญด้านการถ่ายภาพร่วม)
    JPEG (กลุ่มผู้เชี่ยวชาญด้านการถ่ายภาพร่วม)
    DIB (บิตแมปอิสระของอุปกรณ์)
    DICOM (การถ่ายภาพและการสื่อสารดิจิทัล)
    DJVU (รูปแบบกราฟิก)
    DNG (ภาพกล้องดิจิตอล)
    EMF (รูปแบบไฟล์ Metafile ที่ปรับปรุงแล้ว)
    EMZ (Windows บีบอัด Metafile ที่ปรับปรุงแล้ว)
    GIF (รูปแบบการแลกเปลี่ยนกราฟิก)
    JP2 (JPEG 2000)
    J2K (ภาพบีบอัดเวฟเล็ต)
    PNG (กราฟิกเครือข่ายแบบพกพา)
    TIFF (รูปแบบภาพที่ติดแท็ก)
    TIF (รูปแบบภาพที่ติดแท็ก)
    WEBP (รูปภาพเว็บแรสเตอร์)
    WMZ (สกิน Windows Media Player ที่บีบอัด)
    TGA (Targa Graphic)
    SVG (กราฟิกแบบเวกเตอร์ที่ปรับขนาดได้)
    EPS (ภาษา PostScript ที่ห่อหุ้ม)
    CDR (วาดภาพเวกเตอร์)
    CMX (รูปภาพ Corel Exchange)
    OTG (มาตรฐาน OpenDocument)
    ODG (รูปแบบการวาด Apache OpenOffice)