Hi!
I am currently developing an SVG editor for Android (but very likely also for iOS, UWP, etc.)
My problem now is, that I would like to store an SKBitmap to a file as PNG.
I saw that there is a SKImageEncoder which does the job, but it is not mapped yet.
Any chances this will change in the near future? (I do not like workarounds)
https://github.com/google/skia/blob/master/src/images/SkImageEncoder.cpp
If you have an SKBitmap, you can call:
var data = bitmap.Encode (SKImageEncodeFormat.Png, quality: 100);
using (var f = File.Create ("foo.png"))
data.SaveTo (f);
Unfortunately this is not true:
SKBitmap (at last in version 1.49.4-beta) does not have a method "Encode" :-|
see here: https://github.com/mono/SkiaSharp/blob/master/binding/Binding/SKBitmap.cs
AAAH! Now I think I see what the problem is!
You meant "SKImage" but wrote "SKBitmap", right? Because SKImage has an "Encode" method :)
So if I have some "SKBitmap" that I'd like to store, I'd do the following (please correct me if I'm wrong):
`
SKBitmap bitmap = ... I get it from somewhere - trust me;
using(var img = SKImage.FromPixels(bitmap.Info, bitmap.Handle, si.Width * 4))
{
var data = img.Encode(SKImageEncodeFormat.Png, quality: 100);
data.SaveTo(stream);
}
`
... no... that was definetly wrong.... but I guess I am on the right track...
I always get a SIGSEGV so I am doing something wrong, although it seems correct to me:
SKBitmap bitmap = Image;
try
{
bitmap.LockPixels();
IntPtr p;
bitmap.GetPixels(out p);
using (var img = SKImage.FromPixels(bitmap.Info, bitmap.Handle, bitmap.Width * bitmap.BytesPerPixel))
{
var data = img.Encode(SKImageEncodeFormat.Png, quality: quality);
data.SaveTo(stream);
}
}
finally
{
bitmap.UnlockPixels();
}
the stacktrace is:4
06-29 14:34:24.051 E/mono-rt (31174): Stacktrace:
06-29 14:34:24.051 E/mono-rt (31174):
06-29 14:34:24.051 E/mono-rt (31174): at<0xffffffff>
06-29 14:34:24.051 E/mono-rt (31174): at (wrapper managed-to-native) SkiaSharp.SkiaApi.sk_image_new_raster_copy (SkiaSharp.SKImageInfo&,intptr,intptr)
06-29 14:34:24.051 E/mono-rt (31174): at SkiaSharp.SKImage.FromPixels (SkiaSharp.SKImageInfo,intptr,int)
06-29 14:34:24.051 E/mono-rt (31174): at Svg.Platform.SkiaBitmap.SavePng (System.IO.Stream,int) [0x00019] in C:CodeiclSVGSVGSvg.CorePlatformSkiaBitmap.cs:66
06-29 14:34:24.051 E/mono-rt (31174): at Svg.Droid.SampleEditor.Core.Tools.SaveTool/<>c__DisplayClass3_0.b__8 (object) [0x0006d] in C:CodeiclSVGSVGSvg.Editor.Sample.CoreToolsSaveTool.cs:138
06-29 14:34:24.051 E/mono-rt (31174): at Svg.Core.Tools.ToolCommand.Execute (object) [0x00001] in C:CodeiclSVGSVGSvg.Editor.CoreToolsITool.cs:97
06-29 14:34:24.051 E/mono-rt (31174): at Svg.Droid.SampleEditor.Views.EditorView.OnOptionsItemSelected (Android.Views.IMenuItem) [0x0005d] in C:CodeiclSVGSVGSvg.Editor.Sample.DroidViewsEditorView.cs:126
06-29 14:34:24.051 E/mono-rt (31174): at Android.App.Activity.n_OnOptionsItemSelected_Landroid_view_MenuItem_ (intptr,intptr,intptr) [0x00011] in /Users/builder/data/lanes/3236/ee215fc9/source/monodroid/src/Mono.Android/platforms/android-23/src/generated/Android.App.Activity.cs:3935
06-29 14:34:24.051 E/mono-rt (31174): at (wrapper dynamic-method) object.7c4f615e-b4f8-41e0-a9ab-ecd5399d7c82 (intptr,intptr,intptr)
06-29 14:34:24.051 E/mono-rt (31174): at (wrapper native-to-managed) object.7c4f615e-b4f8-41e0-a9ab-ecd5399d7c82 (intptr,intptr,intptr)
06-29 14:34:24.051 E/mono-rt (31174):
06-29 14:34:24.051 E/mono-rt (31174): Attempting native Android stacktrace:
06-29 14:34:24.051 E/mono-rt (31174):
06-29 14:34:24.066 E/mono-rt (31174): at __memcpy_base+88 [0x400d726c]
06-29 14:34:24.066 E/mono-rt (31174): at SkData::PrivateNewWithCopy(void const*, unsigned int)+36 [0x847185e5]
06-29 14:34:24.066 E/mono-rt (31174):
06-29 14:34:24.066 E/mono-rt (31174): =================================================================
06-29 14:34:24.066 E/mono-rt (31174): Got a SIGSEGV while executing native code. This usually indicates
06-29 14:34:24.066 E/mono-rt (31174): a fatal error in the mono runtime or one of the native libraries
06-29 14:34:24.066 E/mono-rt (31174): used by your application.
06-29 14:34:24.066 E/mono-rt (31174): =================================================================
06-29 14:34:24.066 E/mono-rt (31174):
06-29 14:34:24.066 F/libc (31174): Fatal signal 11 (SIGSEGV) at 0x00019000 (code=1), thread 31174 (id.SampleEditor)
I just saw, that there is conversion function in SKIA - could that be bound in SkiaSharp?
static sk_sp<SkImage> MakeFromBitmap(const SkBitmap&);
see SKImage.h
https://github.com/google/skia/blob/master/include/core/SkImage.h
... but if I look at the implementation, I would assume that my second implementation is correct - but still it is failing...
see: SKImage.cpp
https://github.com/google/skia/blob/master/src/image/SkImage.cpp
sk_sp<SkImage> SkImage::MakeFromBitmap(const SkBitmap& bm) {
SkPixelRef* pr = bm.pixelRef();
if (nullptr == pr) {
return nullptr;
}
@gentledepp Is this still an issue?
I am thinking that you are passing the wrong IntPtr to SKImage.FromPixels:
SKBitmap bitmap = Image;
try
{
bitmap.LockPixels();
IntPtr p;
IntPtr pixels = bitmap.GetPixels(out p); // this line and the next
using (var img = SKImage.FromPixels(bitmap.Info, pixels, bitmap.Width * bitmap.BytesPerPixel))
{
var data = img.Encode(SKImageEncodeFormat.Png, quality: quality);
data.SaveTo(stream);
}
}
finally
{
bitmap.UnlockPixels();
}
You should never have to reference the object.Handle from outside the SkiaSharp library. If you have to, you can never know what the underlying native type will be.