|
16 | 16 | using PasteIntoFile.Properties; |
17 | 17 | using PdfSharp.Drawing; |
18 | 18 | using PdfSharp.Pdf; |
19 | | -using SkiaSharp; |
| 19 | +using WebP; |
20 | 20 |
|
21 | 21 | namespace PasteIntoFile { |
22 | 22 |
|
@@ -186,20 +186,17 @@ public override void SaveAs(string path, string extension, bool append = false) |
186 | 186 | if (image == null) |
187 | 187 | throw new FormatException(string.Format(Resources.str_error_cliboard_format_missmatch, extension)); |
188 | 188 |
|
189 | | - var stream = new MemoryStream(); |
190 | | - image.Save(stream, image.RawFormat); |
191 | | - stream.Position = 0; |
192 | 189 |
|
193 | 190 | switch (NormalizeExtension(extension)) { |
194 | 191 | case "webp": |
195 | | - //SKImage.FromEncodedData(stream).Encode(SKEncodedImageFormat.Webp, 90).SaveTo(File.OpenWrite(path)); |
196 | | - var webp = SKBitmap.Decode(stream).PeekPixels().Encode(new SKWebpEncoderOptions(SKWebpEncoderCompression.Lossless, 100)); |
197 | | - using (var fs = new FileStream(path, FileMode.Create)) { |
198 | | - webp.SaveTo(fs); |
199 | | - return; |
200 | | - } |
| 192 | + var bytes = new WebPObject(image).GetWebPLossless(); |
| 193 | + File.WriteAllBytes(path, bytes); |
| 194 | + return; |
201 | 195 | case "pdf": |
202 | 196 | // convert image to ximage |
| 197 | + var stream = new MemoryStream(); |
| 198 | + image.Save(stream, image.RawFormat); |
| 199 | + stream.Position = 0; |
203 | 200 | XImage img = XImage.FromStream(stream); |
204 | 201 | // create pdf document |
205 | 202 | PdfDocument document = new PdfDocument(); |
@@ -235,10 +232,12 @@ public override PreviewHolder Preview(string extension) { |
235 | 232 | // Special formats with intermediate conversion types |
236 | 233 | switch (extension) { |
237 | 234 | case "pdf": |
238 | | - case "webp": |
239 | 235 | // Use png as intermediate format |
240 | 236 | extension = "png"; |
241 | 237 | break; |
| 238 | + case "webp": |
| 239 | + // Lossless as-is |
| 240 | + return PreviewHolder.ForImage(Image); |
242 | 241 | case "ico": |
243 | 242 | return PreviewHolder.ForImage(ImageAsIcon.ToBitmap()); |
244 | 243 | } |
@@ -300,7 +299,8 @@ public TransparentImageContent(Image image) : base(image) { } |
300 | 299 | /// Like ImageContent, but only for formats which support animated frames |
301 | 300 | /// </summary> |
302 | 301 | public class AnimatedImageContent : ImageContent { |
303 | | - public static new readonly string[] EXTENSIONS = { "gif" }; // TODO: in principle "webp" can also support animated frames |
| 302 | + // TODO: in principle "webp" can also support animated frames, but the library we use doesn't support it |
| 303 | + public static new readonly string[] EXTENSIONS = { "gif" }; |
304 | 304 | public AnimatedImageContent(Image image) : base(image) { } |
305 | 305 | public override string[] Extensions => EXTENSIONS; |
306 | 306 | } |
@@ -1008,31 +1008,9 @@ public static ClipboardContents FromFile(string path) { |
1008 | 1008 | // add the file itself |
1009 | 1009 | container.Contents.Add(new FilesContent(new StringCollection { path })); |
1010 | 1010 |
|
1011 | | - // if it's an image (try&catch instead of maintaining a list of supported extensions) |
1012 | | - try { |
1013 | | - var img = Image.FromFile(path); |
1014 | | - img = RotateFlipImageFromExif(img); |
1015 | | - if (img is Metafile mf) { |
1016 | | - container.Contents.Add(new VectorImageContent(mf)); |
1017 | | - } else { |
1018 | | - container.Contents.Add(new ImageContent(img)); |
1019 | | - } |
1020 | | - } catch { |
1021 | | - // Try again with Skia (to support webp) |
1022 | | - try { |
1023 | | - using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { |
1024 | | - var img = SKBitmap.Decode(fs); |
1025 | | - using (var stream = img.PeekPixels().Encode(SKPngEncoderOptions.Default).AsStream()) { |
1026 | | - if (img.AlphaType == SKAlphaType.Opaque) { |
1027 | | - container.Contents.Add(new ImageContent(Image.FromStream(stream))); |
1028 | | - } else { |
1029 | | - // TODO: FIXME: transparency seems to get lost during conversion |
1030 | | - container.Contents.Add(new TransparentImageContent(Image.FromStream(stream))); |
1031 | | - } |
1032 | | - } |
1033 | | - } |
1034 | | - } catch { /* it's not */ } |
1035 | | - } |
| 1011 | + // if it's an image |
| 1012 | + if (ImageContentFromBytes(ext, File.ReadAllBytes(path)) is BaseContent content) |
| 1013 | + container.Contents.Add(content); |
1036 | 1014 |
|
1037 | 1015 |
|
1038 | 1016 | // if it's text like (check for absence of zero byte) |
@@ -1114,6 +1092,38 @@ private static Image ImageFromDataUri(string uri) { |
1114 | 1092 | return null; |
1115 | 1093 | } |
1116 | 1094 |
|
| 1095 | + private static ImageLikeContent ImageContentFromBytes(string ext, byte[] bytes) { |
| 1096 | + try { |
| 1097 | + if (ext == "webp") { |
| 1098 | + var webp = new WebPObject(bytes); |
| 1099 | + var img = new Bitmap(webp.GetImage()); // create copy |
| 1100 | + if (webp.GetInfo().IsAnimated) |
| 1101 | + return new AnimatedImageContent(img); |
| 1102 | + if (webp.GetInfo().HasAlpha) |
| 1103 | + return new TransparentImageContent(img); |
| 1104 | + return new ImageContent(img); |
| 1105 | + } |
| 1106 | + } catch (Exception e) { /* not a webp, or an animated webp which we don't support yet */ |
| 1107 | + Console.WriteLine(e); |
| 1108 | + } |
| 1109 | + try { |
| 1110 | + var img = Image.FromStream(new MemoryStream(bytes)); |
| 1111 | + img = RotateFlipImageFromExif(img); |
| 1112 | + if (img is Metafile mf) |
| 1113 | + return new VectorImageContent(mf); |
| 1114 | + try { |
| 1115 | + if (img.GetFrameCount(FrameDimension.Time) > 1) |
| 1116 | + return new AnimatedImageContent(img); |
| 1117 | + } catch { /* not an animated image */ } |
| 1118 | + if (((ImageFlags)img.Flags).HasFlag(ImageFlags.HasAlpha)) |
| 1119 | + return new TransparentImageContent(img); |
| 1120 | + return new ImageContent(img); |
| 1121 | + } catch (Exception e) { /* not an image? */ |
| 1122 | + Console.WriteLine(e); |
| 1123 | + } |
| 1124 | + return null; |
| 1125 | + } |
| 1126 | + |
1117 | 1127 | /// <summary> |
1118 | 1128 | /// Rotates and flips the given image according to the respective EXIF flag, and remove the EXIF flag |
1119 | 1129 | /// </summary> |
|
0 commit comments