絵文字をImageに描画する方法
やまじいさん 2024/10/12(Sat) 16:49
Reputeless 2024/10/16(Wed) 11:50
Image は縮小回転しての書き込みができないため、レンダーテクスチャを使うのが良いです。
# include <Siv3D.hpp> // Siv3D v0.6.15
void Main()
{
// キャンバスのサイズ
constexpr Size CanvasSize{ 600, 600 };
// レンダーテクスチャ
const MSRenderTexture renderTexture{ CanvasSize, ColorF{ 1.0 } };
// 絵文字
const Texture emoji{ U"🐈"_emoji };
while (System::Update())
{
// レンダーテクスチャに描画する
{
const ScopedRenderTarget2D target{ renderTexture };
if (MouseL.down())
{
emoji.scaled(0.5).drawAt(Cursor::Pos());
}
}
// レンダーテクスチャをリゾルブする
{
Graphics2D::Flush();
renderTexture.resolve();
}
// 保存ボタン
if (SimpleGUI::Button(U"Save", Vec2{ 640, 40 }))
{
Image image;
renderTexture.readAsImage(image);
image.saveWithDialog();
}
// レンダーテクスチャを描画する
renderTexture.draw();
}
}
やまじいさん 2024/10/16(Wed) 15:38
回答いただきありがとうございます。
Imageに絵文字を描くことはできないという理解でよろしいでしょうか。
Imageに描画した画像と絵文字を混在させるようにしたいと思っています。
いただいたコードを修正し、左クリックで絵文字を表示、右ドラッグで直線を描くようにしてみました。
条件コンパイルの#ifの部分にあるようにしてみたのですが、絵文字を描くたびに線が消えてしまいます。
ScopedRenderTarget2Dで設定されたターゲットのテクスチャが、スコープを超えてもそのままになっている気がします。
どのようにしたらいいでしょうか。
# include <Siv3D.hpp> // Siv3D v0.6.15
void Main()
{
Size CanvasSize = Window::DefaultClientSize;
// レンダーテクスチャ
const MSRenderTexture renderTexture{ CanvasSize, ColorF{ 1.0 } };
// 絵文字
const Texture emoji{ U"🐈"_emoji };
Image img(CanvasSize, Palette::White);
DynamicTexture tx;
Point p1, p2;
while (System::Update())
{
tx.fill(img);
tx.draw();
// レンダーテクスチャに描画する
{
const ScopedRenderTarget2D target{ renderTexture };
if (MouseL.down())
{
emoji.drawAt(Cursor::Pos());
}
}
//{ <-- 削除しても問題ないでしょうか
Graphics2D::Flush();
renderTexture.resolve();
//}
if (MouseL.up())
{
Image image;
renderTexture.readAsImage(image);
image.overwrite(img, 0, 0);
}
if (MouseR.down()) p1 = p2 = Cursor::Pos();
else if (MouseR.pressed())
{
p2 = Cursor::Pos();
Line(p1, p2).draw(10, Palette::Aqua);
}
else if (MouseR.up())
{
#if 1 // 絵文字を描くと消えてしまいます
Line(p1, p2).overwrite(img, 10, Palette::Aqua);
#else // 以下のようにすると線は消えません
{
const ScopedRenderTarget2D target{ renderTexture };
Line(p1, p2).draw(10, Palette::Aqua);
}
{
Graphics2D::Flush();
renderTexture.resolve();
}
Image tmp;
renderTexture.readAsImage(tmp);
tmp.overwrite(img, 0, 0);
#endif
}
// レンダーテクスチャを描画する
// renderTexture.draw();
}
}
Reputeless 2024/10/16(Wed) 17:57
そのコードは、img にいくら線を引いたとしても、
if (MouseL.up())
{
Image image;
renderTexture.readAsImage(image);
image.overwrite(img, 0, 0);
}
の箇所で、レンダーテクスチャの中身 image で img を完全に上書きしているので、線が消えるのは正しい動作です。
Image は Image に対して回転や縮小しての描画ができません。
絵文字を使いたい場合、Image や DynamicTexture は一切使わず、すべてレンダーテクスチャで完結させるのが簡単です。
↓ はマウス右ボタンで線を引けるようにしたコードです。レンダーテクスチャだけで完結させると簡単になることがわかると思います。
# include <Siv3D.hpp> // Siv3D v0.6.15
void Main()
{
// キャンバスのサイズ
constexpr Size CanvasSize{ 600, 600 };
// レンダーテクスチャ
const MSRenderTexture renderTexture{ CanvasSize, ColorF{ 1.0 } };
// 絵文字
const Texture emoji{ U"🐈"_emoji };
while (System::Update())
{
// レンダーテクスチャに描画する
{
const ScopedRenderTarget2D target{ renderTexture };
if (MouseL.down()) // 絵文字スタンプ
{
emoji.scaled(0.5).rotated(Random(2_pi)).drawAt(Cursor::Pos());
}
if (MouseR.pressed()) // 線を引く
{
const Point from = (MouseR.down() ? Cursor::Pos() : Cursor::PreviousPos());
const Point to = Cursor::Pos();
Line{ from, to }.draw(LineStyle::RoundCap, 8, Palette::Orange);
}
}
// レンダーテクスチャをリゾルブする
{
Graphics2D::Flush();
renderTexture.resolve();
}
// 保存ボタン
if (SimpleGUI::Button(U"Save", Vec2{ 640, 40 }))
{
Image image;
renderTexture.readAsImage(image);
image.saveWithDialog();
}
// レンダーテクスチャを描画する
renderTexture.draw();
}
}