milligram
修訂 | 99edffefaceb71e9bdd6c1b36e81cf31bea1992e (tree) |
---|---|
時間 | 2011-03-18 10:12:48 |
作者 | beru <berupon@gmai...> |
Commiter | beru |
Alpha Channelを含んだ32bit Bitmapの描画実装
@@ -30,11 +30,38 @@ MG::Container mg(elements, 128); | ||
30 | 30 | MG::Button button1; |
31 | 31 | MG::Button button2; |
32 | 32 | |
33 | -std::vector<uint8_t> imageBuffer; | |
34 | -MG::Bitmap bmpContent; | |
33 | +MG::Bitmap bmp24Content; | |
34 | +std::vector<uint8_t> image24Buffer; | |
35 | + | |
36 | +MG::Bitmap bmp32Content; | |
37 | +std::vector<uint8_t> image32Buffer; | |
38 | + | |
35 | 39 | MG::Element pic1; |
36 | 40 | MG::Element pic2; |
37 | 41 | |
42 | +bool ReadImage(const char* filename, MG::Bitmap& bmp, std::vector<uint8_t>& buffer) | |
43 | +{ | |
44 | + FILE* file = fopen(filename, "r"); | |
45 | + if (!file) { | |
46 | + return false; | |
47 | + } | |
48 | + File fileProxy(file); | |
49 | + ImageInfo imageInfo; | |
50 | + ReadImageInfo(fileProxy, imageInfo); | |
51 | + assert(imageInfo.bitsPerSample == 8); | |
52 | + assert(imageInfo.samplesPerPixel == 3 || imageInfo.samplesPerPixel == 4); | |
53 | + buffer.resize(imageInfo.width * imageInfo.height * imageInfo.samplesPerPixel); | |
54 | + int lineOffsetBytes = imageInfo.width * imageInfo.samplesPerPixel; | |
55 | + ReadImageData(fileProxy, &buffer[0], lineOffsetBytes, 0); | |
56 | + fclose(file); | |
57 | + bmp.bitsPerPixel = imageInfo.bitsPerSample * imageInfo.samplesPerPixel; | |
58 | + bmp.width = imageInfo.width; | |
59 | + bmp.height = imageInfo.height; | |
60 | + bmp.lineOffsetBytes = lineOffsetBytes; | |
61 | + bmp.pBits = &buffer[0]; | |
62 | + return true; | |
63 | +} | |
64 | + | |
38 | 65 | } // anonymous namespace |
39 | 66 | |
40 | 67 | void OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) |
@@ -91,49 +118,38 @@ void OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) | ||
91 | 118 | rect.h = 50; |
92 | 119 | button2.rect = rect; |
93 | 120 | mg.Add(button2); |
94 | - | |
95 | - // read content | |
96 | - { | |
97 | - FILE* file = fopen("test.bmp", "r"); | |
98 | - assert(file); | |
99 | - if (!file) { | |
100 | - return; | |
101 | - } | |
102 | - File fileProxy(file); | |
103 | - ImageInfo imageInfo; | |
104 | - ReadImageInfo(fileProxy, imageInfo); | |
105 | - assert(imageInfo.bitsPerSample == 8 && imageInfo.samplesPerPixel == 3); | |
106 | - imageBuffer.resize(imageInfo.width * imageInfo.height * imageInfo.samplesPerPixel); | |
107 | - int lineOffsetBytes = imageInfo.width * imageInfo.samplesPerPixel; | |
108 | - ReadImageData(fileProxy, &imageBuffer[0], lineOffsetBytes, 0); | |
109 | - fclose(file); | |
110 | - bmpContent.bitsPerPixel = imageInfo.bitsPerSample * imageInfo.samplesPerPixel; | |
111 | - bmpContent.width = imageInfo.width; | |
112 | - bmpContent.height = imageInfo.height; | |
113 | - bmpContent.lineOffsetBytes = lineOffsetBytes; | |
114 | - bmpContent.pBits = &imageBuffer[0]; | |
121 | + | |
122 | + if (!ReadImage("test24.bmp", bmp24Content, image24Buffer)) { | |
123 | + return; | |
124 | + } | |
125 | + if (!ReadImage("test32.bmp", bmp32Content, image32Buffer)) { | |
126 | + return; | |
115 | 127 | } |
128 | + | |
116 | 129 | rect.x = 100; |
117 | 130 | rect.y = 300; |
118 | 131 | pic1.rect = rect; |
119 | 132 | MG::Rectangle irec; |
120 | - irec.x = irec.y = 0; | |
133 | + irec.x = 510; | |
134 | + irec.y = 340; | |
121 | 135 | irec.w = 400; |
122 | 136 | irec.h = 400; |
123 | 137 | pic1.bg.image.rect = irec; |
124 | - pic1.bg.image.pBitmap = &bmpContent; | |
138 | + pic1.bg.image.pBitmap = &bmp24Content; | |
125 | 139 | pic1.needsToDraw = true; |
126 | 140 | mg.Add(pic1); |
127 | 141 | |
128 | 142 | rect.x = 300; |
129 | 143 | rect.y = 200; |
130 | - rect.w = 300; | |
144 | + rect.w = 336; | |
131 | 145 | rect.h = 300; |
132 | 146 | pic2.rect = rect; |
133 | - pic2.bg = pic1.bg; | |
134 | - irec.x = 510; | |
135 | - irec.y = 340; | |
147 | + irec.x = 0; | |
148 | + irec.y = 0; | |
149 | + irec.w = 336; | |
150 | + irec.h = 24; | |
136 | 151 | pic2.bg.image.rect = irec; |
152 | + pic2.bg.image.pBitmap = &bmp32Content; | |
137 | 153 | pic2.needsToDraw = true; |
138 | 154 | mg.Add(pic2); |
139 | 155 |
@@ -3,6 +3,27 @@ | ||
3 | 3 | #include "bitmap.h" |
4 | 4 | #include "arrayutil.h" |
5 | 5 | |
6 | +namespace { | |
7 | + | |
8 | +// http://www.virtualdub.org/blog/pivot/entry.php?id=117 | |
9 | +__forceinline | |
10 | +void blendColor_Phaeron(uint32_t fc, uint8_t fca, uint32_t& bc) | |
11 | +{ | |
12 | + uint32_t bc2 = bc; | |
13 | + uint32_t srb = fc & 0xff00ff; | |
14 | + uint32_t sg = fc & 0x00ff00; | |
15 | + uint32_t drb = bc2 & 0xff00ff; | |
16 | + uint32_t dg = bc2 & 0x00ff00; | |
17 | + uint32_t alpha = fca; | |
18 | + alpha += (alpha > 0); | |
19 | + uint32_t orb = (drb + (((srb - drb) * alpha + 0x800080) >> 8)) & 0xff00ff; | |
20 | + uint32_t og = (dg + (((sg - dg ) * alpha + 0x008000) >> 8)) & 0x00ff00; | |
21 | + | |
22 | + bc = orb+og; | |
23 | +} | |
24 | + | |
25 | +} // namespace anonymous | |
26 | + | |
6 | 27 | namespace MG { |
7 | 28 | |
8 | 29 | Rectangle Bitmap::GetRect() const |
@@ -63,6 +84,27 @@ void BitBlt_Src32_Dst24( | ||
63 | 84 | Bitmap& dst, const Rectangle& dstRect |
64 | 85 | ) |
65 | 86 | { |
87 | + const uint32_t* pSrc = (const uint32_t*) src.pBits; | |
88 | + OffsetPtr(pSrc, src.lineOffsetBytes * srcRect.y); | |
89 | + pSrc += srcRect.x; | |
90 | + | |
91 | + uint8_t* pDst = (uint8_t*) dst.pBits; | |
92 | + OffsetPtr(pDst, dst.lineOffsetBytes * dstRect.y); | |
93 | + pDst += 3 * dstRect.x; | |
94 | + | |
95 | + for (size_t y=0; y<dstRect.h; ++y) { | |
96 | + for (size_t x=0; x<dstRect.w; ++x) { | |
97 | + uint32_t fc = pSrc[x]; | |
98 | + uint8_t fca = fc >> 24; | |
99 | + uint32_t bc = (pDst[x*3+0] << 0) | (pDst[x*3+1] << 8) | (pDst[x*3+2] << 16); | |
100 | + blendColor_Phaeron(fc, fca, bc); | |
101 | + pDst[x*3+0] = (bc >> 0) & 0xff; | |
102 | + pDst[x*3+1] = (bc >> 8) & 0xff; | |
103 | + pDst[x*3+2] = (bc >> 16) & 0xff; | |
104 | + } | |
105 | + OffsetPtr(pSrc, src.lineOffsetBytes); | |
106 | + OffsetPtr(pDst, dst.lineOffsetBytes); | |
107 | + } | |
66 | 108 | } |
67 | 109 | |
68 | 110 | void BitBlt_Src32_Dst32( |