zaf*_*zaf 3 language-agnostic algorithm graphics zoom
对于艺术项目,我将要做的一件事是将图像放大到特定像素.我一直在抚摸下巴,并希望得到一些关于如何进行的建议.
以下是输入参数:
Screen:
sw - screen width
sh - screen height
Image:
iw - image width
ih - image height
Pixel:
px - x position of pixel in image
py - y position of pixel in image
Zoom:
zf - zoom factor (0.0 to 1.0)
Background colour:
bc - background colour to use when screen and image aspect ratios are different
Run Code Online (Sandbox Code Playgroud)
输出:
The zoomed image (no anti-aliasing)
The screen position/dimensions of the pixel we are zooming to.
When zf is 0 the image must fit the screen with correct aspect ratio.
When zf is 1 the selected pixel fits the screen with correct aspect ratio.
Run Code Online (Sandbox Code Playgroud)
我的一个想法是使用类似povray的东西,将相机移向大图像纹理或某些库(例如pygame)进行缩放.有人用简单的伪代码想到更聪明的东西吗?
为了使其更简单,您可以使图像和屏幕具有相同的宽高比.我可以忍受这一点.
我会根据需要更新更多信息.
UPDATE
将已接受的答案转换为PHP
如果原始图像的颜色值以数组形式给出
image[x][y]
Run Code Online (Sandbox Code Playgroud)
然后是缩放图像的颜色值
image[x+zf*(px-x)][y+zf*(py-y)]
Run Code Online (Sandbox Code Playgroud)
关于窗口大小/图像大小 - 图像的初始准备应该注意:将图像缩放到不再适合窗口的点,并用您喜欢的背景颜色填充剩余的像素.
在python中你可以做类似的事情
def naivezoom(im, px, py, zf, bg):
out = Image.new(im.mode, im.size)
pix = out.load()
iw, ih = im.size
for x in range(iw):
for y in range(ih):
xorg = x + zf*(px - x)
yorg = y + zf*(py - y)
if xorg >= 0 and xorg < iw and yorg >= 0 and yorg < ih:
pix[x,y] = im.getpixel( (xorg , yorg) )
else:
pix[x,y] = bg
return out
Run Code Online (Sandbox Code Playgroud)
你设置好之后
im = Image.open("filename.ext")
Run Code Online (Sandbox Code Playgroud)
与来自的对象
import Image
Run Code Online (Sandbox Code Playgroud)
编辑:鉴于stackoverflow徽标,你会得到
替代文字http://i40.tinypic.com/i1cwg7.jpg
对于zf = 0.3,在点25,6附近
替代文字http://i41.tinypic.com/24g5848.png
对于zf = 0.96,大约在同一点上
使用以下代码获得图像
#!/bin/env python
from Tkinter import *
import Image
import ImageTk
def naivezoom(im, p, zf, bg):
out = Image.new(im.mode, im.size)
pix = out.load()
iw, ih = im.size
for x in range(iw):
for y in range(ih):
xorg = x + zf*(p[0] - x)
yorg = y + zf*(p[1] - y)
if xorg >= 0 and xorg < iw and yorg >= 0 and yorg < ih:
pix[x,y] = im.getpixel( (xorg , yorg) )
else:
pix[x,y] = bg
return out
class NaiveTkZoom:
def __init__(self, parent=None):
root = Tk()
self.im = Image.open('logo.jpg')
self.zf = 0.0
self.deltazf = 0.02
self.p = ( 0.1*self.im.size[0],0.1*self.im.size[1])
self.bg = 255
canvas = Canvas(root, width=self.im.size[0]+20 , height=self.im.size[1]+20)
canvas.pack()
root.bind('<Key>', self.onKey)
self.canvas = canvas
self.photo = ImageTk.PhotoImage(self.im)
self.item = self.canvas.create_image(10, 10, anchor=NW, image=self.photo)
def onKey(self, event):
if event.char == "+":
if self.zf < 1:
self.zf += self.deltazf
elif event.char == "-":
if self.zf > 0:
self.zf -= self.deltazf
self.out = naivezoom(self.im, self.p, self.zf, self.bg)
self.photo = ImageTk.PhotoImage(self.out)
self.canvas.delete(self.item)
self.item = self.canvas.create_image(10, 10, anchor=NW, image=self.photo)
print self.p, self.zf
if __name__ == "__main__":
NaiveTkZoom()
mainloop()
Run Code Online (Sandbox Code Playgroud)
使用的库和逐像素的方法并不是世界上最快的,但会给你足够的材料.
上面的代码也不是很干净.
EDIT2(和3,以公式为中心):这是另一次尝试,增加了翻译,但我感觉这也不是最终的(没有时间检查公式).此外,平移的速度是恒定的,但这可能会导致缩放变慢并显示背景(如果缩放的点太靠近边缘).
我还在原始图像上添加了一个点,以便可以看到它发生了什么,而无需在原始图像上绘画.
#!/bin/env python
from Tkinter import *
import Image
import ImageTk
def markImage(im, p, bg):
pix = im.load()
pix[ p[0], p[1] ] = bg
def naiveZoom(im, p, zf, bg):
out = Image.new(im.mode, im.size)
pix = out.load()
iw, ih = im.size
for x in range(iw):
for y in range(ih):
xorg = x + zf*(p[0]+0.5-x) + zf*(1-zf)*(p[0]-iw/2)
yorg = y + zf*(p[1]+0.5-y) + zf*(1-zf)*(p[1]-ih/2)
if xorg >= 0 and xorg < iw and yorg >= 0 and yorg < ih:
pix[x,y] = im.getpixel( (xorg , yorg) )
else:
pix[x,y] = bg
return out
class NaiveTkZoom:
def __init__(self, parent=None):
root = Tk()
self.im = Image.open('py.jpg')
self.zf = 0.0
self.deltazf = 0.05
self.p = (round(0.3*self.im.size[0]), round(0.3*self.im.size[1]) )
self.bg = 255
markImage(self.im, self.p, self.bg)
canvas = Canvas(root, width=self.im.size[0]+20 , height=self.im.size[1]+20)
canvas.pack()
root.bind('<Key>', self.onKey)
self.canvas = canvas
self.photo = ImageTk.PhotoImage(self.im)
self.item = self.canvas.create_image(10, 10, anchor=NW, image=self.photo)
self.change = False
def onKey(self, event):
if event.char == "+":
if self.zf < 1:
self.zf += self.deltazf
self.change = True
elif event.char == "-":
if self.zf > 0:
self.zf -= self.deltazf
self.change = True
if self.change:
self.out = naiveZoom(self.im, self.p, self.zf, self.bg)
self.photo = ImageTk.PhotoImage(self.out)
self.canvas.delete(self.item)
self.change = False
self.item = self.canvas.create_image(10, 10, anchor=NW, image=self.photo)
print self.p, self.zf
if __name__ == "__main__":
NaiveTkZoom()
mainloop()
Run Code Online (Sandbox Code Playgroud)
上面有很多可以改进的东西.:)