Skip to content

Commit 31dcb64

Browse files
committed
Create RGB color spaces from ColorPrimaries and TransferCharacteristics
1 parent 18f0e4e commit 31dcb64

File tree

1 file changed

+52
-12
lines changed

1 file changed

+52
-12
lines changed

SDWebImageAVIFCoder/Classes/SDImageAVIFCoder.m

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,28 @@ static void CalcWhitePoint(uint16_t const colorPrimaries, vImageWhitePoint* cons
2424
white->white_y = primaries[7];
2525
}
2626

27+
static void CalcRGBPrimaries(uint16_t const colorPrimaries, vImageRGBPrimaries* const prim) {
28+
float primaries[8];
29+
avifNclxColourPrimariesGetValues(colorPrimaries, primaries);
30+
prim->red_x = primaries[0];
31+
prim->red_y = primaries[1];
32+
prim->green_x = primaries[2];
33+
prim->green_y = primaries[3];
34+
prim->blue_x = primaries[4];
35+
prim->blue_y = primaries[5];
36+
prim->white_x = primaries[6];
37+
prim->white_y = primaries[7];
38+
}
39+
2740
static void CalcTransferFunction(uint16_t const transferCharacteristics, vImageTransferFunction* const tf) {
41+
// See: https://www.itu.int/rec/T-REC-H.273/en
2842
static const float alpha = 1.099296826809442f;
2943
static const float beta = 0.018053968510807f;
3044
/*
3145
// R' = c0 * pow( c1 * R + c2, gamma ) + c3, (R >= cutoff)
3246
// R' = c4 * R + c5 (R < cutoff)
3347
*/
3448

35-
// See: https://www.itu.int/rec/T-REC-H.273/en
3649
switch(transferCharacteristics) {
3750
case AVIF_NCLX_TRANSFER_CHARACTERISTICS_GAMMA28: // 5
3851
tf->cutoff = -INFINITY;
@@ -131,7 +144,7 @@ static void CalcTransferFunction(uint16_t const transferCharacteristics, vImageT
131144
tf->c4 = 1.0f;
132145
tf->c5 = 0.0f;
133146
break;
134-
// Can't be represented by vImageTransferFunction. Use gamma 2.2 as a default.
147+
// Can't be represented by vImageTransferFunction. Use gamma 2.2 as a fallback.
135148
case AVIF_NCLX_TRANSFER_CHARACTERISTICS_ST2084: // 16
136149
case AVIF_NCLX_TRANSFER_CHARACTERISTICS_BT2100_HLG: // 18
137150
case AVIF_NCLX_TRANSFER_CHARACTERISTICS_LOG_100_1: // 9
@@ -152,7 +165,7 @@ static void CalcTransferFunction(uint16_t const transferCharacteristics, vImageT
152165
break;
153166
}
154167
}
155-
static CGColorSpaceRef CreateMonoColorSpace(uint16_t const colorPrimaries, uint16_t const transferCharacteristics) {
168+
static CGColorSpaceRef CreateColorSpaceMono(uint16_t const colorPrimaries, uint16_t const transferCharacteristics) {
156169
if (@available(macOS 10.10, iOS 8.0, tvOS 8.0, *)) {
157170
vImage_Error err;
158171
vImageWhitePoint white;
@@ -162,6 +175,30 @@ static CGColorSpaceRef CreateMonoColorSpace(uint16_t const colorPrimaries, uint1
162175
CGColorSpaceRef colorSpace = vImageCreateMonochromeColorSpaceWithWhitePointAndTransferFunction(&white, &transfer, kCGRenderingIntentDefault, kvImagePrintDiagnosticsToConsole, &err);
163176
if(err != kvImageNoError) {
164177
NSLog(@"[BUG] Failed to create monochrome color space: %ld", err);
178+
if(colorSpace != NULL) {
179+
CGColorSpaceRelease(colorSpace);
180+
}
181+
return NULL;
182+
}
183+
return colorSpace;
184+
}else{
185+
return NULL;
186+
}
187+
}
188+
189+
static CGColorSpaceRef CreateColorSpaceRGB(uint16_t const colorPrimaries, uint16_t const transferCharacteristics) {
190+
if (@available(macOS 10.10, iOS 8.0, tvOS 8.0, *)) {
191+
vImage_Error err;
192+
vImageRGBPrimaries primaries;
193+
vImageTransferFunction transfer;
194+
CalcRGBPrimaries(colorPrimaries, &primaries);
195+
CalcTransferFunction(transferCharacteristics, &transfer);
196+
CGColorSpaceRef colorSpace = vImageCreateRGBColorSpaceWithPrimariesAndTransferFunction(&primaries, &transfer, kCGRenderingIntentDefault, kvImagePrintDiagnosticsToConsole, &err);
197+
if(err != kvImageNoError) {
198+
NSLog(@"[BUG] Failed to create monochrome color space: %ld", err);
199+
if(colorSpace != NULL) {
200+
CGColorSpaceRelease(colorSpace);
201+
}
165202
return NULL;
166203
}
167204
return colorSpace;
@@ -210,7 +247,7 @@ static void CalcColorSpaceMono(avifImage * avif, CGColorSpaceRef* ref, BOOL* sho
210247
static CGColorSpaceRef sRGB = NULL;
211248
static dispatch_once_t onceToken;
212249
dispatch_once(&onceToken, ^{
213-
sRGB = CreateMonoColorSpace(colorPrimaries, transferCharacteristics);
250+
sRGB = CreateColorSpaceMono(colorPrimaries, transferCharacteristics);
214251
if(sRGB == NULL) {
215252
sRGB = defaultColorSpace;
216253
}
@@ -224,7 +261,7 @@ static void CalcColorSpaceMono(avifImage * avif, CGColorSpaceRef* ref, BOOL* sho
224261
static CGColorSpaceRef bt709 = NULL;
225262
static dispatch_once_t onceToken;
226263
dispatch_once(&onceToken, ^{
227-
bt709 = CreateMonoColorSpace(colorPrimaries, transferCharacteristics);
264+
bt709 = CreateColorSpaceMono(colorPrimaries, transferCharacteristics);
228265
if(bt709 == NULL) {
229266
bt709 = defaultColorSpace;
230267
}
@@ -239,7 +276,7 @@ static void CalcColorSpaceMono(avifImage * avif, CGColorSpaceRef* ref, BOOL* sho
239276
static CGColorSpaceRef bt2020 = NULL;
240277
static dispatch_once_t onceToken;
241278
dispatch_once(&onceToken, ^{
242-
bt2020 = CreateMonoColorSpace(colorPrimaries, transferCharacteristics);
279+
bt2020 = CreateColorSpaceMono(colorPrimaries, transferCharacteristics);
243280
if(bt2020 == NULL) {
244281
bt2020 = defaultColorSpace;
245282
}
@@ -253,7 +290,7 @@ static void CalcColorSpaceMono(avifImage * avif, CGColorSpaceRef* ref, BOOL* sho
253290
static CGColorSpaceRef p3 = NULL;
254291
static dispatch_once_t onceToken;
255292
dispatch_once(&onceToken, ^{
256-
p3 = CreateMonoColorSpace(colorPrimaries, transferCharacteristics);
293+
p3 = CreateColorSpaceMono(colorPrimaries, transferCharacteristics);
257294
if(p3 == NULL) {
258295
p3 = defaultColorSpace;
259296
}
@@ -263,7 +300,7 @@ static void CalcColorSpaceMono(avifImage * avif, CGColorSpaceRef* ref, BOOL* sho
263300
return;
264301
}
265302

266-
*ref = CreateMonoColorSpace(colorPrimaries, transferCharacteristics);
303+
*ref = CreateColorSpaceMono(colorPrimaries, transferCharacteristics);
267304
if(*ref != NULL) {
268305
*shouldRelease = TRUE;
269306
} else {
@@ -474,11 +511,14 @@ static void CalcColorSpaceRGB(avifImage * avif, CGColorSpaceRef* ref, BOOL* shou
474511
*shouldRelease = FALSE;
475512
return;
476513
}
477-
// TODO(ledyba-z): We can support more color spaces
478-
// using vImageCreateRGBColorSpaceWithPrimariesAndTransferFunction
479514

480-
*ref = defaultColorSpace;
481-
*shouldRelease = FALSE;
515+
*ref = CreateColorSpaceRGB(colorPrimaries, transferCharacteristics);
516+
if(*ref != NULL) {
517+
*shouldRelease = TRUE;
518+
} else {
519+
*ref = defaultColorSpace;
520+
*shouldRelease = FALSE;
521+
}
482522
}
483523

484524
static CGImageRef CreateImageFromBuffer(avifImage * avif, vImage_Buffer* result) {

0 commit comments

Comments
 (0)