1 // OpenTween - Client of Twitter
2 // Copyright (c) 2013 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
5 // This file is part of OpenTween.
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 // You should have received a copy of the GNU General Public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
23 using System.Collections.Generic;
25 using System.Runtime.InteropServices;
26 using System.Runtime.Serialization;
28 using System.Diagnostics.CodeAnalysis;
31 using System.Threading.Tasks;
36 /// Image と Stream を対に保持するためのクラス
39 /// Image.FromStream() を使用して Image を生成する場合、
40 /// Image を破棄するまでの間は元となった Stream を破棄できないためその対策として使用する。
42 public class MemoryImage : ICloneable, IDisposable
44 public readonly Stream Stream;
45 public readonly Image Image;
47 protected bool disposed = false;
49 /// <exception cref="InvalidImageException">
50 /// ストリームから読みだされる画像データが不正な場合にスローされる
52 protected MemoryImage(Stream stream)
56 this.Image = Image.FromStream(stream);
58 catch (ArgumentException e)
61 throw new InvalidImageException("Invalid image", e);
63 catch (OutOfMemoryException e)
65 // GDI+ がサポートしない画像形式で OutOfMemoryException がスローされる場合があるらしい
67 throw new InvalidImageException("Invalid image?", e);
69 catch (ExternalException e)
71 // 「GDI+ で汎用エラーが発生しました」という大雑把な例外がスローされる場合があるらしい
73 throw new InvalidImageException("Invalid image?", e);
85 /// MemoryImage インスタンスを複製します
88 /// メソッド実行中にストリームのシークが行われないよう注意して下さい。
89 /// 特に PictureBox で Gif アニメーションを表示している場合は Enabled に false をセットするなどして更新を止めて下さい。
91 /// <returns>複製された MemoryImage</returns>
92 public MemoryImage Clone()
94 this.Stream.Seek(0, SeekOrigin.Begin);
96 return MemoryImage.CopyFromStream(this.Stream);
100 /// MemoryImage インスタンスを非同期に複製します
103 /// メソッド実行中にストリームのシークが行われないよう注意して下さい。
104 /// 特に PictureBox で Gif アニメーションを表示している場合は Enabled に false をセットするなどして更新を止めて下さい。
106 /// <returns>複製された MemoryImage を返すタスク</returns>
107 public Task<MemoryImage> CloneAsync()
109 this.Stream.Seek(0, SeekOrigin.Begin);
111 return MemoryImage.CopyFromStreamAsync(this.Stream);
114 object ICloneable.Clone()
119 protected virtual void Dispose(bool disposing)
121 if (this.disposed) return;
125 this.Image.Dispose();
126 this.Stream.Dispose();
129 this.disposed = true;
132 public void Dispose()
136 // 明示的にDisposeが呼ばれた場合はファイナライザを使用しない
137 GC.SuppressFinalize(this);
146 /// 指定された Stream から MemoryImage を作成します。
149 /// ストリームの内容はメモリ上に展開した後に使用されるため、
150 /// 引数に指定した Stream を MemoryImage より先に破棄しても問題ありません。
152 /// <param name="stream">読み込む対象となる Stream</param>
153 /// <returns>作成された MemoryImage</returns>
154 /// <exception cref="InvalidImageException">不正な画像データが入力された場合</exception>
155 [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]
156 public static MemoryImage CopyFromStream(Stream stream)
158 var memstream = new MemoryStream();
160 stream.CopyTo(memstream);
162 return new MemoryImage(memstream);
166 /// 指定された Stream から MemoryImage を非同期に作成します。
169 /// ストリームの内容はメモリ上に展開した後に使用されるため、
170 /// 引数に指定した Stream を MemoryImage より先に破棄しても問題ありません。
172 /// <param name="stream">読み込む対象となる Stream</param>
173 /// <returns>作成された MemoryImage を返すタスク</returns>
174 /// <exception cref="InvalidImageException">不正な画像データが入力された場合</exception>
175 public async static Task<MemoryImage> CopyFromStreamAsync(Stream stream)
177 var memstream = new MemoryStream();
179 await stream.CopyToAsync(memstream).ConfigureAwait(false);
181 return new MemoryImage(memstream);
185 /// 指定されたバイト列から MemoryImage を作成します。
187 /// <param name="bytes">読み込む対象となるバイト列</param>
188 /// <returns>作成された MemoryImage</returns>
189 /// <exception cref="InvalidImageException">不正な画像データが入力された場合</exception>
190 [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]
191 public static MemoryImage CopyFromBytes(byte[] bytes)
193 return new MemoryImage(new MemoryStream(bytes));
198 /// 不正な画像データに対してスローされる例外
201 public class InvalidImageException : Exception
203 public InvalidImageException() : base() { }
204 public InvalidImageException(string message) : base(message) { }
205 public InvalidImageException(string message, Exception innerException) : base(message, innerException) { }
206 protected InvalidImageException(SerializationInfo info, StreamingContext context) : base(info, context) { }