4f88fca3f1ca46972ed32d49ecafa1884f3eb0c0
Christian Heimke Blimp v.0.2 (2004-11-10)

Christian Heimke authored 13 years ago

1) /* BlinkenLightsInteractiveMovieProgram
Christian Heimke Blimp v.0.6 (2005-03-10)

Christian Heimke authored 13 years ago

2)  * version 0.6 date 2005-03-10
3)  * Copyright (C) 2004-2005: Stefan Schuermans <1stein@schuermans.info>
Christian Heimke Blimp v.0.2 (2004-11-10)

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) import java.awt.*;
10) 
11) public class BlinkenFrame
12) {
13) 
14)   private int height;
15)   private int width;
16)   private int channels;
17)   private int maxval;
18)   private int duration;
19)   private byte[][][] data;
20) 
21)   BlinkenFrame( int height, int width, int channels, int maxval, int duration )
22)   {
23)     if( height < 1 ) height = 1;
24)     if( height > 1024 ) height = 1024;
25)     if( width < 1 ) width = 1;
26)     if( width > 1024 ) width = 1024;
27)     if( channels < 1 ) channels = 1;
28)     if( channels > 16 ) channels = 16;
29)     if( maxval < 1 ) maxval = 1;
30)     if( maxval > 255 ) maxval = 255;
31)     if( duration < 1 ) duration = 1;
32)     if( duration > 65535 ) duration = 65535;
33) 
34)     this.height = height;
35)     this.width = width;
36)     this.channels = channels;
37)     this.maxval = maxval;
38)     this.duration = duration;
39)     data = new byte[height][width][channels];
40)   }
41) 
42)   BlinkenFrame( BlinkenFrame frame )
43)   {
44)     int y, x, c;
45)     height = frame.height;
46)     width = frame.width;
47)     channels = frame.channels;
48)     maxval = frame.maxval;
49)     duration = frame.duration;
50)     data = new byte[height][width][channels];
51)     for( y = 0; y < height; y++ )
52)       for( x = 0; x < width; x++ )
53)         for( c = 0; c < channels; c++ )
54)           data[y][x][c] = frame.data[y][x][c];
55)   }
56) 
57)   public void clear( )
58)   {
59)     int x, y, c;
60)     for( y = 0; y < height; y++ )
61)       for( x = 0; x < width; x++ )
62)         for( c = 0; c < channels; c++ )
63)           data[y][x][c] = 0;
64)   }
65) 
66)   public int getHeight( )
67)   {
68)     return height;
69)   }
70) 
71)   public int getWidth( )
72)   {
73)     return width;
74)   }
75) 
76)   public int getChannels( )
77)   {
78)     return channels;
79)   }
80) 
81)   public int getMaxval( )
82)   {
83)     return maxval;
84)   }
85) 
86)   public int getDuration( )
87)   {
88)     return duration;
89)   }
90) 
91)   public void setDuration( int duration )
92)   {
93)     if( duration < 1 ) duration = 1;
94)     if( duration > 65535 ) duration = 65535;
95)     this.duration = duration;
96)   }
97) 
98)   public byte getPixel( int y, int x, int c )
99)   {
100)     if( y < 0 || y >= height ||
101)         x < 0 || x >= width ||
102) 	c < 0 || c >= channels )
103)       return 0;
104)     return data[y][x][c];
105)   }
106) 
107)   public void setPixel( int y, int x, int c, byte val )
108)   {
109)     if( y < 0 || y >= height ||
110)         x < 0 || x >= width ||
111) 	c < 0 || c >= channels )
112)       return;
113)     if( val > maxval )
114)       val = (byte)maxval;
115)     data[y][x][c] = val;
116)   }
117) 
118)   public Color getColor( int y, int x )
119)   {
120)     if( y < 0 || y >= height ||
121)         x < 0 || x >= width ||
122)         channels < 1 )
123)       return new Color( 0, 0, 0 );
124)     if( channels == 1 )
125)       return new Color( (((int)data[y][x][0] & 0xFF) * 255 + maxval / 2) / maxval,
126)                         (((int)data[y][x][0] & 0xFF) * 255 + maxval / 2) / maxval,
127)                         (((int)data[y][x][0] & 0xFF) * 255 + maxval / 2) / maxval );
128)     if( channels == 2 )
129)       return new Color( (((int)data[y][x][0] & 0xFF) * 255 + maxval / 2) / maxval,
130)                         (((int)data[y][x][1] & 0xFF) * 255 + maxval / 2) / maxval, 0 );
131)     return new Color( (((int)data[y][x][0] & 0xFF) * 255 + maxval / 2) / maxval,
132)                       (((int)data[y][x][1] & 0xFF) * 255 + maxval / 2) / maxval,
133)                       (((int)data[y][x][2] & 0xFF) * 255 + maxval / 2) / maxval );
134)   }
135) 
136)   public void setColor( int y, int x, Color color )
137)   {
138)     int alpha, alpha_, c;
139)     if( y < 0 || y >= height ||
140)         x < 0 || x >= width )
141)       return;
142)     alpha = color.getAlpha( );
143)     alpha_ = 255 - alpha;
144)     if( channels >= 1 )
145)       data[y][x][0] = (byte)(( ((color.getRed( ) * maxval + 127) / 255) * alpha
146)                              + ((int)data[y][x][0] & 0xFF) * alpha_
147)                              ) / 255);
148)     if( channels >= 2 )
149)       data[y][x][1] = (byte)(( ((color.getGreen( ) * maxval + 127) / 255) * alpha
150)                              + ((int)data[y][x][1] & 0xFF) * alpha_
151)                              ) / 255);
152)     if( channels >= 3 )
153)       data[y][x][2] = (byte)(( ((color.getBlue( ) * maxval + 127) / 255) * alpha
154)                              + ((int)data[y][x][2] & 0xFF) * alpha_
155)                              ) / 255);
156)     for( c = 3; c < channels; c++ )
157)       data[y][x][c] = (byte)(( 0
Christian Heimke Blimp v.0.5 (2004-11-19)

Christian Heimke authored 13 years ago

158)                              + ((int)data[y][x][c] & 0xFF) * alpha_
Christian Heimke Blimp v.0.2 (2004-11-10)

Christian Heimke authored 13 years ago

159)                              ) / 255);
160)   }
161) 
162)   public void resize( int height, int width, int channels, int maxval )
163)   {
164)     byte[][][] data;
165)     int y, x, c;
166)     int emptyY, emptyX, skipY, skipX, rangeY, rangeX, val, div;
167) 
168)     if( height < 1 ) height = 1;
169)     if( height > 1024 ) height = 1024;
170)     if( width < 1 ) width = 1;
171)     if( width > 1024 ) width = 1024;
172)     if( channels < 1 ) channels = 1;
173)     if( channels > 16 ) channels = 16;
174)     if( maxval < 1 ) maxval = 1;
175)     if( maxval > 255 ) maxval = 255;
176) 
177)     if( height == this.height &&
178)         width == this.width &&
179)         channels == this.channels &&
180)         maxval == this.maxval )
181)       return;
182) 
183)     //allocate new data array
184)     data = new byte[height][width][channels];
185)     for( y = 0; y < height; y++ )
186)       for( x = 0; x < width; x++ )
187)         for( c = 0; c < channels; c++ )
188)           data[y][x][c] = 0;
189) 
190)     //get number of pixels to skip / to leave empty in X and Y direction
191)     if( height > this.height )
192)     {
193)       emptyY = (height - this.height) / 2; 
194)       skipY = 0;
195)       rangeY = this.height;
196)     }
197)     else
198)     {
199)       emptyY = 0;
200)       skipY = (this.height - height) / 2;
201)       rangeY = height;
202)     }
203)     if( width > this.width )
204)     {
205)       emptyX = (width - this.width) / 2; 
206)       skipX = 0;
207)       rangeX = this.width;
208)     }
209)     else
210)     {
211)       emptyX = 0;
212)       skipX = (this.width - width) / 2;
213)       rangeX = width;
214)     }
215) 
216)     //resize frame with help of calculated parameters
217)     for( y = 0; y < rangeY; y++ )
218)     {
219)       for( x = 0; x < rangeX; x++ )
220)       {
221)         if( channels >= this.channels ) //add channels: copy last channel into new channels
222) 	{
223)           for( c = 0; c < this.channels; c++ )
224)             data[emptyY + y][emptyX + x][c] = (byte)((((int)this.data[skipY + y][skipX + x][c] & 0xFF) * maxval + this.maxval / 2) / this.maxval);
225) 	  for( ; c < channels; c++ )
226) 	    data[emptyY + y][emptyX + x][c] = data[emptyY + y][emptyX + x][this.channels - 1];
227) 	}
228) 	else //remove channels: merge leftover channels with last kept channel
229) 	{
230)           val = 0;
231)           for( c = 0; c < channels - 1; c++ )
232)             data[emptyY + y][emptyX + x][c] = (byte)((((int)this.data[skipY + y][skipX + x][c] & 0xFF) * maxval + this.maxval / 2) / this.maxval);
233)           for( c = channels - 1; c < this.channels; c++ )
234)             val += (int)this.data[skipY + y][skipX + x][c] & 0xFF;
235)           div = this.maxval * (this.channels - channels + 1);
236)           data[emptyY + y][emptyX + x][channels - 1] = (byte)((val * maxval + div / 2) / div);
237) 	}
238)       }
239)     }
240) 
241)     this.height = height;
242)     this.width = width;
243)     this.channels = channels;
244)     this.maxval = maxval;
245)     this.data = data;
246)   }
247) 
Christian Heimke Blimp v.0.3 (2004-11-12)

Christian Heimke authored 13 years ago

248)   public void scale( int height, int width )
249)   {
250)     byte[][][] data;
251)     double scaleHor, scaleVer, ox, oy, ox1, oy1, val;
252)     int c, nx, ny, x, y, oxi, oyi, ox1i, oy1i;
253) 
254)     if( height < 1 ) height = 1;
255)     if( height > 1024 ) height = 1024;
256)     if( width < 1 ) width = 1;
257)     if( width > 1024 ) width = 1024;
258) 
259)     if( height == this.height &&
260)         width == this.width )
261)       return;
262) 
263)     scaleHor = (double)width / (double)this.width;
264)     scaleVer = (double)height / (double)this.height;
265) 
266)     //allocate new data array
267)     data = new byte[height][width][channels];
268) 
269)     //scale every channel
270)     for( c = 0; c < channels; c++ )
271)     {
272)       for( ny = 0; ny < height; ny++ )
273)       {
274)         for( nx = 0; nx < width; nx++ )
275)         {
276)           oy = (double)ny / scaleVer; //sub-pixel exact range in old picture
277)           ox = (double)nx / scaleHor;
278)           oy1 = (double)(ny + 1) / scaleVer - 0.000001;
279)           ox1 = (double)(nx + 1) / scaleHor - 0.000001;
280)           if( oy < 0 || ox < 0 || oy1 >= this.height || ox1 >= this.width) //out of old picture
281)             data[ny][nx][c] = 0;
282)           else
283)           {
284)             oyi = (int)oy;
285)             oxi = (int)ox;
286)             oy1i = (int)oy1;
287)             ox1i = (int)ox1;
288)             if( oyi == oy1i )
289)             {
290)               if( oxi == ox1i) //one source pixel
291)               {
292)                 val = (double)((int)this.data[oyi][oxi][c] & 0xFF);
293)               }
294)               else //one line of source pixels
295)               {
296)                 val = (double)((int)this.data[oyi][oxi][c] & 0xFF) * (1 - ox + oxi)
297)                     + (double)((int)this.data[oyi][ox1i][c] & 0xFF) * (ox1 - ox1i);
298)                 for( x = oxi + 1; x < ox1i; x++ )
299)                   val += (double)((int)this.data[oyi][x][c] & 0xFF);
300)                 val /= ox1 - ox;
301)               }
302)             }
303)             else //one column of source pixels
304)             {
305)               if( oxi == ox1i )
306)               {
307)                 val = (double)((int)this.data[oyi][oxi][c] & 0xFF) * (1 - oy + oyi)
308)                     + (double)((int)this.data[oy1i][oxi][c] & 0xFF) * (oy1 - oy1i);
309)                 for( y = oyi + 1; y < oy1i; y++ )
310)                   val += (double)((int)this.data[y][oxi][c] & 0xFF);
311)                 val /= oy1 - oy;
312)               }
313)               else //rectangle of source pixels
314)               {
315)                 val = (double)((int)this.data[oyi][oxi][c] & 0xFF) * (1 - oy + oyi) * (1 - ox + oxi)
316)                     + (double)((int)this.data[oyi][ox1i][c] & 0xFF) * (1 - oy + oyi) * (ox1 - ox1i)
317)                     + (double)((int)this.data[oy1i][oxi][c] & 0xFF) * (oy1 - oy1i) * (1 - ox + oxi)
318)                     + (double)((int)this.data[oy1i][ox1i][c] & 0xFF) * (oy1 - oy1i) * (ox1 - ox1i);
319)                 for( y = oyi + 1; y < oy1i; y++ )
320)                 {
321)                   val += (double)((int)this.data[y][oxi][c] & 0xFF) * (1 - ox + oxi)
322)                        + (double)((int)this.data[y][ox1i][c] & 0xFF) * (ox1 - ox1i);
323)                 }
324)                 for( x = oxi + 1; x < ox1i; x++ )
325)                 {
326)                   val += (double)((int)this.data[oyi][x][c] & 0xFF) * (1 - oy + oyi)
327)                        + (double)((int)this.data[oy1i][x][c] & 0xFF) * (oy1 - oy1i);
328)                 }
329)                 for( y = oyi + 1; y < oy1i; y++ )
330)                   for( x = oxi + 1; x < ox1i; x++ )
331)                     val += (double)((int)this.data[y][x][c] & 0xFF);
332)                 val /= (oy1 - oy) * (ox1 - ox);
333)               }
334)             }
335)             data[ny][nx][c] = (byte)(int)(val + 0.5);
336)           }
337)         } //for( nx ...
338)       } //for( ny ...
339)     } //for( c ...
340) 
341)     this.height = height;
342)     this.width = width;
343)     this.data = data;
344)   }
345) 
Christian Heimke Blimp v.0.2 (2004-11-10)

Christian Heimke authored 13 years ago

346)   public String toString( )
347)   {
348)     String str = "";
349)     int h, w, c, val;
350)     for( h = 0; h < height; h++ )
351)     {
352)       for( w = 0; w < width; w++ )
353)       {
354)         val = 0;
355)         for( val = 0, c = 0; c < channels; c++ )
Christian Heimke Blimp v.0.6 (2005-03-10)

Christian Heimke authored 13 years ago

356)           val += ((int)data[h][w][c] & 0xFF);