Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for CGImageCreateWithMask. #1555

Merged
merged 1 commit into from
Dec 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions Frameworks/CoreGraphics/CGImage.mm
Original file line number Diff line number Diff line change
Expand Up @@ -525,13 +525,34 @@ CGImageRef CGImageCreateCopyWithColorSpace(CGImageRef ref, CGColorSpaceRef color
}

/**
@Status Stub
@Status Interoperable
@Notes This function does not defer the composition of its mask.
This function supports non-grayscale alpha masks, unlike the reference platform.
*/
CGImageRef CGImageCreateWithMask(CGImageRef image, CGImageRef mask) {
// TODO #1425 - masks are applied during rendering via D2D.
RETURN_NULL_IF(!image);
UNIMPLEMENTED();
return StubReturn();
RETURN_NULL_IF(!mask);
RETURN_NULL_IF(CGImageIsMask(image));
Copy link
Contributor

@msft-Jeyaram msft-Jeyaram Dec 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CGImageIsMask [](start = 19, length = 13)

return null if it's not a mask?

RETURN_NULL_IF(!CGImageIsMask(image)); ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image is the input image, it is contractually disallowed from being a mask.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ops, LOL I was thinking it was mask.

Can you add a check to see if the mask is really as mask?


In reply to: 92708221 [](ancestors = 92708221)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some how my comment won't appear:

Ops, LOL I was thinking it was mask.

Can you add a check to see if the mask is really as mask?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See notes above; the reference platform requires a mask (black/white image). We add support for an alpha clip (alpha image), but an alpha image is not a mask.


size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);

woc::unique_cf<CGContextRef> context{ CGBitmapContextCreate(nullptr,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context [](start = 33, length = 7)

for some unforeseen reason check if bitmapcontextcreate failed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea. this will return a cascading null, but it's better to be safe.

Copy link
Contributor

@msft-Jeyaram msft-Jeyaram Dec 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I'm thinking if someone decides to change the bitmap info (without realizing we don't support all of it due to D2D restrictions)


In reply to: 92708281 [](ancestors = 92708281)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They can't change the bitmap info. Do you mean some internal consumer?

width,
height,
8,
width * 4,
CGImageGetColorSpace(image),
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) };
RETURN_NULL_IF(!context);

CGRect rect{
CGPointZero, { width, height },
};
CGContextClipToMask(context.get(), rect, mask);
CGContextDrawImage(context.get(), rect, image);

return CGBitmapContextCreateImage(context.get());
}

/**
Expand Down
2 changes: 1 addition & 1 deletion include/CoreGraphics/CGImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ COREGRAPHICS_EXPORT CGImageRef CGImageCreateWithPNGDataProvider(CGDataProviderRe

COREGRAPHICS_EXPORT CGImageRef CGImageCreateWithImageInRect(CGImageRef image, CGRect rect);

COREGRAPHICS_EXPORT CGImageRef CGImageCreateWithMask(CGImageRef image, CGImageRef mask) STUB_METHOD;
COREGRAPHICS_EXPORT CGImageRef CGImageCreateWithMask(CGImageRef image, CGImageRef mask);

COREGRAPHICS_EXPORT CGImageRef CGImageCreateWithMaskingColors(CGImageRef image, const CGFloat* components) STUB_METHOD;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,74 @@ DRAW_TEST(CGContextClipping, ClipATransparencyLayer) {
// If the clip mask applies twice (wrong) it will be 25%.
CGContextEndTransparencyLayer(context);
}

DRAW_TEST(CGImage, CreateWithSameSizeMask) {
auto drawingConfig = DrawingTestConfig::Get();

woc::unique_cf<CFStringRef> testFilename{ _CFStringCreateWithStdString(drawingConfig->GetResourcePath("jpg1.jpg")) };
woc::unique_cf<CGImageRef> image{ _CGImageCreateFromJPEGFile(testFilename.get()) };
ASSERT_NE(nullptr, image);

CGSize imageSize{ static_cast<CGFloat>(CGImageGetWidth(image.get())), static_cast<CGFloat>(CGImageGetHeight(image.get())) };

woc::unique_cf<CGImageRef> alphaMask{
__CreateClipImage(imageSize,
ClippingTypeMask,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });

CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 10.0);
CGContextStrokeRect(context, CGRectInset({ CGPointZero, size }, 20, 20));
})
};

ASSERT_NE(nullptr, alphaMask);

woc::unique_cf<CGImageRef> preMaskedImage{ CGImageCreateWithMask(image.get(), alphaMask.get()) };

ASSERT_NE(nullptr, preMaskedImage);

CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

CGContextDrawImage(context, bounds, preMaskedImage.get());
}

DRAW_TEST(CGImage, CreateWithScaledMask) {
auto drawingConfig = DrawingTestConfig::Get();

woc::unique_cf<CFStringRef> testFilename{ _CFStringCreateWithStdString(drawingConfig->GetResourcePath("jpg1.jpg")) };
woc::unique_cf<CGImageRef> image{ _CGImageCreateFromJPEGFile(testFilename.get()) };
ASSERT_NE(nullptr, image);

CGSize imageSize{ static_cast<CGFloat>(CGImageGetWidth(image.get())), static_cast<CGFloat>(CGImageGetHeight(image.get())) };

woc::unique_cf<CGImageRef> alphaMask{
__CreateClipImage({ 64, 64 },
ClippingTypeMask,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });

CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 4.0);
CGPoint points[]{
{ 0, 0 }, { 64, 64 }, { 0, 64 }, { 64, 0 },
};
CGContextStrokeLineSegments(context, points, 4);
})
};

ASSERT_NE(nullptr, alphaMask);

woc::unique_cf<CGImageRef> preMaskedImage{ CGImageCreateWithMask(image.get(), alphaMask.get()) };

ASSERT_NE(nullptr, preMaskedImage);

CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

CGContextDrawImage(context, bounds, preMaskedImage.get());
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.