26

透明な画像 (主に GIF) のサイズを、品質を損なうことなくサイズ変更するための秘密の公式を誰かが知っていますか?

私はたくさんのものを試しましたが、私が得る最も近いものは十分ではありません.

私のメイン画像を見てください:

http://www.thewallcompany.dk/test/main.gif

そして、スケーリングされた画像:

http://www.thewallcompany.dk/test/ScaledImage.gif

//Internal resize for indexed colored images
void IndexedRezise(int xSize, int ySize)
{
  BitmapData sourceData;
  BitmapData targetData;

  AdjustSizes(ref xSize, ref ySize);

  scaledBitmap = new Bitmap(xSize, ySize, bitmap.PixelFormat);
  scaledBitmap.Palette = bitmap.Palette;
  sourceData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
    ImageLockMode.ReadOnly, bitmap.PixelFormat);
  try
  {
    targetData = scaledBitmap.LockBits(new Rectangle(0, 0, xSize, ySize),
      ImageLockMode.WriteOnly, scaledBitmap.PixelFormat);
    try
    {
      xFactor = (Double)bitmap.Width / (Double)scaledBitmap.Width;
      yFactor = (Double)bitmap.Height / (Double)scaledBitmap.Height;
      sourceStride = sourceData.Stride;
      sourceScan0 = sourceData.Scan0;
      int targetStride = targetData.Stride;
      System.IntPtr targetScan0 = targetData.Scan0;
      unsafe
      {
        byte* p = (byte*)(void*)targetScan0;
        int nOffset = targetStride - scaledBitmap.Width;
        int nWidth = scaledBitmap.Width;
        for (int y = 0; y < scaledBitmap.Height; ++y)
        {
          for (int x = 0; x < nWidth; ++x)
          {
            p[0] = GetSourceByteAt(x, y);
            ++p;
          }
          p += nOffset;
        }
      }
    }
    finally
    {
      scaledBitmap.UnlockBits(targetData);
    }
  }
  finally
  {
    bitmap.UnlockBits(sourceData);
  }
}

上記のコードを使用して、インデックス付きのサイズ変更を行っています。

誰にも改善のアイデアはありますか?

4

5 に答える 5

51

スケーリング後にファイル タイプを保持する必要がない場合は、次のアプローチをお勧めします。

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 ではうまく機能しません。詳細については、このブログ記事を参照してください

編集:例のビットマップを破棄するのを忘れました。修正済みです

于 2008-08-27T16:33:43.293 に答える
5

これは、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; 
}

GIFで動作するかどうかは頭の中で覚えていませんが、試してみてください.

注: この機能を完全に称賛することはできません。オンラインの他のサンプルからいくつかのものをつなぎ合わせて、自分のニーズに合わせて動作させました 8^D

于 2008-08-27T16:24:52.053 に答える
3

問題は、走査線ベースのサイズ変更を行っていることだと思います。これにより、どんなに微調整してもジャギーが発生します。優れた画像サイズ変更品質を得るには、サイズ変更されたピクセルがカバーするサイズ変更前のピクセルの平均色を把握するために、さらに作業を行う必要があります。

この Web サイトを運営している人物は、いくつかの画像サイズ変更アルゴリズムについて説明しているブログ投稿を行っています。バイキュービック イメージ スケーリング アルゴリズムが必要な場合があります。

より良い画像サイズ変更

于 2008-08-27T16:24:48.073 に答える
1

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 );
}
于 2009-05-15T20:13:01.847 に答える
0

PNGはGIFよりも間違いなく優れていますが、GIF形式のままにする必要がある場合があります。

GIFまたは8ビットPNGでは、量子化の問題に対処する必要があります。

量子化では、画像を最もよく保存および表現する256色(またはそれ以下)を選択し、RGB値をインデックスに戻します。サイズ変更操作を実行すると、色を混ぜたりバランスを変更したりするため、理想的なカラーパレットが変わります。

10〜30%のようなわずかなサイズ変更の場合は、元のカラーパレットを保持しても問題ない場合があります。

ただし、ほとんどの場合、再定量化する必要があります。

選択する主な2つのアルゴリズムは、OctreeとnQuantです。Octreeは非常に高速で、特にスマートディザリングアルゴリズムをオーバーレイできる場合は非常にうまく機能します。nQuantは、エンコードを実行するために少なくとも80MBのRAMを必要とし(完全なヒストグラムを作成します)、通常は20〜30倍遅くなります(平均的な画像ではエンコードごとに1〜5秒)。ただし、一貫したパフォーマンスを維持するために値を「丸め」ないため、Octreeよりも高い画質が得られる場合があります。

imageresizing.netプロジェクトで透過GIFとアニメーションGIFのサポートを実装するとき、私はOctreeを選択しました。画像パレットを制御できれば、透明度のサポートは難しくありません。

于 2012-06-07T23:02:07.870 に答える