17 #ifndef XBRZ_TOOLS_H_825480175091875 
   18 #define XBRZ_TOOLS_H_825480175091875 
   22 #include <type_traits> 
   27 template <u
int32_t N> 
inline 
   28 unsigned char getByte(uint32_t val) { 
return static_cast<unsigned char>((val >> (8 * N)) & 0xff); }
 
   30 inline unsigned char getAlpha(uint32_t pix) { 
return getByte<3>(pix); }
 
   31 inline unsigned char getRed  (uint32_t pix) { 
return getByte<2>(pix); }
 
   32 inline unsigned char getGreen(uint32_t pix) { 
return getByte<1>(pix); }
 
   33 inline unsigned char getBlue (uint32_t pix) { 
return getByte<0>(pix); }
 
   35 inline uint32_t 
makePixel(
unsigned char a, 
unsigned char r, 
unsigned char g, 
unsigned char b) { 
return (a << 24) | (r << 16) | (
g << 8) | 
b; }
 
   36 inline uint32_t 
makePixel(                 
unsigned char r, 
unsigned char g, 
unsigned char b) { 
return             (r << 16) | (
g << 8) | 
b; }
 
   38 inline uint32_t 
rgb555to888(uint16_t pix) { 
return ((pix & 0x7C00) << 9) | ((pix & 0x03E0) << 6) | ((pix & 0x001F) << 3); }
 
   39 inline uint32_t 
rgb565to888(uint16_t pix) { 
return ((pix & 0xF800) << 8) | ((pix & 0x07E0) << 5) | ((pix & 0x001F) << 3); }
 
   41 inline uint16_t 
rgb888to555(uint32_t pix) { 
return static_cast<uint16_t
>(((pix & 0xF80000) >> 9) | ((pix & 0x00F800) >> 6) | ((pix & 0x0000F8) >> 3)); }
 
   42 inline uint16_t 
rgb888to565(uint32_t pix) { 
return static_cast<uint16_t
>(((pix & 0xF80000) >> 8) | ((pix & 0x00FC00) >> 5) | ((pix & 0x0000F8) >> 3)); }
 
   45 template <
class Pix> 
inline 
   49     using PixByte     = 
typename std::conditional<std::is_same<Pix, PixNonConst>::value, char, 
const char>
::type;
 
   51     static_assert(std::is_integral<PixNonConst>::value, 
"Pix* is expected to be cast-able to char*");
 
   53     return reinterpret_cast<Pix*
>(
reinterpret_cast<PixByte*
>(ptr) + bytes);
 
   58 template <
class Pix> 
inline 
   59 void fillBlock(Pix* trg, 
int pitch , Pix col, 
int blockWidth, 
int blockHeight)
 
   64     for (
int y = 0; y < blockHeight; ++y, trg = 
byteAdvance(trg, pitch))
 
   65         for (
int x = 0; x < blockWidth; ++x)
 
   71 template <
class PixSrc, 
class PixTrg, 
class PixConverter>
 
   73                             PixTrg* trg, 
int trgWidth, 
int trgHeight, 
int trgPitch ,
 
   74                           int yFirst, 
int yLast, PixConverter pixCvrt )
 
   76     static_assert(std::is_integral<PixSrc>::value, 
"PixSrc* is expected to be cast-able to char*");
 
   77     static_assert(std::is_integral<PixTrg>::value, 
"PixTrg* is expected to be cast-able to char*");
 
   79     static_assert(std::is_same<decltype(pixCvrt(PixSrc())), PixTrg>::value, 
"PixConverter returning wrong pixel format");
 
   81     if (srcPitch < srcWidth * 
static_cast<int>(
sizeof(PixSrc))  ||
 
   82         trgPitch < trgWidth * 
static_cast<int>(
sizeof(PixTrg)))
 
   88     yFirst = std::max(yFirst, 0);
 
   89     yLast  = std::min(yLast, trgHeight);
 
   90     if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) 
return;
 
   92     for (
int y = yFirst; y < yLast; ++y)
 
   94         const int ySrc = srcHeight * y / trgHeight;
 
   96         PixTrg*       
const trgLine = 
byteAdvance(trg, y    * trgPitch);
 
   98         for (
int x = 0; x < trgWidth; ++x)
 
  100             const int xSrc = srcWidth * x / trgWidth;
 
  101             trgLine[x] = pixCvrt(srcLine[xSrc]);
 
  108 template <
class PixSrc, 
class PixTrg, 
class PixConverter>
 
  110                                       PixTrg* trg, 
int trgWidth, 
int trgHeight, 
int trgPitch ,
 
  111                                     int yFirst, 
int yLast, PixConverter pixCvrt )
 
  113     static_assert(std::is_integral<PixSrc>::value, 
"PixSrc* is expected to be cast-able to char*");
 
  114     static_assert(std::is_integral<PixTrg>::value, 
"PixTrg* is expected to be cast-able to char*");
 
  116     static_assert(std::is_same<decltype(pixCvrt(PixSrc())), PixTrg>::value, 
"PixConverter returning wrong pixel format");
 
  118     if (srcPitch < srcWidth * 
static_cast<int>(
sizeof(PixSrc))  ||
 
  119         trgPitch < trgWidth * 
static_cast<int>(
sizeof(PixTrg)))
 
  125     yFirst = std::max(yFirst, 0);
 
  126     yLast  = std::min(yLast, srcHeight);
 
  127     if (yFirst >= yLast || trgWidth <= 0 || trgHeight <= 0) 
return;
 
  129     for (
int y = yFirst; y < yLast; ++y)
 
  135         const int yTrgFirst = ( y      * trgHeight + srcHeight - 1) / srcHeight; 
 
  136         const int yTrgLast  = ((y + 1) * trgHeight + srcHeight - 1) / srcHeight; 
 
  137         const int blockHeight = yTrgLast - yTrgFirst;
 
  142               PixTrg* trgLine = 
byteAdvance(trg, yTrgFirst * trgPitch);
 
  145             for (
int x = 0; x < srcWidth; ++x)
 
  147                 const int xTrgLast = ((x + 1) * trgWidth + srcWidth - 1) / srcWidth;
 
  148                 const int blockWidth = xTrgLast - xTrgFirst;
 
  151                     xTrgFirst = xTrgLast;
 
  153                     const auto trgPix = pixCvrt(srcLine[x]);
 
  154                     fillBlock(trgLine, trgPitch, trgPix, blockWidth, blockHeight);
 
  155                     trgLine += blockWidth;
 
  163 template <
class PixTrg, 
class PixConverter>
 
  165                        PixTrg* trg, 
int trgWidth, 
int trgHeight, 
int trgPitch,
 
  166                    int yFirst, 
int yLast, PixConverter pixCvrt )
 
  168     static_assert(std::is_integral<PixTrg>::value,                            
"PixTrg* is expected to be cast-able to char*");
 
  169     static_assert(std::is_same<decltype(pixCvrt(uint32_t())), PixTrg>::value, 
"PixConverter returning wrong pixel format");
 
  171     if (srcPitch < srcWidth * 
static_cast<int>(
sizeof(uint32_t)) ||
 
  172         trgPitch < trgWidth * 
static_cast<int>(
sizeof(PixTrg)))
 
  178     yFirst = std::max(yFirst, 0);
 
  179     yLast  = std::min(yLast, trgHeight);
 
  180     if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) 
return;
 
  182     const double scaleX = 
static_cast<double>(trgWidth ) / srcWidth;
 
  183     const double scaleY = 
static_cast<double>(trgHeight) / srcHeight;
 
  195     std::vector<CoeffsX> buf(trgWidth);
 
  196     for (
int x = 0; x < trgWidth; ++x)
 
  198         const int x1 = srcWidth * x / trgWidth;
 
  200         if (x2 == srcWidth) --x2;
 
  202         const double xx1 = x / scaleX - x1;
 
  203         const double x2x = 1 - xx1;
 
  205         buf[x] = { x1, x2, xx1, x2x };
 
  208     for (
int y = yFirst; y < yLast; ++y)
 
  210         const int y1 = srcHeight * y / trgHeight;
 
  212         if (y2 == srcHeight) --y2;
 
  214         const double yy1 = y / scaleY - y1;
 
  215         const double y2y = 1 - yy1;
 
  218         const uint32_t* 
const srcLineNext = 
byteAdvance(
src, y2 * srcPitch);
 
  219         PixTrg*         
const trgLine     = 
byteAdvance(trg, y  * trgPitch);
 
  221         for (
int x = 0; x < trgWidth; ++x)
 
  224             const int     x1 = buf[x].x1;
 
  225             const int     x2 = buf[x].x2;
 
  226             const double xx1 = buf[x].xx1;
 
  227             const double x2x = buf[x].x2x;
 
  229             const double x2xy2y = x2x * y2y;
 
  230             const double xx1y2y = xx1 * y2y;
 
  231             const double x2xyy1 = x2x * yy1;
 
  232             const double xx1yy1 = xx1 * yy1;
 
  234             auto interpolate = [=](
int offset)
 
  239                 const auto c11 = (srcLine    [x1] >> (8 * offset)) & 0xff;
 
  240                 const auto c21 = (srcLine    [x2] >> (8 * offset)) & 0xff;
 
  241                 const auto c12 = (srcLineNext[x1] >> (8 * offset)) & 0xff;
 
  242                 const auto c22 = (srcLineNext[x2] >> (8 * offset)) & 0xff;
 
  244                 return c11 * x2xy2y + c21 * xx1y2y +
 
  245                        c12 * x2xyy1 + c22 * xx1yy1;
 
  248             const double bi = interpolate(0);
 
  249             const double gi = interpolate(1);
 
  250             const double ri = interpolate(2);
 
  251             const double ai = interpolate(3);
 
  253             const auto b = 
static_cast<uint32_t
>(bi + 0.5);
 
  254             const auto g = 
static_cast<uint32_t
>(gi + 0.5);
 
  255             const auto r = 
static_cast<uint32_t
>(ri + 0.5);
 
  256             const auto a = 
static_cast<uint32_t
>(
ai + 0.5);
 
  258             const uint32_t trgPix = (a << 24) | (r << 16) | (
g << 8) | 
b;
 
  260             trgLine[x] = pixCvrt(trgPix);
 
A small explanation about what's going on here: Each action has access to two game_info objects First...
unsigned char getRed(uint32_t pix)
uint32_t makePixel(unsigned char a, unsigned char r, unsigned char g, unsigned char b)
uint32_t rgb565to888(uint16_t pix)
Pix * byteAdvance(Pix *ptr, int bytes)
unsigned char getBlue(uint32_t pix)
uint32_t rgb555to888(uint16_t pix)
unsigned char getGreen(uint32_t pix)
unsigned char getByte(uint32_t val)
void nearestNeighborScaleOverSource(const PixSrc *src, int srcWidth, int srcHeight, int srcPitch, PixTrg *trg, int trgWidth, int trgHeight, int trgPitch, int yFirst, int yLast, PixConverter pixCvrt)
void nearestNeighborScale(const uint32_t *src, int srcWidth, int srcHeight, uint32_t *trg, int trgWidth, int trgHeight)
uint16_t rgb888to555(uint32_t pix)
void fillBlock(Pix *trg, int pitch, Pix col, int blockWidth, int blockHeight)
unsigned char getAlpha(uint32_t pix)
void bilinearScale(const uint32_t *src, int srcWidth, int srcHeight, uint32_t *trg, int trgWidth, int trgHeight)
uint16_t rgb888to565(uint32_t pix)
rect src
Non-transparent portion of the surface to compose.