in iOS/WAStickersThirdParty/YYImageCoder.m [917:979]
CGImageRef YYCGImageCreateAffineTransformCopy(CGImageRef imageRef, CGAffineTransform transform, CGSize destSize, CGBitmapInfo destBitmapInfo) {
if (!imageRef) return NULL;
size_t srcWidth = CGImageGetWidth(imageRef);
size_t srcHeight = CGImageGetHeight(imageRef);
size_t destWidth = round(destSize.width);
size_t destHeight = round(destSize.height);
if (srcWidth == 0 || srcHeight == 0 || destWidth == 0 || destHeight == 0) return NULL;
CGDataProviderRef tmpProvider = NULL, destProvider = NULL;
CGImageRef tmpImage = NULL, destImage = NULL;
vImage_Buffer src = {0}, tmp = {0}, dest = {0};
if(!YYCGImageDecodeToBitmapBufferWith32BitFormat(imageRef, &src, kCGImageAlphaFirst | kCGBitmapByteOrderDefault)) return NULL;
size_t destBytesPerRow = YYImageByteAlign(destWidth * 4, 32);
tmp.data = malloc(destHeight * destBytesPerRow);
if (!tmp.data) goto fail;
tmp.width = destWidth;
tmp.height = destHeight;
tmp.rowBytes = destBytesPerRow;
vImage_CGAffineTransform vTransform = *((vImage_CGAffineTransform *)&transform);
uint8_t backColor[4] = {0};
vImage_Error error = vImageAffineWarpCG_ARGB8888(&src, &tmp, NULL, &vTransform, backColor, kvImageBackgroundColorFill);
if (error != kvImageNoError) goto fail;
free(src.data);
src.data = NULL;
tmpProvider = CGDataProviderCreateWithData(tmp.data, tmp.data, destHeight * destBytesPerRow, YYCGDataProviderReleaseDataCallback);
if (!tmpProvider) goto fail;
tmp.data = NULL; // hold by provider
tmpImage = CGImageCreate(destWidth, destHeight, 8, 32, destBytesPerRow, YYCGColorSpaceGetDeviceRGB(), kCGImageAlphaFirst | kCGBitmapByteOrderDefault, tmpProvider, NULL, false, kCGRenderingIntentDefault);
if (!tmpImage) goto fail;
CFRelease(tmpProvider);
tmpProvider = NULL;
if ((destBitmapInfo & kCGBitmapAlphaInfoMask) == kCGImageAlphaFirst &&
(destBitmapInfo & kCGBitmapByteOrderMask) != kCGBitmapByteOrder32Little) {
return tmpImage;
}
if (!YYCGImageDecodeToBitmapBufferWith32BitFormat(tmpImage, &dest, destBitmapInfo)) goto fail;
CFRelease(tmpImage);
tmpImage = NULL;
destProvider = CGDataProviderCreateWithData(dest.data, dest.data, destHeight * destBytesPerRow, YYCGDataProviderReleaseDataCallback);
if (!destProvider) goto fail;
dest.data = NULL; // hold by provider
destImage = CGImageCreate(destWidth, destHeight, 8, 32, destBytesPerRow, YYCGColorSpaceGetDeviceRGB(), destBitmapInfo, destProvider, NULL, false, kCGRenderingIntentDefault);
if (!destImage) goto fail;
CFRelease(destProvider);
destProvider = NULL;
return destImage;
fail:
if (src.data) free(src.data);
if (tmp.data) free(tmp.data);
if (dest.data) free(dest.data);
if (tmpProvider) CFRelease(tmpProvider);
if (tmpImage) CFRelease(tmpImage);
if (destProvider) CFRelease(destProvider);
return NULL;
}