代码之家  ›  专栏  ›  技术社区  ›  Daniel

如何正确进行居中缩放?

  •  1
  • Daniel  · 技术社区  · 5 年前

    我的问题比编程更一般,但是它涉及一些基本的C代码,我希望这不会在这里结束。

    我有一个圆形目标显示器,它将显示图像,首先居中并安装:

    enter image description here

    圆的半径是360,这是固定的。

    我需要添加放大和缩小功能(以防图像大于目标)。在本例中,上图为 1282x720 ,因此它远高于圆的大小。(为了适应这个循环,现在它大致是 313x176 )

    卷轴 它有一个选项来设置其 抵消

    为了便于理解,我在图片中间加了一个红点。

    因此,放大后会发生这种情况(图像开始左对齐):

    enter image description here

    请注意它仍然垂直于中间,因为它的高度比它的容器小。

    但是,在下一个放大步骤中,红色中心点将略微向下移动,因为在本例中,图像的高度大于容器,因此它也开始顶部对齐:

    enter image description here

    现在,让它始终处于中心位置很容易:

    image_width/2 - 180, //horizontal skip
    image_height/2 - 180 //vertical skip
    

    在这种情况下,如果我从合身尺寸放大5步到全尺寸,滚动条的跳过数字如下:

    Step0 (fit): 0, 0 
    Step1: 73, 0
    Step2: 170, 16
    Step3: 267, 71
    Step4: 364, 125
    Step5 (original size): 461, 180
    

    但我不希望图像一直保持在中心,我宁愿做一些类似于图像编辑器正在做的事情,即:在缩放操作期间,中心点应保持在中心,而不是用户可以平移,并且下一次缩放操作将使新的中心点保持在中心。

    我该怎么做?

    目标语言是C,并且没有其他可用的第三方库,我需要手动执行此操作。

    Scroller实际上是一个 elm_scroller

    0 回复  |  直到 5 年前
        1
  •  2
  •   SrPanda    5 年前

    您需要修改所有四个位置点,而不仅仅是x2和y2,将它们视为矩形边的中心点,因此要保持居中缩放,正方形的每边都需要“增长”以消除图像的绝对中心。

    • X1>左,Y1>顶部
    • X2>对,Y2>底部
    #include <stdint.h>
    #include <stdio.h>
    
    typedef struct {
    
        int32_t x;
        int32_t y;
        int32_t width;
        int32_t heigth;
    
        uint32_t o_width;
        uint32_t o_heigth;
    
    } IMG_C_POS;
    
    void set_img_c_pos(IMG_C_POS * co, int32_t w, int32_t h){
        co->o_heigth = h;
        co->o_width = w;
        co->heigth = h;
        co->width = w;
        co->x = 0;
        co->y = 0;
    }
    
    void add_img_zoom(IMG_C_POS * co, uint16_t zoom){
        uint32_t zoom_y = (co->o_heigth / 100) * (zoom / 2);
        uint32_t zoom_x = (co->o_width / 100) * (zoom / 2);
        co->heigth -= zoom_y;
        co->width -= zoom_x;
        co->x += zoom_x;
        co->y += zoom_y;
    }
    
    void sub_img_zoom(IMG_C_POS * co, uint16_t zoom){
        uint32_t zoom_y = (co->o_heigth / 100) * (zoom / 2);
        uint32_t zoom_x = (co->o_width / 100) * (zoom / 2);
        co->heigth += zoom_y;
        co->width += zoom_x;
        co->x -= zoom_x;
        co->y -= zoom_y;
    }
    
    void img_new_center(IMG_C_POS * co, int16_t nx, int16_t ny){
        int32_t oy = co->o_heigth / 2;
        if(oy <= ny){
            co->heigth += oy - ny;
            co->y += oy - ny;
        } else {
            co->heigth -= oy - ny;
            co->y -= oy - ny;
        }
        int32_t ox = co->o_width / 2;
        if(ox <= nx){
            co->width += ox - nx;
            co->x += ox - nx;
        } else {
            co->width -= ox - nx;
            co->x -= ox - nx;
        }
    }
    
    void offset_img_center(IMG_C_POS * co, int16_t x_offset, int16_t y_offset){
        if (y_offset != 0){
            int32_t y_m_size = (co->o_heigth / 100) * y_offset;
            co->heigth += y_m_size;
            co->y += y_m_size;
        }
        if (x_offset != 0){
            int32_t x_m_size = (co->o_width / 100) * x_offset;
            co->width += x_m_size;
            co->x += x_m_size;
        }
    }
    
    
    int main(void) {
        
        IMG_C_POS position;
        set_img_c_pos(&position, 1282, 720);
    
        sub_img_zoom(&position, 50);
        img_new_center(&position, (1282 / 2) - 300, (720 / 2) + 100);
    
        for (int i = 0; i < 4; i++){
            printf("X1 -> %-5i Y1 -> %-5i X2 -> %-5i Y2 -> %-5i \n", 
            position.x, position.y, position.width, position.heigth
            );
    
            offset_img_center(&position, 4, -2);
            add_img_zoom(&position, 20);
        }
        
        return 0;
    }