TNB Library
TnbBitmapImage.h
[詳解]
1#pragma once
11#include "TnbBitmapHandle.h"
12#ifndef _WIN32_WCE
13 #pragma comment(lib, "Msimg32.lib")
14#endif
15#ifndef _TnbDOXYGEN //Document作成用シンボル
16 #ifndef AC_SRC_ALPHA
17 #define AC_SRC_ALPHA 0x01
18 #endif
19#endif
20
21
22
23//TNB Library
24namespace TNB
25{
26
27
28
74{
75public:
76
93 {
95 struct TParam
96 {
97 SIZE size;
99 TParam(const SIZE& s) : size(s), work(s.cx * s.cy)
100 {
101 }
102 TParam(void)
103 {
104 size.cx = size.cy = 0;
105 }
106 };
107 CPointerHandleT<TParam> m_pParam;
108 public:
110 CRawData(void) : m_pParam(new TParam()) { }
115 CRawData(const SIZE& s) : m_pParam(new TParam(s)) { }
121 bool IsValid(void) const { return m_pParam->size.cx != 0; }
126 const SIZE& GetSize(void) const { return m_pParam->size; }
131 size_t GetLineBytes(void) const { return m_pParam->size.cx * sizeof(RGBQUAD); }
139 RGBQUAD* Refer(void) { return m_pParam->work; }
147 const RGBQUAD* Refer(void) const { return m_pParam->work; }
155 RGBQUAD* operator[](INDEX y)
156 {
157 if ( y >= static_cast<UINT>(m_pParam->size.cy) ) { return NULL; }
158 return Refer() + (m_pParam->size.cy - y - 1) * m_pParam->size.cx;
159 }
167 const RGBQUAD* operator[](INDEX y) const
168 {
169 if ( y >= static_cast<UINT>(m_pParam->size.cy) ) { return NULL; }
170 return Refer() + (m_pParam->size.cy - y - 1) * m_pParam->size.cx;
171 }
172 };
173
175 CBitmapImage(void) : m_bmp(), m_pRgb(NULL), m_backDC(NULL), m_backBmp(NULL)
176 , m_hWnd(NULL), m_nStretchMode(DEFAULT_STRETCHMODE)
177 {
178 m_size.cx = 0;
179 m_size.cy = 0;
180 }
181
186 CBitmapImage(CBitmapHandle bmp) : m_bmp(), m_pRgb(NULL), m_backDC(NULL), m_backBmp(NULL)
187 , m_hWnd(NULL), m_nStretchMode(DEFAULT_STRETCHMODE)
188 {
189 m_Set(bmp);
190 }
191
198 CBitmapImage(const CBitmapImage& other) : m_bmp(other.m_bmp), m_pRgb(other.m_pRgb), m_backDC(NULL), m_backBmp(NULL)
199 , m_hWnd(other.m_hWnd), m_size(other.m_size), m_nStretchMode(other.m_nStretchMode)
200 {
201 }
202
211 {
212 m_ReleaseDC();
213 m_bmp = other.m_bmp;
214 m_pRgb = other.m_pRgb;
215 m_size = other.m_size;
216 m_hWnd = other.m_hWnd;
217 m_nStretchMode = other.m_nStretchMode;
218 return *this;
219 }
220
222 virtual ~CBitmapImage(void)
223 {
224 Empty();
225 }
226
232 operator CBitmapHandle(void)
233 {
234 return m_bmp;
235 }
236
243 {
244 return m_bmp;
245 }
246
252 void SetWorkWnd(HWND h)
253 {
254 m_hWnd = h;
255 }
256
280 void SetStretchBltMode(int nStretchMode)
281 {
282 m_nStretchMode = nStretchMode;
283 if ( m_backDC != NULL )
284 {
285 ::SetStretchBltMode(m_backDC, m_nStretchMode);
286 ::SetBrushOrgEx(m_backDC, 0, 0, NULL);
287 }
288 }
289
294 void Empty(void)
295 {
296 m_ReleaseDC();
297 m_bmp.Null();
298 m_pRgb = NULL;
299 }
300
306 bool IsEmpty(void) const
307 {
308 return m_bmp.IsNull();
309 }
310
316 const SIZE& GetSize(void) const
317 {
318 ASSERT0( ! IsEmpty(), "CBitmapImage::GetSize()", "画像を持っていないオブジェクトからサイズを取得しようとしています。" );
319 return m_size;
320 }
321
328 bool GetBitmapInfo(BITMAPINFOHEADER& _head) const
329 {
330 BITMAP bp;
331 if ( ::GetObject(m_bmp, sizeof(BITMAP), &bp) > 0 )
332 {
333 ::ZeroMemory(&_head, sizeof(BITMAPINFOHEADER));
334 _head.biSize = sizeof(BITMAPINFOHEADER);
335 _head.biWidth = bp.bmWidth;
336 _head.biHeight = bp.bmHeight;
337 _head.biPlanes = bp.bmPlanes;
338 _head.biBitCount = bp.bmBitsPixel;
339 _head.biCompression = BI_RGB;
340 _head.biSizeImage = bp.bmWidthBytes * bp.bmHeight;
341 return true;
342 }
343 return false;
344 }
345
352 CBitmapImage Clone(void) const
353 {
354 CBitmapImage bi;
355 bi.Set(m_bmp);
356 return bi;
357 }
358
368 {
369 return m_Set(bmp);
370 }
371
379 {
380 CBitmapHandle h = m_bmp;
381 Empty();
382 return h;
383 }
384
394 bool Set(int cx, int cy, COLORREF color = CLR_INVALID)
395 {
396 CWorkDC workDC(m_hWnd);
397 RGBQUAD* pRgb = NULL;
398 HBITMAP h = ms_CreateBitmap(pRgb, workDC, cx, cy);
399 if ( h != NULL && m_Set(h, pRgb) )
400 {
401 ASSERT( m_pRgb != NULL );
402 if ( Fill(color) )
403 {
404 return true;
405 }
406 }
407 Empty();
408 return false;
409 }
410
422 bool SetEx(HDC hDC, int cx, int cy, COLORREF color = CLR_INVALID)
423 {
424 HBITMAP h = ::CreateCompatibleBitmap(hDC, cx, cy);
425 bool r = ( h != NULL && m_Set(h) );
426 if ( r )
427 {
428 r = Fill(color);
429 }
430 return r;
431 }
432
442 {
443 RGBQUAD* pRgb = NULL;
444 return m_Set(CBitmapHandle::Create32bitDibSection(bmp, pRgb), pRgb);
445 }
446
456 bool Set(const CBitmapImage& bmpimg, int cx = 0, int cy = 0)
457 {
458 if ( cx == 0 && cy == 0 )
459 {
460 return Set(bmpimg.m_bmp);
461 }
462 bmpimg.m_CheckSize(cx, cy);
463 if ( Set(cx, cy) )
464 {
465 HDC dc = GetDC();
466 if ( dc != NULL )
467 {
468 bool r = bmpimg.StretchBlt(dc, 0, 0, SRCCOPY, cx, cy);
469 ReleaseDC();
470 return r;
471 }
472 }
473 Empty();
474 return false;
475 }
476
484 bool _deprecated Set(const CRawData& rawData)
485 {
486 Empty();
487 if ( rawData.IsValid() )
488 {
489 const SIZE& size = rawData.GetSize();
490 if ( Set(size.cx, size.cy) )
491 {
492 ASSERT( m_pRgb != NULL );
493 MemCopy(m_pRgb, rawData.Refer(), m_size.cy * m_size.cx);
494 }
495 }
496 return ! m_bmp.IsNull();
497 }
498
509 bool SetFromDC(HDC hdc, const RECT& rect, int cx = 0, int cy = 0)
510 {
511 Empty();
512 SIZE s;
513 if ( ms_CheckSize(s, rect) && Set(s.cx, s.cy) )
514 {
515 HDC dc = GetDC();
516 if ( dc != NULL )
517 {
518 if ( cx <= 0 || cy <= 0 )
519 {
520 ::BitBlt(dc, 0, 0, s.cx, s.cy, hdc, rect.left, rect.top, SRCCOPY); //DCから取り出し
521 }
522 else
523 {
524 ::StretchBlt(dc, 0, 0, cx, cy, hdc, rect.left, rect.top, s.cx, s.cy, SRCCOPY); //DCから取り出し
525 }
526 ReleaseDC();
527 return true;
528 }
529 }
530 Empty();
531 return false;
532 }
533
541 bool SetFromIcon(HICON hIcon, COLORREF backColor)
542 {
543 Empty();
544 ICONINFO ii;
545 ::GetIconInfo(hIcon, &ii);
546 CBitmapImage biColor;
547 CBitmapImage biMask;
548 if ( ! biColor.Set(ii.hbmColor) || ! biMask.Set(ii.hbmMask) )
549 {
550 return false;
551 }
552 const SIZE& size = biColor.GetSize();
553 bool r = Set(size.cx, size.cy, backColor);
554 r &= Insert(0, 0, biMask, SRCAND);
555 r &= Insert(0, 0, biColor, SRCPAINT);
556 if ( ! r )
557 {
558 Empty();
559 }
560 return r;
561 }
562
576 bool SetFromClient(HWND hWnd, const RECT& rect, COLORREF backColor = CLR_INVALID)
577 {
578 if ( Set(rect.right - rect.left, rect.bottom - rect.top, backColor) )
579 {
580#ifndef _WIN32_WCE
581 HDC dc = GetDC();
582 if ( dc != NULL )
583 {
584 ::SetWindowOrgEx(dc, rect.left, rect.top, NULL);
585 WPARAM w = reinterpret_cast<WPARAM>(dc);
586 if ( backColor == CLR_AUTOSELECT )
587 {
588 ::SendMessage(hWnd, WM_ERASEBKGND, w, 0);
589 }
590 ::SendMessage(hWnd, WM_PRINTCLIENT, w, PRF_CLIENT);
591 ReleaseDC();
592 return true;
593 }
594#else
595 return true;
596#endif
597 }
598 Empty();
599 return false;
600 }
601
613 bool SetFromClient(HWND hWnd, COLORREF backColor = CLR_INVALID)
614 {
615 RECT rect;
616 if ( ::GetClientRect(hWnd, &rect) )
617 {
618 return SetFromClient(hWnd, rect, backColor);
619 }
620 Empty();
621 return false;
622 }
623
624 #ifndef _WIN32_WCE
651 bool SetFromWindow(HWND hWnd, COLORREF backColor = CLR_INVALID,
652 LPARAM mode = PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED)
653 {
654 RECT rect;
655 if ( ::GetWindowRect(hWnd, &rect) && Set(rect.right - rect.left, rect.bottom - rect.top, backColor) )
656 {
657 HDC dc = GetDC();
658 if ( dc != NULL )
659 {
660 ::SendMessage(hWnd, WM_PRINT, reinterpret_cast<WPARAM>(dc), mode);
661 ReleaseDC();
662 return true;
663 }
664 }
665 Empty();
666 return false;
667 }
668
683 bool InsertEx(int x, int y, HBITMAP hBitmap, UINT uExFlag = DSS_NORMAL)
684 {
685 HDC dc = GetDC();
686 if ( dc != NULL )
687 {
688 LPARAM l = reinterpret_cast<LPARAM>(hBitmap);
689 bool r = !! ::DrawState(dc, NULL, NULL, l, 0, x, y, 0, 0, DST_BITMAP | uExFlag);
690 ReleaseDC();
691 return r;
692 }
693 return false;
694 }
695 #endif
696
748 bool Insert(int x, int y, const CBitmapImage& bmpimg, DWORD raster = SRCCOPY, int cx = 0, int cy = 0)
749 {
750 if ( ! IsEmpty() && ! bmpimg.IsEmpty() )
751 {
752 HDC dc = GetDC();
753 if ( dc != NULL )
754 {
755 bool r = bmpimg.StretchBlt(dc, x, y, raster, cx, cy);
756 ReleaseDC();
757 return r;
758 }
759 }
760 return false;
761 }
762
778 bool InsertOnTransparent(int x, int y, const CBitmapImage& bmpimg, COLORREF color = CLR_AUTOSELECT, int cx = 0, int cy = 0)
779 {
780 if ( ! IsEmpty() && ! bmpimg.IsEmpty() )
781 {
782 HDC dc = GetDC();
783 if ( dc != NULL )
784 {
785 bool r = bmpimg.TransparentBit(dc, x, y, color, cx, cy);
786 ReleaseDC();
787 return r;
788 }
789 }
790 return false;
791 }
792
807 bool InsertOnAlphaBlend(int x, int y, const CBitmapImage& bmpimg, int parsent = 100, int cx = 0, int cy = 0)
808 {
809 if ( ! IsEmpty() && ! bmpimg.IsEmpty() )
810 {
811 HDC dc = GetDC();
812 if ( dc != NULL )
813 {
814 bool r = bmpimg.AlphaBlend(dc, x, y, parsent, cx, cy);
815 ReleaseDC();
816 return r;
817 }
818 }
819 return false;
820 }
821
838 bool InsertOnSemitransparect(int x, int y, const CBitmapImage& bmpimg, int parsent = 100, COLORREF color = CLR_AUTOSELECT)
839 {
840 if ( ! IsEmpty() && ! bmpimg.IsEmpty() )
841 {
842 HDC dc = GetDC();
843 if ( dc != NULL )
844 {
845 bool r = bmpimg.SemitransparectBlt(dc, x, y, parsent, color);
846 ReleaseDC();
847 return r;
848 }
849 }
850 return false;
851 }
852
861 bool Fill(COLORREF color, const RECT& rect)
862 {
863 HDC dc = GetDC();
864 if ( dc != NULL )
865 {
866 COLORREF c = ::GetBkColor(dc);
867 ::SetBkColor(dc, color);
868 bool r = !! ::ExtTextOut(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
869 ::SetBkColor(dc, c);
870 ReleaseDC();
871 return r;
872 }
873 return false;
874 }
875
883 bool Fill(COLORREF color)
884 {
885 RECT rect = { 0, 0, m_size.cx, m_size.cy };
886 return Fill(color, rect);
887 }
888
891 {
894 };
895
906 bool GradationFill(COLORREF color1, COLORREF color2, EDirection direction, const RECT* pRect = NULL)
907 {
908 HDC dc = GetDC();
909 if ( dc != NULL )
910 {
911 SIZE size = m_size;
912 if ( pRect != NULL )
913 {
914 size.cx = pRect->right - pRect->left;
915 size.cy = pRect->bottom - pRect->top;
916 }
917 int c = 0;
918 if ( direction == Horizontal )
919 {
920 c = size.cx;
921 size.cy = 1;
922 }
923 else
924 {
925 c = size.cy;
926 size.cx = 1;
927 }
928 if ( size.cx > 0 && size.cy > 0 )
929 {
930 CBitmapImage bi;
931 bi.Set(size.cx, size.cy);
932 ASSERT( bi.m_pRgb != NULL );
933 int r1 = GetRValue(color1);
934 int g1 = LOBYTE((color1 >> 8) & 0xFF);
935 int b1 = GetBValue(color1);
936 int r2 = GetRValue(color2);
937 int g2 = LOBYTE((color2 >> 8) & 0xFF);
938 int b2 = GetBValue(color2);
939 int a = c - 1;
940 if ( a <= 0 ) { a = 1; }
941 loop ( i, c )
942 {
943 bi.m_pRgb[i].rgbRed = static_cast<BYTE>((r1 * (a - i) / a) + (r2 * i / a));
944 bi.m_pRgb[i].rgbGreen = static_cast<BYTE>((g1 * (a - i) / a) + (g2 * i / a));
945 bi.m_pRgb[i].rgbBlue = static_cast<BYTE>((b1 * (a - i) / a) + (b2 * i / a));
946 }
947 bool r = false;
948 if ( pRect != NULL )
949 {
950 ::SetBrushOrgEx(dc, pRect->left, pRect->top, NULL);
951 r = bi.DrawTile(dc, *pRect);
952 ::SetBrushOrgEx(dc, 0, 0, NULL);
953 }
954 else
955 {
956 RECT rect = { 0, 0, m_size.cx, m_size.cy };
957 r = bi.DrawTile(dc, rect);
958 }
959 ReleaseDC();
960 return r;
961 }
962 }
963 return false;
964 }
965
976 bool GradationFill(COLORREF color1, COLORREF color2, bool boIsHorizontal, const RECT* pRect = NULL)
977 {
978 EDirection d = boIsHorizontal ? Horizontal : Vertical;
979 return GradationFill(color1, color2, d, pRect);
980 }
981
993 bool GradientFill(const PTRIVERTEX pVertex, DWORD dwNumVertex, const PGRADIENT_RECT pMesh, DWORD dwNumMesh, bool boIsHorizontal)
994 {
995 HDC dc = GetDC();
996 if ( dc != NULL )
997 {
998 DWORD dwMode = boIsHorizontal ? GRADIENT_FILL_RECT_H : GRADIENT_FILL_RECT_V;
999 bool r = !! ::GradientFill(dc, pVertex, dwNumVertex, pMesh, dwNumMesh, dwMode);
1000 ReleaseDC();
1001 return r;
1002 }
1003 return false;
1004 }
1005
1013 bool CustomizeAlpha(BYTE alpha)
1014 {
1015 if ( m_CheckDib() )
1016 {
1017 loop ( i, m_size.cx * m_size.cy )
1018 {
1019 m_pRgb[i].rgbReserved = alpha;
1020 }
1021 return true;
1022 }
1023 return false;
1024 }
1025
1035 bool CustomizeAlpha(BYTE alpha, COLORREF colorEx, BYTE alphaEx)
1036 {
1037 if ( m_CheckDib() )
1038 {
1039 colorEx = (colorEx & 0x0000ff00) | (colorEx & 0x00ff0000) >> 16 | (colorEx & 0x000000ff) << 16;
1040 RGBQUAD* pRgba = m_pRgb;
1041 loop ( i, m_size.cx * m_size.cy )
1042 {
1043 if ( (*(reinterpret_cast<COLORREF*>(pRgba)) & 0x00FFFFFF) == colorEx )
1044 {
1045 pRgba->rgbReserved = alphaEx;
1046 }
1047 else
1048 {
1049 pRgba->rgbReserved = alpha;
1050 }
1051 pRgba++;
1052 }
1053 return true;
1054 }
1055 return false;
1056 }
1057
1066 {
1067 CBitmapImage bi;
1068 if ( ! bi.Set(bmp) )
1069 {
1070 return false;
1071 }
1072 if ( ! m_CheckDib() || ! bi.m_CheckDib() )
1073 {
1074 return false;
1075 }
1076 if ( bi.m_size.cx < m_size.cx || bi.m_size.cy < m_size.cy )
1077 {
1078 return false;
1079 }
1080 loop ( y, m_size.cy )
1081 {
1082 RGBQUAD* pSrc = bi.GetRgbDataPtr(y);
1083 RGBQUAD* pBase = GetRgbDataPtr(y);
1084 loop ( x, m_size.cx )
1085 {
1086 pBase->rgbReserved = pSrc->rgbRed;
1087 pSrc++;
1088 pBase++;
1089 }
1090 }
1091 return true;
1092 }
1093
1102 int ChangePixelColor(COLORREF targetColor, COLORREF drawColor)
1103 {
1104 if ( m_CheckDib() )
1105 {
1106 int rc = 0;
1107 targetColor = (targetColor & 0x0000ff00) | (targetColor & 0x00ff0000) >> 16 | (targetColor & 0x000000ff) << 16;
1108 drawColor = (drawColor & 0x0000ff00) | (drawColor & 0x00ff0000) >> 16 | (drawColor & 0x000000ff) << 16;
1109 COLORREF* pRgba = reinterpret_cast<COLORREF*>(m_pRgb);
1110 loop ( i, m_size.cx * m_size.cy )
1111 {
1112 if ( ((*pRgba) & 0x00FFFFFF) == targetColor )
1113 {
1114 *pRgba = drawColor;
1115 rc++;
1116 }
1117 pRgba++;
1118 }
1119 return rc;
1120 }
1121 return -1;
1122 }
1123
1134 bool ChangePixelColor(COLORREF r, COLORREF g, COLORREF b)
1135 {
1136 struct TRGB
1137 {
1138 BYTE rgbRed;
1139 BYTE rgbGreen;
1140 BYTE rgbBlue;
1141 BYTE rgbReserved;
1142 };
1143 if ( m_CheckDib() )
1144 {
1145 TRGB* R = reinterpret_cast<TRGB*>(&r);
1146 TRGB* G = reinterpret_cast<TRGB*>(&g);
1147 TRGB* B = reinterpret_cast<TRGB*>(&b);
1148 RGBQUAD* P = m_pRgb;
1149 loop ( i, m_size.cx * m_size.cy )
1150 {
1151 int rr = P->rgbRed * R->rgbRed + P->rgbGreen * R->rgbGreen + P->rgbBlue * R->rgbBlue;
1152 int gg = P->rgbRed * G->rgbRed + P->rgbGreen * G->rgbGreen + P->rgbBlue * G->rgbBlue;
1153 int bb = P->rgbRed * B->rgbRed + P->rgbGreen * B->rgbGreen + P->rgbBlue * B->rgbBlue;
1154 P->rgbRed = static_cast<BYTE>(min(rr / 255, 255));
1155 P->rgbGreen = static_cast<BYTE>(min(gg / 255, 255));
1156 P->rgbBlue = static_cast<BYTE>(min(bb / 255, 255));
1157 P++;
1158 }
1159 return true;
1160 }
1161 return false;
1162 }
1163
1172 CBitmapImage Cut(const RECT& rect, int cx = 0, int cy = 0) const
1173 {
1174 CBitmapImage bi;
1175 SIZE s;
1176 if ( ms_CheckSize(s, rect) )
1177 {
1178 ms_CheckSize(cx, cy, s);
1179 CWorkDC workDC(m_hWnd);
1180 CTempDC dc(workDC, m_bmp);
1181 bi.Set(cx, cy);
1182 HDC tempDc = bi.GetDC();
1183 if ( tempDc != NULL )
1184 {
1185 bool r = !! ::StretchBlt(tempDc, 0, 0, cx, cy, dc, rect.left, rect.top, s.cx, s.cy, SRCCOPY);
1186 bi.ReleaseDC();
1187 if ( ! r )
1188 {
1189 bi.Empty();
1190 }
1191 }
1192 else
1193 {
1194 bi.Empty();
1195 }
1196 }
1197 return bi;
1198 }
1199
1208 HDC GetDC(void)
1209 {
1210 if ( ! IsEmpty() && m_backDC == NULL )
1211 {
1212 CWorkDC workDC(m_hWnd);
1213 m_backDC = ::CreateCompatibleDC(workDC);
1214 m_backBmp = ::SelectObject(m_backDC, m_bmp);
1215 ::SetStretchBltMode(m_backDC, m_nStretchMode);
1216 ::SetBrushOrgEx(m_backDC, 0, 0, NULL);
1217 return m_backDC;
1218 }
1219 return NULL;
1220 }
1221
1228 bool ReleaseDC(void)
1229 {
1230 if ( m_backDC != NULL )
1231 {
1232 m_ReleaseDC();
1233 return true;
1234 }
1235 return false;
1236 }
1237
1246 HBITMAP CreateMaskBitmap(bool boIsReverse = false, COLORREF transColor = CLR_AUTOSELECT) const
1247 {
1248 HRGN rgn = CreateRgn(transColor);
1249 if ( rgn != NULL )
1250 {
1251 HBITMAP hMonoBitmap = ::CreateBitmap(m_size.cx, m_size.cy, 1, 1, NULL);
1252 CTempBitmapDC hdc(m_hWnd, hMonoBitmap);
1253 RGBQUAD aColors[2] = { {0, 0, 0, 0}, {255, 255, 255, 0} };
1254 ::SetDIBColorTable(hdc, 0, 2, aColors);
1255 RECT rect = { 0, 0, m_size.cx, m_size.cy };
1256 if ( ! boIsReverse )
1257 {
1258 ::FillRect(hdc, &rect, static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH)));
1259 ::FillRgn(hdc, rgn, static_cast<HBRUSH>(::GetStockObject(BLACK_BRUSH)));
1260 }
1261 else
1262 {
1263 ::FillRect(hdc, &rect, static_cast<HBRUSH>(::GetStockObject(BLACK_BRUSH)));
1264 ::FillRgn(hdc, rgn, static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH)));
1265 }
1266 _DeleteObject(rgn);
1267 return hMonoBitmap;
1268 }
1269 return NULL;
1270 }
1271
1278 CRawData _deprecated CreateRawData(void) const
1279 {
1280 if ( ! IsEmpty() && m_backDC == NULL )
1281 {
1282 if ( m_pRgb == NULL )
1283 {
1284 RGBQUAD* pRgb = NULL;
1286 if ( pRgb != NULL )
1287 {
1288 CRawData data(m_size);
1289 MemCopy(data.Refer(), pRgb, m_size.cx * m_size.cy);
1290 return data;
1291 }
1292 }
1293 else
1294 {
1295 CRawData data(m_size);
1296 MemCopy(data.Refer(), m_pRgb, m_size.cx * m_size.cy);
1297 return data;
1298 }
1299 }
1300 return CRawData();
1301 }
1302
1312 HRGN CreateRgn(COLORREF transColor = CLR_AUTOSELECT) const
1313 {
1314 if ( transColor == CLR_INVALID )
1315 {
1316 return ::CreateRectRgn(0, 0, m_size.cx, m_size.cy);
1317 }
1318 CBitmapImage bi(*this);
1319 if ( ! bi.m_CheckDib() )
1320 {
1321 return NULL;
1322 }
1323 HRGN hRgn = NULL; // リージョンハンドル
1324 transColor = (transColor & 0xff00ff00) |
1325 (transColor & 0x00ff0000) >> 16 |
1326 (transColor & 0x000000ff) << 16;
1327 //
1328 CWorkMem rgbWork(sizeof(RGNDATAHEADER) + sizeof(RECT) * bi.m_size.cx * bi.m_size.cy);
1329 LPRGNDATA pRgnData = reinterpret_cast<LPRGNDATA>(rgbWork.Ref());
1330 LPRECT pRect = reinterpret_cast<LPRECT>(pRgnData->Buffer);
1331 int nCntRect = 0; // 四角形リージョンの数
1332 loop_dn ( y, bi.m_size.cy )
1333 {
1334 const COLORREF* pScanData = reinterpret_cast<const COLORREF*>(bi.GetRgbDataPtr(y));
1335 if ( transColor == CLR_AUTOSELECT )
1336 {
1337 transColor = pScanData[0];
1338 }
1339 // 一行分の透明/非透明の変化点を調査する
1340 loop ( x, bi.m_size.cx )
1341 {
1342 if ( pScanData[x] == transColor )
1343 {
1344 continue;
1345 }
1346 // その位置から透明までの長さをカウントする
1347 pRect->left = down_cast<long>(x);
1348 for ( ; x < static_cast<size_t>(bi.m_size.cx); x++ )
1349 {
1350 if ( pScanData[x] == transColor ) { break; }
1351 }
1352 // その情報を四角形情報として追加する
1353 pRect->right = static_cast<LONG>(x);
1354 pRect->top = static_cast<LONG>(y);
1355 pRect->bottom = static_cast<LONG>(y + 1);
1356 pRect++;
1357 nCntRect++;
1358 }
1359 }
1360 // 書きためた四角形情報を元にリージョンを作成する
1361 pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
1362 pRgnData->rdh.iType = RDH_RECTANGLES;
1363 pRgnData->rdh.nRgnSize = sizeof(RGNDATAHEADER) + sizeof(RECT) * nCntRect;
1364 pRgnData->rdh.nCount = nCntRect;
1365 pRgnData->rdh.rcBound.top = 0;
1366 pRgnData->rdh.rcBound.left = 0;
1367 pRgnData->rdh.rcBound.bottom = bi.m_size.cy;
1368 pRgnData->rdh.rcBound.right = bi.m_size.cx;
1369 hRgn = ::ExtCreateRegion(NULL, pRgnData->rdh.nRgnSize, pRgnData);
1370 if ( hRgn == NULL )
1371 {
1372 _GetLastError("ExtCreateRegion");
1373 }
1374 return hRgn;
1375 }
1376
1386 bool Draw(HDC hdc, int x = 0, int y = 0) const
1387 {
1388 HBITMAP h = m_bmp;
1389 return CBitmapHandle::Draw(hdc, h, x, y);
1390 }
1391
1400 bool Draw(HDC hdc, const POINT& po) const
1401 {
1402 return Draw(hdc, po.x, po.y);
1403 }
1404
1414 bool DrawTile(HDC hdc, const RECT& rect) const
1415 {
1416 if ( ! IsEmpty() )
1417 {
1418 HBRUSH brush = ::CreatePatternBrush(m_bmp);
1419 bool r = !! ::FillRect(hdc, &rect, brush);
1420 _DeleteObject(brush);
1421 return r;
1422 }
1423 return false;
1424 }
1425
1472 bool BitBlt(HDC hdc, int x, int y, DWORD raster = SRCCOPY) const
1473 {
1474 if ( ! IsEmpty() )
1475 {
1476 CTempBitmapDC dc(m_hWnd, m_bmp);
1477 return !! ::BitBlt(hdc, x, y, m_size.cx, m_size.cy, dc, 0, 0, raster);
1478 }
1479 return false;
1480 }
1481
1499 bool StretchBlt(HDC hdc, int x, int y, DWORD raster = SRCCOPY, int cx = 0, int cy = 0) const
1500 {
1501 if ( ! IsEmpty() )
1502 {
1503 m_CheckSize(cx, cy);
1504 CTempBitmapDC dc(m_hWnd, m_bmp);
1505 return !! ::StretchBlt(hdc, x, y, cx, cy, dc, 0, 0, m_size.cx, m_size.cy, raster);
1506 }
1507 return false;
1508 }
1509
1525 bool TransparentBit(HDC hdc, int x, int y, COLORREF color = CLR_AUTOSELECT, int cx = 0, int cy = 0) const
1526 {
1527 if ( ! IsEmpty() )
1528 {
1529 m_CheckSize(cx, cy);
1530 CTempBitmapDC dc(m_hWnd, m_bmp);
1531 color = m_CheckColor(dc, color);
1532 if ( ! IS_RGBVALUE(color) )
1533 {
1534 return !! ::StretchBlt(hdc, x, y, cx, cy, dc, 0, 0, m_size.cx, m_size.cy, SRCCOPY);
1535 }
1536 return !! ::TransparentBlt(hdc, x, y, cx, cy, dc, 0, 0, m_size.cx, m_size.cy, color);
1537 }
1538 return false;
1539 }
1540
1555 bool AlphaBlend(HDC hdc, int x, int y, int parsent = 100, int cx = 0, int cy = 0) const
1556 {
1557 if ( ! IsEmpty() )
1558 {
1559 m_CheckSize(cx, cy);
1560 CTempBitmapDC dc(m_hWnd, m_bmp);
1561 BLENDFUNCTION blend;
1562 blend.BlendOp = AC_SRC_OVER;
1563 blend.BlendFlags = 0;
1564 if ( parsent >= 0 )
1565 {
1566 blend.SourceConstantAlpha = static_cast<BYTE>(parsent * 255 / 100);
1567 blend.AlphaFormat = 0;
1568 }
1569 else
1570 {
1571 blend.SourceConstantAlpha = 255;
1572 blend.AlphaFormat = AC_SRC_ALPHA; //アルファチャネル使用
1573 }
1574 #if ! defined(_WIN32_WCE) || (_WIN32_WCE > 0x500)
1575 return !! ::AlphaBlend(hdc, x, y, cx, cy, dc, 0, 0, m_size.cx, m_size.cy, blend);
1576 #endif
1577 }
1578 return false;
1579 }
1580
1596 bool SemitransparectBlt(HDC hdc, int x, int y, int parsent = 100, COLORREF color = CLR_AUTOSELECT) const
1597 {
1598 if ( parsent >= 0 )
1599 {
1600 if ( parsent >= 100 )
1601 {
1602 return TransparentBit(hdc, x, y, color);
1603 }
1604 else if ( color == CLR_INVALID )
1605 {
1606 return AlphaBlend(hdc, x, y, parsent);
1607 }
1608 }
1609 //
1610 CBitmapImage biBase;
1611 RECT rc = { x, y, x + m_size.cx, y + m_size.cy };
1612 biBase.SetFromDC(hdc, rc);
1613 CBitmapImage biOver;
1614 biOver.Set(*this);
1615 if ( ! biBase.m_CheckDib() || ! biOver.m_CheckDib() )
1616 {
1617 return false;
1618 }
1619 if ( parsent >= 0 )
1620 {
1621 parsent = parsent * 255 / 100;
1622 }
1623 loop ( py, biOver.m_size.cy )
1624 {
1625 const RGBQUAD* pOver = biOver.GetRgbDataPtr(py);
1626 RGBQUAD* pBase = biBase.GetRgbDataPtr(py);
1627 if ( py == 0 && color == CLR_AUTOSELECT )
1628 {
1629 color = RGB(pOver->rgbRed, pOver->rgbGreen, pOver->rgbBlue);
1630 }
1631 DWORD tmp;
1632 loop ( px, biOver.m_size.cx )
1633 {
1634 if ( ! IS_RGBVALUE(color) || color != RGB(pOver->rgbRed, pOver->rgbGreen, pOver->rgbBlue) )
1635 {
1636 int d = parsent;
1637 if ( d < 0 )
1638 {
1639 d = pOver->rgbReserved;
1640 }
1641 tmp = (pBase->rgbBlue * (255 - d)) + (pOver->rgbBlue * d);
1642 pBase->rgbBlue = static_cast<BYTE>((tmp > 255 * 255) ? 255 : (tmp / 255));
1643 tmp = (pBase->rgbGreen * (255 - d)) + (pOver->rgbGreen * d);
1644 pBase->rgbGreen = static_cast<BYTE>((tmp > 255 * 255) ? 255 : (tmp / 255));
1645 tmp = (pBase->rgbRed * (255 - d)) + (pOver->rgbRed * d);
1646 pBase->rgbRed = static_cast<BYTE>((tmp > 255 * 255) ? 255 : (tmp / 255));
1647 }
1648 pBase++;
1649 pOver++;
1650 }
1651 }
1652 return biBase.BitBlt(hdc, x, y);
1653 }
1654
1660 bool HasRgbData(void) const
1661 {
1662 return m_pRgb != NULL;
1663 }
1664
1671 bool ToHaveRgbData(void)
1672 {
1673 if ( m_pRgb == NULL )
1674 {
1675 m_CheckDib();
1676 }
1677 return m_pRgb != NULL;
1678 }
1679
1688 RGBQUAD* GetRgbDataPtr(INT_PTR y = -1)
1689 {
1690 if ( m_pRgb != NULL )
1691 {
1692 if ( y < 0 )
1693 {
1694 return m_pRgb;
1695 }
1696 INT_PTR yy = (m_size.cy - 1) - y;
1697 return &m_pRgb[yy * m_size.cx];
1698 }
1699 return NULL;
1700 }
1701
1710 const RGBQUAD* GetRgbDataPtr(INT_PTR y = -1) const
1711 {
1712 if ( m_pRgb != NULL )
1713 {
1714 if ( y < 0 )
1715 {
1716 return m_pRgb;
1717 }
1718 INT_PTR yy = (m_size.cy - 1) - y;
1719 return &m_pRgb[yy * m_size.cx];
1720 }
1721 return NULL;
1722 }
1723
1731 {
1732 if ( m_pRgb == NULL )
1733 {
1734 return CBitmapHandle();
1735 }
1736 const SIZE& sz = m_size;
1737 CBitmapImage bi;
1738 bi.Set(sz.cy, sz.cx);
1739 bi.ToHaveRgbData();
1740 loop ( y1, sz.cy )
1741 {
1742 INDEX x2 = y1;
1743 const RGBQUAD* p1 = &m_pRgb[y1 * sz.cx];
1744 loop ( x1, sz.cx )
1745 {
1746 INDEX y2 = x1;
1747 RGBQUAD* p2 = bi.GetRgbDataPtr(y2);
1748 p2[x2] = *p1++;
1749 }
1750 }
1751 return bi;
1752 }
1753
1762 CBitmapImage CreateReverseImage(bool isVertical, bool isHorizontal) const
1763 {
1764 if ( m_pRgb == NULL )
1765 {
1766 return CBitmapHandle();
1767 }
1768 const SIZE& sz = m_size;
1769 CBitmapImage bi;
1770 bi.Set(sz.cx, sz.cy);
1771 bi.ToHaveRgbData();
1772 loop ( y1, sz.cy )
1773 {
1774 INDEX y2 = isVertical ? (sz.cy - 1) - y1 : y1;
1775 const RGBQUAD* p1 = &m_pRgb[y1 * sz.cx];
1776 if ( isHorizontal )
1777 {
1778 loop_dn ( x1, sz.cx )
1779 {
1780 bi.m_pRgb[y2 * sz.cx + x1] = *p1++;
1781 }
1782 }
1783 else
1784 {
1785 loop ( x1, sz.cx )
1786 {
1787 bi.m_pRgb[y2 * sz.cx + x1] = *p1++;
1788 }
1789 }
1790 }
1791 return bi;
1792 }
1793
1801 {
1802 if ( m_pRgb == NULL )
1803 {
1804 return CBitmapHandle();
1805 }
1806 const SIZE& sz = m_size;
1807 CBitmapImage bi;
1808 bi.Set(sz.cx, sz.cy);
1809 bi.ToHaveRgbData();
1810 loop ( y1, sz.cy )
1811 {
1812 const RGBQUAD* p = &m_pRgb[y1 * sz.cx];
1813 loop ( x1, sz.cx )
1814 {
1815 BYTE r = p->rgbRed;
1816 BYTE g = p->rgbGreen;
1817 BYTE b = p->rgbBlue;
1818 int a = (r * 30 + g * 59 + b * 11) / 100;
1819 if ( a > 255 )
1820 {
1821 a = 255;
1822 }
1823 RGBQUAD q;
1824 q.rgbRed = static_cast<BYTE>(a);
1825 q.rgbGreen = static_cast<BYTE>(a);
1826 q.rgbBlue = static_cast<BYTE>(a);
1827 bi.m_pRgb[y1 * sz.cx + x1] = q;
1828 p++;
1829 }
1830 }
1831 return bi;
1832 }
1833
1841 {
1842 return m_DilationErosion(true);
1843 }
1844
1852 {
1853 return m_DilationErosion(false);
1854 }
1855
1863 {
1864 if ( m_pRgb == NULL )
1865 {
1866 return CBitmapHandle();
1867 }
1868 CBitmapImage br;
1869 SIZE sz = m_size;
1870 br.Set(sz.cx, sz.cy);
1871 br.ToHaveRgbData();
1872 BYTE vb[9];
1873 loop ( y, sz.cy )
1874 {
1875 const RGBQUAD* po = GetRgbDataPtr(y);
1876 const RGBQUAD* po1 = GetRgbDataPtr(y - 1);// y=0の時期待外の値が返るが以降でカバーしてる
1877 const RGBQUAD* po2 = GetRgbDataPtr(y + 1);// y=sz.cy-1の時期待外の値が返るが以降でカバーしてる
1878 RGBQUAD* pr = br.GetRgbDataPtr(y);
1879 loop ( x, sz.cx )
1880 {
1881 if ( x == 0 || y == 0 || static_cast<int>(x) == sz.cx - 1 || static_cast<int>(y) == sz.cy - 1 )
1882 {
1883 pr[x] = po[x];
1884 }
1885 else
1886 {
1887 vb[0] = po1[x - 1].rgbBlue;
1888 vb[1] = po1[x].rgbBlue;
1889 vb[2] = po1[x + 1].rgbBlue;
1890 vb[3] = po[x - 1].rgbBlue;
1891 vb[4] = po[x].rgbBlue;
1892 vb[5] = po[x + 1].rgbBlue;
1893 vb[6] = po2[x - 1].rgbBlue;
1894 vb[7] = po2[x].rgbBlue;
1895 vb[8] = po2[x + 1].rgbBlue;
1896 ::qsort(vb, 9, sizeof(BYTE), ms_DeSub);
1897 pr[x].rgbBlue = vb[5];
1898 //
1899 vb[0] = po1[x - 1].rgbRed;
1900 vb[1] = po1[x].rgbRed;
1901 vb[2] = po1[x + 1].rgbRed;
1902 vb[3] = po[x - 1].rgbRed;
1903 vb[4] = po[x].rgbRed;
1904 vb[5] = po[x + 1].rgbRed;
1905 vb[6] = po2[x - 1].rgbRed;
1906 vb[7] = po2[x].rgbRed;
1907 vb[8] = po2[x + 1].rgbRed;
1908 ::qsort(vb, 9, sizeof(BYTE), ms_DeSub);
1909 pr[x].rgbRed = vb[5];
1910 //
1911 vb[0] = po1[x - 1].rgbGreen;
1912 vb[1] = po1[x].rgbGreen;
1913 vb[2] = po1[x + 1].rgbGreen;
1914 vb[3] = po[x - 1].rgbGreen;
1915 vb[4] = po[x].rgbGreen;
1916 vb[5] = po[x + 1].rgbGreen;
1917 vb[6] = po2[x - 1].rgbGreen;
1918 vb[7] = po2[x].rgbGreen;
1919 vb[8] = po2[x + 1].rgbGreen;
1920 ::qsort(vb, 9, sizeof(BYTE), ms_DeSub);
1921 pr[x].rgbGreen = vb[5];
1922 }
1923 }
1924 }
1925 return br;
1926 }
1927
1936 DWORD Paint(int x, int y, COLORREF c)
1937 {
1938 if ( ! HasRgbData() )
1939 {
1940 return 0;
1941 }
1942 if ( x < 0 || y < 0 || x >= m_size.cx || y >= m_size.cy )
1943 {
1944 return 0;
1945 }
1946 y = (m_size.cy - 1) - y;
1947 TPaintInfo pi;
1948 pi.size = m_size;
1949 pi.count = 0;
1950 pi.pRgb = m_pRgb;
1951 pi.rgbBase = m_pRgb[x + y * m_size.cx];
1952 pi.rgb.rgbBlue = GetBValue(c);
1953 pi.rgb.rgbRed = GetRValue(c);
1954 pi.rgb.rgbGreen = GetGValue(c);
1955 if ( ! pi.IsEqualBase(pi.rgb) )
1956 {
1957 while ( true )
1958 {
1959 DWORD i = m_PaintSub(x, y, &pi);
1960 if ( i == DWORD_MAX ) break;
1961 x = i & 0xFFFF;
1962 y = i / 0x10000;
1963 }
1964 }
1965 return pi.count;
1966 }
1967
1976 DWORD Save(LPCTSTR lpszFileName, WORD bitsPixel = 0)
1977 {
1978 return CBitmapHandle::Save(lpszFileName, m_bmp, bitsPixel);
1979 }
1980
1981
1982 //-----------------
1983
1984
1995 static HBITMAP _deprecated Load(LPCTSTR lpszFileName, int cx = 0, int cy = 0, UINT fuLoad = LR_CREATEDIBSECTION)
1996 {
1997 return CBitmapHandle::Load(lpszFileName, cx, cy, fuLoad);
1998 }
1999
2012 static HBITMAP _deprecated Load(UINT uBitmapResourceId, int cx = 0, int cy = 0, UINT fuLoad = LR_CREATEDIBSECTION)
2013 {
2014 return CBitmapHandle::Load(uBitmapResourceId, cx, cy, fuLoad);
2015 }
2016
2024 static bool GetBitmapSize(SIZE& _size, HBITMAP hBitmap)
2025 {
2026 BITMAP bm;
2027 if ( ::GetObject(hBitmap, sizeof(BITMAP), &bm) > 0 )
2028 {
2029 _size.cx = bm.bmWidth;
2030 _size.cy = bm.bmHeight;
2031 return true;
2032 }
2033 _GetLastError("GetObject");
2034 _size.cx = 0;
2035 _size.cy = 0;
2036 return false;
2037 }
2038
2046 {
2047 SIZE orgSize;
2048 if ( bmp.GetSize(orgSize) )
2049 {
2050 SIZE sz = { CalcScaleX(orgSize.cx), CalcScaleY(orgSize.cy) };
2051 if ( sz.cx != orgSize.cx || sz.cy != orgSize.cy )
2052 {
2053 CBitmapImage bi;
2054 bi.Set(sz.cx, sz.cy);
2055 bi.Insert(0, 0, bmp, 13369376, sz.cx, sz.cy);
2056 return bi;
2057 }
2058 }
2059 return bmp;
2060 }
2061
2069 static void CalcAdjustRect(RECT& _rect, const SIZE& dstSize, const SIZE& srcSize)
2070 {
2071 int ly = srcSize.cy * dstSize.cx / srcSize.cx;
2072 if ( dstSize.cy >= ly )
2073 {
2074 int d = (dstSize.cy - ly) / 2;
2075 ::SetRect(&_rect, 0, d, dstSize.cx, ly + d);
2076 return;
2077 }
2078 int lx = srcSize.cx * dstSize.cy / srcSize.cy;
2079 int d = (dstSize.cx - lx) / 2;
2080 ::SetRect(&_rect, d, 0, lx + d, dstSize.cy);
2081 }
2082
2083private:
2084
2085 CBitmapHandle m_bmp;
2086 RGBQUAD* m_pRgb;
2087 SIZE m_size;
2088 HWND m_hWnd;
2089 HDC m_backDC;
2090 HGDIOBJ m_backBmp;
2091 int m_nStretchMode;
2092
2094 class CWorkDC
2095 {
2096 HWND m_hWnd;
2097 HDC m_dc;
2098 public:
2099 CWorkDC(HWND hWnd) : m_hWnd(hWnd), m_dc(::GetDC(hWnd))
2100 {
2101 ASSERT0( m_dc != NULL, "GetDC", "失敗しました。" );
2102 }
2103 ~CWorkDC(void)
2104 {
2105 if ( ! ::ReleaseDC(m_hWnd, m_dc) ) { ASSERT0( false, "ReleaseDC", "失敗しました。" ); }
2106 }
2107 operator HDC(void) { return m_dc; }
2108 };
2110 class CTempDC
2111 {
2112 HDC m_dc;
2113 HGDIOBJ m_bmp;
2114 public:
2115 CTempDC(HDC dc, HBITMAP bmp) : m_dc(::CreateCompatibleDC(dc)), m_bmp(::SelectObject(m_dc, bmp))
2116 {
2117 ASSERT0( m_dc != NULL, "CreateCompatibleDC", "失敗しました。" );
2118 ASSERT0( m_bmp != NULL, "SelectObject", "失敗しました。" );
2119 }
2120 ~CTempDC(void)
2121 {
2122 if ( ::SelectObject(m_dc, m_bmp) == NULL ) { ASSERT0( false, "SelectObject", "失敗しました。" ); }
2123 if ( ! ::DeleteDC(m_dc) ) { ASSERT0( false, "DeleteDC", "失敗しました。" ); }
2124 }
2125 operator HDC(void) { return m_dc; }
2126 };
2128 class CTempBitmapDC
2129 {
2130 CWorkDC m_workDC;
2131 CTempDC m_tempDC;
2132 public:
2133 CTempBitmapDC(HWND hWnd, HBITMAP bmp) : m_workDC(hWnd), m_tempDC(m_workDC, bmp) { }
2134 operator HDC(void) { return m_tempDC; }
2135 };
2136
2138 struct TPaintInfo
2139 {
2140 DWORD count;
2141 SIZE size;
2142 RGBQUAD* pRgb;
2143 RGBQUAD rgbBase;
2144 RGBQUAD rgb;
2151 bool IsEqualBase(const RGBQUAD& q) const
2152 {
2153 if ( rgbBase.rgbBlue != q.rgbBlue ) return false;
2154 if ( rgbBase.rgbRed != q.rgbRed ) return false;
2155 if ( rgbBase.rgbGreen != q.rgbGreen ) return false;
2156 return true;
2157 }
2165 bool IsEqualBase(DWORD x, DWORD y) const
2166 {
2167 return IsEqualBase(pRgb[x + y * size.cx]);
2168 }
2169 };
2170
2171 #ifndef _WIN32_WCE
2172 enum { DEFAULT_STRETCHMODE = STRETCH_HALFTONE };
2173 #else
2174 enum { DEFAULT_STRETCHMODE = BILINEAR };
2175 #endif
2176
2177 //小さいほうを選択
2178 static size_t ms_ChoiceMin(size_t a, size_t b)
2179 {
2180 return (a < b) ? a : b;
2181 }
2182 // Bitmapヘッダ設定
2183 static void ms_SetBitmapInfoHeader(BITMAPINFOHEADER& _bi, int cx, int cy, WORD bit = 32)
2184 {
2185 Zero(_bi);
2186 _bi.biSize = sizeof(BITMAPINFOHEADER);
2187 _bi.biWidth = cx;
2188 _bi.biHeight = cy;
2189 _bi.biPlanes = 1;
2190 _bi.biBitCount = bit;
2191 _bi.biCompression = BI_RGB;
2192 }
2193 // 空のビットマップ作成
2194 static HBITMAP ms_CreateBitmap(RGBQUAD*& _pRgb, HDC dc, int cx, int cy)
2195 {
2196 _pRgb = NULL;
2197 if ( cx > 0 && cy > 0 )
2198 {
2199 BITMAPINFOHEADER bm = { 0 };
2200 ms_SetBitmapInfoHeader(bm, cx, cy, 32);
2201 return ::CreateDIBSection(dc, reinterpret_cast<BITMAPINFO*>(&bm), DIB_RGB_COLORS, reinterpret_cast<void **>(&_pRgb), NULL, 0);
2202 }
2203 return NULL;
2204 }
2205 // RECT → SIZE
2206 static bool ms_CheckSize(SIZE& _size, const RECT& rect)
2207 {
2208 _size.cx = rect.right - rect.left;
2209 _size.cy = rect.bottom - rect.top;
2210 return (_size.cx > 0 && _size.cy > 0);
2211 }
2212 static void ms_CheckSize(int& _cx, int& _cy, const SIZE& s)
2213 {
2214 if ( _cx <= 0 ) { _cx = s.cx; }
2215 if ( _cy <= 0 ) { _cy = s.cy; }
2216 }
2217 void m_CheckSize(int& _cx, int& _cy) const
2218 {
2219 ms_CheckSize(_cx, _cy, m_size);
2220 }
2221 // リリース
2222 void m_ReleaseDC(void)
2223 {
2224 if ( m_backDC != NULL )
2225 {
2226 if ( ::SelectObject(m_backDC, m_backBmp) == NULL )
2227 {
2228 ASSERT0( false, "SelectObject", "失敗しました。" );
2229 }
2230 if ( ! ::DeleteDC(m_backDC) )
2231 {
2232 ASSERT0( false, "DeleteDC", "失敗しました。" );
2233 }
2234 m_backDC = NULL;
2235 }
2236 }
2238 COLORREF m_CheckColor(HDC hdc, COLORREF color) const
2239 {
2240 if ( color == CLR_AUTOSELECT )
2241 {
2242 color = ::GetPixel(hdc, 0, m_size.cy - 1);
2243 }
2244 return color;
2245 }
2246 //メンバに記憶
2247 bool m_Set(CBitmapHandle bmp, RGBQUAD* pRgb = NULL)
2248 {
2249 if ( bmp == m_bmp )
2250 {
2251 return true;
2252 }
2253 Empty();
2254 if ( bmp.GetSize(m_size) )
2255 {
2256 m_bmp = bmp;
2257 m_pRgb = pRgb;
2258 return true;
2259 }
2260 return false;
2261 }
2262
2264 static int ms_DeSub(const void* a, const void* b)
2265 {
2266 return *(BYTE*)a - *(BYTE*)b;
2267 }
2268
2270 static inline BYTE ms_GG(const RGBQUAD* p, int cx, int x)
2271 {
2272 return (x < 0 || x >= cx) ? static_cast<BYTE>(0) : p[x].rgbGreen;
2273 }
2274
2276 static inline BYTE ms_max(size_t len, BYTE* p)
2277 {
2278 BYTE r = p[0];
2279 loop ( i, len - 1 )
2280 {
2281 if ( r < p[i + 1] ) r = p[i + 1];
2282 }
2283 return r;
2284 }
2285
2287 static inline BYTE ms_min(size_t len, BYTE* p)
2288 {
2289 BYTE r = p[0];
2290 loop ( i, len - 1 )
2291 {
2292 if ( r > p[i + 1] ) r = p[i + 1];
2293 }
2294 return r;
2295 }
2296
2302 CBitmapImage m_DilationErosion(bool isDilation = true) const
2303 {
2304 if ( m_pRgb == NULL )
2305 {
2306 return CBitmapHandle();
2307 }
2308 SIZE sz = m_size;
2309 CBitmapImage b2;
2310 b2.Set(sz.cx, sz.cy);
2311 b2.ToHaveRgbData();
2312 //ダミーライン作成
2313 CWorkMemT<RGBQUAD> dp(sz.cx);
2314 RGBQUAD rgb = { 0 };
2315 dp.Fill(rgb);
2316 //
2317 loop ( y, sz.cy )
2318 {
2319 RGBQUAD* q = b2.GetRgbDataPtr(y);
2320 const RGBQUAD* p0 = (y == 0) ? dp : GetRgbDataPtr(y - 1);
2321 const RGBQUAD* p1 = GetRgbDataPtr(y);
2322 const RGBQUAD* p2 = (static_cast<int>(y) == sz.cy - 1) ? dp : GetRgbDataPtr(y + 1);
2323 loop ( x, sz.cx )
2324 {
2325 BYTE b[9];
2326 b[0] = ms_GG(p0, sz.cx, x - 1);
2327 b[1] = ms_GG(p0, sz.cx, x + 0);
2328 b[2] = ms_GG(p0, sz.cx, x + 1);
2329 b[3] = ms_GG(p1, sz.cx, x - 1);
2330 b[4] = ms_GG(p1, sz.cx, x + 0);
2331 b[5] = ms_GG(p1, sz.cx, x + 1);
2332 b[6] = ms_GG(p2, sz.cx, x - 1);
2333 b[7] = ms_GG(p2, sz.cx, x + 0);
2334 b[8] = ms_GG(p2, sz.cx, x + 1);
2335 BYTE r = isDilation ? ms_max(9, b) : ms_min(9, b);
2336 q[x].rgbGreen = r;
2337 q[x].rgbBlue = r;
2338 q[x].rgbRed = r;
2339 }
2340 }
2341 return b2;
2342 }
2343
2350 DWORD m_PaintSub(int x, int y, TPaintInfo* p)
2351 {
2352 if ( ! p->IsEqualBase(x, y) )
2353 {
2354 return DWORD_MAX;
2355 }
2356 int i, j;
2357 for ( i = 1;; i++ )
2358 {
2359 if ( p->size.cx <= x + i || ! p->IsEqualBase(x + i, y) )
2360 {
2361 break;
2362 }
2363 }
2364 for ( j = 1;; j++ )
2365 {
2366 if ( 0 > x - j || ! p->IsEqualBase(x - j, y) )
2367 {
2368 break;
2369 }
2370 }
2371 RGBQUAD* q = &(p->pRgb[y * p->size.cx]);
2372 loop ( xx , j + i - 1 )
2373 {
2374 q[x - j + 1 + xx] = p->rgb;
2375 }
2376 p->count += j + i - 1;
2377 //
2378 x = x - j + 1;
2379 j = j + i - 1;
2380 DWORD l = 0;
2381 if ( p->size.cy > y + 1 )
2382 {
2383 for( i = 0; i < j;)
2384 {
2385 if ( ! p->IsEqualBase(x + i, y + 1) )
2386 {
2387 for( ;i < j; i++ )
2388 {
2389 if ( p->IsEqualBase(x + i, y + 1) )
2390 break;
2391 }
2392 }
2393 else
2394 {
2395 for( ; i < j; i++ )
2396 {
2397 if ( ! p->IsEqualBase(x + i, y + 1) )
2398 break;
2399 }
2400 l++;
2401 }
2402 }
2403 }
2404 if ( 0 <= y - 1 )
2405 {
2406 for ( i = 0; i < j; )
2407 {
2408 if ( ! p->IsEqualBase(x + i, y - 1) )
2409 {
2410 for ( ; i < j; i++ )
2411 {
2412 if ( p->IsEqualBase(x + i, y - 1) )
2413 break;
2414 }
2415 }
2416 else
2417 {
2418 for( ; i < j; i++ )
2419 {
2420 if ( ! p->IsEqualBase(x + i, y - 1) )
2421 break;
2422 }
2423 l++;
2424 }
2425 }
2426 }
2427 DWORD k = 0;
2428 for ( i = 0; i < j; i++ )
2429 {
2430 if ( p->size.cy > y + 1 && p->IsEqualBase(x + i, y + 1) )
2431 {
2432 if ( ++k >= l )
2433 {
2434 return (x + i) + (y + 1) * 0x10000;
2435 }
2436 int xx = x + i;
2437 int yy = y + 1;
2438 while ( true )
2439 {
2440 DWORD i = m_PaintSub(xx, yy, p);
2441 if ( i == DWORD_MAX ) break;
2442 xx = i & 0xFFFF;
2443 yy = i / 0x10000;
2444 }
2445 }
2446 if ( 0 <= y - 1 && p->IsEqualBase(x + i, y - 1) )
2447 {
2448 if ( ++k >= l )
2449 {
2450 return (x + i) + (y - 1) * 0x10000;
2451 }
2452 int xx = x + i;
2453 int yy = y - 1;
2454 while ( true )
2455 {
2456 DWORD i = m_PaintSub(xx, yy, p);
2457 if ( i == DWORD_MAX ) break;
2458 xx = i & 0xFFFF;
2459 yy = i / 0x10000;
2460 }
2461 }
2462 }
2463 return DWORD_MAX;
2464 }
2465
2467 bool m_CheckDib(void)
2468 {
2469 if ( ! IsEmpty() && m_pRgb == NULL )
2470 {
2471 CBitmapImage bi;
2472 bi.Set(*this);
2473 if ( bi.m_pRgb == NULL )
2474 {
2475 BITMAP bp;
2476 if ( ::GetObject(bi.m_bmp, sizeof(BITMAP), &bp) > 0 && bp.bmBitsPixel == 32 )
2477 {
2478 bi.m_pRgb = static_cast<RGBQUAD*>(bp.bmBits);
2479 }
2480 }
2481 if ( bi.m_pRgb == NULL )
2482 {
2483 bi.Set(*this, m_size.cx, m_size.cy);
2484 ASSERT( bi.m_pRgb != NULL );
2485 }
2486 *this = bi;
2487 }
2488 return (m_pRgb != NULL);
2489 }
2490};
2491
2492
2493
2494};
2495
ビットマップハンドル関係のヘッダ
#define loop_dn(VAR, CNT)
loop構文.
Definition: TnbDef.h:355
#define loop(VAR, CNT)
loop構文.
Definition: TnbDef.h:343
HBITMAP型ハンドルハンドル
bool GetSize(SIZE &_size) const
[取得] ビットマップサイズ取得.
DWORD Save(LPCTSTR lpszFileName, WORD bitsPixel=0)
[作成] BMPファイル作成.
bool Draw(HDC hdc, int x=0, int y=0) const
[処理] イメージ描画.
static HBITMAP Load(UINT uBitmapResourceId, int cx=0, int cy=0, UINT fuLoad=LR_CREATEDIBSECTION)
[読込] リソース読込み
static HBITMAP Create32bitDibSection(HBITMAP hbm, RGBQUAD *&_pRgb, BITMAPINFOHEADER *pHeader=NULL)
[作成] 32bitビットマップ作成.
ビットマップ生データ管理クラス
size_t GetLineBytes(void) const
[取得] 一ラインBYTE数取得
RGBQUAD * Refer(void)
[取得] データ参照.
const RGBQUAD * Refer(void) const
[取得] データ参照.
bool IsValid(void) const
[確認] 有効確認.
const SIZE & GetSize(void) const
[取得] サイズ取得
const RGBQUAD * operator[](INDEX y) const
[取得] ラインデータ参照.
CRawData(void)
コンストラクタ
RGBQUAD * operator[](INDEX y)
[取得] ラインデータ参照.
CRawData(const SIZE &s)
コンストラクタ
ビットマップイメージ管理クラス
bool DrawTile(HDC hdc, const RECT &rect) const
[処理] イメージタイル描画.
bool CustomizeAlpha(CBitmapHandle bmp)
[処理] アルファチャネル操作.
bool SetFromClient(HWND hWnd, const RECT &rect, COLORREF backColor=CLR_INVALID)
[設定] クライアントからイメージ設定.
CBitmapHandle Detach(void)
[設定] デタッチ.
bool Set(CBitmapHandle bmp)
[設定] イメージ設定.
DWORD Paint(int x, int y, COLORREF c)
[描画] ペイント.
bool IsEmpty(void) const
[確認] Empty状態確認.
bool ChangePixelColor(COLORREF r, COLORREF g, COLORREF b)
[処理] カラー変更.
CBitmapImage CreateReverseImage(bool isVertical, bool isHorizontal) const
[作成] 反転画像作成.
bool GradationFill(COLORREF color1, COLORREF color2, EDirection direction, const RECT *pRect=NULL)
[処理] グラデーション描画.
bool Fill(COLORREF color, const RECT &rect)
[処理] 四角描画.
bool InsertEx(int x, int y, HBITMAP hBitmap, UINT uExFlag=DSS_NORMAL)
[挿入] イメージ挿入.
bool Set(const CBitmapImage &bmpimg, int cx=0, int cy=0)
[設定] イメージ設定.
bool SetEx(HDC hDC, int cx, int cy, COLORREF color=CLR_INVALID)
[設定] 拡張イメージ設定.
bool CustomizeAlpha(BYTE alpha, COLORREF colorEx, BYTE alphaEx)
[処理] アルファチャネル操作.
CBitmapImage(CBitmapHandle bmp)
代入コンストラクタ
bool Insert(int x, int y, const CBitmapImage &bmpimg, DWORD raster=SRCCOPY, int cx=0, int cy=0)
[挿入] イメージ挿入.
RGBQUAD * GetRgbDataPtr(INT_PTR y=-1)
[取得] RGBデータアドレス取得.
bool BitBlt(HDC hdc, int x, int y, DWORD raster=SRCCOPY) const
[表示] イメージ描画.
HRGN CreateRgn(COLORREF transColor=CLR_AUTOSELECT) const
[作成] リージョン作成.
bool SetFromIcon(HICON hIcon, COLORREF backColor)
[作成] ICONからイメージ設定.
int ChangePixelColor(COLORREF targetColor, COLORREF drawColor)
[処理] カラー変更.
CBitmapImage & operator=(const CBitmapImage &other)
コピーオペレータ
bool Fill(COLORREF color)
[処理] 四角描画.
CBitmapImage CreateDilationBitmap(void) const
[作成] 膨張画像作成.
HDC GetDC(void)
[取得]デバイスコンテキストハンドル取得.
bool SetFromClient(HWND hWnd, COLORREF backColor=CLR_INVALID)
[設定] クライアントからイメージ設定.
bool Attach(CBitmapHandle bmp)
[設定] アタッチ.
static void CalcAdjustRect(RECT &_rect, const SIZE &dstSize, const SIZE &srcSize)
[計算] 表示位置調整.
bool InsertOnTransparent(int x, int y, const CBitmapImage &bmpimg, COLORREF color=CLR_AUTOSELECT, int cx=0, int cy=0)
[挿入] 透過処理付イメージ挿入.
CBitmapImage CreateGrayscaleBitmap(void) const
[作成] グレイスケール画像作成.
bool CustomizeAlpha(BYTE alpha)
[処理] アルファチャネル操作.
CBitmapImage Cut(const RECT &rect, int cx=0, int cy=0) const
[取得] イメージ取り出し.
bool SetFromWindow(HWND hWnd, COLORREF backColor=CLR_INVALID, LPARAM mode=PRF_CLIENT|PRF_ERASEBKGND|PRF_NONCLIENT|PRF_OWNED)
[設定] ウィンドウからイメージ設定.
bool _deprecated Set(const CRawData &rawData)
[設定] 生データからイメージ設定.
virtual ~CBitmapImage(void)
デストラクタ
const SIZE & GetSize(void) const
[取得] イメージサイズ取得.
static bool GetBitmapSize(SIZE &_size, HBITMAP hBitmap)
[取得] ビットマップサイズ取得.
const RGBQUAD * GetRgbDataPtr(INT_PTR y=-1) const
[取得] RGBデータアドレス取得.
void SetWorkWnd(HWND h)
[設定] ワークデバイスコンテキスト設定.
bool Set(int cx, int cy, COLORREF color=CLR_INVALID)
[設定] イメージ設定.
bool StretchBlt(HDC hdc, int x, int y, DWORD raster=SRCCOPY, int cx=0, int cy=0) const
[表示] イメージ描画.
bool GradationFill(COLORREF color1, COLORREF color2, bool boIsHorizontal, const RECT *pRect=NULL)
[処理] グラデーション描画.
bool SetFromDC(HDC hdc, const RECT &rect, int cx=0, int cy=0)
[設定] DCからイメージ設定.
CBitmapImage CreateRotateImage(void) const
[作成] 回転画像作成.
CBitmapImage(void)
コンストラクタ
HBITMAP CreateMaskBitmap(bool boIsReverse=false, COLORREF transColor=CLR_AUTOSELECT) const
[作成] マスクパターンビットマップ作成.
DWORD Save(LPCTSTR lpszFileName, WORD bitsPixel=0)
[作成] BMPファイル作成.
static HBITMAP _deprecated Load(UINT uBitmapResourceId, int cx=0, int cy=0, UINT fuLoad=LR_CREATEDIBSECTION)
[読込] リソース読込み
CBitmapImage CreateErosionBitmap(void) const
[作成] 収縮画像作成.
CBitmapHandle GetBitmapHandle(void)
[取得] ビットマップハンドル取得
bool ReleaseDC(void)
[設定] デバイスコンテキストハンドル返却.
void Empty(void)
[設定] 破棄.
bool ToHaveRgbData(void)
[設定] RGBデータ準備.
bool Draw(HDC hdc, int x=0, int y=0) const
[処理] イメージ描画.
CBitmapImage Clone(void) const
[複製] クローン作成
static HBITMAP _deprecated Load(LPCTSTR lpszFileName, int cx=0, int cy=0, UINT fuLoad=LR_CREATEDIBSECTION)
[読込] BMPファイル読込み.
bool GradientFill(const PTRIVERTEX pVertex, DWORD dwNumVertex, const PGRADIENT_RECT pMesh, DWORD dwNumMesh, bool boIsHorizontal)
[処理] グラデーション描画.
CBitmapImage(const CBitmapImage &other)
コピーコンストラクタ
CBitmapImage MedianFilter(void) const
[作成] メディアンフィルター画像作成.
void SetStretchBltMode(int nStretchMode)
[設定] ビットマップ伸縮モード設定.
bool TransparentBit(HDC hdc, int x, int y, COLORREF color=CLR_AUTOSELECT, int cx=0, int cy=0) const
[表示] 透過処理付イメージ描画.
bool SemitransparectBlt(HDC hdc, int x, int y, int parsent=100, COLORREF color=CLR_AUTOSELECT) const
[挿入] 半透明,透過イメージ描画.
bool InsertOnAlphaBlend(int x, int y, const CBitmapImage &bmpimg, int parsent=100, int cx=0, int cy=0)
[挿入] 半透過処理付イメージ挿入.
CRawData _deprecated CreateRawData(void) const
[作成] 生データ作成.
bool HasRgbData(void) const
[確認] RGBデータ有無.
bool GetBitmapInfo(BITMAPINFOHEADER &_head) const
[取得] BITMAPINFOHEADER 取得.
bool Draw(HDC hdc, const POINT &po) const
[処理] イメージ描画.
bool AlphaBlend(HDC hdc, int x, int y, int parsent=100, int cx=0, int cy=0) const
[描画] 半透明処理付イメージ描画.
static CBitmapHandle ChangeByDpi(CBitmapHandle bmp)
[作成] 画像縮小拡大
bool InsertOnSemitransparect(int x, int y, const CBitmapImage &bmpimg, int parsent=100, COLORREF color=CLR_AUTOSELECT)
[挿入] 半透明イメージ挿入(透過色付).
bool IsNull(void) const
[確認] NULLチェック
void Null(void)
[設定] 開放.
const TYP * Ref(void) const
[取得] ポインタ取得
Definition: TnbDef.h:712
void Zero(V &value)
[設定] ゼロクリア.
Definition: TnbDef.h:399
TNB Library
Definition: TnbDoxyTitle.txt:2
void MemCopy(T *_pDst, const void *pSrc, size_t len)
[複製] メモリコピー
Definition: TnbDef.h:376