2013-03-23 112 views
1

嗨即時嘗試繪製對角線在圖像右上角到左下角這裏是我的代碼到目前爲止。在圖像上繪製對角線

width = getWidth(picture) 
    height = getHeight(picture) 
    for x in range(0, width): 
    for y in range(0, height): 
     pixel = getPixel(picture, x, y) 
     setColor(pixel, black) 

感謝

+1

你應該提到你正在使用的圖形庫... – MartinStettner

+0

即時爲學生使用jython環境 – user2194374

回答

1

哪裏你picture對象來自哪裏?它是什麼?到目前爲止還沒有工作?你試圖使用什麼樣的圖像訪問? (我的意思是,你從哪裏得到,或打算獲得「getWidth,getHeight,getPixel,setColor)從?

我認爲沒有圖書館,給你一個」像素「作爲一個整體對象,可以在setColor呼叫是存在的,如果是這樣,它將是世界上最慢的東西 - 也許在銀河系中。

另一方面,如果這些方法確實存在,並且你的圖片,上面的代碼將覆蓋所有的圖像黑色 - 您將在圖像的所有可能的x值(從0到寬度)內獲得所有可能的「y」值(從0到高度),並着色每個黑色

繪製一條線需要您更改x和y同時,更像是:

(使用另一種「虛庫」,而是一個更合理:

for x, y in zip(range(0, width), range(0, height)): 
    picture.setPixel((x,y), Black)) 

這將排序工作,但線不會是完美的,除非形象是完美的正方形 - 否則它會跳過像素圖像最寬的方向。爲了解決這個問題,需要一個更精確的算法 - 但這是第二個你有一個真正的方法來訪問圖像上的像素 - 就像使用Python的成像庫(PIL或Pillow)或pygame或其他庫。

+0

即時通訊使用jython環境爲學生創建圖片較早,是的,它是非常緩慢的獲得所有的像素。是的,我認爲它也是全黑的,但是它從左到右在左側形成了一條粗黑線。 – user2194374

+1

事實上,JES(Jython Environmen for Students)確實會給你一個「像素對象」作爲getPixel的返回值... – MartinStettner

+0

感謝您澄清@MartinStettner - 我永遠不會猜測這樣的事情是真的。 – jsbueno

4

大多數圖形庫都有一些直接繪製直線的方法。

JES存在addLine功能,讓你可以做

addLine(picture, 0, 0, width, height) 

如果你堅持設定的單個像素,你應該看看Bresenham Line Algorithm,這是最有效的算法,一個畫線。

的說明你的代碼:你現在帶着兩個嵌套循環做的是以下

for each column in the picture 
    for each row in the current column 
    set the pixel in the current column and current row to black 

所以基本上您選擇填充黑色像素的整個圖像。

編輯

要繪製在整個圖像的多個斜線(讓他們之間有一個空格),可以使用下面的循環

width = getWidth(picture) 
height = getHeight(picture) 
space = 10 
for x in range(0, 2*width, space): 
    addLine(picture, x, 0, x-width, height) 

這給你喜歡(例子中的圖像是手繪...)

diagonal lines

這使得使用剪輯功能,大多數圖形庫提供,即不在圖像內的行的部分被忽略。請注意,如果沒有2*width(即如果x去只到with),只有線的上左半部分將被繪製...

+0

我確實使用了addLine,但後來意識到我需要它貫穿整個圖像 – user2194374

+0

「addLine」生成的行出了什麼問題?如果您使用(0,0)和(widht,height)作爲線條的終點,則它應該在整個圖像之後... – MartinStettner

+0

是的,除了它只會在圖片的高度圖片左側。我可以添加一個步驟來擴展線條的範圍,但我不知道如何使它們成爲對角線。 – user2194374

1

我想一些數學方面的考慮加入討論......

(只是因爲它是可悲的是JES的addLine功能只消耗黑線,是相當有限的......)

注:下面的代碼使用Bresenham直線算法 POIN通過MartinStettner(謝謝他)結出。

的佈雷森漢姆直線算法是一種算法,它確定爲了形成近似於兩個給定的點之間的直線。由於像素是一個原子實體,所以只能使用某種近似方法在計算機屏幕上繪製一條線。

注:要理解下面的代碼,你需要記住你的基本的學校數學課程(直線方程&三角)一點點。

代碼:

# The following is fast implementation and contains side effects... 

import random 

# Draw point, with check if the point is in the image area 
def drawPoint(pic, col, x, y): 
    if (x >= 0) and (x < getWidth(pic)) and (y >= 0) and (y < getHeight(pic)): 
    px = getPixel(pic, x, y) 
    setColor(px, col) 


# Draw line segment, given two points 
# From Bresenham's line algorithm 
# http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm 
def drawLine(pic, col, x0, y0, x1, y1): 

    dx = abs(x1-x0) 
    dy = abs(y1-y0) 
    sx = sy = 0 

    #sx = 1 if x0 < x1 else -1 
    #sy = 1 if y0 < y1 else -1 

    if (x0 < x1): 
    sx = 1 
    else: 
    sx = -1 
    if (y0 < y1): 
    sy = 1 
    else: 
    sy = -1 

    err = dx - dy 

    while (True): 

    drawPoint(pic, col, x0, y0) 

    if (x0 == x1) and (y0 == y1): 
     break 

    e2 = 2 * err 
    if (e2 > -dy): 
     err = err - dy 
     x0 = x0 + sx 

    if (x0 == x1) and (y0 == y1): 
     drawPoint(pic, col, x0, y0) 
     break 

    if (e2 < dx): 
     err = err + dx 
     y0 = y0 + sy 


# Draw infinite line from segment 
def drawInfiniteLine(pic, col, x0, y0, x1, y1): 
    # y = m * x + b 
    m = (y0-y1)/(x0-x1) 
    # y0 = m * x0 + b => b = y0 - m * x0 
    b = y0 - m * x0 

    x0 = 0 
    y0 = int(m*x0 + b) 
    # get a 2nd point far away from the 1st one 
    x1 = getWidth(pic) 
    y1 = int(m*x1 + b) 

    drawLine(pic, col, x0, y0, x1, y1) 


# Draw infinite line from origin point and angle 
# Angle 'theta' expressed in degres 
def drawInfiniteLineA(pic, col, x, y, theta): 

    # y = m * x + b 
    dx = y * tan(theta * pi/180.0) # (need radians) 
    dy = y 

    if (dx == 0): 
    dx += 0.000000001 # Avoid to divide by zero 

    m = dy/dx 

    # y = m * x + b => b = y - m * x 
    b = y - m * x 

    # get a 2nd point far away from the 1st one 
    x1 = 2 * getWidth(pic) 
    y1 = m*x1 + b 

    drawInfiniteLine(pic, col, x, y, x1, y1) 


# Draw multiple parallele lines, given offset and angle 
def multiLines(pic, col, offset, theta, randOffset = 0): 
    # Range is [-2*width, 2*width] to cover the whole surface 
    for i in xrange(-2*getWidth(pic), 2*getWidth(pic), offset): 
     drawInfiniteLineA(pic, col, i + random.randint(0, randOffset), 1, theta) 

# Draw multiple lines, given offset, angle and angle offset 
def multiLinesA(pic, col, offsetX, offsetY, theta, offsetA): 
    j = 0 
    # Range is [-2*width, 2*width] to cover the whole surface 
    for i in xrange(-2*getWidth(pic), 2*getWidth(pic), offsetX): 
     drawInfiniteLineA(pic, col, i, j, theta) 
     j += offsetY 
     theta += offsetA 



file = pickAFile() 
picture = makePicture(file) 
color = makeColor(0, 65, 65) #pickAColor() 
#drawline(picture, color, 10, 10, 100, 100) 
#drawInfiniteLine(picture, color, 10, 10, 100, 100) 
#drawInfiniteLineA(picture, color, 50, 50, 135.0) 
#multiLines(picture, color, 20, 56.0) 
#multiLines(picture, color, 10, 56.0, 15) 
multiLinesA(picture, color, 10, 2, 1.0, 1.7) 

show(picture) 


輸出(繪畫由皮爾·索拉格斯):


enter image description here

enter image description here

enter image description here


希望這給了一些有趣的想法JES學生......和其他人,以及...

+0

@everyone當'drawInfiniteLine()'的開始處'm'趨於無限時(浮點溢出),會出現一個重要副作用。這可以通過執行如下操作來避免:'if(abs(m)> 100.0):m = 100.0'緊接在計算'm'之後... –

+0

我不再編輯此答案,但是此* *修正我說的可以在這裏看到**:http://stackoverflow.com/a/17288511/1715716 –