forked from overtake/telegram
-
Notifications
You must be signed in to change notification settings - Fork 0
/
EMImageData.m
96 lines (72 loc) · 2.39 KB
/
EMImageData.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#import "EMImageData.h"
static void EMImageDataRelease(void *info, const void *data, size_t size)
{
if (info != NULL)
{
NSPurgeableData *data = (__bridge_transfer NSPurgeableData *)info;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^
{
[data endContentAccess];
});
}
}
typedef struct {
NSUInteger width, height;
} EMImagePixelSize;
@interface EMImageData ()
{
NSPurgeableData *_data;
NSUInteger _bytesPerRow;
EMImagePixelSize _pixelSize;
void *_cachedImagePtr;
NSImage *_cachedImage;
}
@end
@implementation EMImageData
- (instancetype)initWithSize:(CGSize)size generator:(void (^)(uint8_t *memory, NSUInteger bytesPerRow))generator image:(NSImage *__autoreleasing *)image
{
self = [super init];
if (self != nil)
{
_size = size;
_pixelSize = (EMImagePixelSize){.width = (NSUInteger)size.width, .height = (NSUInteger)size.height};
_bytesPerRow = ((4 * (int)_pixelSize.width) + 15) & (~15);
_data = [[NSPurgeableData alloc] initWithLength:_bytesPerRow * _pixelSize.height];
generator([_data mutableBytes], _bytesPerRow);
if (image)
*image = [self _createImage];
else
[_data endContentAccess];
}
return self;
}
- (void)dealloc
{
}
- (bool)isDiscarded
{
return [_data isContentDiscarded];
}
- (NSImage *)image
{
if ([_data beginContentAccess])
return [self _createImage];
return nil;
}
- (NSImage *)_createImage
{
static CGColorSpaceRef colorSpace = NULL;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
colorSpace = [[NSColorSpace genericRGBColorSpace] CGColorSpace];
});
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
CGDataProviderRef dataProvider = CGDataProviderCreateWithData((__bridge_retained void *)_data, [_data bytes], _bytesPerRow, EMImageDataRelease);
CGImageRef image = CGImageCreate(_pixelSize.width, _pixelSize.height, 8, 32, _bytesPerRow, colorSpace, bitmapInfo, dataProvider, NULL, false, (CGColorRenderingIntent)0);
CGDataProviderRelease(dataProvider);
NSImage *result = [[NSImage alloc] initWithCGImage:image size:NSMakeSize(_pixelSize.width,_pixelSize.height)];
CGImageRelease(image);
return result;
}
@end