mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-28 16:20:50 +00:00
Merge pull request #11 from DocHoncho/issue-295-dev
Re-implement nearest-neighbor interpolation
This commit is contained in:
commit
ab42d38947
@ -35,23 +35,22 @@ void resize_image(const Image* src, Image* dst, ResizeMethod method, const Palet
|
||||
switch (method) {
|
||||
|
||||
// TODO optimize this
|
||||
case RESIZE_METHOD_NEAREST_NEIGHBOR: {
|
||||
uint32_t color;
|
||||
double u, v, du, dv;
|
||||
int x, y;
|
||||
case RESIZE_METHOD_NEAREST_NEIGHBOR:
|
||||
{
|
||||
int o_width = src->getWidth(), o_height = src->getHeight();
|
||||
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;
|
||||
du = src->getWidth() * 1.0 / dst->getWidth();
|
||||
dv = src->getHeight() * 1.0 / dst->getHeight();
|
||||
for (y=0; y<dst->getHeight(); ++y) {
|
||||
for (x=0; x<dst->getWidth(); ++x) {
|
||||
color = src->getPixel(MID(0, u, src->getWidth()-1),
|
||||
MID(0, v, src->getHeight()-1));
|
||||
dst->putPixel(x, y, color);
|
||||
u += du;
|
||||
for (int y = 0; y < n_height; y++) {
|
||||
for (int x = 0; x < n_width; x++) {
|
||||
px = floor(x * x_ratio);
|
||||
py = floor(y * y_ratio);
|
||||
i = (int)(py * o_width + px);
|
||||
dst->putPixel(x, y, src->getPixel(i % o_width, i / o_width));
|
||||
}
|
||||
u = 0.0;
|
||||
v += dv;
|
||||
}
|
||||
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