mirror of
https://github.com/aseprite/aseprite.git
synced 2025-04-01 10:21:04 +00:00
Merge pull request #11 from DocHoncho/issue-295-dev
Re-implement nearest-neighbor interpolation
This commit is contained in:
commit
ab42d38947
src/raster
@ -35,23 +35,22 @@ void resize_image(const Image* src, Image* dst, ResizeMethod method, const Palet
|
|||||||
switch (method) {
|
switch (method) {
|
||||||
|
|
||||||
// TODO optimize this
|
// TODO optimize this
|
||||||
case RESIZE_METHOD_NEAREST_NEIGHBOR: {
|
case RESIZE_METHOD_NEAREST_NEIGHBOR:
|
||||||
uint32_t color;
|
{
|
||||||
double u, v, du, dv;
|
int o_width = src->getWidth(), o_height = src->getHeight();
|
||||||
int x, y;
|
int n_width = dst->getWidth(), n_height = dst->getHeight();
|
||||||
|
double x_ratio = o_width / (double)n_width;
|
||||||
|
double y_ratio = o_height / (double)n_height;
|
||||||
|
double px, py;
|
||||||
|
int i;
|
||||||
|
|
||||||
u = v = 0.0;
|
for (int y = 0; y < n_height; y++) {
|
||||||
du = src->getWidth() * 1.0 / dst->getWidth();
|
for (int x = 0; x < n_width; x++) {
|
||||||
dv = src->getHeight() * 1.0 / dst->getHeight();
|
px = floor(x * x_ratio);
|
||||||
for (y=0; y<dst->getHeight(); ++y) {
|
py = floor(y * y_ratio);
|
||||||
for (x=0; x<dst->getWidth(); ++x) {
|
i = (int)(py * o_width + px);
|
||||||
color = src->getPixel(MID(0, u, src->getWidth()-1),
|
dst->putPixel(x, y, src->getPixel(i % o_width, i / o_width));
|
||||||
MID(0, v, src->getHeight()-1));
|
|
||||||
dst->putPixel(x, y, color);
|
|
||||||
u += du;
|
|
||||||
}
|
}
|
||||||
u = 0.0;
|
|
||||||
v += dv;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
111
src/raster/resize_image_unittest.cpp
Normal file
111
src/raster/resize_image_unittest.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// Aseprite Gfx Library
|
||||||
|
// Copyright (C) 2001-2013 David Capello
|
||||||
|
//
|
||||||
|
// This source file is distributed under MIT license,
|
||||||
|
// please read LICENSE.txt for more information.
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "raster/color.h"
|
||||||
|
#include "raster/image.h"
|
||||||
|
#include "raster/algorithm/resize_image.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace raster;
|
||||||
|
|
||||||
|
/***************************
|
||||||
|
* Test dat
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Base image
|
||||||
|
color_t test_image_base_3x3[9] =
|
||||||
|
{
|
||||||
|
0x000000, 0xffffff, 0x000000,
|
||||||
|
0xffffff, 0xffffff, 0xffffff,
|
||||||
|
0x000000, 0xffffff, 0x000000
|
||||||
|
};
|
||||||
|
|
||||||
|
// Base image scaled to 9x9 with nearest neighbor interpolation
|
||||||
|
color_t test_image_scaled_9x9_nearest[81] =
|
||||||
|
{
|
||||||
|
0x000000, 0x000000, 0x000000, 0xffffff, 0xffffff, 0xffffff, 0x000000, 0x000000, 0x000000,
|
||||||
|
0x000000, 0x000000, 0x000000, 0xffffff, 0xffffff, 0xffffff, 0x000000, 0x000000, 0x000000,
|
||||||
|
0x000000, 0x000000, 0x000000, 0xffffff, 0xffffff, 0xffffff, 0x000000, 0x000000, 0x000000,
|
||||||
|
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
|
||||||
|
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
|
||||||
|
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
|
||||||
|
0x000000, 0x000000, 0x000000, 0xffffff, 0xffffff, 0xffffff, 0x000000, 0x000000, 0x000000,
|
||||||
|
0x000000, 0x000000, 0x000000, 0xffffff, 0xffffff, 0xffffff, 0x000000, 0x000000, 0x000000,
|
||||||
|
0x000000, 0x000000, 0x000000, 0xffffff, 0xffffff, 0xffffff, 0x000000, 0x000000, 0x000000
|
||||||
|
};
|
||||||
|
|
||||||
|
// Base image scalled to 9x9 with bilinear interpolation
|
||||||
|
color_t test_image_scaled_9x9_bilinear[81] =
|
||||||
|
{
|
||||||
|
0x000000, 0x000000, 0x565656, 0xa9a9a9, 0xffffff, 0xa9a9a9, 0x565656, 0x000000, 0x000000,
|
||||||
|
0x000000, 0x000000, 0x565656, 0xa9a9a9, 0xffffff, 0xa9a9a9, 0x565656, 0x000000, 0x000000,
|
||||||
|
0x565656, 0x565656, 0x8f8f8f, 0xc6c6c6, 0xffffff, 0xc6c6c6, 0x8f8f8f, 0x565656, 0x565656,
|
||||||
|
0xa9a9a9, 0xa9a9a9, 0xc6c6c6, 0xe2e2e2, 0xffffff, 0xe2e2e2, 0xc6c6c6, 0xa9a9a9, 0xa9a9a9,
|
||||||
|
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
|
||||||
|
0xa9a9a9, 0xa9a9a9, 0xc6c6c6, 0xe2e2e2, 0xffffff, 0xe2e2e2, 0xc6c6c6, 0xa9a9a9, 0xa9a9a9,
|
||||||
|
0x565656, 0x565656, 0x8f8f8f, 0xc6c6c6, 0xffffff, 0xc6c6c6, 0x8f8f8f, 0x565656, 0x565656,
|
||||||
|
0x000000, 0x000000, 0x565656, 0xa9a9a9, 0xffffff, 0xa9a9a9, 0x565656, 0x000000, 0x000000,
|
||||||
|
0x000000, 0x000000, 0x565656, 0xa9a9a9, 0xffffff, 0xa9a9a9, 0x565656, 0x000000, 0x000000
|
||||||
|
};
|
||||||
|
|
||||||
|
Image* create_image_from_data(PixelFormat format, color_t* data, int width, int height)
|
||||||
|
{
|
||||||
|
Image* new_image = Image::create(format, width, height);
|
||||||
|
for (int i = 0; i < width * height; i++) {
|
||||||
|
new_image->putPixel(i % width, i / width, data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple pixel to pixel image comparison
|
||||||
|
bool compare_images(Image* a, Image* b)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < a->getHeight(); y++) {
|
||||||
|
for (int x = 0; x < a->getWidth(); x++) {
|
||||||
|
if (!(a->getPixel(x, y) == b->getPixel(x, y)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResizeImage, NearestNeighborInterp)
|
||||||
|
{
|
||||||
|
Image* src = create_image_from_data(IMAGE_RGB, test_image_base_3x3, 3, 3);
|
||||||
|
Image* dst = Image::create(IMAGE_RGB, 9, 9);
|
||||||
|
|
||||||
|
// Pre-rendered test image for comparison
|
||||||
|
Image* test_dst = create_image_from_data(IMAGE_RGB, test_image_scaled_9x9_nearest, 9, 9);
|
||||||
|
|
||||||
|
algorithm::resize_image(src, dst, algorithm::ResizeMethod::RESIZE_METHOD_NEAREST_NEIGHBOR, NULL, NULL);
|
||||||
|
|
||||||
|
ASSERT_TRUE(compare_images(dst, test_dst)) << "resize_image() result does not match test image!";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResizeImage, BilinearInterpRGBType)
|
||||||
|
{
|
||||||
|
Image* src = create_image_from_data(IMAGE_RGB, test_image_base_3x3, 3, 3);
|
||||||
|
Image* dst = Image::create(IMAGE_RGB, 9, 9);
|
||||||
|
|
||||||
|
// Pre-rendered test image for comparison
|
||||||
|
Image* test_dst = create_image_from_data(IMAGE_RGB, test_image_scaled_9x9_bilinear, 9, 9);
|
||||||
|
|
||||||
|
algorithm::resize_image(src, dst, algorithm::ResizeMethod::RESIZE_METHOD_BILINEAR, NULL, NULL);
|
||||||
|
|
||||||
|
ASSERT_TRUE(compare_images(dst, test_dst)) << "resize_image() result does not match test image!";
|
||||||
|
}
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user