LCOV - code coverage report
Current view: top level - src - imagefilters.cpp (source / functions) Hit Total Coverage
Test: report Lines: 0 82 0.0 %
Date: 2015-07-11 18:23:49 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*
       2             : Copyright (C) 2015 Aaron Suen <warr1024@gmail.com>
       3             : 
       4             : This program is free software; you can redistribute it and/or modify
       5             : it under the terms of the GNU Lesser General Public License as published by
       6             : the Free Software Foundation; either version 2.1 of the License, or
       7             : (at your option) any later version.
       8             : 
       9             : This program is distributed in the hope that it will be useful,
      10             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             : GNU Lesser General Public License for more details.
      13             : 
      14             : You should have received a copy of the GNU Lesser General Public License along
      15             : with this program; if not, write to the Free Software Foundation, Inc.,
      16             : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             : */
      18             : 
      19             : #include "imagefilters.h"
      20             : #include "util/numeric.h"
      21             : #include <math.h>
      22             : 
      23             : /* Fill in RGB values for transparent pixels, to correct for odd colors
      24             :  * appearing at borders when blending.  This is because many PNG optimizers
      25             :  * like to discard RGB values of transparent pixels, but when blending then
      26             :  * with non-transparent neighbors, their RGB values will shpw up nonetheless.
      27             :  *
      28             :  * This function modifies the original image in-place.
      29             :  *
      30             :  * Parameter "threshold" is the alpha level below which pixels are considered
      31             :  * transparent.  Should be 127 for 3d where alpha is threshold, but 0 for
      32             :  * 2d where alpha is blended.
      33             :  */
      34           0 : void imageCleanTransparent(video::IImage *src, u32 threshold)
      35             : {
      36           0 :         core::dimension2d<u32> dim = src->getDimension();
      37             : 
      38             :         // Walk each pixel looking for fully transparent ones.
      39             :         // Note: loop y around x for better cache locality.
      40           0 :         for (u32 ctry = 0; ctry < dim.Height; ctry++)
      41           0 :         for (u32 ctrx = 0; ctrx < dim.Width; ctrx++) {
      42             : 
      43             :                 // Ignore opaque pixels.
      44           0 :                 irr::video::SColor c = src->getPixel(ctrx, ctry);
      45           0 :                 if (c.getAlpha() > threshold)
      46           0 :                         continue;
      47             : 
      48             :                 // Sample size and total weighted r, g, b values.
      49           0 :                 u32 ss = 0, sr = 0, sg = 0, sb = 0;
      50             : 
      51             :                 // Walk each neighbor pixel (clipped to image bounds).
      52           0 :                 for (u32 sy = (ctry < 1) ? 0 : (ctry - 1);
      53           0 :                                 sy <= (ctry + 1) && sy < dim.Height; sy++)
      54           0 :                 for (u32 sx = (ctrx < 1) ? 0 : (ctrx - 1);
      55           0 :                                 sx <= (ctrx + 1) && sx < dim.Width; sx++) {
      56             : 
      57             :                         // Ignore transparent pixels.
      58           0 :                         irr::video::SColor d = src->getPixel(sx, sy);
      59           0 :                         if (d.getAlpha() <= threshold)
      60           0 :                                 continue;
      61             : 
      62             :                         // Add RGB values weighted by alpha.
      63           0 :                         u32 a = d.getAlpha();
      64           0 :                         ss += a;
      65           0 :                         sr += a * d.getRed();
      66           0 :                         sg += a * d.getGreen();
      67           0 :                         sb += a * d.getBlue();
      68             :                 }
      69             : 
      70             :                 // If we found any neighbor RGB data, set pixel to average
      71             :                 // weighted by alpha.
      72           0 :                 if (ss > 0) {
      73           0 :                         c.setRed(sr / ss);
      74           0 :                         c.setGreen(sg / ss);
      75           0 :                         c.setBlue(sb / ss);
      76           0 :                         src->setPixel(ctrx, ctry, c);
      77             :                 }
      78             :         }
      79           0 : }
      80             : 
      81             : /* Scale a region of an image into another image, using nearest-neighbor with
      82             :  * anti-aliasing; treat pixels as crisp rectangles, but blend them at boundaries
      83             :  * to prevent non-integer scaling ratio artifacts.  Note that this may cause
      84             :  * some blending at the edges where pixels don't line up perfectly, but this
      85             :  * filter is designed to produce the most accurate results for both upscaling
      86             :  * and downscaling.
      87             :  */
      88           0 : void imageScaleNNAA(video::IImage *src, const core::rect<s32> &srcrect, video::IImage *dest)
      89             : {
      90             :         double sx, sy, minsx, maxsx, minsy, maxsy, area, ra, ga, ba, aa, pw, ph, pa;
      91             :         u32 dy, dx;
      92           0 :         video::SColor pxl;
      93             : 
      94             :         // Cache rectsngle boundaries.
      95           0 :         double sox = srcrect.UpperLeftCorner.X * 1.0;
      96           0 :         double soy = srcrect.UpperLeftCorner.Y * 1.0;
      97           0 :         double sw = srcrect.getWidth() * 1.0;
      98           0 :         double sh = srcrect.getHeight() * 1.0;
      99             : 
     100             :         // Walk each destination image pixel.
     101             :         // Note: loop y around x for better cache locality.
     102           0 :         core::dimension2d<u32> dim = dest->getDimension();
     103           0 :         for (dy = 0; dy < dim.Height; dy++)
     104           0 :         for (dx = 0; dx < dim.Width; dx++) {
     105             : 
     106             :                 // Calculate floating-point source rectangle bounds.
     107             :                 // Do some basic clipping, and for mirrored/flipped rects,
     108             :                 // make sure min/max are in the right order.
     109           0 :                 minsx = sox + (dx * sw / dim.Width);
     110           0 :                 minsx = rangelim(minsx, 0, sw);
     111           0 :                 maxsx = minsx + sw / dim.Width;
     112           0 :                 maxsx = rangelim(maxsx, 0, sw);
     113           0 :                 if (minsx > maxsx)
     114           0 :                         SWAP(double, minsx, maxsx);
     115           0 :                 minsy = soy + (dy * sh / dim.Height);
     116           0 :                 minsy = rangelim(minsy, 0, sh);
     117           0 :                 maxsy = minsy + sh / dim.Height;
     118           0 :                 maxsy = rangelim(maxsy, 0, sh);
     119           0 :                 if (minsy > maxsy)
     120           0 :                         SWAP(double, minsy, maxsy);
     121             : 
     122             :                 // Total area, and integral of r, g, b values over that area,
     123             :                 // initialized to zero, to be summed up in next loops.
     124           0 :                 area = 0;
     125           0 :                 ra = 0;
     126           0 :                 ga = 0;
     127           0 :                 ba = 0;
     128           0 :                 aa = 0;
     129             : 
     130             :                 // Loop over the integral pixel positions described by those bounds.
     131           0 :                 for (sy = floor(minsy); sy < maxsy; sy++)
     132           0 :                 for (sx = floor(minsx); sx < maxsx; sx++) {
     133             : 
     134             :                         // Calculate width, height, then area of dest pixel
     135             :                         // that's covered by this source pixel.
     136           0 :                         pw = 1;
     137           0 :                         if (minsx > sx)
     138           0 :                                 pw += sx - minsx;
     139           0 :                         if (maxsx < (sx + 1))
     140           0 :                                 pw += maxsx - sx - 1;
     141           0 :                         ph = 1;
     142           0 :                         if (minsy > sy)
     143           0 :                                 ph += sy - minsy;
     144           0 :                         if (maxsy < (sy + 1))
     145           0 :                                 ph += maxsy - sy - 1;
     146           0 :                         pa = pw * ph;
     147             : 
     148             :                         // Get source pixel and add it to totals, weighted
     149             :                         // by covered area and alpha.
     150           0 :                         pxl = src->getPixel((u32)sx, (u32)sy);
     151           0 :                         area += pa;
     152           0 :                         ra += pa * pxl.getRed();
     153           0 :                         ga += pa * pxl.getGreen();
     154           0 :                         ba += pa * pxl.getBlue();
     155           0 :                         aa += pa * pxl.getAlpha();
     156             :                 }
     157             : 
     158             :                 // Set the destination image pixel to the average color.
     159           0 :                 if (area > 0) {
     160           0 :                         pxl.setRed(ra / area + 0.5);
     161           0 :                         pxl.setGreen(ga / area + 0.5);
     162           0 :                         pxl.setBlue(ba / area + 0.5);
     163           0 :                         pxl.setAlpha(aa / area + 0.5);
     164             :                 } else {
     165           0 :                         pxl.setRed(0);
     166           0 :                         pxl.setGreen(0);
     167           0 :                         pxl.setBlue(0);
     168           0 :                         pxl.setAlpha(0);
     169             :                 }
     170           0 :                 dest->setPixel(dx, dy, pxl);
     171             :         }
     172           0 : }

Generated by: LCOV version 1.11