C# 使用C语言调整透明图像的大小#

C# 使用C语言调整透明图像的大小#,c#,.net,image,resize,image-scaling,C#,.net,Image,Resize,Image Scaling,有没有人有秘密的公式来调整透明图像(主要是GIF)的大小而不损失任何质量-究竟是什么 我试过很多东西,但我得到的最接近的还不够好 看看我的主要形象: 然后缩放图像: //索引彩色图像的内部调整大小 void IndexedRezise(int-xSize,int-ySize) { 位图数据源数据; BitmapData目标数据; 调整尺寸(参考X尺寸,参考Y尺寸); scaledBitmap=新位图(xSize、ySize、Bitmap.PixelFormat); scaledBitmap.

有没有人有秘密的公式来调整透明图像(主要是GIF)的大小而不损失任何质量-究竟是什么

我试过很多东西,但我得到的最接近的还不够好

看看我的主要形象:

然后缩放图像:

//索引彩色图像的内部调整大小
void IndexedRezise(int-xSize,int-ySize)
{
位图数据源数据;
BitmapData目标数据;
调整尺寸(参考X尺寸,参考Y尺寸);
scaledBitmap=新位图(xSize、ySize、Bitmap.PixelFormat);
scaledBitmap.Palette=位图.Palette;
sourceData=bitmap.LockBits(新矩形(0,0,bitmap.Width,bitmap.Height),
ImageLockMode.ReadOnly,位图.PixelFormat);
尝试
{
targetData=scaledBitmap.LockBits(新矩形(0,0,xSize,ySize),
ImageLockMode.WriteOnly、scaledBitmap.PixelFormat);
尝试
{
xFactor=(双)bitmap.Width/(双)scaledBitmap.Width;
yFactor=(双)bitmap.Height/(双)scaledBitmap.Height;
sourceStride=sourceData.Stride;
sourceScan0=sourceData.Scan0;
int targetStride=targetData.Stride;
System.IntPtr targetScan0=targetData.Scan0;
不安全的
{
字节*p=(字节*)(空*)targetScan0;
int nOffset=targetStride-scaledBitmap.Width;
int nWidth=缩放位图的宽度;
对于(int y=0;y<缩放位图.Height;++y)
{
对于(int x=0;x
我正在使用上面的代码来进行索引大小调整


有人有改进的想法吗?

我认为问题在于,你正在进行基于扫描线的调整,无论你如何努力调整,这都会导致锯齿状。良好的图像调整质量要求您做更多的工作来计算调整大小后的像素覆盖的预调整像素的平均颜色

这个网站的负责人有一篇博客文章讨论了一些图像大小调整算法。您可能需要一个双三次图像缩放算法


这是一个基本的调整大小功能,我已经在一些利用GDI的应用程序中使用过+

/// <summary>
///    Resize image with GDI+ so that image is nice and clear with required size.
/// </summary>
/// <param name="SourceImage">Image to resize</param>
/// <param name="NewHeight">New height to resize to.</param>
/// <param name="NewWidth">New width to resize to.</param>
/// <returns>Image object resized to new dimensions.</returns>
/// <remarks></remarks>
public static Image ImageResize(Image SourceImage, Int32 NewHeight, Int32 NewWidth)
{
   System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(NewWidth, NewHeight, SourceImage.PixelFormat);

   if (bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format1bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format4bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format8bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Undefined | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.DontCare | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format16bppArgb1555 | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format16bppGrayScale) 
   {
      throw new NotSupportedException("Pixel format of the image is not supported.");
   }

   System.Drawing.Graphics graphicsImage = System.Drawing.Graphics.FromImage(bitmap);

   graphicsImage.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality;
   graphicsImage.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
   graphicsImage.DrawImage(SourceImage, 0, 0, bitmap.Width, bitmap.Height);
   graphicsImage.Dispose();
   return bitmap; 
}
//
///使用GDI+调整图像大小,使图像在所需大小下美观清晰。
/// 
///要调整大小的图像
///要调整大小的新高度。
///要调整大小的新宽度。
///图像对象已调整为新尺寸。
/// 
公共静态图像大小调整(图像源图像,Int32 NewHeight,Int32 NewWidth)
{
System.Drawing.Bitmap Bitmap=新的System.Drawing.Bitmap(新宽度、新高度、SourceImage.PixelFormat);
如果(bitmap.PixelFormat==Drawing.Imaging.PixelFormat.Format1bppIndexed | bitmap.PixelFormat==Drawing.Imaging.PixelFormat==Drawing.PixelFormat.Format8bppIndexed | bitmap.PixelFormat==Drawing.Imaging.PixelFormat.Format==Drawing.PixelFormat |位图.PixelFormat==Drawing.PixelFormat | DontCare |位图.PixelFormat==Drawing.Imaging.PixelFormat.Format16bppArgb1555 | bitmap.PixelFormat==Drawing.Imaging.PixelFormat.Format16bppGrayScale)
{
抛出new NotSupportedException(“不支持图像的像素格式”);
}
System.Drawing.Graphics graphicsImage=System.Drawing.Graphics.FromImage(位图);
graphicsImage.SmoothingMode=Drawing.Drawing2D.SmoothingMode.HighQuality;
graphicsImage.InterpolationMode=Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphicsImage.DrawImage(SourceImage,0,0,bitmap.Width,bitmap.Height);
graphicsImage.Dispose();
返回位图;
}
我不记得它是否能与GIF一起使用,但你可以试试


注意:我不能完全相信这个功能。我从网上的一些其他示例中拼凑了一些东西,使它能够满足我的需要8^D

如果缩放后没有保留文件类型的要求,我建议使用以下方法

using (Image src = Image.FromFile("main.gif"))
using (Bitmap dst = new Bitmap(100, 129))
using (Graphics g = Graphics.FromImage(dst))
{
   g.SmoothingMode = SmoothingMode.AntiAlias;
   g.InterpolationMode = InterpolationMode.HighQualityBicubic;
   g.DrawImage(src, 0, 0, dst.Width, dst.Height);
   dst.Save("scale.png", ImageFormat.Png);
}
结果将具有非常好的抗锯齿边

  • 已删除已被广告替换的图像棚屋图像
如果您必须以gif格式导出图像,那么您就有机会了;GDI+无法很好地使用gif。有关详细信息,请参阅


编辑:我忘了处理示例中的位图;对于试图使用Markus Olsson的解决方案动态调整图像大小并将其写入响应流的任何人,已对其进行了更正

这是行不通的:

Response.ContentType = "image/png";
dst.Save( Response.OutputStream, ImageFormat.Png );
但这将:

Response.ContentType = "image/png";
using (MemoryStream stream = new MemoryStream())
{
    dst.Save( stream, ImageFormat.Png );

    stream.WriteTo( Response.OutputStream );
}

虽然PNG肯定比GIF好,但偶尔也有需要保持GIF格式的用例

使用GIF或8位PNG,您必须解决量化问题

量化是指选择256种(或更少)颜色最能保留和代表图像,然后将RGB值转换回索引。当执行调整大小操作时,理想的调色板会随着颜色混合和平衡的改变而改变

对于轻微的大小调整,如10-30%,您可以保留原始调色板

然而,在大多数情况下,您需要重新量化

主要的两种算法是Octree和nQuant。Octree非常快,并且做得非常好,特别是当你可以覆盖一个智能抖动算法时。nQuant需要至少80MB的RAM来执行编码(它构建一个完整的直方图),并且通常慢20-30倍(平均图像每次编码1-5秒)但是,它有时会产生比八叉树更高的图像质量,因为它不会“舍入”值以保持一致的性能

在项目中实现透明GIF和动画GIF支持时,我选择了八叉树。一旦控制了图像调色板,透明支持就不难了。

Heh,“t
Response.ContentType = "image/png";
using (MemoryStream stream = new MemoryStream())
{
    dst.Save( stream, ImageFormat.Png );

    stream.WriteTo( Response.OutputStream );
}