Skip to content

Commit b827838

Browse files
committed
[WIP] Implement BT709(sRGB) and BT2020
1 parent 6db2c95 commit b827838

File tree

1 file changed

+71
-10
lines changed

1 file changed

+71
-10
lines changed

SDWebImageAVIFCoder/Classes/SDImageAVIFCoder.m

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,68 @@
1616
static void FreeImageData(void *info, const void *data, size_t size) {
1717
free((void *)data);
1818
}
19+
static void CalcColorSpaceMono(avifImage * avif, CGColorSpaceRef* ref, BOOL* shouldRelease) {
20+
static CGColorSpaceRef defaultColorSpace;
21+
{
22+
static dispatch_once_t onceToken;
23+
dispatch_once(&onceToken, ^{
24+
defaultColorSpace = CGColorSpaceCreateDeviceGray();
25+
});
26+
}
27+
default_color_space:
28+
*ref = defaultColorSpace;
29+
*shouldRelease = FALSE;
30+
}
31+
static void CalcColorSpaceRGB(avifImage * avif, CGColorSpaceRef* ref, BOOL* shouldRelease) {
32+
static CGColorSpaceRef defaultColorSpace;
33+
static CGColorSpaceRef bt709;
34+
static CGColorSpaceRef bt2020;
35+
{
36+
static dispatch_once_t onceToken;
37+
dispatch_once(&onceToken, ^{
38+
if (@available(iOS 9.0, tvOS 9.0, *)) {
39+
defaultColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
40+
} else {
41+
defaultColorSpace = CGColorSpaceCreateDeviceRGB();
42+
}
43+
if (@available(macOS 10.11, *)) {
44+
bt709 = CGColorSpaceCreateWithName(kCGColorSpaceITUR_709);
45+
} else {
46+
bt709 = defaultColorSpace;
47+
}
48+
if (@available(macOS 10.11, *)) {
49+
bt2020 = CGColorSpaceCreateWithName(kCGColorSpaceITUR_2020);
50+
} else {
51+
bt2020 = defaultColorSpace;
52+
}
53+
});
54+
}
55+
56+
if((avif->profileFormat == AVIF_PROFILE_FORMAT_ICC) && avif->icc.data && avif->icc.size) {
57+
if (@available(macOS 10.12, *)) {
58+
*ref = CGColorSpaceCreateWithICCData(avif->icc.data);
59+
*shouldRelease = TRUE;
60+
return;
61+
}
62+
}
63+
uint16_t colorPrimaries = avif->nclx.colourPrimaries;
64+
uint16_t transferCharacteristics = avif->nclx.transferCharacteristics;
65+
if(colorPrimaries == AVIF_NCLX_COLOUR_PRIMARIES_UNKNOWN && transferCharacteristics == AVIF_NCLX_TRANSFER_CHARACTERISTICS_UNKNOWN) {
66+
goto default_color_space;
67+
}
68+
if(colorPrimaries == AVIF_NCLX_COLOUR_PRIMARIES_BT709 && transferCharacteristics == AVIF_NCLX_TRANSFER_CHARACTERISTICS_BT709) {
69+
*ref = bt709;
70+
*shouldRelease = FALSE;
71+
}
72+
if(colorPrimaries == AVIF_NCLX_COLOUR_PRIMARIES_BT2020 && (transferCharacteristics == AVIF_NCLX_TRANSFER_CHARACTERISTICS_BT2020_10BIT || transferCharacteristics == AVIF_NCLX_TRANSFER_CHARACTERISTICS_BT2020_12BIT)) {
73+
*ref = bt2020;
74+
*shouldRelease = FALSE;
75+
}
76+
77+
default_color_space:
78+
*ref = defaultColorSpace;
79+
*shouldRelease = FALSE;
80+
}
1981

2082
static CGImageRef CreateImageFromBuffer(avifImage * avif, vImage_Buffer* result) {
2183
BOOL monochrome = avif->yuvPlanes[1] == NULL || avif->yuvPlanes[2] == NULL;
@@ -26,28 +88,27 @@ static CGImageRef CreateImageFromBuffer(avifImage * avif, vImage_Buffer* result)
2688
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, result->data, result->rowBytes * result->height, FreeImageData);
2789
CGBitmapInfo bitmapInfo = usesU16 ? kCGBitmapByteOrder16Host : kCGBitmapByteOrderDefault;
2890
bitmapInfo |= hasAlpha ? kCGImageAlphaFirst : kCGImageAlphaNone;
29-
// FIXME: (ledyba-z): Set appropriate color space.
30-
// use avif->nclx.colourPrimaries and avif->nclx.transferCharacteristics to detect appropriate color space.
91+
92+
// Calc color space
3193
CGColorSpaceRef colorSpace = NULL;
94+
BOOL shouldReleaseColorSpace = FALSE;
3295
if(monochrome){
33-
vImage_Error err;
34-
vImageWhitePoint whitePoint ;
35-
vImageTransferFunction transferFunction;
36-
CGColorRenderingIntent intent;
37-
colorSpace = vImageCreateMonochromeColorSpaceWithWhitePointAndTransferFunction(&whitePoint, &transferFunction, intent, kvImageNoFlags, &err);
96+
CalcColorSpaceMono(avif, &colorSpace, &shouldReleaseColorSpace);
3897
}else{
39-
colorSpace = CGColorSpaceCreateDeviceRGB();
98+
CalcColorSpaceRGB(avif, &colorSpace, &shouldReleaseColorSpace);
4099
}
100+
41101
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
42-
43102
size_t bitsPerComponent = usesU16 ? 16 : 8;
44103
size_t bitsPerPixel = components * bitsPerComponent;
45104
size_t rowBytes = result->width * components * (usesU16 ? sizeof(uint16_t) : sizeof(uint8_t));
46105

47106
CGImageRef imageRef = CGImageCreate(result->width, result->height, bitsPerComponent, bitsPerPixel, rowBytes, colorSpace, bitmapInfo, provider, NULL, NO, renderingIntent);
48107

49108
// clean up
50-
CGColorSpaceRelease(colorSpace);
109+
if(shouldReleaseColorSpace) {
110+
CGColorSpaceRelease(colorSpace);
111+
}
51112
CGDataProviderRelease(provider);
52113

53114
return imageRef;

0 commit comments

Comments
 (0)