Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /*************************************************************************** |
---|---|
2 | Copyright (C) 2007-2009 Sebastian Held <sebastian.held@gmx.de> |
3 | ***************************************************************************/ |
4 | |
5 | /*************************************************************************** |
6 | * * |
7 | * This program is free software; you can redistribute it and/or * |
8 | * modify it under the terms of the GNU General Public License as * |
9 | * published by the Free Software Foundation; either version 2 of * |
10 | * the License or (at your option) version 3 or any later version * |
11 | * accepted by the membership of KDE e.V. (or its successor approved * |
12 | * by the membership of KDE e.V.), which shall act as a proxy * |
13 | * defined in Section 14 of version 3 of the license. * |
14 | * * |
15 | * This program is distributed in the hope that it will be useful, * |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
18 | * GNU General Public License for more details. * |
19 | * * |
20 | * You should have received a copy of the GNU General Public License * |
21 | * along with this program. If not, see <http://www.gnu.org/licenses/>. * |
22 | * * |
23 | ***************************************************************************/ |
24 | |
25 | // uses code from v4lgrab.c (c) Linux Kernel 2.6.30 |
26 | |
27 | #include "barcode_v4l.h" |
28 | #include "../tellico_debug.h" |
29 | |
30 | #include <fcntl.h> /* low-level i/o */ |
31 | #include <errno.h> |
32 | #include <sys/ioctl.h> |
33 | |
34 | extern "C"{ |
35 | #include <libv4l1.h> |
36 | } |
37 | |
38 | using barcodeRecognition::barcode_v4l; |
39 | |
40 | #define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \ |
41 | { \ |
42 | switch (format) \ |
43 | { \ |
44 | case VIDEO_PALETTE_GREY: \ |
45 | switch (depth) \ |
46 | { \ |
47 | case 4: \ |
48 | case 6: \ |
49 | case 8: \ |
50 | (r) = (g) = (b) = (*buf++ << 8);\ |
51 | break; \ |
52 | \ |
53 | case 16: \ |
54 | (r) = (g) = (b) = \ |
55 | *((unsigned short *) buf); \ |
56 | buf += 2; \ |
57 | break; \ |
58 | } \ |
59 | break; \ |
60 | \ |
61 | \ |
62 | case VIDEO_PALETTE_RGB565: \ |
63 | { \ |
64 | unsigned short tmp = *(unsigned short *)buf; \ |
65 | (r) = tmp&0xF800; \ |
66 | (g) = (tmp<<5)&0xFC00; \ |
67 | (b) = (tmp<<11)&0xF800; \ |
68 | buf += 2; \ |
69 | } \ |
70 | break; \ |
71 | \ |
72 | case VIDEO_PALETTE_RGB555: \ |
73 | (r) = (buf[0]&0xF8)<<8; \ |
74 | (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \ |
75 | (b) = ((buf[1] << 2 ) & 0xF8)<<8; \ |
76 | buf += 2; \ |
77 | break; \ |
78 | \ |
79 | case VIDEO_PALETTE_RGB24: \ |
80 | (r) = buf[0] << 8; (g) = buf[1] << 8; \ |
81 | (b) = buf[2] << 8; \ |
82 | buf += 3; \ |
83 | break; \ |
84 | \ |
85 | default: \ |
86 | fprintf(stderr, \ |
87 | "Format %d not yet supported\n", \ |
88 | format); \ |
89 | } \ |
90 | } |
91 | |
92 | barcode_v4l::barcode_v4l() |
93 | { |
94 | m_devname = QString::fromAscii("/dev/video0"); |
95 | m_grab_width = 640; |
96 | m_grab_height = 480; |
97 | |
98 | m_fd = -1; |
99 | m_buffer = 0; |
100 | m_image = 0; |
101 | |
102 | grab_init(); |
103 | } |
104 | |
105 | barcode_v4l::~barcode_v4l() |
106 | { |
107 | if (m_fd >= 0) |
108 | v4l1_close(m_fd); |
109 | if (m_buffer) |
110 | delete m_buffer; |
111 | if (m_image) |
112 | delete m_image; |
113 | } |
114 | |
115 | bool barcode_v4l::isOpen() |
116 | { |
117 | return (m_fd >= 0); |
118 | } |
119 | |
120 | QImage barcode_v4l::grab_one2() |
121 | { |
122 | unsigned int bpp = 24, x, y; |
123 | unsigned int r = 0, g = 0, b = 0; |
124 | unsigned int src_depth = 16; |
125 | char *src = m_buffer->data(); |
126 | |
127 | static int counter = 0; // adjustment disabled; set to e.g. 20 or 50 to enable the brightness adjustment |
128 | |
129 | if (!isOpen()) |
130 | return QImage(); |
131 | |
132 | v4l1_read(m_fd, m_buffer->data(), m_win.width * m_win.height * bpp); |
133 | |
134 | if (counter) { |
135 | long newbright; |
136 | int f; |
137 | counter--; |
138 | f = get_brightness_adj((unsigned char *)m_buffer->data(), m_win.width * m_win.height, &newbright); |
139 | if (f) { |
140 | m_pict.brightness += (newbright << 8); |
141 | myDebug() << "v4l: Adjusting brightness: new brightness "<< m_pict.brightness << endl; |
142 | if (v4l1_ioctl(m_fd, VIDIOCSPICT, &m_pict) == -1) { |
143 | myDebug() << "v4l: Cannot set brightness."<< endl; |
144 | counter = 0; // do not try again |
145 | } |
146 | } else |
147 | counter = 0; // do not try again |
148 | } |
149 | |
150 | if (m_pict.palette == VIDEO_PALETTE_RGB24) { |
151 | // optimized case |
152 | QRgb *scanline; |
153 | for (y = 0; y < m_win.height; ++y) { |
154 | scanline = (QRgb*)m_image->scanLine(y); |
155 | for (x = 0; x < m_win.width; ++x) { |
156 | const char src1 = *(src++); |
157 | const char src2 = *(src++); |
158 | const char src3 = *(src++); |
159 | scanline[x] = qRgb(src1,src2,src3); |
160 | } |
161 | } |
162 | } else { |
163 | // generic case |
164 | for (y = 0; y < m_win.height; ++y) { |
165 | for (x = 0; x < m_win.width; ++x) { |
166 | READ_VIDEO_PIXEL(src, m_pict.palette, src_depth, r, g, b); |
167 | m_image->setPixel( x, y, qRgb(r>>8,g>>8,b>>8) ); |
168 | } |
169 | } |
170 | } |
171 | |
172 | return *m_image; |
173 | } |
174 | |
175 | bool barcode_v4l::grab_init() |
176 | { |
177 | m_fd = v4l1_open(m_devname.toAscii().constData(), O_RDONLY); |
178 | if (m_fd < 0) { |
179 | myDebug() << "v4l: open "<< m_devname << ": "<< strerror(errno) << endl; |
180 | return false; |
181 | } |
182 | |
183 | if (v4l1_ioctl(m_fd, VIDIOCGCAP, &m_capability) < 0) { |
184 | myDebug() << "v4l: ioctl VIDIOCGCAP failed; "<< m_devname << " not a video4linux device?"<< endl; |
185 | v4l1_close(m_fd); |
186 | m_fd = -1; |
187 | return false; |
188 | } |
189 | |
190 | if (v4l1_ioctl(m_fd, VIDIOCGWIN, &m_win) < 0) { |
191 | myDebug() << "v4l: ioctl VIDIOCGWIN failed"<< endl; |
192 | v4l1_close(m_fd); |
193 | m_fd = -1; |
194 | return false; |
195 | } |
196 | |
197 | if (v4l1_ioctl(m_fd, VIDIOCGPICT, &m_pict) < 0) { |
198 | myDebug() << "v4l: ioctl VIDIOCGPICT failed"<< endl; |
199 | v4l1_close(m_fd); |
200 | m_fd = -1; |
201 | return false; |
202 | } |
203 | |
204 | if (m_capability.type & VID_TYPE_MONOCHROME) { |
205 | m_pict.depth=8; |
206 | m_pict.palette=VIDEO_PALETTE_GREY; /* 8bit grey */ |
207 | if (v4l1_ioctl(m_fd, VIDIOCSPICT, &m_pict) < 0) { |
208 | myDebug() << "v4l: Unable to find a supported capture format."<< endl; |
209 | v4l1_close(m_fd); |
210 | m_fd = -1; |
211 | return false; |
212 | } |
213 | } else { |
214 | m_pict.depth=24; |
215 | m_pict.palette=VIDEO_PALETTE_RGB24; |
216 | if (v4l1_ioctl(m_fd, VIDIOCSPICT, &m_pict) < 0) { |
217 | myDebug() << "v4l: Unable to find a supported capture format."<< endl; |
218 | v4l1_close(m_fd); |
219 | m_fd = -1; |
220 | return false; |
221 | } |
222 | } |
223 | |
224 | // check the values |
225 | video_picture temp; |
226 | v4l1_ioctl(m_fd, VIDIOCGPICT, &temp); |
227 | if ((temp.depth != m_pict.depth) || (temp.palette != m_pict.palette)) { |
228 | myDebug() << "v4l: Unable to find a supported capture format."<< endl; |
229 | v4l1_close(m_fd); |
230 | m_fd = -1; |
231 | return false; |
232 | } |
233 | |
234 | int bpp = 24; |
235 | m_buffer = new QByteArray; |
236 | m_buffer->reserve( m_win.width * m_win.height * bpp ); // FIXME! I think the example from the Linux kernel wastes memory here |
237 | m_image = new QImage( m_win.width, m_win.height, QImage::Format_RGB32 ); |
238 | |
239 | return true; |
240 | } |
241 | |
242 | int barcode_v4l::get_brightness_adj(unsigned char *image, long size, long *brightness) { |
243 | long i, tot = 0; |
244 | for (i=0;i<size*3;i++) { |
245 | tot += image[i]; |
246 | } |
247 | *brightness = (128 - tot/(size*3))/3; |
248 | return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130); |
249 | } |
250 |
Warning: That file was not part of the compilation database. It may have many parsing errors.