optimizacija slik
Deploy to Development and Production / deploy (push) Successful in 3s
Details
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 173 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 512 KiB After Width: | Height: | Size: 512 KiB |
|
Before Width: | Height: | Size: 250 KiB After Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 514 KiB After Width: | Height: | Size: 514 KiB |
|
Before Width: | Height: | Size: 390 KiB After Width: | Height: | Size: 390 KiB |
|
Before Width: | Height: | Size: 339 KiB After Width: | Height: | Size: 339 KiB |
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 305 KiB After Width: | Height: | Size: 305 KiB |
|
Before Width: | Height: | Size: 275 KiB After Width: | Height: | Size: 275 KiB |
|
Before Width: | Height: | Size: 227 KiB After Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 180 KiB |
|
Before Width: | Height: | Size: 435 KiB After Width: | Height: | Size: 435 KiB |
|
Before Width: | Height: | Size: 413 KiB After Width: | Height: | Size: 413 KiB |
|
Before Width: | Height: | Size: 367 KiB After Width: | Height: | Size: 367 KiB |
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 454 KiB After Width: | Height: | Size: 454 KiB |
|
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 241 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 230 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
|
@ -53,8 +53,8 @@
|
|||
<section class="container">
|
||||
<!-- === POPRAVEK: Dodani uvodni sliki === -->
|
||||
<div class="image-grid">
|
||||
<div class="grid-image" style="background-image: url('/assets/images/home-slider-07-papiga.jpg');"></div>
|
||||
<div class="grid-image" style="background-image: url('/assets/images/blog-sadje-ogledalo.jpg');"></div>
|
||||
<div class="grid-image" style="background-image: url('/assets/images/home-slider-07-papiga.webp');"></div>
|
||||
<div class="grid-image" style="background-image: url('/assets/images/blog-sadje-ogledalo.webp');"></div>
|
||||
</div>
|
||||
|
||||
<!-- === POPRAVEK: Celotna vsebina bloga v eni datoteki === -->
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
<div class="cenik-hero-image-wrapper animate-on-scroll">
|
||||
<!-- Notranji vsebnik, ki ustvari kvadratno razmerje -->
|
||||
<div class="cenik-hero-image-container">
|
||||
<img src="/assets/images/tempelj.jpg" alt="Tempelj v naravi">
|
||||
<img src="/assets/images/tempelj.webp" alt="Tempelj v naravi">
|
||||
</div>
|
||||
</div>
|
||||
<!-- Besedilo na desni strani -->
|
||||
|
|
|
|||
18
index.html
|
|
@ -49,14 +49,14 @@
|
|||
<div class="slide-content">
|
||||
<figure class="slide-image">
|
||||
<img
|
||||
src="/assets/images/home-slider-01-morje.png"
|
||||
src="/assets/images/home-slider-01-morje.webp"
|
||||
alt="Morje s skalo v ozadju"
|
||||
/>
|
||||
</figure>
|
||||
<div class="slide-text">
|
||||
<!-- === PORTRET === -->
|
||||
<figure class="slide-portrait">
|
||||
<img src="/assets/images/portret.JPG" alt="Portret mag. Hermine Merc">
|
||||
<img src="/assets/images/portret.webp" alt="Portret mag. Hermine Merc">
|
||||
</figure>
|
||||
|
||||
<h2>PSIHOTERAPEVT, VRHUNSKI STROKOVNJAK</h2>
|
||||
|
|
@ -84,7 +84,7 @@
|
|||
<section class="slide">
|
||||
<div class="slide-content">
|
||||
<figure class="slide-image">
|
||||
<img src="/assets/images/home-slider-02-palme.jpg" alt="Pogled na palme in morje" />
|
||||
<img src="/assets/images/home-slider-02-palme.webp" alt="Pogled na palme in morje" />
|
||||
</figure>
|
||||
<div class="slide-text">
|
||||
<h2>
|
||||
|
|
@ -105,7 +105,7 @@
|
|||
<div class="slide-content">
|
||||
<figure class="slide-image">
|
||||
<img
|
||||
src="/assets/images/home-slider-03-puscava.jpg"
|
||||
src="/assets/images/home-slider-03-puscava.webp"
|
||||
alt="Puščavska pokrajina"
|
||||
/>
|
||||
</figure>
|
||||
|
|
@ -126,7 +126,7 @@
|
|||
<div class="slide-content">
|
||||
<figure class="slide-image">
|
||||
<img
|
||||
src="/assets/images/home-slider-04-kanjon-svetloba.jpg"
|
||||
src="/assets/images/home-slider-04-kanjon-svetloba.webp"
|
||||
alt="Svetloba, ki sije v kanjon"
|
||||
/>
|
||||
</figure>
|
||||
|
|
@ -144,7 +144,7 @@
|
|||
<div class="slide-content">
|
||||
<figure class="slide-image">
|
||||
<img
|
||||
src="/assets/images/home-slider-05-drevo-soteska.jpg"
|
||||
src="/assets/images/home-slider-05-drevo-soteska.webp"
|
||||
alt="Drevo, ki raste v soteski"
|
||||
/>
|
||||
</figure>
|
||||
|
|
@ -162,7 +162,7 @@
|
|||
<div class="slide-content">
|
||||
<figure class="slide-image">
|
||||
<img
|
||||
src="/assets/images/home-slider-06-rastlina-pesek.jpg"
|
||||
src="/assets/images/home-slider-06-rastlina-pesek.webp"
|
||||
alt="Rastlina, ki raste iz peska"
|
||||
/>
|
||||
</figure>
|
||||
|
|
@ -179,7 +179,7 @@
|
|||
<section class="slide">
|
||||
<div class="slide-content">
|
||||
<figure class="slide-image">
|
||||
<img src="/assets/images/home-slider-07-papiga.jpg" alt="Barvita papiga na veji" />
|
||||
<img src="/assets/images/home-slider-07-papiga.webp" alt="Barvita papiga na veji" />
|
||||
</figure>
|
||||
<div class="slide-text">
|
||||
<h2>Pristno začutiti sebe</h2>
|
||||
|
|
@ -195,7 +195,7 @@
|
|||
<section class="slide">
|
||||
<div class="slide-content">
|
||||
<figure class="slide-image">
|
||||
<img src="/assets/images/home-slider-08-sipine.jpg" alt="Peščene sipine" />
|
||||
<img src="/assets/images/home-slider-08-sipine.webp" alt="Peščene sipine" />
|
||||
</figure>
|
||||
<div class="slide-text">
|
||||
<h2>Naredite prvi korak</h2>
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@
|
|||
<h1 class="page-title animate-on-scroll">Kaj je psihoterapija?</h1>
|
||||
|
||||
<div class="image-grid">
|
||||
<div class="grid-image animate-on-scroll" style="background-image: url('/assets/images/home-slider-05-drevo-soteska.jpg');"></div>
|
||||
<div class="grid-image animate-on-scroll" style="background-image: url('/assets/images/home-slider-04-kanjon-svetloba.jpg');"></div>
|
||||
<div class="grid-image animate-on-scroll" style="background-image: url('/assets/images/home-slider-05-drevo-soteska.webp');"></div>
|
||||
<div class="grid-image animate-on-scroll" style="background-image: url('/assets/images/home-slider-04-kanjon-svetloba.webp');"></div>
|
||||
</div>
|
||||
|
||||
<div class="text-section animate-on-scroll">
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
<div class="contact-details animate-on-scroll">
|
||||
<h2 class="section-title">Informacije za naročanje</h2>
|
||||
|
||||
<img src="/assets/images/portret-2.JPG" alt="Portret Hermina Merc" class="contact-portrait">
|
||||
<img src="/assets/images/portret-2.webp" alt="Portret Hermina Merc" class="contact-portrait">
|
||||
|
||||
<div class="contact-info-item">
|
||||
<p class="info-data"><strong>Mag. HERMINA MERC</strong><br>Psihoterapevt Specialist Klinični Psiholog</p>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
<h1 class="page-title animate-on-scroll">O meni</h1>
|
||||
<div class="about-grid">
|
||||
<div class="about-image animate-on-scroll">
|
||||
<img src="/assets/images/hermina-merc-portret.jpg" alt="Fotografija Hermine Merc">
|
||||
<img src="/assets/images/hermina-merc-portret.webp" alt="Fotografija Hermine Merc">
|
||||
</div>
|
||||
<div class="about-content">
|
||||
<p class="intro-text animate-on-scroll">Kot psihoterapevtka delujem k ozaveščanju, kultiviranju in osmišljanju tako osebnostnega kot duhovnega potenciala posameznika.</p>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,207 @@
|
|||
import os
|
||||
import argparse
|
||||
import shutil
|
||||
from PIL import Image
|
||||
|
||||
# --- Konfiguracija skripte za projekt "Hermina" ---
|
||||
|
||||
# Predpostavka: ta skripta se nahaja v korenski mapi projekta.
|
||||
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
# Pot do mape, kjer se nahajajo slike, ki jih želimo optimizirati.
|
||||
IMAGES_DIR_PATH = os.path.join("assets", "images")
|
||||
|
||||
# Ime podmape znotraj IMAGES_DIR_PATH, kamor se bodo shranile originalne slike.
|
||||
ORIGINAL_IMAGES_SUBDIR_NAME = "original"
|
||||
|
||||
# Mape, ki jih želimo PREGLEDATI za posodobitev referenc na slike.
|
||||
# '.' pomeni, da začnemo v korenski mapi in pregledamo vse podmape.
|
||||
DIRECTORIES_TO_SCAN = ['.']
|
||||
|
||||
# Mape, ki jih želimo IZKLJUČITI iz pregledovanja (za hitrejše delovanje in varnost).
|
||||
# Skripta ne bo iskala referenc v teh mapah.
|
||||
DIRECTORIES_TO_EXCLUDE_FROM_SCAN = ['.git', '.gitea', '.vscode', '__pycache__']
|
||||
|
||||
# Končnice datotek, v katerih iščemo in posodabljamo reference na slike.
|
||||
FILE_EXTENSIONS_TO_UPDATE = ['.html', '.css', '.js']
|
||||
|
||||
# Nastavitve optimizacije
|
||||
WEBP_QUALITY = 85 # Kakovost kompresije za WebP (0-100). Višje = boljša kvaliteta, večja datoteka.
|
||||
MAX_IMAGE_DIMENSION = 1920 # Slike, večje od te dimenzije (širina ali višina), bodo pomanjšane. 0 za izklop.
|
||||
|
||||
# Končnice slik, ki jih želimo optimizirati.
|
||||
IMAGE_EXTENSIONS_TO_OPTIMIZE = ['.jpg', '.jpeg', '.png']
|
||||
|
||||
# Imena datotek, ki jih želimo preskočiti pri optimizaciji (npr. logotipi, ikone).
|
||||
EXCLUDE_FILES_FROM_OPTIMIZATION = [
|
||||
'favicon.ico'
|
||||
# Dodajte imena drugih datotek po potrebi, npr. 'logo.png'
|
||||
]
|
||||
|
||||
|
||||
# --- Pomožne funkcije (večinoma nespremenjene) ---
|
||||
|
||||
def optimize_image(image_path, output_path, quality, max_dim, dry_run=False):
|
||||
"""
|
||||
Naloži sliko, jo po potrebi pomanjša, optimizira in pretvori v WebP format.
|
||||
"""
|
||||
try:
|
||||
with Image.open(image_path) as img:
|
||||
# Pretvorba slik s paleto (kot so nekatere PNG) v RGBA za ohranitev prosojnosti.
|
||||
if img.mode in ('P', 'LA'):
|
||||
img = img.convert("RGBA")
|
||||
|
||||
if max_dim > 0 and (img.width > max_dim or img.height > max_dim):
|
||||
print(f" Pomanjšujem sliko {os.path.basename(image_path)} iz {img.width}x{img.height} ...", end="")
|
||||
img.thumbnail((max_dim, max_dim), Image.Resampling.LANCZOS)
|
||||
print(f" na {img.width}x{img.height}")
|
||||
else:
|
||||
print(f" Obdelujem sliko {os.path.basename(image_path)} ({img.width}x{img.height})...", end="")
|
||||
|
||||
if not dry_run:
|
||||
img.save(output_path, "webp", quality=quality, method=6)
|
||||
print(f" Shrani v {os.path.basename(output_path)} (kvaliteta: {quality}).")
|
||||
else:
|
||||
print(f" DRY RUN: Shranil bi v {os.path.basename(output_path)} (kvaliteta: {quality}).")
|
||||
|
||||
return True
|
||||
except FileNotFoundError:
|
||||
print(f" Napaka: Izvorna slika '{image_path}' ni najdena.")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f" Napaka pri optimizaciji slike '{image_path}': {e}")
|
||||
return False
|
||||
|
||||
def update_file_references(file_path, old_filename, new_filename, dry_run=False):
|
||||
"""
|
||||
V dani datoteki zamenja vse pojavitve starega imena slike z novim.
|
||||
"""
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
except Exception:
|
||||
# Ignoriramo binarne ali neberljive datoteke
|
||||
return False
|
||||
|
||||
if old_filename in content:
|
||||
updated_content = content.replace(old_filename, new_filename)
|
||||
if not dry_run:
|
||||
try:
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(updated_content)
|
||||
print(f" Posodobljene reference v: '{os.path.relpath(file_path, PROJECT_ROOT)}'")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f" Napaka pri zapisovanju v '{file_path}': {e}")
|
||||
return False
|
||||
else:
|
||||
print(f" DRY RUN: Posodobil bi reference v: '{os.path.relpath(file_path, PROJECT_ROOT)}'")
|
||||
return True
|
||||
return False
|
||||
|
||||
def find_files_to_update(scan_dirs, exclude_dirs):
|
||||
"""
|
||||
Rekurzivno poišče vse datoteke z ustreznimi končnicami, pri tem pa ignorira izključene mape.
|
||||
"""
|
||||
found_files = []
|
||||
for directory in scan_dirs:
|
||||
scan_path = os.path.join(PROJECT_ROOT, directory)
|
||||
for dirpath, dirnames, filenames in os.walk(scan_path):
|
||||
# Učinkovit način za izključitev map: odstranimo jih iz seznama za nadaljnje pregledovanje
|
||||
dirnames[:] = [d for d in dirnames if d not in exclude_dirs]
|
||||
|
||||
for filename in filenames:
|
||||
if any(filename.endswith(ext) for ext in FILE_EXTENSIONS_TO_UPDATE):
|
||||
found_files.append(os.path.join(dirpath, filename))
|
||||
return sorted(list(set(found_files)))
|
||||
|
||||
|
||||
# --- Glavna funkcija ---
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Optimizira slike v WebP in posodobi reference v projektu.")
|
||||
parser.add_argument("--dry-run", action="store_true", help="Prikaže, katere spremembe bi se zgodile, a jih ne izvede.")
|
||||
args = parser.parse_args()
|
||||
|
||||
images_full_path = os.path.join(PROJECT_ROOT, IMAGES_DIR_PATH)
|
||||
original_images_full_path = os.path.join(images_full_path, ORIGINAL_IMAGES_SUBDIR_NAME)
|
||||
|
||||
# Dodamo mapo z originali v seznam za izključitev, da ne skeniramo še tam.
|
||||
DIRECTORIES_TO_EXCLUDE_FROM_SCAN.append(ORIGINAL_IMAGES_SUBDIR_NAME)
|
||||
|
||||
if not os.path.isdir(images_full_path):
|
||||
print(f"Napaka: Mapa s slikami '{images_full_path}' ne obstaja. Preverite pot v konfiguraciji.")
|
||||
return
|
||||
|
||||
if not args.dry_run:
|
||||
os.makedirs(original_images_full_path, exist_ok=True)
|
||||
print(f"Mapa za originale: '{original_images_full_path}'")
|
||||
else:
|
||||
print(f"DRY RUN: Mapa za originale bi bila '{original_images_full_path}'.")
|
||||
|
||||
optimized_images_map = []
|
||||
|
||||
print("\n--- FAZA 1: OPTIMIZACIJA SLIK ---")
|
||||
for filename in os.listdir(images_full_path):
|
||||
file_path = os.path.join(images_full_path, filename)
|
||||
|
||||
# Preskoči podmape (kot je 'original') in datoteke, ki niso datoteke
|
||||
if not os.path.isfile(file_path):
|
||||
continue
|
||||
|
||||
name, ext = os.path.splitext(filename)
|
||||
ext = ext.lower()
|
||||
|
||||
if filename in EXCLUDE_FILES_FROM_OPTIMIZATION:
|
||||
print(f"- Preskakujem izključeno datoteko: '{filename}'")
|
||||
continue
|
||||
|
||||
if ext in IMAGE_EXTENSIONS_TO_OPTIMIZE:
|
||||
new_filename = f"{name}.webp"
|
||||
new_file_path = os.path.join(images_full_path, new_filename)
|
||||
|
||||
# Preveri, če WebP verzija že obstaja in je novejša
|
||||
if os.path.exists(new_file_path) and os.path.getmtime(new_file_path) > os.path.getmtime(file_path):
|
||||
print(f"- WebP '{new_filename}' že obstaja in je posodobljen. Preskakujem optimizacijo.")
|
||||
optimized_images_map.append({'old': filename, 'new': new_filename})
|
||||
continue
|
||||
|
||||
if optimize_image(file_path, new_file_path, WEBP_QUALITY, MAX_IMAGE_DIMENSION, args.dry_run):
|
||||
optimized_images_map.append({'old': filename, 'new': new_filename})
|
||||
if not args.dry_run:
|
||||
try:
|
||||
shutil.move(file_path, os.path.join(original_images_full_path, filename))
|
||||
print(f" Original '{filename}' premaknjen v '{ORIGINAL_IMAGES_SUBDIR_NAME}/'.")
|
||||
except Exception as e:
|
||||
print(f" NAPAKA pri premikanju '{filename}': {e}")
|
||||
else:
|
||||
print(f" DRY RUN: Original '{filename}' bi bil premaknjen v '{ORIGINAL_IMAGES_SUBDIR_NAME}/'.")
|
||||
|
||||
if not optimized_images_map:
|
||||
print("\nNi bilo najdenih novih slik za optimizacijo.")
|
||||
|
||||
print("\n--- FAZA 2: POSODABLJANJE REFERENC V PROJEKTU ---")
|
||||
|
||||
files_to_scan = find_files_to_update(DIRECTORIES_TO_SCAN, DIRECTORIES_TO_EXCLUDE_FROM_SCAN)
|
||||
|
||||
if not files_to_scan:
|
||||
print("Ni najdenih .html, .css ali .js datotek za pregled.")
|
||||
else:
|
||||
print(f"Najdenih {len(files_to_scan)} datotek za pregled...")
|
||||
|
||||
updated_files_count = 0
|
||||
for file_path in files_to_scan:
|
||||
file_was_updated = False
|
||||
for img_info in optimized_images_map:
|
||||
if update_file_references(file_path, img_info['old'], img_info['new'], args.dry_run):
|
||||
file_was_updated = True
|
||||
|
||||
if file_was_updated:
|
||||
updated_files_count += 1
|
||||
|
||||
print(f"\nPregledanih je bilo {len(files_to_scan)} datotek.")
|
||||
print(f"Posodobljenih je bilo {updated_files_count} datotek.")
|
||||
print("\n--- SKRIPTA JE ZAKLJUČILA Z DELOM ---")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
<div class="storitve-hero-image-wrapper animate-on-scroll">
|
||||
<!-- Notranji vsebnik, ki ustvari kvadratno razmerje -->
|
||||
<div class="storitve-hero-image-container">
|
||||
<img src="/assets/images/morje-z-napisom.jpg" alt="Morje z napisom Energy of Eternal Life">
|
||||
<img src="/assets/images/morje-z-napisom.webp" alt="Morje z napisom Energy of Eternal Life">
|
||||
</div>
|
||||
</div>
|
||||
<!-- Vsebnik za besedilo na desni strani -->
|
||||
|
|
|
|||