Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a0c8031

Browse files
Philippe Plantierchearon
Philippe Plantier
authored andcommitted
getImageData fixes when rectangle is outside of canvas
fix a crash in getImageData if the rectangle is outside the canvas return transparent black pixels when getting image data outside the canvas remove dead code, add comments Fixes Automattic#2024 Fixes Automattic#1849
1 parent da33bbe commit a0c8031

File tree

4 files changed

+533
-19
lines changed

4 files changed

+533
-19
lines changed

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ project adheres to [Semantic Versioning](http://semver.org/).
1515
* Support for accessibility and links in PDFs
1616

1717
### Fixed
18+
* Fix a crash in `getImageData` when the rectangle is entirely outside the canvas. ([#2024](https://github.com/Automattic/node-canvas/issues/2024))
19+
* Fix `getImageData` cropping the resulting `ImageData` when the given rectangle is partly outside the canvas. ([#1849](https://github.com/Automattic/node-canvas/issues/1849))
1820

1921
3.0.1
2022
==================

‎src/CanvasRenderingContext2d.cc‎

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,21 +1011,26 @@ Context2d::GetImageData(const Napi::CallbackInfo& info) {
10111011
sh = -sh;
10121012
}
10131013

1014-
if (sx + sw > width) sw = width - sx;
1015-
if (sy + sh > height) sh = height - sy;
1016-
1017-
// WebKit/moz functionality. node-canvas used to return in either case.
1018-
if (sw <= 0) sw = 1;
1019-
if (sh <= 0) sh = 1;
1020-
1021-
// Non-compliant. "Pixels outside the canvas must be returned as transparent
1022-
// black." This instead clips the returned array to the canvas area.
1014+
// Width and height to actually copy
1015+
int cw = sw;
1016+
int ch = sh;
1017+
// Offsets in the destination image
1018+
int ox = 0;
1019+
int oy = 0;
1020+
1021+
// Clamp the copy width and height if the copy would go outside the image
1022+
if (sx + sw > width) cw = width - sx;
1023+
if (sy + sh > height) ch = height - sy;
1024+
1025+
// Clamp the copy origin if the copy would go outside the image
10231026
if (sx < 0) {
1024-
sw += sx;
1027+
ox = -sx;
1028+
cw += sx;
10251029
sx = 0;
10261030
}
10271031
if (sy < 0) {
1028-
sh += sy;
1032+
oy = -sy;
1033+
ch += sy;
10291034
sy = 0;
10301035
}
10311036

@@ -1047,13 +1052,16 @@ Context2d::GetImageData(const Napi::CallbackInfo& info) {
10471052

10481053
uint8_t *dst = (uint8_t *)buffer.Data();
10491054

1055+
if (!(cw > 0 && ch > 0)) goto return_empty;
1056+
10501057
switch (canvas->backend()->getFormat()) {
10511058
case CAIRO_FORMAT_ARGB32: {
1059+
dst += oy * dstStride + ox * 4;
10521060
// Rearrange alpha (argb -> rgba), undo alpha pre-multiplication,
10531061
// and store in big-endian format
1054-
for (int y = 0; y < sh; ++y) {
1062+
for (int y = 0; y < ch; ++y) {
10551063
uint32_t *row = (uint32_t *)(src + srcStride * (y + sy));
1056-
for (int x = 0; x < sw; ++x) {
1064+
for (int x = 0; x < cw; ++x) {
10571065
int bx = x * 4;
10581066
uint32_t *pixel = row + x + sx;
10591067
uint8_t a = *pixel >> 24;
@@ -1082,10 +1090,11 @@ Context2d::GetImageData(const Napi::CallbackInfo& info) {
10821090
break;
10831091
}
10841092
case CAIRO_FORMAT_RGB24: {
1093+
dst += oy * dstStride + ox * 4;
10851094
// Rearrange alpha (argb -> rgba) and store in big-endian format
1086-
for (int y = 0; y < sh; ++y) {
1095+
for (int y = 0; y < ch; ++y) {
10871096
uint32_t *row = (uint32_t *)(src + srcStride * (y + sy));
1088-
for (int x = 0; x < sw; ++x) {
1097+
for (int x = 0; x < cw; ++x) {
10891098
int bx = x * 4;
10901099
uint32_t *pixel = row + x + sx;
10911100
uint8_t r = *pixel >> 16;
@@ -1102,9 +1111,10 @@ Context2d::GetImageData(const Napi::CallbackInfo& info) {
11021111
break;
11031112
}
11041113
case CAIRO_FORMAT_A8: {
1105-
for (int y = 0; y < sh; ++y) {
1114+
dst += oy * dstStride + ox;
1115+
for (int y = 0; y < ch; ++y) {
11061116
uint8_t *row = (uint8_t *)(src + srcStride * (y + sy));
1107-
memcpy(dst, row + sx, dstStride);
1117+
memcpy(dst, row + sx, cw);
11081118
dst += dstStride;
11091119
}
11101120
break;
@@ -1116,9 +1126,10 @@ Context2d::GetImageData(const Napi::CallbackInfo& info) {
11161126
break;
11171127
}
11181128
case CAIRO_FORMAT_RGB16_565: {
1119-
for (int y = 0; y < sh; ++y) {
1129+
dst += oy * dstStride + ox * 2;
1130+
for (int y = 0; y < ch; ++y) {
11201131
uint16_t *row = (uint16_t *)(src + srcStride * (y + sy));
1121-
memcpy(dst, row + sx, dstStride);
1132+
memcpy(dst, row + sx, cw * 2);
11221133
dst += dstStride;
11231134
}
11241135
break;
@@ -1138,6 +1149,7 @@ Context2d::GetImageData(const Napi::CallbackInfo& info) {
11381149
}
11391150
}
11401151

1152+
return_empty:
11411153
Napi::Number swHandle = Napi::Number::New(env, sw);
11421154
Napi::Number shHandle = Napi::Number::New(env, sh);
11431155
Napi::Function ctor = env.GetInstanceData<InstanceData>()->ImageDataCtor.Value();

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /