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;
30 using System.Threading.Tasks;
35 /// Image と Stream を対に保持するためのクラス
38 /// Image.FromStream() を使用して Image を生成する場合、
39 /// Image を破棄するまでの間は元となった Stream を破棄できないためその対策として使用する。
41 public class MemoryImage : ICloneable, IDisposable
43 public readonly Stream Stream;
44 public readonly Image Image;
46 protected bool disposed = false;
48 /// <exception cref="InvalidImageException">
49 /// ストリームから読みだされる画像データが不正な場合にスローされる
51 protected MemoryImage(Stream stream)
55 this.Image = Image.FromStream(stream);
57 catch (ArgumentException e)
60 throw new InvalidImageException("Invalid image", e);
62 catch (OutOfMemoryException e)
64 // GDI+ がサポートしない画像形式で OutOfMemoryException がスローされる場合があるらしい
66 throw new InvalidImageException("Invalid image?", e);
68 catch (ExternalException e)
70 // 「GDI+ で汎用エラーが発生しました」という大雑把な例外がスローされる場合があるらしい
72 throw new InvalidImageException("Invalid image?", e);
84 /// MemoryImage インスタンスを複製します
87 /// メソッド実行中にストリームのシークが行われないよう注意して下さい。
88 /// 特に PictureBox で Gif アニメーションを表示している場合は Enabled に false をセットするなどして更新を止めて下さい。
90 /// <returns>複製された MemoryImage</returns>
91 public MemoryImage Clone()
93 this.Stream.Seek(0, SeekOrigin.Begin);
95 return MemoryImage.CopyFromStream(this.Stream);
99 /// MemoryImage インスタンスを非同期に複製します
102 /// メソッド実行中にストリームのシークが行われないよう注意して下さい。
103 /// 特に PictureBox で Gif アニメーションを表示している場合は Enabled に false をセットするなどして更新を止めて下さい。
105 /// <returns>複製された MemoryImage を返すタスク</returns>
106 public Task<MemoryImage> CloneAsync()
108 this.Stream.Seek(0, SeekOrigin.Begin);
110 return MemoryImage.CopyFromStreamAsync(this.Stream);
113 object ICloneable.Clone()
118 protected virtual void Dispose(bool disposing)
120 if (this.disposed) return;
124 this.Image.Dispose();
125 this.Stream.Dispose();
128 this.disposed = true;
131 public void Dispose()
135 // 明示的にDisposeが呼ばれた場合はファイナライザを使用しない
136 GC.SuppressFinalize(this);
145 /// 指定された Stream から MemoryImage を作成します。
148 /// ストリームの内容はメモリ上に展開した後に使用されるため、
149 /// 引数に指定した Stream を MemoryImage より先に破棄しても問題ありません。
151 /// <param name="stream">読み込む対象となる Stream</param>
152 /// <returns>作成された MemoryImage</returns>
153 /// <exception cref="InvalidImageException">不正な画像データが入力された場合</exception>
154 public static MemoryImage CopyFromStream(Stream stream)
156 var memstream = new MemoryStream();
158 stream.CopyTo(memstream);
160 return new MemoryImage(memstream);
164 /// 指定された Stream から MemoryImage を非同期に作成します。
167 /// ストリームの内容はメモリ上に展開した後に使用されるため、
168 /// 引数に指定した Stream を MemoryImage より先に破棄しても問題ありません。
170 /// <param name="stream">読み込む対象となる Stream</param>
171 /// <returns>作成された MemoryImage を返すタスク</returns>
172 /// <exception cref="InvalidImageException">不正な画像データが入力された場合</exception>
173 public async static Task<MemoryImage> CopyFromStreamAsync(Stream stream)
175 var memstream = new MemoryStream();
177 await stream.CopyToAsync(memstream).ConfigureAwait(false);
179 return new MemoryImage(memstream);
183 /// 指定されたバイト列から MemoryImage を作成します。
185 /// <param name="bytes">読み込む対象となるバイト列</param>
186 /// <returns>作成された MemoryImage</returns>
187 /// <exception cref="InvalidImageException">不正な画像データが入力された場合</exception>
188 public static MemoryImage CopyFromBytes(byte[] bytes)
190 return new MemoryImage(new MemoryStream(bytes));
195 /// 不正な画像データに対してスローされる例外
197 public class InvalidImageException : Exception
199 public InvalidImageException() : base() { }
200 public InvalidImageException(string message) : base(message) { }
201 public InvalidImageException(string message, Exception innerException) : base(message, innerException) { }
202 public InvalidImageException(SerializationInfo info, StreamingContext context) : base(info, context) { }