2011-06-02 8 views
4

皆さん、こんにちは皆さん、 私は現在、APNG Specificationを実装しようとしていますが、フレームレンダリングに問題があります。 My機能はAPNGレンダリング機能の実装

private void UpdateUI() 
    { 
     foreach (PictureBox pb in pics) 
     { 
      APNGBox box = (APNGBox)pb.Tag; 
      APNGLib.APNG png = box.png; 
      if (box.buffer == null) 
      { 
       box.buffer = new Bitmap((int)png.Width, (int)png.Height); 
      } 
      APNGLib.Frame f = png.GetFrame(box.frameNum); 
      using (Graphics g = Graphics.FromImage(box.buffer)) 
      { 
       switch (f.DisposeOp) 
       { 
        case APNGLib.Frame.DisposeOperation.NONE: 
         break; 
        case APNGLib.Frame.DisposeOperation.BACKGROUND: 
         g.Clear(Color.Transparent); 
         break; 
        case APNGLib.Frame.DisposeOperation.PREVIOUS: 
         if (box.prevBuffer != null) 
         { 
          g.DrawImage(box.prevBuffer, Point.Empty); 
         } 
         else 
         { 
          g.Clear(Color.Transparent); 
         } 
         break; 
        default: 
         break; 
       } 
       Bitmap read = png.ToBitmap(box.frameNum++); 
       switch (f.BlendOp) 
       { 
        case APNGLib.Frame.BlendOperation.OVER: 
         g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; 
         break; 
        case APNGLib.Frame.BlendOperation.SOURCE: 
         g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; 
         break; 
        default: 
         break; 
       } 
       g.DrawImage(read, new Point((int)f.XOffset, (int)f.YOffset)); 
      } 

      box.prevBuffer = box.buffer; 
      pb.Image = box.buffer; 

      if (box.frameNum >= box.png.FrameCount) 
      { 
       box.frameNum = 0; 
       box.buffer = null; 
       box.prevBuffer = null; 
      } 
     } 
    } 

APNGBoxは私がAPNG Gallery内のすべての画像に対してそれを実行してきたように、これは、ほとんどが正しいことだと思う

internal class APNGBox 
    { 
     public int frameNum = 0; 
     public APNGLib.APNG png; 
     public Bitmap buffer; 
     public Bitmap prevBuffer; 
    } 

です。しかし、それらのいくつかは間違ってレンダリングされています(This人為的な問題があり、thisは左に一貫して赤いバーを保持しません)。アニメーションを表示するには、Firefox 3以降のページを表示する必要があります。

私はこの問題がDISPOSE_OP_PREVIOUSの処理方法と関係があると信じていますが、間違っていることを理解できません。誰かが私が逃しているかもしれないことを示唆することができます

答えて

5

だから私は最後にそれを理解することができましたし、将来誰かが同様の問題に遭遇する場合に備えてここに投稿します。問題は、主に三重だっ判明:

  1. フレームタイプが一つは、前のフレームのdispose_opではなく、現在のフレームのdispose_opを使用する必要があります
  2. 「PREVIOUS」である場合は、1つは「前のバッファ」を変更しないでくださいそれは
  3. 一つだけ古いフレームの地域全体ではなく、フレームを配置することを確認する必要があり処分方法を決定するために

新しいコードは次のとおりです。

internal class APNGBox 
    { 
     public int frameNum { get; set; } 
     public APNGLib.APNG apng { get; set; } 
     public Bitmap buffer { get; set; } 
     public Bitmap prevBuffer { get; set; } 

     public APNGBox(APNGLib.APNG png) 
     { 
      frameNum = 0; 
      apng = png; 
      buffer = apng.ToBitmap(0); 
      prevBuffer = null; 
     } 
    } 

    private void UpdateUI() 
    { 
     foreach (PictureBox pb in pics) 
     { 
      APNGBox box = (APNGBox)pb.Tag; 
      APNGLib.APNG png = box.apng; 
      if (!png.IsAnimated) 
      { 
       if (pb.Image == null) 
       { 
        pb.Image = png.ToBitmap(); 
       } 
      } 
      else 
      { 
       if (box.frameNum != png.FrameCount - 1) 
       { 
        Bitmap prev = box.prevBuffer == null ? null : new Bitmap(box.prevBuffer); 
        APNGLib.Frame f1 = png.GetFrame(box.frameNum); 
        if (f1.DisposeOp != APNGLib.Frame.DisposeOperation.PREVIOUS) 
        { 
         box.prevBuffer = new Bitmap(box.buffer); 
        } 
        DisposeBuffer(box.buffer, new Rectangle((int)f1.XOffset, (int)f1.YOffset, (int)f1.Width, (int)f1.Height), f1.DisposeOp, prev); 
        box.frameNum++; 
        APNGLib.Frame f2 = png.GetFrame(box.frameNum); 
        RenderNextFrame(box.buffer, new Point((int)f2.XOffset, (int)f2.YOffset), png.ToBitmap(box.frameNum), f2.BlendOp); 
       } 
       else 
       { 
        box.frameNum = 0; 
        box.prevBuffer = null; 
        ClearFrame(box.buffer); 
        RenderNextFrame(box.buffer, Point.Empty, png.ToBitmap(box.frameNum), APNGLib.Frame.BlendOperation.SOURCE); 
       } 
       pb.Invalidate(); 
      } 
     } 
    } 

    private void DisposeBuffer(Bitmap buffer, Rectangle region, APNGLib.Frame.DisposeOperation dispose, Bitmap prevBuffer) 
    { 
     using (Graphics g = Graphics.FromImage(buffer)) 
     { 
      g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; 

      Brush b = new SolidBrush(Color.Transparent); 
      switch (dispose) 
      { 
       case APNGLib.Frame.DisposeOperation.NONE: 
        break; 
       case APNGLib.Frame.DisposeOperation.BACKGROUND: 
        g.FillRectangle(b, region); 
        break; 
       case APNGLib.Frame.DisposeOperation.PREVIOUS: 
        if(prevBuffer != null) 
        { 
         g.FillRectangle(b, region); 
         g.DrawImage(prevBuffer, region, region, GraphicsUnit.Pixel); 
        } 
        break; 
       default: 
        break; 
      } 
     } 
    } 

    private void RenderNextFrame(Bitmap buffer, Point point, Bitmap nextFrame, APNGLib.Frame.BlendOperation blend) 
    { 
     using(Graphics g = Graphics.FromImage(buffer)) 
     { 
      switch(blend) 
      { 
       case APNGLib.Frame.BlendOperation.OVER: 
        g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; 
        break; 
       case APNGLib.Frame.BlendOperation.SOURCE: 
        g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; 
        break; 
       default: 
        break; 
      } 
      g.DrawImage(nextFrame, point); 
     } 
    } 

    private void ClearFrame(Bitmap buffer) 
    { 
     using(Graphics g = Graphics.FromImage(buffer)) 
     { 
      g.Clear(Color.Transparent); 
     } 
    } 
+0

こんにちは、提供するための完全な作業用ソースコードをお持ちですか?私は私のwinformsアプリケーションでapngを表示したいと思います。ありがとう。 – Dede

+0

最後にこれらの作業を行ってからしばらくしていますが、ここでいくつかのデモを作成しました:https://github.com/murrple-1/APNGManagement。また、私は当時のネット/ C#の新機能だったと確信していますので、依存関係のためのNuGetはありません(私はいつかやってください) –

+0

@dede今すぐNuGetサポートを追加しました。あなたにはAPNGViewerアプリが便利です –

関連する問題