缩放/缩放瓷砖图像,将变焦点锚定在鼠标光标上



我有一个项目,正在为瓷砖图像设计一个图像查看器。每个图像瓷砖为256x256像素。对于每个缩放级别,我将每个图像的大小增加5%。我通过将屏幕分为与每个图像相同的大小来表示瓷砖的放置。偏移用于将每个图像完全放置在需要的地方。当缩放达到一定点(1.5)时,我切换到一层新的图像层,这些图像的分辨率比以前的图像更大。缩放方法本身看起来像这样:

def zoomer(self, mouse_pos, zoom_in): #(tuple, bool)
    x, y = mouse_pos
    x_tile, y_tile = x / self.tile_size, y / self.tile_size
    old_scale = self.scale
    if self.scale > 0.75 and self.scale < 1.5:
        if zoom_in:
            self.scale += SCALE_STEP # SCALE_STEP = 5% = 0.05
            ratio = (SCALE_STEP + 1)
        else:
            self.scale -= SCALE_STEP
            ratio = 1 / (SCALE_STEP + 1)
    else:
        if zoom_in:
            self.zoom += 1
            self.scale = 0.8
            ratio = (SCALE_STEP + 1)
        else:
            self.zoom -= 1
            self.scale = 1.45
            ratio = 1 / (SCALE_STEP + 1)
    # Results in x/y lengths of the relevant full image
    x_len = self.size_list[self.levels][0] / self.power()
    y_len = self.size_list[self.levels][1] / self.power()
    # Removing extra pixel if present
    x_len = x_len - (x_len % 2)
    y_len = y_len - (y_len % 2)
    # The tile's picture coordinates
    tile_x = self.origo_tile[0] + x_tile
    tile_y = self.origo_tile[1] + y_tile
    # The mouse's picture pixel address
    x_pic_pos = (tile_x * self.tile_size) - 
                 self.img_x_offset + (x % self.tile_size)
    y_pic_pos = (tile_y * self.tile_size) - 
                 self.img_y_offset + (y % self.tile_size)
    # Mouse percentile placement within the image
    mouse_x_percent = (x_pic_pos / old_scale) / x_len
    mouse_y_percent = (y_pic_pos / old_scale) / y_len
    # The mouse's new picture pixel address
    new_x = (x_len * self.scale) * mouse_x_percent
    new_y = (y_len * self.scale) * mouse_y_percent
    # Scaling tile size
    self.tile_size = int(TILE_SIZE * self.scale)
    # New mouse screen tile position
    new_mouse_x_tile = x / self.tile_size
    new_mouse_y_tile = y / self.tile_size
    # The mouse's new tile address
    new_tile_x = new_x / self.tile_size
    new_tile_y = new_y / self.tile_size
    # New tile offsets
    self.img_x_offset = (x % self.tile_size) - int(new_x % self.tile_size)
    self.img_y_offset = (y % self.tile_size) - int(new_y % self.tile_size)
    # New origo tile
    self.origo_tile = (int(new_tile_x) - new_mouse_x_tile,
                       int(new_tile_y) - new_mouse_y_tile)

现在,由于此问题引起的问题是mouse_.._percent变量似乎与真实位置永远不匹配。出于测试目的,我以鼠标位置为中心的鼠标位置为屏幕中间,图片也以中间为中心。因此,在完美的世界中,所得的mouse_.._percent变量应始终等于50%。对于第一级,它确实可以,但是在缩放时会迅速徘徊。到我到达第一个变焦断点(self.scale == 1.5)时,该位置已漂移到x = 48%y = 42%self.origo_tile是一个元组,包含X/Y坐标,用于在屏幕瓷砖上绘制的瓷砖(0,0)

我已经盯着这个数小时了,但是看不到为此找到一种补救措施...

程序的工作方式:

我很抱歉,我没有足够的时间将其应用于您的代码,但是我写了以下缩放模拟器。该程序允许您多次缩放相同的"图像",并且输出了出现在屏幕中心的图像点以及显示多少图像。


代码:

from __future__ import division #double underscores, defense against the sinister integer division
width=256 #original image size
height=256
posx=128 #original display center, relative to the image
posy=128
while 1:
    print "Display width: ", width
    print "Display height: ", height
    print "Center X: ", posx
    print "Center Y: ", posy
    anchx = int(raw_input("Anchor X: "))
    anchy = int(raw_input("Anchor Y: "))
    zmag = int(raw_input("Zoom Percent (0-inf): "))
    zmag /= 100 #convert from percent to decimal
    zmag = 1/zmag
    width *= zmag
    height *= zmag
    posx = ((anchx-posx)*zmag)+posx
    posy = ((anchy-posy)*zmag)+posy

样本输出:

如果此程序输出以下内容:

Display width: 32.0
Display height: 32.0
Center X: 72.0
Center Y: 72.0

说明:

这意味着放大屏幕仅显示图像的一部分,该部分为32x32像素,该部分的中心位于坐标(72,72)。这意味着在两个轴上都在此特定示例中显示图像的像素56-88。


解决方案/结论:

稍微播放该程序,看看是否可以将其实现到自己的代码中。请记住,不同的程序以不同的方式移动中心,如果您不喜欢它的工作方式,请更改我提供的程序(尽管您可能会,这是一种常见的方法)。快乐编码!