1 /* 2 Copyright (c) 2013 yvt 3 4 This file is part of OpenSpades. 5 6 OpenSpades is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 OpenSpades is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with OpenSpades. If not, see <http://www.gnu.org/licenses/>. 18 19 */ 20 21 #include "SWImage.h" 22 #include <Core/FileManager.h> 23 #include <Core/IStream.h> 24 25 namespace spades { 26 namespace draw { 27 namespace { ProcessPixel(uint32_t col)28 inline uint32_t ProcessPixel(uint32_t col) { 29 unsigned int alpha = static_cast<unsigned int>(col >> 24); 30 alpha += (alpha >> 7); // [0,255] to [0,256] 31 32 unsigned int r = static_cast<unsigned int>((col >> 0) & 0xff); 33 unsigned int g = static_cast<unsigned int>((col >> 8) & 0xff); 34 unsigned int b = static_cast<unsigned int>((col >> 16) & 0xff); 35 r = (r * alpha) >> 8; 36 g = (g * alpha) >> 8; 37 b = (b * alpha) >> 8; 38 39 col &= 0xff000000; 40 col |= b | (g << 8) | (r << 16); // swap RGB/BGR 41 return col; 42 } 43 } 44 SWImage(Bitmap * m)45 SWImage::SWImage(Bitmap *m) 46 : ew(m->GetWidth()), 47 eh(m->GetHeight()), 48 isWhite(false), 49 w(static_cast<float>(m->GetWidth())), 50 h(static_cast<float>(m->GetHeight())), 51 iw(1.f / w), 52 ih(1.f / h) { 53 bmp.resize(ew * eh); 54 55 // premultiplied alpha 56 { 57 uint32_t *inpix = m->GetPixels(); 58 uint32_t *outpix = bmp.data(); 59 bool foundNonWhite = false; 60 for (std::size_t i = ew * eh; i; i--) { 61 uint32_t col = *(inpix++); 62 col = ProcessPixel(col); 63 *(outpix++) = col; 64 65 if (col != 0xffffffff) 66 foundNonWhite = true; 67 } 68 isWhite = !foundNonWhite; 69 } 70 } 71 SWImage(int w,int h)72 SWImage::SWImage(int w, int h) 73 : ew(w), 74 eh(h), 75 isWhite(false), 76 w(static_cast<float>(ew)), 77 h(static_cast<float>(eh)), 78 iw(1.f / w), 79 ih(1.f / h) { 80 bmp.reserve(ew * eh); 81 } 82 ~SWImage()83 SWImage::~SWImage() {} 84 Update(Bitmap & inBmp,int x,int y)85 void SWImage::Update(Bitmap &inBmp, int x, int y) { 86 SPADES_MARK_FUNCTION(); 87 if (x < 0 || y < 0 || x + inBmp.GetWidth() > ew || y + inBmp.GetHeight() > eh) { 88 SPRaise("Out of range."); 89 } 90 91 { 92 int bw = inBmp.GetWidth(); 93 int bh = inBmp.GetHeight(); 94 for (int yy = 0; yy < bh; ++yy) { 95 uint32_t *inpix = inBmp.GetPixels(); 96 uint32_t *outpix = bmp.data(); 97 outpix += x + (y + yy) * ew; 98 inpix += yy * bw; 99 for (unsigned int j = bw; j; --j) { 100 *(outpix++) = ProcessPixel(*(inpix++)); 101 } 102 } 103 } 104 105 isWhite = false; 106 } 107 ~SWImageManager()108 SWImageManager::~SWImageManager() { 109 for (auto it = images.begin(); it != images.end(); it++) 110 it->second->Release(); 111 } 112 RegisterImage(const std::string & name)113 SWImage *SWImageManager::RegisterImage(const std::string &name) { 114 auto it = images.find(name); 115 if (it == images.end()) { 116 Handle<Bitmap> vm; 117 vm.Set(Bitmap::Load(name), false); 118 auto *m = CreateImage(vm); 119 images.insert(std::make_pair(name, m)); 120 m->AddRef(); 121 return m; 122 } else { 123 auto *image = it->second; 124 image->AddRef(); 125 return image; 126 } 127 } 128 CreateImage(Bitmap * vm)129 SWImage *SWImageManager::CreateImage(Bitmap *vm) { return new SWImage(vm); } 130 } 131 } 132