Radek Chalupa   konzultace a školení programování, vývoj software na zakázku

Grafický editor využívající ImageMagick a gtkmm - 3. část

28.2.2019

V tomto prozatím závěrečném článku miniseriálu o knihovně ImageMagick, resp. Magick++ si přidáme ukázku zápisu textu do obrázku a také přidání vlastního popisu/komentáře do souboru s obrázkem.

Přidání popisu do souboru

Pro přidání nebo změnu existujícího popisu/komentáře (přímo do souboru s obrázkem) slouží metoda comment třídy Image, která má parametr (požadovaný text) typu std::string.

Obsah aktuálního komentáře zjistíme pomocí metody attribute s parametrem "comment", která vrátí stávající komentář jako std::string.

V našem ukázkovém projektu si pod oblast s obrázkem přidáme widget typu Gtk::ScrolledWindow a do něj Gtk::TextView, do kterého při načtení obrázku nastavíme (pokud existuje) stávající komentář a při uložení obrázku pak použijeme jako komentář text aktuálně nastavení v TextView.

Metodu nacist_soubor si rozšíříme o nastavení aktuálního komentáře do TextView.

void OknoHlavni::nacist_soubor(const char* soubor) noexcept
{
	try
	{
		_obrazek.nacist(soubor);
		_nacteny_soubor = soubor;
		_oblast_obrazku.set_pixbuf(_obrazek.get_pixbuf());
		_tv_popis.get_buffer()->set_text(_obrazek.get_image()->attribute("comment"));
	}
	catch (std::exception& ex)
	{
		zprava_chyba(ex.what());
	}
}

Při ukládání souboru pak upravíme obsluhu signálu on_soubor_ulozit a on_soubor_ulozit_jako:

void OknoHlavni::on_soubor_ulozit() noexcept
{
	_obrazek.get_image()->comment(_tv_popis.get_buffer()->get_text());
	_obrazek.get_image()->write(_nacteny_soubor.c_str());
}

void OknoHlavni::on_soubor_ulozit_jako() noexcept
{
	if (!_obrazek.je_nacten())
		return;
	Gtk::FileChooserDialog dialog("Uložit obrázek",
          Gtk::FILE_CHOOSER_ACTION_SAVE);
	dialog.set_transient_for(*this);
	dialog.add_button("_Zrušit", Gtk::RESPONSE_CANCEL);
	dialog.add_button("Uložit", Gtk::RESPONSE_OK);
	auto filtr = Gtk::FileFilter::create();
	filtr->set_name("Obrázky");
	filtr->add_mime_type("image/jpeg");
	filtr->add_mime_type("image/tiff");
	filtr->add_mime_type("image/gif");
	dialog.add_filter(filtr);
	int result = dialog.run();
	if (Gtk::RESPONSE_OK != result)
		return;
	std::string str_soubor = dialog.get_filename();
	_obrazek.get_image()->comment(_tv_popis.get_buffer()->get_text());
	_obrazek.get_image()->write(str_soubor.c_str());
}

Zápis textu do obrázku

Pro zápis textu do obrázku slouží metoda annotate, která má více variant ve kterých můžeme kromě vlastního textu nastavit jeho umístění v obrázku. Podrobnější popis samozřejmě lze nalézt v dokumentaci. My zde použijeme variantu která má jako 2. parametr (tím prvním je vždy požadovaný text) jednu z hodnot typu Magick::GravityType, kterou určíme některou stranu či roh obrázku, konkrétně například Magick::SouthEastGravity, která určuje (jak název napovídá těm kteří znají orientaci map podle světových stran :-)) pravý dolní roh.

Pro určení některých parametrů textu máme k disposici další členské funkce třídy Image. My zde použijeme metodu fillColor pro nastavení barvy písma a fontPointSize pro velikost písma.

Do projektu jsem přidal další položku menu a její obsluhu, která vypadá takto:

void OknoHlavni::on_zapsat_text() noexcept
{
	std::string str = "Nějaký testovací text";
	_obrazek.get_image()->fillColor("#d00000");
	_obrazek.get_image()->fontPointsize(50.0);
	_obrazek.get_image()->annotate(str, Magick::SouthEastGravity);
	_obrazek.aktualizovat_data();
	_oblast_obrazku.set_pixbuf(_obrazek.get_pixbuf());
}

Projekt (v CodeLite) si můžete stáhnout v příloze níže.