Automatizando a escolha entre JPEG e PNG com um script

4

Escolher o formato certo para salvar suas imagens é crucial para preservar a qualidade da imagem e reduzir os artefatos. Diferentes formatos seguem diferentes métodos de compactação e vêm com seu próprio conjunto de vantagens e desvantagens.

O JPG, por exemplo, é adequado para fotografias reais que são ricas em gradientes de cor. O PNG sem perdas, por outro lado, é muito superior quando se trata de figuras esquemáticas:

Escolheroformatocertopodeserumatarefadifícilquandosetrabalhacomumgrandenúmerodearquivos.Éporissoqueeuadorariaencontrarumamaneiradeautomatizá-lo.

Umpoucodefundonomeucasodeusoespecífico:

Estoutrabalhandoemváriosfolhetosparaumasériedepalestrasnaminhauniversidade.Osfolhetossãoricosemfiguras,queeutenhoqueextrairdeslidesemformatoPDF.AextraçãodessasimagensmedáPNGssemperdas,quesãodesnecessariamentegrandesàsvezes.

AconversãodessesarquivosespecíficosparaJPEGpodereduzirseutamanhoparamenosde20%dotamanhooriginaldoarquivo,mantendoamesmaqualidade.Issoéimportante,poistrabalharcomcentenasdeimagensgrandesemprocessadoresdetextoébastantepropensoafalhas.

A conversão em lote de todos os PNGs extraídos para JPEGs não é uma opção Estou disposto a seguir, já que muitas, se não a maioria das imagens, são mais adequadas para serem formatadas como PNGs. Convertê-los resultaria em reduções de tamanho insignificantes e, às vezes, até mesmo em tamanho de arquivo - isso é pelo menos o que meus testes mostram.

O que podemos tirar disso é que o tamanho do arquivo após a compactação pode servir como um indicador sobre qual formato é mais adequado para uma imagem específica. Não é um preditor particularmente preciso, mas funciona bem o suficiente. Então, por que não usá-lo na forma de um script:

Euincluí inotifywait porque eu preferiria que o script fosse executado automaticamente assim que eu arrastasse uma imagem extraída em uma pasta.

Esta é uma versão mais simples do script que tenho usado nas últimas semanas:

#!/bin/bash
inotifywait -m --format "%w%f" --exclude '.jpg' -r -e create -e moved_to --fromfile '/home/MHC/.scripts/Workflow/Conversion/include_inotifywait' | while read file; do mogrify -format jpg -quality 92 "$file"
done

A versão avançada do script teria que

  • conseguir lidar com espaços em nomes de arquivos e diretórios
  • preserve os nomes dos arquivos originais
  • achatar imagens PNG se um valor alfa for definido
  • compare o tamanho do arquivo entre a imagem convertida temporária e sua original
  • determina se a diferença é maior que uma dada porcentagem
  • aja de acordo

A conversão real pode ser feita com ferramentas imagemagick:

convert -quality 92 -flatten -background white file.png file.jpg

Infelizmente, minhas habilidades bash não estão nem perto de serem avançadas o suficiente para converter o esquema acima em um roteiro real, mas tenho certeza que muitos de vocês podem.

Meus pontos de reputação aqui são bem baixos, mas eu irei de bom grado conceder a resposta mais útil com a recompensa mais alta que eu puder definir.

Referências: link , link

Editar : veja também meus comentários abaixo para mais algumas informações sobre por que acho que esse script seria a melhor solução para o problema que estou enfrentando.

    
por Glutanimate 05.11.2012 / 03:31

2 respostas

1

Editar: Corrigimos alguns problemas com o script original. Adicionado um alternativo baseado na proposta de Marcks Thomas.

Editar 2 : valores de corte atualizados com base em vários testes de testes . Ainda não sei como estimar tamanhos de arquivo para imagens em escala de cinza. Se você estiver trabalhando com um grande número de imagens fora dos esquemas de cores RGB, talvez queira implementar o primeiro script como um modo de fallback para o segundo.

Editar 3 : adicionada optipng integração. Isso otimiza os tamanhos de arquivos PNG sem perda de qualidade. Veja aqui para mais informações. Algumas melhorias menores.

Versão 0.1

Nota importante : Este script está obsoleto. Versões mais recentes são muito mais eficientes.

Tudo bem, minha pergunta pode ter sido um tanto localizada demais, então coloquei um tempo nela e compilei o script:

#!/bin/bash

# AUTHOR:   (c) MHC (http://askubuntu.com/users/81372/mhc)
# NAME:     Intelliconvert 0.1
# DESCRIPTION:  A script to automate and optimize the choice between different image formats.
# LICENSE:  GNU GPL v3 (http://www.gnu.org/licenses/gpl.html)
# REQUIREMENTS:  Imagemagick

ORIGINAL="$1"

###Filetype check###

MIME=$(file -ib "$ORIGINAL")

if [ "$MIME" = "image/png; charset=binary" ]
  then
    echo "PNG Mode"

###Variables###

      ##Original Image##
    FILENAME=$(basename "$ORIGINAL")
    PARENTDIR=$(dirname "$ORIGINAL")
        SUBFOLDER=$(echo "$PARENTDIR" | cut -d"/" -f10-)
    ORIGARCHIVE="~/ORIG"

      ##Converted Image##
    TEMPDIR="/tmp/imgcomp"
    CONVERTED="$TEMPDIR/$FILENAME.jpg"

      ##Image comparison##
    DIFFLO="50"
    DIFFHI="75"
    CUTOFF="1000000"

      ##DEBUG
    echo "#### SETTINGS ####"
    echo "Filepath to original = $ORIGINAL"
    echo "Filename= $FILENAME"
    echo "Parent directory = $PARENTDIR"
    echo "Archive directory = $ORIGARCHIVE"
    echo "Temporary directory = $TEMPDIR"
    echo "Filepath to converted image = $CONVERTED"
    echo "Low cut-off = $DIFFLO"
    echo "High cut-off = $DIFFHI"

###Conversion###

    convert -quality 92 -flatten -background white "$ORIGINAL" "$CONVERTED"

###Comparison###

    F1=$(stat -c%s "$ORIGINAL" )
    F2=$(stat -c%s "$CONVERTED" )
    FQ=$(echo "($F2*100/$F1)" | bc)

      #Depending on filesize we use a different Cut-off#
    if [ "$F1" -ge "$CUTOFF" ]
      then
        DIFF="$DIFFHI"
      else  
        DIFF="$DIFFLO"
    fi

      ##DEBUG
    echo "### COMPARISON ###"
    echo "Filesize original = $F1 Bytes"
    echo "Filesize converted = $F2 Bytes"
    echo "Chosen cut-off = $DIFF %"
    echo "Actual Ratio = $FQ %"


    if [ "$FQ" -le "$DIFF" ]
      then
           echo "JPEG is more efficient, converting..."
           mv -v "$CONVERTED" "$PARENTDIR"
               mkdir -p "$ORIGARCHIVE/$SUBFOLDER"
           mv -v "$ORIGINAL" "$ORIGARCHIVE/$SUBFOLDER"
      else
           echo "PNG is fine, exiting."
           rm -v "$CONVERTED"
    fi


  else
    echo "File does not exist or unknown MIME type, exiting."

fi

O script funciona bem em combinação com o Watcher .

Este é o meu primeiro script adequado, então pode haver alguns bugs não resolvidos e problemas que eu não vi. Sinta-se à vontade para usá-lo e aprimorá-lo. Se você fizer isso, eu agradeceria se você pudesse deixar um comentário aqui, para que eu possa aprender com isso.

Versão 0.2.1

Uma forma mais eficiente de encontrar o formato correto pode ser obtida comparando o tamanho do arquivo do original com o seu tamanho estimado como uma imagem não comprimida :

#!/bin/bash

# AUTHOR:   (c) MHC (http://askubuntu.com/users/81372/mhc)
# NAME:     Intelliconvert 0.2.1
# DESCRIPTION:  A script to automate and optimize the choice between different image formats.
# LICENSE:  GNU GPL v3 (http://www.gnu.org/licenses/gpl.html)
# REQUIREMENTS:  Imagemagick, Optipng

################ Filetype Check#################

MIME=$(file -ib "$1")

if [ "$MIME" = "image/png; charset=binary" ]
  then
    echo "###PNG Mode###"

####################Settings####################

##Folders##
ORIGARCHIVE="~/ORIG"

##Comparison##
DIFFLO="25"
DIFFHI="20"
CUTOFF="1000000"

################################################

###Variables###

ORIGINAL="$1"
FILENAME=$(basename "$ORIGINAL")
PARENTDIR=$(dirname "$ORIGINAL")
SUBFOLDER=$(echo "$PARENTDIR" | cut -d"/" -f10-)
CONVERTED="$PARENTDIR/$FILENAME.jpg"

#DEBUG#
    echo "###SETTINGS###"
    echo "Filepath to original = $ORIGINAL"
    echo "Filename= $FILENAME"
    echo "Parent directory = $PARENTDIR"
    echo "Archive directory = $ORIGARCHIVE"
    echo "Filepath to converted image = $CONVERTED"
    echo "Low cut-off = $DIFFLO"
    echo "High cut-off = $DIFFHI"


###Image data###

        WIDTH=$(identify -format "%w" "$ORIGINAL")
        HEIGHT=$(identify -format "%h" "$ORIGINAL")
        ZBIT=$(identify -format "%z" "$ORIGINAL")
        COL=$(identify -format "%[colorspace]" "$ORIGINAL")
        F1=$(stat -c%s "$ORIGINAL")

        if [ "$COL" = "RGB" ]
          then
              CHANN="3"
          else
              CHANN="1"
        fi


###Cutoff setting###

    if [ "$F1" -ge "$CUTOFF" ]
      then
        DIFF="$DIFFHI"
      else  
        DIFF="$DIFFLO"
    fi


###Calculations on uncompressed image###

        BMPSIZE=$(echo "($WIDTH*$HEIGHT*$ZBIT*$CHANN/8)" | bc)
        FR=$(echo "($F1*100/$BMPSIZE)" | bc)

#DEBUG#

        echo "###IMAGE DATA###"
        echo "Image Dimensions = $WIDTH x $HEIGHT"
        echo "Colour Depth = $ZBIT"
        echo "Colour Profile = $COL"
        echo "Channels = $CHANN"
        echo "Estimated uncompressed size = $BMPSIZE"
        echo "Actual file size = $F1"
        echo "Estimated size ratio = $FR %"
        echo "Cutoff at $DIFF %"

###Backup###

        echo "###BACKUP###"
        mkdir -p "$ORIGARCHIVE/$SUBFOLDER"  #keep the original folder structure
        cp -v "$ORIGINAL" "$ORIGARCHIVE/$SUBFOLDER"
        echo ""

###Comparison###

    if [ "$FR" -ge "$DIFF" ]
      then
          echo "JPEG is more efficient, converting..."
          convert -quality 92 -flatten -background white "$ORIGINAL" "$CONVERTED"
              echo "Done."
          echo "Cleaning up..."
          rm -v "$ORIGINAL"
      else
          echo "PNG is fine, passing over to optipng."
              echo "Optimizing..."
              optipng "$ORIGINAL"
              echo "Done."
    fi

################ Filetype Check#################

  else
    echo "File does not exist or unknown MIME type, exiting."

fi
Adere a @Marcks Thomas pela ótima idéia.

    
por 10.11.2012 / 09:21
1

Os PDFs suportam codificações sem perdas e codificação JPEG. (JPEG 2000 também.) Você pode querer uma ferramenta que extraia os dados da imagem diretamente do PDF, deixando-os como estão. Pdfimages, do pacote XPDF , fará isso.

O ImageMagick renderizará a página inteira e a extrairá. Isso descarta a escolha da codificação que já está armazenada no PDF e não é a melhor maneira de realizar essa tarefa.

    
por 05.11.2012 / 03:55