Vuo 2.4.4
Loading...
Searching...
No Matches
VuoImageGet.cc
Go to the documentation of this file.
1
10#include "VuoFreeImage.h"
11#include "VuoImageGet.h"
12
14#include "VuoImageRotate.h"
15#include "VuoGlPool.h"
16#include "VuoUrl.h"
17#include "VuoUrlFetch.h"
18
19#include <string.h>
20
21#pragma clang diagnostic push
22#pragma clang diagnostic ignored "-Wdocumentation"
24#define BOOL FREEIMAGE_BOOL
25#include <FreeImage.h>
26#undef BOOL
27#pragma clang diagnostic pop
28
29#include <OpenGL/CGLMacro.h>
30
31extern "C"
32{
33#ifdef VUO_COMPILER
35 "title" : "VuoImageGet",
36 "dependencies" : [
37 "VuoFreeImage",
38 "VuoImage",
39 "VuoImageCoreGraphics",
40 "VuoImageRotate",
41 "VuoUrlFetch",
42 ]
43});
44#endif
45}
46
47
55float VuoImage_getScaleFactor(const char *url)
56{
58 if (!resolvedUrl)
59 return 1;
60 VuoLocal(resolvedUrl);
61
62 VuoText path;
63 if (!VuoUrl_getParts(resolvedUrl, NULL, NULL, NULL, NULL, &path, NULL, NULL))
64 return 1;
65 VuoLocal(path);
66
67 size_t lastDot = VuoText_findLastOccurrence(path, ".");
68 if (lastDot < 6)
69 return 1;
70
71 // `@` is URL-escaped as `%40`.
72 if (path[lastDot-6] == '%' && path[lastDot-5] == '4' && path[lastDot-4] == '0' && path[lastDot-2] == 'x')
73 {
74 char c = path[lastDot-3];
75 if (c >= '1' && c <= '9')
76 return c - '0';
77 }
78
79 return 1;
80}
81
88VuoImage VuoImage_get(const char *imageURL)
89{
90 if (!imageURL || !strlen(imageURL))
91 return NULL;
92
93 void *data;
94 unsigned int dataLength;
95 if (!VuoUrl_fetch(imageURL, &data, &dataLength))
96 return NULL;
97
98 // Decode the memory buffer into a straightforward array of BGRA pixels
99 FIBITMAP *dib;
100 {
101 FIMEMORY *hmem = FreeImage_OpenMemory((BYTE *)data, dataLength);
102
103 FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
104 if (fif == FIF_UNKNOWN)
105 {
106 // FreeImage couldn't read it; try CoreGraphics.
107 CFDataRef cfd = CFDataCreateWithBytesNoCopy(nullptr, (UInt8 *)data, dataLength, kCFAllocatorNull);
108 if (cfd)
109 {
110 CGImageSourceRef cgis = CGImageSourceCreateWithData(cfd, nullptr);
111 CFRelease(cfd);
112 if (cgis)
113 {
114 size_t imageIndex = 0;
115 CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(cgis, imageIndex, nullptr);
116 int32_t orientation = kCGImagePropertyOrientationUp;
117 if (properties)
118 {
119 CFNumberRef orientationCF = static_cast<CFNumberRef>(CFDictionaryGetValue(properties, kCGImagePropertyOrientation));
120 CFNumberGetValue(orientationCF, kCFNumberSInt32Type, &orientation);
121 CFRelease(properties);
122 }
123
124 CGImageRef cgi = CGImageSourceCreateImageAtIndex(cgis, imageIndex, nullptr);
125 CFRelease(cgis);
126 if (cgi)
127 {
129 if (vi)
130 vi->scaleFactor = VuoImage_getScaleFactor(imageURL);
131 CGImageRelease(cgi);
132 FreeImage_CloseMemory(hmem);
133 free(data);
134
135 if (orientation != kCGImagePropertyOrientationUp)
136 {
138 VuoLocal(rotator);
139
140 VuoReal angleInDegrees = 0;
141 if (orientation == kCGImagePropertyOrientationDown)
142 angleInDegrees = 180;
143 else if (orientation == kCGImagePropertyOrientationLeft)
144 angleInDegrees = 90;
145 else if (orientation == kCGImagePropertyOrientationRight)
146 angleInDegrees = -90;
147
148 VuoImage rotatedImage = VuoImageRotate_rotate(vi, rotator, angleInDegrees, true);
149 VuoRetain(vi);
150 VuoRelease(vi);
151 vi = rotatedImage;
152 }
153
154 return vi;
155 }
156 }
157 }
158
159 VUserLog("Error: '%s': FreeImage couldn't determine the image type. The file might not be an image, or it might be corrupted.", imageURL);
160 FreeImage_CloseMemory(hmem);
161 free(data);
162 return NULL;
163 }
164 if (!FreeImage_FIFSupportsReading(fif))
165 {
166 VUserLog("Error: '%s': FreeImage can't read this type of image.", imageURL);
167 FreeImage_CloseMemory(hmem);
168 free(data);
169 return NULL;
170 }
171
172 dib = FreeImage_LoadFromMemory(fif, hmem, JPEG_EXIFROTATE);
173 FreeImage_CloseMemory(hmem);
174
175 if (!dib)
176 {
177 VUserLog("Error: '%s': FreeImage couldn't read this image. The file might be corrupted.", imageURL);
178 free(data);
179 return NULL;
180 }
181 }
182
183 VuoImage vuoImage = VuoFreeImage_convertFreeImageToVuoImage(dib, data, imageURL);
184 if (!vuoImage)
185 return NULL;
186
187 vuoImage->scaleFactor = VuoImage_getScaleFactor(imageURL);
188
189 return vuoImage;
190}