[androidkit] Introduce Image support
Two sources from now: - encoded data factory - Surface.makeImageSnapshot() Change-Id: Icbf2f855e489839dc82db425916c8644418a2fb7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/410324 Reviewed-by: Jorge Betancourt <jmbetancourt@google.com> Commit-Queue: Florin Malita <fmalita@google.com>
This commit is contained in:
parent
25be58e24b
commit
934c02142e
1
BUILD.gn
1
BUILD.gn
@ -2495,6 +2495,7 @@ if (skia_enable_tools) {
|
||||
sources = [
|
||||
"modules/androidkit/src/AndroidKit.cpp",
|
||||
"modules/androidkit/src/Canvas.cpp",
|
||||
"modules/androidkit/src/Image.cpp",
|
||||
"modules/androidkit/src/Matrix.cpp",
|
||||
"modules/androidkit/src/Paint.cpp",
|
||||
"modules/androidkit/src/RuntimeShaderBuilder.cpp",
|
||||
|
@ -24,6 +24,7 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
}
|
||||
|
||||
REGISTER_NATIVES(Canvas)
|
||||
REGISTER_NATIVES(Image)
|
||||
REGISTER_NATIVES(Matrix)
|
||||
REGISTER_NATIVES(Paint)
|
||||
REGISTER_NATIVES(RuntimeShaderBuilder)
|
||||
|
@ -79,6 +79,16 @@ void Canvas_DrawRect(JNIEnv* env, jobject, jlong native_instance,
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas_DrawImage(JNIEnv* env, jobject, jlong native_instance, jlong native_image,
|
||||
jfloat x, jfloat y) {
|
||||
auto* canvas = reinterpret_cast<SkCanvas*>(native_instance);
|
||||
auto* image = reinterpret_cast<SkImage *>(native_image);
|
||||
|
||||
if (canvas && image) {
|
||||
canvas->drawImage(image, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int register_androidkit_Canvas(JNIEnv* env) {
|
||||
@ -92,6 +102,7 @@ int register_androidkit_Canvas(JNIEnv* env) {
|
||||
{"nConcat16f" , "(J[F)V" , reinterpret_cast<void*>(Canvas_Concat16f) },
|
||||
{"nDrawColor" , "(JFFFF)V" , reinterpret_cast<void*>(Canvas_DrawColor) },
|
||||
{"nDrawRect" , "(JFFFFJ)V", reinterpret_cast<void*>(Canvas_DrawRect) },
|
||||
{"nDrawImage" , "(JJFF)V" , reinterpret_cast<void*>(Canvas_DrawImage) },
|
||||
};
|
||||
|
||||
const auto clazz = env->FindClass("org/skia/androidkit/Canvas");
|
||||
|
53
modules/androidkit/src/Image.cpp
Normal file
53
modules/androidkit/src/Image.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "include/core/SkImage.h"
|
||||
|
||||
namespace {
|
||||
|
||||
jlong Image_Create(JNIEnv* env, jobject, jbyteArray jdata) {
|
||||
auto size = env->GetArrayLength(jdata);
|
||||
auto* data = env->GetByteArrayElements(jdata, nullptr);
|
||||
auto image = SkImage::MakeFromEncoded(SkData::MakeWithCopy(data, SkToSizeT(size)));
|
||||
|
||||
env->ReleaseByteArrayElements(jdata, data, 0);
|
||||
|
||||
return reinterpret_cast<jlong>(image.release());
|
||||
}
|
||||
|
||||
void Image_Release(JNIEnv*, jobject, jlong native_instance) {
|
||||
SkSafeUnref(reinterpret_cast<const SkImage*>(native_instance));
|
||||
}
|
||||
|
||||
jint Image_GetWidth(JNIEnv*, jobject, jlong native_instance) {
|
||||
const auto* image = reinterpret_cast<const SkImage*>(native_instance);
|
||||
return image ? image->width() : 0;
|
||||
}
|
||||
|
||||
jint Image_GetHeight(JNIEnv*, jobject, jlong native_instance) {
|
||||
const auto* image = reinterpret_cast<const SkImage*>(native_instance);
|
||||
return image ? image->height() : 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int register_androidkit_Image(JNIEnv* env) {
|
||||
static const JNINativeMethod methods[] = {
|
||||
{"nCreate" , "([B)J", reinterpret_cast<void*>(Image_Create) },
|
||||
{"nRelease" , "(J)V" , reinterpret_cast<void*>(Image_Release) },
|
||||
|
||||
{"nGetWidth" , "(J)I" , reinterpret_cast<void*>(Image_GetWidth) },
|
||||
{"nGetHeight", "(J)I" , reinterpret_cast<void*>(Image_GetHeight)},
|
||||
};
|
||||
|
||||
const auto clazz = env->FindClass("org/skia/androidkit/Image");
|
||||
return clazz
|
||||
? env->RegisterNatives(clazz, methods, SK_ARRAY_COUNT(methods))
|
||||
: JNI_ERR;
|
||||
}
|
@ -225,35 +225,45 @@ static void Surface_FlushAndSubmit(JNIEnv* env, jobject, jlong native_surface) {
|
||||
}
|
||||
}
|
||||
|
||||
static int Surface_GetWidth(JNIEnv* env, jobject, jlong native_surface) {
|
||||
static jint Surface_GetWidth(JNIEnv* env, jobject, jlong native_surface) {
|
||||
const auto* surface = reinterpret_cast<Surface*>(native_surface);
|
||||
return surface ? surface->width() : 0;
|
||||
}
|
||||
|
||||
static int Surface_GetHeight(JNIEnv* env, jobject, jlong native_surface) {
|
||||
static jint Surface_GetHeight(JNIEnv* env, jobject, jlong native_surface) {
|
||||
const auto* surface = reinterpret_cast<Surface*>(native_surface);
|
||||
return surface ? surface->height() : 0;
|
||||
}
|
||||
|
||||
static jlong Surface_MakeSnapshot(JNIEnv* env, jobject, jlong native_surface) {
|
||||
if (const auto* surface = reinterpret_cast<Surface*>(native_surface)) {
|
||||
auto snapshot = surface->makeImageSnapshot();
|
||||
return reinterpret_cast<jlong>(snapshot.release());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *** End of JNI methods ***
|
||||
|
||||
} // namespace
|
||||
|
||||
int register_androidkit_Surface(JNIEnv* env) {
|
||||
static const JNINativeMethod methods[] = {
|
||||
{"nCreateBitmap" , "(Landroid/graphics/Bitmap;)J",
|
||||
reinterpret_cast<void*>(Surface_CreateBitmap) },
|
||||
{"nCreateBitmap" , "(Landroid/graphics/Bitmap;)J",
|
||||
reinterpret_cast<void*>(Surface_CreateBitmap) },
|
||||
{"nCreateThreadedSurface" , "(Landroid/view/Surface;)J",
|
||||
reinterpret_cast<void*>(Surface_CreateThreadedSurface) },
|
||||
{"nCreateVKSurface", "(Landroid/view/Surface;)J",
|
||||
reinterpret_cast<void*>(Surface_CreateVK) },
|
||||
{"nCreateGLSurface", "(Landroid/view/Surface;)J",
|
||||
reinterpret_cast<void*>(Surface_CreateGL) },
|
||||
{"nRelease" , "(J)V", reinterpret_cast<void*>(Surface_Release) },
|
||||
{"nGetNativeCanvas", "(J)J", reinterpret_cast<void*>(Surface_GetNativeCanvas)},
|
||||
{"nFlushAndSubmit" , "(J)V", reinterpret_cast<void*>(Surface_FlushAndSubmit) },
|
||||
{"nGetWidth" , "(J)I", reinterpret_cast<void*>(Surface_GetWidth) },
|
||||
{"nGetHeight" , "(J)I", reinterpret_cast<void*>(Surface_GetHeight) },
|
||||
reinterpret_cast<void*>(Surface_CreateThreadedSurface) },
|
||||
{"nCreateVKSurface" , "(Landroid/view/Surface;)J",
|
||||
reinterpret_cast<void*>(Surface_CreateVK) },
|
||||
{"nCreateGLSurface" , "(Landroid/view/Surface;)J",
|
||||
reinterpret_cast<void*>(Surface_CreateGL) },
|
||||
{"nRelease" , "(J)V", reinterpret_cast<void*>(Surface_Release) },
|
||||
{"nGetNativeCanvas" , "(J)J", reinterpret_cast<void*>(Surface_GetNativeCanvas)},
|
||||
{"nFlushAndSubmit" , "(J)V", reinterpret_cast<void*>(Surface_FlushAndSubmit) },
|
||||
{"nGetWidth" , "(J)I", reinterpret_cast<void*>(Surface_GetWidth) },
|
||||
{"nGetHeight" , "(J)I", reinterpret_cast<void*>(Surface_GetHeight) },
|
||||
{"nMakeImageSnapshot", "(J)J", reinterpret_cast<void*>(Surface_MakeSnapshot) },
|
||||
};
|
||||
|
||||
const auto clazz = env->FindClass("org/skia/androidkit/Surface");
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "tools/sk_app/WindowContext.h"
|
||||
|
||||
#include "include/core/SkImage.h"
|
||||
#include "include/core/SkPictureRecorder.h"
|
||||
#include "include/core/SkRefCnt.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
@ -34,6 +35,10 @@ public:
|
||||
int width() const { return fSurface ? fSurface->width() : 0; }
|
||||
int height() const { return fSurface ? fSurface->height() : 0; }
|
||||
|
||||
sk_sp<SkImage> makeImageSnapshot() const {
|
||||
return fSurface ? fSurface->makeImageSnapshot() : nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
sk_sp<SkSurface> fSurface;
|
||||
};
|
||||
|
@ -8,6 +8,7 @@
|
||||
package org.skia.androidkit;
|
||||
|
||||
import org.skia.androidkit.Color;
|
||||
import org.skia.androidkit.Image;
|
||||
import org.skia.androidkit.Matrix;
|
||||
import org.skia.androidkit.Paint;
|
||||
import org.skia.androidkit.Surface;
|
||||
@ -70,6 +71,11 @@ public class Canvas {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: sampling options
|
||||
public void drawImage(Image image, float x, float y) {
|
||||
nDrawImage(mNativeInstance, image.getNativeInstance(), x, y);
|
||||
}
|
||||
|
||||
// package private
|
||||
Canvas(Surface surface, long native_instance) {
|
||||
mNativeInstance = native_instance;
|
||||
@ -92,4 +98,5 @@ public class Canvas {
|
||||
private static native void nDrawRect(long nativeInstance,
|
||||
float left, float right, float top, float bottom,
|
||||
long nativePaint);
|
||||
private static native void nDrawImage(long nativeInstance, long nativeImage, float x, float y);
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2021 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.skia.androidkit;
|
||||
|
||||
public class Image {
|
||||
private long mNativeInstance;
|
||||
|
||||
/**
|
||||
* Construct an Image from encoded (PNG, GIF, etc) data.
|
||||
*
|
||||
* Returns null for unsupported formats or invalid data.
|
||||
*/
|
||||
public static Image fromEncoded(byte[] encodedData) {
|
||||
long nativeImage = nCreate(encodedData);
|
||||
return nativeImage != 0
|
||||
? new Image(nativeImage)
|
||||
: null;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return nGetWidth(mNativeInstance);
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return nGetHeight(mNativeInstance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases any resources associated with this Paint.
|
||||
*/
|
||||
public void release() {
|
||||
nRelease(mNativeInstance);
|
||||
mNativeInstance = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
release();
|
||||
}
|
||||
|
||||
// package private
|
||||
Image(long nativeInstance) {
|
||||
mNativeInstance = nativeInstance;
|
||||
}
|
||||
|
||||
// package private
|
||||
long getNativeInstance() { return mNativeInstance; }
|
||||
|
||||
private static native long nCreate(byte[] encodedData);
|
||||
private static native void nRelease(long nativeInstance);
|
||||
|
||||
private static native int nGetWidth(long nativeInstance);
|
||||
private static native int nGetHeight(long nativeInstance);
|
||||
}
|
@ -12,6 +12,7 @@ import android.os.Build;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
import org.skia.androidkit.Canvas;
|
||||
import org.skia.androidkit.Image;
|
||||
|
||||
public class Surface {
|
||||
private long mNativeInstance;
|
||||
@ -51,6 +52,15 @@ public class Surface {
|
||||
return new Canvas(this, nGetNativeCanvas(mNativeInstance));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an Image capturing the Surface contents.
|
||||
* Subsequent drawing to Surface contents are not captured.
|
||||
*/
|
||||
public Image makeImageSnapshot() {
|
||||
return new Image(nMakeImageSnapshot(mNativeInstance));
|
||||
}
|
||||
|
||||
/***
|
||||
* Triggers the immediate execution of all pending draw operations.
|
||||
*
|
||||
@ -104,4 +114,5 @@ public class Surface {
|
||||
private static native void nFlushAndSubmit(long nativeInstance);
|
||||
private static native int nGetWidth(long nativeInstance);
|
||||
private static native int nGetHeight(long nativeInstance);
|
||||
private static native long nMakeImageSnapshot(long nativeInstance);
|
||||
}
|
||||
|
@ -11,9 +11,11 @@ import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.widget.ImageView;
|
||||
import java.io.InputStream;
|
||||
import org.skia.androidkit.*;
|
||||
|
||||
public class MainActivity extends Activity implements SurfaceHolder.Callback {
|
||||
@ -33,7 +35,7 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback {
|
||||
|
||||
// Bitmap
|
||||
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
|
||||
Bitmap bmp = Bitmap.createBitmap(200, 200, conf);
|
||||
Bitmap bmp = Bitmap.createBitmap(400, 400, conf);
|
||||
Surface bitmapSurface = new Surface(bmp);
|
||||
Canvas canvas = bitmapSurface.getCanvas();
|
||||
|
||||
@ -49,6 +51,20 @@ public class MainActivity extends Activity implements SurfaceHolder.Callback {
|
||||
canvas.drawRect(0, 0, 100, 100, p);
|
||||
canvas.restore();
|
||||
|
||||
Image snapshot = bitmapSurface.makeImageSnapshot();
|
||||
canvas.drawImage(snapshot, 0, 200);
|
||||
|
||||
try {
|
||||
InputStream is = getResources().openRawResource(R.raw.brickwork_texture);
|
||||
byte[] data = new byte[is.available()];
|
||||
is.read(data);
|
||||
|
||||
Image image = Image.fromEncoded(data);
|
||||
canvas.drawImage(image, 200, 0);
|
||||
} catch (Exception e) {
|
||||
Log.e("AndroidKit Demo", "Could not load Image resource: " + R.raw.brickwork_texture);
|
||||
}
|
||||
|
||||
ImageView image = findViewById(R.id.image);
|
||||
image.setImageBitmap(bmp);
|
||||
|
||||
|
@ -16,8 +16,8 @@
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="200px"
|
||||
android:layout_height="200px"
|
||||
android:layout_width="400px"
|
||||
android:layout_height="400px"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
</ImageView>
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 151 KiB |
Loading…
Reference in New Issue
Block a user