OSDN Git Service

MemoryImageクラスを追加
authorKimura Youichi <kim.upsilon@bucyou.net>
Mon, 4 Feb 2013 12:59:48 +0000 (21:59 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Wed, 6 Feb 2013 15:24:13 +0000 (00:24 +0900)
Image.FromStream() を使うと元となったストリームを破棄せずに保持する必要があるため、その管理にこのクラスを使用する。

OpenTween/MemoryImage.cs [new file with mode: 0644]
OpenTween/OTPictureBox.cs
OpenTween/OpenTween.csproj

diff --git a/OpenTween/MemoryImage.cs b/OpenTween/MemoryImage.cs
new file mode 100644 (file)
index 0000000..069e76b
--- /dev/null
@@ -0,0 +1,111 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2013 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Drawing;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace OpenTween
+{
+    /// <summary>
+    /// Image と Stream を対に保持するためのクラス
+    /// </summary>
+    /// <remarks>
+    /// Image.FromStream() を使用して Image を生成する場合、
+    /// Image を破棄するまでの間は元となった Stream を破棄できないためその対策として使用する。
+    /// </remarks>
+    public class MemoryImage : IDisposable
+    {
+        public readonly Stream Stream;
+        public readonly Image Image;
+
+        protected bool disposed = false;
+
+        protected MemoryImage(Stream stream)
+        {
+            this.Stream = stream;
+            this.Image = Image.FromStream(stream);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (this.disposed) return;
+
+            if (disposing)
+            {
+                this.Image.Dispose();
+                this.Stream.Dispose();
+            }
+
+            this.disposed = true;
+        }
+
+        public void Dispose()
+        {
+            this.Dispose(true);
+
+            // 明示的にDisposeが呼ばれた場合はファイナライザを使用しない
+            GC.SuppressFinalize(this);
+        }
+
+        ~MemoryImage()
+        {
+            this.Dispose(false);
+        }
+
+        /// <summary>
+        /// 指定された Stream から MemoryImage を作成します。
+        /// </summary>
+        /// <remarks>
+        /// ストリームの内容はメモリ上に展開した後に使用されるため、
+        /// 引数に指定した Stream を MemoryImage より先に破棄しても問題ありません。
+        /// </remarks>
+        /// <param name="stream">読み込む対象となる Stream</param>
+        /// <returns>作成された MemoryImage</returns>
+        public static MemoryImage CopyFromStream(Stream stream)
+        {
+            var memstream = new MemoryStream();
+
+            var buffer = new byte[1024];
+            int length;
+            while ((length = stream.Read(buffer, 0, buffer.Length)) > 0)
+            {
+                memstream.Write(buffer, 0, length);
+            }
+
+            return new MemoryImage(memstream);
+        }
+
+        /// <summary>
+        /// 指定されたバイト列から MemoryImage を作成します。
+        /// </summary>
+        /// <param name="stream">読み込む対象となるバイト列</param>
+        /// <returns>作成された MemoryImage</returns>
+        public static MemoryImage CopyFromBytes(byte[] bytes)
+        {
+            return new MemoryImage(new MemoryStream(bytes));
+        }
+    }
+}
index 1f79ba4..d366023 100644 (file)
@@ -41,10 +41,10 @@ namespace OpenTween
             get { return base.Image; }
             set
             {
-                if (base.Image != null && this.imageFromLoadMethod)
+                if (this.memoryImage != null)
                 {
-                    this.DisposeImageFromStream();
-                    this.imageFromLoadMethod = false;
+                    this.memoryImage.Dispose();
+                    this.memoryImage = null;
                 }
                 base.Image = value;
             }
@@ -66,8 +66,10 @@ namespace OpenTween
         }
         private string _ImageLocation;
 
-        private bool imageFromLoadMethod = false;
-        private Stream imageStream = null;
+        /// <summary>
+        /// ImageLocation によりロードされた画像
+        /// </summary>
+        private MemoryImage memoryImage = null;
 
         private Task loadAsyncTask = null;
         private CancellationTokenSource loadAsyncCancelTokenSource = null;
@@ -111,14 +113,7 @@ namespace OpenTween
             return loadImageTask.ContinueWith(t => {
                 if (t.IsFaulted) throw t.Exception;
 
-                var bytes = t.Result;
-
-                // InitialImageの表示時に DisposeImageFromStream() が呼ばれるためここでは不要
-
-                this.imageStream = new MemoryStream(bytes);
-                this.imageStream.Write(bytes, 0, bytes.Length);
-
-                return Image.FromStream(this.imageStream, true, true);
+                return MemoryImage.CopyFromBytes(t.Result);
             }, cancelToken)
             .ContinueWith(t =>
             {
@@ -130,8 +125,8 @@ namespace OpenTween
                     }
                     else
                     {
-                        this.Image = t.Result;
-                        this.imageFromLoadMethod = true;
+                        this.Image = t.Result.Image;
+                        this.memoryImage = t.Result;
                     }
                 }
 
@@ -165,18 +160,6 @@ namespace OpenTween
             }
         }
 
-        /// <summary>
-        /// LoadAsync メソッドで取得した画像の破棄
-        /// </summary>
-        protected void DisposeImageFromStream()
-        {
-            if (this.Image != null)
-                this.Image.Dispose();
-
-            if (this.imageStream != null)
-                this.imageStream.Dispose();
-        }
-
         public new Image ErrorImage
         {
             get { return base.ErrorImage; }
@@ -279,8 +262,8 @@ namespace OpenTween
             if (this.expandedInitialImage != null)
                 this.expandedInitialImage.Dispose();
 
-            if (this.imageFromLoadMethod)
-                this.DisposeImageFromStream();
+            if (this.memoryImage != null)
+                this.memoryImage.Dispose();
         }
     }
 }
index 904657b..44bc6ff 100644 (file)
     <Compile Include="DetailsListView.cs">
       <SubType>Component</SubType>
     </Compile>
+    <Compile Include="MemoryImage.cs" />
     <Compile Include="OTPictureBox.cs">
       <SubType>Component</SubType>
     </Compile>