У меня есть магазин электронной коммерции, созданный в asp.net С# (Webforms), и многие новые изображения продукта очень труднодоступны, поэтому я хотел бы пометить их своим логотипом или доменным именем.
Слишком много продуктов, чтобы просто загружать изображения и добавлять водяные знаки, а пользователи с ограниченным опытом редактирования изображений будут загружать новые (поэтому они не будут иметь понятия, как добавить водяной знак).
Итак, я думаю, это просто оставляет меня с помощью HttpHandler? Да нет? Если это так, вы можете дать некоторое представление (предпочтительно примеры кода на С#) в наиболее эффективный способ добавления водяного знака, учитывая, что на некоторых страницах будет около 20 изображений (Jpegs) на (Все из которых должны быть помечены водяным знаком)
Ответ 1
Я бы получил объект Graphics
в jpeg, а затем нарисовал водяной знак поверх этого элемента и сохранил его снова с помощью водяного знака:
using (Image image = Image.FromFile("myImage.jpg"))
using(Graphics g = Graphics.FromImage( image)){
g.DrawImage( myWaterMarkImage, myPosition);
image.Save(myFilename);
}
Ответ 2
Похоже, что это может быть полезно:
http://www.switchonthecode.com/tutorials/csharp-snippet-tutorial-how-to-draw-text-on-an-image
Пока он фокусируется на тексте, я уверен, что с небольшим изменением вы также можете добавить графику.
После реализации вы можете либо вызывать его один раз для просмотра, либо добавлять его перед сохранением файла.
Ответ 3
Вот пример HttpHandler
/// <summary>
/// Summary description for $codebehindclassname$
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class ImageHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string imageName = string.Empty;
string physicalPath = string.Empty;
Image image = null;
Image thumbnailImage = null;
Bitmap bitmap = null;
using (MemoryStream memoryStream = new MemoryStream())
{
string actionName = context.Request.QueryString["Image"];
string opacity = context.Request.QueryString["Opacity"];
int opacityPercent = int.Parse(opacity);
Color waterMarkColor = Color.Gray;
switch (actionName)
{
case "BlueHills":
string myCompany = "My Company Name";
Font font = new Font("Times New Roman", 8f);
context.Response.ContentType = "image/png";
bitmap = Resources.Resources.BlueHills;
Graphics g = Graphics.FromImage(bitmap);
Brush myBrush = new SolidBrush(Color.FromArgb(opacityPercent, waterMarkColor));
SizeF sz = g.MeasureString(myCompany, font);
int X = (int)(bitmap.Width - sz.Width) / 2;
int Y = (int)(sz.Height) / 2;
g.DrawString(myCompany, font, myBrush, new Point(X, Y));
bitmap.Save(memoryStream, ImageFormat.Png);
break;
default:
string test = actionName;
break;
}
context.Response.BinaryWrite(memoryStream.GetBuffer());
memoryStream.Close();
if (image != null) { image.Dispose(); }
if (thumbnailImage != null) { thumbnailImage.Dispose(); }
if (bitmap != null) { bitmap.Dispose(); }
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
и может быть вызвана так:
<asp:Image ID="Image1" runat="server" ImageUrl="~/ImageHandler.ashx?Image=BlueHills&Opacity=50" />
Ответ 4
Я предлагаю вам взглянуть на классы WPF для выполнения этой задачи (GDI + устарели в веб-контексте).
Путь (я не знаю, является ли ЛУЧШИЙ способ, но я уже сделал это и прекрасно работает) что-то похожее на:
// Load the original image
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(physical_imagepath);
image.EndInit();
// Create a final render image
RenderTargetBitmap final = new RenderTargetBitmap(yourNeededWidth, yourNeededHeight, yourDpiDefault, yourDpiDefault, PixelFormats.Default);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
Rect rectImage = new Rect(0, 0, (double)image.PixelWidth, (double)image.PixelHeight);
dc.DrawImage(image, rectImage);
// Load the bitmap of the watermark
BitmapImage watermark = new BitmapImage();
watermark.BeginInit();
watermark.CacheOption = BitmapCacheOption.OnLoad;
watermark.UriSource = new Uri(physical_logopath);
watermark.EndInit();
// Defines the watermark box
Rect rectWatermark = new Rect(0, 0, (double)watermark.PixelWidth, (double)watermark.PixelHeight);
/* use rectWatermark.X and rectWatermark.Y to move your watermark box around on the final image */
dc.DrawImage(watermark, rectWatermark);
}
final.Render(dv);
// And then serve the final Bitmap to the client
Конечно, все написано как HttpHandler.
Код выше не проверен.
(небольшие объявления: я опубликовал ItemCanyon Item, которые выполняют аналогичную работу).
Ответ 5
Это не ответ, а несколько советов:
- Jpeg не поддерживает прозрачность, лучшее, что вы, вероятно, можете сделать, это добавить изображение водяного знака и сделать его очень светло-серым.
- Используйте общий обработчик (.ashx), он очень легкий и не позволяет вам добавлять что-либо в ваш файл web.config.
- Если на странице будет больше 20 изображений, тогда я бы рекомендовал добавить водяной знак, когда вы получите изображения. Это одноразовая стоимость за изображение и ускорит загрузку страниц с изображениями.
Я не могу ручаться за наиболее эффективный способ добавления водяного знака, но если вы идете с подсказкой № 3, это становится менее важным, поскольку вы будете выполнять операцию только один раз за изображение. Я бы просто использовал пространство имен System.Drawing, чтобы это сделать; просто убедитесь, что вы используете ресурсы, которые вы используете (изображение, графика и т.д.), хотя я уверен, что там есть библиотеки, которые будут работать намного лучше.
Ответ 6
Очевидная оптимизация любого "на лету" означает кеширование "водяного знака", если вы можете позволить себе стоимость хранения. Таким образом, эффективность операции по рандомизации не имеет большого значения.