Skip to content

Commit f53e43f

Browse files
authored
fix(🏞️): add output parameter to makeImageSnapshot() (#3155)
1 parent d48ca2b commit f53e43f

File tree

7 files changed

+38
-7
lines changed

7 files changed

+38
-7
lines changed

packages/skia/cpp/api/JsiSkImageFactory.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ namespace jsi = facebook::jsi;
1717

1818
class JsiSkImageFactory : public JsiSkHostObject {
1919
public:
20+
JSI_HOST_FUNCTION(MakeNull) {
21+
return jsi::Object::createFromHostObject(
22+
runtime, std::make_shared<JsiSkImage>(getContext(), nullptr));
23+
}
24+
2025
JSI_HOST_FUNCTION(MakeImageFromEncoded) {
2126
auto data = JsiSkData::fromValue(runtime, arguments[0]);
2227
auto image = SkImages::DeferredFromEncodedData(data);
@@ -86,6 +91,13 @@ class JsiSkImageFactory : public JsiSkHostObject {
8691
if (image == nullptr) {
8792
throw std::runtime_error("Failed to convert native texture to SkImage!");
8893
}
94+
if (count > 4 && arguments[4].isObject() &&
95+
arguments[4].asObject(runtime).isHostObject(runtime)) {
96+
auto jsiImage = arguments[4].asObject(runtime).asHostObject<JsiSkImage>(
97+
runtime);
98+
jsiImage->setObject(image);
99+
return jsi::Value(runtime, arguments[4]);
100+
}
89101
return jsi::Object::createFromHostObject(
90102
runtime, std::make_shared<JsiSkImage>(getContext(), std::move(image)));
91103
}
@@ -96,7 +108,8 @@ class JsiSkImageFactory : public JsiSkHostObject {
96108
MakeImageFromNativeBuffer),
97109
JSI_EXPORT_FUNC(JsiSkImageFactory,
98110
MakeImageFromNativeTextureUnstable),
99-
JSI_EXPORT_FUNC(JsiSkImageFactory, MakeImage))
111+
JSI_EXPORT_FUNC(JsiSkImageFactory, MakeImage),
112+
JSI_EXPORT_FUNC(JsiSkImageFactory, MakeNull))
100113

101114
explicit JsiSkImageFactory(std::shared_ptr<RNSkPlatformContext> context)
102115
: JsiSkHostObject(std::move(context)) {}

packages/skia/cpp/api/JsiSkSurface.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class JsiSkSurface : public JsiSkWrappingSkPtrHostObject<SkSurface> {
6464
JSI_HOST_FUNCTION(makeImageSnapshot) {
6565
auto surface = getObject();
6666
sk_sp<SkImage> image;
67-
if (count == 1) {
67+
if (count > 0 && arguments[0].isObject()) {
6868
auto rect = JsiSkRect::fromValue(runtime, arguments[0]);
6969
image = surface->makeImageSnapshot(SkIRect::MakeXYWH(
7070
rect->x(), rect->y(), rect->width(), rect->height()));
@@ -75,6 +75,11 @@ class JsiSkSurface : public JsiSkWrappingSkPtrHostObject<SkSurface> {
7575
auto recording = surface->recorder()->snap();
7676
DawnContext::getInstance().submitRecording(recording.get());
7777
#endif
78+
if (count > 1 && arguments[1].isObject()) {
79+
auto jsiImage = arguments[1].asObject(runtime).asHostObject<JsiSkImage>(runtime);
80+
jsiImage->setObject(image);
81+
return jsi::Value(runtime, arguments[1]);
82+
}
7883
return jsi::Object::createFromHostObject(
7984
runtime, std::make_shared<JsiSkImage>(getContext(), std::move(image)));
8085
}

packages/skia/src/renderer/__tests__/e2e/DataEncoding.spec.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ describe("Data Encoding", () => {
5252
const offscreen = Skia.Surface.MakeOffscreen(1, 1)!;
5353
const canvas = offscreen.getCanvas();
5454
canvas.drawImage(img, 0, 0);
55-
return Array.from(offscreen.makeImageSnapshot().encodeToBytes());
55+
const snapshotImage = Skia.Image.MakeNull();
56+
offscreen.makeImageSnapshot(undefined, snapshotImage);
57+
return Array.from(snapshotImage.encodeToBytes());
5658
});
5759
expect(result.length).toBeGreaterThan(0);
5860
});
@@ -68,7 +70,9 @@ describe("Data Encoding", () => {
6870
const offscreen = Skia.Surface.MakeOffscreen(1, 1)!;
6971
const canvas = offscreen.getCanvas();
7072
canvas.drawImage(img, 0, 0);
71-
return offscreen.makeImageSnapshot().encodeToBase64();
73+
const snapshotImage = Skia.Image.MakeNull();
74+
offscreen.makeImageSnapshot(undefined, snapshotImage);
75+
return snapshotImage.encodeToBase64();
7276
});
7377
expect(result.length).toBeGreaterThan(0);
7478
});

packages/skia/src/skia/types/Image/ImageFactory.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface ImageInfo {
2121
}
2222

2323
export interface ImageFactory {
24+
MakeNull: () => SkImage;
2425
/**
2526
* Return an Image backed by the encoded data, but attempt to defer decoding until the image
2627
* is actually used/drawn. This deferral allows the system to cache the result, either on the
@@ -70,7 +71,8 @@ export interface ImageFactory {
7071
texture: unknown,
7172
width: number,
7273
height: number,
73-
mipmapped?: boolean
74+
mipmapped?: boolean,
75+
outputImage?: SkImage
7476
) => SkImage;
7577

7678
/**

packages/skia/src/skia/types/Surface/Surface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export interface SkSurface extends SkJSIInstance<"Surface"> {
3535
3636
example: https://fiddle.skia.org/c/@Surface_makeImageSnapshot
3737
*/
38-
makeImageSnapshot(bounds?: SkRect): SkImage;
38+
makeImageSnapshot(bounds?: SkRect, outputImage?: SkImage): SkImage;
3939

4040
/**
4141
* Make sure any queued draws are sent to the screen or the GPU.

packages/skia/src/skia/web/JsiSkImageFactory.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export class JsiSkImageFactory extends Host implements ImageFactory {
2020
super(CanvasKit);
2121
}
2222

23+
MakeNull() {
24+
return new JsiSkImage(this.CanvasKit, null as unknown as Image);
25+
}
26+
2327
MakeImageFromViewTag(viewTag: number): Promise<SkImage | null> {
2428
const view = viewTag as unknown as HTMLElement;
2529
// TODO: Implement screenshot from view in React JS

packages/skia/src/skia/web/JsiSkSurface.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,15 @@ export class JsiSkSurface
3535
return new JsiSkCanvas(this.CanvasKit, this.ref.getCanvas());
3636
}
3737

38-
makeImageSnapshot(bounds?: SkRect): SkImage {
38+
makeImageSnapshot(bounds?: SkRect, outputImage?: JsiSkImage): SkImage {
3939
const image = this.ref.makeImageSnapshot(
4040
bounds
4141
? Array.from(JsiSkRect.fromValue(this.CanvasKit, bounds))
4242
: undefined
4343
);
44+
if (outputImage) {
45+
outputImage.ref = image;
46+
}
4447
return new JsiSkImage(this.CanvasKit, image);
4548
}
4649

0 commit comments

Comments
 (0)