2013-12-08 69 views
2

我正在研究將圖像轉換爲灰度或反轉顏色的程序。它使用不同的灰度算法,大部分工作正常,但我遇到了一些我一直在努力克服的問題。我有一個問題是試圖保存圖像。爲了能夠處理不同的文件類型,我使用PIL打開圖像,然後將其轉換爲tk PhotoImage。現在圖像是PhotoImage我找不出一種方法來保存,Tkinter的文檔提到了一種方法,但是失敗了。我的另一個問題是我想使用複選框來旋轉圖像,我有一個功能rotateIt這樣做,但我無法獲得複選框的工作,因爲IntVar()似乎沒有改變,請注意我的使用lambda使它與單選按鈕一起工作。 (感謝這裏的另一位成員)這是程序的代碼。 (我還在學習,遇到問題搞清楚如何不使用全局變量來完成相同的任務。)將tk PhotoImage轉換回PIL圖像以節省一些麻煩

from PIL import Image, ImageTk 
from graphics import GraphWin 
from tkinter import filedialog # Will be used to open the file from the user 
import tkinter 
import os 

# Global variables for radio buttons---- 
radio1 = True 
radio2 = False 
radio3 = False 
radio4 = False 
#-------------------------------------------- 

# Global variables for picture----------- 
pic = '' 
tkPic = '' 
tkPic2 = '' 
picToConvert = '' 
picWidth = 0 
picHeight = 0 
canvas1 = '' 
#--------------------------------------------- 

def rotateIt(pic1): 
    pictureRotated = pic1.rotate(180) 
    return pictureRotated 
# Function for radio buttons 

def whichSelected(numberSelected): 
     global radio1 
     global radio2 
     global radio3 
     global radio4 
     if numberSelected == 4: 
      radio1 = False 
      radio4 = True 
     if numberSelected == 3: 
      radio1 = False 
      radio3 = True 
     if numberSelected == 2: 
      radio1 = False 
      radio2 = True 
     if numberSelected == 1: 
      radio1 = True 


# Gray Algorithms--------------------------------------------- 
def grayAverage(r,g,b): 
    algorithm = (r + g + b) // 3 
    return (algorithm) 

def invertRGB(r,g,b): 
     r = 255 - r 
     g = 255 - g 
     b = 255 - b 
     return (r,g,b) 

def lightness(r,g,b): 
     algorithm = (max(r, g, b) + min(r, g, b)) // 2 
     return (algorithm) 

def luminosity(r,g,b): 
     algorithm = int(((0.21 * r) + (0.71 * g) + (0.07 * b))) 
     return (algorithm) 

def getRGB(r,g,b): 
     red = eval(input ("Enter the value of red: ")) 
     green = eval(input ("Enter the value of green: ")) 
     blue = eval(input ("Enter the value of blue: ")) 
     algorithm = red-r + green-g + blue-b // 3 
     return (algorithm) 
# End Gray Algorithms----------------------------------------------------------------------------- 

# Draws window, opens picture selected by user, packs the canvas 
def drawWindow(): 
    window = tkinter.Tk() 
    window.title(os.environ.get("USERNAME")) # sets the window title to the 
    return window 

def drawCanvas(): 
    global window 
    global canvas1 
    canvas1 = tkinter.Canvas(window, width = 820, height =340) # Draws a canvas onto the tkinter window 
    canvas1.pack() 
    return canvas1 

# Global variables for window and canvas 
window = drawWindow() 
canvas1 = drawCanvas() 
# ----------------------------------------------------------------------------------- 

    # Radio Button Code--------------------------------------------------------- 
def drawRadioButtons(): 
    global window 
    var = tkinter.IntVar() 
    option1 = tkinter.Radiobutton(window, text ='Average Grayscale   ',variable = var, value = 1,command = lambda: whichSelected(1)) 
    option2 = tkinter.Radiobutton(window, text ='Lightness Grayscale   ',variable = var, value = 2, command = lambda: whichSelected(2)) 
    option3 = tkinter.Radiobutton(window, text ='Luminosity Grayscale  ',variable = var, value = 3, command = lambda: whichSelected(3)) 
    option4 = tkinter.Radiobutton(window, text ='Invert',variable = var, value = 4, command = lambda: whichSelected(4)) 

    option1.select() # Sets the first button to clicked 
    # Pack Radio Buttons 
    option1.pack(anchor = 'sw') 
    option2.pack(anchor = 'sw') 
    option3.pack(anchor = 'sw') 
    option4.pack(anchor = 'sw') 
    # End Radio Button code --------------------------------------------------------- 

def openImage(): 
    global window 
    global canvas1 
    global pic 
    global picWidth 
    global picHeight 
    global tkPic 
    global tkPic2 
    global picToConvert 
    canvas1.delete('all') 
    del pic 
    del tkPic 
    picToConvert = filedialog.askopenfilename(defaultextension='.jpg') # Used to open the file selected by the user 
    pic = Image.open(picToConvert) 
    picWidth, picHeight = pic.size # PIL method .size gives both the width and height of a picture 
    tkPic = ImageTk.PhotoImage(pic, master = window) # Converts the pic image to a tk PhotoImage 
    canvas1.create_image(10,10,anchor='nw', image = tkPic) 

def saveImage(): 
    global pic 
    global tkPic2 
    pic = Image.open(tkPic2) 
    toSave = filedialog.asksaveasfile(mode='w',defaultextension='.jpg') 
    pic.save(toSave) 

def change_pixel(): 
    global window 
    global canvas1 
    global tkPic2 
    global pic 
    global radio1 
    global radio2 
    global radio3 
    global radio4 
    # Treats the image as a 2d array, iterates through changing the 
    #values of each pixel with the algorithm for gray 

    rgbList = pic.load() #Get a 2d array of the pixels 
    for row in range(picWidth): 
     for column in range(picHeight): 
      rgb = rgbList[row,column] 
      r,g,b = rgb # Unpacks the RGB value tuple per pixel 
      if radio1 == True: 
       grayAlgorithm1 = grayAverage(r,g,b) 
       rgbList[row,column] = (grayAlgorithm1, grayAlgorithm1, grayAlgorithm1) 
      elif radio2 == True: 
       grayAlgorithm1 = lightness(r,g,b) 
       rgbList[row,column] = (grayAlgorithm1, grayAlgorithm1, grayAlgorithm1) 
      elif radio3 == True: 
       grayAlgorithm1= luminosity(r,g,b) 
       rgbList[row,column] = (grayAlgorithm1, grayAlgorithm1, grayAlgorithm1) # Gives each pixel a new RGB value 
      elif radio4 == True: 
       r,g,b= invertRGB(r,g,b) 
       rgbList[row,column] = (r, g, b) # Gives each pixel a new RGB value 
     # Converting to a tkinter PhotoImage 
    del tkPic2 
    tkPic2 = ImageTk.PhotoImage(pic, master = window) 
    canvas1.create_image(815,170, anchor='e',image = tkPic2) 

# Function to create a button, takes the button text and the function to be called on click 
def tkButtonCreate(text, command): 
    tkinter.Button(window, text = text, command = command).pack() 

def main(): 
    drawRadioButtons() 
    tkButtonCreate('Open Image',openImage) 
    tkButtonCreate('Convert', change_pixel) 
    tkButtonCreate('Save',saveImage) 
    window.mainloop() 
    #convertButton = tkinter.Button(window,text = 'Convert', command = change_pixel).pack() 
main() 
+1

「......但失敗。」定義‘失敗’。你有錯誤嗎?圖像是否保存在原始狀態?圖像沒有保存,但tkinter報告它是? –

+0

Tk的文檔顯示了一個使用IO字符串對象的.save()方法。這個失敗,我假設,因爲它不能寫PIL PhotoImage – DougLuce

+0

_how_它會失敗嗎?它會崩潰嗎?拋出錯誤?什麼錯誤? –

回答

2

saveImage()

刪除pic = Image.open(tkPic2)要保存文件使用:

def saveImage(): 
    global pic 
    toSave = filedialog.asksaveasfile(mode='w',defaultextension='.jpg') 
    pic.save(toSave) 

其它:爲更好地使用物體None代替''

pic = None 
tkPic = None 
tkPic2 = None 
picToConvert = None 
canvas1 = None 

此外,del給你None

del tkPic2 # now tkPic2 == None 

編輯:用IntVar和旋轉的問題解決方案。

我創建全局變量var = None,然後我可以在函數中使用它(使用global var

我「到位」使用pic = pic.rotate(180)旋轉無新的變量。

我添加單選按鈕Rotation和功能onConvert運行rotateItchange_pixel,現在我創造tkPic2onConvert

from PIL import Image, ImageTk 
#from graphics import GraphWin # not needed 

# for Python 3.x 
from tkinter import filedialog # Will be used to open the file from the user 
import tkinter 

# for Python 2.x 
#import Tkinter as tkinter 
#import tkFileDialog as filedialog # Will be used to open the file from the user 

import os 

# --- Global variables for radio buttons --- 

radio1 = True 
radio2 = False 
radio3 = False 
radio4 = False 

#-------------------------------------------- 

# --- Global variables for picture --- 

pic = None 
tkPic = None 
tkPic2 = None 
picToConvert = None 
picWidth = 0 
picHeight = 0 
canvas1 = None 

var = None #create global variable 

#---------------------------------------------------------------------- 

def rotateIt(): 
    global pic 

    print "(debug) rotateIt:", pic 
    pic = pic.rotate(180) 

# --- Function for radio buttons --- 

def whichSelected(numberSelected): 
     global radio1 
     global radio2 
     global radio3 
     global radio4 

     if numberSelected == 4: 
      radio1 = False 
      radio4 = True 
     elif numberSelected == 3: 
      radio1 = False 
      radio3 = True 
     elif numberSelected == 2: 
      radio1 = False 
      radio2 = True 
     elif numberSelected == 1: 
      radio1 = True 


# --- Gray Algorithms --- 

def grayAverage(r, g, b): 
    return (r + g + b) // 3 

def invertRGB(r,g,b): 
    return (255 - r, 255 - g, 255 - b) 


def lightness(r,g,b): 
    return (max(r, g, b) + min(r, g, b)) // 2 

def luminosity(r,g,b): 
    return int(((0.21 * r) + (0.71 * g) + (0.07 * b))) 

def getRGB(r,g,b): 
    red = eval(input("Enter the value of red: ")) 
    green = eval(input("Enter the value of green: ")) 
    blue = eval(input("Enter the value of blue: ")) 

    return red-r + green-g + blue-b // 3 

# --- End Gray Algorithms --- 

# Draws window, opens picture selected by user, packs the canvas 
def drawWindow(): 
    window = tkinter.Tk() 
    window.title(os.environ.get("USERNAME")) # sets the window title to the 

    return window 

def drawCanvas(): 
    global window 
    global canvas1 
    canvas1 = tkinter.Canvas(window, width = 820, height =340) # Draws a canvas onto the tkinter window 
    canvas1.pack() 

    return canvas1 

# Global variables for window and canvas 
window = drawWindow() 
canvas1 = drawCanvas() 

#---------------------------------------------------------------------- 

# --- Radio Button Code --- 

def drawRadioButtons(): 
    global window, var 

    var = tkinter.IntVar() 

    option1 = tkinter.Radiobutton(window, text ='Average Grayscale', variable = var, value = 1, command = lambda: whichSelected(1)) 
    option2 = tkinter.Radiobutton(window, text ='Lightness Grayscale', variable = var, value = 2, command = lambda: whichSelected(2)) 
    option3 = tkinter.Radiobutton(window, text ='Luminosity Grayscale', variable = var, value = 3, command = lambda: whichSelected(3)) 
    option4 = tkinter.Radiobutton(window, text ='Invert',    variable = var, value = 4, command = lambda: whichSelected(4)) 
    option5 = tkinter.Radiobutton(window, text ='Rotate 180',   variable = var, value = 5) 

    # Sets the first button to clicked 
    option1.select() 

    # Pack Radio Buttons 
    option1.pack(anchor = 'sw') 
    option2.pack(anchor = 'sw') 
    option3.pack(anchor = 'sw') 
    option4.pack(anchor = 'sw') 
    option5.pack(anchor = 'sw') 
    # End Radio Button code 

def openImage(): 
    global window 
    global canvas1 
    global pic 
    global picWidth 
    global picHeight 
    global tkPic 
    global tkPic2 
    global picToConvert 

    canvas1.delete('all') 
    del pic 
    del tkPic 

    picToConvert = filedialog.askopenfilename(defaultextension='.jpg') # Used to open the file selected by the user 
    pic = Image.open(picToConvert).convert('RGB') 
    picWidth, picHeight = pic.size # PIL method .size gives both the width and height of a picture 
    tkPic = ImageTk.PhotoImage(pic, master = window) # Converts the pic image to a tk PhotoImage 
    canvas1.create_image(10,10,anchor='nw', image = tkPic) 

#---------------------------------------------------------------------- 

def saveImage(): 
    global pic 

    toSave = filedialog.asksaveasfile(mode='w',defaultextension='.jpg') 
    pic.save(toSave) 

#---------------------------------------------------------------------- 

def onConvert(): 
    global var 
    global tkPic2 
    global window 

    if var.get() == 5: 
     rotateIt(pic) 
    else: 
     change_pixel() 

    # Converting to a tkinter PhotoImage 

    if tkPic2: 
     del tkPic2 

    tkPic2 = ImageTk.PhotoImage(pic, master = window) 
    canvas1.create_image(815,170, anchor='e',image = tkPic2) 

#---------------------------------------------------------------------- 

def change_pixel(): 
    global window 
    global canvas1 
    global pic 

    global radio1 
    global radio2 
    global radio3 
    global radio4 

    # Treats the image as a 2d array, iterates through changing the 
    #values of each pixel with the algorithm for gray 

    rgbList = pic.load() #Get a 2d array of the pixels 
    for row in range(picWidth): 
     for column in range(picHeight): 
      rgb = rgbList[row,column] 
      #print rgb 
      r,g,b = rgb # Unpacks the RGB value tuple per pixel 
      if radio1 == True: 
       grayAlgorithm1 = grayAverage(r,g,b) 
       rgbList[row,column] = (grayAlgorithm1, grayAlgorithm1, grayAlgorithm1) 
      elif radio2 == True: 
       grayAlgorithm1 = lightness(r,g,b) 
       rgbList[row,column] = (grayAlgorithm1, grayAlgorithm1, grayAlgorithm1) 
      elif radio3 == True: 
       grayAlgorithm1= luminosity(r,g,b) 
       rgbList[row,column] = (grayAlgorithm1, grayAlgorithm1, grayAlgorithm1) # Gives each pixel a new RGB value 
      elif radio4 == True: 
       rgbList[row,column] = invertRGB(r,g,b) # Gives each pixel a new RGB value 

#---------------------------------------------------------------------- 

# Function to create a button, takes the button text and the function to be called on click 
def tkButtonCreate(text, command): 
    tkinter.Button(window, text = text, command = command).pack() 

#---------------------------------------------------------------------- 

def main(): 
    drawRadioButtons() 
    tkButtonCreate('Open Image',openImage) 
    tkButtonCreate('Convert', onConvert) 
    tkButtonCreate('Save',saveImage) 
    window.mainloop() 
    #convertButton = tkinter.Button(window,text = 'Convert', command = change_pixel).pack() 

#---------------------------------------------------------------------- 

main() 
+0

這是輸出在對saveImage()進行修改後,我認爲這是我第一次嘗試保存這個文件時收到的原始錯誤。 'Tkinter回調中的例外 回溯(最近一次通話最後): 文件「C:\ python33 \ lib \ tkinter \ __ init__」。文件「L:\ Final Project \#Greyscale_rev8.py」,第138行,在saveImage tkPic2.save(toSave) AttributeError:'PhotoImage',第1475行,在__call__中 返回self.func(* args) 對象沒有屬性'save'' – DougLuce

+0

我將它們切換爲None,使用None變得更有意義,這要感謝 – DougLuce

+1

我正確的代碼 - 我看到你已經在'pic'中轉換圖像,所以不需要使用'tkPic2' – furas