Pobieranie obrazów z Instagrama

Pobieranie obrazów z Instagrama

Czasem zachodzi potrzeba pobrania zdjęcia z Instagrama w pełnej dostępnej rozdzielczości. Wbrew pozorom jest to dość proste.

W zasadzie, jedyne, co należy wykonać, to odnaleźć wpis meta nazywający się „og:image”:

<meta property="og:image" content="https://serwer/zdjecie.jpg" />

Zawartość właściwości „content” to link do zdjęcia w pełnej rozdzielczości.

Jeśli jednak chcesz pobrać większą ilość zdjęć, bądź robisz to dość często, przyda się mała automatyzacja. Napisałem do tego celu mały skrypt, który działa pod kontrolą TamperMonkey. Wszystko, co ten skrypt robi, to na dole strony (pomiędzy zdjęciem a stopką) wstawia link do zdjęcia.

Po zainstalowaniu TamperMonkey, jeśli go jeszcze nie masz, wystarczy zainstalować ten skrypt. Uwaga, skrypt działa na stronie postu, nie na stronach kolekcji. Aby przejść do strony postu z podglądu zdjęcia, należy wybrać opcję „Go to post„.

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

Seriale Netflix – Marvel

Na przełomie listopada i grudnia w końcu skusiłem się na bezpłatny miesiąc testów Netfliksa. Powiem tylko tyle, że efektem testów jest przedłużenie 😉

W ramach owych testów postanowiłem sprawdzić, co Netflix wyczarował do spółki z Marvelem. Skusiły mnie takie nazwiska trzymających pieczę nad produkcjami, jak Stan Lee i Joe Quesada. Zacząłem trochę krzywo, bo od Punishera.

Historia zaczyna się, gdy Punisher ukrywa się pod nowym nazwiskiem, już po wykończeniu ludzi odpowiedzialnych za wymordowanie jego rodziny. Jak to zwykle bywa, zostaje zmuszony do powrotu na ulicę. Po obejrzeniu serialu (póki co, jest jeden sezon) poczytałem trochę opinii w necie – zawsze to robię dopiero po obejrzeniu filmu. Sporo ludzi marudzi, że Punisher mało brutalny jest i że w Daredevilu (o czym niżej) jest znacznie lepszy. Hmm… wg mnie w Daredevilu jest dokładnie taki sam, identyczny charakter. Jeśli ktoś twierdzi inaczej, to krzywo oglądał oba seriale i raczej oglądał tylko obrazki 😉 W każdym razie, mnie kupili tą historią.

Idąc tym tropem, obejrzałem oba (na razie) sezony Daredevila. Ujmę to tak: jeśli ktoś zna tę postać tylko z filmu z Benem Affleckiem, to szybko zapomnijcie o swoich odczuciach z tym związanych. Serial to zupełnie inna bajka. Szczerze mówiąc, dawno nie widziałem tak dobrego serialu, a już na pewno nie marvelowego. Zgrabna fabuła, wartka akcja, postaci naprawdę świetne. No i rzecz bardzo rzadko spotykana – czarny charakter jest nareszcie fantastycznie narysowany. Wilson Fisk (przyszły Kingpin) jest wyrazisty jak mało co. Najlepiej by go określił Shrek 😉 że jest jak cebula.

Po Daredevilu przyszedł czas na The Defenders. Okazało się, że spośród 4 indywidualnych seriali, ten należy obejrzeć właśnie po Daredevilu, gdyż jest on bezpośrednią kontynuacją jego fabuły. Ponownie zmierzymy się z organizacją The Hand i Czarnym Słońcem. Opisać ten mini-serial nie jest łatwo. Bohaterowie: Daredevil jak to Daredevil, świetny. Reszty do tej pory nie znałem (filmowo, rzecz jasna). Jessica Jones wypadła rewelacyjnie, jej postać wykreowana naprawdę świetnie. Luke Cage idealnie… nijaki. W zasadzie nic o tym człowieku się nie da powiedzieć. A Iron Fist… klapa kompletna. Nie wiem, może taki był zamysł producentów, żeby zrobić z niego rozkojarzonego dzieciaka ze świecącą pięścią. W każdym razie, wiem teraz, że tych dwóch indywidualnych seriali raczej nie będę próbował oglądać. Natomiast ozdobą były dialogi Jessiki z Daredevilem. Ta dwójka wymiatała 🙂 Co do samej akcji: skonstruowana jest poprawnie, a dzięki skróceniu formatu do 8 tylko odcinków, nie ma dłużyzn. Jedyne, co mogę zarzucić mu, to łzawe zakończenie, którego jakoś chyba nie mogli sobie odmówić, oraz oczywistą, spodziewaną i sztampową ostatnią scenę. Poza tym, serial jest ok.

Po obejrzeniu Defenders, postanowiłem sprawdzić Jessikę Jones, która tam wypadła naprawdę bardzo ciekawie. Serial zupełnie różny od typowych produkcji marvelowskich – bo i bohaterka jakże inna (choć oryginalnie bardzo mocno wpleciona w życiorys Spidermana). Nie jest to typowe superbohaterskie kino, raczej kryminalny thriller. Ogląda jednak się to naprawdę dobrze, zwłaszcza pierwszą połowę. Druga połówka chyba nieco zbyt mocno skupiona na relacjach Jessiki z Kilgravem, ale tak została skreślona fabuła, więc nie ma co narzekać. Serial zdecydowanie dla dorosłych – seks i przemoc kapią z ekranu solidnymi strugami. Ogólnie szczerze polecam obejrzenie.

Na koniec… muszę przyznać, że pozytywnie mnie te seriale zaskoczyły. Znając różne produkcje Marvela, te naprawdę się wybijają ponad przeciętność. Co prawda, najprawdopodobniej (choć nie widziałem) Iron Fist i Luke Cage bedą beznadziejne, ale te wymienione powyżej jak najbardziej na plus. Brawo Netflix 🙂

Na koniec 2… Boję się otworzyć lodówkę. Boję się, że wyskoczy z niej… Claire 😉  w każdym serialu (chyba tylko w Punisheru jej nie było?) ta postać się pojawia. W sumie, być może to był zabieg pozwalający na spięcie fabuły w The Defenders, choć i tak sposób ich spotania się był lekko… hm, niezręczny 😉 no, ale sam bym chyba też tego lepiej nie zrobił, więc się tylko czepiam.

Na koniec 3 😉 czołówka z The Defenders, napisana przez Johna Paesano, wymiata. Jest też na Spotify’u, jakby co.

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

Lost Alpha Director’s Cut – early screenshots

As S.T.A.L.K.E.R.: Lost Alpha – Director’s Cut is getting more and more of its final look, I’ve decided to publish some screenshots.

I will be adding more images here, but I won’t add any new post anytime soon, so just check this one back from time to time.

Please note: as the game is still under development, the quality of images can vary between each other. However, all of them are quite fresh – but the final game can look a bit different.

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin
Selektor koloru z trybem float

Selektor koloru z trybem float

Jest wiele selektorów kolorów online. Większość zwraca wyniki w wartościach RGB z zakresu <0..255>, w zapisie szesnastkowym, oraz HSL. Jednak brakuje w nich wszystkich jeszcze jednej formy podawania wyników: w formie wartości RGB w zakresie <0..1>, używanym w niektórych programach, zwłaszcza 3D. Osobiście często używam POV-Raya i za każdym razem muszę używać kalkulatora, aby przeliczyć wszystkie trzy wartości na odpowiedni zakres.

Początkowo miałem zamiar napisać malutki programik do tego celu, ale stwierdziłem, że wersja on-line będzie wygodniejsza w użyciu. Nie jest to żadne rocket science 😉 ale swoje zadanie spełnia. Może w przyszłości jakoś go rozbuduję i usprawnię, ale… nie obiecuję 😉

Jeszcze jedna uwaga… poniższe nie działa z IE… 🙁






Może się komuś przyda – mi na pewno 🙂

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

Pluginy aplikacji Qt5

Tworzenie systemu pluginów aplikacji działającej na różnych systemach wymagało zawsze wielokrotnej implementacji tego samego – dla każdego systemu oddzielnie, głównie z powodu sposobu dynamicznego ładowania bibliotek. W Qt jednak jest inaczej – framework ten udostępnia bardzo sprawnie działający system pluginów.

Na początek zdefiniujmy interfejs (API):

#ifndef DESIGNLAYER_API_H
#define DESIGNLAYER_API_H

#include <QString>
#include <QtPlugin>

namespace apophysis
	{		
	class DesignLayerAPI
		{
		public:
			virtual ~DesignLayerAPI() {};
			virtual QString getName() = 0;
		};
	}

#define DesignLayerAPI_iid "org.apophysis.DesignLayerAPI"

Q_DECLARE_INTERFACE(apophysis::DesignLayerAPI, DesignLayerAPI_iid)

#endif // DESIGNLAYER_API_H

Widzimy tu wirtualną klasę, definiującą metodę getName(). Po definicji API, następuje definicja interfejsu, po którym Qt będzie rozpoznawać nasze pluginy, implementujące te API.

Czas na plugin. Deklarujemy klasę implementującą API:

#ifndef DESIGNLAYER_IMAGE_H
#define DESIGNLAYER_IMAGE_H

#include <QObject>
#include <QString>
#include <DesignLayerAPI.h>

class designLayerImage : public QObject, apophysis::DesignLayerAPI
	{
	Q_OBJECT
		Q_PLUGIN_METADATA(IID "org.apophysis.DesignLayerAPI" FILE "designLayerImage.json")
		Q_INTERFACES(apophysis::DesignLayerAPI)

	public:
		designLayerImage();
		QString getName() Q_DECL_OVERRIDE;
	private:
		QString theName;
	};

#endif // DESIGNLAYER_IMAGE_H

Oprócz deklaracji metod zadeklarowanych w interfejsie, widzimy tu jeszcze jedną rzecz: definicję metadanych. Po co to? Metadane pluginu można odczytać bez faktycznego ładowania biblioteki. Zapisujemy je w pliku JSON, np:

{
"type"			:	"Layer",
"name"			:	"Image layer plugin",
"shortname"		:	"ImageLayer",
"version"		:	"0.1",
"author"		:	"Apophysis internal",
"description"	:	"Used mainly for backgrounds: solid colour, gradients, images, etc."
}

Właściwa implementacja jest oczywista, żadnej magii tu nie ma:

#include "designLayerImage.h"

designLayerImage::designLayerImage()
	:
	theName(QLatin1Literal("Unnamed image layer"))
	{
	}

QString designLayerImage::getName()
	{
	return theName;
	}

OK, mamy plugin. Jak go użyć? Na szczęście, to również jest proste (i przenośne! Na pewno działa bez zmian pod Windows i Linux, pod OSX nie sprawdzałem).

Najpierw sprawdzimy w działaniu system metadanych. Załóżmy, że pluginy mamy w podkatalogu plugins (niespodzianka!):

#include <QPluginLoader>
#include <DesignLayerAPI.h>

void listPlugins()
	{
	QDir pluginsDir(qApp->applicationDirPath());
	pluginsDir.cd(QLatin1Literal("plugins"));
	foreach(QString fileName, pluginsDir.entryList(QDir::Files, QDir::Name))
		{
		QString libExt;
#if defined(Q_OS_WIN)
		libExt = QLatin1Literal("dll");
#elif defined(Q_OS_MAC)
		libExt = QLatin1Literal("bundle");
#elif defined(Q_OS_LINUX)
		libExt = QLatin1Literal("so");
#endif
		if (QFileInfo(fileName).suffix().toLower() == libExt)
			{
			QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
			qDebug() << "File:" << fileName;
			QJsonObject jsonMetaData = pluginLoader.metaData().value(QLatin1Literal("MetaData")).toObject();
			qDebug() << jsonMetaData.value(QLatin1Literal("type")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("name")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("shortname")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("version")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("author")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("description")).toString();
			}
		}
	}

W zasadzie moglibyśmy się obejść bez sekcji sprawdzania rozszerzenia plików, ale używam tego w razie, gdyby w katalogu były jeszcze jakieś inne pliki (ot, chociażby PDB).

OK, czas na crème de la crème, czyli stworzenie instancji klasy zaimplementowanej w pluginie:

void apophysis::Design::addLayer(const QString & aLayerType)
	{
	QDir pluginsDir(qApp->applicationDirPath());
	pluginsDir.cd(QLatin1Literal("plugins"));
	foreach(QString fileName, pluginsDir.entryList(QDir::Files, QDir::Name))
		{
		QString libExt;
#if defined(Q_OS_WIN)
		libExt = QLatin1Literal("dll");
#elif defined(Q_OS_MAC)
		libExt = QLatin1Literal("bundle");
#elif defined(Q_OS_LINUX)
		libExt = QLatin1Literal("so");
#endif
		if (QFileInfo(fileName).suffix().toLower() == libExt)
			{
			QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
			QString plugintype = pluginLoader.metaData().value(QLatin1Literal("MetaData")).toObject().value(QLatin1Literal("type")).toString();
			QString pluginshortname = pluginLoader.metaData().value(QLatin1Literal("MetaData")).toObject().value(QLatin1Literal("shortname")).toString();
			if ((plugintype == QLatin1Literal("Layer")) && (pluginshortname == aLayerType))
				{
				QObject *plugin = pluginLoader.instance();
				if (plugin)
					{
					apophysis::DesignLayerAPI *layer = qobject_cast<apophysis::DesignLayerAPI *>(plugin);
					if (layer)
						theLayers.append(layer);
					}
				}
			}
		}
	}

Jak widać, zarówno tworzenie, jak i używanie pluginów w tym systemie jest trywialne - i jest całkowicie przenośne.

Happy coding!

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin

Git a automatyczne budowanie Jenkinsem

Do tej pory, na cele Continuous Integration, w Jenkinsie miałem ustawione sprawdzanie repozytorium Git (opcja SCM polling) co 15 minut. W zasadzie to działało, ale bywały momenty, że owe 15 minut było okresem zbyt długim. Można oczywiście (nikt nie broni…) ustawić okres sprawdzania na * * * * *, czyli sprawdzanie co minutę, ale to również nie jest dobre rozwiązanie, z oczywistych powodów. Dlatego też postanowiłem powiesić akcję odpytywania Gita przez Jenkinsa na haku, żeby automagicznie każdy push od developera powodował start Jenkinsa.

Oczywiście, Jenkins musi być wyposażony we wtyczkę Git.

Zaczynamy od próby ręcznego zdalnego wywołania Jenkinsa. Otóż wtyczka Git otwiera takową drogę właśnie na okoliczność notyfikacji o nowym commicie. Jak czytamy w dokumentacji wtyczki, można powiadomić Jenkinsa o konkretnym commicie, ale ja na cele Continuous Integration i tak chcę pobrać najnowsze w danej chwili źródła, aby sprawdzić integrację poszczególnych prac właśnie. Dlatego użyjemy najprostszej formy wywołania wtyczki, która spowoduje wymuszenie odpytania repozytorium o zmiany.

Na początek, w konfiguracji zadania Jenkinsowego, usuwamy wszelkie terminarze, jakie mieliśmy – ale samą opcję Poll SCM musimy pozostawić włączoną (ale pustą):

Jenkins SCM Polling

Następnie, będąc na serwerze gitowym, instalujemy pakiet curl, jeśli go tam jeszcze nie ma. Gdy już go mamy, wywołujemy testową komendę:

curl http://moj.jenkins.com:8080/git/notifyCommit?url=git@moj.git.com:WspanialeRepo

Ścieżka do repozytorium powinna być dokładnie taka sama, jaką podajemy przy jego klonowaniu. Jeśli wszystko pójdzie dobrze, przeczytamy, że zostało zlecone odpytanie repozytorium. Sprawdzamy w logach Jenkinsa Git Polling Log, czy rzeczywiście tak było.

Jeśli wszystko zadziałało, czas ten proces zautomatyzować. Aby wywołać jakąś akcję po każdym pushu od developera, musimy zdefiniować hak post-receive. W katalogu repozytorium znajduje się podkatalog hooks. Tworzymy nowy plik i nadajemy mu właściwe uprawnienia:

touch post-receive
chown git:git post-receive
chmod 775 post-receive

i edytujemy go:

#!/bin/sh
curl http://moj.jenkins.com:8080/git/notifyCommit?url=git@moj.git.com:WspanialeRepo

Od tej pory, za każdym razem, gdy developer zrobi pusha, Jenkins wykona swoją robotę 🙂 A my cieszymy się z Continuous Integration 😉

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin
Google Nik Collection za darmo!

Google Nik Collection za darmo!

Wczoraj Google uderzyło z przepięknym prezentem Wielkanocnym – pakiet Google Nik Collection został pakietem… darmowym! 🙂

Jeśli jest ktoś (interesujący się fotografią), kto nie zna jeszcze tego pakietu, ten musi czym prędzej nadrobić zaległości. Pakiet składa się z:

  • Analog Efex Pro
  • Color Efex Pro
  • Silver Efex Pro
  • Viveza
  • HDR Efex Pro

oraz dwóch najważniejszych:

  • Sharpener Pro
  • Dfine

Jako szybki test, wziąłem moje niedawno wykonane zdjęcie na tapetę. Trzy zdjęcia, bracketowane co 2EV. Najpierw przepuściłem je przez RAW Pre-Sharpenera, następnie połączyłem w HDR Efex i na końcu wygładziłem w Dfine. Żadnej więcej obróbki nie stosowałem, poza eksportem do JPEGa, oczywiście 😉 Efekt poniżej.


Zachęcam do zapoznania się z pakietem, warto.

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin
Obiektyw Sigma UC ZOOM 70-210mm 1:4-5.6

Obiektyw Sigma UC ZOOM 70-210mm 1:4-5.6

Jako, że zbliża się wielkimi krokami nowy sezon występów tanecznych mojej córki, Natalki, a także wiedząc, jak wielką porażką (przynajmniej wg mnie samego) fotograficzną z tego tytułu był sezon poprzedni, postanowiłem rozejrzeć się za nowym obiektywem. Oczywiście, rozmawiamy o cenach dla ludzi, dla których fotografia to tylko hobby. Wiem, że za 2-4 tysiące mógłbym mieć wspaniałe szkło, no ale… wystarczy, że aparat tyle kosztował 😉  Jeszcze gwoli uzupełnienia tematu, ostatnio zakupiłem również monopod, który przyda się na tego typu imprezy, gdzie ze statywem nie ma się jak pchać.

Po kilku tygodniach polowań udało mi się wygrać aukcję, na której wytargałem Sigmę UC ZOOM 70-210mm 1:4-5.6 na bagnecie pentaksa za jedyne 91 zł 🙂 Zbyt wiele od niego nie oczekiwałem… dzisiaj przyszedł, więc po pracy wybrałem się z nim nad wody Odry (wystarczy wyjść z biura i już tam jestem 😉 ).

Na pierwszy ogień poszedł test bokeh. Tutaj nie miałem zbyt wielkich oczekiwań – raz, że zoom, dwa, że dość ciemny jednak (pełna dziura to zaledwie f4). I… mocno się zdziwiłem. Obiektyw ma przepiękny bokeh!

Potem poszedł test ostrości… dzisiaj, jako że z ręki strzelałem, na krótkim końcu i w okolicach (tak 70-90mm). Tutaj również obiektyw zdał test. Wychodzi na to, że za 90 zł udało mi się dostać całkiem udane szkiełko 🙂  duże toto co prawda, no i oczywiście w pełni manualne, ale mi to akurat w ogóle nie przeszkadza (gdy się uczyłem fotografii, nie istniał autofokus 😉 ).

Reasumując: za mniej, niż 100zł mam szkiełko, które potrafi dać sporo radości 🙂 czego i Wam życzę. A za dwa tygodnie dam znać, jak się toto spisuje w trudnych warunkach oświetleniowych…

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin
Dogwood 52 Week Photography Challenge

Dogwood 52 Week Photography Challenge

Z początkiem tego roku, trafiłem na ciekawy projekt fotograficzny: Dogwood 52 Week Photography Challenge. Projekt polega na tym, że są ustalone 52 tematy zdjęć, które należy wykonywać tydzień po tygodniu. Za każdym razem należy wykonać nowe zdjęcie, specjalnie na potrzeby owego projektu. W ten sposób, w miarę egzekucji, powinniśmy rozwinąć nasze zdolności postrzegania świata dookoła nas, a także wzmocnić umiejętności czysto techniczne, nauczyć się planowania fotografii itd.

Stwierdziłem, że taki projekt to ciekawa sprawa – no i przystąpiłem do niego 🙂 Aktualnie ukończyłem tydzień szósty i już myślę nad tygodniem siódmym. Poniżej możecie obejrzeć moje wypociny. Galeria poniżej będzie uaktualniana w miarę postępów.

Oprócz opisu, dostępnego pod linkiem powyżej, można znaleźć w sieci kilka miejsc, gdzie ludzie wykonujący ów challenge, publikują swoje prace, pomagając sobie nawzajem. Przekrój umiejętności uczestników jest ogromny, od totalnych początkujących, do półprofesjonalistów. Jest oficjalna grupa na Facebooku, jest półoficjalna grupa na Flickr, są i inne miejsca.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmail
twitterlinkedin