- merge the latest code from my minibranch:

- use a static image to refer to when choosing your image brightness so returning to normal (100) displays the original colours
- allow  individual colours (RGB) to be adjusted as well as adjusting them all simultaneously
- apply the chosen brightness from the dialog to the main image
- implement greyscale, so an image can be displayed in black and white
- implement inverting of colours so an image can be displayed as a negative.



svn path=/trunk/; revision=24784
This commit is contained in:
Ged Murphy
2006-11-19 19:49:45 +00:00
parent 54b8308c2b
commit fc73d244e4
9 changed files with 554 additions and 188 deletions
+127 -37
View File
@@ -1,9 +1,10 @@
#include "precomp.h"
#include <precomp.h>
VOID
AdjustBrightness(PIMAGEADJUST pImgAdj,
HDC hdcMem)
BOOL
DisplayBlackAndWhite(HWND hwnd,
HDC hdcMem,
HBITMAP hBitmap)
{
BITMAPINFO bi;
BITMAP bitmap;
@@ -11,35 +12,39 @@ AdjustBrightness(PIMAGEADJUST pImgAdj,
DWORD Count = 0;
INT i, j;
PBYTE pBits;
RECT rc;
GetObject(hBitmap,
sizeof(BITMAP),
&bitmap);
/* Bitmap header */
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = pImgAdj->ImageRect.right;
bi.bmiHeader.biHeight = pImgAdj->ImageRect.bottom;
bi.bmiHeader.biWidth = bitmap.bmWidth;
bi.bmiHeader.biHeight = bitmap.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = pImgAdj->ImageRect.right * 4 * pImgAdj->ImageRect.bottom;
bi.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * 4;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
/* Buffer */
pBits = (PBYTE)HeapAlloc(ProcessHeap,
0,
pImgAdj->ImageRect.right * 4 * pImgAdj->ImageRect.bottom);
bitmap.bmWidth * bitmap.bmHeight * 4);
if (!pBits)
return FALSE;
/* get the bits from the original bitmap */
bRes = GetDIBits(hdcMem,
pImgAdj->hBitmap,
hBitmap,
0,
pImgAdj->ImageRect.bottom,
bitmap.bmHeight,
pBits,
&bi,
DIB_RGB_COLORS);
GetObject(pImgAdj->hBitmap,
sizeof(BITMAP),
&bitmap);
for (i = 0; i < bitmap.bmHeight; i++)
{
for (j = 0; j < bitmap.bmWidth; j++)
@@ -56,35 +61,22 @@ AdjustBrightness(PIMAGEADJUST pImgAdj,
g = GetGValue(Val);
r = GetBValue(Val);
/* Red */
r += pImgAdj->RedVal;
if (r > 255) r = 255;
else if (r < 0) r = 0;
// get the average color value
Val = (r+g+b)/3;
/* Green */
g += pImgAdj->GreenVal;
if (g > 255) g = 255;
else if (g < 0) g = 0;
/* Blue */
b += pImgAdj->BlueVal;
if (b > 255) b = 255;
else if (b < 0) b = 0;
/* Store in reverse order */
Val = RGB(b, g, r);
CopyMemory(&pBits[Count],
&Val,
// assign to RGB color
Val = RGB(Val, Val, Val);
CopyMemory(&pBits[Count],
&Val,
4);
/* RGB color take 4 bytes.The high-order byte must be zero */
Count += 4;
Count+=4;
}
}
/* Set the new pixel bits */
SetDIBits(hdcMem,
pImgAdj->hBitmap,
hBitmap,
0,
bRes,
pBits,
@@ -95,7 +87,105 @@ AdjustBrightness(PIMAGEADJUST pImgAdj,
0,
pBits);
InvalidateRect(pImgAdj->hPicPrev,
&pImgAdj->ImageRect,
GetClientRect(hwnd,
&rc);
InvalidateRect(hwnd,
&rc,
FALSE);
return TRUE;
}
BOOL
DisplayInvertedColors(HWND hwnd,
HDC hdcMem,
HBITMAP hBitmap)
{
BITMAPINFO bi;
BITMAP bitmap;
BOOL bRes;
DWORD Count = 0;
INT i, j;
PBYTE pBits;
RECT rc;
GetObject(hBitmap,
sizeof(BITMAP),
&bitmap);
/* Bitmap header */
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = bitmap.bmWidth;
bi.bmiHeader.biHeight = bitmap.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * 4;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
/* Buffer */
pBits = (PBYTE)HeapAlloc(ProcessHeap,
0,
bitmap.bmWidth * bitmap.bmHeight * 4);
if (!pBits)
return FALSE;
/* get the bits from the original bitmap */
bRes = GetDIBits(hdcMem,
hBitmap,
0,
bitmap.bmHeight,
pBits,
&bi,
DIB_RGB_COLORS);
for (i = 0; i < bitmap.bmHeight; i++)
{
for (j = 0; j < bitmap.bmWidth; j++)
{
DWORD Val = 0;
INT b, g, r;
CopyMemory(&Val,
&pBits[Count],
4);
b = 255 - GetRValue(Val);
g = 255 - GetGValue(Val);
r = 255 - GetBValue(Val);
Val = RGB(b, g, r);
CopyMemory(&pBits[Count],
&Val,
4);
Count+=4;
}
}
/* Set the new pixel bits */
SetDIBits(hdcMem,
hBitmap,
0,
bRes,
pBits,
&bi,
DIB_RGB_COLORS);
HeapFree(ProcessHeap,
0,
pBits);
GetClientRect(hwnd,
&rc);
InvalidateRect(hwnd,
&rc,
FALSE);
return TRUE;
}
@@ -0,0 +1,379 @@
#include "precomp.h"
#define BASECOLOUR 100
VOID
AdjustBrightness(HBITMAP hOrigBitmap,
HBITMAP hNewBitmap,
HWND hwnd,
HDC hdcMem,
INT RedVal,
INT GreenVal,
INT BlueVal)
{
BITMAPINFO bi;
BITMAP bitmap;
BOOL bRes;
DWORD Count = 0;
INT i, j;
PBYTE pBits;
RECT rc;
GetObject(hNewBitmap,
sizeof(BITMAP),
&bitmap);
/* Bitmap header */
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = bitmap.bmWidth;
bi.bmiHeader.biHeight = bitmap.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = bitmap.bmWidth * bitmap.bmHeight * 4;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
/* Buffer */
pBits = (PBYTE)HeapAlloc(ProcessHeap,
0,
bitmap.bmWidth * bitmap.bmHeight * 4);
if (!pBits)
return;
/* get the bits from the original bitmap */
bRes = GetDIBits(hdcMem,
hOrigBitmap,
0,
bitmap.bmHeight,
pBits,
&bi,
DIB_RGB_COLORS);
for (i = 0; i < bitmap.bmHeight; i++)
{
for (j = 0; j < bitmap.bmWidth; j++)
{
DWORD Val = 0;
INT b, g, r;
CopyMemory(&Val,
&pBits[Count],
4);
/* Get pixels in reverse order */
b = GetRValue(Val);
g = GetGValue(Val);
r = GetBValue(Val);
/* Red */
r += RedVal;
if (r > 255) r = 255;
else if (r < 0) r = 0;
/* Green */
g += GreenVal;
if (g > 255) g = 255;
else if (g < 0) g = 0;
/* Blue */
b += BlueVal;
if (b > 255) b = 255;
else if (b < 0) b = 0;
/* Store in reverse order */
Val = RGB(b, g, r);
CopyMemory(&pBits[Count],
&Val,
4);
/* RGB color take 4 bytes.The high-order byte must be zero */
Count += 4;
}
}
/* Set the new pixel bits */
SetDIBits(hdcMem,
hNewBitmap,
0,
bRes,
pBits,
&bi,
DIB_RGB_COLORS);
HeapFree(ProcessHeap,
0,
pBits);
GetClientRect(hwnd,
&rc);
InvalidateRect(hwnd,
&rc,
FALSE);
}
static PIMAGEADJUST
OnInitDialog(PIMAGEADJUST pImgAdj,
HWND hDlg,
LPARAM lParam)
{
pImgAdj = HeapAlloc(ProcessHeap,
0,
sizeof(IMAGEADJUST));
if (!pImgAdj)
return NULL;
pImgAdj->Info = (PMAIN_WND_INFO)lParam;
if (!pImgAdj->Info->ImageEditors)
goto fail;
pImgAdj->hPicPrev = GetDlgItem(hDlg, IDC_PICPREVIEW);
GetClientRect(pImgAdj->hPicPrev,
&pImgAdj->ImageRect);
/* Make a static copy of the main image */
pImgAdj->hBitmap = CopyImage(pImgAdj->Info->ImageEditors->hBitmap,
IMAGE_BITMAP,
pImgAdj->ImageRect.right,
pImgAdj->ImageRect.bottom,
LR_CREATEDIBSECTION);
if (!pImgAdj->hBitmap)
goto fail;
/* Make a copy which will be updated */
pImgAdj->hPreviewBitmap = CopyImage(pImgAdj->Info->ImageEditors->hBitmap,
IMAGE_BITMAP,
pImgAdj->ImageRect.right,
pImgAdj->ImageRect.bottom,
LR_CREATEDIBSECTION);
if (!pImgAdj->hPreviewBitmap)
goto fail;
pImgAdj->RedVal = pImgAdj->BlueVal = pImgAdj->GreenVal = 0;
/* setup dialog */
SendDlgItemMessage(hDlg,
IDC_BRI_FULL,
BM_SETCHECK,
BST_CHECKED,
0);
SendDlgItemMessage(hDlg,
IDC_BRI_TRACKBAR,
TBM_SETRANGE,
TRUE,
(LPARAM)MAKELONG(0, 200));
SendDlgItemMessage(hDlg,
IDC_BRI_TRACKBAR,
TBM_SETPOS,
TRUE,
(LPARAM)BASECOLOUR);
SetDlgItemText(hDlg,
IDC_BRI_EDIT,
_T("100"));
return pImgAdj;
fail:
HeapFree(ProcessHeap,
0,
pImgAdj);
return NULL;
}
static VOID
OnDrawItem(PIMAGEADJUST pImgAdj,
LPARAM lParam)
{
LPDRAWITEMSTRUCT lpDrawItem;
HDC hdcMem;
lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
if(lpDrawItem->CtlID == IDC_PICPREVIEW)
{
SelectObject(hdcMem,
pImgAdj->hPreviewBitmap);
BitBlt(lpDrawItem->hDC,
pImgAdj->ImageRect.left,
pImgAdj->ImageRect.top,
pImgAdj->ImageRect.right,
pImgAdj->ImageRect.bottom,
hdcMem,
0,
0,
SRCCOPY);
DeleteDC(hdcMem);
}
}
static VOID
OnTrackBar(PIMAGEADJUST pImgAdj,
HWND hDlg)
{
HDC hdcMem;
DWORD TrackPos;
TrackPos = (DWORD)SendDlgItemMessage(hDlg,
IDC_BRI_TRACKBAR,
TBM_GETPOS,
0,
0);
SetDlgItemInt(hDlg,
IDC_BRI_EDIT,
TrackPos,
FALSE);
if (IsDlgButtonChecked(hDlg, IDC_BRI_FULL) == BST_CHECKED)
{
pImgAdj->RedVal = pImgAdj->GreenVal = pImgAdj->BlueVal = TrackPos - BASECOLOUR;
}
else if (IsDlgButtonChecked(hDlg, IDC_BRI_RED) == BST_CHECKED)
{
pImgAdj->RedVal = TrackPos - BASECOLOUR;
}
else if (IsDlgButtonChecked(hDlg, IDC_BRI_GREEN) == BST_CHECKED)
{
pImgAdj->GreenVal = TrackPos - BASECOLOUR;
}
else if (IsDlgButtonChecked(hDlg, IDC_BRI_BLUE) == BST_CHECKED)
{
pImgAdj->BlueVal = TrackPos - BASECOLOUR;
}
hdcMem = GetDC(pImgAdj->hPicPrev);
AdjustBrightness(pImgAdj->hBitmap,
pImgAdj->hPreviewBitmap,
pImgAdj->hPicPrev,
hdcMem,
pImgAdj->RedVal,
pImgAdj->GreenVal,
pImgAdj->BlueVal);
ReleaseDC(pImgAdj->hPicPrev, hdcMem);
}
static BOOL
OnCommand(PIMAGEADJUST pImgAdj,
HWND hDlg,
UINT uID)
{
switch (uID)
{
case IDOK:
{
HDC hdcMem;
hdcMem = GetDC(pImgAdj->Info->ImageEditors->hSelf);
AdjustBrightness(pImgAdj->Info->ImageEditors->hBitmap,
pImgAdj->Info->ImageEditors->hBitmap,
pImgAdj->Info->ImageEditors->hSelf,
hdcMem,
pImgAdj->RedVal,
pImgAdj->GreenVal,
pImgAdj->BlueVal);
ReleaseDC(pImgAdj->Info->ImageEditors->hSelf,
hdcMem);
EndDialog(hDlg,
uID);
return TRUE;
}
case IDCANCEL:
{
EndDialog(hDlg,
uID);
return TRUE;
}
}
return FALSE;
}
INT_PTR CALLBACK
BrightnessProc(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
static PIMAGEADJUST pImgAdj = NULL;
switch (message)
{
case WM_INITDIALOG:
{
pImgAdj = OnInitDialog(pImgAdj,
hDlg,
lParam);
if (!pImgAdj)
{
EndDialog(hDlg, -1);
return FALSE;
}
return TRUE;
}
case WM_DRAWITEM:
{
OnDrawItem(pImgAdj,
lParam);
return TRUE;
}
case WM_HSCROLL:
{
if (LOWORD(wParam) == TB_THUMBTRACK ||
LOWORD(wParam) == TB_ENDTRACK)
{
OnTrackBar(pImgAdj,
hDlg);
}
return TRUE;
}
case WM_COMMAND:
{
return OnCommand(pImgAdj,
hDlg,
LOWORD(wParam));
}
case WM_DESTROY:
{
if (pImgAdj)
{
if (pImgAdj->hBitmap)
DeleteObject(pImgAdj->hBitmap);
if (pImgAdj->hPreviewBitmap)
DeleteObject(pImgAdj->hPreviewBitmap);
HeapFree(ProcessHeap,
0,
pImgAdj);
}
}
}
return FALSE;
}
@@ -1,145 +0,0 @@
#include <precomp.h>
INT_PTR CALLBACK
BrightnessProc(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
static PIMAGEADJUST pImgAdj = NULL;
switch (message)
{
case WM_INITDIALOG:
{
pImgAdj = HeapAlloc(ProcessHeap,
0,
sizeof(IMAGEADJUST));
if (!pImgAdj)
return -1;
/* setup values */
pImgAdj->Info = (PMAIN_WND_INFO)lParam;
pImgAdj->hPicPrev = GetDlgItem(hDlg, IDC_PICPREVIEW);
GetClientRect(pImgAdj->hPicPrev,
&pImgAdj->ImageRect);
pImgAdj->hBitmap = CopyImage(pImgAdj->Info->ImageEditors->hBitmap,
IMAGE_BITMAP,
pImgAdj->ImageRect.right,
pImgAdj->ImageRect.bottom,
LR_CREATEDIBSECTION);
pImgAdj->OldTrackPos = 100;
pImgAdj->RedVal = pImgAdj->BlueVal = pImgAdj->GreenVal = 0;
/* setup dialog */
SendDlgItemMessage(hDlg,
IDC_BRI_FULL,
BM_SETCHECK,
BST_CHECKED,
0);
SendDlgItemMessage(hDlg,
IDC_BRI_TRACKBAR,
TBM_SETRANGE,
TRUE,
(LPARAM)MAKELONG(0, 200));
SendDlgItemMessage(hDlg,
IDC_BRI_TRACKBAR,
TBM_SETPOS,
TRUE,
(LPARAM)100);
SetDlgItemText(hDlg,
IDC_BRI_EDIT,
_T("100"));
return TRUE;
}
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT lpDrawItem;
HDC hdcMem;
lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
if(lpDrawItem->CtlID == IDC_PICPREVIEW)
{
SelectObject(hdcMem,
pImgAdj->hBitmap);
BitBlt(lpDrawItem->hDC,
pImgAdj->ImageRect.left,
pImgAdj->ImageRect.top,
pImgAdj->ImageRect.right,
pImgAdj->ImageRect.bottom,
hdcMem,
0,
0,
SRCCOPY);
DeleteDC(hdcMem);
}
return TRUE;
}
case WM_HSCROLL:
{
if (LOWORD(wParam) == TB_THUMBTRACK ||
LOWORD(wParam) == TB_ENDTRACK)
{
HDC hdcMem;
DWORD TrackPos = (DWORD)SendDlgItemMessage(hDlg,
IDC_BRI_TRACKBAR,
TBM_GETPOS,
0,
0);
/* quick hack, change all the colours regardless */
pImgAdj->RedVal = pImgAdj->BlueVal = pImgAdj->GreenVal = TrackPos - pImgAdj->OldTrackPos;
pImgAdj->OldTrackPos = TrackPos;
SetDlgItemInt(hDlg,
IDC_BRI_EDIT,
TrackPos,
FALSE);
hdcMem = GetDC(pImgAdj->hPicPrev);
AdjustBrightness(pImgAdj,
hdcMem);
ReleaseDC(pImgAdj->hPicPrev, hdcMem);
}
return TRUE;
}
case WM_COMMAND:
{
if (LOWORD(wParam) == IDOK ||
LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg,
LOWORD(wParam));
return TRUE;
}
}
break;
case WM_DESTROY:
{
DeleteObject(pImgAdj->hBitmap);
HeapFree(ProcessHeap,
0,
pImgAdj);
}
}
return FALSE;
}
@@ -4,8 +4,8 @@ typedef struct _IMAGEADJUST
PMAIN_WND_INFO Info;
HWND hPicPrev;
HBITMAP hBitmap;
HBITMAP hPreviewBitmap;
RECT ImageRect;
DWORD OldTrackPos;
INT RedVal;
INT GreenVal;
INT BlueVal;
@@ -16,10 +16,19 @@ INT_PTR CALLBACK ImagePropDialogProc(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam);
INT_PTR CALLBACK BrightnessProc(HWND hDlg,
UINT message,
WPARAM wParam,
LPARAM lParam);
VOID AdjustBrightness(PIMAGEADJUST pImgAdj,
HDC hdcMem);
VOID AdjustBrightness(HBITMAP hOrigBitmap,
HBITMAP hNewBitmap,
HWND hwnd,
HDC hdcMem,
INT RedVal,
INT GreenVal,
INT BlueVal);
BOOL DisplayBlackAndWhite(HWND hwnd, HDC hdcMem, HBITMAP hBitmap);
BOOL DisplayInvertedColors(HWND hwnd, HDC hdcMem, HBITMAP hBitmap);
@@ -18,10 +18,10 @@
<compilationunit name="unit.c">
<file>about.c</file>
<file>adjust.c</file>
<file>brightness.c</file>
<file>custcombo.c</file>
<file>floatwindow.c</file>
<file>font.c</file>
<file>imageprop.c</file>
<file>imagesoft.c</file>
<file>imgedwnd.c</file>
<file>mainwnd.c</file>
@@ -1,4 +1,4 @@
#include <precomp.h>
#include "precomp.h"
static const TCHAR szImageEditWndClass[] = TEXT("ImageSoftEditWndClass");
@@ -33,13 +33,15 @@ EditWndUpdateScrollInfo(PEDIT_WND_INFO Info)
}
static VOID
static BOOL
LoadBlankCanvas(PEDIT_WND_INFO Info)
{
/* FIXME: convert this to a DIB Section */
/* set bitmap dimensions */
Info->Width = Info->OpenInfo->New.Width;
Info->Height = Info->OpenInfo->New.Height;
return TRUE;
}
static BOOL
@@ -125,6 +127,8 @@ LoadDIBImage(PEDIT_WND_INFO Info)
static BOOL
InitEditWnd(PEDIT_WND_INFO Info)
{
//BOOL bRet = FALSE;
Info->Zoom = 100;
if (Info->OpenInfo != NULL)
@@ -50,6 +50,11 @@ BEGIN
MENUITEM "Brightness...", ID_BRIGHTNESS
MENUITEM "Contrast...", -1, GRAYED
MENUITEM "Hue/Saturation...", -1, GRAYED
POPUP "Colour"
BEGIN
MENUITEM "Black and White" ID_BLACKANDWHITE
MENUITEM "Invert Colours" ID_INVERTCOLORS
END
MENUITEM SEPARATOR
MENUITEM "Blur", -1, GRAYED
MENUITEM "Sharpen", -1, GRAYED
@@ -906,6 +906,28 @@ MainWndCommand(PMAIN_WND_INFO Info,
(LPARAM)Info);
break;
case ID_BLACKANDWHITE:
{
if (Info->ImageEditors)
{
DisplayBlackAndWhite(Info->ImageEditors->hSelf,
Info->ImageEditors->hDCMem,
Info->ImageEditors->hBitmap);
}
}
break;
case ID_INVERTCOLORS:
{
if (Info->ImageEditors)
{
DisplayInvertedColors(Info->ImageEditors->hSelf,
Info->ImageEditors->hDCMem,
Info->ImageEditors->hBitmap);
}
}
break;
case ID_EXIT:
SendMessage(Info->hSelf,
WM_CLOSE,
@@ -80,6 +80,8 @@
/* Adjust */
#define ID_BRIGHTNESS 2100
#define ID_BLACKANDWHITE 2101
#define ID_INVERTCOLORS 2102
#define ID_ABOUT 2400