Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
157 kaklik 1
/*
2
    AVRcamVIEW: A PC application to test out the functionallity of the
3
     AVRcam real-time image processing engine.
4
    Copyright (C) 2004    Brent A. Taylor
5
 
6
    This program is free software; you can redistribute it and/or
7
    modify it under the terms of the GNU General Public
8
    License as published by the Free Software Foundation; either
9
    version 2 of the License, or (at your option) any later version.
10
 
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
    General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public
17
    License along with this program; if not, write to the Free Software
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
20
   For more information on the AVRcamVIEW, please contact:
21
 
22
   taylorba@comcast.net
23
 
24
   or go to www.jrobot.net for more details regarding the system.
25
*/
26
 
27
package avr.swing;
28
 
29
import java.awt.*;
30
import java.awt.image.*;
31
import java.io.*;
32
import java.nio.*;
33
import java.nio.channels.*;
34
import javax.swing.*;
35
 
36
import avr.lang.*;
37
 
38
public class JCapturePanel extends JPanel {
39
 
40
   // constant variables for the interpolate state machine
41
   private static final int RED        = 0x01;
42
   private static final int BLUE       = 0x02;
43
   private static final int GREEN_EVEN = 0x04;
44
   private static final int GREEN_ODD  = 0x08;
45
 
46
   private BufferedImage bayerImage;
47
   private BufferedImage image;
48
 
49
   public JCapturePanel() {
50
      super(null);
51
 
52
      bayerImage = new BufferedImage(AVRSystem.IMAGE_WIDTH, AVRSystem.IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
53
      image = new BufferedImage(AVRSystem.IMAGE_WIDTH, AVRSystem.IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
54
 
55
   }
56
 
57
   public void paintComponent(Graphics g) {
58
      super.paintComponent(g);
59
      if(bayerImage != null) {
60
 
61
         Dimension size = getSize();
62
         Insets insets = getInsets();
63
 
64
         Image offscreenImage = this.createImage(size.width, size.height);
65
 
66
         Graphics2D g2d = (Graphics2D)offscreenImage.getGraphics();
67
 
68
         // scale the images so they fit side by side for either the full
69
         // width or full height of the window
70
         double xScale = size.width / (double)(insets.left + 5 + AVRSystem.IMAGE_WIDTH + 10 + AVRSystem.IMAGE_WIDTH + 5 + insets.right);
71
         double yScale = size.height / (double)(insets.top + 5 + AVRSystem.IMAGE_HEIGHT + 5 + insets.bottom);
72
         double scale = Math.min(xScale, yScale);
73
 
74
         g2d.scale(scale, scale);
75
 
76
         g2d.drawImage(bayerImage, insets.left + 5, insets.top + 5, null);
77
         g2d.drawImage(image, insets.left + 5 + AVRSystem.IMAGE_WIDTH + 10, insets.top + 5, null);
78
 
79
         g.drawImage(offscreenImage, 0, 0, null);
80
 
81
      }
82
   }
83
 
84
   public Dimension getMinimumSize() {
85
      return getPreferredSize();
86
   }
87
 
88
   public Dimension getPreferredSize() {
89
      Insets insets = getInsets();
90
      return new Dimension(insets.left + 5 + AVRSystem.IMAGE_WIDTH + 10 + AVRSystem.IMAGE_WIDTH + 5 + insets.right,
91
                           insets.top + 5 + AVRSystem.IMAGE_HEIGHT + 5 + insets.bottom);
92
   }
93
 
94
   public Dimension getMaximumSize() {
95
      return getPreferredSize();
96
   }
97
 
98
   public int getRGB(int x, int y) {
99
      return image.getRGB(x, y);
100
   }
101
 
102
   public void openBayer(File file) throws IOException {
103
 
104
      FileInputStream inStream = new FileInputStream(file);
105
      FileChannel inChannel = inStream.getChannel();
106
 
107
      ByteBuffer[] buffers = new ByteBuffer[bayerImage.getWidth()];
108
 
109
      for(int x = 0; x < buffers.length; x++) {
110
         buffers[x] = ByteBuffer.allocate(bayerImage.getHeight() * 4);
111
      }
112
 
113
      inChannel.read(buffers);
114
 
115
      inStream.close();
116
      inChannel.close();
117
 
118
      int[] pixels = new int[bayerImage.getHeight()];
119
 
120
      for(int x = 0; x < bayerImage.getWidth(); x++) {
121
         buffers[x].flip();
122
         buffers[x].asIntBuffer().get(pixels);
123
         bayerImage.setRGB(x, 0, 1, pixels.length, pixels, 0, 1);
124
      }
125
 
126
      interpolate();
127
 
128
   }
129
 
130
   public void saveBayer(File file) throws IOException {
131
 
132
      ByteBuffer[] buffers = new ByteBuffer[bayerImage.getWidth()];
133
 
134
      for(int x = 0; x < buffers.length; x++) {
135
         buffers[x] = ByteBuffer.allocate(bayerImage.getHeight() * 4);
136
         for(int y = 0; y < bayerImage.getHeight(); y++) {
137
            buffers[x].putInt(bayerImage.getRGB(x, y));
138
         }
139
         buffers[x].flip();
140
      }
141
 
142
      FileOutputStream outStream = new FileOutputStream(file);
143
      FileChannel outChannel = outStream.getChannel();
144
 
145
      outChannel.write(buffers);
146
 
147
      outStream.close();
148
      outChannel.close();
149
 
150
   }
151
 
152
   public void setRow(int row, ByteBuffer data, boolean finished) {
153
 
154
      int[] pixels = new int[AVRSystem.IMAGE_WIDTH * 2];
155
 
156
      int x = 0;
157
 
158
      while(data.hasRemaining()) {
159
 
160
         byte pixel = data.get();
161
 
162
         if((x & 1) == 0) {
163
 
164
            // green
165
            pixels[x] = (pixel & 0xF0) << 8;
166
 
167
            // blue
168
            pixels[AVRSystem.IMAGE_WIDTH + x] = (pixel & 0x0F) << 4;
169
 
170
         } else {
171
 
172
            // green
173
            pixels[AVRSystem.IMAGE_WIDTH + x] = ((pixel & 0x0F) << 4) << 8;
174
 
175
            // red
176
            pixels[x] = (pixel & 0xF0) << 16;
177
 
178
         }
179
 
180
         x++;
181
 
182
      }
183
 
184
      bayerImage.setRGB(0, row * 2, AVRSystem.IMAGE_WIDTH, 2, pixels, 0, AVRSystem.IMAGE_WIDTH);
185
 
186
      if(finished) {
187
         interpolate();
188
      }
189
 
190
      repaint();
191
 
192
   }
193
 
194
   /* ********************************************************
195
    * The bayerImage is in the bayer format shown below.
196
    *
197
    *      |   |   |   |   |   |   |   |   |   | . | 1 | 1 |
198
    *      |   |   |   |   |   |   |   |   |   | . | 7 | 7 |
199
    *      | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | . | 4 | 5 |
200
    * -----+---+---+---+---+---+---+---+---+---+ . +---+---+
201
    *    0 | G | R | G | R | G | R | G | R | G | . | G | R |
202
    * -----+---+---+---+---+---+---+---+---+---+ . +---+---+
203
    *    1 | B | G | B | G | B | G | B | G | B | . | B | G |
204
    * -----+---+---+---+---+---+---+---+---+---+ . +---+---+
205
    *    2 | G | R | G | R | G | R | G | R | G | . | G | R |
206
    * -----+---+---+---+---+---+---+---+---+---+ . +---+---+
207
    *    3 | B | G | B | G | B | G | B | G | B | . | B | G |
208
    * -----+---+---+---+---+---+---+---+---+---+ . +---+---+
209
    *    4 | G | R | G | R | G | R | G | R | G | . | G | R |
210
    * -----+---+---+---+---+---+---+---+---+---+ . +---+---+
211
    *    5 | B | G | B | G | B | G | B | G | B | . | B | G |
212
    * -----+---+---+---+---+---+---+---+---+---+ . +---+---+
213
    *    .   .   .   .   .   .   .   .   .   .   .   .   .
214
    * -----+---+---+---+---+---+---+---+---+---+ . +---+---+
215
    *  142 | G | R | G | R | G | R | G | R | G | . | G | R |
216
    * -----+---+---+---+---+---+---+---+---+---+ . +---+---+
217
    *  143 | B | G | B | G | B | G | B | G | B | . | B | G |
218
    * -----+---+---+---+---+---+---+---+---+---+ . +---+---+
219
    *
220
    * The corners are calculated, then the edges, then the center.
221
    *
222
    */
223
 
224
   private void interpolate() {
225
 
226
      int red = 0;
227
      int green = 0;
228
      int blue = 0;
229
 
230
      int currColor = GREEN_ODD;
231
      int nextColor = RED;
232
 
233
      int width = AVRSystem.IMAGE_WIDTH;
234
      int height = AVRSystem.IMAGE_HEIGHT;
235
 
236
      // *** do the corners of the image ***
237
      // upper left corner
238
      red   = bayerImage.getRGB(1, 0);
239
      green = bayerImage.getRGB(0, 0);
240
      blue  = bayerImage.getRGB(0, 1);
241
      image.setRGB(0, 0, red | green | blue);
242
 
243
      // upper right corner
244
      red   = bayerImage.getRGB(width - 1, 0);
245
      green = (bayerImage.getRGB(width - 2, 0) + bayerImage.getRGB(width - 1, 1)) / 2;
246
      blue  = bayerImage.getRGB(width - 2, 1);
247
      image.setRGB(width - 1, 0, red | green | blue);
248
 
249
      // lower left corner
250
      red   = bayerImage.getRGB(1, height - 2);
251
      green = (bayerImage.getRGB(0, height - 2) + bayerImage.getRGB(1, height - 1)) / 2;
252
      blue  = bayerImage.getRGB(0, height - 1);
253
      image.setRGB(0, height - 1, red | green | blue);
254
 
255
      // lower right corner
256
      red   = bayerImage.getRGB(width - 1, height - 2);
257
      green = bayerImage.getRGB(width - 1, height - 1);
258
      blue  = bayerImage.getRGB(width - 2, height - 1);
259
      image.setRGB(width - 1, height - 1, red | green | blue);
260
 
261
      // *** do the north edge
262
      currColor = RED;
263
      for(int x = 1, y = 0; x < width - 1; x++) {
264
         switch(currColor) {
265
            case RED:
266
               red   = bayerImage.getRGB(x, y);
267
               green = (bayerImage.getRGB(x + 1, y) + bayerImage.getRGB(x, y + 1) + bayerImage.getRGB(x - 1, y)) / 3;
268
               blue  = (bayerImage.getRGB(x + 1, y + 1) + bayerImage.getRGB(x - 1, y + 1)) / 2;
269
               nextColor = GREEN_EVEN;
270
               break;
271
            case GREEN_EVEN:
272
               red   = (bayerImage.getRGB(x - 1, y) + bayerImage.getRGB(x + 1, y)) / 2;
273
               green = bayerImage.getRGB(x, y);
274
               blue  = bayerImage.getRGB(x, y + 1);
275
               nextColor = RED;
276
               break;
277
            default:
278
               AVRSystem.LOG.warning("Invalid color for row start: " + currColor);
279
         }
280
         currColor = nextColor;
281
         image.setRGB(x, y, red | green | blue);
282
      }
283
 
284
      // *** do the west edge
285
      currColor = BLUE;
286
      for(int y = 1, x = 0; y < height - 1; y++) {
287
         switch(currColor) {
288
            case BLUE:
289
               red   = (bayerImage.getRGB(x + 1, y + 1) + bayerImage.getRGB(x + 1, y - 1)) / 2;
290
               green = (bayerImage.getRGB(x, y - 1) + bayerImage.getRGB(x + 1, y) + bayerImage.getRGB(x, y + 1)) / 3;
291
               blue  = bayerImage.getRGB(x, y);
292
               nextColor = GREEN_EVEN;
293
               break;
294
            case GREEN_EVEN:
295
               red   = bayerImage.getRGB(x + 1, y);
296
               green = bayerImage.getRGB(x, y);
297
               blue  = (bayerImage.getRGB(x, y - 1) + bayerImage.getRGB(x, y + 1)) / 2;
298
               nextColor = BLUE;
299
               break;
300
         }
301
         currColor = nextColor;
302
         image.setRGB(x, y, red | green | blue);
303
      }
304
 
305
      // *** do the east edge
306
      currColor = GREEN_ODD;
307
      for(int y = 1, x = width - 1; y < height - 1; y++) {
308
         switch(currColor) {
309
            case RED:
310
               blue  = (bayerImage.getRGB(x - 1, y + 1) + bayerImage.getRGB(x - 1, y - 1)) / 2;
311
               green = (bayerImage.getRGB(x, y - 1) + bayerImage.getRGB(x - 1, y) + bayerImage.getRGB(x, y + 1)) / 3;
312
               red   = bayerImage.getRGB(x, y);
313
               nextColor = GREEN_EVEN;
314
               break;
315
            case GREEN_ODD:
316
               blue  = bayerImage.getRGB(x - 1, y);
317
               green = bayerImage.getRGB(x, y);
318
               red   = (bayerImage.getRGB(x, y - 1) + bayerImage.getRGB(x, y + 1)) / 2;
319
               nextColor = BLUE;
320
               break;
321
         }
322
         currColor = nextColor;
323
         image.setRGB(x, y, red | green | blue);
324
      }
325
 
326
      // *** do the south edge
327
      currColor = GREEN_ODD;
328
      for(int x = 1, y = height - 1; x < width - 1; x++) {
329
         switch(currColor) {
330
            case GREEN_ODD:
331
               red   = bayerImage.getRGB(x, y - 1);
332
               green = bayerImage.getRGB(x, y);
333
               blue  = (bayerImage.getRGB(x - 1, y) + bayerImage.getRGB(x + 1, y)) / 2;
334
               nextColor = BLUE;
335
               break;
336
            case BLUE:
337
               red   = (bayerImage.getRGB(x - 1, y - 1) + bayerImage.getRGB(x + 1, y - 1)) / 2;
338
               green = (bayerImage.getRGB(x, y - 1) + bayerImage.getRGB(x + 1, y) + bayerImage.getRGB(x - 1, y)) / 3;
339
               blue  = bayerImage.getRGB(x, y);
340
               nextColor = GREEN_ODD;
341
               break;
342
            default:
343
               AVRSystem.LOG.warning("Invalid color for row start: " + currColor);
344
         }
345
         currColor = nextColor;
346
         image.setRGB(x, y, red | green | blue);
347
      }
348
 
349
      // *** do the center box ***
350
      currColor = RED;
351
      for(int y = 1; y < height - 1; y++) {
352
         // change the starting color for the row
353
         switch(currColor) {
354
            case RED:
355
               currColor = GREEN_ODD;
356
               break;
357
            case GREEN_ODD:
358
               currColor = RED;
359
               break;
360
            default:
361
               AVRSystem.LOG.warning("Invalid color for row start: " + currColor);
362
 
363
         }
364
         for(int x = 1; x < width - 1; x++) {
365
 
366
            switch(currColor) {
367
               case RED:
368
                  red   = bayerImage.getRGB(x, y);
369
 
370
                  green = (bayerImage.getRGB(x, y - 1) + bayerImage.getRGB(x + 1, y) +
371
                           bayerImage.getRGB(x, y + 1) + bayerImage.getRGB(x - 1, y)) / 4;
372
 
373
                  blue  = (bayerImage.getRGB(x - 1, y - 1) + bayerImage.getRGB(x + 1, y + 1) +
374
                           bayerImage.getRGB(x + 1, y - 1) + bayerImage.getRGB(x - 1, y + 1)) / 4;
375
                  nextColor = GREEN_EVEN;
376
                  break;
377
               case GREEN_EVEN:
378
                  red   = (bayerImage.getRGB(x - 1, y) + bayerImage.getRGB(x + 1, y)) / 2;
379
                  green = bayerImage.getRGB(x, y);
380
                  blue  = (bayerImage.getRGB(x, y - 1) + bayerImage.getRGB(x, y + 1)) / 2;
381
                  nextColor = RED;
382
                  break;
383
               case GREEN_ODD:
384
                  red   = (bayerImage.getRGB(x, y - 1) + bayerImage.getRGB(x, y + 1)) / 2;
385
                  green = bayerImage.getRGB(x, y);
386
                  blue  = (bayerImage.getRGB(x - 1, y) + bayerImage.getRGB(x + 1, y)) / 2;
387
                  nextColor = BLUE;
388
                  break;
389
               case BLUE:
390
                  red   = (bayerImage.getRGB(x - 1, y - 1) + bayerImage.getRGB(x + 1, y + 1) +
391
                           bayerImage.getRGB(x + 1, y - 1) + bayerImage.getRGB(x - 1, y + 1)) / 4;
392
 
393
                  green = (bayerImage.getRGB(x, y - 1) + bayerImage.getRGB(x + 1, y) +
394
                           bayerImage.getRGB(x, y + 1) + bayerImage.getRGB(x - 1, y)) / 4;
395
 
396
                  blue  = bayerImage.getRGB(x, y);
397
                  nextColor = GREEN_ODD;
398
                  break;
399
               default:
400
                  AVRSystem.LOG.warning("Invalid color: " + currColor);
401
            }
402
 
403
            currColor = nextColor;
404
 
405
            image.setRGB(x, y, red | green | blue);
406
         }
407
      }
408
 
409
   }
410
 
411
}