prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Thumbnailing of transparent images seems to break
  ### Describe the bug
  <img width="1119" alt="image" src="https://user-images.githubusercontent.com/7915741/191974542-041bdb37-f2e0-4181-9267-9a24d5df66b3.png">
  
  ### How to reproduce
  <img width="1119" alt="image" src="https://user-images.githubusercontent.com/7915741/191974542-041bdb37-f2e0-4181-9267-9a24d5df66b3.png">
  
  ### Expected behaviour
  Not <img width="1119" alt="image" src="https://user-images.githubusercontent.com/7915741/191974542-041bdb37-f2e0-4181-9267-9a24d5df66b3.png">
  
  ### Screenshots
  <img width="1119" alt="image" src="https://user-images.githubusercontent.com/7915741/191974542-041bdb37-f2e0-4181-9267-9a24d5df66b3.png">
  
  ### Additional context
  
  
  </issue>
  <code>
  [start of website/utils/media/services.py]
  1 import io
  2 import os
  3 
  4 from django.conf import settings
  5 from django.core import signing
  6 from django.core.files.base import ContentFile
  7 from django.core.files.storage import get_storage_class, DefaultStorage
  8 from django.core.files.uploadedfile import InMemoryUploadedFile
  9 from django.db.models.fields.files import FieldFile, ImageFieldFile
  10 from django.urls import reverse
  11 
  12 
  13 def save_image(storage, image, path, format):
  14     buffer = io.BytesIO()
  15     image.convert("RGB").save(fp=buffer, format=format)
  16     buff_val = buffer.getvalue()
  17     content = ContentFile(buff_val)
  18     file = InMemoryUploadedFile(
  19         content,
  20         None,
  21         f"foo.{format.lower()}",
  22         f"image/{format.lower()}",
  23         content.tell,
  24         None,
  25     )
  26     return storage.save(path, file)
  27 
  28 
  29 def get_media_url(file, attachment=False):
  30     """Get the url of the provided media file to serve in a browser.
  31 
  32     If the file is private a signature will be added.
  33     Do NOT use this with user input
  34     :param file: the file field
  35     :param attachment: True if the file is a forced download
  36     :return: the url of the media
  37     """
  38     storage = DefaultStorage()
  39     file_name = file
  40     if isinstance(file, ImageFieldFile) or isinstance(file, FieldFile):
  41         storage = file.storage
  42         file_name = file.name
  43 
  44     return f"{storage.url(file_name, attachment)}"
  45 
  46 
  47 def get_thumbnail_url(file, size, fit=True):
  48     """Get the thumbnail url of a media file, NEVER use this with user input.
  49 
  50     If the thumbnail exists this function will return the url of the
  51     media file, with signature if necessary. Does it not yet exist a route
  52     that executes the :func:`utils.media.views.generate_thumbnail`
  53     will be the output.
  54     :param file: the file field
  55     :param size: size of the image
  56     :param fit: False to keep the aspect ratio, True to crop
  57     :return: get-thumbnail path
  58     """
  59     storage = DefaultStorage()
  60     name = file
  61 
  62     if isinstance(file, ImageFieldFile) or isinstance(file, FieldFile):
  63         storage = file.storage
  64         name = file.name
  65 
  66     is_public = isinstance(storage, get_storage_class(settings.PUBLIC_FILE_STORAGE))
  67     size_fit = "{}_{}".format(size, int(fit))
  68 
  69     if name.endswith(".svg") and is_public:
  70         return storage.url(name)
  71 
  72     sig_info = {
  73         "size": size,
  74         "fit": int(fit),
  75         "name": name,
  76         "thumb_path": f"thumbnails/{size_fit}/{name}",
  77         "serve_path": f"thumbnails/{size_fit}/{name}",
  78         "storage": f"{storage.__class__.__module__}.{storage.__class__.__name__}",
  79     }
  80 
  81     # We provide a URL instead of calling it as a function, so that using
  82     # it means kicking off a new GET request. If we would need to check all files for the
  83     # thumbnails inline, loading an album overview would have high latency.
  84     return (
  85         reverse("get-thumbnail", args=[os.path.join(size_fit, sig_info["name"])])
  86         + f"?sig={signing.dumps(sig_info)}"
  87     )
  88
  [end of website/utils/media/services.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/website/utils/media/services.py b/website/utils/media/services.py
  --- a/website/utils/media/services.py
  +++ b/website/utils/media/services.py
  @@ -12,7 +12,7 @@
   
   def save_image(storage, image, path, format):
       buffer = io.BytesIO()
  -    image.convert("RGB").save(fp=buffer, format=format)
  +    image.convert("RGB" if format == "JPEG" else "RGBA").save(fp=buffer, format=format)
       buff_val = buffer.getvalue()
       content = ContentFile(buff_val)
       file = InMemoryUploadedFile(
  
verification_info: {"golden_diff": "diff --git a/website/utils/media/services.py b/website/utils/media/services.py\n--- a/website/utils/media/services.py\n+++ b/website/utils/media/services.py\n@@ -12,7 +12,7 @@\n \n def save_image(storage, image, path, format):\n     buffer = io.BytesIO()\n-    image.convert(\"RGB\").save(fp=buffer, format=format)\n+    image.convert(\"RGB\" if format == \"JPEG\" else \"RGBA\").save(fp=buffer, format=format)\n     buff_val = buffer.getvalue()\n     content = ContentFile(buff_val)\n     file = InMemoryUploadedFile(\n", "issue": "Thumbnailing of transparent images seems to break\n### Describe the bug\r\n<img width=\"1119\" alt=\"image\" src=\"https://user-images.githubusercontent.com/7915741/191974542-041bdb37-f2e0-4181-9267-9a24d5df66b3.png\">\r\n\r\n### How to reproduce\r\n<img width=\"1119\" alt=\"image\" src=\"https://user-images.githubusercontent.com/7915741/191974542-041bdb37-f2e0-4181-9267-9a24d5df66b3.png\">\r\n\r\n### Expected behaviour\r\nNot <img width=\"1119\" alt=\"image\" src=\"https://user-images.githubusercontent.com/7915741/191974542-041bdb37-f2e0-4181-9267-9a24d5df66b3.png\">\r\n\r\n### Screenshots\r\n<img width=\"1119\" alt=\"image\" src=\"https://user-images.githubusercontent.com/7915741/191974542-041bdb37-f2e0-4181-9267-9a24d5df66b3.png\">\r\n\r\n### Additional context\r\n\n", "before_files": [{"content": "import io\nimport os\n\nfrom django.conf import settings\nfrom django.core import signing\nfrom django.core.files.base import ContentFile\nfrom django.core.files.storage import get_storage_class, DefaultStorage\nfrom django.core.files.uploadedfile import InMemoryUploadedFile\nfrom django.db.models.fields.files import FieldFile, ImageFieldFile\nfrom django.urls import reverse\n\n\ndef save_image(storage, image, path, format):\n    buffer = io.BytesIO()\n    image.convert(\"RGB\").save(fp=buffer, format=format)\n    buff_val = buffer.getvalue()\n    content = ContentFile(buff_val)\n    file = InMemoryUploadedFile(\n        content,\n        None,\n        f\"foo.{format.lower()}\",\n        f\"image/{format.lower()}\",\n        content.tell,\n        None,\n    )\n    return storage.save(path, file)\n\n\ndef get_media_url(file, attachment=False):\n    \"\"\"Get the url of the provided media file to serve in a browser.\n\n    If the file is private a signature will be added.\n    Do NOT use this with user input\n    :param file: the file field\n    :param attachment: True if the file is a forced download\n    :return: the url of the media\n    \"\"\"\n    storage = DefaultStorage()\n    file_name = file\n    if isinstance(file, ImageFieldFile) or isinstance(file, FieldFile):\n        storage = file.storage\n        file_name = file.name\n\n    return f\"{storage.url(file_name, attachment)}\"\n\n\ndef get_thumbnail_url(file, size, fit=True):\n    \"\"\"Get the thumbnail url of a media file, NEVER use this with user input.\n\n    If the thumbnail exists this function will return the url of the\n    media file, with signature if necessary. Does it not yet exist a route\n    that executes the :func:`utils.media.views.generate_thumbnail`\n    will be the output.\n    :param file: the file field\n    :param size: size of the image\n    :param fit: False to keep the aspect ratio, True to crop\n    :return: get-thumbnail path\n    \"\"\"\n    storage = DefaultStorage()\n    name = file\n\n    if isinstance(file, ImageFieldFile) or isinstance(file, FieldFile):\n        storage = file.storage\n        name = file.name\n\n    is_public = isinstance(storage, get_storage_class(settings.PUBLIC_FILE_STORAGE))\n    size_fit = \"{}_{}\".format(size, int(fit))\n\n    if name.endswith(\".svg\") and is_public:\n        return storage.url(name)\n\n    sig_info = {\n        \"size\": size,\n        \"fit\": int(fit),\n        \"name\": name,\n        \"thumb_path\": f\"thumbnails/{size_fit}/{name}\",\n        \"serve_path\": f\"thumbnails/{size_fit}/{name}\",\n        \"storage\": f\"{storage.__class__.__module__}.{storage.__class__.__name__}\",\n    }\n\n    # We provide a URL instead of calling it as a function, so that using\n    # it means kicking off a new GET request. If we would need to check all files for the\n    # thumbnails inline, loading an album overview would have high latency.\n    return (\n        reverse(\"get-thumbnail\", args=[os.path.join(size_fit, sig_info[\"name\"])])\n        + f\"?sig={signing.dumps(sig_info)}\"\n    )\n", "path": "website/utils/media/services.py"}]}