private GifFrameData[] GenerateTexturesList(int width, int height, int[] pointers, float[] frameDelays) { if (width == 0 || height == 0) { Debug.Log("Couldn't create external textures! width or height are 0!"); return(null); } GifFrameData[] gifTextures = new GifFrameData[pointers.Length]; for (int j = 0; j < pointers.Length; j++) { Texture2D newTex = Texture2D.CreateExternalTexture(width, height, TextureFormat.ARGB32, false, false, (System.IntPtr)pointers[j]); if (newTex == null) { Debug.Log("Couldn't create external texture!"); continue; } newTex.wrapMode = TextureWrapMode.Clamp; gifTextures[j] = new GifFrameData() { texture = newTex, delay = frameDelays[j] / 1000 }; } return(gifTextures); }
/// <summary> /// このGifエンコーダーに引数の画像データ(<paramref name="image"/>)を追加する /// </summary> /// <param name="image">追加する画像データ</param> /// <param name="delay">1フレームあたりのディレイ(1/100秒単位)</param> /// <exception cref="ArgumentNullException"> /// 追加する画像データ(<paramref name="image"/>)がNULLの場合に発生 /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// 1フレームあたりのディレイ(<paramref name="delay"/>)が0未満の値の場合に発生 /// </exception> /// <exception cref="ArgumentException"> /// コンストラクタで指定した 出力用ストリーム または、保存先パスが以下の場合に発生する /// ・出力用ストリームが書き込みをサポートしていない または、既に閉じられている場合 /// ・保存先パスが空文字 または、<see cref="Path.GetInvalidPathChars"/> で定義される /// 無効な文字が含まれている場合 /// </exception> /// <exception cref="System.Runtime.InteropServices.ExternalException"> /// 引数の画像データ(<paramref name="image"/>)が正しくないイメージ形式の場合に発生 /// </exception> /// <exception cref="ObjectDisposedException"> /// コンストラクタで指定した 出力用ストリーム または、保存先パスが以下の場合に発生する /// ・出力用ストリームが既に閉じられている場合 /// </exception> /// <exception cref="NotSupportedException"> /// コンストラクタで指定した 出力用ストリーム または、保存先パスが以下の場合に発生する /// ・出力用ストリームがシーク・書き込みをサポートしていない場合 /// ・保存先のパスにドライブラベル(C:\)の一部ではないコロン文字(:)が含まれている場合 /// </exception> /// <exception cref="IOException"> /// コンストラクタで指定した 出力用ストリーム または、保存先パスが以下の場合に発生する /// ・保存先のパスがシステム定義の最大長を超えている場合 /// [<see cref="PathTooLongException"/>] /// (Windowsでは、パスは 248 文字未満、ファイル名は 260 文字未満にする必要がある) /// ・保存先のパスが示すディレクトリが正しくない場合 /// [<see cref="DirectoryNotFoundException"/>] /// (マップされていないドライブ名が指定されている場合等) /// ・I/O エラーが発生した場合 /// [<see cref="IOException"/>] /// </exception> /// <exception cref="UnauthorizedAccessException"> /// コンストラクタで指定した 出力用ストリーム または、保存先パスが以下の場合に発生する /// ・保存先のパスにおいて、隠しファイル等のアクセスできないファイルが既に存在している場合に発生 /// </exception> /// <exception cref="System.Security.SecurityException"> /// 呼び出し元に、必要なアクセス許可がない場合に発生 /// </exception> /// <exception cref="GifEncoderException"> /// Gifデータへのエンコードに失敗した場合に発生 /// </exception> public void AddImage(Image image, short delay) { // 引数チェック if (image == null) { throw new ArgumentNullException(nameof(image)); } else if (delay < 0) { // 引数のディレイが0未満の値の場合、例外をスローする throw new ArgumentOutOfRangeException( paramName: nameof(delay), actualValue: delay, message: string.Format( CultureInfo.InvariantCulture, CommonMessage.ArgumentOutOfRangeExceptionMessageFormatLessThan, 0)); } // BitmapFrameを生成するために使用する、画像データ用のStreamを生成 MemoryStream imageStream; MemoryStream gifStream; using (imageStream = new MemoryStream()) using (gifStream = new MemoryStream()) { // 画像データをメモリに書き出す image.Save(imageStream, ImageFormat.Png); // メモリから呼び出す位置を設定 imageStream.Seek(0, SeekOrigin.Begin); // BitmapFrameを生成 BitmapFrame bitmapFrame = BitmapFrame.Create( imageStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); // エンコーダーにBitmapFrameを追加する GifBitmapEncoder gifBitmapEncoder = new GifBitmapEncoder(); gifBitmapEncoder.Frames.Add(bitmapFrame); // Gifデータにエンコードをする try { // エンコードを行いGif形式のデータをバイナリ形式で取得する // (メモリーストリームを利用してバイナリデータを取得) gifBitmapEncoder.Save(gifStream); byte[] gif = gifStream.ToArray(); // Gifデータのbyte配列からGifのフレーム単位のデータを生成する GifFrameData frameData = new GifFrameData(gif, delay); // 生成したデータのデータサイズを保存していないデータのデータサイズに加算する NotSaveDataSize += frameData.DataSize; // Gifデータのリストに追加する GifData.Add(new GifFrameData(gif, delay)); // 自動保存を行う場合 かつ 保存していないデータが閾値を超えている場合、 // 保存を行う if (IsEachTimeSave && NotSaveDataSize > ThresholdForSave) { Save(); } } catch (Exception ex) when(ex is InvalidOperationException || ex is ArgumentException) { // Gifのデータへのエンコードが失敗 // または、生成したデータが不正な場合、例外をスローする throw new GifEncoderException(ErrorMessage.GifEncoderErrorEncodingFailed, ex); } finally { // GifBitmapEncoderを破棄 gifBitmapEncoder.Frames.Clear(); } } }
/// <summary> /// Decode to textures from GIF data /// </summary> /// <param name="gifData">GIF data</param> /// <param name="callback">Callback method(param is GIF texture list)</param> /// <param name="filterMode">Textures filter mode</param> /// <param name="wrapMode">Textures wrap mode</param> /// <returns>IEnumerator</returns> private static IEnumerator DecodeTextureCoroutine(GifData gifData, Action <GifFrameData[]> callback, FilterMode filterMode, TextureWrapMode wrapMode) { if (gifData.m_imageBlockList == null || gifData.m_imageBlockList.Count < 1) { yield break; } GifFrameData[] gifTexList = new GifFrameData[gifData.m_imageBlockList.Count]; List <ushort> disposalMethodList = new List <ushort>(gifData.m_imageBlockList.Count); int imgIndex = 0; for (int i = 0; i < gifData.m_imageBlockList.Count; i++) { byte[] decodedData = GetDecodedData(gifData.m_imageBlockList[i]); GraphicControlExtension?graphicCtrlEx = GetGraphicCtrlExt(gifData, imgIndex); int transparentIndex = GetTransparentIndex(graphicCtrlEx); disposalMethodList.Add(GetDisposalMethod(graphicCtrlEx)); Color32 bgColor; List <byte[]> colorTable = GetColorTableAndSetBgColor(gifData, gifData.m_imageBlockList[i], transparentIndex, out bgColor); yield return(0); bool filledTexture; Texture2D tex = CreateTexture2D(gifData, gifTexList, imgIndex, disposalMethodList, bgColor, filterMode, wrapMode, out filledTexture); yield return(0); // Set pixel data int dataIndex = 0; // Reverse set pixels. because GIF data starts from the top left. for (int y = tex.height - 1; y >= 0; y--) { SetTexturePixelRow(tex, y, gifData.m_imageBlockList[i], decodedData, ref dataIndex, colorTable, bgColor, transparentIndex, filledTexture); } tex.Apply(); yield return(0); float delaySec = GetDelaySec(graphicCtrlEx); // Add to GIF texture list gifTexList[imgIndex] = new GifFrameData() { texture = tex, delay = delaySec }; imgIndex++; } if (callback != null) { callback(gifTexList); } yield break; }