Nima uçun rasmlarni dastur bilan qayta işlaş kerak?
Tasavvur qiling: onlayn dökoningiz uçun 300 ta mahsulot rasmi bor. Ularning hammasini bir xil ölçamga keltiriş, kiçik nusxalar (eskizlar) yasaş va burçagiga dökon nomini yozib çiqiş kerak. Grafik muharrirda buni qölda bajariş bir neça kun oladi, Python bilan esa bir neça daqiqa.
Python'da rasmlar bilan işlaş uçun eng maşhur kutubxona — Pillow. U eski PIL (Python Imaging Library) kutubxonasining davomçisi, şuning uçun kodda PIL nomi bilan import qilinadi. Pillow JPEG, PNG, WebP, GIF, BMP va boşqa köplab formatlarni qöllab-quvvatlaydi.
Örnatiş
pip install Pillow
Örnatilganini tekşiriş uçun versiyani çiqaramiz. Eʼtibor bering: paket nomi Pillow, lekin import nomi PIL.
import PIL
print(PIL.__version__)
Sinov rasmini yaratiş
Misollarni sinab köriş uçun qölingizda rasm bölmasa ham muammo yöq — Image.new() bilan yangi rasm yaratiş mumkin. Unga rejim ("RGB" — rangli), ölçam (kenglik, balandlik piksellarda) va fon rangi beriladi.
from PIL import Image
rasm = Image.new("RGB", (1200, 800), "skyblue")
rasm.save("sinov.png")
print(rasm.size, rasm.mode)
(1200, 800) RGB
Rangni nomi bilan ("skyblue", "white"), "#1e90ff" kabi HEX kod bilan yoki (30, 144, 255) kabi RGB kortej bilan beriş mumkin.
Rasmni oçiş va maʼlumot oliş
Image.open() faylni oçadi. Rasm obyektining eng foydali atributlari: size (kenglik va balandlik), width, height, mode (rang rejimi) va format (fayl formati).
from PIL import Image
with Image.open("sinov.png") as rasm:
print("Format:", rasm.format)
print("Ölçam:", rasm.size)
print("Kenglik:", rasm.width, "Balandlik:", rasm.height)
print("Rejim:", rasm.mode)
rasm.show() # rasmni tizimdagi rasm köruvçi dasturda oçadi
Format: PNG
Ölçam: (1200, 800)
Kenglik: 1200 Balandlik: 800
Rejim: RGB
Eng köp uçraydigan rejimlar:
| Rejim | Maʼnosi |
|---|---|
RGB | rangli rasm: qizil, yaşil, kök kanallar |
RGBA | rangli + şaffoflik (alpha) kanali, köpinça PNG |
L | kulrang (oq-qora) rasm, har piksel 0–255 |
P | palitrali rasm, köpinça GIF |
CMYK | bosmaxona uçun rang modeli |
Ölçamni özgartiriş: resize va thumbnail
resize() rasmni siz aytgan aniq ölçamga keltiradi va yangi rasm qaytaradi. Proporsiyani saqlaş kerak bölsa, balandlikni özingiz hisoblaysiz. thumbnail() esa rasmni berilgan çegaraga siğadigan qilib kiçraytiradi, proporsiyani özi saqlaydi va asl obyektni özgartiradi.
from PIL import Image
with Image.open("sinov.png") as rasm:
# 1) Aniq ölçam (proporsiya buzilişi mumkin)
kvadrat = rasm.resize((500, 500))
# 2) Kenglik 400 px, balandlik proporsional
yangi_kenglik = 400
yangi_balandlik = round(rasm.height * yangi_kenglik / rasm.width)
kichik = rasm.resize((yangi_kenglik, yangi_balandlik), Image.Resampling.LANCZOS)
# 3) thumbnail: 300x300 ga siğadigan qilib, joyida kiçraytiradi
eskiz = rasm.copy()
eskiz.thumbnail((300, 300))
print(kvadrat.size, kichik.size, eskiz.size)
(500, 500) (400, 267) (300, 200)
Image.Resampling.LANCZOS — kiçraytirişda eng sifatli natija beradigan usul. thumbnail() rasmni faqat kiçraytiradi, heç qaçon kattalaştirmaydi.
Kesiş: crop
crop() rasmdan törtburçak bölakni kesib oladi. Unga törtta son beriladi: (chap, yuqori, öng, pastki). Koordinatalar çap yuqori burçakdan (0, 0) boşlanadi, y öqi esa pastga qarab ösadi.
from PIL import Image
with Image.open("sinov.png") as rasm:
# Örtadagi 400x400 kvadratni kesib olamiz
tomon = 400
chap = (rasm.width - tomon) // 2
yuqori = (rasm.height - tomon) // 2
markaz = rasm.crop((chap, yuqori, chap + tomon, yuqori + tomon))
markaz.save("markaz.png")
print(markaz.size)
(400, 400)
Bu usul profil rasmlari (avatar) uçun juda qulay: har qanday rasmdan markaziy kvadrat qism olinadi.
Aylantiriş va akslantiriş
rotate() rasmni soat strelkasiga qarşi berilgan gradusga buradi. expand=True bölsa, rasm kesilib qolmasligi uçun ölçam kattalaşadi; böş qolgan joylar fillcolor bilan böyaladi. transpose() esa rasmni akslantiradi yoki 90° ga karrali burçakka aniq buradi.
from PIL import Image
with Image.open("sinov.png") as rasm:
qiya = rasm.rotate(30, expand=True, fillcolor="white")
tik = rasm.rotate(90, expand=True)
oyna = rasm.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
teskari = rasm.transpose(Image.Transpose.FLIP_TOP_BOTTOM)
print(rasm.size, tik.size, oyna.size)
qiya.save("qiya.png")
(1200, 800) (800, 1200) (1200, 800)
Kulrang rasm va filtrlar
convert() rasm rejimini özgartiradi. "L" rejimiga ötkazsangiz, rasm oq-qora (kulrang) böladi. ImageFilter modulida esa tayyor filtrlar bor: BLUR (xiralaştiriş), SHARPEN (tiniqlaştiriş), CONTOUR, EDGE_ENHANCE va boşqalar. GaussianBlur(radius) xiralik darajasini sozlaş imkonini beradi.
from PIL import Image, ImageFilter
with Image.open("sinov.png") as rasm:
kulrang = rasm.convert("L")
kulrang.save("kulrang.png")
rasm.filter(ImageFilter.BLUR).save("xira.png")
rasm.filter(ImageFilter.SHARPEN).save("tiniq.png")
rasm.filter(ImageFilter.GaussianBlur(radius=8)).save("juda_xira.png")
print(kulrang.mode)
L
filter() va convert() asl rasmni özgartirmaydi — ular har doim yangi rasm qaytaradi. Şuning uçun bitta asl rasmdan bir neçta turli natija oliş mumkin.
ImageDraw: şakl va matn çiziş
ImageDraw.Draw(rasm) rasm ustida çiziş uçun “qalam” yaratadi. U bilan törtburçak, ellips, çiziq va matn çiziş mumkin. Quyidagi misolda dökon uçun oddiy çegirma banneri yasaymiz.
from PIL import Image, ImageDraw, ImageFont
banner = Image.new("RGB", (800, 400), "#fff4e0")
qalam = ImageDraw.Draw(banner)
# Ramka va bezaklar
qalam.rectangle([10, 10, 789, 389], outline="#d35400", width=6)
qalam.ellipse([620, 40, 760, 180], fill="#e74c3c")
qalam.line([40, 300, 760, 300], fill="#d35400", width=3)
# Şrift: tizimda bölmasa, Pillow'ning öz şriftidan foydalanamiz
try:
shrift = ImageFont.truetype("arial.ttf", 48)
except OSError:
shrift = ImageFont.load_default(size=48)
qalam.text((40, 120), "Kitoblarga çegirma!", fill="#2c3e50", font=shrift)
qalam.text((655, 85), "-20%", fill="white", font=ImageFont.load_default(size=36))
qalam.text((40, 320), "Faqat şu hafta", fill="#7f8c8d", font=ImageFont.load_default(size=28))
banner.save("banner.png")
Bu yerda koordinatalar yana (x, y) körinişida: rectangle va ellipse uçun [x0, y0, x1, y1] — çap yuqori va öng pastki burçaklar. ImageFont.load_default(size=...) Pillow 10.1 dan boşlab mavjud; eski versiyalarda size parametri yöq.
Suv belgisi qöşiş
Mahsulot rasmlariga dökon nomini yarim şaffof qilib yoziş keng tarqalgan vazifa. Buning uçun alohida şaffof qatlam (RGBA) yaratamiz, matnni unga çizamiz va Image.alpha_composite() bilan asl rasm ustiga qöyamiz.
from PIL import Image, ImageDraw, ImageFont
def suv_belgisi(yol: str, matn: str, natija: str) -> None:
with Image.open(yol) as asl:
rasm = asl.convert("RGBA")
qatlam = Image.new("RGBA", rasm.size, (255, 255, 255, 0))
qalam = ImageDraw.Draw(qatlam)
shrift = ImageFont.load_default(size=max(16, rasm.width // 20))
# Matn egallaydigan joyni ölçab, öng pastki burçakka joylaymiz
chap, yuqori, ong, past = qalam.textbbox((0, 0), matn, font=shrift)
x = rasm.width - (ong - chap) - 20
y = rasm.height - (past - yuqori) - 20
qalam.text((x, y), matn, font=shrift, fill=(255, 255, 255, 140))
birlashgan = Image.alpha_composite(rasm, qatlam)
birlashgan.convert("RGB").save(natija, quality=90)
suv_belgisi("sinov.png", "Kitob dökoni", "belgili.jpg")
textbbox() matn qança joy egallaşini qaytaradi — şu orqali matnni istalgan burçakka aniq joylaş mumkin. filldagi törtinçi son (140) — şaffoflik: 0 butunlay körinmas, 255 butunlay töq.
Turli formatlarda saqlaş
save() formatni fayl kengaytmasidan aniqlaydi. Har bir formatning öz xususiyatlari bor:
| Format | Qaçon işlatiladi | Muhim parametrlar |
|---|---|---|
JPEG | fotosuratlar, şaffoflik yöq | quality (1–95), optimize=True |
PNG | grafika, matn, logotip, şaffoflik | optimize=True (sifat yöqolmaydi) |
WebP | veb-saytlar uçun ixçam format | quality, lossless=True |
from pathlib import Path
from PIL import Image
with Image.open("banner.png") as rasm:
rasm.save("banner_85.jpg", quality=85, optimize=True)
rasm.save("banner_50.jpg", quality=50)
rasm.save("banner.webp", quality=80)
rasm.save("banner_opt.png", optimize=True)
for nom in ["banner.png", "banner_opt.png", "banner_85.jpg", "banner_50.jpg", "banner.webp"]:
hajm = Path(nom).stat().st_size / 1024
print(f"{nom:16} {hajm:8.1f} KB")
Natijadagi hajmlar rasmga boğliq, lekin odatda WebP eng ixçam, JPEGda esa quality kamaygan sari fayl kiçrayadi va sifat pasayadi.
Ommaviy qayta işlaş: papkadagi barça rasmlarga eskiz
Endi bobning boşidagi vazifani hal qilamiz: rasmlar papkasidagi barça rasmlar uçun eskizlar papkasiga 300×300 ga siğadigan JPEG nusxalar yaratamiz. pathlib fayllarni topişni, Pillow esa qayta işlaşni bajaradi.
from pathlib import Path
from PIL import Image, ImageOps, UnidentifiedImageError
KENGAYTMALAR = {".jpg", ".jpeg", ".png", ".webp", ".bmp"}
def eskizlar_yarat(manba: Path, maqsad: Path, olcham=(300, 300)) -> int:
maqsad.mkdir(parents=True, exist_ok=True)
soni = 0
for fayl in sorted(manba.iterdir()):
if fayl.suffix.lower() not in KENGAYTMALAR:
continue
try:
with Image.open(fayl) as rasm:
rasm = ImageOps.exif_transpose(rasm) # telefon rasmlarini töğrilaş
rasm.thumbnail(olcham)
yangi = maqsad / f"{fayl.stem}_eskiz.jpg"
rasm.convert("RGB").save(yangi, quality=85, optimize=True)
except (UnidentifiedImageError, OSError) as xato:
print(f"Ötkazib yuborildi: {fayl.name} ({xato})")
continue
print(f"{fayl.name} -> {yangi.name} {rasm.size}")
soni += 1
return soni
# Sinaş uçun bir neçta rasm yaratib olamiz
manba = Path("rasmlar")
manba.mkdir(exist_ok=True)
for i, (rang, olcham) in enumerate([("red", (1600, 900)), ("green", (800, 1200)), ("navy", (640, 640))], 1):
Image.new("RGB", olcham, rang).save(manba / f"mahsulot{i}.png")
(manba / "izoh.txt").write_text("rasm emas", encoding="utf-8")
jami = eskizlar_yarat(manba, Path("eskizlar"))
print("Jami:", jami)
mahsulot1.png -> mahsulot1_eskiz.jpg (300, 169)
mahsulot2.png -> mahsulot2_eskiz.jpg (200, 300)
mahsulot3.png -> mahsulot3_eskiz.jpg (300, 300)
Jami: 3
Bu kodda bir neçta muhim tafsilot bor: kengaytma lower() bilan tekşiriladi (.JPG ham topilsin), rasm bölmagan yoki buzilgan fayllar try/except bilan ötkazib yuboriladi, natija esa alohida papkaga yoziladi — asl rasmlar heç qaçon ustidan yozilmaydi.
Xulosa
Pillowpip install Pillowbilan örnatiladi vafrom PIL import Imagedeb import qilinadi.Image.open()faylni oçadi,Image.new()yangi rasm yaratadi;size,mode,formatasosiy maʼlumotlarni beradi.resize()aniq ölçam beradi,thumbnail()proporsiyani saqlab joyida kiçraytiradi;crop()kesadi,rotate()vatranspose()buradi.convert("L")kulrang rasm,ImageFilteresaBLUR,SHARPEN,GaussianBlurkabi filtrlar beradi.ImageDrawbilan şakl va matn çiziladi; şaffof qatlam vaalpha_composite()suv belgisi uçun işlatiladi.JPEG,PNG,WebPformatlaridaqualityvaoptimizeparametrlari bilan saqlanadi; ommaviy işlov uçunpathlibbilan birga işlatiladi.
Maşqlar
- Berilgan rasmni 90°, 180° va 270° ga burib, har birini
burilgan_90.pngkabi nomlar bilan saqlaydigan funksiya yozing.
Yeçim
from PIL import Image
def burib_saqla(yol: str) -> None:
with Image.open(yol) as rasm:
for burchak in (90, 180, 270):
rasm.rotate(burchak, expand=True).save(f"burilgan_{burchak}.png")
burib_saqla("sinov.png")
- Rasmdan markaziy kvadratni kesib olib, uni 256×256 ölçamli avatar sifatida
PNGformatida saqlaydiganavatar_yasa(yol, natija)funksiyasini yozing.
Yeçim
from PIL import Image
def avatar_yasa(yol: str, natija: str, olcham: int = 256) -> None:
with Image.open(yol) as rasm:
tomon = min(rasm.size)
chap = (rasm.width - tomon) // 2
yuqori = (rasm.height - tomon) // 2
kvadrat = rasm.crop((chap, yuqori, chap + tomon, yuqori + tomon))
kvadrat.resize((olcham, olcham), Image.Resampling.LANCZOS).save(natija)
avatar_yasa("sinov.png", "avatar.png")
- Papkadagi barça
.pngrasmlarni kulrang qilib,kulrangpapkasigaWebPformatida (quality=80) saqlang.
Yeçim
from pathlib import Path
from PIL import Image
manba = Path("rasmlar")
maqsad = Path("kulrang")
maqsad.mkdir(exist_ok=True)
for fayl in manba.glob("*.png"):
with Image.open(fayl) as rasm:
rasm.convert("L").save(maqsad / f"{fayl.stem}.webp", quality=80)
print("Tayyor:", fayl.name)
- 600×400 ölçamli tabriknoma yasang: fon rangi, ramka, markazda “Navröz muborak!” yozuvi va bir neçta rangli doira bölsin. Matnni markazga joylaş uçun
textbbox()dan foydalaning.
Yeçim
import random
from PIL import Image, ImageDraw, ImageFont
kenglik, balandlik = 600, 400
karta = Image.new("RGB", (kenglik, balandlik), "#e8f8f5")
qalam = ImageDraw.Draw(karta)
qalam.rectangle([8, 8, kenglik - 9, balandlik - 9], outline="#16a085", width=5)
for _ in range(12):
x, y = random.randint(20, kenglik - 60), random.randint(20, balandlik - 60)
r = random.randint(10, 30)
rang = random.choice(["#f1c40f", "#e67e22", "#2ecc71", "#e74c3c"])
qalam.ellipse([x, y, x + r, y + r], fill=rang)
matn = "Navröz muborak!"
shrift = ImageFont.load_default(size=44)
chap, yuqori, ong, past = qalam.textbbox((0, 0), matn, font=shrift)
x = (kenglik - (ong - chap)) // 2
y = (balandlik - (past - yuqori)) // 2
qalam.text((x, y), matn, fill="#0e6655", font=shrift)
karta.save("navroz.png")