Kép tömörítése nem megy

Segítsetek kérlek. Viszonylag egyszerű feladatot szerettem volna megoldani. Egy könyvtárban lévő jpg képeket akartam konvertálni, úgy hogy max 500KB legyen a fájl mérete. Persze kérdeztem a jóbarátomat a chatgpt-t is, de sajnos nem sikerült megoldani, hogy egy nagyon nagy méretű és felbontású képet tömörítsen/átméretezzen. És íme a szkript:

#!/bin/bash

# Maximális fájlméret bájtban (500 KB)
MAX_SIZE=512000

# Minőségi beállítások
QUALITY_START=85
QUALITY_MIN=40
QUALITY_STEP=5

# Átméretezési korlátok
MAX_WIDTH=1600
MAX_HEIGHT=1600

# Iterálás a .jpg fájlokon az aktuális könyvtárban
for FILE in *.jpg; do
    # Ellenőrizzük, hogy tényleg létezik-e fájl
    if [ ! -f "$FILE" ]; then
        echo "Nincsenek .jpg fájlok az aktuális könyvtárban."
        exit 1
    fi

    # Fájl méretének ellenőrzése
    FILE_SIZE=$(stat -c%s "$FILE")
    if [ "$FILE_SIZE" -le "$MAX_SIZE" ]; then
        echo "✔️ Már megfelelő méretű: $FILE"
        continue
    fi

    echo "⚙️ Feldolgozás: $FILE"

    # Új fájlnév létrehozása _converted utótaggal
    NEW_FILE="${FILE%.*}_converted.jpg"

    # Ideiglenes fájl létrehozása
    TEMP_FILE="${NEW_FILE}_temp.jpg"
    cp "$FILE" "$TEMP_FILE"

    # Kép felbontásának lekérdezése
    IMAGE_WIDTH=$(identify -format "%w" "$TEMP_FILE")
    IMAGE_HEIGHT=$(identify -format "%h" "$TEMP_FILE")

    # Ha a kép szélessége vagy magassága túl nagy, akkor átméretezzük
    if [ "$IMAGE_WIDTH" -gt "$MAX_WIDTH" ] || [ "$IMAGE_HEIGHT" -gt "$MAX_HEIGHT" ]; then
        echo "🔄 Átméretezés szükséges: $FILE"
        convert "$TEMP_FILE" -resize "${MAX_WIDTH}x${MAX_HEIGHT}" "$TEMP_FILE"
    fi

    # Minőség csökkentése + átméretezés
    QUALITY=$QUALITY_START
    while [ "$QUALITY" -ge "$QUALITY_MIN" ]; do
        # Próbálunk minőséget csökkenteni
        convert "$TEMP_FILE" -sampling-factor 4:2:0 -strip -quality "$QUALITY" "$TEMP_FILE"
        
        # Fájl méretének újraellenőrzése
        NEW_SIZE=$(stat -c%s "$TEMP_FILE")
        if [ "$NEW_SIZE" -le "$MAX_SIZE" ]; then
            mv "$TEMP_FILE" "$NEW_FILE"
            echo "✅ Sikeresen tömörítve: $NEW_FILE (Új méret: $((NEW_SIZE / 1024)) KB)"
            break
        fi

        QUALITY=$((QUALITY - QUALITY_STEP))
    done

    # Ha nem sikerült 500 KB alá csökkenteni, törlés
    if [ "$QUALITY" -lt "$QUALITY_MIN" ]; then
        echo "⚠️ Nem sikerült 500 KB alá csökkenteni: $FILE"
        rm "$TEMP_FILE"
    fi
done

A hiba: ⚙ Feldolgozás: 01 Előtte.jpg
🔄 Átméretezés szükséges: 01 Előtte.jpg
⚠ Nem sikerült 500 KB alá csökkenteni: 01 Előtte.jpg
 

A fájl amibe beletörik a bicskája a 01 Előtte.jpg egy 3056x3056 állomány, mérete pedig 3.0MiB

Persze, ha valakinek van tuti műkődő snipeete aminek nem törik bele a bicskája az ekkora állományokba és megosztja itt velem azt is nagyon szépen  megköszönöm.

Köszönöm az ötleteket.

Szerk. A célom, hogy weben jelenítsem meg a képeket és ehhez szeretném konvertálni. Lehet tehát webp is a formátum.

Hozzászólások

Szerkesztve: 2025. 04. 11., p – 19:34

deepSeek első megoldása:
 

#!/bin/bash

# Maximális fájlméret bájtban (500 KB)
MAX_SIZE=512000

# Minőségi beállítások
QUALITY_START=80
QUALITY_MIN=40
QUALITY_STEP=5

# Átméretezési korlátok
MAX_WIDTH=1600
MAX_HEIGHT=1600

# Formátum (jpg vagy webp)
OUTPUT_FORMAT="webp"

# Iterálás a .jpg fájlokon az aktuális könyvtárban
for FILE in *.jpg; do
    # Ellenőrizzük, hogy tényleg létezik-e fájl
    if [ ! -f "$FILE" ]; then
        echo "Nincsenek .jpg fájlok az aktuális könyvtárban."
        exit 1
    fi

    # Fájl méretének ellenőrzése
    FILE_SIZE=$(stat -c%s "$FILE")
    if [ "$FILE_SIZE" -le "$MAX_SIZE" ] && [ "$OUTPUT_FORMAT" == "jpg" ]; then
        echo "✔️ Már megfelelő méretű: $FILE"
        continue
    fi

    echo "⚙️ Feldolgozás: $FILE"

    # Új fájlnév létrehozása
    NEW_FILE="${FILE%.*}_converted.$OUTPUT_FORMAT"

    # Kép felbontásának lekérdezése
    IMAGE_INFO=$(identify -format "%w %h" "$FILE")
    IMAGE_WIDTH=${IMAGE_INFO% *}
    IMAGE_HEIGHT=${IMAGE_INFO#* }

    # Átméretezési paraméterek kiszámítása
    if (( IMAGE_WIDTH > MAX_WIDTH || IMAGE_HEIGHT > MAX_HEIGHT )); then
        echo "🔄 Átméretezés szükséges: $FILE"
        RESIZE_OPT="-resize ${MAX_WIDTH}x${MAX_HEIGHT}>"
    else
        RESIZE_OPT=""
    fi

    # Konverzió próbálkozások különböző minőségekkel
    QUALITY=$QUALITY_START
    while (( QUALITY >= QUALITY_MIN )); do
        if [ "$OUTPUT_FORMAT" == "webp" ]; then
            convert "$FILE" $RESIZE_OPT -sampling-factor 4:2:0 -strip -quality $QUALITY -define webp:method=6 "$NEW_FILE"
        else
            convert "$FILE" $RESIZE_OPT -sampling-factor 4:2:0 -strip -quality $QUALITY "$NEW_FILE"
        fi

        # Fájl méretének ellenőrzése
        NEW_SIZE=$(stat -c%s "$NEW_FILE")
        if (( NEW_SIZE <= MAX_SIZE )); then
            echo "✅ Sikeresen konvertálva: $NEW_FILE (Új méret: $((NEW_SIZE / 1024)) KB, Minőség: $QUALITY)"
            break
        fi

        rm -f "$NEW_FILE"
        QUALITY=$((QUALITY - QUALITY_STEP))
    done

    if (( QUALITY < QUALITY_MIN )); then
        echo "⚠️ Nem sikerült $((MAX_SIZE/1024)) KB alá csökkenteni: $FILE"
        # Még egy utolsó próbálkozás agresszívabb tömörítéssel
        if [ "$OUTPUT_FORMAT" == "webp" ]; then
            convert "$FILE" $RESIZE_OPT -sampling-factor 4:2:0 -strip -quality $QUALITY_MIN -define webp:method=6 -define webp:auto-filter=true "$NEW_FILE"
        else
            convert "$FILE" $RESIZE_OPT -sampling-factor 4:2:0 -strip -quality $QUALITY_MIN "$NEW_FILE"
        fi
        NEW_SIZE=$(stat -c%s "$NEW_FILE")
        echo "⚠️ Legalábbis csökkentve: $NEW_FILE (Végső méret: $((NEW_SIZE / 1024)) KB)"
    fi
done

4 képpel próbáltam 1,9-3,4Mib az eredmény 59-201 Kib

Ez tényleg sokkal jobb. Ugyan nem sikerült 500 alá vinni, de 600-700KiB lett a maximum. Úgy tűnik a deepSeek hasznosabb. Legközelebb megpróbálom ezzel is. 

Köszönöm a segítséged!

“The basic tool for the manipulation of reality is the manipulation of words. If you can control the meaning of words, you can control the people who must use them.”

― Philip K. Dick

AI ide vagy oda, meg kell érteni, amit javasol. Pl. így első ránézésre a vakaródzás a felbontás ellenőrzésével teljesen felesleges, mert a convert tudja, hogy nem kicsinyíti, amit nem kell.

Itt egy részlet, ami a jpeg-recompresst használja. Annyi, hogy ez logót is tesz rá, aki azt nem tudja kiszedni belőle ezt a felesleget, az meg is érdemli :D

fswatch  "${SRCDIR}" | while read File
do
 if [ -f "${File}" ]
 then

  echo "${File} incoming."
  OutFile="${DSTDIR}"$(basename "${File}")
  OutFile="${OutFile%.*}.jpg"

  convert "${File}" -geometry 2000x2000\> ppm:-  | \
  convert - "${LOGO}" -channel A -evaluate multiply 0.1 +channel +distort affine "0,0 0,0 %[w],%[h] %[fx:t?v.w*(u.h/v.h*0.1):s.w],%[fx:t?v.h*(u.h/v.h*0.1):s.h]" -shave 1 -gravity southwest -geometry +20+20 -composite -depth 8 ppm:- |\
  ~/.local/bin/jpeg-recompress --quality low --accurate --ppm -  "${OutFile}"
  exiftool -overwrite_original -tagsfromfile "${File}" -Alldates "${OutFile}"
  rm "${File}"
 fi
done

Ezt is lehet loopba tenni, de azt csinálja meg nektek az AI

Ja, ami a lényeg, hogy ezzel - szerintem - sokkal jobb képminőséget és kisebb vagy összemérhető fájlméretet értem el, mint a webp-vel. Jó pár éve írtam, meg persze akkor is elfogult voltam magam irányába, szóval lehet hogy mégse.

Hát lehet ki is próbálnám, ha nem kellene github repót klónoznom, lefordítanom, függőségeket ellenőriznem és még a pathba is betennem. Akkor inkább a csúnyább és azonnal működő megoldást választom. 

Tudom lusta dög vagyok, de ha a fenti példa működik én nem erőltetem a dolgot...

Egyébként biztos vagyok benne, hogy a te megoldásod sokkal jobb. Ez nem is kérdés.

Szerk. Visszavonom. Megtaláltam a csomagokat is. https://github.com/ImageProcessing-ElectronicPublications/jpeg-recompre…

Elnézést kérek. Ki fogom próbálni.

“The basic tool for the manipulation of reality is the manipulation of words. If you can control the meaning of words, you can control the people who must use them.”

― Philip K. Dick

Igazság szerint a felbontás ellenőrzésénél pattant el az agyam, és ez volt készen :)

Anno valszeg ezzel fordíttottam:

#!/bin/bash
WRKD=/tmp/work/jpgr
PKGS="build-essential autoconf automake pkg-config nasm libtool cmake libpng-dev libwebp-dev"
mkdir -p "${WRKD}"; cd "${WRKD}"

sudo apt-get install -y ${PKGS}

if [ -d mozjpeg ]
then
  cd mozjpeg
  git pull
  cd ..
else
  git clone git@github.com:mozilla/mozjpeg.git
fi

mkdir -p mozjpeg/build ; cd mozjpeg/build

cmake -DCMAKE_INSTALL_PREFIX=/home/fisher/.local/ -G"Unix Makefiles" ../

make

make install

mkdir -p "${WRKD}"; cd "${WRKD}"

if [ -d libiqa ]
then
  cd libiqa
  git pull
  cd ..
else
  git clone git@github.com:ImageProcessing-ElectronicPublications/libiqa.git
fi

cd libiqa


make && make install PREFIX=/home/fisher/.local/

mkdir -p "${WRKD}"; cd "${WRKD}"

if [ -d libsmallfry  ]
then
  cd libsmallfry
  git pull
  cd ..
else
  git clone git@github.com:ImageProcessing-ElectronicPublications/libsmallfry.git
fi

cd libsmallfry

make install PREFIX=/home/fisher/.local/

mkdir -p "${WRKD}"; cd "${WRKD}"

if [ -d jpeg-recompress ]
then
  cd jpeg-recompress
  git pull
  cd ..
else
  git clone git@github.com:ImageProcessing-ElectronicPublications/jpeg-recompress.git
fi

cd jpeg-recompress

CFLAGS="-I/home/fisher/.local/include/ -L/home/fisher/.local/lib/"  PREFIX=~/local/ make install

cd
Szerkesztve: 2025. 04. 12., szo – 09:16

A convert  -resize 950300@ formájú paraméterezése nem játszik?

@ kép területét jelenti pixelben....

Szerkesztve: 2025. 04. 12., szo – 19:49

Kb. tizenöt perc alatt ennyi telik tőlem:

#!/bin/bash

RES=2000
IMGPATH=$@
OUTDIR=/tmp/
MAXQ=90
MINQ=10
MAXSIZE=200000


trap "echo Crap." SIGINT

for Dir in ${IMGPATH}
do
  find "${Dir}" -type f -iname '*.jpg' | while read InputFile
  do
    Quality=${MAXQ}
    echo -n "Processinq ${InputFile}: "
    OutputFile="${OUTDIR}/$(basename "${InputFile}")"
    while $bumbumbum
    do
      [ $(stat -c%s "${InputFile}") -lt ${MAXSIZE} ] && break
      echo -n ${Quality}
      convert "${InputFile}" -geometry ${RES}x${RES}\> -quality ${Quality} "${OutputFile}"
      echo -n ", "
     [ $(stat -c%s "${OutputFile}") -lt ${MAXSIZE} ] && break
     Quality=$(( Quality - 5))
     [ ${Quality} -lt ${MINQ} ] && break
   done
   echo " done."
  done
done

Amit lehetne optimalizálni, hogy csak egyszer kicsinyíti le a képet, persze nem .jpg, hanem valami könnyen feldolgozható, veszteségmentes formátumba. Ezzel akár sok cpu-t is lehet nyerni, ha a bejövő képek (nagyon) nagyok.

 

Update: csak betettem még egy sort, hogy ha a mérete már eleve jó, akkor skippelje.

Köszönöm, mindenképpen ki fogom próbálni. Jól láttam, hogy duplikátumokat is tud keresni?

“The basic tool for the manipulation of reality is the manipulation of words. If you can control the meaning of words, you can control the people who must use them.”

― Philip K. Dick

"Jól láttam, hogy duplikátumokat is tud keresni?"

Igen, és nem csak a teljesen azonosakat, hanem a hasonlókat is megtalálja. A hasonlóság foka választható.

https://sign-el-soft.hu/keprendezes.html

Nagy Gábor   https://sign-el-soft.hu