457e4846709bec58a78d082a73b408dbcf900761
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

1) /* BlinkenLib
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

2)  * version 0.3 date 2005-02-16
Christian Heimke BlinkenLib v.0.2 (2005-01-27)

Christian Heimke authored 13 years ago

3)  * Copyright 2004-2005 Stefan Schuermans <1stein@schuermans.info>
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

4)  * Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html
5)  * a blinkenarea.org project
6)  * powered by eventphone.de
7)  */
8) 
9) #include <stdio.h>
10) #include <stdlib.h>
11) #include <string.h>
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

12) #include <stdint.h>
13) #include <netinet/in.h>
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

14) 
15) #include "BlinkenConstants.h"
16) #include "BlinkenFrame.h"
17) #include "Tools.h"
18) 
19) struct sBlinkenFrame
20) {
21)   int height;
22)   int width;
23)   int channels;
24)   int maxval;
25)   int duration;
26)   unsigned char * * * pppData;
27) };
28) 
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

29) //blinken protocol headers
30) typedef struct sBlinkenProtoBlpHdr
31) {
32)   uint32_t magic;
33)   uint32_t frameNo;
34)   uint16_t width;
35)   uint16_t height;
36) } stBlinkenProtoBlpHdr;
37) #define BlinkenProtoBlpMagic 0xDEADBEEF
38) typedef struct sBlinkenProtoEblpHdr
39) {
40)   uint32_t magic;
41)   uint32_t frameNo;
42)   uint16_t width;
43)   uint16_t height;
44) } stBlinkenProtoEblpHdr;
45) #define BlinkenProtoEblpMagic 0xFEEDBEEF
46) typedef struct sBlinkenProtoMcufHdr
47) {
48)   uint32_t magic;
49)   uint16_t height;
50)   uint16_t width;
51)   uint16_t channels;
52)   uint16_t maxval;
53) } stBlinkenProtoMcufHdr;
54) #define BlinkenProtoMcufMagic 0x23542666
55) 
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

56) stBlinkenFrame * BlinkenFrameNew( int height, int width, int channels, int maxval, int duration )
57) {
58)   stBlinkenFrame * pFrame;
59) 
60)   if( height < BlinkenHeightMin ) height = BlinkenHeightMin;
61)   if( height > BlinkenHeightMax ) height = BlinkenHeightMax;
62)   if( width < BlinkenWidthMin ) width = BlinkenWidthMin;
63)   if( width > BlinkenWidthMax ) width = BlinkenWidthMax;
64)   if( channels < BlinkenChannelsMin ) channels = BlinkenChannelsMin;
65)   if( channels > BlinkenChannelsMax ) channels = BlinkenMaxvalMax;
66)   if( maxval < BlinkenMaxvalMin ) maxval = BlinkenMaxvalMin;
67)   if( maxval > BlinkenMaxvalMax ) maxval = BlinkenMaxvalMax;
68)   if( duration < BlinkenDurationMin ) duration = BlinkenDurationMin;
69)   if( duration > BlinkenDurationMax ) duration = BlinkenDurationMax;
70) 
71)   pFrame = (stBlinkenFrame *)malloc( sizeof( stBlinkenFrame ) );
72)   if( pFrame == NULL )
73)     return NULL;
74) 
75)   pFrame->height = height;
76)   pFrame->width = width;
77)   pFrame->channels = channels;
78)   pFrame->maxval = maxval;
79)   pFrame->duration = duration;
80) 
81)   pFrame->pppData = (unsigned char * * *)malloc3D( height, width, channels, sizeof( unsigned char ) );
82)   if( pFrame->pppData == NULL )
83)   {
84)     free( pFrame );
85)     return NULL;
86)   }
87) 
88)   return pFrame;
89) }
90) 
91) stBlinkenFrame * BlinkenFrameClone( stBlinkenFrame * pSrcFrame )
92) {
93)   int y, x, c;
94)   stBlinkenFrame * pFrame;
95) 
96)   if( pSrcFrame == NULL )
97)     return NULL;
98) 
99)   pFrame = BlinkenFrameNew( pSrcFrame->height, pSrcFrame->width,
100)                             pSrcFrame->channels, pSrcFrame->maxval, pSrcFrame->duration );
101)   if( pFrame == NULL )
102)     return NULL;
103) 
104)   for( y = 0; y < pFrame->height; y++ )
105)     for( x = 0; x < pFrame->width; x++ )
106)       for( c = 0; c < pFrame->channels; c++ )
107)         pFrame->pppData[y][x][c] = pSrcFrame->pppData[y][x][c];
108) 
109)   return pFrame;
110) }
111) 
112) void BlinkenFrameFree( stBlinkenFrame * pFrame )
113) {
114)   if( pFrame == NULL )
115)     return;
116) 
117)   free( pFrame->pppData );
118)   free( pFrame );
119) }
120) 
121) void BlinkenFrameClear( stBlinkenFrame * pFrame )
122) {
123)   int y, x, c;
124) 
125)   if( pFrame == NULL )
126)     return;
127) 
128)   for( y = 0; y < pFrame->height; y++ )
129)     for( x = 0; x < pFrame->width; x++ )
130)       for( c = 0; c < pFrame->channels; c++ )
131)         pFrame->pppData[y][x][c] = 0;
132) }
133) 
134) int BlinkenFrameGetHeight( stBlinkenFrame * pFrame )
135) {
136)   if( pFrame == NULL )
137)     return 0;
138) 
139)   return pFrame->height;
140) }
141) 
142) int BlinkenFrameGetWidth( stBlinkenFrame * pFrame )
143) {
144)   if( pFrame == NULL )
145)     return 0;
146) 
147)   return pFrame->width;
148) }
149) 
150) int BlinkenFrameGetChannels( stBlinkenFrame * pFrame )
151) {
152)   if( pFrame == NULL )
153)     return 0;
154) 
155)   return pFrame->channels;
156) }
157) 
158) int BlinkenFrameGetMaxval( stBlinkenFrame * pFrame )
159) {
160)   if( pFrame == NULL )
161)     return 0;
162) 
163)   return pFrame->maxval;
164) }
165) 
166) int BlinkenFrameGetDuration( stBlinkenFrame * pFrame )
167) {
168)   if( pFrame == NULL )
169)     return 0;
170) 
171)   return pFrame->duration;
172) }
173) 
174) void BlinkenFrameSetDuration( stBlinkenFrame * pFrame, int duration )
175) {
176)   if( pFrame == NULL )
177)     return;
178) 
179)   if( duration < BlinkenDurationMin ) duration = BlinkenDurationMin;
180)   if( duration > BlinkenDurationMax ) duration = BlinkenDurationMax;
181) 
182)   pFrame->duration = duration;
183) }
184) 
185) unsigned char BlinkenFrameGetPixel( stBlinkenFrame * pFrame, int y, int x, int c )
186) {
187)   if( pFrame == NULL ||
188)       y < 0 || y >= pFrame->height ||
189)       x < 0 || x >= pFrame->width ||
190)       c < 0 || c >= pFrame->channels )
191)       return 0;
192) 
193)   return pFrame->pppData[y][x][c];
194) }
195) 
196) void BlinkenFrameSetPixel( stBlinkenFrame * pFrame, int y, int x, int c, unsigned char val )
197) {
198)   if( pFrame == NULL ||
199)       y < 0 || y >= pFrame->height ||
200)       x < 0 || x >= pFrame->width ||
201)       c < 0 || c >= pFrame->channels )
202)       return;
203) 
204)   if( val > pFrame->maxval )
205)     val = pFrame->maxval;
206)   pFrame->pppData[y][x][c] = val;
207) }
208) 
209) unsigned long BlinkenFrameGetColor( stBlinkenFrame * pFrame, int y, int x )
210) {
211)   if( pFrame == NULL ||
212)       y < 0 || y >= pFrame->height ||
213)       x < 0 || x >= pFrame->width )
214)       return 0;
215) 
216)   if( pFrame->channels == 1 )
217)     return (((unsigned long)pFrame->pppData[y][x][0] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 16 |
218)            (((unsigned long)pFrame->pppData[y][x][0] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 8 |
219)            (((unsigned long)pFrame->pppData[y][x][0] * 255 + pFrame->maxval / 2) / pFrame->maxval);
220)   if( pFrame->channels == 2 )
221)     return (((unsigned long)pFrame->pppData[y][x][0] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 16 |
222)            (((unsigned long)pFrame->pppData[y][x][1] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 8;
223)   return (((unsigned long)pFrame->pppData[y][x][0] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 16 |
224)          (((unsigned long)pFrame->pppData[y][x][1] * 255 + pFrame->maxval / 2) / pFrame->maxval) << 8 |
225)          (((unsigned long)pFrame->pppData[y][x][2] * 255 + pFrame->maxval / 2) / pFrame->maxval);
226) }
227) 
228) void BlinkenFrameSetColor( stBlinkenFrame * pFrame, int y, int x, unsigned long color )
229) {
230)   int alpha, alpha_, c;
231) 
232)   if( pFrame == NULL ||
233)       y < 0 || y >= pFrame->height ||
234)       x < 0 || x >= pFrame->width )
235)       return;
236) 
237)   alpha = (color >> 24) & 0xFF;
238)   alpha_ = 255 - alpha;
239)   if( pFrame->channels >= 1 )
240)     pFrame->pppData[y][x][0] = (unsigned char)(( ((((color >> 16) & 0xFF) * pFrame->maxval + 127) / 255) * alpha
241)                                                + (unsigned long)pFrame->pppData[y][x][0] * alpha_
242)                                                ) / 255);
243)   if( pFrame->channels >= 2 )
244)     pFrame->pppData[y][x][1] = (unsigned char)(( ((((color >> 8) & 0xFF) * pFrame->maxval + 127) / 255) * alpha
245)                                                + (unsigned long)pFrame->pppData[y][x][1] * alpha_
246)                                                ) / 255);
247)   if( pFrame->channels >= 3 )
248)     pFrame->pppData[y][x][2] = (unsigned char)(( (((color & 0xFF) * pFrame->maxval + 127) / 255) * alpha
249)                                                + (unsigned long)pFrame->pppData[y][x][2] * alpha_
250)                                                ) / 255);
251)   for( c = 3; c < pFrame->channels; c++ )
252)     pFrame->pppData[y][x][c] = (unsigned char)(( 0
253)                                                + (unsigned long)pFrame->pppData[y][x][c] * alpha_
254)                                                ) / 255);
255) }
256) 
257) void BlinkenFrameResize( stBlinkenFrame * pFrame, int height, int width, int channels, int maxval )
258) {
259)   unsigned char * * * pppData;
260)   int y, x, c;
261)   int emptyY, emptyX, skipY, skipX, rangeY, rangeX;
262)   unsigned long val, div;
263) 
264)   if( pFrame == NULL )
265)     return;
266) 
267)   if( height < BlinkenHeightMin ) height = BlinkenHeightMin;
268)   if( height > BlinkenHeightMax ) height = BlinkenHeightMax;
269)   if( width < BlinkenWidthMin ) width = BlinkenWidthMin;
270)   if( width > BlinkenWidthMax ) width = BlinkenWidthMax;
271)   if( channels < BlinkenChannelsMin ) channels = BlinkenChannelsMin;
272)   if( channels > BlinkenChannelsMax ) channels = BlinkenMaxvalMax;
273)   if( maxval < BlinkenMaxvalMin ) maxval = BlinkenMaxvalMin;
274)   if( maxval > BlinkenMaxvalMax ) maxval = BlinkenMaxvalMax;
275) 
276)   if( height == pFrame->height &&
277)       width == pFrame->width &&
278)       channels == pFrame->channels &&
279)       maxval == pFrame->maxval )
280)     return;
281) 
282)   //allocate new data array
283)   pppData = (unsigned char * * *)malloc3D( height, width, channels, sizeof( unsigned char ) );
284)   if( pppData == NULL )
285)     return;
286)   for( y = 0; y < height; y++ )
287)     for( x = 0; x < width; x++ )
288)       for( c = 0; c < channels; c++ )
289)         pppData[y][x][c] = 0;
290) 
291)   //get number of pixels to skip / to leave empty in X and Y direction
292)   if( height > pFrame->height )
293)   {
294)     emptyY = (height - pFrame->height) / 2; 
295)     skipY = 0;
296)     rangeY = pFrame->height;
297)   }
298)   else
299)   {
300)     emptyY = 0;
301)     skipY = (pFrame->height - height) / 2;
302)     rangeY = height;
303)   }
304)   if( width > pFrame->width )
305)   {
306)     emptyX = (width - pFrame->width) / 2; 
307)     skipX = 0;
308)     rangeX = pFrame->width;
309)   }
310)   else
311)   {
312)     emptyX = 0;
313)     skipX = (pFrame->width - width) / 2;
314)     rangeX = width;
315)   }
316) 
317)   //resize frame with help of calculated parameters
318)   for( y = 0; y < rangeY; y++ )
319)   {
320)     for( x = 0; x < rangeX; x++ )
321)     {
322)       if( channels >= pFrame->channels ) //add channels: copy last channel into new channels
323)       {
324)         for( c = 0; c < pFrame->channels; c++ )
325)           pppData[emptyY + y][emptyX + x][c] = (unsigned char)(((unsigned long)pFrame->pppData[skipY + y][skipX + x][c] * maxval + pFrame->maxval / 2) / pFrame->maxval);
326)         for( ; c < channels; c++ )
327)           pppData[emptyY + y][emptyX + x][c] = pppData[emptyY + y][emptyX + x][pFrame->channels - 1];
328)       }
329)       else //remove channels: merge leftover channels with last kept channel
330)       {
331)         val = 0;
332)         for( c = 0; c < channels - 1; c++ )
333)           pppData[emptyY + y][emptyX + x][c] = (unsigned char)(((unsigned long)pFrame->pppData[skipY + y][skipX + x][c] * maxval + pFrame->maxval / 2) / pFrame->maxval);
334)         for( c = channels - 1; c < pFrame->channels; c++ )
335)           val += (unsigned long)pFrame->pppData[skipY + y][skipX + x][c];
336)         div = pFrame->maxval * (pFrame->channels - channels + 1);
337)         pppData[emptyY + y][emptyX + x][channels - 1] = (unsigned char)((val * maxval + div / 2) / div);
338)       }
339)     }
340)   }
341) 
342)   pFrame->height = height;
343)   pFrame->width = width;
344)   pFrame->channels = channels;
345)   pFrame->maxval = maxval;
346)   free( pFrame->pppData );
347)   pFrame->pppData = pppData;
348) }
349) 
350) void BlinkenFrameScale( stBlinkenFrame * pFrame, int height, int width )
351) {
352)   unsigned char * * * pppData;
353)   double scaleHor, scaleVer, ox, oy, ox1, oy1, val;
354)   int c, nx, ny, x, y, oxi, oyi, ox1i, oy1i;
355) 
356)   if( pFrame == NULL )
357)     return;
358) 
359)   if( height < BlinkenHeightMin ) height = BlinkenHeightMin;
360)   if( height > BlinkenHeightMax ) height = BlinkenHeightMax;
361)   if( width < BlinkenWidthMin ) width = BlinkenWidthMin;
362)   if( width > BlinkenWidthMax ) width = BlinkenWidthMax;
363) 
364)   if( height == pFrame->height &&
365)       width == pFrame->width )
366)     return;
367) 
368)   scaleHor = (double)width / (double)pFrame->width;
369)   scaleVer = (double)height / (double)pFrame->height;
370) 
371)   //allocate new data array
372)   pppData = (unsigned char * * *)malloc3D( height, width, pFrame->channels, sizeof( unsigned char ) );
373)   if( pppData == NULL )
374)     return;
375) 
376)   //scale every channel
377)   for( c = 0; c < pFrame->channels; c++ )
378)   {
379)     for( ny = 0; ny < height; ny++ )
380)     {
381)       for( nx = 0; nx < width; nx++ )
382)       {
383)         oy = (double)ny / scaleVer; //sub-pixel exact range in old picture
384)         ox = (double)nx / scaleHor;
385)         oy1 = (double)(ny + 1) / scaleVer - 0.000001;
386)         ox1 = (double)(nx + 1) / scaleHor - 0.000001;
387)         if( oy < 0 || ox < 0 || oy1 >= pFrame->height || ox1 >= pFrame->width) //out of old picture
388)           pppData[ny][nx][c] = 0;
389)         else
390)         {
391)           oyi = (int)oy;
392)           oxi = (int)ox;
393)           oy1i = (int)oy1;
394)           ox1i = (int)ox1;
395)           if( oyi == oy1i )
396)           {
397)             if( oxi == ox1i) //one source pixel
398)             {
399)               val = (double)pFrame->pppData[oyi][oxi][c];
400)             }
401)             else //one line of source pixels
402)             {
403)               val = (double)pFrame->pppData[oyi][oxi][c] * (1 - ox + oxi)
404)                   + (double)pFrame->pppData[oyi][ox1i][c] * (ox1 - ox1i);
405)               for( x = oxi + 1; x < ox1i; x++ )
406)                 val += (double)pFrame->pppData[oyi][x][c];
407)               val /= ox1 - ox;
408)             }
409)           }
410)           else //one column of source pixels
411)           {
412)             if( oxi == ox1i )
413)             {
414)               val = (double)pFrame->pppData[oyi][oxi][c] * (1 - oy + oyi)
415)                   + (double)pFrame->pppData[oy1i][oxi][c] * (oy1 - oy1i);
416)               for( y = oyi + 1; y < oy1i; y++ )
417)                 val += (double)pFrame->pppData[y][oxi][c];
418)               val /= oy1 - oy;
419)             }
420)             else //rectangle of source pixels
421)             {
422)               val = (double)pFrame->pppData[oyi][oxi][c] * (1 - oy + oyi) * (1 - ox + oxi)
423)                   + (double)pFrame->pppData[oyi][ox1i][c] * (1 - oy + oyi) * (ox1 - ox1i)
424)                   + (double)pFrame->pppData[oy1i][oxi][c] * (oy1 - oy1i) * (1 - ox + oxi)
425)                   + (double)pFrame->pppData[oy1i][ox1i][c] * (oy1 - oy1i) * (ox1 - ox1i);
426)               for( y = oyi + 1; y < oy1i; y++ )
427)               {
428)                 val += (double)pFrame->pppData[y][oxi][c] * (1 - ox + oxi)
429)                      + (double)pFrame->pppData[y][ox1i][c] * (ox1 - ox1i);
430)               }
431)               for( x = oxi + 1; x < ox1i; x++ )
432)               {
433)                 val += (double)pFrame->pppData[oyi][x][c] * (1 - oy + oyi)
434)                      + (double)pFrame->pppData[oy1i][x][c] * (oy1 - oy1i);
435)               }
436)               for( y = oyi + 1; y < oy1i; y++ )
437)                 for( x = oxi + 1; x < ox1i; x++ )
438)                   val += (double)pFrame->pppData[y][x][c];
439)               val /= (oy1 - oy) * (ox1 - ox);
440)             }
441)           }
442)           pppData[ny][nx][c] = (unsigned char)(val + 0.5);
443)         }
444)       } //for( nx ...
445)     } //for( ny ...
446)   } //for( c ...
447) 
448)   pFrame->height = height;
449)   pFrame->width = width;
450)   free( pFrame->pppData );
451)   pFrame->pppData = pppData;
452) }
453) 
454) char * BlinkenFrameToString( stBlinkenFrame * pFrame )
455) {
456)   int size, y, x, c;
457)   char * str, * ptr;
458)   unsigned long val;
459) 
460)   if( pFrame == NULL )
461)     return NULL;
462) 
463)   size = pFrame->height * (pFrame->width + 1) + 32;
464) 
465)   str = (char *)malloc( size );
466)   if( str == NULL )
467)     return NULL;
468) 
469)   ptr = str;
470)   
471)   for( y = 0; y < pFrame->height; y++ )
472)   {
473)     for( x = 0; x < pFrame->width; x++ )
474)     {
475)       val = 0;
476)       for( val = 0, c = 0; c < pFrame->channels; c++ )
477)         val += pFrame->pppData[y][x][c];
478)       val = val * 7 / pFrame->maxval / pFrame->channels;
479)       *ptr = " -+*%#&@"[val];
480)       ptr++;
481)     }
482)     *ptr = '\n';
483)     ptr++;
484)   }
485) 
486)   sprintf( ptr, "%u ms\n", pFrame->duration );
487) 
488)   return str;
489) }
490)