// Copyright 2018 Slightech Co., Ltd. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include "CameraEngine.h" const char* dstr[] = { "default","dc1394","ps3eye","raspi","uvccam","","","","","","file","folder"}; const char* fstr[] = { "unknown", "mono8", "mono16", "rgb8", "rgb16", "mono16s", "rgb16s", "raw8", "raw16", "rgba", "yuyv", "uyvy", "yuv411", "yuv444", "yuv420p", "yuv410p", "yvyu", "yuv211", "", "", "jpeg", "mjpeg", "mpeg", "mpeg2", "mpeg4", "h263", "h264", "", "", "", "dvpal", "dvntsc" }; void CameraEngine::printInfo() { printf("camera: %s\n",cfg->name); printf("driver: %s\n",dstr[cfg->driver]); printf("codec: %s\n",fstr[cfg->cam_format]); if (cfg->frame_mode<0) { if (cfg->cam_fps==(int)cfg->cam_fps) printf("format: %dx%d, %dfps\n",cfg->frame_width,cfg->frame_height,(int)cfg->cam_fps); else printf("format: %dx%d, %.1ffps\n",cfg->frame_width,cfg->frame_height,cfg->cam_fps); } else printf("format7_%d: %dx%d\n",cfg->frame_mode,cfg->frame_width,cfg->frame_height); } void CameraEngine::setMinMaxConfig(CameraConfig *cam_cfg, std::vector cfg_list) { if ((cam_cfg->cam_width>0) && (cam_cfg->cam_height>0) && (cam_cfg->cam_fps>0)) return; int max_width = 0; int max_height = 0; int min_width = INT_MAX; int min_height = INT_MAX; float max_fps = 0; float min_fps = INT_MAX; for (unsigned int i=0;icam_format) continue; // wrong format if (cfg_list[i].frame_mode!=cam_cfg->frame_mode) continue; // wrong format7 if (cfg_list[i].cam_width>max_width) max_width = cfg_list[i].cam_width; if (cfg_list[i].cam_widthmax_height) max_height = cfg_list[i].cam_height; if (cfg_list[i].cam_widthcam_width==SETTING_MAX) || (cam_cfg->cam_width>max_width)) cam_cfg->cam_width = max_width; else if ((cam_cfg->cam_width==SETTING_MIN) || (cam_cfg->cam_widthcam_width = min_width; if ((cam_cfg->cam_height==SETTING_MAX) || (cam_cfg->cam_height>max_height)) cam_cfg->cam_height = max_height; else if ((cam_cfg->cam_height==SETTING_MIN) || (cam_cfg->cam_heightcam_height = min_height; if (cam_cfg->cam_fps>0) return; for (unsigned int i=0;icam_format) continue; // wrong format if (cfg_list[i].frame_mode!=cam_cfg->frame_mode) continue; // wrong format7 if ((cfg_list[i].cam_width!=cam_cfg->cam_width) || (cfg_list[i].cam_height!=cam_cfg->cam_height)) continue; // wrong size if (cfg_list[i].cam_fps>max_fps) max_fps = cfg_list[i].cam_fps; if (cfg_list[i].cam_fpscam_fps==SETTING_MAX) || (cam_cfg->cam_fps>max_fps)) cam_cfg->cam_fps = max_fps; if ((cam_cfg->cam_fps==SETTING_MIN) || (cam_cfg->cam_fpscam_fps = min_fps; } bool CameraEngine::showSettingsDialog(bool lock) { return true; } void CameraEngine::control(unsigned char key) { if(!settingsDialog) return; int step = 0; switch(key) { case VALUE_DECREASE: step = getCameraSettingStep(currentCameraSetting); if (step==1) step = (int)((float)ctrl_max/256.0f); if (step<1) step=1; ctrl_val -= step; if (ctrl_valctrl_max) ctrl_val=ctrl_max; setCameraSetting(currentCameraSetting,ctrl_val); break; case SETTING_PREVIOUS: currentCameraSetting--; if(currentCameraSetting<0) { if (cfg->color) currentCameraSetting=COLOR_BLUE; else currentCameraSetting=BACKLIGHT; } if ((!hasCameraSetting(currentCameraSetting)) || (getCameraSettingAuto(currentCameraSetting))) control(SETTING_PREVIOUS); break; case SETTING_NEXT: currentCameraSetting++; if ((cfg->color) && (currentCameraSetting>COLOR_BLUE)) currentCameraSetting=0; else if ((!cfg->color) && (currentCameraSetting>BACKLIGHT)) currentCameraSetting=0; if ((!hasCameraSetting(currentCameraSetting)) || (getCameraSettingAuto(currentCameraSetting))) control(SETTING_NEXT); break; case KEY_D: resetCameraSettings(); break; } ctrl_val = getCameraSetting(currentCameraSetting); ctrl_max = getMaxCameraSetting(currentCameraSetting); ctrl_min = getMinCameraSetting(currentCameraSetting); } void CameraEngine::uyvy2gray(int width, int height, unsigned char *src, unsigned char *dest) { for (int i=height*width/2;i>0;i--) { src++; *dest++ = *src++; src++; *dest++ = *src++; } } void CameraEngine::crop_uyvy2gray(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; cam_buf += 2*y_off*cam_w; int x_end = cam_w-(frm_w+x_off); for (int i=frm_h;i>0;i--) { cam_buf += 2*x_off; for (int j=frm_w/2;j>0;j--) { cam_buf++; *frm_buf++ = *cam_buf++; cam_buf++; *frm_buf++ = *cam_buf++; } cam_buf += 2*x_end; } } void CameraEngine::yuyv2gray(int width, int height, unsigned char *src, unsigned char *dest) { for (int i=height*width/2;i>0;i--) { *dest++ = *src++; src++; *dest++ = *src++; src++; } } void CameraEngine::crop_yuyv2gray(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; cam_buf += 2*y_off*cam_w; int x_end = cam_w-(frm_w+x_off); for (int i=frm_h;i>0;i--) { cam_buf += 2*x_off; for (int j=frm_w/2;j>0;j--) { *frm_buf++ = *cam_buf++; cam_buf++; *frm_buf++ = *cam_buf++; cam_buf++; } cam_buf += 2*x_end; } } //void yuv2rgb_conv(int Y1, int Y2, int U, int V, unsigned char *dest) { void yuv2rgb_conv(int Y, int U, int V, unsigned char *dest) { /*int R = (int)(Y + 1.370705f * V); int G = (int)(Y - 0.698001f * V - 0.337633f * U); int B = (int)(Y + 1.732446f * U);*/ // integer method is twice as fast int C = 298*(Y - 16); int R = (C + 409*V + 128) >> 8; int G = (C - 100*U - 208*V + 128) >> 8; int B = (C + 516*U + 128) >> 8; SAT(R); SAT(G); SAT(B); *dest++ = R; *dest++ = G; *dest++ = B; } void CameraEngine::uyvy2rgb(int width, int height, unsigned char *src, unsigned char *dest) { int Y1,Y2,U,V; for(int i=width*height/2;i>0;i--) { // U and V are +-0.5 U = *src++ - 128; Y1 = *src++; V = *src++ - 128; Y2 = *src++; yuv2rgb_conv(Y1,U,V,dest); yuv2rgb_conv(Y2,U,V,dest+=3); dest+=3; } } void CameraEngine::crop_uyvy2rgb(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; int Y1,Y2,U,V; cam_buf += 2*y_off*cam_w; int x_end = cam_w-(frm_w+x_off); for (int i=frm_h;i>0;i--) { cam_buf += 2*x_off; for (int j=frm_w/2;j>0;j--) { // U and V are +-0.5 U = *cam_buf++ - 128; Y1 = *cam_buf++; V = *cam_buf++ - 128; Y2 = *cam_buf++; yuv2rgb_conv(Y1,U,V,frm_buf); yuv2rgb_conv(Y2,U,V,frm_buf+=3); frm_buf+=3; } cam_buf += 2*x_end; } } void CameraEngine::yuyv2rgb(int width, int height, unsigned char *src, unsigned char *dest) { int Y1,Y2,U,V; for(int i=width*height/2;i>0;i--) { Y1 = *src++; U = *src++ - 128; Y2 = *src++; V = *src++ - 128; yuv2rgb_conv(Y1,U,V,dest); yuv2rgb_conv(Y2,U,V,dest+=3); dest+=3; } } void CameraEngine::crop_yuyv2rgb(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; int Y1,Y2,U,V; cam_buf += 2*y_off*cam_w; int x_end = cam_w-(frm_w+x_off); for (int i=frm_h;i>0;i--) { cam_buf += 2*x_off; for (int j=frm_w/2;j>0;j--) { // U and V are +-0.5 Y1 = *cam_buf++; U = *cam_buf++ - 128; Y2 = *cam_buf++; V = *cam_buf++ - 128; yuv2rgb_conv(Y1,U,V,frm_buf); yuv2rgb_conv(Y2,U,V,frm_buf+=3); frm_buf+=3; } cam_buf += 2*x_end; } } void CameraEngine::gray2rgb(int width, int height, unsigned char *src, unsigned char *dest) { int size = width*height; for (int i=size;i>0;i--) { unsigned char pixel = *src++; *dest++ = pixel; *dest++ = pixel; *dest++ = pixel; } } void CameraEngine::crop_gray2rgb(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; cam_buf += y_off*cam_w; int x_end = cam_w-(frm_w+x_off); for (int i=frm_h;i>0;i--) { cam_buf += x_off; for (int j=frm_w;j>0;j--) { unsigned char pixel = *cam_buf++; *frm_buf++ = pixel; *frm_buf++ = pixel; *frm_buf++ = pixel; } cam_buf += x_end; } } void CameraEngine::grayw2rgb(int width, int height, unsigned char *src, unsigned char *dest) { unsigned short src_pixel; unsigned char dest_pixel; unsigned char pixel; for(int i=width*height;i>0;i--) { pixel = *src++ ; src_pixel = pixel | (*src++ << 8); dest_pixel = (unsigned char)(src_pixel/4); *dest++ = dest_pixel; *dest++ = dest_pixel; *dest++ = dest_pixel; } } void CameraEngine::crop_grayw2rgb(int cam_w, unsigned char *src, unsigned char *dest) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; unsigned short src_pixel; unsigned char dest_pixel; unsigned char pixel; src += 2*y_off*cam_w; int x_end = cam_w-(frm_w+x_off); for (int i=frm_h;i>0;i--) { src += 2*x_off; for (int j=frm_w;j>0;j--) { pixel = *src++; src_pixel = pixel | (*src++ << 8); dest_pixel = (unsigned char)(src_pixel/4); *dest++ = dest_pixel; *dest++ = dest_pixel; *dest++ = dest_pixel; } src += 2*x_end; } } void CameraEngine::grayw2gray(int width, int height, unsigned char *src, unsigned char *dest) { unsigned short value; unsigned char pixel; for(int i=width*height;i>0;i--) { pixel = *src++; value = pixel | (*src++ << 8); *dest++ = (unsigned char)(value/4); } } void CameraEngine::crop_grayw2gray(int cam_w, unsigned char *src, unsigned char *dest) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; unsigned short src_pixel; unsigned char pixel; src += 2*y_off*cam_w; int x_end = cam_w-(frm_w+x_off); for (int i=frm_h;i>0;i--) { src += 2*x_off; for (int j=frm_w;j>0;j--) { pixel = *src++; src_pixel = pixel | (*src++ << 8); *dest++ = (unsigned char)(src_pixel/4); } src += 2*x_end; } } void CameraEngine::crop(int cam_w, int cam_h, unsigned char *cam_buf, unsigned char *frm_buf, int b) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; cam_buf += b*(y_off*cam_w + x_off); for (int i=frm_h;i>0;i--) { memcpy(frm_buf, cam_buf, b*cam_w); cam_buf += b*cam_w; frm_buf += b*frm_w; } } void CameraEngine::flip(int width, int height, unsigned char *src, unsigned char *dest, int b) { int size = b*width*height; dest += size-1; for(int i=size;i>0;i--) { *dest-- = *src++; } } void CameraEngine::flip_crop(int cam_w, int cam_h, unsigned char *cam_buf, unsigned char *frm_buf, int b) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; cam_buf += b*y_off*cam_w; frm_buf += b*frm_w*frm_h-1; int xend = (cam_w-(frm_w+x_off)); for (int i=frm_h;i>0;i--) { cam_buf += b*x_off; for (int j=b*frm_w;j>0;j--) { *frm_buf-- = *cam_buf++; } cam_buf += b*xend; } } void CameraEngine::rgb2gray(int width, int height, unsigned char *src, unsigned char *dest) { int R,G,B; for (int i=width*height;i>0;i--) { R = *src++; G = *src++; B = *src++; *dest++ = HBT(R*77 + G*151 + B*28); } } void CameraEngine::flip_rgb2gray(int width, int height, unsigned char *src, unsigned char *dest) { int size = width*height; dest += size-1; int R,G,B; for (int i=size;i>0;i--) { R = *src++; G = *src++; B = *src++; *dest-- = HBT(R*77 + G*151 + B*28); } } void CameraEngine::crop_rgb2gray(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; cam_buf += 3*y_off*cam_w; int x_end = cam_w-(frm_w+x_off); int R,G,B; for (int i=frm_h;i>0;i--) { cam_buf += 3*x_off; for (int j=frm_w;j>0;j--) { R = *cam_buf++; G = *cam_buf++; B = *cam_buf++; *frm_buf++ = HBT(R*77 + G*151 + B*28); } cam_buf += 3*x_end; } } void CameraEngine::flip_crop_rgb2gray(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) { if(!cfg->frame) return; int x_off = cfg->frame_xoff; int y_off = cfg->frame_yoff; int frm_w = cfg->frame_width; int frm_h = cfg->frame_height; cam_buf += 3*y_off*cam_w; int x_end = cam_w-(frm_w+x_off); frm_buf += frm_w*frm_h-1; int R,G,B; for (int i=frm_h;i>0;i--) { cam_buf += 3*x_off; for (int j=frm_w;j>0;j--) { R = *cam_buf++; G = *cam_buf++; B = *cam_buf++; *frm_buf-- = HBT(R*77 + G*151 + B*28); } cam_buf += 3*x_end; } } void CameraEngine::setupFrame() { if(!cfg->frame) { cfg->frame_width = cfg->cam_width; cfg->frame_height = cfg->cam_height; return; } // size sanity check if (cfg->frame_width%2!=0) cfg->frame_width--; if (cfg->frame_height%2!=0) cfg->frame_height--; if (cfg->frame_width<=0) cfg->frame_width = cfg->cam_width; if (cfg->frame_height<=0) cfg->frame_height = cfg->cam_height; if (cfg->frame_width > cfg->cam_width) cfg->frame_width = cfg->cam_width; if (cfg->frame_height > cfg->cam_height) cfg->frame_height = cfg->cam_height; // no cropping if same size if ((cfg->frame_width==cfg->cam_width) && (cfg->frame_height==cfg->cam_height)) { cfg->frame_width = cfg->cam_width; cfg->frame_height = cfg->cam_height; cfg->frame = false; return; } // offset sanity check int xdiff = cfg->cam_width-cfg->frame_width; if (xdiff<0) cfg->frame_xoff = 0; else if (cfg->frame_xoff > xdiff) cfg->frame_xoff = xdiff; int ydiff = cfg->cam_height-cfg->frame_height; if (ydiff<0) cfg->frame_yoff = 0; else if (cfg->frame_yoff > ydiff) cfg->frame_yoff = ydiff; } void CameraEngine::applyCameraSetting(int mode, int value) { if (!hasCameraSetting(mode)) return; switch (value) { case SETTING_AUTO: if (hasCameraSettingAuto(mode)) { setCameraSettingAuto(mode,true); return; } case SETTING_OFF: case SETTING_DEFAULT: setDefaultCameraSetting(mode); return; case SETTING_MIN: setCameraSettingAuto(mode,false); setCameraSetting(mode,getMinCameraSetting(mode)); return; case SETTING_MAX: setCameraSettingAuto(mode,false); setCameraSetting(mode,getMaxCameraSetting(mode)); return; default: { int max = getMaxCameraSetting(mode); int min = getMinCameraSetting(mode); if (valuemax) value = max; setCameraSettingAuto(mode,false); setCameraSetting(mode,value); } } } void CameraEngine::resetCameraSettings() { for (int mode=MODE_MIN;mode<=MODE_MAX;mode++) setDefaultCameraSetting(mode); } void CameraEngine::applyCameraSettings() { resetCameraSettings(); applyCameraSetting(BRIGHTNESS,cfg->brightness); applyCameraSetting(CONTRAST,cfg->contrast); applyCameraSetting(SHARPNESS,cfg->sharpness); applyCameraSetting(GAIN,cfg->gain); applyCameraSetting(EXPOSURE,cfg->exposure); applyCameraSetting(SHUTTER,cfg->shutter); applyCameraSetting(FOCUS,cfg->focus); applyCameraSetting(WHITE,cfg->white); applyCameraSetting(POWERLINE,cfg->powerline); applyCameraSetting(BACKLIGHT,cfg->backlight); applyCameraSetting(GAMMA,cfg->gamma); applyCameraSetting(SATURATION,cfg->saturation); applyCameraSetting(COLOR_HUE,cfg->hue); applyCameraSetting(COLOR_RED,cfg->red); applyCameraSetting(COLOR_GREEN,cfg->green); applyCameraSetting(COLOR_BLUE,cfg->blue); } int CameraEngine::updateSetting(int mode) { if (!hasCameraSetting(mode)) return SETTING_OFF; if (getCameraSettingAuto(mode)) return SETTING_AUTO; int value = getCameraSetting(mode); if (value==getDefaultCameraSetting(mode)) value = SETTING_DEFAULT; else if (value==getMinCameraSetting(mode)) value = SETTING_MIN; else if (value==getMaxCameraSetting(mode)) value = SETTING_MAX; return value; } void CameraEngine::updateSettings() { cfg->brightness = updateSetting(BRIGHTNESS); cfg->contrast = updateSetting(CONTRAST); cfg->sharpness = updateSetting(SHARPNESS); cfg->gain = updateSetting(GAIN); cfg->exposure = updateSetting(EXPOSURE); cfg->shutter = updateSetting(SHUTTER); cfg->focus = updateSetting(FOCUS); cfg->white = updateSetting(WHITE); cfg->backlight = updateSetting(BACKLIGHT); cfg->powerline = updateSetting(POWERLINE); cfg->gamma = updateSetting(GAMMA); if (cfg->color) { cfg->saturation = updateSetting(SATURATION); cfg->hue = updateSetting(COLOR_HUE); cfg->red = updateSetting(COLOR_RED); cfg->green = updateSetting(COLOR_GREEN); cfg->blue = updateSetting(COLOR_BLUE); } else { cfg->saturation = SETTING_OFF; cfg->hue = SETTING_OFF; cfg->red = SETTING_OFF; cfg->green = SETTING_OFF; cfg->blue = SETTING_OFF; } }