kaleidoscope 1.4.0
 
Loading...
Searching...
No Matches
kaleidoscope.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  Point2D_t
 Data struct for pixel locations. More...
 
struct  TransformationInfo_t
 Data struct for transformation information. More...
 
struct  KaleidoscopeHandle_t
 Struct for kaleidoscope effect generator. More...
 

Typedefs

typedef struct Point2D_t Point2D
 
typedef struct TransformationInfo_t TransformationInfo
 
typedef struct KaleidoscopeHandle_t KaleidoscopeHandle
 

Functions

void getKaleidoscopeVersion (int *major, int *minor, int *patch)
 Get the Kaleidoscope Library version as integer.
 
char * getKaleidoscopeVersionString ()
 Get the Kaleidoscope Library version as string.
 
char * getKaleidoscopeLibraryInfo ()
 Get the Kaleidoscope Library info as string.
 
void interpolate (TransformationInfo *dataOut, TransformationInfo *dataIn, int width, int height)
 A simple interpolation function. Internal use only.
 
void rotatePoints (TransformationInfo *outData, TransformationInfo *orgData, int width, int height, double angle)
 Rotates the coordinates of sliced triangle. Internal use only.
 
int sliceTriangle (TransformationInfo *transformPtr, int width, int height, int n, double scaleDown)
 Slices a suitable triangle from image.
 
int initKaleidoscope (KaleidoscopeHandle *handler, int n, int width, int height, int nComponents, double scaleDown)
 Initializes kaleidoscope handler.
 
void processKaleidoscope (KaleidoscopeHandle *handler, double k, unsigned char *imgIn, unsigned char *imgOut)
 Applies kaleidoscope effect to image.
 
void deInitKaleidoscope (KaleidoscopeHandle *handler)
 Deinitializes kaleidoscope handler.
 

Typedef Documentation

◆ KaleidoscopeHandle

Definition at line 46 of file kaleidoscope.h.

◆ Point2D

typedef struct Point2D_t Point2D

Definition at line 12 of file kaleidoscope.h.

◆ TransformationInfo

Definition at line 28 of file kaleidoscope.h.

Function Documentation

◆ deInitKaleidoscope()

void deInitKaleidoscope ( KaleidoscopeHandle * handler)

Deinitializes kaleidoscope handler.

Parameters
[in]handlerKaleidoscope effect handler

Definition at line 304 of file kaleidoscope.c.

305{
306 if (handler)
307 free(handler->pTransferFunc);
308}
struct TransformationInfo_t * pTransferFunc
Transformation info.
Here is the caller graph for this function:

◆ getKaleidoscopeLibraryInfo()

char * getKaleidoscopeLibraryInfo ( )

Get the Kaleidoscope Library info as string.

Returns
char* Library information

Definition at line 30 of file kaleidoscope.c.

31{
32 int offset = 0;
33 static char info[125];
34
35 strncpy(info, PROJECT_VERSION, sizeof(PROJECT_VERSION));
36 offset += sizeof(PROJECT_VERSION);
37 memset(&info[offset - 1], 32, 1);
38 strncpy(&info[offset], COMPILER_NAME, sizeof(COMPILER_NAME));
39 offset += sizeof(COMPILER_NAME);
40 memset(&info[offset - 1], 32, 1);
41 strncpy(&info[offset], COMPILER_VERSION, sizeof(COMPILER_VERSION));
42 offset += sizeof(COMPILER_VERSION);
43 memset(&info[offset - 1], 32, 1);
44 strncpy(&info[offset], BUILD_TYPE, sizeof(BUILD_TYPE));
45 offset += sizeof(BUILD_TYPE);
46 memset(&info[offset - 1], 32, 1);
47 strncpy(&info[offset], PROJECT_BUILD_DATE, sizeof(PROJECT_BUILD_DATE));
48 offset += sizeof(PROJECT_BUILD_DATE);
49 memset(&info[offset - 1], 32, 1);
50 strncpy(&info[offset], PROJECT_BUILD_TIME, sizeof(PROJECT_BUILD_TIME));
51 // offset += sizeof(PROJECT_BUILD_TIME);
52
53 return info;
54}
Here is the caller graph for this function:

◆ getKaleidoscopeVersion()

void getKaleidoscopeVersion ( int * major,
int * minor,
int * patch )

Get the Kaleidoscope Library version as integer.

Parameters
[in,out]majorMajor number
[in,out]minorMinor number
[in,out]patchPatch number

Definition at line 13 of file kaleidoscope.c.

14{
15 if (major && minor && patch)
16 {
17 *major = PROJECT_MAJOR_VERSION;
18 *minor = PROJECT_MINOR_VERSION;
19 *patch = PROJECT_PATCH_VERSION;
20 }
21}

◆ getKaleidoscopeVersionString()

char * getKaleidoscopeVersionString ( )

Get the Kaleidoscope Library version as string.

Returns
char* Library version

Definition at line 23 of file kaleidoscope.c.

24{
25 static char info[sizeof(PROJECT_VERSION)];
26 strncpy(info, PROJECT_VERSION, sizeof(PROJECT_VERSION));
27 return info;
28}

◆ initKaleidoscope()

int initKaleidoscope ( KaleidoscopeHandle * handler,
int n,
int width,
int height,
int nComponents,
double scaleDown )

Initializes kaleidoscope handler.

Parameters
[in,out]handlerKaleidoscope effect handler
[in]nNumber of images for effect
[in]widthImage width
[in]heightImage height
[in]nComponentsNumber of image components (eg 3 for RGB)
[in]scaleDownScale down ratio to shrink image. Must be between 0.0 and 1.0
Returns
int 0 on success, negative otherwise

Definition at line 199 of file kaleidoscope.c.

200{
201 int idx, jdx;
202
203 int retval = EXIT_FAILURE;
204 const int nPixels = width * height;
205 TransformationInfo *buffPtr1 = NULL, *buffPtr2 = NULL;
206
207 // Check parameters
208 if (handler == NULL || n <= 2 || width <= 0 || height <= 0 || nComponents <= 0 || scaleDown <= 0.0 ||
209 scaleDown >= 1.0)
210 return EXIT_FAILURE;
211
212 assert(handler);
213 assert(n > 2);
214 assert(width > 0);
215 assert(height > 0);
216 assert(nComponents > 0);
217 assert(scaleDown > 0.0);
218 assert(scaleDown < 1.0);
219
220 handler->width = width;
221 handler->height = height;
222 handler->nComponents = nComponents;
223
224 buffPtr1 = (TransformationInfo *)calloc(nPixels, sizeof(TransformationInfo));
225 buffPtr2 = (TransformationInfo *)calloc(nPixels, sizeof(TransformationInfo));
226 if (!buffPtr1 || !buffPtr2)
227 goto cleanup;
228
229 if (sliceTriangle(buffPtr1, width, height, n, scaleDown))
230 goto cleanup;
231
232 // Rotate all points and fix origin to left top
233 for (idx = 0; idx < n; ++idx)
234 {
235 double rotationAngle = idx * (360.0 / n);
236 rotatePoints(buffPtr2, buffPtr1, width, height, rotationAngle);
237 }
238
239 // Fill rotation artifacts
240 memset(buffPtr1, 0, sizeof(TransformationInfo) * width * height);
241 interpolate(buffPtr1, buffPtr2, width, height);
242
243 // Remove zeros and set to points for handler
244 handler->nPoints = 0;
245 for (idx = 0; idx < nPixels; ++idx)
246 {
247 TransformationInfo *ptr = &buffPtr1[idx];
248 if (!(ptr->srcLocation.x) || !(ptr->srcLocation.y))
249 continue;
250
251 buffPtr1[handler->nPoints] = *ptr;
252 buffPtr1[handler->nPoints].srcOffset =
253 ptr->srcLocation.x * nComponents + ptr->srcLocation.y * width * nComponents;
254 buffPtr1[handler->nPoints].dstOffset =
255 ptr->dstLocation.x * nComponents + ptr->dstLocation.y * width * nComponents;
256 ++(handler->nPoints);
257 }
258
259 // Sort
260 qsort(buffPtr1, handler->nPoints, sizeof(TransformationInfo), compare);
261
262 // Deduplicate
263 jdx = 0;
264 for (idx = 1; idx < handler->nPoints; ++idx)
265 {
266 if (compare(&buffPtr1[jdx], &buffPtr1[idx]))
267 {
268 buffPtr1[jdx] = buffPtr1[idx];
269 ++jdx;
270 }
271 }
272 handler->nPoints = jdx;
273
274 handler->pTransferFunc = (TransformationInfo *)malloc(handler->nPoints * sizeof(TransformationInfo));
275 memcpy(handler->pTransferFunc, buffPtr1, handler->nPoints * sizeof(TransformationInfo));
276 retval = EXIT_SUCCESS;
277
278cleanup:
279 free(buffPtr1);
280 free(buffPtr2);
281
282 if (retval == EXIT_FAILURE)
283 free(handler->pTransferFunc);
284
285 return retval;
286}
void interpolate(TransformationInfo *dataOut, TransformationInfo *dataIn, int width, int height)
A simple interpolation function. Internal use only.
void rotatePoints(TransformationInfo *outData, TransformationInfo *orgData, int width, int height, double angle)
Rotates the coordinates of sliced triangle. Internal use only.
int compare(const void *lhsPtr, const void *rhsPtr)
int sliceTriangle(TransformationInfo *transformPtr, int width, int height, int n, double scaleDown)
Slices a suitable triangle from image.
int height
Image height.
int width
Image width.
long long nPoints
Total number of points of transfer function.
unsigned char nComponents
Number of components (eg 3 for RGB)
Data struct for transformation information.
unsigned long long srcOffset
Offset from source image.
unsigned long long dstOffset
Offset from destination image.
Point2D srcLocation
Location from source image.
Point2D dstLocation
Location to destination image.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ interpolate()

void interpolate ( TransformationInfo * dataOut,
TransformationInfo * dataIn,
int width,
int height )

A simple interpolation function. Internal use only.

Parameters
[out]dataOutOutput (interpolated) binary image
[in]dataInInput binary image
[in]widthWidth of input image
[in]heightHeight of input image

Definition at line 63 of file kaleidoscope.c.

64{
65 int idx, jdx;
66
67 // Very simple implementation of nearest neighbour interpolation
68 for (idx = 1; idx < height - 1; ++idx)
69 {
70 int heightOffset = idx * width;
71 for (jdx = 1; jdx < width - 1; ++jdx)
72 {
73 TransformationInfo *ptrIn = &dataIn[heightOffset + jdx];
74 TransformationInfo *ptrOut = &dataOut[heightOffset + jdx];
75 if (!(ptrIn->dstLocation.x) && !(ptrIn->dstLocation.y))
76 {
77 ptrOut->dstLocation.x = jdx;
78 ptrOut->dstLocation.y = idx;
79 if (((ptrIn - 1)->dstLocation.x) || ((ptrIn - 1)->dstLocation.y)) // Left
80 {
81 ptrOut->srcLocation.x = (ptrIn - 1)->srcLocation.x + 1;
82 ptrOut->srcLocation.y = (ptrIn - 1)->srcLocation.y;
83 }
84 else if (((ptrIn + 1)->dstLocation.x) || ((ptrIn + 1)->dstLocation.y)) // Right
85 {
86 ptrOut->srcLocation.x = (ptrIn + 1)->srcLocation.x - 1;
87 ptrOut->srcLocation.y = (ptrIn + 1)->srcLocation.y;
88 }
89 else if (((ptrIn - width)->dstLocation.x) || ((ptrIn - width)->dstLocation.y)) // Top
90 {
91 ptrOut->srcLocation.x = (ptrIn - width)->srcLocation.x;
92 ptrOut->srcLocation.y = (ptrIn - width)->srcLocation.y - 1;
93 }
94 else if (((ptrIn + width)->dstLocation.x) || ((ptrIn + width)->dstLocation.y)) // Bottom
95 {
96 ptrOut->srcLocation.x = (ptrIn + width)->srcLocation.x;
97 ptrOut->srcLocation.y = (ptrIn + width)->srcLocation.y + 1;
98 }
99 else if (((ptrIn - width - 1)->dstLocation.x) || ((ptrIn - width - 1)->dstLocation.y)) // Top-Left
100 {
101 ptrOut->srcLocation.x = (ptrIn - width - 1)->srcLocation.x - 1;
102 ptrOut->srcLocation.y = (ptrIn - width - 1)->srcLocation.y - 1;
103 }
104 else if (((ptrIn - width + 1)->dstLocation.x) || ((ptrIn - width + 1)->dstLocation.y)) // Top-Right
105 {
106 ptrOut->srcLocation.x = (ptrIn - width + 1)->srcLocation.x + 1;
107 ptrOut->srcLocation.y = (ptrIn - width + 1)->srcLocation.y - 1;
108 }
109 else if (((ptrIn + width - 1)->dstLocation.x) || ((ptrIn + width - 1)->dstLocation.y)) // Bottom-Left
110 {
111 ptrOut->srcLocation.x = (ptrIn + width - 1)->srcLocation.x - 1;
112 ptrOut->srcLocation.y = (ptrIn + width - 1)->srcLocation.y - 1;
113 }
114 else if (((ptrIn + width + 1)->dstLocation.x) || ((ptrIn + width + 1)->dstLocation.y)) // Bottom-Right
115 {
116 ptrOut->srcLocation.x = (ptrIn + width + 1)->srcLocation.x + 1;
117 ptrOut->srcLocation.y = (ptrIn + width + 1)->srcLocation.y + 1;
118 }
119 else
120 memset(ptrOut, 0, sizeof(TransformationInfo));
121 }
122 else
123 *ptrOut = *ptrIn;
124 }
125 }
126}
Here is the caller graph for this function:

◆ processKaleidoscope()

void processKaleidoscope ( KaleidoscopeHandle * handler,
double k,
unsigned char * imgIn,
unsigned char * imgOut )

Applies kaleidoscope effect to image.

Parameters
[in]handlerKaleidoscope effect handler
[in]kVariable to dim background. Should be between 0.0 and 1.0
[in]imgInInput image
[out]imgOutOutput image

Definition at line 288 of file kaleidoscope.c.

289{
290 long long idx;
291 const long long nComponents = handler->nComponents;
292 const long long nPixels = (long long)handler->width * handler->height * handler->nComponents;
293
294 unsigned char *srcPtr = imgIn;
295 unsigned char *destPtr = imgOut;
296 TransformationInfo *ptrTransform = &(handler->pTransferFunc[0]);
297
298 for (idx = 0; idx < nPixels; ++idx, ++destPtr, ++srcPtr) // Dim image
299 *destPtr = (unsigned char)((*srcPtr) * k);
300 for (idx = 0; idx < handler->nPoints; ++idx, ++ptrTransform) // Merge
301 memcpy(&(imgOut[ptrTransform->dstOffset]), &(imgIn[ptrTransform->srcOffset]), nComponents);
302}
Here is the caller graph for this function:

◆ rotatePoints()

void rotatePoints ( TransformationInfo * outData,
TransformationInfo * orgData,
int width,
int height,
double angle )

Rotates the coordinates of sliced triangle. Internal use only.

Parameters
[out]outDataRotated data
[in]orgDataSliced data coordinates
[in]widthWidth of input image
[in]heightHeight of input image
[in]angleTop angle of sliced triangle

Definition at line 128 of file kaleidoscope.c.

129{
130 int idx;
131 double cosVal = cos(angle * M_PI / 180);
132 double sinVal = sin(angle * M_PI / 180);
133
134 for (idx = 0; idx < width * height; ++idx)
135 {
136 if (orgData[idx].dstLocation.x || orgData[idx].dstLocation.y)
137 {
138 int newX = (int)round(orgData[idx].dstLocation.x * cosVal + orgData[idx].dstLocation.y * sinVal);
139 int newY = (int)round(orgData[idx].dstLocation.y * cosVal - orgData[idx].dstLocation.x * sinVal);
140
141 // Fix origin to top left again
142 newX += (width / 2);
143 newY += (height / 2);
144
145 if (newX <= width && newX >= 0 && newY <= height && newY >= 0)
146 {
147 outData[newY * width + newX].srcLocation = orgData[idx].srcLocation;
148 outData[newY * width + newX].dstLocation.x = newX;
149 outData[newY * width + newX].dstLocation.y = newY;
150 }
151 }
152 }
153}
Here is the caller graph for this function:

◆ sliceTriangle()

int sliceTriangle ( TransformationInfo * transformPtr,
int width,
int height,
int n,
double scaleDown )

Slices a suitable triangle from image.

Parameters
[out]transformPtrSliced triangle coordinates
[in]widthWidth of input image
[in]heightHeight of input image
[in]nNumber of images for effect
[in]scaleDownScale down ratio to shrink image
Returns
int 0 on success, -1 otherwise

Definition at line 155 of file kaleidoscope.c.

156{
157 int idx, jdx;
158
159 // Variables
160 const double topAngle = 360.0 / n;
161 const double tanVal = tan(topAngle / 2.0 * M_PI / 180.0); // tan(topAngle / 2) in radians
162 const int triangleHeight = (int)fmin(round(width / (2.0 * tanVal)), height - 1);
163 const int heightStart = (height - triangleHeight) / 2;
164 const int heightEnd = (height + triangleHeight) / 2;
165 const int scaleDownOffset = (int)(height * scaleDown / 2);
166
167 // Ensure limits within image
168 assert(heightStart >= 0);
169 assert(heightStart <= height);
170 assert(heightEnd >= 0);
171 assert(heightEnd <= height);
172
173 for (idx = heightStart; idx < heightEnd; ++idx)
174 {
175 const int currentBaseLength = (int)((idx - heightStart) * tanVal);
176
177 const int widthStart = (width / 2 - currentBaseLength);
178 const int widthEnd = (width / 2 + currentBaseLength);
179
180 // Ensure limits within image
181 if (widthStart < 0 || widthStart > width || widthEnd < 0 || widthEnd > width)
182 continue;
183
184 TransformationInfo *ptr = &transformPtr[idx * width];
185 for (jdx = widthStart; jdx <= widthEnd; ++jdx)
186 {
187 ptr[jdx].srcLocation.x = jdx;
188 ptr[jdx].srcLocation.y = idx;
189
190 // Calculate coordinates respect to center to prepare rotating
191 ptr[jdx].dstLocation.x = (int)((jdx - width / 2) * scaleDown);
192 ptr[jdx].dstLocation.y = (int)((idx - heightStart - height / 2) * scaleDown + scaleDownOffset);
193 }
194 }
195
196 return EXIT_SUCCESS;
197}
Here is the caller graph for this function: