Merge pull request #53 from SDWebImage/bugfix_grayscale
Fix the issue when WebP Encoding grayscale image with only 1 channel
This commit is contained in:
commit
2460818eab
|
@ -736,6 +736,9 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
|
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
|
||||||
|
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
|
||||||
|
size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
|
||||||
|
size_t components = bitsPerPixel / bitsPerComponent;
|
||||||
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
|
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
|
||||||
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
|
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
|
||||||
CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
|
CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
|
||||||
|
@ -763,10 +766,15 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
if (!dataRef) {
|
if (!dataRef) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
// Check colorSpace is RGB/RGBA
|
||||||
|
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
|
||||||
|
BOOL isRGB = CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelRGB;
|
||||||
|
|
||||||
uint8_t *rgba = NULL; // RGBA Buffer managed by CFData, don't call `free` on it, instead call `CFRelease` on `dataRef`
|
uint8_t *rgba = NULL; // RGBA Buffer managed by CFData, don't call `free` on it, instead call `CFRelease` on `dataRef`
|
||||||
// We could not assume that input CGImage's color mode is always RGB888/RGBA8888. Convert all other cases to target color mode using vImage
|
// We could not assume that input CGImage's color mode is always RGB888/RGBA8888. Convert all other cases to target color mode using vImage
|
||||||
if (byteOrderNormal && ((alphaInfo == kCGImageAlphaNone) || (alphaInfo == kCGImageAlphaLast))) {
|
BOOL isRGB888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaNone && components == 3;
|
||||||
|
BOOL isRGBA8888 = isRGB && byteOrderNormal && alphaInfo == kCGImageAlphaLast && components == 4;
|
||||||
|
if (isRGB888 || isRGBA8888) {
|
||||||
// If the input CGImage is already RGB888/RGBA8888
|
// If the input CGImage is already RGB888/RGBA8888
|
||||||
rgba = (uint8_t *)CFDataGetBytePtr(dataRef);
|
rgba = (uint8_t *)CFDataGetBytePtr(dataRef);
|
||||||
} else {
|
} else {
|
||||||
|
@ -775,10 +783,11 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
vImage_Error error = kvImageNoError;
|
vImage_Error error = kvImageNoError;
|
||||||
|
|
||||||
vImage_CGImageFormat srcFormat = {
|
vImage_CGImageFormat srcFormat = {
|
||||||
.bitsPerComponent = (uint32_t)CGImageGetBitsPerComponent(imageRef),
|
.bitsPerComponent = (uint32_t)bitsPerComponent,
|
||||||
.bitsPerPixel = (uint32_t)CGImageGetBitsPerPixel(imageRef),
|
.bitsPerPixel = (uint32_t)bitsPerPixel,
|
||||||
.colorSpace = CGImageGetColorSpace(imageRef),
|
.colorSpace = colorSpace,
|
||||||
.bitmapInfo = bitmapInfo
|
.bitmapInfo = bitmapInfo,
|
||||||
|
.renderingIntent = CGImageGetRenderingIntent(imageRef)
|
||||||
};
|
};
|
||||||
vImage_CGImageFormat destFormat = {
|
vImage_CGImageFormat destFormat = {
|
||||||
.bitsPerComponent = 8,
|
.bitsPerComponent = 8,
|
||||||
|
@ -793,14 +802,15 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
vImage_Buffer src = {
|
vImage_Buffer src;
|
||||||
.data = (uint8_t *)CFDataGetBytePtr(dataRef),
|
error = vImageBuffer_InitWithCGImage(&src, &srcFormat, nil, imageRef, kvImageNoFlags);
|
||||||
.width = width,
|
if (error != kvImageNoError) {
|
||||||
.height = height,
|
vImageConverter_Release(convertor);
|
||||||
.rowBytes = bytesPerRow
|
CFRelease(dataRef);
|
||||||
};
|
return nil;
|
||||||
vImage_Buffer dest;
|
}
|
||||||
|
|
||||||
|
vImage_Buffer dest;
|
||||||
error = vImageBuffer_Init(&dest, height, width, destFormat.bitsPerPixel, kvImageNoFlags);
|
error = vImageBuffer_Init(&dest, height, width, destFormat.bitsPerPixel, kvImageNoFlags);
|
||||||
if (error != kvImageNoError) {
|
if (error != kvImageNoError) {
|
||||||
vImageConverter_Release(convertor);
|
vImageConverter_Release(convertor);
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.3 MiB |
|
@ -292,6 +292,35 @@ const int64_t kAsyncTestTimeout = 5;
|
||||||
expect(config.method).to.equal(4);
|
expect(config.method).to.equal(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)testEncodingGrayscaleImage {
|
||||||
|
NSURL *grayscaleImageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"TestImageGrayscale" withExtension:@"jpg"];
|
||||||
|
NSData *grayscaleImageData = [NSData dataWithContentsOfURL:grayscaleImageURL];
|
||||||
|
UIImage *grayscaleImage = [[UIImage alloc] initWithData:grayscaleImageData];
|
||||||
|
expect(grayscaleImage).notTo.beNil();
|
||||||
|
|
||||||
|
NSData *webpData = [SDImageWebPCoder.sharedCoder encodedDataWithImage:grayscaleImage format:SDImageFormatWebP options:nil];
|
||||||
|
expect(webpData).notTo.beNil();
|
||||||
|
|
||||||
|
UIImage *decodedImage = [UIImage sd_imageWithData:webpData];
|
||||||
|
expect(decodedImage).notTo.beNil();
|
||||||
|
|
||||||
|
// Sample to verify that encoded WebP image's color is correct.
|
||||||
|
// The wrong case before bugfix is that each column color will repeats 3 times.
|
||||||
|
CGPoint point1 = CGPointMake(271, 764);
|
||||||
|
CGPoint point2 = CGPointMake(round(point1.x + decodedImage.size.width / 3), point1.y);
|
||||||
|
UIColor *color1 = [decodedImage sd_colorAtPoint:point1];
|
||||||
|
UIColor *color2 = [decodedImage sd_colorAtPoint:point2];
|
||||||
|
CGFloat r1, r2;
|
||||||
|
CGFloat g1, g2;
|
||||||
|
CGFloat b1, b2;
|
||||||
|
[color1 getRed:&r1 green:&g1 blue:&b1 alpha:nil];
|
||||||
|
[color2 getRed:&r2 green:&g2 blue:&b2 alpha:nil];
|
||||||
|
expect(255 * r1).notTo.equal(255 * r2);
|
||||||
|
expect(255 * g1).notTo.equal(255 * g2);
|
||||||
|
expect(255 * b1).notTo.equal(255 * b2);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation SDWebImageWebPCoderTests (Helpers)
|
@implementation SDWebImageWebPCoderTests (Helpers)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
0EF5B6264833B7BC20894578 /* Pods_SDWebImageWebPCoderTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46F21AD7D1692EBAC4D0FF33 /* Pods_SDWebImageWebPCoderTests.framework */; };
|
0EF5B6264833B7BC20894578 /* Pods_SDWebImageWebPCoderTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46F21AD7D1692EBAC4D0FF33 /* Pods_SDWebImageWebPCoderTests.framework */; };
|
||||||
3219F3B2228B0453003822A6 /* TestImageBlendAnimated.webp in Resources */ = {isa = PBXBuildFile; fileRef = 3219F3B1228B0453003822A6 /* TestImageBlendAnimated.webp */; };
|
3219F3B2228B0453003822A6 /* TestImageBlendAnimated.webp in Resources */ = {isa = PBXBuildFile; fileRef = 3219F3B1228B0453003822A6 /* TestImageBlendAnimated.webp */; };
|
||||||
|
325E268E25C82BE1000B807B /* TestImageGrayscale.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 325E268D25C82BE1000B807B /* TestImageGrayscale.jpg */; };
|
||||||
808C918E213FD131004B0F7C /* SDWebImageWebPCoderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 808C918D213FD131004B0F7C /* SDWebImageWebPCoderTests.m */; };
|
808C918E213FD131004B0F7C /* SDWebImageWebPCoderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 808C918D213FD131004B0F7C /* SDWebImageWebPCoderTests.m */; };
|
||||||
808C919C213FD2B2004B0F7C /* TestImageStatic.webp in Resources */ = {isa = PBXBuildFile; fileRef = 808C919A213FD2B2004B0F7C /* TestImageStatic.webp */; };
|
808C919C213FD2B2004B0F7C /* TestImageStatic.webp in Resources */ = {isa = PBXBuildFile; fileRef = 808C919A213FD2B2004B0F7C /* TestImageStatic.webp */; };
|
||||||
808C919D213FD2B2004B0F7C /* TestImageAnimated.webp in Resources */ = {isa = PBXBuildFile; fileRef = 808C919B213FD2B2004B0F7C /* TestImageAnimated.webp */; };
|
808C919D213FD2B2004B0F7C /* TestImageAnimated.webp in Resources */ = {isa = PBXBuildFile; fileRef = 808C919B213FD2B2004B0F7C /* TestImageAnimated.webp */; };
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
28D8AA3D3015E075692FD3E3 /* Pods-SDWebImageWebPCoderTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageWebPCoderTests.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-SDWebImageWebPCoderTests/Pods-SDWebImageWebPCoderTests.debug.xcconfig"; sourceTree = "<group>"; };
|
28D8AA3D3015E075692FD3E3 /* Pods-SDWebImageWebPCoderTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageWebPCoderTests.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-SDWebImageWebPCoderTests/Pods-SDWebImageWebPCoderTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
3219F3B1228B0453003822A6 /* TestImageBlendAnimated.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestImageBlendAnimated.webp; sourceTree = "<group>"; };
|
3219F3B1228B0453003822A6 /* TestImageBlendAnimated.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestImageBlendAnimated.webp; sourceTree = "<group>"; };
|
||||||
|
325E268D25C82BE1000B807B /* TestImageGrayscale.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = TestImageGrayscale.jpg; sourceTree = "<group>"; };
|
||||||
46F21AD7D1692EBAC4D0FF33 /* Pods_SDWebImageWebPCoderTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageWebPCoderTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
46F21AD7D1692EBAC4D0FF33 /* Pods_SDWebImageWebPCoderTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageWebPCoderTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
808C918B213FD130004B0F7C /* SDWebImageWebPCoderTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SDWebImageWebPCoderTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
808C918B213FD130004B0F7C /* SDWebImageWebPCoderTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SDWebImageWebPCoderTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
808C918D213FD131004B0F7C /* SDWebImageWebPCoderTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageWebPCoderTests.m; sourceTree = "<group>"; };
|
808C918D213FD131004B0F7C /* SDWebImageWebPCoderTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageWebPCoderTests.m; sourceTree = "<group>"; };
|
||||||
|
@ -78,6 +80,7 @@
|
||||||
808C9199213FD2B2004B0F7C /* Images */ = {
|
808C9199213FD2B2004B0F7C /* Images */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
325E268D25C82BE1000B807B /* TestImageGrayscale.jpg */,
|
||||||
808C919A213FD2B2004B0F7C /* TestImageStatic.webp */,
|
808C919A213FD2B2004B0F7C /* TestImageStatic.webp */,
|
||||||
808C919B213FD2B2004B0F7C /* TestImageAnimated.webp */,
|
808C919B213FD2B2004B0F7C /* TestImageAnimated.webp */,
|
||||||
3219F3B1228B0453003822A6 /* TestImageBlendAnimated.webp */,
|
3219F3B1228B0453003822A6 /* TestImageBlendAnimated.webp */,
|
||||||
|
@ -154,6 +157,7 @@
|
||||||
3219F3B2228B0453003822A6 /* TestImageBlendAnimated.webp in Resources */,
|
3219F3B2228B0453003822A6 /* TestImageBlendAnimated.webp in Resources */,
|
||||||
808C919D213FD2B2004B0F7C /* TestImageAnimated.webp in Resources */,
|
808C919D213FD2B2004B0F7C /* TestImageAnimated.webp in Resources */,
|
||||||
808C919C213FD2B2004B0F7C /* TestImageStatic.webp in Resources */,
|
808C919C213FD2B2004B0F7C /* TestImageStatic.webp in Resources */,
|
||||||
|
325E268E25C82BE1000B807B /* TestImageGrayscale.jpg in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue