Задача - штамповать разные изображения на полотно. Вот только размер полотна заранее неизвестен. Штампую при помощи Graphics
var bmp = new Bitmap(1, 1);
var g = Graphics.FromImage(bmp);
g.DrawImage(someImage, 0,0, someImage.Width,someImage.Height);
Последнее действие может быть не единственным. То есть мне может понадобиться вставить много картинок, текста и еще хрен знает чего. И при этом я не хочу заморачиваться вычислением размера картинки. Есть ли для этого автоматические средства?
Скорее всего велосипед, но раз решений не предложили, изобрел сам. Вдруг кому пригодится.
Вот класс самой канвы.
public class InfinityCanvas
{
List<ImageLayer> _layers { get; } = new List<ImageLayer>();
int _minLeftTopX = int.MaxValue;
int _minLeftTopY = int.MaxValue;
int _maxRightBottomX = int.MinValue;
int _maxRightBottomY = int.MinValue;
public void AddImage(Image image, Point position)
{
AddImage(image, position.X, position.Y);
}
public void AddImage(Image image, int x, int y)
{
_layers.Add(new ImageLayer(image, x, y));
if (_minLeftTopX >= x)
_minLeftTopX = x;
if (_minLeftTopY >= y)
_minLeftTopY = y;
if (_maxRightBottomX <= x + image.Width)
_maxRightBottomX = x + image.Width;
if (_maxRightBottomY <= y + image.Height)
_maxRightBottomY = y + image.Height;
}
public Image GetResult()
{
if (_layers.Count == 0)
{
var b = new Bitmap(1, 1);
return b;
}
var res = new Bitmap(_maxRightBottomX - _minLeftTopX, _maxRightBottomY - _minLeftTopY);
var g = Graphics.FromImage(res);
for (var i = 0; i < _layers.Count; i++)
{
var lay = _layers[i];
g.DrawImage(lay.Image, lay.LeftTopX - _minLeftTopX, lay.LeftTopY - _minLeftTopY, lay.Image.Width, lay.Image.Height);
}
return res;
}
}
Вот класс слоя
class ImageLayer
{
public Image Image { get; set; }
public int LeftTopX { get; set; }
public int LeftTopY { get; set; }
public ImageLayer(Image image, int x, int y)
{
Image = image;
LeftTopX = x;
LeftTopY = y;
}
}
Вот так используем
var ic = new InfinityCanvas();
ic.AddImage(someImage, -100, -100);
ic.AddImage(someImage, someImage.Width, someImage.Height);
ic.GetResult().Save("1.png");
В результате получаем рисунок, в левом верхнем и в правом нижнем углах которого изображение, содержащееся в someImage
. Между изображениями расстояние 100 по обоим осям.
Вы можете создать достаточно большое полотно, к примеру 10000 на 10000 пикселей и рисовать на нем сколько нужно. Затем обрезаете ненужную часть(и) с помощью этого:
static Bitmap TrimBitmap(Bitmap source)
{
Rectangle srcRect = default(Rectangle);
BitmapData data = null;
try
{
data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] buffer = new byte[data.Height * data.Stride];
Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);
int xMin = int.MaxValue;
int xMax = 0;
int yMin = int.MaxValue;
int yMax = 0;
for (int y = 0; y < data.Height; y++)
{
for (int x = 0; x < data.Width; x++)
{
byte alpha = buffer[y * data.Stride + 4 * x + 3];
if (alpha != 0)
{
if (x < xMin) xMin = x;
if (x > xMax) xMax = x;
if (y < yMin) yMin = y;
if (y > yMax) yMax = y;
}
}
}
if (xMax < xMin || yMax < yMin)
{
// Image is empty...
return null;
}
srcRect = Rectangle.FromLTRB(xMin, yMin, xMax, yMax);
}
finally
{
if (data != null)
source.UnlockBits(data);
}
Bitmap dest = new Bitmap(srcRect.Width, srcRect.Height);
Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);
using (Graphics graphics = Graphics.FromImage(dest))
{
graphics.DrawImage(source, destRect, srcRect, GraphicsUnit.Pixel);
}
return dest;
}
Как правильно протестировать Data access layer с помощью Mock, а именно репозитории, предоставляющие доступ к базе данных через контекст?
Хоть и есть несколько статей на хабре, есть реализация на C++, не могу понять как переделать это под С#Может быть вдруг кто-то реализовал?
Добрый день! Мне нужно получить gmail письма пользователяПрограмма открывает ссылку авторизации в WebBrowser, пользователь входит, я получаю код