index d65cfd4e0d78178a49c92289ac5f231df38635ad..39c82daf6ed9ba5808f70514afd1b85b4c6efacc 100644 (file)
#include "display/nr-filter-utils.h"
#include "libnr/nr-pixblock.h"
#include "display/nr-filter-utils.h"
#include "libnr/nr-pixblock.h"
+#include "libnr/nr-blit.h"
namespace NR {
namespace NR {
* decimal part. (24.8 assuming 32-bit int)
*/
__attribute__ ((const))
* decimal part. (24.8 assuming 32-bit int)
*/
__attribute__ ((const))
-inline int sampley(unsigned const char a, unsigned const char b,
+inline static int sampley(unsigned const char a, unsigned const char b,
unsigned const char c, unsigned const char d,
const double len)
{
unsigned const char c, unsigned const char d,
const double len)
{
* Returns the interpolated value in 8-bit format, ready to be written
* to output buffer.
*/
* Returns the interpolated value in 8-bit format, ready to be written
* to output buffer.
*/
-inline int samplex(const int a, const int b, const int c, const int d, const double len) {
+inline static int samplex(const int a, const int b, const int c, const int d, const double len) {
double lenf = len - floor(len);
int sum = 0;
sum += (int)(a * (((-1.0 / 3.0) * lenf + 4.0 / 5.0) * lenf - 7.0 / 15.0) * lenf);
double lenf = len - floor(len);
int sum = 0;
sum += (int)(a * (((-1.0 / 3.0) * lenf + 4.0 / 5.0) * lenf - 7.0 / 15.0) * lenf);
* Catches reading and writing outside the pixblock area.
* When enabled, decreases filter rendering speed massively.
*/
* Catches reading and writing outside the pixblock area.
* When enabled, decreases filter rendering speed massively.
*/
-inline void _check_index(NRPixBlock const * const pb, int const location, int const line)
+inline static void _check_index(NRPixBlock const * const pb, int const location, int const line)
{
if(false) {
int max_loc = pb->rs * (pb->area.y1 - pb->area.y0);
{
if(false) {
int max_loc = pb->rs * (pb->area.y1 - pb->area.y0);
@@ -88,13 +89,22 @@ inline void _check_index(NRPixBlock const * const pb, int const location, int co
}
}
}
}
-void scale_bicubic(NRPixBlock *to, NRPixBlock *from)
+static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from)
{
if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) {
{
if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) {
- g_warning("A non-32-bpp image passed to scale_bicubic: scaling aborted.");
+ g_warning("A non-32-bpp image passed to scale_bicubic_rgba: scaling aborted.");
return;
}
return;
}
+ bool free_from_on_exit = false;
+ if (from->mode != to->mode){
+ NRPixBlock *o_from = from;
+ from = new NRPixBlock;
+ nr_pixblock_setup_fast(from, to->mode, o_from->area.x0, o_from->area.y0, o_from->area.x1, o_from->area.y1, false);
+ nr_blit_pixblock_pixblock(from, o_from);
+ free_from_on_exit = true;
+ }
+
// Precalculate sizes of source and destination pixblocks
int from_width = from->area.x1 - from->area.x0;
int from_height = from->area.y1 - from->area.y0;
// Precalculate sizes of source and destination pixblocks
int from_width = from->area.x1 - from->area.x0;
int from_height = from->area.y1 - from->area.y0;
}
}
}
}
}
}
+ if (free_from_on_exit) {
+ nr_pixblock_release(from);
+ delete from;
+ }
+
+}
+
+void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from)
+{
+ if (NR_PIXBLOCK_BPP(from) != 1 || NR_PIXBLOCK_BPP(to) != 1) {
+ g_warning("A non-8-bpp image passed to scale_bicubic_alpha: scaling aborted.");
+ return;
+ }
+
+ // Precalculate sizes of source and destination pixblocks
+ int from_width = from->area.x1 - from->area.x0;
+ int from_height = from->area.y1 - from->area.y0;
+ int to_width = to->area.x1 - to->area.x0;
+ int to_height = to->area.y1 - to->area.y0;
+
+ // from_step: when advancing one pixel in destination image,
+ // how much we should advance in source image
+ double from_stepx = (double)from_width / (double)to_width;
+ double from_stepy = (double)from_height / (double)to_height;
+
+ // Loop through every pixel of destination image, a line at a time
+ for (int to_y = 0 ; to_y < to_height ; to_y++) {
+ double from_y = to_y * from_stepy + from_stepy / 2;
+ // Pre-calculate beginning of the four horizontal lines, from
+ // which we should read
+ int from_line[4];
+ for (int i = 0 ; i < 4 ; i++) {
+ if ((int)floor(from_y) + i - 1 >= 0) {
+ if ((int)floor(from_y) + i - 1 < from_height) {
+ from_line[i] = ((int)floor(from_y) + i - 1) * from->rs;
+ } else {
+ from_line[i] = (from_height - 1) * from->rs;
+ }
+ } else {
+ from_line[i] = 0;
+ }
+ }
+ // Loop through this horizontal line in destination image
+ // For every pixel, calculate the color of pixel with
+ // bicubic interpolation and set the pixel value in destination image
+ for (int to_x = 0 ; to_x < to_width ; to_x++) {
+ double from_x = to_x * from_stepx + from_stepx / 2;
+ int line[4];
+ for (int i = 0 ; i < 4 ; i++) {
+ int k = (int)floor(from_x) + i - 1;
+ if (k < 0) k = 0;
+ if (k >= from_width) k = from_width - 1;
+ _check_index(from, from_line[0] + k, __LINE__);
+ _check_index(from, from_line[1] + k, __LINE__);
+ _check_index(from, from_line[2] + k, __LINE__);
+ _check_index(from, from_line[3] + k, __LINE__);
+ line[i] = sampley(NR_PIXBLOCK_PX(from)[from_line[0] + k],
+ NR_PIXBLOCK_PX(from)[from_line[1] + k],
+ NR_PIXBLOCK_PX(from)[from_line[2] + k],
+ NR_PIXBLOCK_PX(from)[from_line[3] + k],
+ from_y);
+ }
+ int result;
+ result = samplex(line[0], line[1], line[2], line[3],
+ from_x);
+
+ _check_index(to, to_y * to->rs + to_x, __LINE__);
+
+ NR_PIXBLOCK_PX(to)[to_y * to->rs + to_x] = clamp(result);
+ }
+ }
+}
+
+void scale_bicubic(NRPixBlock *to, NRPixBlock *from)
+{
+ if (NR_PIXBLOCK_BPP(to) == 4 && NR_PIXBLOCK_BPP(from) == 4) {
+ scale_bicubic_rgba(to, from);
+ } else if (NR_PIXBLOCK_BPP(to) == 1 && NR_PIXBLOCK_BPP(from) == 1) {
+ scale_bicubic_alpha(to, from);
+ } else {
+ g_warning("NR::scale_bicubic: unsupported bitdepths for scaling: to %d, from %d", NR_PIXBLOCK_BPP(to), NR_PIXBLOCK_BPP(from));
+ }
}
} /* namespace NR */
}
} /* namespace NR */