枕头png压缩

时间:2018-09-18 11:09:21

标签: django python-3.x python-imaging-library

我正在制作一个简单的应用程序,能够使用Pillow库,python3和Django压缩jpeg和png格式的图像。制作了一个简单的视图,能够识别格式,保存压缩图像并提供一些压缩统计信息。使用jpeg格式的图片时,效果确实很好,我的compressicons接近原始大小的70-80%,而且效果非常快,但是如果我上传png,效果会更差。压缩需要很长时间,并且只有原始大小的3-5%。试图找到一些方法来升级压缩脚本并坚持下去。

现在,我在我的django压缩视图中获得了这个脚本:

from django.shortcuts import render, redirect, get_object_or_404, reverse
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
from django.http import JsonResponse
from django.contrib import auth
from .forms import InputForm, SignUpForm, LoginForm, FTPForm
import os
import sys
from PIL import Image
from .models import image, imagenew, FTPinput
from django.views import View
import datetime
from django.utils import timezone
import piexif


class BasicUploadView(View):
    def get(self, request):
        return render(self.request, 'main/index.html', {})

    def post(self, request):
        form = InputForm(self.request.POST, self.request.FILES)
        if form.is_valid():              
            photo = form.save(commit=False)
            photo.name = photo.image.name
            photo.delete_time = timezone.now() + datetime.timedelta(hours=1)
            photo.user = request.user
            photo.size = photo.image.size
            photo = form.save()

            name = (photo.name).replace(' ', '_')

            picture = Image.open(photo.image)

            if picture.mode in ('RGB'):
                piexif.remove('/home/andrey/sjimalka' + photo.image.url)
                picture.save('media/new/'+name,"JPEG",optimize=True,quality=75)
                newpic = 'new/'+name
                new = imagenew.objects.create(
                    name = name,
                    image = newpic,
                    delete_time = timezone.now() + datetime.timedelta(hours=1),
                    user = request.user,
                )
                if new.image.size < photo.image.size:
                    diff = round((new.image.size-photo.image.size)/float(photo.image.size)*100, 2)
                else:
                    diff = str(round((new.image.size-photo.image.size)/float(photo.image.size)*100, 2))+' Не удалось сжать файл'
                oldsize = round(photo.image.size/1000000, 2)
                newsize = round(new.image.size/1000000, 2)
                id = new.pk
                imagenew.objects.filter(pk=id).update(size=new.image.size)
            elif picture.mode != ('RGB'):
                picture.save('media/new/'+name,"PNG", optimize=True, quality=75)
                newpic = 'new/'+name
                new = imagenew.objects.create(
                    name = name,
                    image = newpic,
                    delete_time = timezone.now() + datetime.timedelta(hours=1),
                    user = request.user,
                )
                if new.image.size < photo.image.size:
                    diff = round((new.image.size-photo.image.size)/float(photo.image.size)*100, 2)
                else:
                    diff = str(round((new.image.size-photo.image.size)/float(photo.image.size)*100, 2))+' Не удалось сжать файл'

                oldsize = round(photo.image.size/1000000, 2)
                newsize = round(new.image.size/1000000, 2)
                id = new.pk
                imagenew.objects.filter(pk=id).update(size=new.image.size)

            data = {'is_valid': True, 'name': new.image.name, 'url': new.image.url, 'diff': diff,
                'oldsize':oldsize, 'newsize':newsize,}
        else:
            alert = 'Данный формат не поддерживается. Пожалуйста загрузите картинки форматов png или jpg(jpeg)'
            data = {'is_valid': False, 'name': alert,}
        return JsonResponse(data)

问题:是否有任何方法可以使具有png上传功能的脚本工作更快,并且(更重要的是)使png大小压缩更接近jpeg?也许我应该使用另一个python库?

2 个答案:

答案 0 :(得分:2)

  

tinypng如何工作?他们以50-60%的压缩率压缩了相同的png文件

它们可能会将调色板从24位减少到8位。这是有关此问题的详细答案-https://stackoverflow.com/a/12146901/1925257

您可以像这样在枕头中尝试:

picture_8bit = picture.convert(mode='P', palette=Image.ADAPTIVE)
picture_8bit.save(...) # do as usual

这应该与tinypng相似。


您必须了解,缩小调色板的尺寸意味着,如果图像具有多种颜色,则由于8位只能包含256种颜色,您将损失大部分颜色。

答案 1 :(得分:2)

Pillow Image.quatize 的文档显示了一种更便捷的方法来压缩png文件。在个人实验中,以下代码可以使png压缩为原始大小的70%,这也接近 ImageMagick 创建的结果。

std::filesystem::path my_path("foo.txt");
std::filesystem::path my_output_path(my_path.stem()+std::filesystem::path(".my_extension"));
相关问题