Ampliar una imagen (Tema Programación)

Me he propuesto, como ejercicio. Idear una función que amplie el tamaño de una imagen.

De momento, he hecho mi "imagen virtual" con un array:

unsigned char[10][10] Ejemplo =

{{0,0,0,2,0,0,0,0,0,0},
{0,0,2,2,0,0,2,2,0,0},
{0,4,4,4,2,2,4,4,0,0},
{4,4,4,4,4,2,4,4,4,0},
{4,4,4,4,4,4,4,4,4,0},
{4,4,4,4,4,4,4,4,4,0},
{4,4,4,4,4,4,4,4,4,0},
{4,4,4,4,4,4,4,4,4,0},
{0,4,4,4,4,4,4,4,0,0}};


Cada número representa un color de la paleta de colores, dibujando los pixeles uno a uno tenemos la imagen.

He ideado este algoritmo por el momento (Objetivo es la imagen original, y Devolver es la imagen ampliada):

void Escalar(Sprite Objetivo,Sprite Devolver,int x, int y,int Escala)
{

     for (int j = 0; j < y; j++)
           for (int i = 0; i < x;i++)
               for (int l = j*Escala; l <= (j*Escala)+Escala;l++)
                 for (int k = i*Escala; k <= (i*Escala)+Escala;k++)
                   Devolver[k][l] = Objetivo[i][j];
}


Basicamente, lo que hace es repetir los números de una matriz. Obtenemos el siguiente resultado (Escala = 2):

Imagen

Ejemplo Original:

(0,0,0,4,4,4,4,4,0,0,)
0,0,4,4,4,4,4,4,4,0,)
0,2,4,4,4,4,4,4,4,0,)
2,2,4,4,4,4,4,4,4,0,)
0,0,2,4,4,4,4,4,4,0,)
0,0,2,2,4,4,4,4,4,0,)
0,2,4,4,4,4,4,4,4,0,)
0,2,4,4,4,4,4,4,4,0,)
0,0,0,4,4,4,4,4,0,0,)
0,0,0,0,0,0,0,0,0,0,)

Ejemplo Ampliado:

(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,)
0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0,0,)
0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,0,0,2,2,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,0,0,2,2,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,0,0,2,2,2,2,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,0,0,2,2,2,2,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,)
0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0,0,)
0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,0,0,0,0,)
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,)
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,)


Parece que hemos conseguido nuestro objetivo, pero... Probemos ahora un valor de escala grande (20):

Imagen

¡La imagen sale cuadriculada!. ¿Cómo puedo conseguir que salga más "redondeada"?. ¿Alguna idea?


PD: La imagen no sale pixelada, las manchas que se ven allí han salido al pasar las capturas a PNG
Tendrás que calcular el valor de los pixels con algún tipo de interpolación, hay varios métodos. Aquí tienes algunos nombres y algoritmos: http://en.wikipedia.org/wiki/Image_scaling . Buscando en google algo como "image scaling interpolation methods" encontrarás mucha información.
Si te fijas estas usando colores de sistema de una paleta limitada (¿16?) por lo que consiguir degradar el color es complicado y los resultados burdos.

En caso de que uses un espacio de colores tipo RGB:
- Si es una escala con enteros: despues de escalar comprueba con los vecinos (por ejemplo: arriba(12,5%), abajo(12,5%), izq(12,5%), derecha(12,5%) y centro(50%))
- Si es una escala con decimales: usa interpolación bilineal para escalar, es básicamente lo mismo que lo anterior pero el "porcentaje" depende de la distancia con los 4 puntos más próximos. http://en.wikipedia.org/wiki/Bilinear_interpolation
2 respuestas