画像パターンの塗り
画像パターンをタイル状に敷き詰める方法です。
画像を使って塗りつぶしを行う場合、縮尺の設定や回転のしてなど座標変換が必要になります。
座標変換の詳細は別の投稿にまとめますのでこちらでの設定内容は簡単な説明のみとなります。
class SvgImage
{
public:
+ LPCTSTR AddImagePattern(BYTE* pbSrc, DWORD dwSrcLength, int nWidth, int nHeight,
+ double dScaleX, double dScaleY, mdPoint pn, int nDegree,
+ int nDepth = 0);
}
//
LPCTSTR SvgImage::AddImagePattern(BYTE* pbSrc, DWORD dwSrcLength,
int nWidth, int nHeight, double dScaleX, double dScaleY, mdPoint pn,
int nDegree, int nDepth)
{
CString patternName;
SvgTag* svgDefs = new SvgTag();
svgDefs->m_strName = L"defs";
svgDefs->m_nDepth = nDepth + 1;
svgDefs->m_bOne = FALSE;
m_arrayTag.Add(svgDefs);
SvgTag* svgPattern = new SvgTag();
svgPattern->m_strName = L"pattern";
svgPattern->m_nDepth = nDepth + 2;
svgPattern->m_bOne = FALSE;
svgPattern->m_arrAttr.Add(L"id");
patternName.Format(L"pattern99-%d", m_nPattern);
m_nPattern++;
svgPattern->m_arrAttrValue.Add(patternName);
CString name = patternName;
wstring wstrName = static_cast<wstring>(name.GetBuffer());
m_hashPattern.insert(std::make_pair(wstrName, m_arrayTag.GetSize()));
svgPattern->m_arrAttr.Add(L"patternUnits");
svgPattern->m_arrAttrValue.Add(L"userSpaceOnUse");
svgPattern->m_arrAttr.Add(L"patternContentUnits");
svgPattern->m_arrAttrValue.Add(L"userSpaceOnUse");
svgPattern->m_arrAttr.Add(L"patternTransform");
CString strTransform;
strTransform.Format(L"rotate(%d)scale(%.03lf,%.03lf)",
-nDegree, dScaleX, -dScaleY);
svgPattern->m_arrAttrValue.Add(strTransform);
svgPattern->m_arrAttr.Add(L"x");
svgPattern->m_arrAttrValue.Add(L"0");
svgPattern->m_arrAttr.Add(L"y");
svgPattern->m_arrAttrValue.Add(L"0");
svgPattern->m_arrAttr.Add(L"width");
CString strWidth;
strWidth.Format(L"%d", nWidth);
svgPattern->m_arrAttrValue.Add(strWidth);
svgPattern->m_arrAttr.Add(L"height");
CString strHeight;
strHeight.Format(L"%d", nHeight);
svgPattern->m_arrAttrValue.Add(strHeight);
m_arrayTag.Add(svgPattern);
mdSvgTag* svgImageTag = new mdSvgTag();
svgImageTag->m_strName = L"image";
svgImageTag->m_nDepth = nDepth + 3;
svgImageTag->m_bOne = TRUE;
svgImageTag->m_arrAttr.Add(L"x");
svgImageTag->m_arrAttrValue.Add(L"0");
svgImageTag->m_arrAttr.Add(L"y");
svgImageTag->m_arrAttrValue.Add(L"0");
svgImageTag->m_arrAttr.Add(L"width");
svgImageTag->m_arrAttrValue.Add(strWidth);
svgImageTag->m_arrAttr.Add(L"height");
svgImageTag->m_arrAttrValue.Add(strHeight);
// 画像データの埋め込み
bool bResult = false;
DWORD dwDestLength = 0;
LPTSTR psDest = NULL;
CString strBase64;
if (CryptBinaryToString(pbSrc, dwSrcLength, CRYPT_STRING_BASE64,
NULL, &dwDestLength) == TRUE)
{
psDest = new TCHAR[dwDestLength + 1];
if (CryptBinaryToString(pbSrc, dwSrcLength, CRYPT_STRING_BASE64,
psDest, &dwDestLength) == TRUE)
{
strBase64 = CString(psDest);
bResult = true;
}
delete psDest;
}
CString strSrc;
strSrc.Format(L"data:image/png;base64,%s", static_cast<LPCWSTR>(strBase64));
svgImageTag->m_arrAttr.Add(L"xlink:href");
svgImageTag->m_arrAttrValue.Add(strSrc);
m_arrayTag.Add(svgImageTag);
return patternName;
}
defs タグを作成します。
SvgTag* svgDefs = new SvgTag();
svgDefs->m_strName = L"defs";
svgDefs->m_nDepth = nDepth + 1;
svgDefs->m_bOne = FALSE;
m_arrayTag.Add(svgDefs);
pattern タグを用意します。
ここまでは塗パターンと同じです。
SvgTag* svgPattern = new SvgTag();
svgPattern->m_strName = L"pattern";
svgPattern->m_nDepth = nDepth + 2;
svgPattern->m_bOne = FALSE;
svgPattern->m_arrAttr.Add(L"id");
patternName.Format(L"pattern99-%d", m_nPattern);
m_nPattern++;
svgPattern->m_arrAttrValue.Add(patternName);
CString name = patternName;
wstring wstrName = static_cast<wstring>(name.GetBuffer());
m_hashPattern.insert(std::make_pair(wstrName, m_arrayTag.GetSize()));
svgPattern->m_arrAttr.Add(L"patternUnits");
svgPattern->m_arrAttrValue.Add(L"userSpaceOnUse");
svgPattern->m_arrAttr.Add(L"patternContentUnits");
svgPattern->m_arrAttrValue.Add(L"userSpaceOnUse");
画像の傾きの調整を座標変換にて行います。
宣言の順番が変わると綺麗にタイル状に配置できなくなることがあるためご注意ください。
svgPattern->m_arrAttr.Add(L"patternTransform");
CString strTransform;
strTransform.Format(L"rotate(%d)scale(%.03lf,%.03lf)",
-nDegree, dScaleX, -dScaleY);
svgPattern->m_arrAttrValue.Add(strTransform);
縦横の幅は元画像と同じサイズを入れます。
svgPattern->m_arrAttr.Add(L"x");
svgPattern->m_arrAttrValue.Add(L"0");
svgPattern->m_arrAttr.Add(L"y");
svgPattern->m_arrAttrValue.Add(L"0");
svgPattern->m_arrAttr.Add(L"width");
CString strWidth;
strWidth.Format(L"%d", nWidth);
svgPattern->m_arrAttrValue.Add(strWidth);
svgPattern->m_arrAttr.Add(L"height");
CString strHeight;
strHeight.Format(L"%d", nHeight);
svgPattern->m_arrAttrValue.Add(strHeight);
image タグを作成します。
mdSvgTag* svgImageTag = new mdSvgTag();
svgImageTag->m_strName = L"image";
svgImageTag->m_nDepth = nDepth + 3;
svgImageTag->m_bOne = TRUE;
svgImageTag->m_arrAttr.Add(L"x");
svgImageTag->m_arrAttrValue.Add(L"0");
svgImageTag->m_arrAttr.Add(L"y");
svgImageTag->m_arrAttrValue.Add(L"0");
svgImageTag->m_arrAttr.Add(L"width");
svgImageTag->m_arrAttrValue.Add(strWidth);
svgImageTag->m_arrAttr.Add(L"height");
svgImageTag->m_arrAttrValue.Add(strHeight);
「MFC から SVG の画像」で説明したものと同じ方法で画像データの埋め込みを行います。
// 画像データの埋め込み
bool bResult = false;
DWORD dwDestLength = 0;
LPTSTR psDest = NULL;
CString strBase64;
if (CryptBinaryToString(pbSrc, dwSrcLength, CRYPT_STRING_BASE64,
NULL, &dwDestLength) == TRUE)
{
psDest = new TCHAR[dwDestLength + 1];
if (CryptBinaryToString(pbSrc, dwSrcLength, CRYPT_STRING_BASE64,
psDest, &dwDestLength) == TRUE)
{
strBase64 = CString(psDest);
bResult = true;
}
delete psDest;
}
CString strSrc;
strSrc.Format(L"data:image/png;base64,%s", static_cast<LPCWSTR>(strBase64));
svgImageTag->m_arrAttr.Add(L"xlink:href");
svgImageTag->m_arrAttrValue.Add(strSrc);
m_arrayTag.Add(svgImageTag);