From c55d6189d1366f0dc528d4b170f83c6b5c4d7c0e Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Fri, 24 Jun 2022 17:01:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=AE=9A=E4=B9=89GA?= =?UTF-8?q?MMA=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sane/DlgArea.cpp | 7 +- sane/DlgGamma.cpp | 668 ++++++++++++++++++++++++++++++++++++++ sane/DlgGamma.h | 57 ++++ sane/DlgPage.cpp | 52 ++- sane/DlgPage.h | 15 - sane/mem_dc.cpp | 39 +++ sane/mem_dc.h | 19 ++ sane/resource.h | 8 +- sane/sane.rc | 49 +++ sane/sane.vcxproj | 4 + sane/sane.vcxproj.filters | 12 + 11 files changed, 883 insertions(+), 47 deletions(-) create mode 100644 sane/DlgGamma.cpp create mode 100644 sane/DlgGamma.h create mode 100644 sane/mem_dc.cpp create mode 100644 sane/mem_dc.h diff --git a/sane/DlgArea.cpp b/sane/DlgArea.cpp index 5ac8f01..681ffb4 100644 --- a/sane/DlgArea.cpp +++ b/sane/DlgArea.cpp @@ -4,6 +4,7 @@ #include "DlgArea.h" #include "resource.h" #include "scanned_img.h" // for local_trans +#include "mem_dc.h" // CDlgIndicator 对话框 #define MM_PER_INCH 25.4f @@ -18,9 +19,9 @@ dlg_area::dlg_area(HWND parent) : dlg_base(parent, IDD_AREA) , in_set_func_(false) { create(); - SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u6beb\u7c73(mm)"); - SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u82f1\u5bf8(inch)"); - SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u50cf\u7d20(px)"); + SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u6beb\u7c73\uff08mm\uff09"); + SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u82f1\u5bf8\uff08inch\uff09"); + SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u50cf\u7d20\uff08px\uff09"); SendMessage(get_item(IDC_UNIT), CB_SETCURSEL, 0, 0); } dlg_area::~dlg_area() diff --git a/sane/DlgGamma.cpp b/sane/DlgGamma.cpp new file mode 100644 index 0000000..30eeff2 --- /dev/null +++ b/sane/DlgGamma.cpp @@ -0,0 +1,668 @@ +// DlgIndicator.cpp: 实现文件 +// + +#include "DlgGamma.h" +#include "resource.h" +#include "mem_dc.h" + + +#define MAX_KEY_POINTS 4 // not include (0, 0) and (255, 255) + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// calculator +#include +namespace calc +{ + void solve_matrix(double** a, int n, std::vector& coef) + { + int m = 0; + int i, j; + + coef.clear(); + for (j = 0; j < n; j++) { + double max = 0; + double imax = 0; + for (i = j; i < n; i++) { + if (imax < fabs(a[i][j])) { + imax = fabs(a[i][j]); + max = a[i][j];//得到各行中所在列最大元素 + m = i; + } + } + if (fabs(a[j][j]) != max) { + double b = 0; + for (int k = j; k < n + 1; k++) { + b = a[j][k]; + a[j][k] = a[m][k]; + a[m][k] = b; + } + } + for (int r = j; r < n + 1; r++) { + a[j][r] = a[j][r] / max;//让该行的所在列除以所在列的第一个元素,目的是让首元素为1 + } + for (i = j + 1; i < n; i++) { + double c = a[i][j]; + if (c == 0) continue; + for (int s = j; s < n + 1; s++) { + //double tempdata = a[i][s]; + a[i][s] = a[i][s] - a[j][s] * c;//前后行数相减,使下一行或者上一行的首元素为0 + } + } + } + for (i = n - 2; i >= 0; i--) { + for (j = i + 1; j < n; j++) { + a[i][n] = a[i][n] - a[j][n] * a[i][j]; + } + } + + for (int k = 0; k < n; k++) { + coef.push_back(a[k][n]); + } + } + int power(int m, int exp) + { + int val = 1; + for (int i = 0; i < exp; ++i) + val *= m; + + return val; + } + std::vector coefs_from_points(const std::vector& pt) + { + std::vector coef; + double** a = new double* [pt.size()]; + + for (int i = 0; i < pt.size(); ++i) + a[i] = new double[pt.size() + 1]; + + for (int i = 0; i < pt.size(); ++i) + { + for (int j = 0; j < pt.size(); ++j) + a[i][j] = power(pt[i].x, pt.size() - j - 1); + a[i][pt.size()] = pt[i].y; + } + solve_matrix(a, pt.size(), coef); + for (int i = 0; i < pt.size(); ++i) + delete[] a[i]; + delete[] a; + + return coef; + } +} + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// dlg_gamma +dlg_gamma::dlg_gamma(HWND parent, bool color) : dlg_base(parent, IDD_GAMMA), exit_code_(0), is_color_(color), bkgnd_(NULL) +{ + create(); +} +dlg_gamma::~dlg_gamma() +{ + DeleteObject(bkgnd_); +} + + +BOOL dlg_gamma::handle_message(UINT msg, WPARAM wp, LPARAM lp) +{ + wchar_t text[40] = { 0 }; + BOOL ret = TRUE; + + switch (msg) + { + case WM_INITDIALOG: + on_init_dlg(); + UpdateWindow(hwnd()); + break; + case WM_COMMAND: + handle_command(HIWORD(wp), LOWORD(wp), (HWND)lp); + break; + case WM_PAINT: + { + PAINTSTRUCT ps = { 0 }; + HDC hdc = BeginPaint(hwnd(), &ps); + { + compatible_dc dc(hdc); + on_paint(dc.get_dc()); + } + EndPaint(hwnd(), &ps); + } + break; + case WM_MOUSEMOVE: + on_mouse_move(wp, LOWORD(lp), HIWORD(lp)); + break; + case WM_LBUTTONDOWN: + on_lbutton_down(LOWORD(lp), HIWORD(lp)); + break; + case WM_LBUTTONUP: + on_lbutton_up(LOWORD(lp), HIWORD(lp)); + break; + default: + ret = FALSE; + } + return ret; +} +void dlg_gamma::handle_command(WORD code, WORD id, HANDLE ctrl) +{ + if (code == BN_CLICKED) + { + if (id == IDC_BUTTON_RESET) + { + init_curve(cur_, cur_->clr); + InvalidateRect(hwnd(), NULL, FALSE); + } + else + { + exit_code_ = id; + } + } + else if (code == EN_CHANGE) + { + if (id == IDC_EDIT_INPUT) + { + wchar_t val[40] = { 0 }; + int y = 0; + + GetDlgItemTextW(hwnd(), id, val, _countof(val) - 1); + y = _wtoi(val); + if (y < cur_->points[0].x) + SetDlgItemInt(hwnd(), IDC_EDIT_INPUT, cur_->points[0].x, FALSE); + if (y > cur_->points[1].x) + SetDlgItemInt(hwnd(), IDC_EDIT_INPUT, cur_->points[1].x, FALSE); + else + { + y = calc_value(y); + SetDlgItemInt(hwnd(), IDC_EDIT_OUTPUT, y, FALSE); + } + } + } + else if (code == CBN_SELCHANGE) + { + on_combo_sel_changed(id, SendMessage((HWND)ctrl, CB_GETCURSEL, 0, 0)); + } +} +void dlg_gamma::create_background(void) +{ + COLORREF bclr = RGB(128, 128, 128); + HDC hdc = GetWindowDC(hwnd()), + cdc = CreateCompatibleDC(hdc); + HBRUSH bkg = CreateSolidBrush(bclr); + HPEN grid = CreatePen(PS_SOLID, 1, RGB(0, 0, 0)), + old = (HPEN)SelectObject(cdc, grid); + HBITMAP ob = NULL; + int w = paint_area_.right - paint_area_.left + 2, + h = paint_area_.bottom - paint_area_.top + 2; + RECT r = { 1, 1, w - 1, h - 1}; + + if (bkgnd_) + DeleteObject(bkgnd_); + + // create bitmap and select into DC + bkgnd_ = CreateCompatibleBitmap(hdc, w, h); + ob = (HBITMAP)SelectObject(cdc, bkgnd_); + SetBkColor(cdc, bclr); + + // background and grid + FillRect(cdc, &r, bkg); + MoveToEx(cdc, r.left, r.top, NULL); + LineTo(cdc, r.right, r.top); + LineTo(cdc, r.right, r.bottom); + LineTo(cdc, r.left, r.bottom); + LineTo(cdc, r.left, r.top); + SelectObject(cdc, old); + DeleteObject(grid); + grid = CreatePen(PS_DASH, 1, RGB(0, 0, 0)); + SelectObject(cdc, grid); + for (int i = 1; i < 6; ++i) + { + MoveToEx(cdc, r.left + i * 50, r.bottom, NULL); + LineTo(cdc, r.left + i * 50, r.top); + + MoveToEx(cdc, r.left, r.bottom - i * 50, NULL); + LineTo(cdc, r.right, r.bottom - i * 50); + } + + // default curve + MoveToEx(cdc, r.left, r.bottom, NULL); + LineTo(cdc, r.right, r.top); + + // free resource + SelectObject(cdc, old); + SelectObject(cdc, ob); + DeleteDC(cdc); + ReleaseDC(hwnd(), hdc); + + DeleteObject(bkg); + DeleteObject(grid); +} +void dlg_gamma::init_curve(GAMMACURVE* curv, COLORREF clr) +{ + curv->points.clear(); + curv->points.push_back({ 0, 0 }); + curv->points.push_back({ 255, 255 }); + curv->coefs = calc::coefs_from_points(curv->points); + curv->drag = -1; + curv->left = 0; + curv->right = 1; + curv->clr = clr; +} +int dlg_gamma::add_drag_point(int x, int y) +{ + int ind = -1; + + if (cur_->points.size() < MAX_KEY_POINTS + 2) + { + for (int i = 2; i < cur_->points.size(); ++i) + { + if (x < cur_->points[i].x) + { + cur_->points.insert(cur_->points.begin() + i, { x, calc_value(x) }); + ind = i; + cur_->coefs = calc::coefs_from_points(cur_->points); + break; + } + else if (x == cur_->points[i].x) + { + ind = i; + break; + } + } + if (ind == -1) + { + ind = cur_->points.size(); + cur_->points.push_back({ x, calc_value(x) }); + cur_->coefs = calc::coefs_from_points(cur_->points); + } + cur_->left = ind - 1; + cur_->right = ind + 1; + if (cur_->left == 1) + cur_->left = 0; + if (cur_->right >= cur_->points.size()) + cur_->right = 1; + } + else + { + for (int i = 2; i < cur_->points.size(); ++i) + { + if (x == cur_->points[i].x) + { + ind = i; + cur_->left = ind - 1; + cur_->right = ind + 1; + if (cur_->left == 1) + cur_->left = 0; + if (cur_->right >= cur_->points.size()) + cur_->right = 1; + break; + } + } + } + cur_->drag = ind; + + return ind; +} +BYTE dlg_gamma::calc_value(BYTE x) +{ + double y = .0f; + for(int j = 0; j < cur_->points.size(); ++j) + y += cur_->coefs[j] * calc::power(x, cur_->points.size() - j - 1); + + if (y > 255.0f) + y = 255.0f; + if (y < .0f) + y = .0f; + if (y < cur_->points[0].y) + y = cur_->points[0].y; + if (y > cur_->points[1].y) + y = cur_->points[1].y; + + return y + .5f; +} +bool dlg_gamma::is_adjacent(POINT p1, POINT p2) +{ + bool neighbour = abs(p1.x - p2.x) <= 3 && abs(p1.y - p2.y) <= 3; + + return neighbour; +} +bool dlg_gamma::hit_test(int* x, int* y) +{ + for (int i = 2; i < cur_->points.size(); ++i) + { + POINT pt = { *x, *y }; + if (is_adjacent(pt, cur_->points[i])) + { + *x = cur_->points[i].x; + *y = cur_->points[i].y; + return true; + } + } + + + int val = calc_value(*x), tolerant = 3; + bool hit = false; + + if (abs(val - *y) < tolerant) + { + *y = val; + hit = true; + } + else + { + int l = *x - tolerant, + u = *x + tolerant; + if (l < 0) + l = 0; + if (u > 255) + u = 255; + for (; l <= u; ++l) + { + val = calc_value(l); + if (abs(val - *y) < tolerant) + { + hit = true; + *x = l; + *y = val; + break; + } + } + } + + return hit; +} +void dlg_gamma::draw_ellipse(HDC hdc, POINT center, int xl, int yl) +{ + center.x += paint_area_.left; + center.y = paint_area_.bottom - center.y; + + HRGN rgn = CreateEllipticRgn(center.x - xl, center.y - yl, center.x + xl, center.y + yl); + HBRUSH brsh = CreateSolidBrush(RGB(255, 0, 255)); + FillRgn(hdc, rgn, brsh); + DeleteObject(brsh); + DeleteObject(rgn); +} + +void dlg_gamma::on_init_dlg(void) +{ + HWND combo = get_item(IDC_SCHEME); + + GetWindowRect(get_item(IDC_STATIC_PAINT), &paint_area_); + screen_2_client(&paint_area_); + paint_area_.right = paint_area_.left + 255; + paint_area_.bottom = paint_area_.top + 255; + create_background(); + + init_curve(&rgb_gray_); + init_curve(&red_, RGB(255, 0, 0)); + init_curve(&green_, RGB(0, 255, 0)); + init_curve(&blue_, RGB(0, 0, 255)); + + SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"\u81ea\u5b9a\u4e49"); + SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"\u8d1f\u7247\uff08RGB\uff09"); + SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"\u5f69\u8272\u8d1f\u7247\uff08RGB\uff09"); + SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"\u8f83\u6697\uff08RGB\uff09"); + SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"\u8f83\u4eae\uff08RGB\uff09"); + SendMessage(combo, CB_SETCURSEL, 0, 0); + + combo = get_item(IDC_CHANNEL); + if (is_color_) + { + SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"RGB"); + SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"\u7ea2"); + SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"\u7eff"); + SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"\u84dd"); + } + else + SendMessageW(combo, CB_ADDSTRING, 0, (LPARAM)L"\u7070"); + SendMessage(combo, CB_SETCURSEL, 0, 0); + cur_ = &rgb_gray_; + + SetDlgItemInt(hwnd(), IDC_EDIT_INPUT, 0, FALSE); + SetDlgItemInt(hwnd(), IDC_EDIT_OUTPUT, 0, FALSE); +} +void dlg_gamma::on_paint(HDC hdc) +{ + HPEN pen = CreatePen(PS_SOLID, 1, cur_->clr), + drag = CreatePen(PS_SOLID, 1, RGB(255, 0, 255)), + old = (HPEN)SelectObject(hdc, pen); + HDC cdc = CreateCompatibleDC(hdc); + HBITMAP ob = (HBITMAP)SelectObject(cdc, bkgnd_); + + BitBlt(hdc, paint_area_.left - 1, paint_area_.top - 1, paint_area_.right - paint_area_.left + 2, paint_area_.bottom - paint_area_.top + 2, + cdc, 0, 0, SRCCOPY); + SelectObject(cdc, ob); + DeleteDC(cdc); + + MoveToEx(hdc, paint_area_.left, paint_area_.bottom, NULL); + for (int i = 0; i < 256; ++i) + { + int y = calc_value(i); + LineTo(hdc, paint_area_.left + i, paint_area_.bottom - y); + } + SelectObject(hdc, drag); + for (int i = 0; i < cur_->points.size(); ++i) + { + draw_ellipse(hdc, cur_->points[i], 3, 3); + } + SelectObject(hdc, old); + + DeleteObject(pen); +} +void dlg_gamma::on_mouse_move(DWORD key, int x, int y) +{ + POINT pt = { x, y }; + + if (PtInRect(&paint_area_, pt)) + { + x -= paint_area_.left; + y = paint_area_.bottom - y; + if (key == MK_LBUTTON && cur_->drag != -1) + { + if (x <= cur_->points[cur_->left].x) + x = cur_->points[cur_->left].x + 1; + else if (x >= cur_->points[cur_->right].x) + x = cur_->points[cur_->right].x - 1; + cur_->points[cur_->drag].x = x; + cur_->points[cur_->drag].y = y; + cur_->coefs = calc::coefs_from_points(cur_->points); + InvalidateRect(hwnd(), NULL, FALSE); + } + else if (key == MK_CONTROL) + { + y = calc_value(x); + pt.y = paint_area_.bottom - y; + ClientToScreen(hwnd(), &pt); + SetCursorPos(pt.x, pt.y); + } + SetDlgItemInt(hwnd(), IDC_EDIT_INPUT, x, FALSE); + SetDlgItemInt(hwnd(), IDC_EDIT_OUTPUT, y, FALSE); + } +} +void dlg_gamma::on_lbutton_down(int x, int y) +{ + x -= paint_area_.left; + y = paint_area_.bottom - y; + if (hit_test(&x, &y)) + { + if(add_drag_point(x, y) != -1) + SetCapture(hwnd()); + } +} +void dlg_gamma::on_lbutton_up(int x, int y) +{ + cur_->drag = -1; + cur_->left = 0; + cur_->right = 1; + ReleaseCapture(); +} +void dlg_gamma::on_combo_sel_changed(int id, int sel) +{ + if (id == IDC_SCHEME) + { + + } + else if (id == IDC_CHANNEL) + { + GAMMACURVE* prev = cur_, * all[] = { &rgb_gray_, &red_, &green_, &blue_ }; + + cur_ = all[sel]; + if (prev != cur_) + { + if (cur_->points.size() == 2) + { + COLORREF clr = cur_->clr; + + *cur_ = *prev; + cur_->clr = clr; + } + InvalidateRect(hwnd(), NULL, FALSE); + } + } +} + +int dlg_gamma::do_modal(HWND parent) +{ + BOOL enable_parent = FALSE, + got = TRUE; + MSG msg = { 0 }; + + if (IsWindow(parent) && parent != GetDesktopWindow()) + { + EnableWindow(parent, FALSE); + enable_parent = TRUE; + } + + ShowWindow(hwnd(), SW_SHOW); + while ((got = GetMessage(&msg, NULL, 0, 0))) + { + if ((DWORD)got == -1) + break; + + //if (enable_parent && msg.hwnd == parent && + // msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST && + // msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) + // continue; + + TranslateMessage(&msg); + DispatchMessage(&msg); + if (exit_code_ == IDOK || exit_code_ == IDCANCEL) + break; + } + ShowWindow(hwnd(), SW_HIDE); + + if (enable_parent) + { + EnableWindow(parent, TRUE); + } + + return exit_code_; +} +void dlg_gamma::get_gamma(SANE_Gamma* gamma) +{ + gamma->apply_to_back = SANE_FALSE; + if (cur_ == &rgb_gray_) + { + gamma->pt_count = cur_->points.size() - 2; + gamma->pt_count_r = gamma->pt_count_g = gamma->pt_count_b = 0; + for (int i = 2; i < gamma->pt_count; ++i) + { + gamma->keypoint[i - 2].x = cur_->points[i].x; + gamma->keypoint[i - 2].y = cur_->points[i].y; + } + + cur_ = &rgb_gray_; + for (int i = 0; i < 256; ++i) + gamma->table[i] = calc_value(i); + } + else + { + gamma->pt_count = 0; + + cur_ = &red_; + gamma->pt_count_r = cur_->points.size(); + for (int i = 2; i < gamma->pt_count; ++i) + { + gamma->keypoint_r[i - 2].x = cur_->points[i].x; + gamma->keypoint_r[i - 2].y = cur_->points[i].y; + } + for (int i = 0; i < 256; ++i) + gamma->table[i] = calc_value(i); + + cur_ = &green_; + gamma->pt_count_g = cur_->points.size(); + for (int i = 2; i < gamma->pt_count; ++i) + { + gamma->keypoint_g[i - 2].x = cur_->points[i].x; + gamma->keypoint_g[i - 2].y = cur_->points[i].y; + } + for (int i = 0; i < 256; ++i) + gamma->table[256 + i] = calc_value(i); + + cur_ = &blue_; + gamma->pt_count_b = cur_->points.size(); + for (int i = 2; i < gamma->pt_count; ++i) + { + gamma->keypoint_b[i - 2].x = cur_->points[i].x; + gamma->keypoint_b[i - 2].y = cur_->points[i].y; + } + for (int i = 0; i < 256; ++i) + gamma->table[512 + i] = calc_value(i); + } +} +void dlg_gamma::set_gamma(const SANE_Gamma* gamma) +{ + int sel = 0; + SendMessage(get_item(IDC_CHANNEL), CB_RESETCONTENT, 0, 0); + if (gamma->pt_count) + { + is_color_ = false; + cur_ = &rgb_gray_; + init_curve(cur_); + for (int i = 0; i < gamma->pt_count; ++i) + { + POINT pt = { gamma->keypoint[i].x, gamma->keypoint[i].y }; + cur_->points.push_back(pt); + } + cur_->coefs = calc::coefs_from_points(cur_->points); + SendMessageW(get_item(IDC_CHANNEL), CB_ADDSTRING, 0, (LPARAM)L"\u7070"); + } + else + { + is_color_ = true; + cur_ = &red_; + init_curve(cur_); + for (int i = 0; i < gamma->pt_count_r; ++i) + { + POINT pt = { gamma->keypoint_r[i].x, gamma->keypoint_r[i].y }; + cur_->points.push_back(pt); + } + cur_->coefs = calc::coefs_from_points(cur_->points); + + cur_ = &green_; + init_curve(cur_); + for (int i = 0; i < gamma->pt_count_g; ++i) + { + POINT pt = { gamma->keypoint_g[i].x, gamma->keypoint_g[i].y }; + cur_->points.push_back(pt); + } + cur_->coefs = calc::coefs_from_points(cur_->points); + + cur_ = &blue_; + init_curve(cur_); + for (int i = 0; i < gamma->pt_count_b; ++i) + { + POINT pt = { gamma->keypoint_b[i].x, gamma->keypoint_b[i].y }; + cur_->points.push_back(pt); + } + cur_->coefs = calc::coefs_from_points(cur_->points); + + SendMessageW(get_item(IDC_CHANNEL), CB_ADDSTRING, 0, (LPARAM)L"RGB"); + SendMessageW(get_item(IDC_CHANNEL), CB_ADDSTRING, 0, (LPARAM)L"\u7ea2"); + SendMessageW(get_item(IDC_CHANNEL), CB_ADDSTRING, 0, (LPARAM)L"\u7eff"); + SendMessageW(get_item(IDC_CHANNEL), CB_ADDSTRING, 0, (LPARAM)L"\u84dd"); + cur_ = &red_; + sel = 1; + } + SendMessage(get_item(IDC_CHANNEL), CB_SETCURSEL, sel, 0); + SendMessage(get_item(IDC_SCHEME), CB_SETCURSEL, 0, 0); +} diff --git a/sane/DlgGamma.h b/sane/DlgGamma.h new file mode 100644 index 0000000..9f5052f --- /dev/null +++ b/sane/DlgGamma.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include + +#include "DlgPage.h" + +// CDlgIndicator 对话框 + +class dlg_gamma: public dlg_base +{ + int exit_code_; + bool is_color_; + RECT paint_area_; + HBITMAP bkgnd_; + + typedef struct _gamma_curve + { + std::vector points; + std::vector coefs; + int drag; + int left; + int right; + COLORREF clr; + }GAMMACURVE; + GAMMACURVE rgb_gray_; + GAMMACURVE red_; + GAMMACURVE green_; + GAMMACURVE blue_; + GAMMACURVE* cur_; + + BOOL handle_message(UINT msg, WPARAM wp, LPARAM lp) override; + void handle_command(WORD code, WORD id, HANDLE ctrl); + void create_background(void); + void init_curve(GAMMACURVE* curv, COLORREF clr = RGB(255, 255, 255)); + int add_drag_point(int x, int y); + BYTE calc_value(BYTE x); + bool is_adjacent(POINT p1, POINT p2); + bool hit_test(int* x, int* y); + void draw_ellipse(HDC hdc, POINT center, int xl, int yl); + + void on_init_dlg(void); + void on_paint(HDC hdc); + void on_mouse_move(DWORD key, int x, int y); + void on_lbutton_down(int x, int y); + void on_lbutton_up(int x, int y); + void on_combo_sel_changed(int id, int sel); + +public: + dlg_gamma(HWND parent, bool color); + ~dlg_gamma(); + +public: + int do_modal(HWND parent); + void get_gamma(SANE_Gamma* gamma); + void set_gamma(const SANE_Gamma* gamma); +}; diff --git a/sane/DlgPage.cpp b/sane/DlgPage.cpp index 87108d0..a3639b9 100644 --- a/sane/DlgPage.cpp +++ b/sane/DlgPage.cpp @@ -5,6 +5,7 @@ #include "resource.h" #include "scanned_img.h" // for local_trans #include "DlgArea.h" +#include "DlgGamma.h" ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -536,6 +537,17 @@ void dlg_page::handle_command(WORD code, WORD id, HANDLE ctrl) } else if (id == dlg_page::dyn_id_base + id_custom_gamma_) { + dlg_gamma dlg(hwnd(), true); + + if (dlg.do_modal(hwnd()) == IDOK) + { + SANE_Gamma gamma = { 0 }; + unsigned int len = sizeof(gamma); + + dlg.get_gamma(&gamma); + sane_.sane_io_control_api(dev_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &gamma, &len); + } + return; } } @@ -899,6 +911,17 @@ bool dlg_page::add_control(int sn, const SANE_Option_Descriptor* desc, void* cur else if (is_sane_opt(OPTION_TITLE_QYSDQX, desc->title)) { // custom gamma control ... + int w = 78; + HWND host = wnd; + + id_custom_gamma_ = sn; + wnd = CreateWindowW(WC_BUTTONW, L"\u8bbe\u7f6e\u8272\u8c03\u66f2\u7ebf", WS_CHILD | WS_VISIBLE, pos_.x + text.cx, pos_.y - 1, w, text.cy + 3, hwnd(), NULL, g_my_inst, NULL); + text.cx += w + dlg_page::gap_x; + EnableWindow(wnd, (desc->cap& SANE_CAP_INACTIVE) == 0 && *(SANE_Bool*)cur_val == SANE_TRUE); + SetWindowLong(wnd, GWL_ID, dlg_page::dyn_id_base + sn); + SendMessage(wnd, WM_SETFONT, (WPARAM)get_font(), 1); + SetPropW(wnd, dlg_page::property_host.c_str(), host); + ctrls_.push_back(wnd); } if (size_.cx < pos_.x + text.cx) size_.cx = pos_.x + text.cx; @@ -975,31 +998,4 @@ const wchar_t* dlg_page::name(void) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// compatible_dc -compatible_dc::compatible_dc(HDC src) : src_(src), old_(NULL) -{ - HWND hwnd = WindowFromDC(src); - RECT r = { 0 }; - - if (!IsWindow(hwnd)) - hwnd = GetDesktopWindow(); - GetWindowRect(hwnd, &r); - size_.cx = r.right - r.left; - size_.cy = r.bottom - r.top; - bmp_ = CreateCompatibleBitmap(src, size_.cx, size_.cy); - hdc_ = CreateCompatibleDC(src); - old_ = (HBITMAP)SelectObject(hdc_, bmp_); - BitBlt(hdc_, 0, 0, size_.cx, size_.cy, src, 0, 0, SRCCOPY); -} -compatible_dc::~compatible_dc() -{ - BitBlt(src_, 0, 0, size_.cx, size_.cy, hdc_, 0, 0, SRCCOPY); - SelectObject(hdc_, old_); - DeleteObject(bmp_); - DeleteDC(hdc_); -} - -HDC compatible_dc::get_dc() -{ - return hdc_; -} \ No newline at end of file +// diff --git a/sane/DlgPage.h b/sane/DlgPage.h index 41d3fb1..179f6cd 100644 --- a/sane/DlgPage.h +++ b/sane/DlgPage.h @@ -121,18 +121,3 @@ public: }; -class compatible_dc -{ - HBITMAP bmp_; - HBITMAP old_; - HDC hdc_; - HDC src_; - SIZE size_; - -public: - compatible_dc(HDC src); - ~compatible_dc(); - -public: - HDC get_dc(void); -}; \ No newline at end of file diff --git a/sane/mem_dc.cpp b/sane/mem_dc.cpp new file mode 100644 index 0000000..d6b72f7 --- /dev/null +++ b/sane/mem_dc.cpp @@ -0,0 +1,39 @@ +// DlgIndicator.cpp: 实现文件 +// + +#include "mem_dc.h"" + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// + + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// compatible_dc +compatible_dc::compatible_dc(HDC src) : src_(src), old_(NULL) +{ + HWND hwnd = WindowFromDC(src); + RECT r = { 0 }; + + if (!IsWindow(hwnd)) + hwnd = GetDesktopWindow(); + GetWindowRect(hwnd, &r); + size_.cx = r.right - r.left; + size_.cy = r.bottom - r.top; + bmp_ = CreateCompatibleBitmap(src, size_.cx, size_.cy); + hdc_ = CreateCompatibleDC(src); + old_ = (HBITMAP)SelectObject(hdc_, bmp_); + BitBlt(hdc_, 0, 0, size_.cx, size_.cy, src, 0, 0, SRCCOPY); +} +compatible_dc::~compatible_dc() +{ + BitBlt(src_, 0, 0, size_.cx, size_.cy, hdc_, 0, 0, SRCCOPY); + SelectObject(hdc_, old_); + DeleteObject(bmp_); + DeleteDC(hdc_); +} + +HDC compatible_dc::get_dc() +{ + return hdc_; +} \ No newline at end of file diff --git a/sane/mem_dc.h b/sane/mem_dc.h new file mode 100644 index 0000000..0c18603 --- /dev/null +++ b/sane/mem_dc.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class compatible_dc +{ + HBITMAP bmp_; + HBITMAP old_; + HDC hdc_; + HDC src_; + SIZE size_; + +public: + compatible_dc(HDC src); + ~compatible_dc(); + +public: + HDC get_dc(void); +}; \ No newline at end of file diff --git a/sane/resource.h b/sane/resource.h index d7cf6cf..022ebaa 100644 --- a/sane/resource.h +++ b/sane/resource.h @@ -6,6 +6,7 @@ #define IDD_SETTING 103 #define IDD_PAGE 105 #define IDD_AREA 106 +#define IDD_GAMMA 107 #define IDC_EDIT_PAPER 1001 #define IDC_EDIT_IMAGE 1002 #define IDC_STATIC_PAPER 1003 @@ -15,6 +16,8 @@ #define IDC_BUTTON_RESTORE 1008 #define IDC_UNIT 1008 #define IDC_BUTTON_HELP 1009 +#define IDC_UNIT2 1009 +#define IDC_SCHEME 1009 #define IDC_EDIT_DPI 1010 #define IDC_BUTTON_RESET 1011 #define IDC_EDIT_x 1012 @@ -22,6 +25,9 @@ #define IDC_EDIT_W 1014 #define IDC_EDIT_H 1015 #define IDC_STATIC_PAINT 1016 +#define IDC_CHANNEL 1017 +#define IDC_EDIT_INPUT 1018 +#define IDC_EDIT_OUTPUT 1019 // Next default values for new objects // @@ -29,7 +35,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 108 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1017 +#define _APS_NEXT_CONTROL_VALUE 1020 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/sane/sane.rc b/sane/sane.rc index 8e4fa82..6ee8e23 100644 --- a/sane/sane.rc +++ b/sane/sane.rc @@ -106,6 +106,25 @@ BEGIN LTEXT "Static",IDC_STATIC_PAINT,9,60,159,144,NOT WS_VISIBLE | WS_BORDER END +IDD_GAMMA DIALOGEX 0, 0, 185, 224 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION +CAPTION "Զɫ" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + COMBOBOX IDC_CHANNEL,49,23,53,103,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "ʼ",IDC_BUTTON_RESET,128,23,50,14 + DEFPUSHBUTTON "ȷ",IDOK,145,204,33,13 + DEFPUSHBUTTON "ȡ",IDCANCEL,108,204,33,13 + LTEXT "ɫ",IDC_STATIC,7,7,41,8 + LTEXT "ɫͨ",IDC_STATIC,7,26,41,8 + LTEXT "Static",IDC_STATIC_PAINT,7,41,171,158,NOT WS_VISIBLE | WS_BORDER + COMBOBOX IDC_SCHEME,49,5,129,103,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_EDIT_OUTPUT,80,205,18,12,ES_AUTOHSCROLL | ES_READONLY + LTEXT "",IDC_STATIC,56,207,24,8 + LTEXT "룺",IDC_STATIC,7,207,25,8 + EDITTEXT IDC_EDIT_INPUT,33,205,18,12,ES_AUTOHSCROLL | ES_NUMBER +END + ///////////////////////////////////////////////////////////////////////////// // @@ -146,6 +165,14 @@ BEGIN TOPMARGIN, 7 BOTTOMMARGIN, 222 END + + IDD_GAMMA, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 178 + TOPMARGIN, 7 + BOTTOMMARGIN, 217 + END END #endif // APSTUDIO_INVOKED @@ -175,6 +202,11 @@ BEGIN 0 END +IDD_GAMMA AFX_DIALOG_LAYOUT +BEGIN + 0 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -192,6 +224,23 @@ BEGIN 0 END +IDD_GAMMA DLGINIT +BEGIN + IDC_CHANNEL, 0x403, 11, 0 +0xc1ba, 0xd7c3, 0xa8a3, 0x6d6d, 0xa9a3, "\000" + IDC_CHANNEL, 0x403, 13, 0 +0xa2d3, 0xe7b4, 0xa8a3, 0x6e69, 0x6863, 0xa9a3, "\000" + IDC_CHANNEL, 0x403, 11, 0 +0xf1cf, 0xd8cb, 0xa8a3, 0x7870, 0xa9a3, "\000" + IDC_SCHEME, 0x403, 11, 0 +0xc1ba, 0xd7c3, 0xa8a3, 0x6d6d, 0xa9a3, "\000" + IDC_SCHEME, 0x403, 13, 0 +0xa2d3, 0xe7b4, 0xa8a3, 0x6e69, 0x6863, 0xa9a3, "\000" + IDC_SCHEME, 0x403, 11, 0 +0xf1cf, 0xd8cb, 0xa8a3, 0x7870, 0xa9a3, "\000" + 0 +END + #endif // (壬й) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/sane/sane.vcxproj b/sane/sane.vcxproj index 5308910..3711a28 100644 --- a/sane/sane.vcxproj +++ b/sane/sane.vcxproj @@ -198,9 +198,11 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$ + + @@ -219,9 +221,11 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$ + + diff --git a/sane/sane.vcxproj.filters b/sane/sane.vcxproj.filters index ca66e29..f9d2520 100644 --- a/sane/sane.vcxproj.filters +++ b/sane/sane.vcxproj.filters @@ -57,6 +57,12 @@ sane2twain\UI + + sane2twain\UI + + + sane2twain\UI + @@ -122,6 +128,12 @@ sane2twain\UI + + sane2twain\UI + + + sane2twain\UI +