2013-07-18 7 views
0

GIF 애니메이션을로드하고 프레임별로 프레임을 비트 맵으로 변환해야합니다. 이를 위해 Drawing.Imaging 라이브러리를 사용하여 프레임별로 프레임을 추출한 다음 각 프레임을 비트 맵으로 캐스팅합니다.C# Drawing.Imaging GIF 프레임이 동일하면 떨어 뜨림

픽셀 차이가 없을 때 연속 프레임이 동일 할 때를 제외하고 모두 정상적으로 작동합니다. 도서관이 그런 틀을 떨어 뜨리는 것 같습니다.

나는 간단한 시험으로 그 대열에왔다. 마지막 원이 사라지고 새 것이 사라지는 순간 사이에 일시적으로 늘어나고 줄어드는 원의 애니메이션을 만들었습니다. 추출한 비트 맵으로 구성된 애니메이션을 재생할 때 일시 중지가 나타나지 않습니다. 동일한 프레임 길이이지만 동일한 프레임의 양이 다른 GIF를 비교하면 리턴 된 totalframescount 값이 다릅니다. 나는 또한 웹 브라우저가 똑같은 연속 된 프레임을 올바르게 표시한다는 것을 관찰했다.

public void DrawGif(Image img) 
    { 

     FrameDimension dimension = new FrameDimension(img.FrameDimensionsList[0]); 
     int frameCountTotal = img.GetFrameCount(dimension); 

     for (int framecount = 0; framecount < frameCountTotal; framecount++) 
     { 
      img.SelectActiveFrame(dimension, framecount); 

      Bitmap bmp = new Bitmap(img); //cast Image type to Bitmap 

       for (int i = 0; i < 16; i++) 
       { 
        for (int j = 0; j < 16; j++) 
        { 
         Color color = bmp.GetPixel(i, j); 
         DrawPixel(i, j, 0, color.R, color.G, color.B); 

        } 
       } 
  1. 는 사람이 같은 문제가 발생합니까?
  2. 저는 C#을 처음 접했을 때 .NET lib를 수정하는 방법이 있습니까?
  3. 어쩌면 내 문제에 대한 해결책이 있는데, 내가 모르는 사이에 라이브러리를 바꾸지 않아도 될까요?

업데이트 코드 - 결과는 Image 중복 프레임을 저장하지 동일한

public void DrawGif(img) 
    { 
     int frameCountTotal = img.GetFrameCount(FrameDimension.Time); 
     for (int framecount = 0; framecount < frameCountTotal; framecount++) 
      { 
    img.SelectActiveFrame(FrameDimension.Time, framecount); 
    Bitmap bmp = new Bitmap(img); 

    for (int i = 0; i < 16; i++) 
      { 
       for (int j = 0; j < 16; j++) 
       { 
         Color color = bmp.GetPixel(i, j); 
         DrawPixel(i, j, 0, color.R, color.G, color.B); 

       } 
+0

'FrameDimension.Time' 또는'FrameDimension.Page'를 명시 적으로 시도 했습니까? 페이지를 원하는 것처럼 보이지만 시간이 목록의 첫 번째 유형 일 수 있습니다. – mao47

+0

아니, 나는 이것을 시도하지 않았다. 나는 아직 그 수업에 익숙하지 않다. 주어진 GIF 파일의 경우 프레임 양을 결정하고 연속 프레임을 프레임별로로드해야합니까? –

+0

img.SelectActiveFrame (dimension, framecount)을 img.SelectActiveFrame (FrameDimension.Time, framecount)로 대체하고 총 프레임 수를 int로 바꾼 것입니다. frameCountTotal = img.GetFrameCount (FrameDimension.Time) --- 결과를 변경하지 않았습니다. - 여전히 동일한 프레임이 없습니다. –

답변

1

이다, 그래서 당신은 계정에 각 프레임의 time을해야합니다. 다음은 모든 프레임을 가져 오는 방법과 정확한 길이에 관한 this book in Windows Programming을 기반으로 한 샘플 코드입니다. 예 :

public class Gif 
{ 
    public static List<Frame> LoadAnimatedGif(string path) 
    { 
     //If path is not found, we should throw an IO exception 
     if (!File.Exists(path)) 
      throw new IOException("File does not exist"); 

     //Load the image 
     var img = Image.FromFile(path); 

     //Count the frames 
     var frameCount = img.GetFrameCount(FrameDimension.Time); 

     //If the image is not an animated gif, we should throw an 
     //argument exception 
     if (frameCount <= 1) 
      throw new ArgumentException("Image is not animated"); 

     //List that will hold all the frames 
     var frames = new List<Frame>(); 

     //Get the times stored in the gif 
     //PropertyTagFrameDelay ((PROPID) 0x5100) comes from gdiplusimaging.h 
     //More info on http://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx 
     var times = img.GetPropertyItem(0x5100).Value; 

     //Convert the 4bit duration chunk into an int 

     for (int i = 0; i < frameCount; i++) 
     { 
      //convert 4 bit value to integer 
      var duration = BitConverter.ToInt32(times, 4*i); 

      //Add a new frame to our list of frames 
      frames.Add(
       new Frame() 
       { 
        Image = new Bitmap(img), 
        Duration = duration 
       }); 

      //Set the write frame before we save it 
      img.SelectActiveFrame(FrameDimension.Time, i); 


     } 

     //Dispose the image when we're done 
     img.Dispose(); 

     return frames; 
    } 
} 

우리는 코드가 Bitmap를로드 각 프레임

//Class to store each frame 
public class Frame 
{ 
    public Bitmap Image { get; set; } 
    public int Duration { get; set;} 
} 

의 비트 맵과 시간을 절약은 GIF 애니메이션 멀티 프레임인지 여부를 확인하는 구조가 필요합니다. 그런 다음 모든 프레임을 반복하여 각 프레임의 비트 맵과 지속 시간을 보유하는 별도의 Frame 개체 목록을 구성합니다. 간단한 사용 :

var frameList = Gif.LoadAnimatedGif ("a.gif"); 

var i = 0; 
foreach(var frame in frameList) 
    frame.Image.Save ("frame_" + i++ + ".png"); 
+0

난 그냥 시도하고 결과를 변경하지 않는 것 같아요 - 난 여전히 모든 프레임을 얻을하지 않습니다. "frame-by-frame-drawloop"을 입력하기 전에 얼마나 많은 프레임이 있는지 확인하고 (getframescount), 있어야 할 프레임 수보다 적습니다. –

+0

@PK 각 프레임의 시간이 더 긴 시간 동안 표시되는지 확인해야합니다. 이것은 하나의 이미지의 여러 프레임으로 간주 될 수 있음을 나타냅니다. – mao47

+0

또한 다음 작업을 수행하십시오. GetFrameCount (FrameDimension.Time) – LouD