Skip to content

Commit

Permalink
Merge pull request #14 from link-u/fix/hdr-alpha
Browse files Browse the repository at this point in the history
Scale alpha planes [0, (1 << bit-depth) - 1] to [0, 65536]
  • Loading branch information
ledyba-z authored Mar 9, 2020
2 parents 62c8e95 + 4713673 commit ab2fde9
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 21 deletions.
60 changes: 40 additions & 20 deletions Example/Tests/Tests.m
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ -(void)assertColor8: (NSString*)filename img:(CGImageRef)img expectedColor:(UInt
for(size_t c = 0; c < 3; ++c) {
int32_t result = pix[c];
int32_t expected = expectedColor[c];
XCTAssertTrue(ok = (abs(result - expected) <= threshold8), "(x: %ld, y: %ld, c:%ld): result=%d vs expected=%d (%@)", x, y, c, result, expected, filename);
XCTAssertTrue(ok = (abs(result - expected) <= threshold8),
"(x: %ld, y: %ld, c:%ld): result=%d vs expected=%d (%@)",
x, y, c, result, expected, filename);
}
if(!ok) {
goto end;
Expand Down Expand Up @@ -202,9 +204,13 @@ -(void)assertColorAlpha8: (NSString*)filename img:(CGImageRef)img expectedColor:
for(size_t c = 1; c < 4; ++c) {
int32_t result = pix[c];
int32_t expected = expectedColor[c-1];
XCTAssertTrue(ok &= (abs(result - expected) <= threshold8), "(x: %ld, y: %ld, c:%ld): result=%d vs expected=%d (%@)", x, y, c, result, expected, filename);
XCTAssertTrue(ok &= (abs(result - expected) <= threshold8),
"(x: %ld, y: %ld, c:%ld): result=%d vs expected=%d (%@)",
x, y, c, result, expected, filename);
}
XCTAssertTrue(ok &= (pix[0] == (x < 128 ? 0xff : 0x00)), "(x: %ld, y: %ld, c: alpha): result=%d vs expected=%d (%@)", x, y, pix[0], x < 128 ? 0xff : 0x00, filename);
XCTAssertTrue(ok &= (pix[0] == (x < 128 ? 0xff : 0x00)),
"(x: %ld, y: %ld, c: alpha): result=%d vs expected=%d (%@)",
x, y, pix[0], x < 128 ? 0xff : 0x00, filename);
if(!ok) {
goto end;
}
Expand Down Expand Up @@ -233,7 +239,9 @@ -(void)assertColor16: (NSString*)filename img:(CGImageRef)img expectedColor:(UIn
for(size_t c = 0; c < 3; ++c) {
int32_t result = pix[c];
int32_t expected = expectedColor[c];
XCTAssertTrue(ok &= (abs(result - expected) <= threshold16), "(x: %ld, y: %ld, c:%ld): result=%d vs expected=%d (%@)", x, y, c, result, expected, filename);
XCTAssertTrue(ok &= (abs(result - expected) <= threshold16),
"(x: %ld, y: %ld, c:%ld): result=%d vs expected=%d (%@)",
x, y, c, result, expected, filename);
}
if(!ok) {
goto end;
Expand All @@ -257,15 +265,19 @@ -(void)assertColorAlpha16: (NSString*)filename img:(CGImageRef)img expectedColor
XCTAssertEqual(numComponents, 4);
XCTAssertEqual(bytesPerPixel, 8);
for(size_t y = 0; y < height; ++y) {
for(size_t x = 0; x < width; ++x) {
for(size_t x = 64; x < width; x+=128) {
UInt16* pix = (UInt16*)(buf + (stride * y) + (bytesPerPixel * x));
bool ok = true;
for(size_t c = 1; c < 4; ++c) {
int32_t result = pix[c];
int32_t expected = expectedColor[c-1];
XCTAssertTrue(ok &= (abs(result - expected) <= threshold16), "(x: %ld, y: %ld, c:%ld): result=%d vs expected=%d (%@)", x, y, c, result, expected, filename);
XCTAssertTrue(ok &= (abs(result - expected) <= threshold16),
"(x: %ld, y: %ld, c:%ld): result=%d vs expected=%d (%@)",
x, y, c, result, expected, filename);
}
XCTAssertTrue(ok &= (pix[0] == (x < 128 ? 0xffff : 0x0000)), "(x: %ld, y: %ld, c: alpha): result=%d vs expected=%d (%@)", x, y, pix[0], x < 128 ? 0xffff : 0x00, filename);
XCTAssertTrue(ok &= (pix[0] == (x < 128 ? 0xffff : 0x0000)),
"(x: %ld, y: %ld, c: alpha): result=%d vs expected=%d (%@)",
x, y, pix[0], x < 128 ? 0xffff : 0x00, filename);
if(!ok) {
goto end;
}
Expand All @@ -292,7 +304,9 @@ -(void)assertMono8: (NSString*)filename img:(CGImageRef)img
for(size_t x = 0; x < width; ++x) {
bool ok = true;
UInt8* pix = (buf + (stride * y) + (bytesPerPixel * x));
XCTAssertTrue(ok &= (abs(pix0 - *pix) <= threshold8), "(x: %ld, y: %ld): result=%d vs expected=%d (%@)", x, y, *pix, pix0, filename);
XCTAssertTrue(ok &= (abs(pix0 - *pix) <= threshold8),
"(x: %ld, y: %ld): result=%d vs expected=%d (%@)",
x, y, *pix, pix0, filename);
if(!ok) {
goto end;
}
Expand All @@ -319,8 +333,12 @@ -(void)assertMonoAlpha8: (NSString*)filename img:(CGImageRef)img
for(size_t x = 64; x < width; x+=128) {
bool ok = true;
UInt8* pix = (buf + (stride * y) + (bytesPerPixel * x));
XCTAssertTrue(ok &= (abs(pix0 - pix[1]) <= threshold8), "(x: %ld, y: %ld, c: mono): result=%d vs expected=%d (%@)", x, y, pix[1], pix0, filename);
XCTAssertTrue(ok &= (pix[0] == (x < 128 ? 0xff : 0x00)), "(x: %ld, y: %ld, c: alpha): result=%d vs expected=%d (%@)", x, y, pix[0], x < 128 ? 0xff : 0x00, filename);
XCTAssertTrue(ok &= (abs(pix0 - pix[1]) <= threshold8),
"(x: %ld, y: %ld, c: mono): result=%d vs expected=%d (%@)",
x, y, pix[1], pix0, filename);
XCTAssertTrue(ok &= (pix[0] == (x < 128 ? 0xff : 0x00)),
"(x: %ld, y: %ld, c: alpha): result=%d vs expected=%d (%@)",
x, y, pix[0], x < 128 ? 0xff : 0x00, filename);
if(!ok) {
goto end;
}
Expand Down Expand Up @@ -348,7 +366,9 @@ -(void)assertMono16: (NSString*)filename img:(CGImageRef)img
for(size_t x = 0; x < width; ++x) {
UInt16* pix = (UInt16*)(buf + (stride * y) + (bytesPerPixel * x));
bool ok = true;
XCTAssertTrue(ok &= (abs(pix0 - *pix) <= threshold16), "(x: %ld, y: %ld): result=%d vs expected=%d (%@)", x, y, *pix, pix0, filename);
XCTAssertTrue(ok &= (abs(pix0 - *pix) <= threshold16),
"(x: %ld, y: %ld): result=%d vs expected=%d (%@)",
x, y, *pix, pix0, filename);
if(!ok) {
goto end;
}
Expand All @@ -372,11 +392,15 @@ -(void)assertMonoAlpha16: (NSString*)filename img:(CGImageRef)img
XCTAssertEqual(bytesPerPixel, 4);
UInt16 const pix0 = ((UInt16*)buf)[1];
for(size_t y = 0; y < height; ++y) {
for(size_t x = 0; x < width; ++x) {
for(size_t x = 64; x < width; x+=128) {
UInt16* pix = (UInt16*)(buf + (stride * y) + (bytesPerPixel * x));
bool ok = true;
XCTAssertTrue(ok &= (abs(pix0 - pix[1]) <= threshold16), "(x: %ld, y: %ld): result=%d vs expected=%d (%@)", x, y, pix[1], pix0, filename);
XCTAssertTrue(ok &= (pix[0] == (x < 128 ? 0xffff : 0x0000)), "(x: %ld, y: %ld, c: alpha): result=%d vs expected=%d (%@)", x, y, pix[0], x < 128 ? 0xffff : 0x0000, filename);
XCTAssertTrue(ok &= (abs(pix0 - pix[1]) <= threshold16),
"(x: %ld, y: %ld): result=%d vs expected=%d (%@)",
x, y, pix[1], pix0, filename);
XCTAssertTrue(ok &= (pix[0] == (x < 128 ? 0xffff : 0x0000)),
"(x: %ld, y: %ld, c: alpha): result=%d vs expected=%d (%@)",
x, y, pix[0], x < 128 ? 0xffff : 0x0000, filename);
if(!ok) {
goto end;
}
Expand Down Expand Up @@ -420,9 +444,7 @@ - (void)assertImages: (NSMutableArray*) list colorName:(NSString*)colorName expe
}
}else{
if([alpha isEqualToString:@"with-alpha"]) {
// FIXME(ledyba-z): This issue blocks testing alpha plane:
// https://github.com/AOMediaCodec/libavif/issues/86
//[self assertMonoAlpha16: convertedFilename img:img.CGImage];
[self assertMonoAlpha16: convertedFilename img:img.CGImage];
}else{
[self assertMono16: convertedFilename img:img.CGImage];
}
Expand All @@ -436,9 +458,7 @@ - (void)assertImages: (NSMutableArray*) list colorName:(NSString*)colorName expe
}
} else {
if([alpha isEqualToString:@"with-alpha"]) {
// FIXME(ledyba-z): This issue blocks testing alpha plane:
// https://github.com/AOMediaCodec/libavif/issues/86
//[self assertColorAlpha16: convertedFilename img:img.CGImage expectedColor:expectedColor16];
[self assertColorAlpha16: convertedFilename img:img.CGImage expectedColor:expectedColor16];
} else {
[self assertColor16: convertedFilename img:img.CGImage expectedColor:expectedColor16];
}
Expand Down
52 changes: 51 additions & 1 deletion SDWebImageAVIFCoder/Classes/SDImageAVIFCoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,10 @@ static CGImageRef CreateImage8(avifImage * avif) {
origCr.rowBytes = 0;
memset(origCr.data, pixelRange.CbCr_bias, origCr.width);
}


//TODO: (ledyba-z) we have to scale alpha when libavif v0.6.0 comes.
// https://github.com/AOMediaCodec/libavif/issues/91

uint8_t const permuteMap[4] = {0, 1, 2, 3};
switch(avif->yuvFormat) {
case AVIF_PIXEL_FORMAT_NONE:
Expand Down Expand Up @@ -521,6 +524,7 @@ static CGImageRef CreateImage16U(avifImage * avif) {
uint16_t* resultBufferData = NULL;
uint16_t* argbBufferData = NULL;
uint16_t* ayuvBufferData = NULL;
uint16_t* scaledAlphaBufferData = NULL;
uint16_t* dummyCbData = NULL;
uint16_t* dummyCrData = NULL;
uint16_t* dummyAlphaData = NULL;
Expand Down Expand Up @@ -637,10 +641,53 @@ static CGImageRef CreateImage16U(avifImage * avif) {

vImage_Buffer origAlpha = {0};
if(hasAlpha) {
float* floatAlphaBufferData = NULL;
floatAlphaBufferData = calloc(avif->width * avif->height, sizeof(float));
scaledAlphaBufferData = calloc(avif->width * avif->height, sizeof(uint16_t));
if(floatAlphaBufferData == NULL || scaledAlphaBufferData == NULL) {
err = kvImageMemoryAllocationError;
goto end_prepare_alpha;
}
origAlpha.data = avif->alphaPlane;
origAlpha.width = avif->width;
origAlpha.height = avif->height;
origAlpha.rowBytes = avif->alphaRowBytes;

vImage_Buffer floatAlphaBuffer = {
.data = floatAlphaBufferData,
.width = avif->width,
.height = avif->height,
.rowBytes = avif->width * sizeof(float),
};
vImage_Buffer scaledAlphaBuffer = {
.data = scaledAlphaBufferData,
.width = avif->width,
.height = avif->height,
.rowBytes = avif->width * sizeof(uint16_t),
};
err = vImageConvert_16UToF(&origAlpha, &floatAlphaBuffer, 0.0f, 1.0f, kvImageNoFlags);
if(err != kvImageNoError) {
NSLog(@"Failed to convert alpha planes from uint16 to float: %ld", err);
goto end_prepare_alpha;
}
float scale = 1.0f;
if(avif->depth == 10) {
scale = (float)((1 << 10) - 1) / 65535.0f;
} else if(avif->depth == 12) {
scale = (float)((1 << 12) - 1) / 65535.0f;
}
err = vImageConvert_FTo16U(&floatAlphaBuffer, &scaledAlphaBuffer, 0.0f, scale, kvImageNoFlags);
if(err != kvImageNoError) {
NSLog(@"Failed to convert alpha planes from uint16 to float: %ld", err);
goto end_prepare_alpha;
}
origAlpha.data = scaledAlphaBufferData;
origAlpha.rowBytes = avif->width * sizeof(uint16_t);
end_prepare_alpha:
free(floatAlphaBufferData);
if(err != kvImageNoError) {
goto end_all;
}
} else {
// allocate dummy data to convert monochrome images.
origAlpha.rowBytes = avif->width * sizeof(uint16_t);
Expand Down Expand Up @@ -750,6 +797,8 @@ static CGImageRef CreateImage16U(avifImage * avif) {
dummyCrData = NULL;
free(dummyAlphaData);
dummyAlphaData = NULL;
free(scaledAlphaBufferData);
scaledAlphaBufferData = NULL;

err = vImageConvert_YpCbCrToARGB_GenerateConversion(&matrix,
&pixelRange,
Expand Down Expand Up @@ -935,6 +984,7 @@ static CGImageRef CreateImage16U(avifImage * avif) {
free(resultBufferData);
free(argbBufferData);
free(ayuvBufferData);
free(scaledAlphaBufferData);
free(dummyCbData);
free(dummyCrData);
free(dummyAlphaData);
Expand Down

0 comments on commit ab2fde9

Please sign in to comment.