l'image en rotation par un angle EasyBMP

voix
0

Je suis en train de faire pivoter une image bmp en utilisant EasyBMP. lorsque l'angle est compris entre 0 et 90 ou 270 et 360 de la rotation est très bien. mais quand entre 180 et 270 le rectangle limite est étiré et pour un angle entre 90 et 180 je reçois une erreur de segmentation. Je suis convaincu que le problème se pose de

int width = image.TellWidth();
int height = image.TellHeight();

float sine= sin(angle);
float cosine=cos(angle);

float x1=-height*sine;
float y1=height*cosine;
float x2=width*cosine-height*sine;
float y2=height*cosine+width*sine;
float x3=width*cosine;
float y3=width*sine;

float minx=min(0,min(x1,min(x2,x3)));
float miny=min(0,min(y1,min(y2,y3)));
float maxx=max(x1,max(x2,x3));
float maxy=max(y1,max(y2,y3));

int outWidth;
int outHeight;


     outWidth=(int)ceil(fabs(maxx)-minx);
     outHeight=(int)ceil(fabs(maxy)-miny);
output.SetSize(outHeight,outWidth);

for(int x=0; x<outWidth; x++)
{
    for(int y=0; y<outHeight; y++)
    {
        int srcX=(int)((x+minx)*cosine+(y+miny)*sine); 
            int srcY=(int)((y+miny)*cosine-(x+minx)*sine);
        if(srcX>=0 &&srcX<width && srcY>=0 && srcY<height)
        {
            output.SetPixel(x,y,image.GetPixel(srcX,srcY));
        }
    }
}
Créé 13/06/2012 à 23:50
source utilisateur
Dans d'autres langues...                            


1 réponses

voix
0

Ce qui suit est la façon dont je résolu ce problème. Le TL; DR: la transformation de rotation tourne autour 0, 0, donc si votre image coordonnées réglée à 0,0 en bas à gauche, vous avez besoin de traduire l'image pour être centrée sur 0,0 en premier. En outre, le péché et cos attendent radians, pas en degrés, donc n'oubliez pas de convertir d'abord

Le long chemin: Je commencé par la création d'un programme simple qui a facilement vérifié réponses, pour savoir où les choses vont mal.

La première chose que je remarque est que 90.0f ne produirait aucune sortie. Cela semblait bizarre, alors je me suis cassé dans le « taille de l'image de sortie » printf et réalisé que la hauteur de sortie a été calculée comme étant -87. Il est clair que ça ne va pas, donc nous allons voir pourquoi cela pourrait se produire.

En remontant un peu, outHeight=(int)ceil(fabs(maxy)-miny);donc nous allons comprendre comment nous se retrouver avec une hauteur de sortie négative en soustrayant Maxy et Miny. Il semble Maxy est -0,896 ... et Miny est 88,503 ... Cependant, la valeur absolue de Maxy est prise avant de soustraire Miny, ce qui signifie que nous sommes se retrouver avec 0,896 à 88,503. Whoa, ce n'est pas bon! Essayons de faire la soustraction en prenant la valeur absolue.

Recompiler avec à la fois la largeur et la hauteur en tant que tel: outWidth = (int) ceil (usines de fabrication (maxx-minx)); outHeight = (int) ceil (usines de fabrication (maxy-miny));

nous obtient des valeurs beaucoup mieux. Maintenant outWidth et outHeight sont 2 et 90, respectivement. Ceci est massivement améliorée, mais doit être la hauteur 100. Nous allons aborder plus tard.

Pour savoir où le calcul ne va pas, je réorganise les termes pour aller ensemble: avec x, y avec y. Ensuite, j'ajusté l'espacement et ajouté entre parenthèses pour le rendre plus lisible et d'assurer l'ordre des opérations (beats sûr essayant de regarder une table OoO;)). Comme il est clair que vous enfreignez la multiplication de la matrice de rotation, je vais nommer vos variables quelque chose d'un peu plus intuitif que x1, x2, etc. A partir de maintenant, x1 est topLeftTransformedX, x2 est topRightTransformedX, x3 existera comme bottomLeftTransformedX (toujours 0), et x4 sera bottomRightTransformedX, même pour Y. plus longtemps, mais beaucoup plus facile de savoir ce que vous avez affaire.

Avec cela, à ce moment, je vois la même chose que vous faites ... alors je me suis souvenu de quelque chose, d'après les chiffres vus à partir de ce code plus propre (même mathématiques que le vôtre, mais encore plus facile à déboguer).

Tout à coup, mes calculs pour X ressemble à ceci: // x = x cos - y flotteur sin topLeftTransformedX = (-midX * cosinus) - (* Midy sine); flotter topRightTransformedX = (MIDX * cosinus) - (Midy * sine); flotter bottomLeftTransformedX = (-midX * cosinus) - (-midY * sine); flotter bottomRightTransformedX = (MIDX * cosinus) - (-midY * sine);

La matrice de rotation tourne autour du point central. Vous devez traduire l'image pour être centrée autour de ce pour une bonne rotation.

Puis, en essayant de comprendre pourquoi ce serait donner les valeurs qu'il est, je rappelais quelque chose d'autre - angle doit être en radians.

Tout à coup, il fonctionne presque tout. Il y a encore un peu plus à faire, mais cela, vous devriez obtenir 95% du chemin ou plus. J'espère que cela aide!

// bmprotate.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <math.h>

#define min(x,y) x < y ? x : y
#define max(x,y) x > y ? x : y
#define PI 3.14159

void rotate(int width, int height, float angleInDeg)
{
    float angle = angleInDeg * (PI/180.0f);
    float midX = ((float)width) / 2.0f;
    float midY = ((float)height) / 2.0f;

    float sine = sin(angle);
    float cosine = cos(angle);

    // x = x cos - y sin
    float topLeftTransformedX = (-midX * cosine) - (midY * sine);
    float topRightTransformedX = (midX * cosine) - (midY * sine);
    float bottomLeftTransformedX  = (-midX * cosine) - (-midY * sine);
    float bottomRightTransformedX = (midX * cosine) - (-midY * sine);

    float minx = min( topLeftTransformedX, min(topRightTransformedX, min(bottomLeftTransformedX, bottomRightTransformedX)) );
    float maxx = max( topLeftTransformedX, max(topRightTransformedX, max(bottomLeftTransformedX, bottomRightTransformedX)) );

    // y = x sin + y cos
    float topLeftTransformedY = (-midX * sine) + (midY * cosine);
    float topRightTransformedY = (midX * sine) + (midY * cosine);
    float bottomLeftTransformedY  = (-midX * sine) + (-midY * cosine);
    float bottomRightTransformedY = (midX * sine) + (-midY * cosine);



    float miny = min( topLeftTransformedY, min(topRightTransformedY, min(bottomLeftTransformedY, bottomRightTransformedY)) );
    float maxy = max( topLeftTransformedY, max(topRightTransformedY, max(bottomLeftTransformedY, bottomRightTransformedY)) );

    int outWidth;
    int outHeight;

    printf("(%f,%f) , (%f,%f) , (%f,%f) , (%f,%f)\n", 
        topLeftTransformedX, topLeftTransformedY, 
        topRightTransformedX, topRightTransformedY, 
        bottomLeftTransformedX, bottomLeftTransformedY, 
        bottomRightTransformedX, bottomRightTransformedY);


    outWidth = (int) ceil( fabs(maxx) + fabs(minx));
    outHeight = (int) ceil( fabs(maxy) + fabs(miny) );

    printf("output image size: (%d,%d)\n",outWidth,outHeight);
    for(int x=0; x<outWidth; x++)
    {
        for(int y=0; y<outHeight; y++)
        {
            int srcX=(int)((x+minx)*cosine+(y+miny)*sine); 
            int srcY=(int)((y+miny)*cosine-(x+minx)*sine);

            if(srcX >=0 && srcX < width && srcY >= 0 && srcY < height)
            {
                printf("(x,y) = (%d,%d)\n",srcX, srcY);
            }
        }
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    rotate(100,2,90.0f);
    for (int i = 0; i < 360; i++)
    {

    }
    return 0;
}
Créé 14/06/2012 à 03:20
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more