Управление InkPicture - Как сохранить чернила и изображение в файл изображения
Я видел статьи, демонстрирующие, что чернила могут быть сохранены с фоновым изображением, так что чернила накладываются на изображение, а затем сохраняются как один файл изображения. Но, к сожалению, статьи, которые я видел, не содержат подробностей о том, как это делается. Я могу легко сохранить фоновое изображение с помощью следующего утверждения:
axInkPicture1.Picture.Save(@"\path\to\file.gif");
... но на фоновое изображение не накладываются чернила
Я не знаю ни одного прямого способа экономии чернил, но вот как я это делаю в настоящее время:
string tempPath = Path.GetTempPath();
string tempFile = tempPath + @"\file.gif";
// save to a temp file
if (axInkPicture1.Ink.Strokes.Count > 0)
{
byte[] bytes = (byte[])axInkPicture1.Ink.Save(InkPersistenceFormat.IPF_GIF, InkPersistenceCompressionMode.IPCM_Default);
using (MemoryStream ms = new MemoryStream(bytes))
{
using (Bitmap gif = new Bitmap(ms))
{
gif.Save(tempFile);
}
}
}
Это экономит чернила, но нет фонового изображения.
Как сохранить чернила и изображение в одном файле?
Любая помощь или указание направления приветствуется...
### РЕДАКТИРОВАТЬВот что еще я пробовал до сих пор
InkRectangle inkBox = axInkPicture1.Ink.GetBoundingBox();
byte[] gifbits = (byte[])axInkPicture1.Ink.Save(InkPersistenceFormat.IPF_GIF, InkPersistenceCompressionMode.IPCM_Default);
using (System.IO.MemoryStream buffer = new System.IO.MemoryStream(gifbits))
using (var inkImage = new Bitmap(buffer))
using (var picture = new Bitmap(axInkPicture1.Picture))
using (var g = Graphics.FromImage(picture))
{
g.DrawImage(inkImage, new Rectangle(inkBox.Left, inkBox.Right, axInkPicture1.Picture.Width, axInkPicture1.Height));
picture.Save(tempFile, System.Drawing.Imaging.ImageFormat.Gif);
}
... но мне все еще не повезло. Это сохраняет только фоновое изображение, а не чернила. Есть идеи, что я делаю не так?
заранее спасибо
2 ответа
Ооооо.... после большого стука головы и скрежета зубов, я наконец-то нашел решение своей проблемы, хотя, возможно, не то решение, которое я ожидал, и, возможно, не лучшее решение, но оно работает. Я новичок в мире C# и.net, поэтому, пожалуйста, не стесняйтесь поправлять меня, если я скажу что-нибудь глупое здесь.
Я обнаружил, что код в моем редакторе выше действительно работал, я просто не мог видеть чернила, потому что они были за пределами прямоугольника. Очевидно, прямоугольники, полученные с помощью метода GetBoundingBox(), дают вам координаты чернил в пространстве, которые значительно отличаются от координат пикселей.
Помня об этом, моей следующей целью стало преобразование координат inkSpace в координаты пикселей с использованием метода inkSpaceToPixels. Я боролся с этим некоторое время и никогда не мог понять, как это сделать, используя версию activex для inkPicure или axInkPicture. Для hdcDisplay потребовалась некоторая рукоятка, которую я никак не мог обернуть.
В конце концов, я использовал версию.net (Microsoft.Ink) из Microsoft.Ink.dll. Единственная причина, по которой я начал использовать версию ActiveX, заключалась в том, что по какой-то причине я не смог установить Windows Tablet PC SDK на свой компьютер для разработки. Он продолжал жаловаться, что для его установки мне понадобилась ОС WinXP Tablet PC. Я понял, что смог установить его на другой (Win7) ПК, а затем просто скопировать.dll с этого ПК.
Итак, вот последняя версия, которая сейчас работает... вот так!
//set the temporary file paths
string tempPath = Path.GetTempPath();
string tempFile = tempPath + @"tmpFile.png";
//get the bounding box and reference point for the ink strokes (in inkspace coordinates!)
Rectangle inkBox = inkPicture1.Ink.GetBoundingBox();
Point point = new Point(inkBox.Left, inkBox.Top);
MessageBox.Show(point.X.ToString() + ", " + point.Y.ToString());//"before" coordinates
// Convert inkspace coordinates to pixel coordinates using Renderer
Graphics tempGraphics = CreateGraphics();
Microsoft.Ink.Renderer inkRenderer = new Renderer();
inkRenderer.InkSpaceToPixel(tempGraphics, ref point);;
MessageBox.Show(point.X.ToString() + ", " + point.Y.ToString());//"after" coordinates
// Clean up
tempGraphics.Dispose();
// save the ink and background image to a temp file
if (inkPicture1.Ink.Strokes.Count > 0)
{
byte[] bytes = inkPicture1.Ink.Save(PersistenceFormat.Gif, CompressionMode.NoCompression);
using (MemoryStream ms = new MemoryStream(bytes))
{
using (Bitmap gif = new Bitmap(ms))
using (var bmp = new Bitmap(inkPicture1.BackgroundImage))
using (var g = Graphics.FromImage(bmp))
{
g.DrawImage(gif, new Rectangle(point.X, point.Y, gif.Width, gif.Height));
bmp.Save(tempFile, System.Drawing.Imaging.ImageFormat.Png);
}
}
}
Извините за длинное объяснение, но я чувствовал, что простое размещение решения без адекватного объяснения оставило бы слишком много открытых вопросов...
Я думаю, у меня недостаточно 50 репутации, чтобы комментировать, поэтому я отвечу этим комментарием для других, которые могут появиться здесь после поиска в Google, как я сделал:
Это было очень полезно. Я перевел на VB, и это сработало.
После некоторого колебания я нашел DLL по адресу:
C: \ Program Files (x86) \ Общие файлы \Microsoft Shared\Ink\Microsoft.Ink.dll
По всей видимости, я не единственный, у кого возникла проблема с поиском библиотеки DLL, так как в Google есть много записей о том, как ее получить - многие ошибаются, и большинство не так просты.
Если вы только начинаете с захвата подписи, не забудьте добавить фоновое изображение в свой элемент управления, иначе в этой строке произойдет сбой:
Использование bmp = New Bitmap(InkPicture1.BackgroundImage)