This commit is contained in:
Zen-CODE 2014-09-08 20:25:43 +02:00
commit a6b5d26dba
1 changed files with 71 additions and 36 deletions

View File

@ -27,10 +27,10 @@ ctypedef signed long CFIndex
cdef unsigned int kCFStringEncodingUTF8 = 0x08000100
cdef extern from "stdlib.h":
cdef extern from "stdlib.h" nogil:
void* calloc(size_t, size_t)
cdef extern from "CoreGraphics/CGDataProvider.h":
cdef extern from "CoreGraphics/CGDataProvider.h" nogil:
ctypedef void *CFDataRef
unsigned char *CFDataGetBytePtr(CFDataRef)
@ -48,7 +48,7 @@ cdef extern from "CoreGraphics/CGDataProvider.h":
CGRect CGRectMake(float, float, float, float)
cdef extern from "CoreFoundation/CFBase.h":
cdef extern from "CoreFoundation/CFBase.h" nogil:
ctypedef void *CFAllocatorRef
ctypedef void *CFStringRef
ctypedef void *CFURLRef
@ -58,7 +58,7 @@ cdef extern from "CoreFoundation/CFBase.h":
void CFRelease(CFTypeRef cf)
cdef extern from "CoreFoundation/CFURL.h":
cdef extern from "CoreFoundation/CFURL.h" nogil:
ctypedef void *CFURLRef
ctypedef int CFURLPathStyle
int kCFURLPOSIXPathStyle
@ -70,7 +70,11 @@ cdef extern from "CoreFoundation/CFURL.h":
cdef extern from "CoreFoundation/CFDictionary.h":
ctypedef void *CFDictionaryRef
cdef extern from "CoreGraphics/CGImage.h":
cdef extern from "CoreFoundation/CoreFoundation.h" nogil:
CFDataRef CFDataCreateWithBytesNoCopy(
CFAllocatorRef, char *, int length, CFAllocatorRef)
cdef extern from "CoreGraphics/CGImage.h" nogil:
ctypedef void *CGImageRef
void CGImageRelease(CGImageRef image)
size_t CGImageGetWidth(CGImageRef)
@ -83,16 +87,16 @@ cdef extern from "CoreGraphics/CGImage.h":
int kCGImageAlphaPremultipliedFirst
int kCGBitmapByteOrder32Host
cdef extern from "CoreGraphics/CGColorSpace.h":
cdef extern from "CoreGraphics/CGColorSpace.h" nogil:
ctypedef void *CGColorSpaceRef
CGColorSpaceRef CGColorSpaceCreateDeviceRGB()
void CGColorSpaceRelease(CGColorSpaceRef cs)
cdef extern from "CoreGraphics/CGAffineTransform.h":
cdef extern from "CoreGraphics/CGAffineTransform.h" nogil:
ctypedef void *CGAffineTransform
CGAffineTransform CGAffineTransformMake(float a, float b, float c, float d, float tx, float ty)
cdef extern from "CoreGraphics/CGContext.h":
cdef extern from "CoreGraphics/CGContext.h" nogil:
ctypedef void *CGContextRef
void CGContextRelease(CGContextRef c)
void CGContextDrawImage(CGContextRef, CGRect, CGImageRef)
@ -101,20 +105,22 @@ cdef extern from "CoreGraphics/CGContext.h":
void CGContextSetBlendMode(CGContextRef, int)
void CGContextConcatCTM(CGContextRef fc, CGAffineTransform matrix)
cdef extern from "CoreGraphics/CGBitmapContext.h":
cdef extern from "CoreGraphics/CGBitmapContext.h" nogil:
CGImageRef CGBitmapContextCreateImage(CGColorSpaceRef)
CGContextRef CGBitmapContextCreate(
void *data, size_t width, size_t height, size_t bitsPerComponent,
size_t bytesPerRow, CGColorSpaceRef colorspace, unsigned int bitmapInfo)
cdef extern from "ImageIO/CGImageSource.h":
cdef extern from "ImageIO/CGImageSource.h" nogil:
ctypedef void *CGImageSourceRef
CGImageSourceRef CGImageSourceCreateWithURL(
CFURLRef, CFDictionaryRef)
CGImageRef CGImageSourceCreateImageAtIndex(
CGImageSourceRef, size_t, CFDictionaryRef)
CGImageRef CGImageSourceCreateWithData(
CFDataRef data, CFDictionaryRef options)
cdef extern from "ImageIO/CGImageDestination.h":
cdef extern from "ImageIO/CGImageDestination.h" nogil:
ctypedef void *CGImageDestinationRef
CGImageDestinationRef CGImageDestinationCreateWithURL(
CFURLRef, CFStringRef, size_t, CFDictionaryRef)
@ -122,7 +128,7 @@ cdef extern from "ImageIO/CGImageDestination.h":
CGImageRef image, CFDictionaryRef properties)
int CGImageDestinationFinalize(CGImageDestinationRef idst)
cdef extern from "Accelerate/Accelerate.h":
cdef extern from "Accelerate/Accelerate.h" nogil:
ctypedef struct vImage_Buffer:
void *data
int width
@ -134,32 +140,62 @@ cdef extern from "Accelerate/Accelerate.h":
int flags)
def load_image_data(bytes _url):
def load_image_data(bytes _url, bytes _data=None):
cdef size_t width, height
cdef char *r_data = NULL
cdef size_t datalen = 0
cdef char *c_url = NULL
cdef char *c_data = NULL
if _url:
c_url = _url
datalen = len(_url)
if _data:
c_data = _data
datalen = len(_data)
c_load_image_data(c_url, c_data, datalen, &width, &height, &r_data)
if r_data == NULL:
raise ValueError("No image to load at {}".format(_url))
py_data = r_data[:width * height * 4]
free(r_data)
return (width, height, 'rgba', py_data)
cdef void c_load_image_data(char *_url, char *_data, size_t datalen, size_t *width, size_t
*height, char **r_data) nogil:
# load an image from the _url with CoreGraphics, and output an RGBA string.
cdef CFURLRef url
url = CFURLCreateFromFileSystemRepresentation(NULL, <bytes> _url, len(_url), 0)
cdef CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(url, NULL)
if not myImageSourceRef:
CFRelease(url)
raise ValueError('No image to load at %r' % _url)
cdef CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL)
cdef size_t width = CGImageGetWidth(myImageRef)
cdef size_t height = CGImageGetHeight(myImageRef)
cdef CGRect rect = CGRectMake(0, 0, width, height)
cdef CGImageSourceRef myImageSourceRef
cdef CFDataRef dataref
width[0] = height[0] = 0
r_data[0] = NULL
if _data != NULL:
dataref = CFDataCreateWithBytesNoCopy(NULL, _data, datalen, NULL)
myImageSourceRef = CGImageSourceCreateWithData(dataref, NULL)
else:
url = CFURLCreateFromFileSystemRepresentation(NULL, <unsigned char *>_url, datalen, 0)
myImageSourceRef = CGImageSourceCreateWithURL(url, NULL)
if not myImageSourceRef:
CFRelease(url)
return
cdef CGImageRef myImageRef = CGImageSourceCreateImageAtIndex(myImageSourceRef, 0, NULL)
width[0] = CGImageGetWidth(myImageRef)
height[0] = CGImageGetHeight(myImageRef)
cdef CGRect rect = CGRectMake(0, 0, width[0], height[0])
cdef CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB()
cdef vImage_Buffer src
cdef vImage_Buffer dest
dest.height = src.height = height
dest.width = src.width = width
dest.rowBytes = src.rowBytes = width * 4
src.data = calloc(width * 4, height)
dest.data = calloc(width * 4, height)
dest.height = src.height = height[0]
dest.width = src.width = width[0]
dest.rowBytes = src.rowBytes = width[0] * 4
src.data = calloc(width[0] * 4, height[0])
dest.data = r_data[0] = <char *>calloc(width[0] * 4, height[0])
# endianness: kCGBitmapByteOrder32Little = (2 << 12)
# (2 << 12) | kCGImageAlphaPremultipliedLast)
cdef CGContextRef myBitmapContext = CGBitmapContextCreate(
src.data, width, height, 8, width * 4, space,
src.data, width[0], height[0], 8, width[0] * 4, space,
kCGBitmapByteOrder32Host | kCGImageAlphaNoneSkipFirst)
CGContextSetBlendMode(myBitmapContext, kCGBlendModeCopy)
@ -169,9 +205,6 @@ def load_image_data(bytes _url):
cdef unsigned char *pmap = [2, 1, 0, 3]
vImagePermuteChannels_ARGB8888(&src, &dest, pmap, 0)
# get a python string
r_data = (<char *>dest.data)[:width * height * 4]
# release everything
CFRelease(url)
CGImageRelease(<CGImageRef>myImageSourceRef)
@ -179,9 +212,7 @@ def load_image_data(bytes _url):
CGContextRelease(myBitmapContext)
CGColorSpaceRelease(space)
free(src.data)
free(dest.data)
return (width, height, 'rgba', r_data)
#free(dest.data) # this part is freed by the caller.
def save_image_rgba(filename, width, height, data, flipped):
# compatibility, could be removed i guess
@ -285,7 +316,11 @@ class ImageLoaderImageIO(ImageLoaderBase):
def load(self, filename):
# FIXME: if the filename is unicode, the loader is failing.
ret = load_image_data(str(filename))
if hasattr(filename, "fileno"):
data = filename.read()
ret = load_image_data(None, data)
else:
ret = load_image_data(str(filename))
if ret is None:
Logger.warning('Image: Unable to load image <%s>' % filename)
raise Exception('Unable to load image')