添加自定义GAMMA界面

This commit is contained in:
gb 2022-06-24 17:01:00 +08:00
parent 1e762283c6
commit c55d6189d1
11 changed files with 883 additions and 47 deletions

View File

@ -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\u7c73mm");
SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u82f1\u5bf8inch");
SendMessageW(get_item(IDC_UNIT), CB_ADDSTRING, 0, (LPARAM)L"\u50cf\u7d20px");
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()

668
sane/DlgGamma.cpp Normal file
View File

@ -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 <math.h>
namespace calc
{
void solve_matrix(double** a, int n, std::vector<double>& 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<double> coefs_from_points(const std::vector<POINT>& pt)
{
std::vector<double> 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);
}

57
sane/DlgGamma.h Normal file
View File

@ -0,0 +1,57 @@
#pragma once
#include <Windows.h>
#include <string>
#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<POINT> points;
std::vector<double> 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);
};

View File

@ -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_;
}
//

View File

@ -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);
};

39
sane/mem_dc.cpp Normal file
View File

@ -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_;
}

19
sane/mem_dc.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <Windows.h>
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);
};

View File

@ -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

View File

@ -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
/////////////////////////////////////////////////////////////////////////////

View File

@ -198,9 +198,11 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$
<ClCompile Include="..\..\code_device\hgsane\sane_hg_mdw.cpp" />
<ClCompile Include="..\..\code_device\hgsane\sane_option.cpp" />
<ClCompile Include="DlgArea.cpp" />
<ClCompile Include="DlgGamma.cpp" />
<ClCompile Include="DlgIndicator.cpp" />
<ClCompile Include="DlgPage.cpp" />
<ClCompile Include="DlgSetting.cpp" />
<ClCompile Include="mem_dc.cpp" />
<ClCompile Include="sane_option_trans.cpp" />
<ClCompile Include="scanned_img.cpp" />
<ClCompile Include="scanner.cpp" />
@ -219,9 +221,11 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$
<ClInclude Include="..\..\sdk\include\sane\sane_ex.h" />
<ClInclude Include="..\..\sdk\include\sane\sane_option_definitions.h" />
<ClInclude Include="DlgArea.h" />
<ClInclude Include="DlgGamma.h" />
<ClInclude Include="DlgIndicator.h" />
<ClInclude Include="DlgPage.h" />
<ClInclude Include="DlgSetting.h" />
<ClInclude Include="mem_dc.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="s2t_api.h" />
<ClInclude Include="sane_option_trans.h" />

View File

@ -57,6 +57,12 @@
<ClCompile Include="DlgArea.cpp">
<Filter>sane2twain\UI</Filter>
</ClCompile>
<ClCompile Include="mem_dc.cpp">
<Filter>sane2twain\UI</Filter>
</ClCompile>
<ClCompile Include="DlgGamma.cpp">
<Filter>sane2twain\UI</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\code_device\hgsane\cJSON.h">
@ -122,6 +128,12 @@
<ClInclude Include="DlgArea.h">
<Filter>sane2twain\UI</Filter>
</ClInclude>
<ClInclude Include="mem_dc.h">
<Filter>sane2twain\UI</Filter>
</ClInclude>
<ClInclude Include="DlgGamma.h">
<Filter>sane2twain\UI</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="sane.def">