And*_*kij 1 django python-imaging-library python-3.x
我正在制作一个简单的应用程序,能够使用 Pillow 库、python3 和 Django 压缩 jpeg 和 png 格式的图像。做了一个简单的视图,能够识别格式,保存压缩图像并给出一些压缩统计数据。对于 jpeg 格式的图像,它工作得非常好,我得到的压缩图标接近原始大小的 70-80%,并且工作得非常快,但如果我上传 png,我的工作效果会更糟。压缩时间较长,且只有原始大小的3-5%。试图找到一些升级压缩脚本的方法,并坚持下去。
\n\n现在我在 Django 压缩视图中得到了这个脚本:
\n\nfrom django.shortcuts import render, redirect, get_object_or_404, reverse\nfrom django.contrib.auth import login, authenticate, logout\nfrom django.contrib.auth.models import User\nfrom django.http import HttpResponse, HttpResponseRedirect\nfrom django.http import JsonResponse\nfrom django.contrib import auth\nfrom .forms import InputForm, SignUpForm, LoginForm, FTPForm\nimport os\nimport sys\nfrom PIL import Image\nfrom .models import image, imagenew, FTPinput\nfrom django.views import View\nimport datetime\nfrom django.utils import timezone\nimport piexif\n\n\nclass BasicUploadView(View):\n def get(self, request):\n return render(self.request, \'main/index.html\', {})\n\n def post(self, request):\n form = InputForm(self.request.POST, self.request.FILES)\n if form.is_valid(): \n photo = form.save(commit=False)\n photo.name = photo.image.name\n photo.delete_time = timezone.now() + datetime.timedelta(hours=1)\n photo.user = request.user\n photo.size = photo.image.size\n photo = form.save()\n\n name = (photo.name).replace(\' \', \'_\')\n\n picture = Image.open(photo.image)\n\n if picture.mode in (\'RGB\'):\n piexif.remove(\'/home/andrey/sjimalka\' + photo.image.url)\n picture.save(\'media/new/\'+name,"JPEG",optimize=True,quality=75)\n newpic = \'new/\'+name\n new = imagenew.objects.create(\n name = name,\n image = newpic,\n delete_time = timezone.now() + datetime.timedelta(hours=1),\n user = request.user,\n )\n if new.image.size < photo.image.size:\n diff = round((new.image.size-photo.image.size)/float(photo.image.size)*100, 2)\n else:\n diff = str(round((new.image.size-photo.image.size)/float(photo.image.size)*100, 2))+\' \xd0\x9d\xd0\xb5 \xd1\x83\xd0\xb4\xd0\xb0\xd0\xbb\xd0\xbe\xd1\x81\xd1\x8c \xd1\x81\xd0\xb6\xd0\xb0\xd1\x82\xd1\x8c \xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb\'\n oldsize = round(photo.image.size/1000000, 2)\n newsize = round(new.image.size/1000000, 2)\n id = new.pk\n imagenew.objects.filter(pk=id).update(size=new.image.size)\n elif picture.mode != (\'RGB\'):\n picture.save(\'media/new/\'+name,"PNG", optimize=True, quality=75)\n newpic = \'new/\'+name\n new = imagenew.objects.create(\n name = name,\n image = newpic,\n delete_time = timezone.now() + datetime.timedelta(hours=1),\n user = request.user,\n )\n if new.image.size < photo.image.size:\n diff = round((new.image.size-photo.image.size)/float(photo.image.size)*100, 2)\n else:\n diff = str(round((new.image.size-photo.image.size)/float(photo.image.size)*100, 2))+\' \xd0\x9d\xd0\xb5 \xd1\x83\xd0\xb4\xd0\xb0\xd0\xbb\xd0\xbe\xd1\x81\xd1\x8c \xd1\x81\xd0\xb6\xd0\xb0\xd1\x82\xd1\x8c \xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb\'\n\n oldsize = round(photo.image.size/1000000, 2)\n newsize = round(new.image.size/1000000, 2)\n id = new.pk\n imagenew.objects.filter(pk=id).update(size=new.image.size)\n\n data = {\'is_valid\': True, \'name\': new.image.name, \'url\': new.image.url, \'diff\': diff,\n \'oldsize\':oldsize, \'newsize\':newsize,}\n else:\n alert = \'\xd0\x94\xd0\xb0\xd0\xbd\xd0\xbd\xd1\x8b\xd0\xb9 \xd1\x84\xd0\xbe\xd1\x80\xd0\xbc\xd0\xb0\xd1\x82 \xd0\xbd\xd0\xb5 \xd0\xbf\xd0\xbe\xd0\xb4\xd0\xb4\xd0\xb5\xd1\x80\xd0\xb6\xd0\xb8\xd0\xb2\xd0\xb0\xd0\xb5\xd1\x82\xd1\x81\xd1\x8f. \xd0\x9f\xd0\xbe\xd0\xb6\xd0\xb0\xd0\xbb\xd1\x83\xd0\xb9\xd1\x81\xd1\x82\xd0\xb0 \xd0\xb7\xd0\xb0\xd0\xb3\xd1\x80\xd1\x83\xd0\xb7\xd0\xb8\xd1\x82\xd0\xb5 \xd0\xba\xd0\xb0\xd1\x80\xd1\x82\xd0\xb8\xd0\xbd\xd0\xba\xd0\xb8 \xd1\x84\xd0\xbe\xd1\x80\xd0\xbc\xd0\xb0\xd1\x82\xd0\xbe\xd0\xb2 png \xd0\xb8\xd0\xbb\xd0\xb8 jpg(jpeg)\'\n data = {\'is_valid\': False, \'name\': alert,}\n return JsonResponse(data)\nRun Code Online (Sandbox Code Playgroud)\n\n问题:有没有什么方法可以使 png 上传的脚本工作得更快,并且(更重要的是)使 png 大小压缩更接近 jpeg?也许我应该使用另一个 python 库?
\n那么tinypng是如何工作的呢?他们将相同的 png 文件压缩 50-60%
他们可能将调色板从 24 位减少到 8 位。这是有关该问题的详细答案 - /sf/answers/850283101/
你可以在 Pillow 中尝试这样做:
picture_8bit = picture.convert(
mode='P', # use mode='PA' for transparency
palette=Image.ADAPTIVE
)
picture_8bit.save(...) # do as usual
Run Code Online (Sandbox Code Playgroud)
这应该类似于tinypng 的工作方式。
如果你不想要透明度,最好先转换RGBA为RGB,然后再转换为P模式:
picture_rgb = picture.convert(mode='RGB') # convert RGBA to RGB
picture_8bit = picture_rgb.convert(mode='P', ...)
Run Code Online (Sandbox Code Playgroud)
convert()如上所示的调用实际上会quantize()在后台调用,并且Median Cut默认情况下将使用算法来减少调色板。
在某些情况下,使用其他算法(例如MAXCOVERAGE. 要使用不同的算法,您可以quantize()直接调用该方法:
picture_rgb = picture.convert(mode='RGB') # convert RGBA to RGB
picture_8bit = picture.quantize(colors=256, method=Image.MAXCOVERAGE)
Run Code Online (Sandbox Code Playgroud)
您必须明白,缩小调色板意味着如果图像有很多颜色,您将失去其中的大部分颜色,因为 8 位只能包含 256 种颜色。
| 归档时间: |
|
| 查看次数: |
6886 次 |
| 最近记录: |