C 如何正确进行居中缩放?

C 如何正确进行居中缩放?,c,zooming,C,Zooming,我的问题比编程更一般,但是它涉及一些基本的C代码,我希望这不会在这里结束 我有一个圆形目标显示器,它将显示图像,首先居中并安装: 圆的半径是360,这是固定的 我需要添加放大和缩小功能(以防图像大于目标)。在本例中,上面的图像是1282x720,因此它远高于圆的大小。(为了适应这个循环,现在它大约是313x176) 我想做一个正确对齐的“中心固定缩放”,即:当前居中的物体在缩放操作后应保持居中 图像被放入一个名为scroller的组件中,该组件有一个设置其偏移量的选项,即从内容的顶部和左侧跳过

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

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

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

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

我想做一个正确对齐的“中心固定缩放”,即:当前居中的物体在缩放操作后应保持居中

图像被放入一个名为scroller的组件中,该组件有一个设置其偏移量的选项,即从内容的顶部和左侧跳过多少像素。默认情况下,此滚动条组件将其内容与左上角对齐

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

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

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

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

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

我需要让滚动条滚动到

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,并且没有其他可用的第三方库,我需要手动执行此操作


滚动条实际上是一个。

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

  • X1>左侧,Y1>顶部
  • X2>右侧,Y2>底部
#包括
#包括
类型定义结构{
int32_t x;
int32_t y;
int32_t宽度;
内部高度;
uint32_t_____________宽度;
uint32的高度;
}IMG_C_POS;
无效集合\u img\u c\u pos(img\u c\u pos*co,int32\u t w,int32\u t h){
co->o_高度=h;
co->o_宽度=w;
co->高度=h;
co->宽度=w;
co->x=0;
co->y=0;
}
无效添加图像缩放(图像缩放){
uint32 t缩放y=(co->o_高度/100)*(缩放/2);
uint32\u t zoom\u x=(co->o\u width/100)*(zoom/2);
co->高度-=缩放;
co->宽度-=缩放x;
co->x+=缩放x;
co->y+=缩放y;
}
无效子屏幕缩放(屏幕缩放){
uint32 t缩放y=(co->o_高度/100)*(缩放/2);
uint32\u t zoom\u x=(co->o\u width/100)*(zoom/2);
co->高度+=缩放;
co->宽度+=缩放x;
co->x-=缩放x;
co->y-=缩放y;
}
无效img_新中心(img_C_POS*co,int16_t nx,int16_t ny){
int32_t oy=co->o_高度/2;
如果(oy高度+=oy-ny;
co->y+=oy-ny;
}否则{
co->高度-=oy-ny;
co->y-=oy-ny;
}
int32\u t ox=co->o\u宽度/2;
如果(x宽度+=x-nx;
co->x+=ox-nx;
}否则{
co->宽度-=ox-nx;
co->x-=ox-nx;
}
}
无效偏移量\u图像中心(图像中心位置*co、int16\u t x\u偏移量、int16\u t y\u偏移量){
如果(y_偏移量!=0){
int32_t y_m u size=(co->o_高度/100)*y_偏移量;
co->高度+=y___尺寸;
co->y+=y\m\U尺寸;
}
如果(x_偏移量!=0){
int32_t x_m_size=(co->o_宽度/100)*x_偏移量;
co->宽度+=x_m_尺寸;
co->x+=x_m_尺寸;
}
}
内部主(空){
IMG_C_POS位置;
设置img和c位置(&position,1282720);
子图像缩放(&position,50);
img_新中心和位置,(1282/2)-300,(720/2)+100;
对于(int i=0;i<4;i++){
printf(“X1->%-5iy1->%-5ix2->%-5iy2->%-5i\n”,
位置x,位置y,位置宽度,位置高度
);
偏移量(中心和位置,4,-2);
添加图像缩放(&position,20);
}
返回0;
}

我认为这是一个非常有趣的问题,但不幸的是,我认为这是一个相当模糊的问题,没有您使用的编程语言的上下文。例如,C#WPF对一个非常简单的
ScaleTransform
,您可以告诉它比例因子并定义一个中心点(例如X=50%,Y=50%).Python可能需要一些第三方映像库和一些您描述的手动代码。对于经验较少的程序员来说,使用C显然有点难度,因为它甚至需要实现基本概念,如中心点的概念等。语言是C,我将添加它。而且没有可用的库,我必须计算手动编辑。你可以发布一个什么是
滚动条
的示例或模型吗?你有能力更改控件的代码吗?这很可能会改变人们提供答案和反馈的方式。滚动条实际上是一个
elm_滚动条
,基本上它不只是一个容器,它通过内容扩展并使之成为一个容器“可滚动"使用滚动条。这一个看起来不好。让我们只考虑宽度:在原始情况下要为:<代码> 1282代码> 461 > <代码>被偏移。一个小的:<代码> 1088 /代码>宽度和<代码> 364 < /代码>偏移。比例的计算:<代码> 1088/1282~0.8487 < /代码>:计算新的偏移:<代码> 0.8487×461~391</COD。e> 。而不是364.Thx。一个小的补充:我的图像的原始大小是1282x720,为了适应这个图像
#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;
}