Skip to content

Commit

Permalink
Decode image data directly on iOS
Browse files Browse the repository at this point in the history
...instead of rendering to a core graphics context and then copying the context's buffer.

Seems like our alpha un-premultiply logic is no longer taking affect: https://github.com/rive-app/rive/blob/1c9233455851e5d346c4c97b01fdf74a5966017d/packages/runtime_ios/Source/Renderer/RenderContextManager.mm#L74-L82

Expected:
<img src="https://rive-public-testing.s3.us-west-1.amazonaws.com/golden-tests/ios/2024-07-31/127/golden/mesh.png"/>
Currently:
<img src="https://rive-public-testing.s3.us-west-1.amazonaws.com/golden-tests/ios/2024-07-31/127/iphone-15-pro-max/mesh.png"/>

Thread with details here: https://2dimensions.slack.com/archives/C06ER4J62BA/p1722438338690329

This fixes the issue by extracting the decoded PNG bytes directly (which are un-premultiplied).

Diffs=
714b8894f Decode image data directly on iOS (#7820)

Co-authored-by: Chris Dalton <[email protected]>
Co-authored-by: Luigi Rosso <[email protected]>
  • Loading branch information
3 people committed Aug 12, 2024
1 parent 3cc51d9 commit 9846f45
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 28 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
55de8286c5ba680de950a3a0aac26e13bb890d6b
714b8894f37ab931a1df4b27d63c1e0991a97e3a
31 changes: 4 additions & 27 deletions Source/Renderer/PlatformCGImage.mm
Original file line number Diff line number Diff line change
Expand Up @@ -49,40 +49,17 @@ bool PlatformCGImageDecode(const uint8_t* encodedBytes,
break;
}

// Now create a drawing context to produce RGBA pixels

const size_t bitsPerComponent = 8;
CGBitmapInfo cgInfo = kCGBitmapByteOrder32Big; // rgba
if (isOpaque)
{
cgInfo |= kCGImageAlphaNoneSkipLast;
}
else
{
cgInfo |= kCGImageAlphaPremultipliedLast; // premul
}
CFDataRef dataRef = CGDataProviderCopyData(CGImageGetDataProvider(image));
const UInt8* pixelData = CFDataGetBytePtr(dataRef);
const size_t width = CGImageGetWidth(image);
const size_t height = CGImageGetHeight(image);
const size_t rowBytes = width * 4; // 4 bytes per pixel
const size_t size = rowBytes * height;

std::vector<uint8_t> pixels;
pixels.resize(size);

AutoCF cs = CGColorSpaceCreateDeviceRGB();
AutoCF cg =
CGBitmapContextCreate(pixels.data(), width, height, bitsPerComponent, rowBytes, cs, cgInfo);
if (!cg)
{
return false;
}

CGContextSetBlendMode(cg, kCGBlendModeCopy);
CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image);

platformImage->width = rive::castTo<uint32_t>(width);
platformImage->height = rive::castTo<uint32_t>(height);
platformImage->opaque = isOpaque;
platformImage->pixels = std::move(pixels);
platformImage->pixels = std::vector<uint8_t>(pixelData, pixelData + size);
CFRelease(dataRef);
return true;
}

0 comments on commit 9846f45

Please sign in to comment.