31 #include <boost/circular_buffer.hpp>
32 #include <boost/math/constants/constants.hpp>
36 SDL_version sdl_version;
37 SDL_GetVersion(&sdl_version);
38 return version_info(sdl_version.major, sdl_version.minor, sdl_version.patch);
45 if(ver.major < major)
return false;
46 if(ver.major > major)
return true;
48 if(ver.minor < minor)
return false;
49 if(ver.minor > minor)
return true;
51 if(ver.patch < patch)
return false;
61 PLAIN_LOG <<
"Cannot use xbrz scaling with zoom factor > 5.";
70 surface dst(surf->w *z, surf->h * z);
77 if(surf ==
nullptr || dst ==
nullptr) {
78 PLAIN_LOG <<
"Could not create surface to scale onto";
95 assert(SDL_ALPHA_TRANSPARENT==0);
100 if(
w == surf->w &&
h == surf->h) {
108 if (
w == 0 ||
h ==0) {
113 if(surf ==
nullptr || dst ==
nullptr) {
114 PLAIN_LOG <<
"Could not create surface to scale onto";
132 assert(SDL_ALPHA_TRANSPARENT==0);
137 if(
w == surf->w &&
h == surf->h) {
145 if (
w == 0 ||
h ==0) {
150 if(surf ==
nullptr || dst ==
nullptr) {
151 PLAIN_LOG <<
"Could not create surface to scale onto";
159 const uint32_t*
const src_pixels = src_lock.
pixels();
160 uint32_t*
const dst_pixels = dst_lock.
pixels();
166 for(
int ydst = 0; ydst !=
h; ++ydst, ysrc += yratio) {
168 for(
int xdst = 0; xdst !=
w; ++xdst, xsrc += xratio) {
172 const uint32_t*
const src_word = src_pixels + ysrcint*surf->w + xsrcint;
173 uint32_t*
const dst_word = dst_pixels + ydst*dst->w + xdst;
174 const int dx = (xsrcint + 1 < surf->w) ? 1 : 0;
175 const int dy = (ysrcint + 1 < surf->h) ? surf->w : 0;
178 uint32_t rr,gg,bb,aa, temp;
180 uint32_t pix[4], bilin[4];
203 const int32_t
e = 0x000000FF & xsrc;
204 const int32_t
s = 0x000000FF & ysrc;
205 const int32_t
n = 0xFF -
s;
208 const int32_t we = 0xFF -
e;
211 pix[1] = *(src_word + dx);
212 pix[2] = *(src_word + dy);
213 pix[3] = *(src_word + dx + dy);
221 rr = bb = gg = aa = 0;
222 for (loc=0; loc<4; loc++) {
234 temp = (
a * bilin[loc]);
250 *dst_word = (
a << 24) + (r << 16) + (
g << 8) +
b;
261 assert(SDL_ALPHA_TRANSPARENT==0);
266 if(
w == surf->w &&
h == surf->h) {
274 if(surf ==
nullptr || dst ==
nullptr) {
275 PLAIN_LOG <<
"Could not create surface to scale onto";
283 const uint32_t*
const src_pixels = src_lock.
pixels();
284 uint32_t*
const dst_pixels = dst_lock.
pixels();
290 for(
int ydst = 0; ydst !=
h; ++ydst, ysrc += yratio) {
292 for(
int xdst = 0; xdst !=
w; ++xdst, xsrc += xratio) {
296 const uint32_t*
const src_word = src_pixels + ysrcint*surf->w + xsrcint;
297 uint32_t*
const dst_word = dst_pixels + ydst*dst->w + xdst;
298 const int dx = (xsrcint + 1 < surf->w) ? 1 : 0;
299 const int dy = (ysrcint + 1 < surf->h) ? surf->w : 0;
302 uint32_t rr,gg,bb,aa;
303 uint16_t avg_r, avg_g, avg_b;
304 uint32_t pix[4], bilin[4];
318 const int32_t east = 0x000000FF & xsrc;
319 const int32_t south = 0x000000FF & ysrc;
320 const int32_t north = 0xFF - south;
321 const int32_t west = 0xFF - east;
324 pix[1] = *(src_word + dx);
325 pix[2] = *(src_word + dy);
326 pix[3] = *(src_word + dx + dy);
328 bilin[0] = north*west;
329 bilin[1] = north*east;
330 bilin[2] = south*west;
331 bilin[3] = south*east;
337 avg_r = avg_g = avg_b = 0;
339 for (loc=0; loc<4; loc++) {
366 rr = gg = bb = aa = 0;
367 for (loc=0; loc<4; loc++) {
373 r =
static_cast<uint8_t
>(avg_r);
374 g =
static_cast<uint8_t
>(avg_g);
375 b =
static_cast<uint8_t
>(avg_b);
377 rr += r * bilin[loc];
378 gg +=
g * bilin[loc];
379 bb +=
b * bilin[loc];
380 aa +=
a * bilin[loc];
386 *dst_word = (
a << 24) + (r << 16) + (
g << 8) +
b;
398 assert(SDL_ALPHA_TRANSPARENT==0);
403 if(
w == surf->w &&
h == surf->h) {
411 if (
w == 0 ||
h ==0) {
416 if(surf ==
nullptr || dst ==
nullptr) {
417 PLAIN_LOG <<
"Could not create surface to scale onto";
425 const uint32_t*
const src_pixels = src_lock.
pixels();
426 uint32_t*
const dst_pixels = dst_lock.
pixels();
428 float xratio =
static_cast<float>(surf->w) /
w;
429 float yratio =
static_cast<float>(surf->h) /
h;
432 for(
int ydst = 0; ydst !=
h; ++ydst, ysrc += yratio) {
434 for(
int xdst = 0; xdst !=
w; ++xdst, xsrc += xratio) {
435 float red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f;
437 float summation = 0.0f;
441 for(
float xloc = xsrc; xloc < xsrc+xratio; xloc += 1) {
442 const float xsize = std::min<float>(std::floor(xloc+1)-xloc,xsrc+xratio-xloc);
444 for(
float yloc = ysrc; yloc < ysrc+yratio; yloc += 1) {
445 const int xsrcint = std::max<int>(0,std::min<int>(surf->w-1,
static_cast<int>(xsrc)));
446 const int ysrcint = std::max<int>(0,std::min<int>(surf->h-1,
static_cast<int>(ysrc)));
447 const float ysize = std::min<float>(std::floor(yloc+1)-yloc,ysrc+yratio-yloc);
451 SDL_GetRGBA(src_pixels[ysrcint*surf->w + xsrcint],surf->format,&r,&
g,&
b,&
a);
452 float value = xsize * ysize;
464 red = red / alpha + 0.5f;
465 green = green / alpha + 0.5f;
466 blue = blue / alpha + 0.5f;
467 alpha = alpha / summation + 0.5f;
470 dst_pixels[ydst*dst->w + xdst] = SDL_MapRGBA(
472 ,
static_cast<uint8_t
>(red)
473 ,
static_cast<uint8_t
>(green)
474 ,
static_cast<uint8_t
>(blue)
475 ,
static_cast<uint8_t
>(alpha));
489 if((red == 0 && green == 0 && blue == 0)) {
496 if(nsurf ==
nullptr) {
497 PLAIN_LOG <<
"failed to make neutral surface";
503 uint32_t* beg = lock.
pixels();
504 uint32_t* end = beg + nsurf->w*surf->h;
507 uint8_t alpha = (*beg) >> 24;
515 r = std::max<int>(0,std::min<int>(255,
static_cast<int>(r)+red));
516 g = std::max<int>(0,std::min<int>(255,
static_cast<int>(
g)+green));
517 b = std::max<int>(0,std::min<int>(255,
static_cast<int>(
b)+blue));
519 *beg = (alpha << 24) + (r << 16) + (
g << 8) +
b;
535 if(nsurf ==
nullptr) {
536 PLAIN_LOG <<
"failed to make neutral surface";
542 uint32_t* beg = lock.
pixels();
543 uint32_t* end = beg + nsurf->w*surf->h;
546 uint8_t alpha = (*beg) >> 24;
559 const uint8_t avg =
static_cast<uint8_t
>((
560 77 *
static_cast<uint16_t
>(r) +
561 150 *
static_cast<uint16_t
>(
g) +
562 29 *
static_cast<uint16_t
>(
b) ) / 256);
564 *beg = (alpha << 24) | (avg << 16) | (avg << 8) | avg;
580 if(nsurf ==
nullptr) {
581 PLAIN_LOG <<
"failed to make neutral surface";
587 uint32_t* beg = lock.
pixels();
588 uint32_t* end = beg + nsurf->w*surf->h;
591 uint8_t alpha = (*beg) >> 24;
594 uint8_t r,
g,
b, result;
602 result =
static_cast<uint8_t
>(0.299 * r + 0.587 *
g + 0.114 *
b) > threshold ? 255 : 0;
604 *beg = (alpha << 24) | (result << 16) | (result << 8) | result;
620 if(nsurf ==
nullptr) {
621 PLAIN_LOG <<
"failed to make neutral surface";
627 uint32_t* beg = lock.
pixels();
628 uint32_t* end = beg + nsurf->w*surf->h;
631 uint8_t alpha = (*beg) >> 24;
642 uint8_t outRed = std::min(255,
static_cast<int>((r * 0.393) + (
g * 0.769) + (
b * 0.189)));
643 uint8_t outGreen = std::min(255,
static_cast<int>((r * 0.349) + (
g * 0.686) + (
b * 0.168)));
644 uint8_t outBlue = std::min(255,
static_cast<int>((r * 0.272) + (
g * 0.534) + (
b * 0.131)));
646 *beg = (alpha << 24) | (outRed << 16) | (outGreen << 8) | (outBlue);
662 if(nsurf ==
nullptr) {
663 PLAIN_LOG <<
"failed to make neutral surface";
669 uint32_t* beg = lock.
pixels();
670 uint32_t* end = beg + nsurf->w*surf->h;
673 uint8_t alpha = (*beg) >> 24;
676 uint8_t r,
g,
b, newR, newG, newB;
685 newR = r > thresholdR ? 255 - r : r;
686 newG =
g > thresholdG ? 255 -
g :
g;
687 newB =
b > thresholdB ? 255 -
b :
b;
689 *beg = (alpha << 24) | (newR << 16) | (newG << 8) | (newB);
705 if(nsurf ==
nullptr) {
706 PLAIN_LOG <<
"failed to make neutral surface";
712 uint32_t* beg = lock.
pixels();
713 uint32_t* end = beg + nsurf->w*surf->h;
716 uint8_t alpha = (*beg) >> 24;
718 *beg = (0xff << 24) | (alpha << 16) | (alpha << 8) | alpha;
733 if(nsurf ==
nullptr) {
734 PLAIN_LOG <<
"failed to make neutral surface";
740 uint32_t* beg = lock.
pixels();
741 uint32_t* end = beg + nsurf->w*surf->h;
745 *beg = 0xff000000 | *beg;
763 if(nsurf ==
nullptr) {
764 PLAIN_LOG <<
"failed to blur the shadow surface";
770 uint32_t* beg = lock.
pixels();
771 uint32_t* end = beg + nsurf->w*surf->h;
774 uint8_t alpha = (*beg) >> 24;
780 *beg = (alpha*4) << 24;
797 if(nsurf ==
nullptr) {
798 PLAIN_LOG <<
"failed to make neutral surface";
804 uint32_t* beg = lock.
pixels();
805 uint32_t* end = beg + nsurf->w*surf->h;
808 uint8_t alpha = (*beg) >> 24;
811 uint8_t red, green, blue, newRed, newGreen, newBlue, newAlpha;
884 *beg = (newAlpha << 24) | (newRed << 16) | (newGreen << 8) | newBlue;
899 if(map_rgb.empty()) {
904 if(nsurf ==
nullptr) {
905 PLAIN_LOG <<
"failed to make neutral surface";
910 uint32_t* beg = lock.
pixels();
911 uint32_t* end = beg + nsurf->w*surf->h;
914 uint8_t alpha = (*beg) >> 24;
919 uint32_t oldrgb = (*beg) | 0xFF000000;
922 if(
i != map_rgb.end()) {
923 *beg = (alpha << 24) | (
i->second.to_argb_bytes() & 0x00FFFFFF);
935 if(surf ==
nullptr) {
941 if(nsurf ==
nullptr) {
942 PLAIN_LOG <<
"could not make neutral surface...";
948 uint32_t* beg = lock.
pixels();
949 uint32_t* end = beg + nsurf->w*surf->h;
951 if (amount < 0) amount = 0;
953 uint8_t alpha = (*beg) >> 24;
965 *beg = (alpha << 24) + (r << 16) + (
g << 8) +
b;
977 if(surf ==
nullptr) {
981 SDL_SetSurfaceAlphaMod(surf, alpha_mod);
992 if(nsurf ==
nullptr) {
993 PLAIN_LOG <<
"could not make neutral surface...";
999 uint32_t* beg = lock.
pixels();
1000 uint32_t* end = beg + nsurf->w*surf->h;
1003 uint8_t alpha = (*beg) >> 24;
1011 alpha = uint8_t(std::max<int>(0,std::min<int>(255,
static_cast<int>(alpha) + amount)));
1012 *beg = (alpha << 24) + (r << 16) + (
g << 8) +
b;
1024 if(surf ==
nullptr) {
1025 *empty_result =
true;
1028 if(mask ==
nullptr) {
1035 if(nsurf ==
nullptr || nmask ==
nullptr) {
1036 PLAIN_LOG <<
"could not make neutral surface...";
1039 if (nsurf->w != nmask->w) {
1044 std::stringstream ss;
1045 ss <<
"Detected an image with bad dimensions: ";
1046 if(!filename.empty()) ss << filename <<
": ";
1047 ss << nsurf->w <<
"x" << nsurf->h;
1049 PLAIN_LOG <<
"It will not be masked, please use: "<< nmask->w <<
"x" << nmask->h;
1058 uint32_t* beg = lock.
pixels();
1059 uint32_t* end = beg + nsurf->w*surf->h;
1060 const uint32_t* mbeg = mlock.
pixels();
1061 const uint32_t* mend = mbeg + nmask->w*nmask->h;
1063 while(beg != end && mbeg != mend) {
1064 uint8_t alpha = (*beg) >> 24;
1072 uint8_t malpha = (*mbeg) >> 24;
1073 if (alpha > malpha) {
1079 *beg = (alpha << 24) + (r << 16) + (
g << 8) +
b;
1087 *empty_result = empty;
1094 if(surf ==
nullptr) {
1097 if(mask ==
nullptr){
1101 if (surf->w != mask->w || surf->h != mask->h ) {
1109 if(nsurf ==
nullptr || nmask ==
nullptr) {
1110 PLAIN_LOG <<
"could not make neutral surface...";
1118 const uint32_t* mbeg = mlock.
pixels();
1119 const uint32_t* mend = mbeg + nmask->w*nmask->h;
1120 uint32_t* beg = lock.
pixels();
1123 while(mbeg != mend) {
1124 uint8_t malpha = (*mbeg) >> 24;
1126 uint8_t alpha = (*beg) >> 24;
1140 if(surf ==
nullptr) {
1143 if(lightmap ==
nullptr) {
1149 if(nsurf ==
nullptr) {
1150 PLAIN_LOG <<
"could not make neutral surface...";
1153 if (nsurf->w != lightmap->w) {
1158 PLAIN_LOG <<
"Detected an image with bad dimensions: " << nsurf->w <<
"x" << nsurf->h;
1159 PLAIN_LOG <<
"It will not be lighted, please use: "<< lightmap->w <<
"x" << lightmap->h;
1166 uint32_t* beg = lock.
pixels();
1167 uint32_t* end = beg + nsurf->w * nsurf->h;
1168 const uint32_t* lbeg = llock.
pixels();
1169 const uint32_t* lend = lbeg + lightmap->w * lightmap->h;
1171 while(beg != end && lbeg != lend) {
1172 uint8_t alpha = (*beg) >> 24;
1185 int dr = (
static_cast<int>(lr) - 128) * 2;
1186 int dg = (
static_cast<int>(
lg) - 128) * 2;
1187 int db = (
static_cast<int>(lb) - 128) * 2;
1189 r = std::max<int>(0,std::min<int>(255, r + dr));
1190 g = std::max<int>(0,std::min<int>(255,
g + dg));
1191 b = std::max<int>(0,std::min<int>(255,
b + db));
1193 *beg = (alpha << 24) + (r << 16) + (
g << 8) +
b;
1206 if(surf ==
nullptr) {
1212 if(res ==
nullptr) {
1213 PLAIN_LOG <<
"could not make neutral surface...";
1217 SDL_Rect
rect {0, 0, surf->w, surf->h};
1225 if(surf ==
nullptr) {
1229 const int max_blur = 256;
1230 if(depth > max_blur) {
1234 uint32_t queue[max_blur];
1235 const uint32_t* end_queue = queue + max_blur;
1237 const uint32_t ff = 0xff;
1239 const unsigned pixel_offset =
rect.y * surf->w +
rect.x;
1242 for(
int y = 0; y <
rect.h; ++y) {
1243 const uint32_t* front = &queue[0];
1244 uint32_t* back = &queue[0];
1245 uint32_t red = 0, green = 0, blue = 0, avg = 0;
1246 uint32_t*
p = lock.
pixels() + pixel_offset + y * surf->w;
1247 for(
int x = 0; x <= depth && x <
rect.w; ++x, ++
p) {
1248 red += ((*p) >> 16)&0xFF;
1249 green += ((*p) >> 8)&0xFF;
1253 if(back == end_queue) {
1258 p = lock.
pixels() + pixel_offset + y * surf->w;
1259 for(
int x = 0; x <
rect.w; ++x, ++
p) {
1261 | (std::min(red/avg,ff) << 16)
1262 | (std::min(green/avg,ff) << 8)
1263 | std::min(blue/avg,ff);
1266 red -= ((*front) >> 16)&0xFF;
1267 green -= ((*front) >> 8)&0xFF;
1268 blue -= *front&0xFF;
1271 if(front == end_queue) {
1276 if(x + depth+1 <
rect.w) {
1277 uint32_t* q =
p + depth+1;
1278 red += ((*q) >> 16)&0xFF;
1279 green += ((*q) >> 8)&0xFF;
1283 if(back == end_queue) {
1290 for(
int x = 0; x <
rect.w; ++x) {
1291 const uint32_t* front = &queue[0];
1292 uint32_t* back = &queue[0];
1293 uint32_t red = 0, green = 0, blue = 0, avg = 0;
1294 uint32_t*
p = lock.
pixels() + pixel_offset + x;
1295 for(
int y = 0; y <= depth && y <
rect.h; ++y,
p += surf->w) {
1296 red += ((*p) >> 16)&0xFF;
1297 green += ((*p) >> 8)&0xFF;
1301 if(back == end_queue) {
1306 p = lock.
pixels() + pixel_offset + x;
1307 for(
int y = 0; y <
rect.h; ++y,
p += surf->w) {
1309 | (std::min(red/avg,ff) << 16)
1310 | (std::min(green/avg,ff) << 8)
1311 | std::min(blue/avg,ff);
1314 red -= ((*front) >> 16)&0xFF;
1315 green -= ((*front) >> 8)&0xFF;
1316 blue -= *front&0xFF;
1319 if(front == end_queue) {
1324 if(y + depth+1 <
rect.h) {
1325 uint32_t* q =
p + (depth+1)*surf->w;
1326 red += ((*q) >> 16)&0xFF;
1327 green += ((*q) >> 8)&0xFF;
1331 if(back == end_queue) {
1341 if(surf ==
nullptr) {
1347 if(res ==
nullptr) {
1348 PLAIN_LOG <<
"could not make neutral surface...";
1352 const int max_blur = 256;
1353 if(depth > max_blur) {
1363 : alpha(((*
p) >> 24)&0xFF)
1364 , red(((*
p) >> 16)&0xFF)
1365 , green(((*
p) >> 8)&0xFF)
1366 , blue((*
p)&0xFF) {}
1373 Average() : alpha(), red(), green(), blue()
1375 Average& operator+=(
const Pixel& pix){
1376 red += pix.alpha * pix.red;
1377 green += pix.alpha * pix.green;
1378 blue += pix.alpha * pix.blue;
1382 Average& operator-=(
const Pixel& pix){
1383 red -= pix.alpha * pix.red;
1384 green -= pix.alpha * pix.green;
1385 blue -= pix.alpha * pix.blue;
1389 uint32_t operator()(
unsigned num){
1390 const uint32_t ff = 0xff;
1394 return (std::min(alpha/num,ff) << 24)
1395 | (std::min(red/alpha,ff) << 16)
1396 | (std::min(green/alpha,ff) << 8)
1397 | std::min(blue/alpha,ff);
1401 boost::circular_buffer<Pixel> queue(depth*2+1);
1406 for(y = 0; y < res->h; ++y) {
1411 uint32_t*
p = lock.
pixels() + y*res->w;
1412 for(x = 0; x <= depth && x < res->w; ++x, ++
p) {
1413 assert(!queue.full());
1414 queue.push_back(Pixel{
p});
1415 avg += queue.back();
1420 for(x = 0; x < res->w; ++x, ++
p) {
1422 const uint32_t num = queue.size();
1427 avg -= queue.front();
1428 assert(!queue.empty());
1433 if(x + depth+1 < res->w) {
1434 uint32_t* q =
p + depth+1;
1435 assert(!queue.full());
1436 queue.push_back(Pixel{q});
1437 avg += queue.back();
1440 assert(
static_cast<int>(queue.size()) == std::min(depth, res->w));
1445 for(x = 0; x < res->w; ++x) {
1450 uint32_t*
p = lock.
pixels() + x;
1451 for(y = 0; y <= depth && y < res->h; ++y,
p += res->w) {
1452 assert(!queue.full());
1453 queue.push_back(Pixel{
p});
1454 avg += queue.back();
1459 for(y = 0; y < res->h; ++y,
p += res->w) {
1461 const uint32_t num = queue.size();
1466 avg -= queue.front();
1467 assert(!queue.empty());
1472 if(y + depth+1 < res->h) {
1473 uint32_t* q =
p + (depth+1)*res->w;
1474 assert(!queue.full());
1475 queue.push_back(Pixel{q});
1476 avg += queue.back();
1479 assert(
static_cast<int>(queue.size()) == std::min(depth, res->h));
1493 if(res ==
nullptr) {
1494 PLAIN_LOG <<
"Could not create a new surface in cut_surface()";
1498 std::size_t sbpp = surf->format->BytesPerPixel;
1499 std::size_t spitch = surf->pitch;
1500 std::size_t rbpp = res->format->BytesPerPixel;
1501 std::size_t rpitch = res->pitch;
1504 SDL_Rect src_rect = r;
1505 SDL_Rect dst_rect { 0, 0, r.w, r.h };
1507 if (src_rect.x < 0) {
1508 if (src_rect.x + src_rect.w <= 0)
1510 dst_rect.x -= src_rect.x;
1511 dst_rect.w += src_rect.x;
1512 src_rect.w += src_rect.x;
1515 if (src_rect.y < 0) {
1516 if (src_rect.y + src_rect.h <= 0)
1518 dst_rect.y -= src_rect.y;
1519 dst_rect.h += src_rect.y;
1520 src_rect.h += src_rect.y;
1524 if(src_rect.x >= surf->w || src_rect.y >= surf->h)
1530 const uint8_t* src =
reinterpret_cast<const uint8_t *
>(slock.
pixels());
1531 uint8_t* dest =
reinterpret_cast<uint8_t *
>(rlock.
pixels());
1533 for(
int y = 0; y < src_rect.h && (src_rect.y + y) < surf->h; ++y) {
1534 const uint8_t* line_src = src + (src_rect.y + y) * spitch + src_rect.x * sbpp;
1535 uint8_t* line_dest = dest + (dst_rect.y + y) * rpitch + dst_rect.x * rbpp;
1536 std::size_t
size = src_rect.w + src_rect.x <= surf->w ? src_rect.w : surf->w - src_rect.x;
1538 assert(rpitch >= src_rect.w * rbpp);
1539 memcpy(line_dest, line_src,
size * rbpp);
1546 ,
const double amount
1549 if(surf==
nullptr) {
1555 if(nsurf ==
nullptr) {
1556 PLAIN_LOG <<
"could not make neutral surface...";
1562 uint32_t* beg = lock.
pixels();
1563 uint32_t* end = beg + nsurf->w*surf->h;
1565 uint16_t ratio = amount * 256;
1566 const uint16_t red = ratio * color.r;
1567 const uint16_t green = ratio * color.g;
1568 const uint16_t blue = ratio * color.b;
1569 ratio = 256 - ratio;
1572 uint8_t
a =
static_cast<uint8_t
>(*beg >> 24);
1573 uint8_t r = (ratio *
static_cast<uint8_t
>(*beg >> 16) + red) >> 8;
1574 uint8_t
g = (ratio *
static_cast<uint8_t
>(*beg >> 8) + green) >> 8;
1575 uint8_t
b = (ratio *
static_cast<uint8_t
>(*beg) + blue) >> 8;
1577 *beg = (
a << 24) | (r << 16) | (
g << 8) |
b;
1593 int src_w, src_h, dst_w, dst_h;
1594 float min_x, min_y, sine, cosine;
1598 const float radians = angle * boost::math::constants::pi<float>() / 180;
1599 cosine = std::cos(radians);
1600 sine = std::sin(radians);
1602 src_w = surf->w * zoom;
1603 src_h = surf->h * zoom;
1605 const float point_1x = src_h * -sine;
1606 const float point_1y = src_h * cosine;
1607 const float point_2x = src_w * cosine - src_h * sine;
1608 const float point_2y = src_h * cosine + src_w * sine;
1609 const float point_3x = src_w * cosine;
1610 const float point_3y = src_w * sine;
1614 min_x = std::min(0.0F, std::min(point_1x, std::min(point_2x, point_3x)));
1615 min_y = std::min(0.0F, std::min(point_1y, std::min(point_2y, point_3y)));
1616 max_x = (angle > 90 && angle < 180) ? 0 : std::max(point_1x, std::max(point_2x, point_3x));
1617 max_y = (angle > 180 && angle < 270) ? 0 : std::max(point_1y, std::max(point_2y, point_3y));
1618 dst_w =
static_cast<int>(ceil(std::abs(max_x) - min_x)) / zoom;
1619 dst_h =
static_cast<int>(ceil(std::abs(max_y) - min_y)) / zoom;
1626 const float scale = 1.f / zoom;
1627 const int max_x = dst_w * zoom;
1628 const int max_y = dst_h * zoom;
1631 for (
int x = 0; x < max_x; x += offset)
1632 for (
int y = 0; y < max_y; y += offset) {
1634 const float source_x = (x + min_x)*cosine + (y + min_y)*sine;
1635 const float source_y = (y + min_y)*cosine - (x + min_x)*sine;
1637 if (source_x >= 0 && source_x < src_w
1638 && source_y >= 0 && source_y < src_h)
1641 get_pixel(src, src_lock, source_x, source_y));
1650 const int bpp = surf->format->BytesPerPixel;
1652 uint8_t*
const dst =
reinterpret_cast<uint8_t*
>(surf_lock.
pixels()) + y * surf->pitch + x * bpp;
1658 *
reinterpret_cast<uint16_t*
>(dst) = pixel;
1661 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1662 dst[0] = (pixel >> 16) & 0xff;
1663 dst[1] = (pixel >> 8) & 0xff;
1664 dst[2] = pixel & 0xff;
1666 dst[0] = pixel & 0xff;
1667 dst[1] = (pixel >> 8) & 0xff;
1668 dst[2] = (pixel >> 16) & 0xff;
1672 *
reinterpret_cast<uint32_t*
>(dst) = pixel;
1681 const int bpp = surf->format->BytesPerPixel;
1683 const uint8_t*
const src =
reinterpret_cast<const uint8_t*
>(surf_lock.
pixels()) + y * surf->pitch + x * bpp;
1688 return *
reinterpret_cast<const uint16_t*
>(src);
1690 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
1691 return src[0] << 16 | src[1] << 8 | src[2];
1693 return src[0] | src[1] << 8 | src[2] << 16;
1696 return *
reinterpret_cast<const uint32_t*
>(src);
1704 if ( surf ==
nullptr )
1710 if ( nsurf ==
nullptr ) {
1711 PLAIN_LOG <<
"could not make neutral surface...";
1717 uint32_t*
const pixels = lock.
pixels();
1721 for (
int y=0; y != nsurf->h/2; ++y) {
1722 for(
int x=0; x != nsurf->w; ++x) {
1723 const int index1 = y*nsurf->w + x;
1724 const int index2 = (nsurf->h-y)*nsurf->w - x - 1;
1725 std::swap(pixels[index1],pixels[index2]);
1729 if (
is_odd(nsurf->h) ) {
1731 for (
int x=0; x != nsurf->w/2; ++x) {
1732 const int index1 = (nsurf->h/2)*nsurf->w + x;
1733 const int index2 = (nsurf->h/2)*nsurf->w + (nsurf->w - x - 1);
1734 std::swap(pixels[index1],pixels[index2]);
1746 if ( surf ==
nullptr )
1749 surface dst(surf->h, surf->w);
1751 if ( surf ==
nullptr || dst ==
nullptr ) {
1752 PLAIN_LOG <<
"could not make neutral surface...";
1760 const uint32_t*
const src_pixels = src_lock.
pixels();
1761 uint32_t*
const dst_pixels = dst_lock.
pixels();
1764 for(
int y = 0; y != surf->h; ++y) {
1765 for (
int x = 0; x != surf->w; ++x ) {
1766 const int src_index = y*surf->w + x;
1767 const int dst_index = clockwise ?
1768 x*dst->w + (dst->w-1-y) :
1769 (dst->h-1-x)*dst->w + y;
1770 dst_pixels[dst_index] = src_pixels[src_index];
1781 if(surf ==
nullptr) {
1787 if(nsurf ==
nullptr) {
1788 PLAIN_LOG <<
"could not make neutral surface...";
1794 uint32_t*
const pixels = lock.
pixels();
1796 for(
int y = 0; y != nsurf->h; ++y) {
1797 for(
int x = 0; x != nsurf->w/2; ++x) {
1798 const int index1 = y*nsurf->w + x;
1799 const int index2 = (y+1)*nsurf->w - x - 1;
1800 std::swap(pixels[index1],pixels[index2]);
1810 if(surf ==
nullptr) {
1816 if(nsurf ==
nullptr) {
1817 PLAIN_LOG <<
"could not make neutral surface...";
1823 uint32_t*
const pixels = lock.
pixels();
1825 for(
int x = 0; x != nsurf->w; ++x) {
1826 for(
int y = 0; y != nsurf->h/2; ++y) {
1827 const int index1 = y*nsurf->w + x;
1828 const int index2 = (nsurf->h-y-1)*surf->w + x;
1829 std::swap(pixels[index1],pixels[index2]);
1839 if (src ==
nullptr) {
1844 if(area.x >= src->w || area.y >= src->h || area.x + area.w < 0 || area.y + area.h < 0) {
1848 if(area.x + area.w > src->w) {
1849 area.w = src->w - area.x;
1851 if(area.y + area.h > src->h) {
1852 area.h = src->h - area.y;
1858 if(dst ==
nullptr) {
1859 PLAIN_LOG <<
"Could not create a new surface in get_surface_portion()";
1864 SDL_BlendMode src_blend;
1865 SDL_GetSurfaceBlendMode(src, &src_blend);
1866 SDL_SetSurfaceBlendMode(src, SDL_BLENDMODE_NONE);
1867 SDL_BlitSurface(src, &area, dst,
nullptr);
1868 SDL_SetSurfaceBlendMode(src, src_blend);
1880 bool operator()(uint32_t pixel)
const {
1881 uint8_t alpha = pixel >> 24;
1882 return alpha != 0x00;
1890 SDL_Rect res {0,0,0,0};
1892 if(nsurf ==
nullptr) {
1893 PLAIN_LOG <<
"failed to make neutral surface";
1897 const not_alpha calc;
1900 const uint32_t*
const pixels = lock.
pixels();
1903 for(
n = 0;
n != nsurf->h; ++
n) {
1904 const uint32_t*
const start_row = pixels +
n*nsurf->w;
1905 const uint32_t*
const end_row = start_row + nsurf->w;
1907 if(std::find_if(start_row,end_row,calc) != end_row)
1913 for(
n = 0;
n != nsurf->h-res.y; ++
n) {
1914 const uint32_t*
const start_row = pixels + (nsurf->h-
n-1)*surf->w;
1915 const uint32_t*
const end_row = start_row + nsurf->w;
1917 if(std::find_if(start_row,end_row,calc) != end_row)
1924 res.h = nsurf->h - res.y -
n;
1926 for(
n = 0;
n != nsurf->w; ++
n) {
1928 for(y = 0; y != nsurf->h; ++y) {
1929 const uint32_t pixel = pixels[y*nsurf->w +
n];
1940 for(
n = 0;
n != nsurf->w-res.x; ++
n) {
1942 for(y = 0; y != nsurf->h; ++y) {
1943 const uint32_t pixel = pixels[y*nsurf->w + surf->w -
n - 1];
1952 res.w = nsurf->w - res.x -
n;
Helper class for pinning SDL surfaces into memory.
surface clone() const
Makes a copy of this surface.
Represents version numbers.
std::unordered_map< color_t, color_t > color_range_map
void swap(config &lhs, config &rhs)
Implement non-member swap function for std::swap (calls config::swap).
Standard logging facilities (interface).
constexpr int fixed_point_to_int(int32_t n)
If positive, just bit shift.
constexpr bool is_odd(T num)
constexpr unsigned fixed_point_multiply(int32_t n1, int32_t n2)
constexpr int32_t fixed_point_divide(int n1, int n2)
version_info get_version()
Returns the runtime SDL version.
bool runtime_at_least(uint8_t major, uint8_t minor=0, uint8_t patch=0)
Returns true if the runtime SDL version is at or greater than the specified version,...
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
void nearestNeighborScale(const uint32_t *src, int srcWidth, int srcHeight, uint32_t *trg, int trgWidth, int trgHeight)
void scale(size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight, const ScalerCfg &cfg=ScalerCfg(), int yFirst=0, int yLast=std::numeric_limits< int >::max())
Contains the SDL_Rect helper code.
The basic class for representing 8-bit RGB or RGBA colour values.
static constexpr color_t from_argb_bytes(uint32_t c)
Creates a new color_t object from a uint32_t variable.
An abstract description of a rectangle with integer coordinates.
static map_location::DIRECTION n
static map_location::DIRECTION s
surface alpha_to_greyscale(const surface &surf)
surface blur_alpha_surface(const surface &surf, int depth)
Cross-fades a surface with alpha channel.
surface adjust_surface_color(const surface &surf, int red, int green, int blue)
surface recolor_image(surface surf, const color_range_map &map_rgb)
Recolors a surface using a map with source and converted palette values.
surface negative_image(const surface &surf, const int thresholdR, const int thresholdG, const int thresholdB)
surface swap_channels_image(const surface &surf, channel r, channel g, channel b, channel a)
surface light_surface(const surface &surf, const surface &lightmap)
Light surf using lightmap.
surface shadow_image(const surface &surf, int scale)
create an heavy shadow of the image, by blurring, increasing alpha and darkening
surface scale_surface_nn(const surface &surf, int w, int h)
Scale a surface using the nearest neighbor algorithm (provided by xBRZ lib)
surface scale_surface_legacy(const surface &surf, int w, int h)
Scale a surface using simple bilinear filtering (discarding rgb from source pixels with 0 alpha)
void put_pixel(const surface &surf, surface_lock &surf_lock, int x, int y, uint32_t pixel)
Helper methods for setting/getting a single pixel in an image.
surface adjust_surface_alpha_add(const surface &surf, int amount)
surface flip_surface(const surface &surf)
void adjust_surface_alpha(surface &surf, uint8_t alpha_mod)
surface sepia_image(const surface &surf)
surface blur_surface(const surface &surf, int depth)
Cross-fades a surface.
surface blend_surface(const surface &surf, const double amount, const color_t color)
Blends a surface with a color.
uint32_t get_pixel(const surface &surf, const const_surface_lock &surf_lock, int x, int y)
surface cut_surface(const surface &surf, const SDL_Rect &r)
Cuts a rectangle from a surface.
surface wipe_alpha(const surface &surf)
surface flop_surface(const surface &surf)
surface brighten_image(const surface &surf, int32_t amount)
surface get_surface_portion(const surface &src, SDL_Rect &area)
Get a portion of the screen.
surface scale_surface_xbrz(const surface &surf, std::size_t z)
Scale a surface using xBRZ algorithm.
SDL_Rect get_non_transparent_portion(const surface &surf)
surface scale_surface_sharp(const surface &surf, int w, int h)
Scale a surface using modified nearest neighbour algorithm.
surface monochrome_image(const surface &surf, const int threshold)
surface rotate_90_surface(const surface &surf, bool clockwise)
Rotates a surface 90 degrees.
surface rotate_180_surface(const surface &surf)
Rotates a surface 180 degrees.
surface greyscale_image(const surface &surf)
surface scale_surface(const surface &surf, int w, int h)
Scale a surface using alpha-weighted modified bilinear filtering Note: causes artifacts with alpha gr...
surface mask_surface(const surface &surf, const surface &mask, bool *empty_result, const std::string &filename)
Applies a mask on a surface.
surface rotate_any_surface(const surface &surf, float angle, int zoom, int offset)
Rotates a surface by any degrees.
bool in_mask_surface(const surface &surf, const surface &mask)
Check if a surface fit into a mask.