kaleidoscope 1.4.0
 
Loading...
Searching...
No Matches
kaleidoscope.c File Reference
#include "kaleidoscope.h"
#include "kaleidoscope-config.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Include dependency graph for kaleidoscope.c:

Go to the source code of this file.

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.
 
int compare (const void *lhsPtr, const void *rhsPtr)
 
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.
 

Function Documentation

◆ compare()

int compare ( const void * lhsPtr,
const void * rhsPtr )

Definition at line 56 of file kaleidoscope.c.

57{
58 const TransformationInfo *lhs = (const TransformationInfo *)lhsPtr;
59 const TransformationInfo *rhs = (const TransformationInfo *)rhsPtr;
60 return lhs->dstOffset - rhs->dstOffset;
61}
Data struct for transformation information.
unsigned long long dstOffset
Offset from destination image.
Here is the caller graph for this function:

◆ 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)
unsigned long long srcOffset
Offset from source 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: