diff --git a/config.json b/config.json index 3d5a630..26f2acd 100644 --- a/config.json +++ b/config.json @@ -1,9 +1,10 @@ { + "libdir" : "./build", "data_dir": "./data", "driver" : "sim", "sim" : { - "path" : "sim" + "path" : "." }, "mem_limit_mb" : 0, "wdir" : { diff --git a/include/camera.h b/include/camera.h index 0c1e4e9..c6d6272 100644 --- a/include/camera.h +++ b/include/camera.h @@ -55,6 +55,7 @@ namespace ols { opt_wb, opt_wb_r, opt_wb_b, + opt_tint, opt_focus, opt_gain, opt_gamma, @@ -139,6 +140,12 @@ namespace ols { bayer_gb }; + enum CamByteOrder { + byteorder_rgb, + byteorder_bgr + }; + + std::string bayer_type_to_str(CamBayerType bayer); CamBayerType bayer_type_from_str(std::string const &s); @@ -167,7 +174,8 @@ namespace ols { /// struct CamFrame { CamStreamType format; /// image format - CamBayerType bayer = bayer_na; + CamBayerType bayer = bayer_na; + CamByteOrder byteorder = byteorder_bgr; /// byte order of camera int frame_counter; /// frame counter since camera started double unix_timestamp; /// time in sconds since Jan 1, 1970 when image was captured, inlcuding subsecond units int width; /// image width diff --git a/include/data_items.h b/include/data_items.h index ccfc0bf..549a793 100644 --- a/include/data_items.h +++ b/include/data_items.h @@ -55,6 +55,7 @@ namespace ols { struct CameraFrame : public QueueData { CamStreamFormat format; CamBayerType bayer = bayer_na; + CamByteOrder byteorder = byteorder_bgr; double timestamp; std::shared_ptr source_frame; std::shared_ptr jpeg_frame; diff --git a/src/camera.cpp b/src/camera.cpp index c59cb92..6552391 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -91,13 +91,13 @@ std::ostream &operator<<(std::ostream &out,CamStreamFormat const &fmt) static char const *option_string_ids[] = { - "auto_exp", "auto_wb", "auto_focus", "exp", "wb", "wb_r", "wb_b", "focus", "gain", "gamma", "brightness","contrast", "temperature", "cooler_target","cooler_on", "fan_on", "cooler_power","average_bin","black_level","conv_gain_hcg","conv_gain_hdr","low_noise","high_fullwell", + "auto_exp", "auto_wb", "auto_focus", "exp", "wb", "wb_r", "wb_b", "tint", "focus", "gain", "gamma", "brightness","contrast", "temperature", "cooler_target","cooler_on", "fan_on", "cooler_power","average_bin","black_level","conv_gain_hcg","conv_gain_hdr","low_noise","high_fullwell", "iso", "shutter", "viewfinder", "capturetarget", "keep_images", "capture_delay", "zoom", "live_stretch" }; static char const *option_names[] = { - "Auto Exp.", "Auto WB", "Auto Focus", "Exp.", "WB", "WB Red", "WB Blue", "Focus", "Gain", "Gamma", "Bright.", "Contr.", "Temp.", "Cooler Tgt.", "Cooler", "Fan","Cooler Pwr.","Avg. Bin","Black Lvl.","ConvGain L-0/H-1","ConvGain Lcg-0/Hcg-1/Hdr-2","Low Noise","High Fullwell", + "Auto Exp.", "Auto WB", "Auto Focus", "Exp.", "WB", "WB Red", "WB Blue", "Tint", "Focus", "Gain", "Gamma", "Bright.", "Contr.", "Temp.", "Cooler Tgt.", "Cooler", "Fan","Cooler Pwr.","Avg. Bin","Black Lvl.","ConvGain L-0/H-1","ConvGain Lcg-0/Hcg-1/Hdr-2","Low Noise","High Fullwell", "ISO", "Shutter", "View Finder" , "Capture Target", "Keep Images", "Inter-Shot Delay", "Zoom", "Auto Str." diff --git a/src/ols.cpp b/src/ols.cpp index bdad501..1e4593b 100644 --- a/src/ols.cpp +++ b/src/ols.cpp @@ -242,6 +242,7 @@ void OpenLiveStacker::handle_video_frame(CamFrame const &cf) frame->format.width = cf.width; frame->format.height = cf.height; frame->bayer = cf.bayer; + frame->byteorder = cf.byteorder; frame->timestamp = cf.unix_timestamp; frame->source_frame = std::shared_ptr(new VideoFrame(cf.data,cf.data_size)); frame->dropped = dropped_since_last_update_; diff --git a/src/toup_camera.cpp b/src/toup_camera.cpp index a2d93b1..f6b4d3b 100644 --- a/src/toup_camera.cpp +++ b/src/toup_camera.cpp @@ -267,25 +267,59 @@ namespace ols bpp = 2; // update to 1/2 if TOUPCAM_OPTION_BITDEPTH 0/1 for now using 1 unconditionaly frm.format = !(info_.model->flag & TOUPCAM_FLAG_MONO) ? stream_raw16 : stream_mono16; } - // printf("handle_frame=%dx%d(raw=%d, bpp=%d)\n", nW, nH, raw, bpp); +// printf("handle_frame=%dx%d(raw=%d, bpp=%d)\n", nW, nH, raw, bpp); size_t bufSize = nW * nH * bpp; if (buf_.size() != bufSize) // Just in case buf_.resize(bufSize); - unsigned w = 0, h = 0; - hr = Toupcam_PullImage(hcam_, buf_.data(), bpp * 8, &w, &h); +// unsigned w = 0, h = 0; + ToupcamFrameInfoV4 info = { 0 }; +// hr = Toupcam_PullImage(hcam_, buf_.data(), bpp * 8, &w, &h); + hr = Toupcam_PullImageV4(hcam_, buf_.data(), 0, bpp * 8, 0, &info); if (FAILED(hr)) { handle_error("Toupcam_PullImage",hr); return; } -/* // printf("handle_frame: Toupcam_PullImage=(%ux%u)\n", w, h); - hr = Toupcam_put_Option(hcam_, TOUPCAM_OPTION_FLUSH, 2); +// printf("handle_frame: Toupcam_PullImage=(%ux%u)\n", info.v3.width, info.v3.height); +/* + //RGB frame + for (int i=0; i < 1920*1080*3; i+=3) { + buf_[i] = 255; + buf_[i+1] = 0; + buf_[i+2] = 0; + } +*/ +// printf("Frame color sample r:%d g:%d b:%d\n", buf_[0], buf_[1], buf_[2]); +/* + //RAW16 frame + + uint16_t pattern[2][2] = { + {0xFFFF, 0x0}, // top-left and top-right + {0x0, 0x0} // bottom-left and bottom-right + }; + + for (int y = 0; y < 1080; ++y) { + for (int x = 0; x < 1920; ++x) { + int px = x % 2; + int py = y % 2; + uint16_t val = pattern[py][px]; + + size_t index = (y * 1920 + x) * 2; + buf_[index] = val & 0xFF; // low byte + buf_[index + 1] = (val >> 8) & 0xFF; // high byte + } + } +*/ + + // printf("handle_frame: Toupcam_PullImage=(%ux%u)\n", w, h); +/* + hr = Toupcam_put_Option(hcam_, TOUPCAM_OPTION_FLUSH, 2); if (FAILED(hr)) { handle_error("Toupcam_put_Option FLUSH",hr); // printf("handle_frame:Toupcam_put_Option(TOUPCAM_OPTION_FLUSH, 2)=%d\n", hr); - }*/ - + } +*/ if(bpp == 2) { int bits=16; if(info_.model->flag & TOUPCAM_FLAG_RAW10) @@ -302,12 +336,13 @@ namespace ols gettimeofday(&tv, nullptr); frm.unix_timestamp = tv.tv_sec; frm.unix_timestamp += tv.tv_usec * 1e-6; - frm.width = w; - frm.height = h; + frm.width = info.v3.width; + frm.height = info.v3.height; frm.data = buf_.data(); frm.data_size = buf_.size(); frm.frame_counter = frame_counter_++; frm.bayer = bayerPattern_; + frm.byteorder = byteorder_rgb; { std::unique_lock guard(lock_); if (callback_) @@ -420,7 +455,6 @@ namespace ols stream_active_ = 1; - #ifndef MAKEFOURCC #define MAKEFOURCC(a, b, c, d) ((unsigned)(unsigned char)(a) | ((unsigned)(unsigned char)(b) << 8) | ((unsigned)(unsigned char)(c) << 16) | ((unsigned)(unsigned char)(d) << 24)) #endif @@ -435,23 +469,23 @@ namespace ols switch (nFourCC) { case MAKEFOURCC('G', 'B', 'R', 'G'): - // printf("Toupcam_get_RawFormat(%s, %d)\n", "GBRG", bitsperpixel); + printf("Toupcam_get_RawFormat(%s, %d)\n", "GBRG", bitsperpixel); bayerPattern_ = bayer_gr; break; case MAKEFOURCC('R', 'G', 'G', 'B'): - // printf("Toupcam_get_RawFormat(%s, %d)\n", "RGGB", bitsperpixel); + printf("Toupcam_get_RawFormat(%s, %d)\n", "RGGB", bitsperpixel); bayerPattern_ = bayer_bg; break; case MAKEFOURCC('B', 'G', 'G', 'R'): - // printf("Toupcam_get_RawFormat(%s, %d)\n", "BGGR", bitsperpixel); + printf("Toupcam_get_RawFormat(%s, %d)\n", "BGGR", bitsperpixel); bayerPattern_ = bayer_rg; break; case MAKEFOURCC('G', 'R', 'B', 'G'): - // printf("Toupcam_get_RawFormat(%s, %d)\n", "GRBG", bitsperpixel); + printf("Toupcam_get_RawFormat(%s, %d)\n", "GRBG", bitsperpixel); bayerPattern_ = bayer_gb; break; case MAKEFOURCC('Y', 'Y', 'Y', 'Y'): - // printf("Toupcam_get_RawFormat(%s, %d)\n", "YYYY", bitsperpixel); + printf("Toupcam_get_RawFormat(%s, %d)\n", "YYYY", bitsperpixel); break; // monochromatic sensor default: break; @@ -501,6 +535,7 @@ namespace ols if (!(info_.model->flag & TOUPCAM_FLAG_MONO)) { opts.push_back(opt_auto_wb); opts.push_back(opt_wb); + opts.push_back(opt_tint); } if (info_.model->flag & TOUPCAM_FLAG_TEC) // Thermoelectric Cooler Present { @@ -601,6 +636,20 @@ namespace ols r.def_val = 6503; return r; } + break; + case opt_tint: + { + int temp=6503,tint=1000; + Toupcam_get_TempTint(hcam_,&temp,&tint); + r.type = type_number; + r.min_val = 200; + r.max_val = 2500; + r.step_size = 1; + r.cur_val = tint; + r.def_val = 1000; + return r; + } + break; case opt_average_bin: { r.type = type_bool; @@ -799,8 +848,17 @@ namespace ols break; case opt_wb: { - int temp = value; - int tint = 1000; // default + int temp,tint; + Toupcam_get_TempTint(hcam_,&temp,&tint); //get tint + temp = value; + hr = Toupcam_put_TempTint(hcam_,temp,tint); + } + break; + case opt_tint: + { + int temp,tint; + Toupcam_get_TempTint(hcam_,&temp,&tint); //get temp + tint = value; hr = Toupcam_put_TempTint(hcam_,temp,tint); } break; diff --git a/src/video_generator.cpp b/src/video_generator.cpp index da9a2f5..394a9b4 100644 --- a/src/video_generator.cpp +++ b/src/video_generator.cpp @@ -126,7 +126,13 @@ namespace ols { break; case stream_rgb24: { - cv::Mat rgb(frame->format.height,frame->format.width,CV_8UC3,frame->source_frame->data()); + cv::Mat tmp(frame->format.height,frame->format.width,CV_8UC3,frame->source_frame->data()); + cv::Mat rgb; + if (frame->byteorder == byteorder_rgb) { + cv::cvtColor(tmp,rgb,cv::COLOR_RGB2BGR); + } else { + rgb = tmp; + } frame->frame_dr = 255; frame->raw = rgb; handle_jpeg_stack(frame,rgb,true); @@ -144,7 +150,7 @@ namespace ols { case stream_raw16: { cv::Mat bayer(frame->format.height,frame->format.width,(bpp==1 ? CV_8UC1 : CV_16UC1),frame->source_frame->data()); - cv::Mat desp,rgb; + cv::Mat desp,rgb; if(remove_hot_pixels_) desp = remove_hot_pixels(bayer,false); else @@ -158,6 +164,27 @@ namespace ols { default: BOOSTER_ERROR("stacker") << "Invalid bayer patter"; } + if (frame->byteorder == byteorder_rgb) { + switch(frame->bayer) { + case bayer_rg: cv::cvtColor(desp,rgb,cv::COLOR_BayerBG2RGB); break; // COLOR_BayerRGGB2RGB = COLOR_BayerBG2RGB + case bayer_gr: cv::cvtColor(desp,rgb,cv::COLOR_BayerGB2RGB); break; // COLOR_BayerGRBG2RGB = COLOR_BayerGB2RGB + case bayer_bg: cv::cvtColor(desp,rgb,cv::COLOR_BayerRG2RGB); break; // COLOR_BayerBGGR2RGB = COLOR_BayerRG2RGB + case bayer_gb: cv::cvtColor(desp,rgb,cv::COLOR_BayerGR2RGB); break; // COLOR_BayerGBRG2RGB = COLOR_BayerGR2RGB + case bayer_na: cv::cvtColor(desp,rgb,cv::COLOR_GRAY2RGB); break; // handle case when indigo reports raw but it actually mono + default: + BOOSTER_ERROR("stacker") << "Invalid bayer patter"; + } + } else { + switch(frame->bayer) { + case bayer_rg: cv::cvtColor(desp,rgb,cv::COLOR_BayerBG2BGR); break; // COLOR_BayerRGGB2BGR = COLOR_BayerBG2BGR + case bayer_gr: cv::cvtColor(desp,rgb,cv::COLOR_BayerGB2BGR); break; // COLOR_BayerGRBG2BGR = COLOR_BayerGB2BGR + case bayer_bg: cv::cvtColor(desp,rgb,cv::COLOR_BayerRG2BGR); break; // COLOR_BayerBGGR2BGR = COLOR_BayerRG2BGR + case bayer_gb: cv::cvtColor(desp,rgb,cv::COLOR_BayerGR2BGR); break; // COLOR_BayerGBRG2BGR = COLOR_BayerGR2BGR + case bayer_na: cv::cvtColor(desp,rgb,cv::COLOR_GRAY2BGR); break; // handle case when indigo reports raw but it actually mono + default: + BOOSTER_ERROR("stacker") << "Invalid bayer patter"; + } + } frame->frame_dr = (bpp==1 ? 255 : 65535); handle_jpeg_stack(frame,rgb,false); frame->raw = bayer; diff --git a/www-data/media/js/code.js b/www-data/media/js/code.js index 12284fa..bfe49fe 100644 --- a/www-data/media/js/code.js +++ b/www-data/media/js/code.js @@ -903,6 +903,7 @@ function updateAllDependent(optid,value) updateDependent('wb',enable); updateDependent('wb_r',enable); updateDependent('wb_b',enable); + updateDependent('tint',enable); } } @@ -964,7 +965,7 @@ function prepareControls(ctls) aexp_on = ctl.cur != 0; console.log('AEXP on=' + aexp_on); } - else if(ctl.option_id == 'wb' || ctl.option_id == 'wb_r' || ctl.option_id == 'wb_b') { + else if(ctl.option_id == 'wb' || ctl.option_id == 'wb_r' || ctl.option_id == 'wb_b' || ctl.option_id == 'tint') { if(has_awb && awb_on) disabled = true; } @@ -2823,7 +2824,7 @@ function newProfileOptions(ctls) has_ae = true; if((ctl.option_id == 'exp' || ctl.option_id == 'gain') && has_ae) continue; - if((ctl.option_id == 'wb' || ctl.option_id == 'wb_r' || ctl.option_id == 'wb_b') && has_awb) + if((ctl.option_id == 'wb' || ctl.option_id == 'wb_r' || ctl.option_id == 'wb_b' || ctl.option_id == 'tint') && has_awb) continue; var str = `
  • ${ctl.name}: ${ctl.cur}
  • \n`; res = res + str;