File indexing completed on 2024-05-12 16:45:35
0001 /*************************************************************************** 0002 Copyright (C) 2007-2009 Sebastian Held <sebastian.held@gmx.de> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 // uses code from v4lgrab.c (c) Linux Kernel 2.6.30 0026 0027 #include "barcode_v4l.h" 0028 #include "../tellico_debug.h" 0029 0030 #include <fcntl.h> /* low-level i/o */ 0031 #include <errno.h> 0032 #include <sys/ioctl.h> 0033 0034 extern "C" { 0035 #include <libv4l1.h> 0036 } 0037 0038 using barcodeRecognition::barcode_v4l; 0039 0040 #define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \ 0041 { \ 0042 switch (format) \ 0043 { \ 0044 case VIDEO_PALETTE_GREY: \ 0045 switch (depth) \ 0046 { \ 0047 case 4: \ 0048 case 6: \ 0049 case 8: \ 0050 (r) = (g) = (b) = (*buf++ << 8);\ 0051 break; \ 0052 \ 0053 case 16: \ 0054 (r) = (g) = (b) = \ 0055 *((unsigned short *) buf); \ 0056 buf += 2; \ 0057 break; \ 0058 } \ 0059 break; \ 0060 \ 0061 \ 0062 case VIDEO_PALETTE_RGB565: \ 0063 { \ 0064 unsigned short tmp = *(unsigned short *)buf; \ 0065 (r) = tmp&0xF800; \ 0066 (g) = (tmp<<5)&0xFC00; \ 0067 (b) = (tmp<<11)&0xF800; \ 0068 buf += 2; \ 0069 } \ 0070 break; \ 0071 \ 0072 case VIDEO_PALETTE_RGB555: \ 0073 (r) = (buf[0]&0xF8)<<8; \ 0074 (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \ 0075 (b) = ((buf[1] << 2 ) & 0xF8)<<8; \ 0076 buf += 2; \ 0077 break; \ 0078 \ 0079 case VIDEO_PALETTE_RGB24: \ 0080 (r) = buf[0] << 8; (g) = buf[1] << 8; \ 0081 (b) = buf[2] << 8; \ 0082 buf += 3; \ 0083 break; \ 0084 \ 0085 default: \ 0086 fprintf(stderr, \ 0087 "Format %d not yet supported\n", \ 0088 format); \ 0089 } \ 0090 } 0091 0092 barcode_v4l::barcode_v4l() 0093 { 0094 m_devname = QStringLiteral("/dev/video0"); 0095 m_grab_width = 640; 0096 m_grab_height = 480; 0097 0098 m_fd = -1; 0099 m_buffer = nullptr; 0100 m_image = nullptr; 0101 0102 grab_init(); 0103 } 0104 0105 barcode_v4l::~barcode_v4l() 0106 { 0107 if (m_fd >= 0) 0108 v4l1_close(m_fd); 0109 if (m_buffer) 0110 delete m_buffer; 0111 if (m_image) 0112 delete m_image; 0113 } 0114 0115 bool barcode_v4l::isOpen() 0116 { 0117 return (m_fd >= 0); 0118 } 0119 0120 QImage barcode_v4l::grab_one2() 0121 { 0122 unsigned int bpp = 24, x, y; 0123 unsigned int r = 0, g = 0, b = 0; 0124 unsigned int src_depth = 16; 0125 char *src = m_buffer->data(); 0126 0127 static int counter = 0; // adjustment disabled; set to e.g. 20 or 50 to enable the brightness adjustment 0128 0129 if (!isOpen()) 0130 return QImage(); 0131 0132 v4l1_read(m_fd, m_buffer->data(), m_win.width * m_win.height * bpp); 0133 0134 if (counter) { 0135 long newbright; 0136 int f; 0137 counter--; 0138 f = get_brightness_adj((unsigned char *)m_buffer->data(), m_win.width * m_win.height, &newbright); 0139 if (f) { 0140 m_pict.brightness += (newbright << 8); 0141 myDebug() << "v4l: Adjusting brightness: new brightness " << m_pict.brightness; 0142 if (v4l1_ioctl(m_fd, VIDIOCSPICT, &m_pict) == -1) { 0143 myDebug() << "v4l: Cannot set brightness."; 0144 counter = 0; // do not try again 0145 } 0146 } else 0147 counter = 0; // do not try again 0148 } 0149 0150 if (m_pict.palette == VIDEO_PALETTE_RGB24) { 0151 // optimized case 0152 QRgb *scanline; 0153 for (y = 0; y < m_win.height; ++y) { 0154 scanline = reinterpret_cast<QRgb*>(m_image->scanLine(y)); 0155 for (x = 0; x < m_win.width; ++x) { 0156 const char src1 = *(src++); 0157 const char src2 = *(src++); 0158 const char src3 = *(src++); 0159 scanline[x] = qRgb(src1,src2,src3); 0160 } 0161 } 0162 } else { 0163 // generic case 0164 for (y = 0; y < m_win.height; ++y) { 0165 for (x = 0; x < m_win.width; ++x) { 0166 READ_VIDEO_PIXEL(src, m_pict.palette, src_depth, r, g, b); 0167 m_image->setPixel( x, y, qRgb(r>>8,g>>8,b>>8) ); 0168 } 0169 } 0170 } 0171 0172 return *m_image; 0173 } 0174 0175 bool barcode_v4l::grab_init() 0176 { 0177 m_fd = v4l1_open(m_devname.toLatin1().constData(), O_RDONLY); 0178 if (m_fd < 0) { 0179 myDebug() << "v4l: open " << m_devname << ": " << strerror(errno); 0180 return false; 0181 } 0182 0183 if (v4l1_ioctl(m_fd, VIDIOCGCAP, &m_capability) < 0) { 0184 myDebug() << "v4l: ioctl VIDIOCGCAP failed; " << m_devname << " not a video4linux device?"; 0185 v4l1_close(m_fd); 0186 m_fd = -1; 0187 return false; 0188 } 0189 0190 if (v4l1_ioctl(m_fd, VIDIOCGWIN, &m_win) < 0) { 0191 myDebug() << "v4l: ioctl VIDIOCGWIN failed"; 0192 v4l1_close(m_fd); 0193 m_fd = -1; 0194 return false; 0195 } 0196 0197 if (v4l1_ioctl(m_fd, VIDIOCGPICT, &m_pict) < 0) { 0198 myDebug() << "v4l: ioctl VIDIOCGPICT failed"; 0199 v4l1_close(m_fd); 0200 m_fd = -1; 0201 return false; 0202 } 0203 0204 if (m_capability.type & VID_TYPE_MONOCHROME) { 0205 m_pict.depth=8; 0206 m_pict.palette=VIDEO_PALETTE_GREY; /* 8bit grey */ 0207 if (v4l1_ioctl(m_fd, VIDIOCSPICT, &m_pict) < 0) { 0208 myDebug() << "v4l: Unable to find a supported capture format."; 0209 v4l1_close(m_fd); 0210 m_fd = -1; 0211 return false; 0212 } 0213 } else { 0214 m_pict.depth=24; 0215 m_pict.palette=VIDEO_PALETTE_RGB24; 0216 if (v4l1_ioctl(m_fd, VIDIOCSPICT, &m_pict) < 0) { 0217 myDebug() << "v4l: Unable to find a supported capture format."; 0218 v4l1_close(m_fd); 0219 m_fd = -1; 0220 return false; 0221 } 0222 } 0223 0224 // check the values 0225 video_picture temp; 0226 v4l1_ioctl(m_fd, VIDIOCGPICT, &temp); 0227 if ((temp.depth != m_pict.depth) || (temp.palette != m_pict.palette)) { 0228 myDebug() << "v4l: Unable to find a supported capture format."; 0229 v4l1_close(m_fd); 0230 m_fd = -1; 0231 return false; 0232 } 0233 0234 int bpp = 24; 0235 m_buffer = new QByteArray; 0236 m_buffer->reserve( m_win.width * m_win.height * bpp ); // FIXME! I think the example from the Linux kernel wastes memory here 0237 m_image = new QImage( m_win.width, m_win.height, QImage::Format_RGB32 ); 0238 0239 return true; 0240 } 0241 0242 int barcode_v4l::get_brightness_adj(unsigned char *image, long size, long *brightness) { 0243 long i, tot = 0; 0244 for (i=0;i<size*3;i++) { 0245 tot += image[i]; 0246 } 0247 *brightness = (128 - tot/(size*3))/3; 0248 return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130); 0249 }