保持纵横比的同时调整图像大小

huangapple go评论69阅读模式
英文:

Resize images while preserving aspect ratio

问题

我有一个小问题,可能有一个简单的解决方案,但不幸的是我在数学上不太擅长。

我有三张图片需要叠加在一起,它们的高度加起来超过了屏幕高度。

为了解决这个问题,我做了一个简单的比例,并改变了三张图片的高度,就像这样(这是假设的,不是实际的代码):

new_img1.height = img1.height * screen.height // (img1.height + img2.height + img3.height)

我遇到的问题是如何做同样的事情,但是考虑到宽度,因为这三张图片的宽度都相同。

我想要的是,这三张图片始终具有与原始相同的宽度,但根据新的高度调整大小(以便这三张图片在两个维度上按比例变小)。

我尝试了几次,但我的数学能力不怎么帮助我XD

我该怎么解决?哦,我正在使用Python 3.9和Pygame(尽管对于后者我不认为需要知道)。

英文:

I have a small problem that could have a simple solution, but unfortunately I'm not very good at math.

I have three images that need to be stacked on top of each other and their heights add up to more than the screen height.

So to fix, I did a simple proportion and changed the height of the three images, like this (it's hypothetical, not the actual code):

new_img1.height = img1.height * screen.height // (img1.height + img2.height + img3.height)

The problem I'm having is doing the same thing, but with the width, considering all three images have the same width.

What I want is that the three images always have the same width as originally, but resized with the new height (so that the three images are proportionally smaller in both dimensions)

I've made several attempts, but my mathematical limits don't help me much XD

How should I fix? Ah, I'm using Python 3.9 with Pygame (although for the latter I don't think it needed to know)

答案1

得分: 2

如果要保持纵横比例,必须使用相同的缩放因子来缩放图像的宽度和高度:

scale_factor = screen.height // (img1.height + img2.height + img3.height) 
new_img1.width = img1.width * scale_factor
new_img1.height = img1.height * scale_factor 
new_img2.width = img2.width * scale_factor
new_img2.height = img2.height * scale_factor 
new_img3.width = img3.width * scale_factor
new_img3.height = img3.height * scale_factor 

如果要使所有图像具有相同的宽度,首先必须为每个图像计算缩放因子以缩放图像的宽度。然后,您可以计算高度的缩放因子:

max_width = max(img1.width, img2.width, img3.width)
scale_factor1 = max_width / img1.width
scale_factor2 = max_width / img2.width
scale_factor3 = max_width / img3.width
height_scale = screen.height / (img1.height * scale_factor1 + img2.height * scale_factor2 + img3.height * scale_factor3)
scale_factor1 *= height_scale
scale_factor2 *= height_scale
scale_factor3 *= height_scale

演示算法的最小示例:

import pygame, random

pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()

update_rects = True
run = True
while run:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False 
        if event.type == pygame.KEYDOWN:
            update_rects = True

    if update_rects:
        rect1 = pygame.Rect(0, 0, random.randrange(50, 100), random.randrange(50, 100))
        rect2 = pygame.Rect(0, 0, random.randrange(50, 100), random.randrange(50, 100))
        rect3 = pygame.Rect(0, 0, random.randrange(50, 100), random.randrange(50, 100))
        update_rects = False

    max_width = max(rect1.width, rect2.width, rect2.width)
    scale_factor1 = max_width / rect1.width
    scale_factor2 = max_width / rect2.width
    scale_factor3 = max_width / rect3.width
    height_scale = window.get_height() / (rect1.height * scale_factor1 + rect2.height * scale_factor2 + rect3.height * scale_factor3)
    scale_factor1 *= height_scale
    scale_factor2 *= height_scale
    scale_factor3 *= height_scale
    
    rect1.width *= scale_factor1
    rect1.height *= scale_factor1
    rect2.width *= scale_factor2
    rect2.height *= scale_factor2
    rect3.width *= scale_factor3
    rect3.height *= scale_factor3

    rect2.top = rect1.bottom
    rect3.top = rect2.bottom

    window.fill(0)
    pygame.draw.rect(window, "red", rect1)    
    pygame.draw.rect(window, "blue", rect2)
    pygame.draw.rect(window, "yellow", rect3)    
    pygame.display.flip()

pygame.quit()
exit()
英文:

If you want to keep the aspect ratio, you must scale the width and height of the image with the same scaling factor:

scale_factor = screen.height // (img1.height + img2.height + img3.height) 
new_img1.width = img1.width * scale_factor
new_img1.height = img1.height * scale_factor 
new_img2.width = img2.width * scale_factor
new_img2.height = img2.height * scale_factor 
new_img3.width = img3.width * scale_factor
new_img3.height = img3.height * scale_factor 

If you want all images to have the same width, you must first calculate the scale factor for each image to scale the width of the images. Then you can calculate the scale factor for the height:

max_width = max(img1.width, img2.width, img3.width)
scale_factor1 = max_width / img1.width
scale_factor2 = max_width / img2.width
scale_factor3 = max_width / img3.width
height_scale = screen.height / (img1.height * scale_factor1 + img2.height * scale_factor2 + img3.height * scale_factor3)
scale_factor1 *= height_scale
scale_factor2 *= height_scale
scale_factor3 *= height_scale

Minimal example to demonstrate the algorithm:

import pygame, random

pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()

update_rects = True
run = True
while run:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False 
        if event.type == pygame.KEYDOWN:
            update_rects = True

    if update_rects:
        rect1 = pygame.Rect(0, 0, random.randrange(50, 100), random.randrange(50, 100))
        rect2 = pygame.Rect(0, 0, random.randrange(50, 100), random.randrange(50, 100))
        rect3 = pygame.Rect(0, 0, random.randrange(50, 100), random.randrange(50, 100))
        update_rects = False

    max_width = max(rect1.width, rect2.width, rect2.width)
    scale_factor1 = max_width / rect1.width
    scale_factor2 = max_width / rect2.width
    scale_factor3 = max_width / rect3.width
    height_scale = window.get_height() / (rect1.height * scale_factor1 + rect2.height * scale_factor2 + rect3.height * scale_factor3)
    scale_factor1 *= height_scale
    scale_factor2 *= height_scale
    scale_factor3 *= height_scale
    
    rect1.width *= scale_factor1
    rect1.height *= scale_factor1
    rect2.width *= scale_factor2
    rect2.height *= scale_factor2
    rect3.width *= scale_factor3
    rect3.height *= scale_factor3

    rect2.top = rect1.bottom
    rect3.top = rect2.bottom

    window.fill(0)
    pygame.draw.rect(window, "red", rect1)    
    pygame.draw.rect(window, "blue", rect2)
    pygame.draw.rect(window, "yellow", rect3)    
    pygame.display.flip()

pygame.quit()
exit()

huangapple
  • 本文由 发表于 2023年1月8日 23:09:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75048860.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定