web-dev-qa-db-fra.com

mathématiques / algorithme Ajuster l'image à l'écran pour conserver le rapport hauteur / largeur

J'ai besoin d'aide avec les mathématiques/algorithmes pour prendre une image de taille connue et l'adapter à l'une des deux dimensions d'écran:

720 x 480 ou 1280 x 1024.

Les dimensions de l'image proviennent d'un fichier XML, mais ces dimensions sont les dimensions Web, j'obtiens également une sélection d'images XML qui peuvent être de résolution plus élevée et plus basse que les dimensions Web.

Ce que je veux, c'est utiliser le rapport d'aspect des dimensions Web pour afficher l'image à plus haute résolution, si disponible, sur un écran HD (1280x720), ou, si l'utilisateur est sur un écran SD (720x480) afficher l'image sur cet écran .

D'autres choses qui seraient utiles pour cela, mais une priorité plus faible, seraient, si je sais que la résolution de l'image est plus petite dans les deux dimensions qu'un écran SD (dans ce cas, tout ce que je sais, c'est la dimension Web et la dimension horizontale du fichier image), pour l'afficher en taille réelle sur cet écran.

J'espère que c'est assez clair.

Merci!

42
alphablender

Générique comme peut l'être:

Données d'image: (wje, hje) et définir rje = wje/hje
Résolution d'écran: (ws, hs) et définir rs = ws/hs

Dimensions de l'image à l'échelle:

rs > ri ? (wi * hs/hi, hs) : (ws, hi * ws/wi)

Ainsi, par exemple:

         20
|------------------|
    10
|---------|

--------------------     ---   ---
|         |        |      | 7   |
|         |        |      |     | 10
|----------        |     ---    |
|                  |            |
--------------------           ---

ws = 20
hs = 10
wi = 10
hi = 7

20/10 > 10/7 ==> (wi * hs/hi, hs) = (10 * 10/7, 10) = (100/7, 10) ~ (14.3, 10)

Ce qui, comme vous pouvez le voir, s'adapte clairement à la taille de l'écran, car la hauteur est celle de l'écran mais conserve clairement le rapport d'aspect puisque 14.3/10 ~ 10/7

MISE À JOUR

Centrez l'image comme suit:

appeler (wnouveau, hnouveau) les nouvelles dimensions.

top = (hs - hnew)/2
left = (ws - wnew)/2
147
davin

Ici, c'est en simple C.

Vous souhaitez mettre à l'échelle les deux coordonnées en fonction du facteur d'échelle renvoyé.

/* Pour un rectangle à l'intérieur d'un écran, obtenez le facteur d'échelle qui permet au rectangle 
 D'être mis à l'échelle sans étirement ni écrasement. */
 float 
 aspect_correct_scale_for_rect (const float screen [2], const float rect [2]) 
 {
 float screenAspect = screen [0]/screen [ 1]; 
 Float rectAspect = rect [0]/rect [1]; 
 
 Float scaleFactor; 
 If (screenAspect> rectAspect) 
 scaleFactor = screen [1]/rect [1]; 
 else 
 scaleFactor = screen [0]/rect [0]; 
 
 return scaleFactor; 
} 
 
11
Michael Labbé

Je comprends la réponse acceptée et cela fonctionne, mais j'ai toujours trouvé la méthode suivante plus simple et succincte pour le "meilleur ajustement":

// prep
let maxWidth = 190,
    maxHeight = 150;
let imgWidth = photo.width,
    imgHeight = photo.height;

// calc
let widthRatio = maxWidth / imgWidth,
    heightRatio = maxHeight / imgHeight;
let bestRatio = Math.min(widthRatio, heightRatio);

// output
let newWidth = imgWidth * bestRatio,
    newHeight = imgHeight * bestRatio;
6
pstanton

Correction du rapport hauteur/largeur avec letterboxing ou fit-to-screen

J'ai récemment rédigé une méthode pour gérer ce problème exact dans iOS. J'utilise la bibliothèque de matrices propres pour faire une mise à l'échelle, mais le principe (facteur de mise à l'échelle) est le même sans matrices.

Eigen::Matrix4x4f aspectRatioCorrection(bool fillScreen, const Eigen::Vector2f &screenSize, const Eigen::Vector2f &imageSize)
{
    Eigen::Matrix4x4f scalingMatrix(Eigen::Matrix4x4f::Identity());

    float screenWidth = screenSize.x();
    float screenHeight = screenSize.y();
    float screenAspectRatio = screenWidth / screenHeight;
    float imageWidth = imageSize.x();
    float imageHeight = imageSize.y();
    float imageAspectRatio = imageWidth / imageHeight;

    float scalingFactor;
    if (fillScreen) {
        if (screenAspectRatio > imageAspectRatio) {
            scalingFactor = screenWidth / imageWidth;
        } else {
            scalingFactor = screenHeight / imageHeight;
        }
    } else {
        if (screenAspectRatio > imageAspectRatio) {
            scalingFactor =  screenHeight / imageHeight;
        } else {
            scalingFactor = screenWidth / imageWidth;
        }
    }

    scalingMatrix(0, 0) = scalingFactor;
    scalingMatrix(1, 1) = scalingFactor;

    return scalingMatrix;
}
4
Cameron Lowell Palmer