Добавление фона графики на изображение HTTP обработчика
-
26-09-2019 - |
Вопрос
Следующий код является обработчиком, который принимает проценты (проценты графа, чтобы показать как синее), максимальное (максимальное значение) и значение (номер) галлонов (число) для создания измерителя прогресса в стиле термометра. Он выводит график, который добавляется в веб-форму, как <img src="Thermometer.ashx" alt="" />
.
Поскольку этот график предназначен для демонстрации прогресса как количество галлонов в воде сохранено, было бы неплохо иметь синий цвет наполнить изображение водного бочка. Для этого я попытался добавить образ бочки с прозрачным интерьером в веб-форму и попытался расположить его перед изображением термометра, но это не сработало, так как кажется невозможным слой изображения поверх одного созданного обработчик.
Мой вопрос в том, возможно, можно ли добавить образ бочки через код, чтобы служить контуром для синего термометра? Или изображение бочка должна быть создана с нуля в коде? Я боюсь последнего, так как я, наверное, не могу в нее кодировать.
Пожалуйста, смотрите ниже и дайте мне знать, если есть что-нибудь, что я могу сделать.
Благодарю вас!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Drawing;
using System.Net;
using System.Drawing.Imaging;
using System.Web.UI.HtmlControls;
namespace rainbarrel
{
public class Thermometer : IHttpHandler
{
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
int Percent = 25;
int Max = 20000;
bool Gallon = true;
float Pixels = (float)Percent * 2.15f;
Bitmap TempImage = new Bitmap(200, 250);
Graphics TempGraphics = Graphics.FromImage(TempImage);
TempGraphics.FillRectangle(Brushes.White, new Rectangle(0, 0, 200, 250));
Pen TempPen = new Pen(Color.Black);
BarrelFill(TempImage, Percent);
bool DrawText = true;
float Amount = Max;
for (float y = 20.0f; y < 235.0f; y += 10.75f)
{
TempGraphics.DrawLine(TempPen, 119, y, 125, y);
if (DrawText)
{
Font TempFont = new Font("Arial", 8.0f, FontStyle.Regular);
if (Gallon)
{
TempGraphics.DrawString(Amount.ToString() + " Gal", TempFont, Brushes.Black, 130, y);
}
else
{
TempGraphics.DrawString(Amount.ToString(), TempFont, Brushes.Black, 130, y);
}
DrawText = false;
}
else DrawText = true;
Amount -= ((Max / 100) * 5.0f);
}
string etag = "\"" + Percent.GetHashCode() + "\"";
string incomingEtag = context.Request.Headers["If-None-Match"];
context.Response.Cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(1));
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetMaxAge(new TimeSpan(7, 0, 0, 0));
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
context.Response.Cache.SetETag(etag);
if (String.Compare(incomingEtag, etag) == 0)
{
context.Response.StatusCode = (int)HttpStatusCode.NotModified;
context.Response.End();
}
else
{
context.Response.ContentType = "image/Gif";
TempImage.Save(context.Response.OutputStream, ImageFormat.Gif);
TempImage.MakeTransparent();
}
}
private void BarrelFill(Bitmap TempImage, int Percent)
{
if (Percent == 100)
{
FillRectangle(TempImage, 60, 20, 235);
}
else
{
FillRectangle(TempImage, 60, (int)(235.0f - ((float)Percent * 2.15f)), 235);
}
}
private void FillRectangle(Bitmap TempImage, int x, int y1, int y2)
{
int MaxDistance = 50;
for (int i = x - MaxDistance; i < x + MaxDistance; ++i)
{
for (int j = y1; j < y2; ++j)
{
float Distance = (float)Math.Abs((i - x));
int BlueColor = (int)(255.0f * (1.0 - (Distance / (2.0f * MaxDistance))));
TempImage.SetPixel(i, j, Color.FromArgb(30, 144, BlueColor));
}
}
}
}
}
ОБНОВИТЬ:
Я нашел этот пост здесь, который показал мне, как решить:Наложение изображений с GDI +
Вот мое решение:
Image Barrel = Image.FromFile("C:\\Inetpub\\wwwroot\\barrel\\barrel_trans.png");
TempGraphics.DrawImage(Barrel, -5, 0, 120, 240);
Barrel.Dispose();
Однако качество слоя PNG плохого (слегка размытия), хотя оригинал очень острый и понятный. Есть ли способ сохранить качество изображения оригинала?
Спасибо заранее за вашу помощь.
Решение
Изменение TempImage.Save(context.Response.OutputStream, ImageFormat.gif);
к JPEG решил проблему качества.
Другие советы
Я считаю, что лучший способ достичь этого, будет создать все изображение в C # и отправить это. Вы можете получить точное позиционирование ствола над «термометром», и если баррель уже является (полу) прозрачный PNG, вы можете просто сделать .drawImage прямо над термостатом, добавить текст и сделать все, что вы хотите, прежде чем отправить обратно окончательное изображение непосредственно в отзывю.
Пару других предложений для вас:
Поскольку вы передаете все непосредственно в своем острубеке, вы должны утилизировать свои собственные внутренние одноразовые ресурсы. «Использование блоков - самый простой способ. Вам понадобится по крайней мере эти два:
using (Graphics TempGraphics = GetGraphicsFromBitmap(TempImage))
{
for (float y = 20.0f; y < 235.0f; y += 10.75f)
{
TempGraphics.DrawLine(TempPen, 119, y, 125, y);
...
}
}
и
using (Font TempFont = new Font("Arial", 8.0f, FontStyle.Regular))
{
...
}