2024-05-08 22:43:27 +04:00

65 lines
2.0 KiB
Objective-C

#import <QOILoader/QOILoader.h>
#define QOI_IMPLEMENTATION
#import "qoi.h"
NSData * _Nullable encodeImageQOI(UIImage * _Nonnull image) {
if (image == nil) {
return nil;
}
CGImageRef cgImage = image.CGImage;
if (cgImage == nil) {
return nil;
}
CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage);
if (dataProvider == nil) {
return nil;
}
NSData *data = (__bridge_transfer NSData *)CGDataProviderCopyData(dataProvider);
if (data == nil) {
return nil;
}
if (CGImageGetBitsPerPixel(cgImage) / CGImageGetBitsPerComponent(cgImage) != 4) {
return nil;
}
int outLength = 0;
void *outBytes = qoi_encode(data.bytes, &(qoi_desc){
.width = (unsigned int)CGImageGetWidth(cgImage),
.height = (unsigned int)CGImageGetHeight(cgImage),
.channels = 4,
.colorspace = QOI_SRGB
}, &outLength);
if (outBytes == nil) {
return nil;
}
return [[NSData alloc] initWithBytesNoCopy:outBytes length:outLength freeWhenDone:true];
}
static void releaseMallocedMemory(void *info, const void *data, size_t size) {
free((void *)data);
}
UIImage * _Nullable decodeImageQOI(NSData * _Nonnull data) {
qoi_desc desc;
void *outPixels = qoi_decode(data.bytes, (int)data.length, &desc, 4);
if (outPixels == nil) {
return nil;
}
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(nil, outPixels, desc.width * 4 * desc.height, releaseMallocedMemory);
if (dataProvider == nil) {
free(outPixels);
return nil;
}
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;
CGImageRef cgImage = CGImageCreate(desc.width, desc.height, 8, 8 * 4, desc.width * 4, CGColorSpaceCreateDeviceRGB(), bitmapInfo, dataProvider, nil, false, kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider);
UIImage *image = [[UIImage alloc] initWithCGImage:cgImage];
CGImageRelease(cgImage);
return image;
}