Skocz do zawartości

PyGTK - Przycinanie zdjęć


prymula

Rekomendowane odpowiedzi

Witajcie

Piszę prosty skrypt ( w zasadzie na własny użytek, ale mogę się podzielić ), do przycinania zdjęć do najpopularniejszych formatów papierów fotograficznych. Szczerze mówiąc, póki co aplikacja obsługuje jako tako jedynie format A6 – gdyż jest jeszcze ciągle w budowie. Przycinanie działa, choć z reguły źle przycina u dołu zdjęcia, jeśli nad górną ramką jest więcej wolnej przestrzeni. Jeśli górna rama jest na górze, wówczas jest dobrze. Nie wiem z czego to wynika, czy błąd jest w moim skrypcie. Czy też błąd leży po stronie biblioteki GdkPixbuf, która notabene partaczy po wycięciu nieco zdjęcie ( spada jakość – pikselizacja ? ). Dlatego zastanawiam się na biblioteką Imlib. Jednak nie wiem czy warto się rzucać, na głęboką wodę, gdyż wydaje mi się że trudniej ją zastosować, niż Pixbuf.

Opis listingu dotyczącego skrawka z całości:

Zmienne self.picture_view_width oraz self.picture_view_height dotyczą rozmiaru obrazka w kontrolce.

Natomiast self.border_x, self.border_y, self.border_width i self.border_height nawiązują to parametrów ramki która to wskazuje jak i o ile przyciąć zdjęcie.

Zmienne self.picture_orig_width oraz self.picture_orig_height mówią o rozmiarze zdjęcia adekwatnego do kopii na dysku.

Zmienne crop_x, crop_y, crop_width, crop_height dotyczą parametrów wycinki dokonywanej z orginału

 

def photo_crop(self, button):
		
		if self.border_x != 0 :
			bx = self.picture_view_width / self.border_x
			crop_x = self.picture_orig_width / bx
		else:
			crop_x = 0
			
		if self.border_y != 0:
			by = self.picture_view_height / self.border_y
			crop_y = self.picture_orig_height / by
		else:
			crop_y = 0
			
		bw = self.picture_view_width / self.border_width
		crop_width = (self.picture_orig_width) / bw - crop_x
		
		bh = self.picture_view_height / self.border_height
		crop_height = (self.picture_orig_height) / bh - crop_y
		
		# False - kanał Alpha
		self.pixbuf_tmp = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, crop_width, crop_height)

		# zera na koncu to dest_x i dest_y
		self.pixbuf_orig.copy_area(crop_x, crop_y, crop_width, crop_height, self.pixbuf_tmp, 0, 0)
		
		
		print ("crop_x: "+str(crop_x))
		print ("crop_y: "+str(crop_y))
		print ("crop_width: "+str(crop_width))
		print ("crop_height: "+str(crop_height))
		
		
		if self.format_size == "10x15":
			if crop_width > crop_height:
				self.picture_view_width = 600
				self.picture_view_height = 400

			if crop_height > crop_width:
				self.picture_view_height = 600
				self.picture_view_width = 400
		
		# tylko do testów
		self.pixbuf_tmp.savev("/home/przem/Obrazy/ZAPISANY.jpg", "jpeg")
		
		self.pixbuf_view = self.pixbuf_tmp.scale_simple(self.picture_view_width, self.picture_view_height, GdkPixbuf.InterpType.BILINEAR)
		

		self.picture_view_x = 0
		self.picture_view_y = 0

		self.border_visible = False

		self.drawing_area.queue_draw()

Link do całości:

Pakiet RPM i SRPM

Tej młodej, pięknej istocie przycięło nieco stopy...Z-Ramka.thumb.png.69255830a84e3687f756854b7c5e2776.png578213070_Po-przyciciu.thumb.png.2c6795bc08670b56a34e60651f2550a9.png 

  • Upvote 1
Odnośnik do komentarza
Udostępnij na innych stronach

Masz gdzieś błąd przy wyliczaniu rozmiaru ramki. Najłatwiej to zauważyć gdy zmniejszysz ramkę (ctrl+scroll) i zaczniesz ją przesuwać gdy przesuwasz w dół wysokość ramki  się zwiększa i gdy przesuwasz w prawo szerokość ramki się również zwiększa. przy wyjechaniu poza obraz współrzędne np startowe x,y są ujemne i program nie działa prawidłowo.

Sporo kodu się powtarza i pasowało by go opakować w funkcje.

Odnośnik do komentarza
Udostępnij na innych stronach

Zapytam jak się ma 600x400 do 10x15. tu piksele a tu centymetry. Może potrzeba jakiegoś przeliczania piksele<->dpi? Dlaczego jest tam skalowanie 'scale_simple). Może to powoduje utratę jakości?

Radek Głębicki

Odnośnik do komentarza
Udostępnij na innych stronach

Dziękuję za zainteresowanie.

Racja po stronie @Radosław prawidłowa rozdzielczość dla podglądu powinna wynosić 413,34x582,66. Wyliczenie wycięcia podzieliłem na wertykalne oraz horyzontalne – pomogło. Jednak nie w każdym przypadku, gdyż na niektórych pozycjach na zdjęciu np. w formacie 3/2, potrafi się wyłożyć. Oraz skrypt głupieje przy zdjęciach ze smartfonu. Generalnie najlepiej trawi zdjęcia z kompaktów. Jednak i przy nich potrafi zachowywać się nieprzywidywanie. Przycięcie zdjęcia do rozmiary 10x15, daje wynik daleki od ideału, gdyż jest widoczny narzut z prawej strony. Spotkałem się z opinią że biblioteka Pixbuf, nie do końca udała się autorom – pewnie stąd te te losowe ‘zonki’ po przycięciu. Choć czytałem o tym dość dawno.

Pozdrawiam

Nie wiem z czego wynika ta dodatkowa tabulatura na listingu...

if self.horizontal == True and self.vertical == False:

			if self.border_x != 0 :
				bx = self.picture_view_width / self.border_x
				crop_x = self.picture_orig_width / bx
			else:
				crop_x = 0
			
			if self.border_y != 0:
				by = self.picture_view_height / self.border_y
				crop_y = self.picture_orig_height / by
			else:
				crop_y = 0
			
			bw = self.picture_view_width / self.border_width
			crop_width = self.picture_orig_width / bw
		
			bh = self.picture_view_height / self.border_height
			crop_height = self.picture_orig_height / bh 
		
			print ("HORIZONTAL")
		
		elif self.horizontal == False and self.vertical == True:

			if self.border_x != 0 :
				bx = self.picture_view_height / self.border_x
				crop_x = self.picture_orig_height / bx
			else:
				crop_x = 0
			
			if self.border_y != 0:
				by = self.picture_view_width / self.border_y
				crop_y = self.picture_orig_width / by
			else:
				crop_y = 0
			
			bw = self.picture_view_height / self.border_width
			crop_width = self.picture_orig_height / bw 
		
			bh = self.picture_view_width / self.border_height
			crop_height = self.picture_orig_width / bh
		
			print ("VERTICAL")

 

ps. Link do zmodyfikowanej całości ten sam co wcześniej

Edytowane przez prymula
dojście do sedna sprawy
Odnośnik do komentarza
Udostępnij na innych stronach

  • 1 month later...

Suma sumarum udało mi się okiełznać tą niesforną  ramkę, skrypt przycina zdjęcia prawidłowo. Poprawiłem jakość po skalowaniu, jako że aplikacja może wydrukować zdjęcie po przycięciu, efekt końcowy jest nawet, nawet. Możliwa jest ramka wokół zdjęcia, dotyczy to szczególnie zdjęć horyzontalnych. Zamierzam dodać przekształcenia ramki na zdjęciach wertykalnych do formatu horyzontalnego i odwrotnie. Nie taka zła ta biblioteka Pixbuf, nie pamiętam dobrze której wersji dotyczyły nie pochlebne  opinie - możliwe że pierwszej.

Odnośnik do komentarza
Udostępnij na innych stronach

5 godzin temu, prymula napisał:

Suma sumarum udało mi się okiełznać tą niesforną  ramkę, skrypt przycina zdjęcia prawidłowo

Gratulacje!

Kilka uwag. Często powielasz ten sam kod (if elif elif elif ...) bo ustawiasz odpowiednie wartości w zależności od rozmiary fotografii, pasowałoby zapisać wszystkie potrzebne parametry w odpowiedniej konfiguracji np. w słowniku.

>>> config = { "10x15" : { "width" : 148, "height" : 104.99 }, 
               "13x18" : { "width" : 178, "height" : 127 } }
>>> config["13x18"]["width"]
178
>>> config["10x15"]["width"]
148

Kod jest wtedy bardziej przejrzysty, łatwiej dodać nowe formaty zdjęć, mniejsza szansa na popełnienie błędu i szybsze poprawki itd, no i kod jest bardziej przejrzysty, bo zamiast powielać ciągle ten sam fragmenty wystarczy napisać go tylko raz np.

page_width = config[self.format_size]["width"]
page_height = config[self.format_size]["height"]

Oczywiście zamiast trzymać konfigurację w kodzie, najlepiej, aby była ona w oddzielnym pliku np. JSON.

No i polecam zapoznać się z takimi narzędziami jak pylint (linter - dba o "jakość kodu" oraz yapf - formatuje kod, oraz https://packaging.python.org/en/latest/tutorials/packaging-projects/.

Odnośnik do komentarza
Udostępnij na innych stronach

Ten mój archaiczny sposób pisania, wynika pewnie z tego że przed laty, zaczynałem od języka strukturalnego a nie pisałem w języku obiektowym który jest zorientowany na dane. Określić parametry w słowniku, no cóż to w sumie dobry pomysł, bądź co bądź to w końcu Python. Jednak jest to dla mnie pewne wyzwanie a o oddzielnym pliku z konfiguracją już nie wspominając. W poprzedniej wersji wkradło się niedopatrzenie, zdjęcia horyzontalne były nadto rozciągnięte w pionie co psuło wynik.  

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
×
×
  • Dodaj nową pozycję...