System.Drawing을 사용하여 투명한 이미지를 어떻게 그리나요?
-
06-07-2019 - |
문제
웹 페이지에 표시하기 위해 .aspx 페이지에서 투명한 GIF를 반환하려고합니다. 이미지가 투명성을 갖도록하려고 노력하고 있지만 이미지가 투명 해야하는 곳에서 검은 색이 계속됩니다.
내가 뭘 잘못하고 있는지 아는 사람 있나요?
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Load
'' Change the response headers to output a GIF image.
Response.Clear()
Response.ContentType = "image/gif"
Dim width = 110
Dim height = width
'' Create a new 32-bit bitmap image
Dim b = New Bitmap(width, height)
'' Create Grahpics object for drawing
Dim g = Graphics.FromImage(b)
Dim rect = New Rectangle(0, 0, width - 1, height - 1)
'' Fill in with Transparent
Dim tbrush = New System.Drawing.SolidBrush(Color.Transparent)
g.FillRectangle(tbrush, rect)
'' Draw Circle Border
Dim bPen = Pens.Red
g.DrawPie(bPen, rect, 0, 365)
'' Fill in Circle
Dim cbrush = New SolidBrush(Color.LightBlue)
g.FillPie(cbrush, rect, 0, 365)
'' Clean up
g.Flush()
g.Dispose()
'' Make Transparent
b.MakeTransparent()
b.Save(Response.OutputStream, Imaging.ImageFormat.Gif)
Response.Flush()
Response.End()
End Sub
해결책
불행히도 비트 맵 객체를 사용하여 투명한 GIF를 만드는 쉬운 방법은 없습니다. (보다 이 KB 기사)
대안으로 사용중인 코드와의 투명성을 지원하는 PNG 형식을 사용할 수 있습니다.
다른 팁
예, 제롬이 말했듯이, 비트 맵 객체를 사용하는 투명한 GIF를 만들 수있는 것은 없습니다. 쓰레기!
어쨌든, 나는 PNG를 생성하기 위해 코드를 변경했으며 모든 것이 예상대로 작동합니다.
PNG를 출력 스트림에 직접 쓸 수 없기 때문에 필요한 작은 작업이 있습니다. PNG를 MemoryStream에 작성한 다음 OutputStream에 작성해야했습니다.
내 구현의 최종 코드는 다음과 같습니다.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.Load
'' Change the response headers to output a JPEG image.
Response.Clear()
Response.ContentType = "image/png"
Dim width = 11
Dim height = width
'' Create a new 32-bit bitmap image
Dim b = New Bitmap(width, height)
'' Create Grahpics object for drawing
Dim g = Graphics.FromImage(b)
'' Fill the image with a color to be made Transparent after drawing is finished.
g.Clear(Color.Gray)
'' Get rectangle where the Circle will be drawn
Dim rect = New Rectangle(0, 0, width - 1, height - 1)
'' Draw Circle Border
Dim bPen = Pens.Black
g.DrawPie(bPen, rect, 0, 365)
'' Fill in Circle
Dim cbrush = New SolidBrush(Color.Red)
g.FillPie(cbrush, rect, 0, 365)
'' Clean up
g.Flush()
g.Dispose()
'' Make Transparent
b.MakeTransparent(Color.Gray)
'' Write PNG to Memory Stream then write to OutputStream
Dim ms = New MemoryStream()
b.Save(ms, Imaging.ImageFormat.Png)
ms.WriteTo(Response.OutputStream)
Response.Flush()
Response.End()
End Sub
그것은이다 가능한, 그러나 쉽지는 않습니다
프로젝트에서 안전하지 않은 코드를 사용할 수 있다면 포인터를 사용하여 색상 테이블을 찢어 투명성을 작동시키는 몇 가지 방법이 있습니다.
Bob Powell의 샘플 양식 앱은 여기에서 사용할 수 있습니다. http://www.bobpowell.net/giftransparency.htm. 나는 몇 년 전에 웹 핸들러 에서이 방법에 대한 변형을 사용하여 한 달에 약 1 천만 번 타격을 받았으며 잘 작동하는 것처럼 보였습니다.
제한된 컬러 팔레트 만 사용하는 경우 색상 테이블 처리를 필요한 색상으로 줄일 수 있습니다 (정확히 어떻게했는지 정확히 기억할 수 없습니다 ...).
즉, PNG는 메트릭 크랩로드입니다.
다음은 비트 맵에서 GIF (이미 투명성이있는) 변환 (크기를 조정하고 싶다고 함)을 갖는 코드가 있습니다. 그런 다음 투명성으로 제대로 표시 될 수 있습니다.
imagePath = System.Web.HttpContext.Current.Request.MapPath(libraryPath + reqImageFile);
System.Drawing.Image image = null;
Bitmap resizedImage = null;
if (reqWidth == 0) { reqWidth = image.Width; }
if (reqHeight == 0) { reqHeight = image.Height; }
image = System.Drawing.Image.FromFile(imagePath);
reqWidth = image.Width;
reqHeight = image.Height;
//here is the transparency 'special' treatment
resizedImage = new Bitmap(reqWidth, reqHeight, PixelFormat.Format8bppIndexed);
ColorPalette pal = resizedImage.Palette;
for (int i = 0; i < pal.Entries.Length; i++)
{
Color col = pal.Entries[i];
pal.Entries[i] = Color.FromArgb(0, col.R, col.G, col.B);
}
resizedImage.Palette = pal;
BitmapData src = ((Bitmap)image).LockBits(new Rectangle(0, 0, reqWidth, reqHeight), ImageLockMode.ReadOnly, image.PixelFormat);
BitmapData dst = resizedImage.LockBits(new Rectangle(0, 0, resizedImage.Width, resizedImage.Height),
ImageLockMode.WriteOnly, resizedImage.PixelFormat);
((Bitmap)image).UnlockBits(src);
resizedImage.UnlockBits(dst);
행운을 빕니다 !
Grégoire lafortune