如何在不使用乘法的情况下绘制实心圆?

时间:2011-12-16 06:53:30

标签: math graphics

假设您处于受限计算环境中,乘法操作很昂贵或不可用。您可以访问已知尺寸图像的像素流。你如何在图像上画圆圈?

1 个答案:

答案 0 :(得分:2)

这是一个Python脚本,演示了如何在不使用乘法的情况下绘制圆。它使用公式x 2 + y 2 > r 2 检查当前像素位置(x,y)是否在圆外。

the rate of change of the difference between the squares of adjacent pixel indices is 2开始,可以使用加法来维持平方值的运行计算。当您遍历像素时,您将继续向正在运行的“正方形”计算中添加一个数字(称为z),对于每个像素,您还将向z添加2。

下面的__init__函数确实包含一些乘法运算。但是,如果图像尺寸不变,编译器将执行乘法,并仅将结果加载到设备上。如果图像尺寸不是常数,则只需在启动时执行一次“慢”乘法,而不是每像素执行一次。

#!/usr/bin/env python

class CircularMaskGenerator:
    '''Generates a circular "mask" for an image.
    Maintains a running computation of squared values to eliminate the need for multiplication'''

    def __init__(self, w, h):
        self.image_width = w
        self.image_height = h

        # Precompute some important values.
        # The embedded device doesn't actaully have to do this math; the
        # compiler does it before loading the code onto the device.

        self.half_image_width = self.image_width >> 1
        self.half_image_height = self.image_height >> 1
        self.radius = self.half_image_height

        self.squared_half_image_width = self.half_image_width*self.half_image_width
        self.squared_half_image_height = self.half_image_height*self.half_image_height
        self.squared_radius = self.radius*self.radius

        # The "deltas" are the difference between the squared values of adjacent pixel indices.
        self.initial_x_squared_delta = 1 - self.image_width
        self.initial_y_squared_delta = 1 - self.image_height

        self.resetFrame()

    def resetFrame(self):

        # Start with a white binary image
        import Image
        self.image = Image.new("1", (self.image_width, self.image_height), 1)
        self.pixels = self.image.load()

        # Reset indices
        self.resetColumnIndex()
        self.resetRowIndex()

    def processPixel(self):

        # Write a black pixel if we're outside the circle
        if self.current_x_squared + self.current_y_squared > self.squared_radius:
            self.pixels[(self.current_column_index, self.current_row_index)] = 0

        self.updateIndices()

    def updateIndices(self):
        '''Update the indices and squares values'''

        self.incrementColumnIndex()

        # Wrap to the next row if necessary
        if self.current_column_index == self.image_width:
            self.incrementRowIndex()

            # Wrap to the next frame if necessary
            if self.current_row_index == self.image_height:
                self.writeImage()
                self.resetFrame()

    def incrementColumnIndex(self):
        self.current_column_index += 1
        self.current_x_squared += self.current_x_squared_delta
        self.current_x_squared_delta += 2

    def resetColumnIndex(self):
        self.current_column_index = 0
        self.current_x_squared = self.squared_half_image_width
        self.current_x_squared_delta = self.initial_x_squared_delta

    def incrementRowIndex(self):
        '''The row increment has to send the column index back to the left.'''

        self.resetColumnIndex()

        self.current_row_index += 1
        self.current_y_squared += self.current_y_squared_delta
        self.current_y_squared_delta += 2

    def resetRowIndex(self):
        self.current_row_index = 0
        self.current_y_squared = self.squared_half_image_height
        self.current_y_squared_delta = self.initial_y_squared_delta

    def writeImage(self):
        '''Save the image in PNG format in the current directory'''
        self.image.save("output.png", "PNG")

# =============================================================================
def simulate_system():

    image_width = 800
    image_height = 600

    # initialize the system
    circle_processor = CircularMaskGenerator(image_width, image_height)

    # supply a pixel stream to drive the system
    for i in xrange(image_width*image_height):
        circle_processor.processPixel()

# =============================================================================
if __name__ == "__main__":
    simulate_system()

此代码创建一个居中的圆圈,如下所示:

enter image description here