Должен ли я объединять изображения в памяти (.py) или в представлении (HTML)? - PullRequest
1 голос
/ 26 сентября 2011

My facebook app позволяет пользователю загрузить изображение, выбрать его изображение (глаза, нос, рот или другую часть тела), а затем объединить, выбрав три случайных изображения по категории, и это прекрасно работает. и код выглядит хорошо и читабельно, хотя и не очень продвинутый:

class CyberFazeHandler(BaseHandler):

    def get_random_image(self, category):
        fileinfos = FileInfo.all().filter("category =", category)
        return fileinfos[random.randint(0, fileinfos.count()-1)] 

    def get(self):
        eyes_image = self.get_random_image(category="eyes")
    nose_image = self.get_random_image(category="nose")
    mouth_image = self.get_random_image(category="mouth")
        eyes_data = None
        try:
        eyes_data = blobstore.fetch_data(eyes_image.blob.key(), 0, 50000)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find eyes data for file '+str(eyes_image.key().id())+' (' + unicode(e) + u')')

        eyes_img = None

        try:
            eyes_img = images.Image(image_data=eyes_data)

... теперь я просто выбираю 3 случайных изображения и затем объединяю их в шаблон:

<a href="/file/{{eyes_image.key.id}}"><img src="{{eyes_url}}"></a><br>
<a href="/file/{{nose_image.key.id}}"><img src="{{nose_url}}"></a><br>
<a href="/file/{{mouth_image.key.id}}"><img src="{{mouth_url}}"></a>

Можно ли это улучшить, отправив составное изображение, объединяющее три изображения в одно? Преимущество состоит в том, что все изображение будет загружаться одновременно и что оно будет сохранено уже, если в следующий раз произойдет рандомизация, результат уже будет сохранен. Что ты думаешь?

Спасибо (приложение apps.facebook.com/cyberfaze, вы можете проверить, что я сделал для удовольствия и обучения)

Весь класс

class CyberFazeHandler(BaseHandler):

    def get_random_image(self, category):
        fileinfos = FileInfo.all().filter("category =", category)
        return fileinfos[random.randint(0, fileinfos.count()-1)] #optimize

    def get(self):
        eyes_image = self.get_random_image(category="eyes")
    nose_image = self.get_random_image(category="nose")
    mouth_image = self.get_random_image(category="mouth")
        eyes_data = None
        try:
        eyes_data = blobstore.fetch_data(eyes_image.blob.key(), 0, 50000)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find eyes data for file '+str(eyes_image.key().id())+' (' + unicode(e) + u')')

        eyes_img = None

        try:
            eyes_img = images.Image(image_data=eyes_data)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find eyes img for file '+str(eyes_image.key().id())+' (' + unicode(e) + u')')


        nose_data = None
        try:
            nose_data = blobstore.fetch_data(nose_image.blob.key(), 0, 50000)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find nose data for file '+str(nose_image.key().id())+' (' + unicode(e) + u')')


        nose_img = None

        try:
            nose_img = images.Image(image_data=nose_data)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find nose img for file '+str(nose_image.key().id())+' (' + unicode(e) + u')')


        mouth_data = None
        try:
        mouth_data = blobstore.fetch_data(mouth_image.blob.key(), 0, 50000)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find mouth data for file '+str(eyes_image.key().id())+' (' + unicode(e) + u')')


        mouth_img = None

        try:
            mouth_img = images.Image(image_data=mouth_data)
        except Exception, e:
            self.set_message(type=u'error',
                content=u'Could not find mouth img for file '+str(mouth_image.key().id())+' (' + unicode(e) + u')')


    minimum = min(int(eyes_img.width), int(nose_img.width), int(mouth_img.width))

    eyes_url = images.get_serving_url(str(eyes_image.blob.key()), size=minimum)
    nose_url = images.get_serving_url(str(nose_image.blob.key()), size=minimum)
    mouth_url = images.get_serving_url(str(mouth_image.blob.key()), size=minimum)

        self.render(u'cyberfaze', minimum=minimum, eyes_image=eyes_image, eyes_url=eyes_url, nose_image=nose_image, nose_url=nose_url, mouth_image=mouth_image, mouth_url=mouth_url, form_url = blobstore.create_upload_url('/upload'),)

После перезаписи он работает как сказано:

class CyberFazeHandler(BaseHandler):

    def get_random_image(self, category):

        q = FileInfo.all()
        q.filter('category =', category)
        q.filter('randomvalue >=', random.random())
        return q.get()

    def get_random_image_legacy(self, category):
        fileinfos = FileInfo.all().filter('category =', category)
        return fileinfos[random.randint(0, fileinfos.count() - 1)]

    def get(self):

        eyes_image = self.get_random_image(category='eyes')
    if not eyes_image:
       logging.debug("getting eyes failed, trying legacy method")
           eyes_image = self.get_random_image_legacy(category='eyes')
        nose_image = self.get_random_image(category='nose')
    if not nose_image:
           nose_image = self.get_random_image_legacy(category='nose')

        mouth_image = self.get_random_image(category='mouth')
    if not mouth_image:
           mouth_image = self.get_random_image_legacy(category='mouth')

        eyes_data = None
        try:
            eyes_data = blobstore.fetch_data(eyes_image.blob.key(), 0,
                    50000)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find eyes data for file '
                              + str(eyes_image.key().id()) + ' ('
                             + unicode(e) + u')')

        eyes_img = None

        try:
            eyes_img = images.Image(image_data=eyes_data)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find eyes img for file '
                              + str(eyes_image.key().id()) + ' ('
                             + unicode(e) + u')')

        nose_data = None
        try:
            nose_data = blobstore.fetch_data(nose_image.blob.key(), 0,
                    50000)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find nose data for file '
                              + str(nose_image.key().id()) + ' ('
                             + unicode(e) + u')')

        nose_img = None

        try:
            nose_img = images.Image(image_data=nose_data)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find nose img for file '
                              + str(nose_image.key().id()) + ' ('
                             + unicode(e) + u')')

        mouth_data = None
        try:
            mouth_data = blobstore.fetch_data(mouth_image.blob.key(),
                    0, 50000)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find mouth data for file '
                              + str(eyes_image.key().id()) + ' ('
                             + unicode(e) + u')')

        mouth_img = None

        try:
            mouth_img = images.Image(image_data=mouth_data)
        except Exception, e:
            self.set_message(type=u'error',
                             content=u'Could not find mouth img for file '
                              + str(mouth_image.key().id()) + ' ('
                             + unicode(e) + u')')

        minimum = min(int(eyes_img.width), int(nose_img.width),
                      int(mouth_img.width))

        eyes_url = images.get_serving_url(str(eyes_image.blob.key()),
                size=minimum)
        nose_url = images.get_serving_url(str(nose_image.blob.key()),
                size=minimum)
        mouth_url = images.get_serving_url(str(mouth_image.blob.key()),
                size=minimum)

        self.render(
            u'cyberfaze',
            minimum=minimum,
            eyes_image=eyes_image,
            eyes_url=eyes_url,
            nose_image=nose_image,
            nose_url=nose_url,
            mouth_image=mouth_image,
            mouth_url=mouth_url,
            form_url=blobstore.create_upload_url('/upload'),
            )

1 Ответ

1 голос
/ 27 сентября 2011

То, что более эффективно, зависит от того, как оно будет использовано.Если пользователь будет загружать много таких гибридных приложений, имеет смысл отправлять их как отдельные изображения, потому что браузер будет кэшировать меньше изображений (a + b + c изображений вместо a * b * c).

Ваш код имеет гораздо более вопиющую проблему с производительностью, однако:

def get_random_image(self, category):
    fileinfos = FileInfo.all().filter("category =", category)
    return fileinfos[random.randint(0, fileinfos.count()-1)] 

Каждый раз, когда вы вызываете эту функцию, он будет выполнять операцию подсчета, которая равна O (n) с числомиз FileInfo объектов, затем выполните запрос смещения, который равен O (n) со смещением.Это очень медленно и неэффективно, и будет увеличиваться по мере увеличения количества изображений.

Если вы ожидаете, что набор изображений будет небольшим (менее нескольких тысяч) и достаточно постоянным, просто сохраните ихв коде, который будет быстрее, чем любой другой вариант.Если набор больше или изменяется во время выполнения, присвойте случайное значение в диапазоне от 0 до 1 каждому объекту и используйте такой запрос, чтобы получить случайно выбранный объект:

q = FileInfo.all()
q.filter('category =', category)
q.filter('random >=', random.random())
return q.get()
...