Пример #1
0
    def test_generate_inverted_ascii(self, generate_ascii_mock):
        """
        Tests if the foreground and background are properly inverted when
        generating ASCII "images".
        """

        # Set-up some test data.
        data = "Some test data"

        # Set-up one foreground and background colour. These are not used for
        # ASCII itself (instead a plus/minus sign is used).
        foreground = "#ffffff"
        background = "#000000"

        # Set-up the generator.
        generator = Generator(5, 5, foreground=[foreground], background=background)

        # Verify that foreground/background is picked correctly when no
        # inverstion is requsted.
        generator.generate(data, 200, 200, inverted=False, output_format="ascii")
        generate_ascii_mock.assert_called_with(mock.ANY, "+", "-")

        # Verify that foreground/background is picked correctly when inversion
        # is requsted.
        generator.generate(data, 200, 200, inverted=True, output_format="ascii")
        generate_ascii_mock.assert_called_with(mock.ANY, "-", "+")
Пример #2
0
    def test_generate_matrix(self):
        """
        Verifies that the matrix is generated correctly based on passed hashed
        bytes.
        """

        # The resulting half-matrix should be as follows (first byte is for
        # ignored in matrix generation):
        #
        # 100
        # 011
        # 100
        # 001
        # 110
        hash_bytes = [0b11111111, 0b10101010, 0b01010101]

        expected_matrix = [
            [True, False, False, False, True],
            [False, True, True, True, False],
            [True, False, False, False, True],
            [False, False, True, False, False],
            [True, True, False, True, True],
            ]

        generator = Generator(5, 5)

        matrix = generator._generate_matrix(hash_bytes)

        self.assertEqual(matrix, expected_matrix)
Пример #3
0
    def test_generate_format(self):
        """
        Tests if identicons are generated in requested format.
        """

        # Set-up a generator.
        generator = Generator(5, 5)

        # Set-up some test data.
        data = "some test data"

        # Verify that PNG image is returned when requested.
        raw_image = generator.generate(data, 200, 200, output_format="png")
        image_stream = BytesIO(raw_image)
        image = PIL.Image.open(image_stream)
        self.assertEqual(image.format, "PNG")

        # Verify that JPEG image is returned when requested.
        raw_image = generator.generate(data, 200, 200, output_format="jpeg")
        image_stream = BytesIO(raw_image)
        image = PIL.Image.open(image_stream)
        self.assertEqual(image.format, "JPEG")

        # Verify that GIF image is returned when requested.
        raw_image = generator.generate(data, 200, 200, output_format="gif")
        image_stream = BytesIO(raw_image)
        image = PIL.Image.open(image_stream)
        self.assertEqual(image.format, "GIF")

        # Verify that ASCII "image" is returned when requested.
        raw_image = generator.generate(data, 200, 200, output_format="ascii")
        self.assertIsInstance(raw_image, str)
Пример #4
0
    def test_generate_ascii(self):
        """
        Tests the generated identicon in ASCII format.
        """

        # Set-up parameters that will be used for generating the image.
        foreground = "1"
        background = "0"
        matrix = [
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 1, 1, 1, 0],
            [0, 1, 1, 1, 0],
            ]

        # Set-up a generator.
        generator = Generator(5, 5)

        # Generate the ASCII image.
        ascii_image = generator._generate_ascii(matrix, foreground, background)

        # Verify that the result is as expected.
        expected_result = """00100
00100
00100
01110
01110"""
        self.assertEqual(ascii_image, expected_result)
Пример #5
0
def get_default_image():
    # TODO: change the random generator
    width = 200
    height = 200
    padding = [20, 20, 20, 20]
    foreground = [
        "rgb(45,79,255)", "rgb(254,180,44)", "rgb(226,121,234)",
        "rgb(30,179,253)", "rgb(232,77,65)", "rgb(49,203,115)",
        "rgb(141,69,170)"
    ]
    background = "rgb(224,224,224)"
    generator = Generator(5, 5, foreground=foreground, background=background)
    basestr = strftime("%H-%M-%S", gmtime()) + "-" + str(random.uniform(0, 59))
    raw_image = generator.generate(basestr, width, height, padding=padding)
    image_stream = BytesIO(raw_image)
    image = PIL.Image.open(image_stream)
    image_io = BytesIO()
    image.save(image_io, format='PNG')

    # Create a new Django file-like object to be used in models as ImageField using
    # InMemoryUploadedFile.  If you look at the source in Django, a
    # SimpleUploadedFile is essentially instantiated similarly to what is shown here
    image__in_memory_uploaded_file = InMemoryUploadedFile(
        image_io, None, 'avatar.png', 'image/png', image_io.seek(0, SEEK_END),
        None)
    # give your file to InMemoryUploadedFile to create django imagefield object
    return image__in_memory_uploaded_file
Пример #6
0
    def test_generate_png_compare(self):
        """
        Tests generated PNG identicon against a set of pre-generated samples.
        """

        # Set-up a list of foreground colours (taken from Sigil). Same as used
        # for reference images.
        foreground = ["rgb(45,79,255)",
                      "rgb(254,180,44)",
                      "rgb(226,121,234)",
                      "rgb(30,179,253)",
                      "rgb(232,77,65)",
                      "rgb(49,203,115)",
                      "rgb(141,69,170)"]

        # Set-up a background colour (taken from Sigil). Same as used for
        # reference images.
        background = "rgb(224,224,224)"

        # Set-up parameters equivalent as used for samples.
        width = 200
        height = 200
        padding = (20, 20, 20, 20)

        # Load the reference images, making sure they're in RGB mode.
        test1_ref = PIL.Image.open("tests/samples/test1.png").convert(mode="RGB")
        test2_ref = PIL.Image.open("tests/samples/test2.png").convert(mode="RGB")
        test3_ref = PIL.Image.open("tests/samples/test3.png").convert(mode="RGB")

        # Set-up the Generator.
        generator = Generator(5, 5, foreground=foreground, background=background)

        # Generate first test identicon.
        raw_image = generator.generate("test1", width, height, padding=padding)
        image_stream = BytesIO(raw_image)
        test1 = PIL.Image.open(image_stream)

        # Generate second test identicon.
        raw_image = generator.generate("test2", width, height, padding=padding)
        image_stream = BytesIO(raw_image)
        test2 = PIL.Image.open(image_stream)

        # Generate third test identicon.
        raw_image = generator.generate("test3", width, height, padding=padding)
        image_stream = BytesIO(raw_image)
        test3 = PIL.Image.open(image_stream)

        # Calculate differences between generated identicons and references.
        diff1 = PIL.ImageChops.difference(test1, test1_ref)
        diff2 = PIL.ImageChops.difference(test2, test2_ref)
        diff3 = PIL.ImageChops.difference(test3, test3_ref)

        # Verify that all the diffs are essentially black (i.e. no differences
        # between generated identicons and reference samples).
        expected_extrema = ((0, 0), (0, 0), (0, 0))

        self.assertEqual(diff1.getextrema(), expected_extrema)
        self.assertEqual(diff2.getextrema(), expected_extrema)
        self.assertEqual(diff3.getextrema(), expected_extrema)
 def __init__(self):
     Resource.__init__(self)
     self.generator = Generator(
         SIZE,
         SIZE,
         foreground=FOREGROUND,
         background=BACKGROUND,
     )
Пример #8
0
    def test_get_bit(self):
        """
        Tests if the check whether bit is 1 or 0 is performed correctly.
        """

        generator = Generator(5, 5)
        hash_bytes = [0b10010001, 0b10001000, 0b00111001]

        # Check a couple of bits from the above hash bytes.
        self.assertEqual(True, generator._get_bit(0, hash_bytes))
        self.assertEqual(True, generator._get_bit(7, hash_bytes))
        self.assertEqual(False, generator._get_bit(22, hash_bytes))
        self.assertEqual(True, generator._get_bit(23, hash_bytes))
Пример #9
0
    def test_init_parameters(self):
        """
        Verifies that the constructor sets-up the instance properties correctly.
        """

        generator = Generator(5, 5, digest=hashlib.sha1, foreground=["#111111", "#222222"], background="#aabbcc")

        # sha1 provides 160 bits of entropy - 20 bytes.
        self.assertEqual(generator.digest_entropy, 20 * 8)
        self.assertEqual(generator.digest, hashlib.sha1)
        self.assertEqual(generator.rows, 5)
        self.assertEqual(generator.columns, 5)
        self.assertEqual(generator.foreground, ["#111111", "#222222"])
        self.assertEqual(generator.background, "#aabbcc")
Пример #10
0
    def test_generate_format_invalid(self):
        """
        Tests if an exception is raised in case an unsupported format is
        requested when generating the identicon.
        """

        # Set-up a generator.
        generator = Generator(5, 5)

        # Set-up some test data.
        data = "some test data"

        # Verify that an exception is raised in case of unsupported format.
        self.assertRaises(ValueError, generator.generate, data, 200, 200, output_format="invalid")
Пример #11
0
    def test_data_to_digest_byte_list_hex_lookalike(self):
        """
        Test if correct digest byte list is returned for passed raw data that
        has same length as hex digest string.
        """

        # Set-up some test hex digest (md5), and expected result.
        data = "qqwweerrttyyuuiiooppaassddffgghh"
        expected_digest_byte_list = [25, 182, 52, 218, 118, 220, 26, 145, 164, 222, 33, 221, 183, 140, 98, 246]

        # Instantiate a generator.
        generator = Generator(5, 5, digest=hashlib.md5)

        # Call the method and get the results.
        digest_byte_list = generator._data_to_digest_byte_list(data)

        # Verify the expected and actual result are identical.
        self.assertEqual(expected_digest_byte_list, digest_byte_list)
Пример #12
0
    def test_data_to_digest_byte_list_hex(self):
        """
        Test if correct digest byte list is returned for passed hex digest
        string.
        """

        # Set-up some test hex digest (md5), and expected result.
        hex_digest = "e19c1283c925b3206685ff522acfe3e6"
        expected_digest_byte_list = [225, 156, 18, 131, 201, 37, 179, 32, 102, 133, 255, 82, 42, 207, 227, 230]

        # Instantiate a generator.
        generator = Generator(5, 5, digest=hashlib.md5)

        # Call the method and get the results.
        digest_byte_list = generator._data_to_digest_byte_list(hex_digest)

        # Verify the expected and actual result are identical.
        self.assertEqual(expected_digest_byte_list, digest_byte_list)
Пример #13
0
    def test_data_to_digest_byte_list_raw(self):
        """
        Test if correct digest byte list is returned for raw (non-hex-digest)
        data passed to the method.
        """

        # Set-up some raw data, and set-up the expected result.
        data = "this is a test\n"
        expected_digest_byte_list = [225, 156, 18, 131, 201, 37, 179, 32, 102, 133, 255, 82, 42, 207, 227, 230]

        # Instantiate a generator.
        generator = Generator(5, 5, digest=hashlib.md5)

        # Call the method and get the results.
        digest_byte_list = generator._data_to_digest_byte_list(data)

        # Verify the expected and actual result are identical.
        self.assertEqual(expected_digest_byte_list, digest_byte_list)
Пример #14
0
    def test_generate_png_basics(self):
        """
        Tests some basics about generated PNG identicon image. This includes:

        - Dimensions of generated image.
        - Format of generated image.
        - Mode of generated image.
        """

        # Set-up parameters that will be used for generating the image.
        width = 200
        height = 200
        padding = [20, 20, 20, 20]
        foreground = "#ffffff"
        background = "#000000"
        matrix = [
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 1, 1, 1, 0],
            [0, 1, 1, 1, 0],
            ]

        # Set-up a generator.
        generator = Generator(5, 5)

        # Generate the raw image.
        raw_image = generator._generate_png(matrix, width, height, padding, foreground, background)

        # Try to load the raw image.
        image_stream = BytesIO(raw_image)
        image = PIL.Image.open(image_stream)

        # Verify image size, format, and mode.
        self.assertEqual(image.size[0], 240)
        self.assertEqual(image.size[1], 240)
        self.assertEqual(image.format, "PNG")
        self.assertEqual(image.mode, "RGB")
Пример #15
0
    def test_generate_foreground(self, generate_png_mock):
        """
        Tests if the foreground colour is picked correctly.
        """

        # Set-up some foreground colours and a single background colour.
        foreground = ["#000000", "#111111", "#222222", "#333333", "#444444", "#555555"]
        background = "#ffffff"

        # Set-up the generator.
        generator = Generator(5, 5, foreground=foreground, background=background)

        # The first byte of hex digest should be 121 for this data, which should
        # result in foreground colour of index '1'.
        data = "some test data"
        generator.generate(data, 200, 200)
        generate_png_mock.assert_called_with(mock.ANY, mock.ANY, mock.ANY, mock.ANY, foreground[1], background)

        # The first byte of hex digest should be 149 for this data, which should
        # result in foreground colour of index '5'.
        data = "some other test data"
        generator.generate(data, 200, 200)
        generate_png_mock.assert_called_with(mock.ANY, mock.ANY, mock.ANY, mock.ANY, foreground[5], background)
Пример #16
0
    def test_generate_inverted_png(self, generate_png_mock):
        """
        Tests if the foreground and background are properly inverted when
        generating PNG images.
        """

        # Set-up some test data.
        data = "Some test data"

        # Set-up one foreground and background colour.
        foreground = "#ffffff"
        background = "#000000"

        # Set-up the generator.
        generator = Generator(5, 5, foreground=[foreground], background=background)

        # Verify that colours are picked correctly when no inverstion is requsted.
        generator.generate(data, 200, 200, inverted=False, output_format="png")
        generate_png_mock.assert_called_with(mock.ANY, mock.ANY, mock.ANY, mock.ANY, foreground, background)

        # Verify that colours are picked correctly when inversion is requsted.
        generator.generate(data, 200, 200, inverted=True, output_format="png")
        generate_png_mock.assert_called_with(mock.ANY, mock.ANY, mock.ANY, mock.ANY, background, foreground)
Пример #17
0
def get_avatar(md5):
    image = None

    # fetch image from redis or ldap
    if redis_store.exists(md5):
        user_dn = redis_store.get(md5)
        dn_sha1hex = hashlib.sha1(user_dn).hexdigest()

        try:
            if redis_store.exists(dn_sha1hex):
                image = _get_image_from_redis(dn_sha1hex)
            else:
                image = _get_image_from_ldap(user_dn.decode(), dn_sha1hex)

                # cache image on redis
                if current_app.config.get("AVATAR_CACHE", True):
                    img_ttl = current_app.config["AVATAR_TTL"]
                    redis_store.hset(dn_sha1hex, "raw", image)
                    redis_store.expire(dn_sha1hex, img_ttl)

                image = Image.open(BytesIO(image))
        except OSError:
            current_app.logger.warning(
                "Cannot read image of {0}".format(user_dn))
    else:
        current_app.logger.warning("MD5 {0} not in redis.".format(md5))

    # default image
    if image is None:
        default_args = ["d", "default"]
        default_image = current_app.config["AVATAR_DEFAULT_IMAGE"]
        keyword = _get_argval_from_request(default_args, default_image)
        static_images = current_app.config["AVATAR_STATIC_IMAGES"]
        static_path = current_app.config["AVATAR_STATIC"]
        identicon_enable = current_app.config["AVATAR_IDENTICON_ENABLE"]
        identicon_cache = current_app.config["AVATAR_IDENTICON_CACHE"]

        if identicon_enable == "true" and keyword == "identicon":
            redis_key = md5 + "-identicon"

            # fetch image from redis
            if identicon_cache == "true" and redis_store.exists(redis_key):
                image = _get_image_from_redis(redis_key)
            else:
                generator = Generator(
                    int(current_app.config["AVATAR_IDENTICON_SIZE"]),
                    int(current_app.config["AVATAR_IDENTICON_SIZE"]),
                    foreground=current_app.
                    config["AVATAR_IDENTICON_FOREGROUND"],
                    background=current_app.
                    config["AVATAR_IDENTICON_BACKGROUND"],
                )
                image = generator.generate(
                    md5,
                    int(current_app.config["AVATAR_MAX_SIZE"]),
                    int(current_app.config["AVATAR_MAX_SIZE"]),
                    padding=(0, -4, 0, -4),
                )

                # cache image on redis
                if identicon_cache == "true":
                    img_ttl = current_app.config["AVATAR_TTL"]
                    redis_store.hset(redis_key, "raw", image)
                    redis_store.expire(redis_key, img_ttl)

                image = Image.open(BytesIO(image))

        elif keyword not in static_images or keyword == "404":
            abort(404)
        else:
            image = Image.open(
                os.path.join(static_path, static_images[keyword]))

    # sizes
    default_size = int(current_app.config["AVATAR_DEFAULT_SIZE"])
    size = _get_argval_from_request(["s", "size"], default_size)
    width = _get_argval_from_request(["w", "width"], default_size)
    height = _get_argval_from_request(["h", "height"], default_size)

    # resize methods
    default_method = current_app.config["AVATAR_DEFAULT_METHOD"]
    resize_method = _get_argval_from_request(["m", "method"], default_method)
    if resize_method not in RESIZE_METHODS:
        resize_method = default_method

    if width == default_size and size != default_size:
        width = size
    if height == default_size and size != default_size:
        height = size

    if resize_method in ["crop", "cover", "contain", "thumbnail"]:
        size = (_max_size(width), _max_size(height))
    elif resize_method == "width":
        size = _max_size(width)
    elif resize_method == "height":
        size = _max_size(height)

    buffer_image = BytesIO()

    try:
        resized_image = resizeimage.resize(resize_method, image, size)
    except resizeimage.ImageSizeError:
        if resize_method in ["width", "height"]:
            resized_image = image
        else:
            size = image.height if image.height > image.width else image.width
            size = (size, size)
            resized_image = resizeimage.resize(resize_method, image, size)

    resized_image.save(buffer_image, image.format, quality=95)
    buffer_image.seek(0)

    mimetypes.init()
    mimetype = mimetypes.types_map["." + image.format.lower()]
    return send_file(buffer_image, mimetype=mimetype)
Пример #18
0
def image(request, data):
    """
    Generates identicon image based on passed data.

    Arguments:

      data - Data which should be used for generating an identicon. This data
      will be used in order to create a digest which is used for generating the
      identicon. If the data passed is a hex digest already, the digest will be
      used as-is.

    Returns:

      Identicon image in raw format.
    """

    # Get image width, height, padding, and format from GET parameters, or
    # fall-back to default values from settings.
    try:
        width = int(request.GET.get("w", PYDENTICON_WIDTH))
    except ValueError:
        raise SuspiciousOperation(
            "Identicon width must be a positive integer.")
    try:
        height = int(request.GET.get("h", PYDENTICON_HEIGHT))
    except ValueError:
        raise SuspiciousOperation(
            "Identicon height must be a positive integer.")
    output_format = request.GET.get("f", PYDENTICON_FORMAT)
    try:
        padding = [int(p) for p in request.GET["p"].split(",")]
    except KeyError:
        padding = PYDENTICON_PADDING
    except ValueError:
        raise SuspiciousOperation(
            "Identicon padding must consist out of 4 positive integers separated with commas."
        )
    if "i" in request.GET:
        inverted = request.GET.get("i")
        if inverted.lower() == "true":
            inverted = True
        elif inverted.lower() == "false":
            inverted = False
        else:
            raise SuspiciousOperation(
                "Inversion parameter must be a boolean (true/false).")
    else:
        inverted = PYDENTICON_INVERT

    # Validate the input parameters.
    if not isinstance(width, int) or width <= 0:
        raise SuspiciousOperation(
            "Identicon width must be a positive integer.")
    if not isinstance(height, int) or height <= 0:
        raise SuspiciousOperation(
            "Identicon height must be a positive integer.")
    if not all([isinstance(p, int) and p >= 0
                for p in padding]) or len(padding) != 4:
        raise SuspiciousOperation(
            "Padding must be a 4-element tuple consisting out of positive integers."
        )

    # Set-up correct content type based on requested identicon format.
    if output_format == "png":
        content_type = "image/png"
    elif output_format == "ascii":
        content_type = "text/plain"
    else:
        raise SuspiciousOperation(
            "Unsupported identicon format requested - '%s' % output_format")

    # Initialise a generator.
    generator = Generator(PYDENTICON_ROWS,
                          PYDENTICON_COLUMNS,
                          foreground=PYDENTICON_FOREGROUND,
                          background=PYDENTICON_BACKGROUND,
                          digest=PYDENTICON_DIGEST)

    # Generate the identicion.
    content = generator.generate(data,
                                 width,
                                 height,
                                 padding=padding,
                                 output_format=output_format,
                                 inverted=inverted)

    # Create and return the response.
    response = HttpResponse(content, content_type=content_type)

    return response
Пример #19
0
except Exception as e:
    pass

from flask import Flask
import config

app = Flask('phobook')
app.config.from_object('config')

# Handling OPTION Method request for cross site
from flask_cors import CORS, cross_origin
cors = CORS(app, resources={r"/*":{"origins":"*"}})

# Identicon generator
from pydenticon import Generator
pydent = Generator(8, 8)

from app.db import init_db, db_session
init_db()

from app.login import *


@app.teardown_appcontext
def shutdown_session(exception):
    db_session.remove()

from app.controller import routes
routes(app)

from flask_socketio import SocketIO
Пример #20
0
def get_avatar(md5):
    image = None

    # fetch image from redis or ldap
    if redis_store.exists(md5):
        user_dn = redis_store.get(md5)
        dn_sha1hex = hashlib.sha1(user_dn).hexdigest()

        try:
            if redis_store.exists(dn_sha1hex):
                image = _get_image_from_redis(dn_sha1hex)
            else:
                image = _get_image_from_ldap(user_dn.decode(), dn_sha1hex)

                # cache image on redis
                if current_app.config.get('AVATAR_CACHE', True):
                    img_ttl = current_app.config['AVATAR_TTL']
                    redis_store.hset(dn_sha1hex, 'raw', image)
                    redis_store.expire(dn_sha1hex, img_ttl)

                image = Image.open(BytesIO(image))
        except OSError:
            current_app.logger.warning(
                'Cannot read image of {0}'.format(user_dn))
    else:
        current_app.logger.warning('MD5 {0} not in redis.'.format(md5))

    # default image
    if image is None:
        default_args = ['d', 'default']
        default_image = current_app.config['AVATAR_DEFAULT_IMAGE']
        keyword = _get_argval_from_request(default_args, default_image)
        static_images = current_app.config['AVATAR_STATIC_IMAGES']
        static_path = current_app.config['AVATAR_STATIC']
        identicon_enable = current_app.config['AVATAR_IDENTICON_ENABLE']
        identicon_cache = current_app.config['AVATAR_IDENTICON_CACHE']

        if identicon_enable == 'true' and keyword == 'identicon':
            redis_key = md5 + "-identicon"

            # fetch image from redis
            if identicon_cache == 'true' and redis_store.exists(redis_key):
                image = _get_image_from_redis(redis_key)
            else:
                generator = Generator(
                    int(current_app.config['AVATAR_IDENTICON_SIZE']),
                    int(current_app.config['AVATAR_IDENTICON_SIZE']),
                    foreground=current_app.
                    config['AVATAR_IDENTICON_FOREGROUND'],
                    background=current_app.
                    config['AVATAR_IDENTICON_BACKGROUND'])
                image = generator.generate(
                    md5,
                    int(current_app.config['AVATAR_MAX_SIZE']),
                    int(current_app.config['AVATAR_MAX_SIZE']),
                    padding=(0, -4, 0, -4))

                # cache image on redis
                if identicon_cache == 'true':
                    img_ttl = current_app.config['AVATAR_TTL']
                    redis_store.hset(redis_key, 'raw', image)
                    redis_store.expire(redis_key, img_ttl)

                image = Image.open(BytesIO(image))

        elif keyword not in static_images or keyword == '404':
            abort(404)
        else:
            image = Image.open(
                os.path.join(static_path, static_images[keyword]))

    # sizes
    default_size = int(current_app.config['AVATAR_DEFAULT_SIZE'])
    size = _get_argval_from_request(['s', 'size'], default_size)
    width = _get_argval_from_request(['w', 'width'], default_size)
    height = _get_argval_from_request(['h', 'height'], default_size)

    # resize methods
    default_method = current_app.config['AVATAR_DEFAULT_METHOD']
    resize_method = _get_argval_from_request(['m', 'method'], default_method)
    if resize_method not in RESIZE_METHODS:
        resize_method = default_method

    if width == default_size and size != default_size:
        width = size
    if height == default_size and size != default_size:
        height = size

    if resize_method in ['crop', 'cover', 'contain', 'thumbnail']:
        size = (_max_size(width), _max_size(height))
    elif resize_method == 'width':
        size = _max_size(width)
    elif resize_method == 'height':
        size = _max_size(height)

    buffer_image = BytesIO()

    try:
        resized_image = resizeimage.resize(resize_method, image, size)
    except resizeimage.ImageSizeError:
        if resize_method in ['width', 'height']:
            resized_image = image
        else:
            size = image.height if image.height > image.width else image.width
            size = (size, size)
            resized_image = resizeimage.resize(resize_method, image, size)

    resized_image.save(buffer_image, image.format, quality=95)
    buffer_image.seek(0)

    mimetypes.init()
    mimetype = mimetypes.types_map['.' + image.format.lower()]
    return send_file(buffer_image, mimetype=mimetype)