10

Potrzebuję zmienić rozmiar i przyciąć obraz do określonej szerokości i wysokości. Udało mi się skonstruować metodę, która stworzy kwadratową miniaturę, ale nie jestem pewien, jak to zastosować, gdy pożądana miniatura nie jest kwadratowa.App Engine Przycinanie do określonej szerokości i wysokości

def rescale(data, width, height): 
"""Rescale the given image, optionally cropping it to make sure the result image has the specified width and height.""" 
from google.appengine.api import images 

new_width = width 
new_height = height 

img = images.Image(data) 

org_width, org_height = img.width, img.height 

# We must determine if the image is portrait or landscape 
# Landscape 
if org_width > org_height: 
    # With the Landscape image we want the crop to be centered. We must find the 
    # height to width ratio of the image and Convert the denominater to a float 
    # so that ratio will be a decemal point. The ratio is the percentage of the image 
    # that will remain. 
    ratio = org_height/float(org_width) 
    # To find the percentage of the image that will be removed we subtract the ratio 
    # from 1 By dividing this number by 2 we find the percentage that should be 
    # removed from each side this is also our left_x coordinate 
    left_x = (1- ratio)/2 
    # By subtract the left_x from 1 we find the right_x coordinate 
    right_x = 1 - left_x 
    # crop(image_data, left_x, top_y, right_x, bottom_y), output_encoding=images.PNG) 
    img.crop(left_x, 0.0, right_x, 1.0) 
    # resize(image_data, width=0, height=0, output_encoding=images.PNG) 
    img.resize(height=height) 
# Portrait 
elif org_width < org_height: 
    ratio = org_width/float(org_height) 
    # crop(image_data, left_x, top_y, right_x, bottom_y), output_encoding=images.PNG) 
    img.crop(0.0, 0.0, 1.0, ratio) 
    # resize(image_data, width=0, height=0, output_encoding=images.PNG) 
    img.resize(width=witdh) 

thumbnail = img.execute_transforms() 
return thumbnail 

Jeśli jest lepszy sposób, aby to zrobić, proszę dać mi znać. Każda pomoc będzie bardzo ceniona.

Oto schemat wyjaśniający pożądany proces. crop_diagram

Dzięki

Kyle

Odpowiedz

17

Miałem podobny problem (twój zrzut ekranu był bardzo przydatny). To jest moje rozwiązanie:

def rescale(img_data, width, height, halign='middle', valign='middle'): 
    """Resize then optionally crop a given image. 

    Attributes: 
    img_data: The image data 
    width: The desired width 
    height: The desired height 
    halign: Acts like photoshop's 'Canvas Size' function, horizontally 
      aligning the crop to left, middle or right 
    valign: Verticallly aligns the crop to top, middle or bottom 

    """ 
    image = images.Image(img_data) 

    desired_wh_ratio = float(width)/float(height) 
    wh_ratio = float(image.width)/float(image.height) 

    if desired_wh_ratio > wh_ratio: 
    # resize to width, then crop to height 
    image.resize(width=width) 
    image.execute_transforms() 
    trim_y = (float(image.height - height)/2)/image.height 
    if valign == 'top': 
     image.crop(0.0, 0.0, 1.0, 1 - (2 * trim_y)) 
    elif valign == 'bottom': 
     image.crop(0.0, (2 * trim_y), 1.0, 1.0) 
    else: 
     image.crop(0.0, trim_y, 1.0, 1 - trim_y) 
    else: 
    # resize to height, then crop to width 
    image.resize(height=height) 
    image.execute_transforms() 
    trim_x = (float(image.width - width)/2)/image.width 
    if halign == 'left': 
     image.crop(0.0, 0.0, 1 - (2 * trim_x), 1.0) 
    elif halign == 'right': 
     image.crop((2 * trim_x), 0.0, 1.0, 1.0) 
    else: 
     image.crop(trim_x, 0.0, 1 - trim_x, 1.0) 

    return image.execute_transforms() 
+0

Dziękuję. Właśnie tego szukałem. –

+0

wielkie dzięki za kod, działa świetnie! – goggin13

+0

thx! dokładnie to, czego szukałem. – fceruti

2

Można określić zarówno heightiwidth parametry resize - nie zmieni proporcje (nie można tego zrobić z GAE na moduł images), ale upewni się, że każdy z dwóch wymiarów jest zgodny z określoną wartością (w rzeczywistości jeden będzie dokładnie równy podanej wartości, a drugi będzie <=).

Nie jestem pewien, dlaczego najpierw przycinasz i później zmieniasz rozmiar - wygląda na to, że powinieneś zrobić coś odwrotnie ... zmienić rozmiar tak, aby oryginalny obraz "pasował", jak to możliwe, następnie przycinaj, aby zapewnić dokładny wynikowy wymiar. (Nie używałbyś oryginalnych podanych wartości wysokości i szerokości do zmiany rozmiaru - skalowałeś je tak, aby żaden z wynikowych obrazów nie był "marnowany" również jako "pusty", jeśli dobrze rozumiem twoje wymagania). Może więc nie rozumiem dokładnie tego, czego potrzebujesz - czy mógłbyś podać przykład (adresy URL obrazu, który wygląda przed przetworzeniem, po to, jak powinien wyglądać po przetwarzaniu, i szczegóły parametrów, które chcesz przekazać) ?

+0

Dziękuję Alex, powiedzmy, że mam na przykład obraz o szerokości 500 pikseli i wysokości 300 pikseli. Chciałbym, aby przycięty obraz (miniatura) miał szerokość 150 pikseli i wysokość 100 pikseli. Wierzę, że masz pierwsze prawo do zmiany rozmiaru. Jestem pewien, że cała funkcja jest dość prosta, właśnie walczę z kodem. Oto link do diagramu opisującego proces. http://farm3.static.flickr.com/2543/4205690696_b3821a12e9_o.gif –