- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
使用 python 创建允许图像缩放和在其上绘制线条的应用程序的最佳方法是什么?
我一直致力于使用 pygame 来执行此操作,方法是在非常大的表面(大小约为 15000)上绘制图像并使用 pygame.transform.scale(),它允许我进行缩放。此外,使用 convert_alpha() 创建了一个用于画线的额外表面并将其设置为 0 alpha。
这种方法的问题是,如果我需要创建大尺寸的 pygame.surface,它会花费很多时间和内存。此外, transform.scale() 花费很多时间。除了线条之外,还为绘图类型创建了许多额外的表面。
那么,有没有更好的方法来使用 pygame 做同样的事情?或另一种做同样事情的方法?谢谢。
最佳答案
缩放图像可以通过复制“基本图像”的一部分,然后仅将较小的部分缩放到与窗口相同的大小来实现。这样,代码只保存基本图像、背景和子图像。您永远不会将整个图像缩放到缩放级别。
在下面的示例代码中,我使用“pan-box”的概念实现了这一点,它是 PyGame rectangle (Rect
) 定义缩放部分的大小和位置。实际上,它是一个矩形的“放大镜”。
代码的核心是在这个框的坐标和大小范围内复制背景,然后将它们缩放到与窗口相同的大小,复制到“背景”图像:
window_size = ( WINDOW_WIDTH, WINDOW_HEIGHT )
zoom_image = pygame.Surface( ( pan_box.width, pan_box.height ) ) # new surface
zoom_image.blit( base_image, ( 0, 0 ), pan_box ) # copy base image
pygame.transform.scale( zoom_image, window_size, background ) # scale into the background
window.blit( background, ( 0, 0 ) )
pygame.display.flip()
这就是行动的关键。这很有效,因为它只是在框所在的位置抓取原始图像的内容,并将其缩放以适合窗口。平移或缩放只是移动平移框或使其变大/变小的问题。
但是,为了保持此核心代码简单,示例中有更多代码主要将泛框保持在图像中。事实上,大多数示例都是简单的检查,以确保我们不会越界。
图像复制和缩放是相对占用 CPU 资源的操作。因此,您将在代码中看到进行测试以确定是否需要执行某些操作的点。例如,如果 pan-box 没有改变,我们不需要创建新的背景图像。我们也不需要制作新的 zoom_image
如果泛框的大小没有改变。像这样的小检查大大提高了代码的速度。
引用代码:
import pygame
import sys
# Window size
WINDOW_WIDTH = 300
WINDOW_HEIGHT = 300
WINDOW_SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE
image_filename = None
PAN_BOX_WIDTH = 64
PAN_BOX_HEIGHT = 64
PAN_STEP = 5
def errorExit( message, code=1 ):
""" Write an error message to the console, then exit with an error code """
sys.stderr.write( message + "\n" )
sys.exit( code )
# The first argument is either the image filename
# or a "--help" request for help
# Did we get any arguments?
if ( len( sys.argv ) == 1 ):
errorExit( "Give an image Filename as an argument" )
else:
# Get image filename as first argument
for arg in sys.argv[1:]:
if ( arg in [ '-h', '--help', '-?', '/?' ] ):
errorExit( "Zooms an image, using arrow keys to pan\nGive an image Filename as an argument" )
# Use the first argument as the image source
image_filename = sys.argv[1]
sys.stdout.write( "Using [%s] as the image\n" % ( image_filename ) )
### PyGame initialisation
pygame.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("Image Pan")
### Can we load the user's image OK?
try:
base_image = pygame.image.load( image_filename ).convert()
except:
errorExit( "Failed to open [%s]" % ( image_filename ) )
### Pan-position
background = pygame.Surface( ( WINDOW_WIDTH, WINDOW_HEIGHT ) ) # zoomed section is copied here
zoom_image = None
pan_box = pygame.Rect( 0, 0, PAN_BOX_WIDTH, PAN_BOX_HEIGHT ) # curent pan "cursor position"
last_box = pygame.Rect( 0, 0, 1, 1 )
### Main Loop
clock = pygame.time.Clock()
done = False
while not done:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
# Movement keys
# Pan-box moves up/down/left/right, Zooms with + and -
keys = pygame.key.get_pressed()
if ( keys[pygame.K_UP] ):
pan_box.y -= PAN_STEP
if ( keys[pygame.K_DOWN] ):
pan_box.y += PAN_STEP
if ( keys[pygame.K_LEFT] ):
pan_box.x -= PAN_STEP
if ( keys[pygame.K_RIGHT] ):
pan_box.x += PAN_STEP
if ( keys[pygame.K_PLUS] or keys[pygame.K_EQUALS] ):
pan_box.width += PAN_STEP
pan_box.height += PAN_STEP
if ( pan_box.width > WINDOW_WIDTH ): # Ensure size is sane
pan_box.width = WINDOW_WIDTH
if ( pan_box.height > WINDOW_HEIGHT ):
pan_box.height = WINDOW_HEIGHT
if ( keys[pygame.K_MINUS] ):
pan_box.width -= PAN_STEP
pan_box.height -= PAN_STEP
if ( pan_box.width < PAN_STEP ): # Ensure size is sane
pan_box.width = PAN_STEP
if ( pan_box.height < PAN_STEP ):
pan_box.height = PAN_STEP
# Ensure the pan-box stays within image
PAN_BOX_WIDTH = min( PAN_BOX_WIDTH, base_image.get_width() )
PAN_BOX_HEIGHT = min( PAN_BOX_HEIGHT, base_image.get_height() )
if ( pan_box.x < 0 ):
pan_box.x = 0
elif ( pan_box.x + pan_box.width >= base_image.get_width() ):
pan_box.x = base_image.get_width() - pan_box.width - 1
if ( pan_box.y < 0 ):
pan_box.y = 0
elif ( pan_box.y + pan_box.height >= base_image.get_height() ):
pan_box.y = base_image.get_height() - pan_box.height - 1
# Re-do the zoom, but only if the pan box has changed since last time
if ( pan_box != last_box ):
# Create a new sub-image but only if the size changed
# otherwise we can just re-use it
if ( pan_box.width != last_box.width or pan_box.height != last_box.height ):
zoom_image = pygame.Surface( ( pan_box.width, pan_box.height ) )
zoom_image.blit( base_image, ( 0, 0 ), pan_box ) # copy base image
window_size = ( WINDOW_WIDTH, WINDOW_HEIGHT )
pygame.transform.scale( zoom_image, window_size, background ) # scale into thebackground
last_box = pan_box.copy() # copy current position
window.blit( background, ( 0, 0 ) )
pygame.display.flip()
# Clamp FPS
clock.tick_busy_loop(60)
pygame.quit()
关于python - 创建图像查看器并允许通过 python 缩放、拖动和画线的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63795236/
我对java Graphics不熟悉,我想在3个按钮上画一条线。我找到了一些绘制线条的方法,但没有一个将其绘制在按钮顶部。 这是我的 GUI 类 public class GUI extends JF
我正在尝试画线。 int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.
我目前正在尝试在 BabylonJS 中跟踪对象的路径。 为此,我想在现有位置和以前的位置之间画一条线。 我能得到的最接近的是一个立方体。 var plane = BABYLON.Mesh.Creat
我正在尝试绘制一棵递归树,但我已经卡在了开头。一段时间以来,我一直在尝试解决这个问题,但似乎无法解决。 我正在使用 StdDraw 库。这就是我想做的: 我已经画好了树干(黑线)。但我也需要画红线。
在我之前的问题中 For Loop Functions in Python ,我在放置包含为刽子手游戏划线的命令的函数时遇到了麻烦。它并没有完全划清界线,我首先怀疑这是 for 循环或函数的问题。现在
我有一个自定义布局,可以根据触摸输入画一条线。我让它画了线,但是当用户触摸屏幕时,线消失了,它画了一条新线。我想要它做的是画一条新线并将上一条线留在那里。这是我的代码: import andr
我想使用触摸监听器在屏幕上画一条线,但是当我再次尝试画线时,它会删除上一条线。我正在使用这段代码:- 我无法找到问题的解决方案。 public class Drawer extends View
我已经阅读了一堆涉及 XNA(以及它的各种版本)的教程,但我仍然对绘制原语感到有些困惑。一切似乎真的很复杂。 有人可以使用代码向我展示在屏幕上绘制一两行的最简单的 XNA 实现吗?也许有一个简短的解释
我是 Objective C 的初学者,我试图用 Paint 风格制作一个程序,我正在用平移手势画一条线。我可以做出手势,但问题是我无法在我用鼠标经过的地方画图,每次它重新加载我之前删除的那个点时。帮
如何使用 SVG 绘制连接 2 个图像的线?。例如我想画一条线连接 $1 和 $2(假设 $1 和 $2 是图像): $1 $2 是否需要 Javascript? 谢谢! 最佳答案 您可以轻松
我在创建此代码时遇到问题。我遇到的问题是,当我单击以停止绘制线条时,它有 50% 的机会第一次工作但是如果你只做直线,它似乎只能正常工作,但我希望它从任何方向工作,我不是 100% 确定为什么它不工作
我想在我的 TextView 中的数字/字母之间绘制垂直线。所以它看起来应该类似于 A|B|C|D 不使用 | 字符,而是使用 drawLine()。 我正在尝试使用 TextView 的宽度来做到这
我刚刚开始使用 AWT 来使用 GUI。框架正在打开,但线路未显示。 import java.awt.*; import java.awt.event.*; class A extends Frame
我可以使用 CGContext 绘制线条。如何使用 UIView 绘制具有相同坐标的线?以后想移动线条,需要用到UIView。 func DrawLine() { UIGraphicsBegi
请在此处查看我的代码 http://jsbin.com/ijoxa3/edit var drawHorizondalLine = function(x1,y1,x2,y2, color) {
IE9 Canvas 现在支持虚线吗?目前我正在做一些与以下非常相似的事情: var CP = window.CanvasRenderingContext2D && CanvasRenderingCo
我有一个程序,我正试图在一个小部件上画一条线。这是我的代码: 标题: #include #include class DrawingWidget : public QWidget{ Q_O
基于此question ,我写了这个 jsfiddle ,我想补充两点。问题可能是点位于六边形内。 这是 HTML:
我正在尝试从一个对象到目标对象画一条线。我设法做到了这一点,但是线条是从中心绘制的 我想做的是在目标上绘制从平面边缘到平面边缘的线 在此图像中,白线是当前绘制的连接,红线是我希望绘制线的方式 现在线条
如何添加线条,就像我在 Paint 中使用 ILNumerics 绘制一样?我的场景正在使用该代码构建: ilPanel1.Scene = new ILScene() { new ILP
我是一名优秀的程序员,十分优秀!