From f149ba76748bf55f5cd63ea2569a939659ecf5ea Mon Sep 17 00:00:00 2001 From: Maxime Cauvin Date: Tue, 5 Mar 2019 15:35:23 +0900 Subject: [PATCH] Added missing namespaces for UniGif --- .../BeatSaberDrinkWater/DrinkWaterPanel.cs | 2 + .../BeatSaberDrinkWater/UniGif/UniGif.cs | 95 +- .../BeatSaberDrinkWater/UniGif/UniGifConst.cs | 433 ++++---- .../UniGif/UniGifDecoder.cs | 871 ++++++++-------- .../UniGif/UniGifExtension.cs | 83 +- .../UniGif/UniGifFormatter.cs | 941 +++++++++--------- .../BeatSaberDrinkWater/UniGif/UniGifImage.cs | 552 +++++----- .../Utility/UniGifImageAspectController.cs | 115 +-- 8 files changed, 1558 insertions(+), 1534 deletions(-) diff --git a/BeatSaberDrinkWater/BeatSaberDrinkWater/DrinkWaterPanel.cs b/BeatSaberDrinkWater/BeatSaberDrinkWater/DrinkWaterPanel.cs index af5e493..3fb5384 100644 --- a/BeatSaberDrinkWater/BeatSaberDrinkWater/DrinkWaterPanel.cs +++ b/BeatSaberDrinkWater/BeatSaberDrinkWater/DrinkWaterPanel.cs @@ -1,4 +1,6 @@ using BeatSaberDrinkWater.Settings; +using BeatSaberDrinkWater.UniGif; +using BeatSaberDrinkWater.UniGif.Utility; using BeatSaberDrinkWater.Utilities; using CustomUI.BeatSaber; using System; diff --git a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGif.cs b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGif.cs index 882d552..1649d0b 100644 --- a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGif.cs +++ b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGif.cs @@ -10,63 +10,66 @@ This software is released under the MIT License. using System.Collections.Generic; using UnityEngine; -public static partial class UniGif +namespace BeatSaberDrinkWater.UniGif { - /// - /// Get GIF texture list Coroutine - /// - /// GIF file byte data - /// Callback method(param is GIF texture list, Animation loop count, GIF image width (px), GIF image height (px)) - /// Textures filter mode - /// Textures wrap mode - /// Debug Log Flag - /// IEnumerator - public static IEnumerator GetTextureListCoroutine( - byte[] bytes, - Action, int, int, int> callback, - FilterMode filterMode = FilterMode.Bilinear, - TextureWrapMode wrapMode = TextureWrapMode.Clamp, - bool debugLog = false) + public static partial class UniGif { - int loopCount = -1; - int width = 0; - int height = 0; - - // Set GIF data - var gifData = new GifData(); - if (SetGifData(bytes, ref gifData, debugLog) == false) + /// + /// Get GIF texture list Coroutine + /// + /// GIF file byte data + /// Callback method(param is GIF texture list, Animation loop count, GIF image width (px), GIF image height (px)) + /// Textures filter mode + /// Textures wrap mode + /// Debug Log Flag + /// IEnumerator + public static IEnumerator GetTextureListCoroutine( + byte[] bytes, + Action, int, int, int> callback, + FilterMode filterMode = FilterMode.Bilinear, + TextureWrapMode wrapMode = TextureWrapMode.Clamp, + bool debugLog = false) { - Debug.LogError("GIF file data set error."); - if (callback != null) + int loopCount = -1; + int width = 0; + int height = 0; + + // Set GIF data + var gifData = new GifData(); + if (SetGifData(bytes, ref gifData, debugLog) == false) { - callback(null, loopCount, width, height); + Debug.LogError("GIF file data set error."); + if (callback != null) + { + callback(null, loopCount, width, height); + } + yield break; } - yield break; - } - // Decode to textures from GIF data - List gifTexList = null; - yield return DecodeTextureCoroutine(gifData, result => gifTexList = result, filterMode, wrapMode); + // Decode to textures from GIF data + List gifTexList = null; + yield return DecodeTextureCoroutine(gifData, result => gifTexList = result, filterMode, wrapMode); - if (gifTexList == null || gifTexList.Count <= 0) - { - Debug.LogError("GIF texture decode error."); - if (callback != null) + if (gifTexList == null || gifTexList.Count <= 0) { - callback(null, loopCount, width, height); + Debug.LogError("GIF texture decode error."); + if (callback != null) + { + callback(null, loopCount, width, height); + } + yield break; } - yield break; - } - loopCount = gifData.m_appEx.loopCount; - width = gifData.m_logicalScreenWidth; - height = gifData.m_logicalScreenHeight; + loopCount = gifData.m_appEx.loopCount; + width = gifData.m_logicalScreenWidth; + height = gifData.m_logicalScreenHeight; - if (callback != null) - { - callback(gifTexList, loopCount, width, height); - } + if (callback != null) + { + callback(gifTexList, loopCount, width, height); + } - yield break; + yield break; + } } } \ No newline at end of file diff --git a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifConst.cs b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifConst.cs index 0c67421..7872d15 100644 --- a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifConst.cs +++ b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifConst.cs @@ -10,266 +10,269 @@ This software is released under the MIT License. using System.Text; using UnityEngine; -public static partial class UniGif +namespace BeatSaberDrinkWater.UniGif { - /// - /// Gif Texture - /// - public class GifTexture + public static partial class UniGif { - // Texture - public Texture2D m_texture2d; - // Delay time until the next texture. - public float m_delaySec; - - public GifTexture(Texture2D texture2d, float delaySec) + /// + /// Gif Texture + /// + public class GifTexture { - m_texture2d = texture2d; - m_delaySec = delaySec; - } - } + // Texture + public Texture2D m_texture2d; + // Delay time until the next texture. + public float m_delaySec; - /// - /// GIF Data Format - /// - private struct GifData - { - // Signature - public byte m_sig0, m_sig1, m_sig2; - // Version - public byte m_ver0, m_ver1, m_ver2; - // Logical Screen Width - public ushort m_logicalScreenWidth; - // Logical Screen Height - public ushort m_logicalScreenHeight; - // Global Color Table Flag - public bool m_globalColorTableFlag; - // Color Resolution - public int m_colorResolution; - // Sort Flag - public bool m_sortFlag; - // Size of Global Color Table - public int m_sizeOfGlobalColorTable; - // Background Color Index - public byte m_bgColorIndex; - // Pixel Aspect Ratio - public byte m_pixelAspectRatio; - // Global Color Table - public List m_globalColorTable; - // ImageBlock - public List m_imageBlockList; - // GraphicControlExtension - public List m_graphicCtrlExList; - // Comment Extension - public List m_commentExList; - // Plain Text Extension - public List m_plainTextExList; - // Application Extension - public ApplicationExtension m_appEx; - // Trailer - public byte m_trailer; - - public string signature - { - get + public GifTexture(Texture2D texture2d, float delaySec) { - char[] c = { (char)m_sig0, (char)m_sig1, (char)m_sig2 }; - return new string(c); + m_texture2d = texture2d; + m_delaySec = delaySec; } } - public string version + /// + /// GIF Data Format + /// + private struct GifData { - get + // Signature + public byte m_sig0, m_sig1, m_sig2; + // Version + public byte m_ver0, m_ver1, m_ver2; + // Logical Screen Width + public ushort m_logicalScreenWidth; + // Logical Screen Height + public ushort m_logicalScreenHeight; + // Global Color Table Flag + public bool m_globalColorTableFlag; + // Color Resolution + public int m_colorResolution; + // Sort Flag + public bool m_sortFlag; + // Size of Global Color Table + public int m_sizeOfGlobalColorTable; + // Background Color Index + public byte m_bgColorIndex; + // Pixel Aspect Ratio + public byte m_pixelAspectRatio; + // Global Color Table + public List m_globalColorTable; + // ImageBlock + public List m_imageBlockList; + // GraphicControlExtension + public List m_graphicCtrlExList; + // Comment Extension + public List m_commentExList; + // Plain Text Extension + public List m_plainTextExList; + // Application Extension + public ApplicationExtension m_appEx; + // Trailer + public byte m_trailer; + + public string signature { - char[] c = { (char)m_ver0, (char)m_ver1, (char)m_ver2 }; - return new string(c); + get + { + char[] c = { (char)m_sig0, (char)m_sig1, (char)m_sig2 }; + return new string(c); + } } - } - public void Dump() - { - Debug.Log("GIF Type: " + signature + "-" + version); - Debug.Log("Image Size: " + m_logicalScreenWidth + "x" + m_logicalScreenHeight); - Debug.Log("Animation Image Count: " + m_imageBlockList.Count); - Debug.Log("Animation Loop Count (0 is infinite): " + m_appEx.loopCount); - if (m_graphicCtrlExList != null && m_graphicCtrlExList.Count > 0) + public string version { - var sb = new StringBuilder("Animation Delay Time (1/100sec)"); - for (int i = 0; i < m_graphicCtrlExList.Count; i++) + get { - sb.Append(", "); - sb.Append(m_graphicCtrlExList[i].m_delayTime); + char[] c = { (char)m_ver0, (char)m_ver1, (char)m_ver2 }; + return new string(c); } - Debug.Log(sb.ToString()); } - Debug.Log("Application Identifier: " + m_appEx.applicationIdentifier); - Debug.Log("Application Authentication Code: " + m_appEx.applicationAuthenticationCode); - } - } - - /// - /// Image Block - /// - private struct ImageBlock - { - // Image Separator - public byte m_imageSeparator; - // Image Left Position - public ushort m_imageLeftPosition; - // Image Top Position - public ushort m_imageTopPosition; - // Image Width - public ushort m_imageWidth; - // Image Height - public ushort m_imageHeight; - // Local Color Table Flag - public bool m_localColorTableFlag; - // Interlace Flag - public bool m_interlaceFlag; - // Sort Flag - public bool m_sortFlag; - // Size of Local Color Table - public int m_sizeOfLocalColorTable; - // Local Color Table - public List m_localColorTable; - // LZW Minimum Code Size - public byte m_lzwMinimumCodeSize; - // Block Size & Image Data List - public List m_imageDataList; - public struct ImageDataBlock - { - // Block Size - public byte m_blockSize; - // Image Data - public byte[] m_imageData; + public void Dump() + { + Debug.Log("GIF Type: " + signature + "-" + version); + Debug.Log("Image Size: " + m_logicalScreenWidth + "x" + m_logicalScreenHeight); + Debug.Log("Animation Image Count: " + m_imageBlockList.Count); + Debug.Log("Animation Loop Count (0 is infinite): " + m_appEx.loopCount); + if (m_graphicCtrlExList != null && m_graphicCtrlExList.Count > 0) + { + var sb = new StringBuilder("Animation Delay Time (1/100sec)"); + for (int i = 0; i < m_graphicCtrlExList.Count; i++) + { + sb.Append(", "); + sb.Append(m_graphicCtrlExList[i].m_delayTime); + } + Debug.Log(sb.ToString()); + } + Debug.Log("Application Identifier: " + m_appEx.applicationIdentifier); + Debug.Log("Application Authentication Code: " + m_appEx.applicationAuthenticationCode); + } } - } - /// - /// Graphic Control Extension - /// - private struct GraphicControlExtension - { - // Extension Introducer - public byte m_extensionIntroducer; - // Graphic Control Label - public byte m_graphicControlLabel; - // Block Size - public byte m_blockSize; - // Disposal Mothod - public ushort m_disposalMethod; - // Transparent Color Flag - public bool m_transparentColorFlag; - // Delay Time - public ushort m_delayTime; - // Transparent Color Index - public byte m_transparentColorIndex; - // Block Terminator - public byte m_blockTerminator; - } + /// + /// Image Block + /// + private struct ImageBlock + { + // Image Separator + public byte m_imageSeparator; + // Image Left Position + public ushort m_imageLeftPosition; + // Image Top Position + public ushort m_imageTopPosition; + // Image Width + public ushort m_imageWidth; + // Image Height + public ushort m_imageHeight; + // Local Color Table Flag + public bool m_localColorTableFlag; + // Interlace Flag + public bool m_interlaceFlag; + // Sort Flag + public bool m_sortFlag; + // Size of Local Color Table + public int m_sizeOfLocalColorTable; + // Local Color Table + public List m_localColorTable; + // LZW Minimum Code Size + public byte m_lzwMinimumCodeSize; + // Block Size & Image Data List + public List m_imageDataList; - /// - /// Comment Extension - /// - private struct CommentExtension - { - // Extension Introducer - public byte m_extensionIntroducer; - // Comment Label - public byte m_commentLabel; - // Block Size & Comment Data List - public List m_commentDataList; + public struct ImageDataBlock + { + // Block Size + public byte m_blockSize; + // Image Data + public byte[] m_imageData; + } + } - public struct CommentDataBlock + /// + /// Graphic Control Extension + /// + private struct GraphicControlExtension { + // Extension Introducer + public byte m_extensionIntroducer; + // Graphic Control Label + public byte m_graphicControlLabel; // Block Size public byte m_blockSize; - // Image Data - public byte[] m_commentData; + // Disposal Mothod + public ushort m_disposalMethod; + // Transparent Color Flag + public bool m_transparentColorFlag; + // Delay Time + public ushort m_delayTime; + // Transparent Color Index + public byte m_transparentColorIndex; + // Block Terminator + public byte m_blockTerminator; } - } - /// - /// Plain Text Extension - /// - private struct PlainTextExtension - { - // Extension Introducer - public byte m_extensionIntroducer; - // Plain Text Label - public byte m_plainTextLabel; - // Block Size - public byte m_blockSize; - // Block Size & Plain Text Data List - public List m_plainTextDataList; + /// + /// Comment Extension + /// + private struct CommentExtension + { + // Extension Introducer + public byte m_extensionIntroducer; + // Comment Label + public byte m_commentLabel; + // Block Size & Comment Data List + public List m_commentDataList; + + public struct CommentDataBlock + { + // Block Size + public byte m_blockSize; + // Image Data + public byte[] m_commentData; + } + } - public struct PlainTextDataBlock + /// + /// Plain Text Extension + /// + private struct PlainTextExtension { + // Extension Introducer + public byte m_extensionIntroducer; + // Plain Text Label + public byte m_plainTextLabel; // Block Size public byte m_blockSize; - // Plain Text Data - public byte[] m_plainTextData; - } - } + // Block Size & Plain Text Data List + public List m_plainTextDataList; - /// - /// Application Extension - /// - private struct ApplicationExtension - { - // Extension Introducer - public byte m_extensionIntroducer; - // Extension Label - public byte m_extensionLabel; - // Block Size - public byte m_blockSize; - // Application Identifier - public byte m_appId1, m_appId2, m_appId3, m_appId4, m_appId5, m_appId6, m_appId7, m_appId8; - // Application Authentication Code - public byte m_appAuthCode1, m_appAuthCode2, m_appAuthCode3; - // Block Size & Application Data List - public List m_appDataList; + public struct PlainTextDataBlock + { + // Block Size + public byte m_blockSize; + // Plain Text Data + public byte[] m_plainTextData; + } + } - public struct ApplicationDataBlock + /// + /// Application Extension + /// + private struct ApplicationExtension { + // Extension Introducer + public byte m_extensionIntroducer; + // Extension Label + public byte m_extensionLabel; // Block Size public byte m_blockSize; - // Application Data - public byte[] m_applicationData; - } + // Application Identifier + public byte m_appId1, m_appId2, m_appId3, m_appId4, m_appId5, m_appId6, m_appId7, m_appId8; + // Application Authentication Code + public byte m_appAuthCode1, m_appAuthCode2, m_appAuthCode3; + // Block Size & Application Data List + public List m_appDataList; - public string applicationIdentifier - { - get + public struct ApplicationDataBlock { - char[] c = { (char)m_appId1, (char)m_appId2, (char)m_appId3, (char)m_appId4, (char)m_appId5, (char)m_appId6, (char)m_appId7, (char)m_appId8 }; - return new string(c); + // Block Size + public byte m_blockSize; + // Application Data + public byte[] m_applicationData; } - } - public string applicationAuthenticationCode - { - get + public string applicationIdentifier + { + get + { + char[] c = { (char)m_appId1, (char)m_appId2, (char)m_appId3, (char)m_appId4, (char)m_appId5, (char)m_appId6, (char)m_appId7, (char)m_appId8 }; + return new string(c); + } + } + + public string applicationAuthenticationCode { - char[] c = { (char)m_appAuthCode1, (char)m_appAuthCode2, (char)m_appAuthCode3 }; - return new string(c); + get + { + char[] c = { (char)m_appAuthCode1, (char)m_appAuthCode2, (char)m_appAuthCode3 }; + return new string(c); + } } - } - public int loopCount - { - get + public int loopCount { - if (m_appDataList == null || m_appDataList.Count < 1 || - m_appDataList[0].m_applicationData.Length < 3 || - m_appDataList[0].m_applicationData[0] != 0x01) + get { - return 0; + if (m_appDataList == null || m_appDataList.Count < 1 || + m_appDataList[0].m_applicationData.Length < 3 || + m_appDataList[0].m_applicationData[0] != 0x01) + { + return 0; + } + return BitConverter.ToUInt16(m_appDataList[0].m_applicationData, 1); } - return BitConverter.ToUInt16(m_appDataList[0].m_applicationData, 1); } } } -} +} \ No newline at end of file diff --git a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifDecoder.cs b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifDecoder.cs index 64eeca3..841c4d9 100644 --- a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifDecoder.cs +++ b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifDecoder.cs @@ -11,383 +11,392 @@ This software is released under the MIT License. using System.Text; using UnityEngine; -public static partial class UniGif +namespace BeatSaberDrinkWater.UniGif { - /// - /// Decode to textures from GIF data - /// - /// GIF data - /// Callback method(param is GIF texture list) - /// Textures filter mode - /// Textures wrap mode - /// IEnumerator - private static IEnumerator DecodeTextureCoroutine(GifData gifData, Action> callback, FilterMode filterMode, TextureWrapMode wrapMode) + public static partial class UniGif { - if (gifData.m_imageBlockList == null || gifData.m_imageBlockList.Count < 1) + /// + /// Decode to textures from GIF data + /// + /// GIF data + /// Callback method(param is GIF texture list) + /// Textures filter mode + /// Textures wrap mode + /// IEnumerator + private static IEnumerator DecodeTextureCoroutine(GifData gifData, Action> callback, FilterMode filterMode, TextureWrapMode wrapMode) { - yield break; - } + if (gifData.m_imageBlockList == null || gifData.m_imageBlockList.Count < 1) + { + yield break; + } - List gifTexList = new List(gifData.m_imageBlockList.Count); - List disposalMethodList = new List(gifData.m_imageBlockList.Count); + List gifTexList = new List(gifData.m_imageBlockList.Count); + List disposalMethodList = new List(gifData.m_imageBlockList.Count); - int imgIndex = 0; + int imgIndex = 0; - for (int i = 0; i < gifData.m_imageBlockList.Count; i++) - { - byte[] decodedData = GetDecodedData(gifData.m_imageBlockList[i]); + for (int i = 0; i < gifData.m_imageBlockList.Count; i++) + { + byte[] decodedData = GetDecodedData(gifData.m_imageBlockList[i]); - GraphicControlExtension? graphicCtrlEx = GetGraphicCtrlExt(gifData, imgIndex); + GraphicControlExtension? graphicCtrlEx = GetGraphicCtrlExt(gifData, imgIndex); - int transparentIndex = GetTransparentIndex(graphicCtrlEx); + int transparentIndex = GetTransparentIndex(graphicCtrlEx); - disposalMethodList.Add(GetDisposalMethod(graphicCtrlEx)); + disposalMethodList.Add(GetDisposalMethod(graphicCtrlEx)); - Color32 bgColor; - List colorTable = GetColorTableAndSetBgColor(gifData, gifData.m_imageBlockList[i], transparentIndex, out bgColor); + Color32 bgColor; + List colorTable = GetColorTableAndSetBgColor(gifData, gifData.m_imageBlockList[i], transparentIndex, out bgColor); - yield return 0; + yield return 0; - bool filledTexture; - Texture2D tex = CreateTexture2D(gifData, gifTexList, imgIndex, disposalMethodList, bgColor, filterMode, wrapMode, out filledTexture); + bool filledTexture; + Texture2D tex = CreateTexture2D(gifData, gifTexList, imgIndex, disposalMethodList, bgColor, filterMode, wrapMode, out filledTexture); - yield return 0; + 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(); + // 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; + yield return 0; - float delaySec = GetDelaySec(graphicCtrlEx); + float delaySec = GetDelaySec(graphicCtrlEx); - // Add to GIF texture list - gifTexList.Add(new GifTexture(tex, delaySec)); + // Add to GIF texture list + gifTexList.Add(new GifTexture(tex, delaySec)); - imgIndex++; - } + imgIndex++; + } - if (callback != null) - { - callback(gifTexList); - } + if (callback != null) + { + callback(gifTexList); + } - yield break; - } + yield break; + } - #region Call from DecodeTexture methods + #region Call from DecodeTexture methods - /// - /// Get decoded image data from ImageBlock - /// - private static byte[] GetDecodedData(ImageBlock imgBlock) - { - // Combine LZW compressed data - List lzwData = new List(); - for (int i = 0; i < imgBlock.m_imageDataList.Count; i++) + /// + /// Get decoded image data from ImageBlock + /// + private static byte[] GetDecodedData(ImageBlock imgBlock) { - for (int k = 0; k < imgBlock.m_imageDataList[i].m_imageData.Length; k++) + // Combine LZW compressed data + List lzwData = new List(); + for (int i = 0; i < imgBlock.m_imageDataList.Count; i++) { - lzwData.Add(imgBlock.m_imageDataList[i].m_imageData[k]); + for (int k = 0; k < imgBlock.m_imageDataList[i].m_imageData.Length; k++) + { + lzwData.Add(imgBlock.m_imageDataList[i].m_imageData[k]); + } } - } - // LZW decode - int needDataSize = imgBlock.m_imageHeight * imgBlock.m_imageWidth; - byte[] decodedData = DecodeGifLZW(lzwData, imgBlock.m_lzwMinimumCodeSize, needDataSize); + // LZW decode + int needDataSize = imgBlock.m_imageHeight * imgBlock.m_imageWidth; + byte[] decodedData = DecodeGifLZW(lzwData, imgBlock.m_lzwMinimumCodeSize, needDataSize); - // Sort interlace GIF - if (imgBlock.m_interlaceFlag) - { - decodedData = SortInterlaceGifData(decodedData, imgBlock.m_imageWidth); + // Sort interlace GIF + if (imgBlock.m_interlaceFlag) + { + decodedData = SortInterlaceGifData(decodedData, imgBlock.m_imageWidth); + } + return decodedData; } - return decodedData; - } - /// - /// Get color table and set background color (local or global) - /// - private static List GetColorTableAndSetBgColor(GifData gifData, ImageBlock imgBlock, int transparentIndex, out Color32 bgColor) - { - List colorTable = imgBlock.m_localColorTableFlag ? imgBlock.m_localColorTable : gifData.m_globalColorTableFlag ? gifData.m_globalColorTable : null; - - if (colorTable != null) - { - // Set background color from color table - byte[] bgRgb = colorTable[gifData.m_bgColorIndex]; - bgColor = new Color32(bgRgb[0], bgRgb[1], bgRgb[2], (byte)(transparentIndex == gifData.m_bgColorIndex ? 0 : 255)); - } - else + /// + /// Get color table and set background color (local or global) + /// + private static List GetColorTableAndSetBgColor(GifData gifData, ImageBlock imgBlock, int transparentIndex, out Color32 bgColor) { - bgColor = Color.black; - } + List colorTable = imgBlock.m_localColorTableFlag ? imgBlock.m_localColorTable : gifData.m_globalColorTableFlag ? gifData.m_globalColorTable : null; - return colorTable; - } + if (colorTable != null) + { + // Set background color from color table + byte[] bgRgb = colorTable[gifData.m_bgColorIndex]; + bgColor = new Color32(bgRgb[0], bgRgb[1], bgRgb[2], (byte)(transparentIndex == gifData.m_bgColorIndex ? 0 : 255)); + } + else + { + bgColor = Color.black; + } - /// - /// Get GraphicControlExtension from GifData - /// - private static GraphicControlExtension? GetGraphicCtrlExt(GifData gifData, int imgBlockIndex) - { - if (gifData.m_graphicCtrlExList != null && gifData.m_graphicCtrlExList.Count > imgBlockIndex) - { - return gifData.m_graphicCtrlExList[imgBlockIndex]; + return colorTable; } - return null; - } - /// - /// Get transparent color index from GraphicControlExtension - /// - private static int GetTransparentIndex(GraphicControlExtension? graphicCtrlEx) - { - int transparentIndex = -1; - if (graphicCtrlEx != null && graphicCtrlEx.Value.m_transparentColorFlag) + /// + /// Get GraphicControlExtension from GifData + /// + private static GraphicControlExtension? GetGraphicCtrlExt(GifData gifData, int imgBlockIndex) { - transparentIndex = graphicCtrlEx.Value.m_transparentColorIndex; - } - return transparentIndex; - } - - /// - /// Get delay seconds from GraphicControlExtension - /// - private static float GetDelaySec(GraphicControlExtension? graphicCtrlEx) - { - // Get delay sec from GraphicControlExtension - float delaySec = graphicCtrlEx != null ? graphicCtrlEx.Value.m_delayTime / 100f : (1f / 60f); - if (delaySec <= 0f) - { - delaySec = 0.1f; + if (gifData.m_graphicCtrlExList != null && gifData.m_graphicCtrlExList.Count > imgBlockIndex) + { + return gifData.m_graphicCtrlExList[imgBlockIndex]; + } + return null; } - return delaySec; - } - /// - /// Get disposal method from GraphicControlExtension - /// - private static ushort GetDisposalMethod(GraphicControlExtension? graphicCtrlEx) - { - return graphicCtrlEx != null ? graphicCtrlEx.Value.m_disposalMethod : (ushort)2; - } - - /// - /// Create Texture2D object and initial settings - /// - private static Texture2D CreateTexture2D(GifData gifData, List gifTexList, int imgIndex, List disposalMethodList, Color32 bgColor, FilterMode filterMode, TextureWrapMode wrapMode, out bool filledTexture) - { - filledTexture = false; - - // Create texture - Texture2D tex = new Texture2D(gifData.m_logicalScreenWidth, gifData.m_logicalScreenHeight, TextureFormat.ARGB32, false); - tex.filterMode = filterMode; - tex.wrapMode = wrapMode; - - // Check dispose - ushort disposalMethod = imgIndex > 0 ? disposalMethodList[imgIndex - 1] : (ushort)2; - int useBeforeIndex = -1; - if (disposalMethod == 0) - { - // 0 (No disposal specified) - } - else if (disposalMethod == 1) + /// + /// Get transparent color index from GraphicControlExtension + /// + private static int GetTransparentIndex(GraphicControlExtension? graphicCtrlEx) { - // 1 (Do not dispose) - useBeforeIndex = imgIndex - 1; - } - else if (disposalMethod == 2) - { - // 2 (Restore to background color) - filledTexture = true; - Color32[] pix = new Color32[tex.width * tex.height]; - for (int i = 0; i < pix.Length; i++) + int transparentIndex = -1; + if (graphicCtrlEx != null && graphicCtrlEx.Value.m_transparentColorFlag) { - pix[i] = bgColor; + transparentIndex = graphicCtrlEx.Value.m_transparentColorIndex; } - tex.SetPixels32(pix); - tex.Apply(); + return transparentIndex; } - else if (disposalMethod == 3) + + /// + /// Get delay seconds from GraphicControlExtension + /// + private static float GetDelaySec(GraphicControlExtension? graphicCtrlEx) { - // 3 (Restore to previous) - for (int i = imgIndex - 1; i >= 0; i--) + // Get delay sec from GraphicControlExtension + float delaySec = graphicCtrlEx != null ? graphicCtrlEx.Value.m_delayTime / 100f : (1f / 60f); + if (delaySec <= 0f) { - if (disposalMethodList[i] == 0 || disposalMethodList[i] == 1) - { - useBeforeIndex = i; - break; - } + delaySec = 0.1f; } + return delaySec; } - if (useBeforeIndex >= 0) + /// + /// Get disposal method from GraphicControlExtension + /// + private static ushort GetDisposalMethod(GraphicControlExtension? graphicCtrlEx) { - filledTexture = true; - Color32[] pix = gifTexList[useBeforeIndex].m_texture2d.GetPixels32(); - tex.SetPixels32(pix); - tex.Apply(); + return graphicCtrlEx != null ? graphicCtrlEx.Value.m_disposalMethod : (ushort)2; } - return tex; - } + /// + /// Create Texture2D object and initial settings + /// + private static Texture2D CreateTexture2D(GifData gifData, List gifTexList, int imgIndex, List disposalMethodList, Color32 bgColor, FilterMode filterMode, TextureWrapMode wrapMode, out bool filledTexture) + { + filledTexture = false; - /// - /// Set texture pixel row - /// - private static void SetTexturePixelRow(Texture2D tex, int y, ImageBlock imgBlock, byte[] decodedData, ref int dataIndex, List colorTable, Color32 bgColor, int transparentIndex, bool filledTexture) - { - // Row no (0~) - int row = tex.height - 1 - y; + // Create texture + Texture2D tex = new Texture2D(gifData.m_logicalScreenWidth, gifData.m_logicalScreenHeight, TextureFormat.ARGB32, false); + tex.filterMode = filterMode; + tex.wrapMode = wrapMode; - for (int x = 0; x < tex.width; x++) - { - // Line no (0~) - int line = x; - - // Out of image blocks - if (row < imgBlock.m_imageTopPosition || - row >= imgBlock.m_imageTopPosition + imgBlock.m_imageHeight || - line < imgBlock.m_imageLeftPosition || - line >= imgBlock.m_imageLeftPosition + imgBlock.m_imageWidth) + // Check dispose + ushort disposalMethod = imgIndex > 0 ? disposalMethodList[imgIndex - 1] : (ushort)2; + int useBeforeIndex = -1; + if (disposalMethod == 0) + { + // 0 (No disposal specified) + } + else if (disposalMethod == 1) + { + // 1 (Do not dispose) + useBeforeIndex = imgIndex - 1; + } + else if (disposalMethod == 2) { - // Get pixel color from bg color - if (filledTexture == false) + // 2 (Restore to background color) + filledTexture = true; + Color32[] pix = new Color32[tex.width * tex.height]; + for (int i = 0; i < pix.Length; i++) { - tex.SetPixel(x, y, bgColor); + pix[i] = bgColor; } - continue; + tex.SetPixels32(pix); + tex.Apply(); } - - // Out of decoded data - if (dataIndex >= decodedData.Length) + else if (disposalMethod == 3) { - if (filledTexture == false) + // 3 (Restore to previous) + for (int i = imgIndex - 1; i >= 0; i--) { - tex.SetPixel(x, y, bgColor); - if (dataIndex == decodedData.Length) + if (disposalMethodList[i] == 0 || disposalMethodList[i] == 1) { - Debug.LogError("dataIndex exceeded the size of decodedData. dataIndex:" + dataIndex + " decodedData.Length:" + decodedData.Length + " y:" + y + " x:" + x); + useBeforeIndex = i; + break; } } - dataIndex++; - continue; } - // Get pixel color from color table + if (useBeforeIndex >= 0) { - byte colorIndex = decodedData[dataIndex]; - if (colorTable == null || colorTable.Count <= colorIndex) + filledTexture = true; + Color32[] pix = gifTexList[useBeforeIndex].m_texture2d.GetPixels32(); + tex.SetPixels32(pix); + tex.Apply(); + } + + return tex; + } + + /// + /// Set texture pixel row + /// + private static void SetTexturePixelRow(Texture2D tex, int y, ImageBlock imgBlock, byte[] decodedData, ref int dataIndex, List colorTable, Color32 bgColor, int transparentIndex, bool filledTexture) + { + // Row no (0~) + int row = tex.height - 1 - y; + + for (int x = 0; x < tex.width; x++) + { + // Line no (0~) + int line = x; + + // Out of image blocks + if (row < imgBlock.m_imageTopPosition || + row >= imgBlock.m_imageTopPosition + imgBlock.m_imageHeight || + line < imgBlock.m_imageLeftPosition || + line >= imgBlock.m_imageLeftPosition + imgBlock.m_imageWidth) { + // Get pixel color from bg color if (filledTexture == false) { tex.SetPixel(x, y, bgColor); - if (colorTable == null) - { - Debug.LogError("colorIndex exceeded the size of colorTable. colorTable is null. colorIndex:" + colorIndex); - } - else + } + continue; + } + + // Out of decoded data + if (dataIndex >= decodedData.Length) + { + if (filledTexture == false) + { + tex.SetPixel(x, y, bgColor); + if (dataIndex == decodedData.Length) { - Debug.LogError("colorIndex exceeded the size of colorTable. colorTable.Count:" + colorTable.Count + " colorIndex:" + colorIndex); + Debug.LogError("dataIndex exceeded the size of decodedData. dataIndex:" + dataIndex + " decodedData.Length:" + decodedData.Length + " y:" + y + " x:" + x); } } dataIndex++; continue; } - byte[] rgb = colorTable[colorIndex]; - // Set alpha - byte alpha = transparentIndex >= 0 && transparentIndex == colorIndex ? (byte)0 : (byte)255; - - if (filledTexture == false || alpha != 0) + // Get pixel color from color table { - // Set color - Color32 col = new Color32(rgb[0], rgb[1], rgb[2], alpha); - tex.SetPixel(x, y, col); + byte colorIndex = decodedData[dataIndex]; + if (colorTable == null || colorTable.Count <= colorIndex) + { + if (filledTexture == false) + { + tex.SetPixel(x, y, bgColor); + if (colorTable == null) + { + Debug.LogError("colorIndex exceeded the size of colorTable. colorTable is null. colorIndex:" + colorIndex); + } + else + { + Debug.LogError("colorIndex exceeded the size of colorTable. colorTable.Count:" + colorTable.Count + " colorIndex:" + colorIndex); + } + } + dataIndex++; + continue; + } + byte[] rgb = colorTable[colorIndex]; + + // Set alpha + byte alpha = transparentIndex >= 0 && transparentIndex == colorIndex ? (byte)0 : (byte)255; + + if (filledTexture == false || alpha != 0) + { + // Set color + Color32 col = new Color32(rgb[0], rgb[1], rgb[2], alpha); + tex.SetPixel(x, y, col); + } } - } - dataIndex++; + dataIndex++; + } } - } - #endregion + #endregion - #region Decode LZW & Sort interrace methods + #region Decode LZW & Sort interrace methods - /// - /// GIF LZW decode - /// - /// LZW compressed data - /// LZW minimum code size - /// Need decoded data size - /// Decoded data array - private static byte[] DecodeGifLZW(List compData, int lzwMinimumCodeSize, int needDataSize) - { - int clearCode = 0; - int finishCode = 0; + /// + /// GIF LZW decode + /// + /// LZW compressed data + /// LZW minimum code size + /// Need decoded data size + /// Decoded data array + private static byte[] DecodeGifLZW(List compData, int lzwMinimumCodeSize, int needDataSize) + { + int clearCode = 0; + int finishCode = 0; - // Initialize dictionary - Dictionary dic = new Dictionary(); - int lzwCodeSize = 0; - InitDictionary(dic, lzwMinimumCodeSize, out lzwCodeSize, out clearCode, out finishCode); + // Initialize dictionary + Dictionary dic = new Dictionary(); + int lzwCodeSize = 0; + InitDictionary(dic, lzwMinimumCodeSize, out lzwCodeSize, out clearCode, out finishCode); - // Convert to bit array - byte[] compDataArr = compData.ToArray(); - var bitData = new BitArray(compDataArr); + // Convert to bit array + byte[] compDataArr = compData.ToArray(); + var bitData = new BitArray(compDataArr); - byte[] output = new byte[needDataSize]; - int outputAddIndex = 0; + byte[] output = new byte[needDataSize]; + int outputAddIndex = 0; - string prevEntry = null; + string prevEntry = null; - bool dicInitFlag = false; + bool dicInitFlag = false; - int bitDataIndex = 0; + int bitDataIndex = 0; - // LZW decode loop - while (bitDataIndex < bitData.Length) - { - if (dicInitFlag) + // LZW decode loop + while (bitDataIndex < bitData.Length) { - InitDictionary(dic, lzwMinimumCodeSize, out lzwCodeSize, out clearCode, out finishCode); - dicInitFlag = false; - } + if (dicInitFlag) + { + InitDictionary(dic, lzwMinimumCodeSize, out lzwCodeSize, out clearCode, out finishCode); + dicInitFlag = false; + } - int key = bitData.GetNumeral(bitDataIndex, lzwCodeSize); + int key = bitData.GetNumeral(bitDataIndex, lzwCodeSize); - string entry = null; + string entry = null; - if (key == clearCode) - { - // Clear (Initialize dictionary) - dicInitFlag = true; - bitDataIndex += lzwCodeSize; - prevEntry = null; - continue; - } - else if (key == finishCode) - { - // Exit - Debug.LogWarning("early stop code. bitDataIndex:" + bitDataIndex + " lzwCodeSize:" + lzwCodeSize + " key:" + key + " dic.Count:" + dic.Count); - break; - } - else if (dic.ContainsKey(key)) - { - // Output from dictionary - entry = dic[key]; - } - else if (key >= dic.Count) - { - if (prevEntry != null) + if (key == clearCode) + { + // Clear (Initialize dictionary) + dicInitFlag = true; + bitDataIndex += lzwCodeSize; + prevEntry = null; + continue; + } + else if (key == finishCode) + { + // Exit + Debug.LogWarning("early stop code. bitDataIndex:" + bitDataIndex + " lzwCodeSize:" + lzwCodeSize + " key:" + key + " dic.Count:" + dic.Count); + break; + } + else if (dic.ContainsKey(key)) + { + // Output from dictionary + entry = dic[key]; + } + else if (key >= dic.Count) { - // Output from estimation - entry = prevEntry + prevEntry[0]; + if (prevEntry != null) + { + // Output from estimation + entry = prevEntry + prevEntry[0]; + } + else + { + Debug.LogWarning("It is strange that come here. bitDataIndex:" + bitDataIndex + " lzwCodeSize:" + lzwCodeSize + " key:" + key + " dic.Count:" + dic.Count); + bitDataIndex += lzwCodeSize; + continue; + } } else { @@ -395,185 +404,179 @@ private static byte[] DecodeGifLZW(List compData, int lzwMinimumCodeSize, bitDataIndex += lzwCodeSize; continue; } - } - else - { - Debug.LogWarning("It is strange that come here. bitDataIndex:" + bitDataIndex + " lzwCodeSize:" + lzwCodeSize + " key:" + key + " dic.Count:" + dic.Count); - bitDataIndex += lzwCodeSize; - continue; - } - // Output - // Take out 8 bits from the string. - byte[] temp = Encoding.Unicode.GetBytes(entry); - for (int i = 0; i < temp.Length; i++) - { - if (i % 2 == 0) + // Output + // Take out 8 bits from the string. + byte[] temp = Encoding.Unicode.GetBytes(entry); + for (int i = 0; i < temp.Length; i++) { - output[outputAddIndex] = temp[i]; - outputAddIndex++; + if (i % 2 == 0) + { + output[outputAddIndex] = temp[i]; + outputAddIndex++; + } } - } - if (outputAddIndex >= needDataSize) - { - // Exit - break; - } + if (outputAddIndex >= needDataSize) + { + // Exit + break; + } - if (prevEntry != null) - { - // Add to dictionary - dic.Add(dic.Count, prevEntry + entry[0]); - } + if (prevEntry != null) + { + // Add to dictionary + dic.Add(dic.Count, prevEntry + entry[0]); + } - prevEntry = entry; + prevEntry = entry; - bitDataIndex += lzwCodeSize; + bitDataIndex += lzwCodeSize; - if (lzwCodeSize == 3 && dic.Count >= 8) - { - lzwCodeSize = 4; - } - else if (lzwCodeSize == 4 && dic.Count >= 16) - { - lzwCodeSize = 5; - } - else if (lzwCodeSize == 5 && dic.Count >= 32) - { - lzwCodeSize = 6; - } - else if (lzwCodeSize == 6 && dic.Count >= 64) - { - lzwCodeSize = 7; - } - else if (lzwCodeSize == 7 && dic.Count >= 128) - { - lzwCodeSize = 8; - } - else if (lzwCodeSize == 8 && dic.Count >= 256) - { - lzwCodeSize = 9; - } - else if (lzwCodeSize == 9 && dic.Count >= 512) - { - lzwCodeSize = 10; - } - else if (lzwCodeSize == 10 && dic.Count >= 1024) - { - lzwCodeSize = 11; - } - else if (lzwCodeSize == 11 && dic.Count >= 2048) - { - lzwCodeSize = 12; - } - else if (lzwCodeSize == 12 && dic.Count >= 4096) - { - int nextKey = bitData.GetNumeral(bitDataIndex, lzwCodeSize); - if (nextKey != clearCode) + if (lzwCodeSize == 3 && dic.Count >= 8) { - dicInitFlag = true; + lzwCodeSize = 4; + } + else if (lzwCodeSize == 4 && dic.Count >= 16) + { + lzwCodeSize = 5; + } + else if (lzwCodeSize == 5 && dic.Count >= 32) + { + lzwCodeSize = 6; + } + else if (lzwCodeSize == 6 && dic.Count >= 64) + { + lzwCodeSize = 7; + } + else if (lzwCodeSize == 7 && dic.Count >= 128) + { + lzwCodeSize = 8; + } + else if (lzwCodeSize == 8 && dic.Count >= 256) + { + lzwCodeSize = 9; + } + else if (lzwCodeSize == 9 && dic.Count >= 512) + { + lzwCodeSize = 10; + } + else if (lzwCodeSize == 10 && dic.Count >= 1024) + { + lzwCodeSize = 11; + } + else if (lzwCodeSize == 11 && dic.Count >= 2048) + { + lzwCodeSize = 12; + } + else if (lzwCodeSize == 12 && dic.Count >= 4096) + { + int nextKey = bitData.GetNumeral(bitDataIndex, lzwCodeSize); + if (nextKey != clearCode) + { + dicInitFlag = true; + } } } - } - - return output; - } - - /// - /// Initialize dictionary - /// - /// Dictionary - /// LZW minimum code size - /// out LZW code size - /// out Clear code - /// out Finish code - private static void InitDictionary(Dictionary dic, int lzwMinimumCodeSize, out int lzwCodeSize, out int clearCode, out int finishCode) - { - int dicLength = (int)Math.Pow(2, lzwMinimumCodeSize); - - clearCode = dicLength; - finishCode = clearCode + 1; - dic.Clear(); + return output; + } - for (int i = 0; i < dicLength + 2; i++) + /// + /// Initialize dictionary + /// + /// Dictionary + /// LZW minimum code size + /// out LZW code size + /// out Clear code + /// out Finish code + private static void InitDictionary(Dictionary dic, int lzwMinimumCodeSize, out int lzwCodeSize, out int clearCode, out int finishCode) { - dic.Add(i, ((char)i).ToString()); - } + int dicLength = (int)Math.Pow(2, lzwMinimumCodeSize); - lzwCodeSize = lzwMinimumCodeSize + 1; - } + clearCode = dicLength; + finishCode = clearCode + 1; - /// - /// Sort interlace GIF data - /// - /// Decoded GIF data - /// Pixel number of horizontal row - /// Sorted data - private static byte[] SortInterlaceGifData(byte[] decodedData, int xNum) - { - int rowNo = 0; - int dataIndex = 0; - var newArr = new byte[decodedData.Length]; - // Every 8th. row, starting with row 0. - for (int i = 0; i < newArr.Length; i++) - { - if (rowNo % 8 == 0) - { - newArr[i] = decodedData[dataIndex]; - dataIndex++; - } - if (i != 0 && i % xNum == 0) - { - rowNo++; - } - } - rowNo = 0; - // Every 8th. row, starting with row 4. - for (int i = 0; i < newArr.Length; i++) - { - if (rowNo % 8 == 4) - { - newArr[i] = decodedData[dataIndex]; - dataIndex++; - } - if (i != 0 && i % xNum == 0) + dic.Clear(); + + for (int i = 0; i < dicLength + 2; i++) { - rowNo++; + dic.Add(i, ((char)i).ToString()); } + + lzwCodeSize = lzwMinimumCodeSize + 1; } - rowNo = 0; - // Every 4th. row, starting with row 2. - for (int i = 0; i < newArr.Length; i++) + + /// + /// Sort interlace GIF data + /// + /// Decoded GIF data + /// Pixel number of horizontal row + /// Sorted data + private static byte[] SortInterlaceGifData(byte[] decodedData, int xNum) { - if (rowNo % 4 == 2) + int rowNo = 0; + int dataIndex = 0; + var newArr = new byte[decodedData.Length]; + // Every 8th. row, starting with row 0. + for (int i = 0; i < newArr.Length; i++) { - newArr[i] = decodedData[dataIndex]; - dataIndex++; + if (rowNo % 8 == 0) + { + newArr[i] = decodedData[dataIndex]; + dataIndex++; + } + if (i != 0 && i % xNum == 0) + { + rowNo++; + } } - if (i != 0 && i % xNum == 0) + rowNo = 0; + // Every 8th. row, starting with row 4. + for (int i = 0; i < newArr.Length; i++) { - rowNo++; + if (rowNo % 8 == 4) + { + newArr[i] = decodedData[dataIndex]; + dataIndex++; + } + if (i != 0 && i % xNum == 0) + { + rowNo++; + } } - } - rowNo = 0; - // Every 2nd. row, starting with row 1. - for (int i = 0; i < newArr.Length; i++) - { - if (rowNo % 8 != 0 && rowNo % 8 != 4 && rowNo % 4 != 2) + rowNo = 0; + // Every 4th. row, starting with row 2. + for (int i = 0; i < newArr.Length; i++) { - newArr[i] = decodedData[dataIndex]; - dataIndex++; + if (rowNo % 4 == 2) + { + newArr[i] = decodedData[dataIndex]; + dataIndex++; + } + if (i != 0 && i % xNum == 0) + { + rowNo++; + } } - if (i != 0 && i % xNum == 0) + rowNo = 0; + // Every 2nd. row, starting with row 1. + for (int i = 0; i < newArr.Length; i++) { - rowNo++; + if (rowNo % 8 != 0 && rowNo % 8 != 4 && rowNo % 4 != 2) + { + newArr[i] = decodedData[dataIndex]; + dataIndex++; + } + if (i != 0 && i % xNum == 0) + { + rowNo++; + } } + + return newArr; } - return newArr; + #endregion } - - #endregion } \ No newline at end of file diff --git a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifExtension.cs b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifExtension.cs index 03e8626..7b89c4a 100644 --- a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifExtension.cs +++ b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifExtension.cs @@ -1,56 +1,59 @@ using UnityEngine; using System.Collections; -/// -/// Extension methods class -/// -public static class UniGifExtension +namespace BeatSaberDrinkWater.UniGif { /// - /// Convert BitArray to int (Specifies the start index and bit length) + /// Extension methods class /// - /// Start index - /// Bit length - /// Converted int - public static int GetNumeral(this BitArray array, int startIndex, int bitLength) + public static class UniGifExtension { - var newArray = new BitArray(bitLength); + /// + /// Convert BitArray to int (Specifies the start index and bit length) + /// + /// Start index + /// Bit length + /// Converted int + public static int GetNumeral(this BitArray array, int startIndex, int bitLength) + { + var newArray = new BitArray(bitLength); + + for (int i = 0; i < bitLength; i++) + { + if (array.Length <= startIndex + i) + { + newArray[i] = false; + } + else + { + bool bit = array.Get(startIndex + i); + newArray[i] = bit; + } + } - for (int i = 0; i < bitLength; i++) + return newArray.ToNumeral(); + } + + /// + /// Convert BitArray to int + /// + /// Converted int + public static int ToNumeral(this BitArray array) { - if (array.Length <= startIndex + i) + if (array == null) { - newArray[i] = false; + Debug.LogError("array is nothing."); + return 0; } - else + if (array.Length > 32) { - bool bit = array.Get(startIndex + i); - newArray[i] = bit; + Debug.LogError("must be at most 32 bits long."); + return 0; } - } - - return newArray.ToNumeral(); - } - /// - /// Convert BitArray to int - /// - /// Converted int - public static int ToNumeral(this BitArray array) - { - if (array == null) - { - Debug.LogError("array is nothing."); - return 0; - } - if (array.Length > 32) - { - Debug.LogError("must be at most 32 bits long."); - return 0; + var result = new int[1]; + array.CopyTo(result, 0); + return result[0]; } - - var result = new int[1]; - array.CopyTo(result, 0); - return result[0]; } -} +} \ No newline at end of file diff --git a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifFormatter.cs b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifFormatter.cs index 11c3960..4e78fa8 100644 --- a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifFormatter.cs +++ b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifFormatter.cs @@ -9,595 +9,598 @@ This software is released under the MIT License. using System.Collections.Generic; using UnityEngine; -public static partial class UniGif +namespace BeatSaberDrinkWater.UniGif { - /// - /// Set GIF data - /// - /// GIF byte data - /// ref GIF data - /// Debug log flag - /// Result - private static bool SetGifData(byte[] gifBytes, ref GifData gifData, bool debugLog) + public static partial class UniGif { - if (debugLog) + /// + /// Set GIF data + /// + /// GIF byte data + /// ref GIF data + /// Debug log flag + /// Result + private static bool SetGifData(byte[] gifBytes, ref GifData gifData, bool debugLog) { - Debug.Log("SetGifData Start."); - } + if (debugLog) + { + Debug.Log("SetGifData Start."); + } - if (gifBytes == null || gifBytes.Length <= 0) - { - Debug.LogError("bytes is nothing."); - return false; - } + if (gifBytes == null || gifBytes.Length <= 0) + { + Debug.LogError("bytes is nothing."); + return false; + } - int byteIndex = 0; + int byteIndex = 0; - if (SetGifHeader(gifBytes, ref byteIndex, ref gifData) == false) - { - Debug.LogError("GIF header set error."); - return false; - } + if (SetGifHeader(gifBytes, ref byteIndex, ref gifData) == false) + { + Debug.LogError("GIF header set error."); + return false; + } - if (SetGifBlock(gifBytes, ref byteIndex, ref gifData) == false) - { - Debug.LogError("GIF block set error."); - return false; - } + if (SetGifBlock(gifBytes, ref byteIndex, ref gifData) == false) + { + Debug.LogError("GIF block set error."); + return false; + } - if (debugLog) - { - gifData.Dump(); - Debug.Log("SetGifData Finish."); + if (debugLog) + { + gifData.Dump(); + Debug.Log("SetGifData Finish."); + } + return true; } - return true; - } - private static bool SetGifHeader(byte[] gifBytes, ref int byteIndex, ref GifData gifData) - { - // Signature(3 Bytes) - // 0x47 0x49 0x46 (GIF) - if (gifBytes[0] != 'G' || gifBytes[1] != 'I' || gifBytes[2] != 'F') - { - Debug.LogError("This is not GIF image."); - return false; - } - gifData.m_sig0 = gifBytes[0]; - gifData.m_sig1 = gifBytes[1]; - gifData.m_sig2 = gifBytes[2]; - - // Version(3 Bytes) - // 0x38 0x37 0x61 (87a) or 0x38 0x39 0x61 (89a) - if ((gifBytes[3] != '8' || gifBytes[4] != '7' || gifBytes[5] != 'a') && - (gifBytes[3] != '8' || gifBytes[4] != '9' || gifBytes[5] != 'a')) + private static bool SetGifHeader(byte[] gifBytes, ref int byteIndex, ref GifData gifData) { - Debug.LogError("GIF version error.\nSupported only GIF87a or GIF89a."); - return false; - } - gifData.m_ver0 = gifBytes[3]; - gifData.m_ver1 = gifBytes[4]; - gifData.m_ver2 = gifBytes[5]; + // Signature(3 Bytes) + // 0x47 0x49 0x46 (GIF) + if (gifBytes[0] != 'G' || gifBytes[1] != 'I' || gifBytes[2] != 'F') + { + Debug.LogError("This is not GIF image."); + return false; + } + gifData.m_sig0 = gifBytes[0]; + gifData.m_sig1 = gifBytes[1]; + gifData.m_sig2 = gifBytes[2]; + + // Version(3 Bytes) + // 0x38 0x37 0x61 (87a) or 0x38 0x39 0x61 (89a) + if ((gifBytes[3] != '8' || gifBytes[4] != '7' || gifBytes[5] != 'a') && + (gifBytes[3] != '8' || gifBytes[4] != '9' || gifBytes[5] != 'a')) + { + Debug.LogError("GIF version error.\nSupported only GIF87a or GIF89a."); + return false; + } + gifData.m_ver0 = gifBytes[3]; + gifData.m_ver1 = gifBytes[4]; + gifData.m_ver2 = gifBytes[5]; - // Logical Screen Width(2 Bytes) - gifData.m_logicalScreenWidth = BitConverter.ToUInt16(gifBytes, 6); + // Logical Screen Width(2 Bytes) + gifData.m_logicalScreenWidth = BitConverter.ToUInt16(gifBytes, 6); - // Logical Screen Height(2 Bytes) - gifData.m_logicalScreenHeight = BitConverter.ToUInt16(gifBytes, 8); + // Logical Screen Height(2 Bytes) + gifData.m_logicalScreenHeight = BitConverter.ToUInt16(gifBytes, 8); - // 1 Byte - { - // Global Color Table Flag(1 Bit) - gifData.m_globalColorTableFlag = (gifBytes[10] & 128) == 128; // 0b10000000 - - // Color Resolution(3 Bits) - switch (gifBytes[10] & 112) + // 1 Byte { - case 112: // 0b01110000 - gifData.m_colorResolution = 8; - break; - case 96: // 0b01100000 - gifData.m_colorResolution = 7; - break; - case 80: // 0b01010000 - gifData.m_colorResolution = 6; - break; - case 64: // 0b01000000 - gifData.m_colorResolution = 5; - break; - case 48: // 0b00110000 - gifData.m_colorResolution = 4; - break; - case 32: // 0b00100000 - gifData.m_colorResolution = 3; - break; - case 16: // 0b00010000 - gifData.m_colorResolution = 2; - break; - default: - gifData.m_colorResolution = 1; - break; - } + // Global Color Table Flag(1 Bit) + gifData.m_globalColorTableFlag = (gifBytes[10] & 128) == 128; // 0b10000000 - // Sort Flag(1 Bit) - gifData.m_sortFlag = (gifBytes[10] & 8) == 8; // 0b00001000 + // Color Resolution(3 Bits) + switch (gifBytes[10] & 112) + { + case 112: // 0b01110000 + gifData.m_colorResolution = 8; + break; + case 96: // 0b01100000 + gifData.m_colorResolution = 7; + break; + case 80: // 0b01010000 + gifData.m_colorResolution = 6; + break; + case 64: // 0b01000000 + gifData.m_colorResolution = 5; + break; + case 48: // 0b00110000 + gifData.m_colorResolution = 4; + break; + case 32: // 0b00100000 + gifData.m_colorResolution = 3; + break; + case 16: // 0b00010000 + gifData.m_colorResolution = 2; + break; + default: + gifData.m_colorResolution = 1; + break; + } - // Size of Global Color Table(3 Bits) - int val = (gifBytes[10] & 7) + 1; - gifData.m_sizeOfGlobalColorTable = (int)Math.Pow(2, val); - } + // Sort Flag(1 Bit) + gifData.m_sortFlag = (gifBytes[10] & 8) == 8; // 0b00001000 - // Background Color Index(1 Byte) - gifData.m_bgColorIndex = gifBytes[11]; + // Size of Global Color Table(3 Bits) + int val = (gifBytes[10] & 7) + 1; + gifData.m_sizeOfGlobalColorTable = (int)Math.Pow(2, val); + } - // Pixel Aspect Ratio(1 Byte) - gifData.m_pixelAspectRatio = gifBytes[12]; + // Background Color Index(1 Byte) + gifData.m_bgColorIndex = gifBytes[11]; - byteIndex = 13; - if (gifData.m_globalColorTableFlag) - { - // Global Color Table(0~255×3 Bytes) - gifData.m_globalColorTable = new List(); - for (int i = byteIndex; i < byteIndex + (gifData.m_sizeOfGlobalColorTable * 3); i += 3) + // Pixel Aspect Ratio(1 Byte) + gifData.m_pixelAspectRatio = gifBytes[12]; + + byteIndex = 13; + if (gifData.m_globalColorTableFlag) { - gifData.m_globalColorTable.Add(new byte[] { gifBytes[i], gifBytes[i + 1], gifBytes[i + 2] }); + // Global Color Table(0~255×3 Bytes) + gifData.m_globalColorTable = new List(); + for (int i = byteIndex; i < byteIndex + (gifData.m_sizeOfGlobalColorTable * 3); i += 3) + { + gifData.m_globalColorTable.Add(new byte[] { gifBytes[i], gifBytes[i + 1], gifBytes[i + 2] }); + } + byteIndex = byteIndex + (gifData.m_sizeOfGlobalColorTable * 3); } - byteIndex = byteIndex + (gifData.m_sizeOfGlobalColorTable * 3); - } - return true; - } + return true; + } - private static bool SetGifBlock(byte[] gifBytes, ref int byteIndex, ref GifData gifData) - { - try + private static bool SetGifBlock(byte[] gifBytes, ref int byteIndex, ref GifData gifData) { - int lastIndex = 0; - while (true) + try { - int nowIndex = byteIndex; - - if (gifBytes[nowIndex] == 0x2c) + int lastIndex = 0; + while (true) { - // Image Block(0x2c) - SetImageBlock(gifBytes, ref byteIndex, ref gifData); + int nowIndex = byteIndex; - } - else if (gifBytes[nowIndex] == 0x21) - { - // Extension - switch (gifBytes[nowIndex + 1]) + if (gifBytes[nowIndex] == 0x2c) { - case 0xf9: - // Graphic Control Extension(0x21 0xf9) - SetGraphicControlExtension(gifBytes, ref byteIndex, ref gifData); - break; - case 0xfe: - // Comment Extension(0x21 0xfe) - SetCommentExtension(gifBytes, ref byteIndex, ref gifData); - break; - case 0x01: - // Plain Text Extension(0x21 0x01) - SetPlainTextExtension(gifBytes, ref byteIndex, ref gifData); - break; - case 0xff: - // Application Extension(0x21 0xff) - SetApplicationExtension(gifBytes, ref byteIndex, ref gifData); - break; - default: - break; + // Image Block(0x2c) + SetImageBlock(gifBytes, ref byteIndex, ref gifData); + + } + else if (gifBytes[nowIndex] == 0x21) + { + // Extension + switch (gifBytes[nowIndex + 1]) + { + case 0xf9: + // Graphic Control Extension(0x21 0xf9) + SetGraphicControlExtension(gifBytes, ref byteIndex, ref gifData); + break; + case 0xfe: + // Comment Extension(0x21 0xfe) + SetCommentExtension(gifBytes, ref byteIndex, ref gifData); + break; + case 0x01: + // Plain Text Extension(0x21 0x01) + SetPlainTextExtension(gifBytes, ref byteIndex, ref gifData); + break; + case 0xff: + // Application Extension(0x21 0xff) + SetApplicationExtension(gifBytes, ref byteIndex, ref gifData); + break; + default: + break; + } + } + else if (gifBytes[nowIndex] == 0x3b) + { + // Trailer(1 Byte) + gifData.m_trailer = gifBytes[byteIndex]; + byteIndex++; + break; } - } - else if (gifBytes[nowIndex] == 0x3b) - { - // Trailer(1 Byte) - gifData.m_trailer = gifBytes[byteIndex]; - byteIndex++; - break; - } - if (lastIndex == nowIndex) - { - Debug.LogError("Infinite loop error."); - return false; - } + if (lastIndex == nowIndex) + { + Debug.LogError("Infinite loop error."); + return false; + } - lastIndex = nowIndex; + lastIndex = nowIndex; + } + } + catch (Exception ex) + { + Debug.LogError(ex.Message); + return false; } - } - catch (Exception ex) - { - Debug.LogError(ex.Message); - return false; - } - return true; - } + return true; + } - private static void SetImageBlock(byte[] gifBytes, ref int byteIndex, ref GifData gifData) - { - ImageBlock ib = new ImageBlock(); + private static void SetImageBlock(byte[] gifBytes, ref int byteIndex, ref GifData gifData) + { + ImageBlock ib = new ImageBlock(); - // Image Separator(1 Byte) - // 0x2c - ib.m_imageSeparator = gifBytes[byteIndex]; - byteIndex++; + // Image Separator(1 Byte) + // 0x2c + ib.m_imageSeparator = gifBytes[byteIndex]; + byteIndex++; - // Image Left Position(2 Bytes) - ib.m_imageLeftPosition = BitConverter.ToUInt16(gifBytes, byteIndex); - byteIndex += 2; + // Image Left Position(2 Bytes) + ib.m_imageLeftPosition = BitConverter.ToUInt16(gifBytes, byteIndex); + byteIndex += 2; - // Image Top Position(2 Bytes) - ib.m_imageTopPosition = BitConverter.ToUInt16(gifBytes, byteIndex); - byteIndex += 2; + // Image Top Position(2 Bytes) + ib.m_imageTopPosition = BitConverter.ToUInt16(gifBytes, byteIndex); + byteIndex += 2; - // Image Width(2 Bytes) - ib.m_imageWidth = BitConverter.ToUInt16(gifBytes, byteIndex); - byteIndex += 2; + // Image Width(2 Bytes) + ib.m_imageWidth = BitConverter.ToUInt16(gifBytes, byteIndex); + byteIndex += 2; - // Image Height(2 Bytes) - ib.m_imageHeight = BitConverter.ToUInt16(gifBytes, byteIndex); - byteIndex += 2; + // Image Height(2 Bytes) + ib.m_imageHeight = BitConverter.ToUInt16(gifBytes, byteIndex); + byteIndex += 2; - // 1 Byte - { - // Local Color Table Flag(1 Bit) - ib.m_localColorTableFlag = (gifBytes[byteIndex] & 128) == 128; // 0b10000000 + // 1 Byte + { + // Local Color Table Flag(1 Bit) + ib.m_localColorTableFlag = (gifBytes[byteIndex] & 128) == 128; // 0b10000000 - // Interlace Flag(1 Bit) - ib.m_interlaceFlag = (gifBytes[byteIndex] & 64) == 64; // 0b01000000 + // Interlace Flag(1 Bit) + ib.m_interlaceFlag = (gifBytes[byteIndex] & 64) == 64; // 0b01000000 - // Sort Flag(1 Bit) - ib.m_sortFlag = (gifBytes[byteIndex] & 32) == 32; // 0b00100000 + // Sort Flag(1 Bit) + ib.m_sortFlag = (gifBytes[byteIndex] & 32) == 32; // 0b00100000 - // Reserved(2 Bits) - // Unused + // Reserved(2 Bits) + // Unused - // Size of Local Color Table(3 Bits) - int val = (gifBytes[byteIndex] & 7) + 1; - ib.m_sizeOfLocalColorTable = (int)Math.Pow(2, val); + // Size of Local Color Table(3 Bits) + int val = (gifBytes[byteIndex] & 7) + 1; + ib.m_sizeOfLocalColorTable = (int)Math.Pow(2, val); - byteIndex++; - } + byteIndex++; + } - if (ib.m_localColorTableFlag) - { - // Local Color Table(0~255×3 Bytes) - ib.m_localColorTable = new List(); - for (int i = byteIndex; i < byteIndex + (ib.m_sizeOfLocalColorTable * 3); i += 3) + if (ib.m_localColorTableFlag) { - ib.m_localColorTable.Add(new byte[] { gifBytes[i], gifBytes[i + 1], gifBytes[i + 2] }); + // Local Color Table(0~255×3 Bytes) + ib.m_localColorTable = new List(); + for (int i = byteIndex; i < byteIndex + (ib.m_sizeOfLocalColorTable * 3); i += 3) + { + ib.m_localColorTable.Add(new byte[] { gifBytes[i], gifBytes[i + 1], gifBytes[i + 2] }); + } + byteIndex = byteIndex + (ib.m_sizeOfLocalColorTable * 3); } - byteIndex = byteIndex + (ib.m_sizeOfLocalColorTable * 3); - } - // LZW Minimum Code Size(1 Byte) - ib.m_lzwMinimumCodeSize = gifBytes[byteIndex]; - byteIndex++; - - // Block Size & Image Data List - while (true) - { - // Block Size(1 Byte) - byte blockSize = gifBytes[byteIndex]; + // LZW Minimum Code Size(1 Byte) + ib.m_lzwMinimumCodeSize = gifBytes[byteIndex]; byteIndex++; - if (blockSize == 0x00) + // Block Size & Image Data List + while (true) { - // Block Terminator(1 Byte) - break; - } + // Block Size(1 Byte) + byte blockSize = gifBytes[byteIndex]; + byteIndex++; - var imageDataBlock = new ImageBlock.ImageDataBlock(); - imageDataBlock.m_blockSize = blockSize; + if (blockSize == 0x00) + { + // Block Terminator(1 Byte) + break; + } - // Image Data(? Bytes) - imageDataBlock.m_imageData = new byte[imageDataBlock.m_blockSize]; - for (int i = 0; i < imageDataBlock.m_imageData.Length; i++) - { - imageDataBlock.m_imageData[i] = gifBytes[byteIndex]; - byteIndex++; + var imageDataBlock = new ImageBlock.ImageDataBlock(); + imageDataBlock.m_blockSize = blockSize; + + // Image Data(? Bytes) + imageDataBlock.m_imageData = new byte[imageDataBlock.m_blockSize]; + for (int i = 0; i < imageDataBlock.m_imageData.Length; i++) + { + imageDataBlock.m_imageData[i] = gifBytes[byteIndex]; + byteIndex++; + } + + if (ib.m_imageDataList == null) + { + ib.m_imageDataList = new List(); + } + ib.m_imageDataList.Add(imageDataBlock); } - if (ib.m_imageDataList == null) + if (gifData.m_imageBlockList == null) { - ib.m_imageDataList = new List(); + gifData.m_imageBlockList = new List(); } - ib.m_imageDataList.Add(imageDataBlock); + gifData.m_imageBlockList.Add(ib); } - if (gifData.m_imageBlockList == null) + private static void SetGraphicControlExtension(byte[] gifBytes, ref int byteIndex, ref GifData gifData) { - gifData.m_imageBlockList = new List(); - } - gifData.m_imageBlockList.Add(ib); - } + GraphicControlExtension gcEx = new GraphicControlExtension(); - private static void SetGraphicControlExtension(byte[] gifBytes, ref int byteIndex, ref GifData gifData) - { - GraphicControlExtension gcEx = new GraphicControlExtension(); - - // Extension Introducer(1 Byte) - // 0x21 - gcEx.m_extensionIntroducer = gifBytes[byteIndex]; - byteIndex++; + // Extension Introducer(1 Byte) + // 0x21 + gcEx.m_extensionIntroducer = gifBytes[byteIndex]; + byteIndex++; - // Graphic Control Label(1 Byte) - // 0xf9 - gcEx.m_graphicControlLabel = gifBytes[byteIndex]; - byteIndex++; + // Graphic Control Label(1 Byte) + // 0xf9 + gcEx.m_graphicControlLabel = gifBytes[byteIndex]; + byteIndex++; - // Block Size(1 Byte) - // 0x04 - gcEx.m_blockSize = gifBytes[byteIndex]; - byteIndex++; + // Block Size(1 Byte) + // 0x04 + gcEx.m_blockSize = gifBytes[byteIndex]; + byteIndex++; - // 1 Byte - { - // Reserved(3 Bits) - // Unused - - // Disposal Mothod(3 Bits) - // 0 (No disposal specified) - // 1 (Do not dispose) - // 2 (Restore to background color) - // 3 (Restore to previous) - switch (gifBytes[byteIndex] & 28) - { // 0b00011100 - case 4: // 0b00000100 - gcEx.m_disposalMethod = 1; - break; - case 8: // 0b00001000 - gcEx.m_disposalMethod = 2; - break; - case 12: // 0b00001100 - gcEx.m_disposalMethod = 3; - break; - default: - gcEx.m_disposalMethod = 0; - break; - } + // 1 Byte + { + // Reserved(3 Bits) + // Unused + + // Disposal Mothod(3 Bits) + // 0 (No disposal specified) + // 1 (Do not dispose) + // 2 (Restore to background color) + // 3 (Restore to previous) + switch (gifBytes[byteIndex] & 28) + { // 0b00011100 + case 4: // 0b00000100 + gcEx.m_disposalMethod = 1; + break; + case 8: // 0b00001000 + gcEx.m_disposalMethod = 2; + break; + case 12: // 0b00001100 + gcEx.m_disposalMethod = 3; + break; + default: + gcEx.m_disposalMethod = 0; + break; + } - // User Input Flag(1 Bit) - // Unknown + // User Input Flag(1 Bit) + // Unknown - // Transparent Color Flag(1 Bit) - gcEx.m_transparentColorFlag = (gifBytes[byteIndex] & 1) == 1; // 0b00000001 + // Transparent Color Flag(1 Bit) + gcEx.m_transparentColorFlag = (gifBytes[byteIndex] & 1) == 1; // 0b00000001 - byteIndex++; - } + byteIndex++; + } - // Delay Time(2 Bytes) - gcEx.m_delayTime = BitConverter.ToUInt16(gifBytes, byteIndex); - byteIndex += 2; + // Delay Time(2 Bytes) + gcEx.m_delayTime = BitConverter.ToUInt16(gifBytes, byteIndex); + byteIndex += 2; - // Transparent Color Index(1 Byte) - gcEx.m_transparentColorIndex = gifBytes[byteIndex]; - byteIndex++; + // Transparent Color Index(1 Byte) + gcEx.m_transparentColorIndex = gifBytes[byteIndex]; + byteIndex++; - // Block Terminator(1 Byte) - gcEx.m_blockTerminator = gifBytes[byteIndex]; - byteIndex++; + // Block Terminator(1 Byte) + gcEx.m_blockTerminator = gifBytes[byteIndex]; + byteIndex++; - if (gifData.m_graphicCtrlExList == null) - { - gifData.m_graphicCtrlExList = new List(); + if (gifData.m_graphicCtrlExList == null) + { + gifData.m_graphicCtrlExList = new List(); + } + gifData.m_graphicCtrlExList.Add(gcEx); } - gifData.m_graphicCtrlExList.Add(gcEx); - } - private static void SetCommentExtension(byte[] gifBytes, ref int byteIndex, ref GifData gifData) - { - CommentExtension commentEx = new CommentExtension(); - - // Extension Introducer(1 Byte) - // 0x21 - commentEx.m_extensionIntroducer = gifBytes[byteIndex]; - byteIndex++; + private static void SetCommentExtension(byte[] gifBytes, ref int byteIndex, ref GifData gifData) + { + CommentExtension commentEx = new CommentExtension(); - // Comment Label(1 Byte) - // 0xfe - commentEx.m_commentLabel = gifBytes[byteIndex]; - byteIndex++; + // Extension Introducer(1 Byte) + // 0x21 + commentEx.m_extensionIntroducer = gifBytes[byteIndex]; + byteIndex++; - // Block Size & Comment Data List - while (true) - { - // Block Size(1 Byte) - byte blockSize = gifBytes[byteIndex]; + // Comment Label(1 Byte) + // 0xfe + commentEx.m_commentLabel = gifBytes[byteIndex]; byteIndex++; - if (blockSize == 0x00) + // Block Size & Comment Data List + while (true) { - // Block Terminator(1 Byte) - break; - } + // Block Size(1 Byte) + byte blockSize = gifBytes[byteIndex]; + byteIndex++; + + if (blockSize == 0x00) + { + // Block Terminator(1 Byte) + break; + } - var commentDataBlock = new CommentExtension.CommentDataBlock(); - commentDataBlock.m_blockSize = blockSize; + var commentDataBlock = new CommentExtension.CommentDataBlock(); + commentDataBlock.m_blockSize = blockSize; - // Comment Data(n Byte) - commentDataBlock.m_commentData = new byte[commentDataBlock.m_blockSize]; - for (int i = 0; i < commentDataBlock.m_commentData.Length; i++) - { - commentDataBlock.m_commentData[i] = gifBytes[byteIndex]; - byteIndex++; + // Comment Data(n Byte) + commentDataBlock.m_commentData = new byte[commentDataBlock.m_blockSize]; + for (int i = 0; i < commentDataBlock.m_commentData.Length; i++) + { + commentDataBlock.m_commentData[i] = gifBytes[byteIndex]; + byteIndex++; + } + + if (commentEx.m_commentDataList == null) + { + commentEx.m_commentDataList = new List(); + } + commentEx.m_commentDataList.Add(commentDataBlock); } - if (commentEx.m_commentDataList == null) + if (gifData.m_commentExList == null) { - commentEx.m_commentDataList = new List(); + gifData.m_commentExList = new List(); } - commentEx.m_commentDataList.Add(commentDataBlock); + gifData.m_commentExList.Add(commentEx); } - if (gifData.m_commentExList == null) + private static void SetPlainTextExtension(byte[] gifBytes, ref int byteIndex, ref GifData gifData) { - gifData.m_commentExList = new List(); - } - gifData.m_commentExList.Add(commentEx); - } - - private static void SetPlainTextExtension(byte[] gifBytes, ref int byteIndex, ref GifData gifData) - { - PlainTextExtension plainTxtEx = new PlainTextExtension(); + PlainTextExtension plainTxtEx = new PlainTextExtension(); - // Extension Introducer(1 Byte) - // 0x21 - plainTxtEx.m_extensionIntroducer = gifBytes[byteIndex]; - byteIndex++; - - // Plain Text Label(1 Byte) - // 0x01 - plainTxtEx.m_plainTextLabel = gifBytes[byteIndex]; - byteIndex++; + // Extension Introducer(1 Byte) + // 0x21 + plainTxtEx.m_extensionIntroducer = gifBytes[byteIndex]; + byteIndex++; - // Block Size(1 Byte) - // 0x0c - plainTxtEx.m_blockSize = gifBytes[byteIndex]; - byteIndex++; + // Plain Text Label(1 Byte) + // 0x01 + plainTxtEx.m_plainTextLabel = gifBytes[byteIndex]; + byteIndex++; - // Text Grid Left Position(2 Bytes) - // Not supported - byteIndex += 2; + // Block Size(1 Byte) + // 0x0c + plainTxtEx.m_blockSize = gifBytes[byteIndex]; + byteIndex++; - // Text Grid Top Position(2 Bytes) - // Not supported - byteIndex += 2; + // Text Grid Left Position(2 Bytes) + // Not supported + byteIndex += 2; - // Text Grid Width(2 Bytes) - // Not supported - byteIndex += 2; + // Text Grid Top Position(2 Bytes) + // Not supported + byteIndex += 2; - // Text Grid Height(2 Bytes) - // Not supported - byteIndex += 2; + // Text Grid Width(2 Bytes) + // Not supported + byteIndex += 2; - // Character Cell Width(1 Bytes) - // Not supported - byteIndex++; + // Text Grid Height(2 Bytes) + // Not supported + byteIndex += 2; - // Character Cell Height(1 Bytes) - // Not supported - byteIndex++; + // Character Cell Width(1 Bytes) + // Not supported + byteIndex++; - // Text Foreground Color Index(1 Bytes) - // Not supported - byteIndex++; + // Character Cell Height(1 Bytes) + // Not supported + byteIndex++; - // Text Background Color Index(1 Bytes) - // Not supported - byteIndex++; + // Text Foreground Color Index(1 Bytes) + // Not supported + byteIndex++; - // Block Size & Plain Text Data List - while (true) - { - // Block Size(1 Byte) - byte blockSize = gifBytes[byteIndex]; + // Text Background Color Index(1 Bytes) + // Not supported byteIndex++; - if (blockSize == 0x00) + // Block Size & Plain Text Data List + while (true) { - // Block Terminator(1 Byte) - break; - } + // Block Size(1 Byte) + byte blockSize = gifBytes[byteIndex]; + byteIndex++; - var plainTextDataBlock = new PlainTextExtension.PlainTextDataBlock(); - plainTextDataBlock.m_blockSize = blockSize; + if (blockSize == 0x00) + { + // Block Terminator(1 Byte) + break; + } - // Plain Text Data(n Byte) - plainTextDataBlock.m_plainTextData = new byte[plainTextDataBlock.m_blockSize]; - for (int i = 0; i < plainTextDataBlock.m_plainTextData.Length; i++) - { - plainTextDataBlock.m_plainTextData[i] = gifBytes[byteIndex]; - byteIndex++; + var plainTextDataBlock = new PlainTextExtension.PlainTextDataBlock(); + plainTextDataBlock.m_blockSize = blockSize; + + // Plain Text Data(n Byte) + plainTextDataBlock.m_plainTextData = new byte[plainTextDataBlock.m_blockSize]; + for (int i = 0; i < plainTextDataBlock.m_plainTextData.Length; i++) + { + plainTextDataBlock.m_plainTextData[i] = gifBytes[byteIndex]; + byteIndex++; + } + + if (plainTxtEx.m_plainTextDataList == null) + { + plainTxtEx.m_plainTextDataList = new List(); + } + plainTxtEx.m_plainTextDataList.Add(plainTextDataBlock); } - if (plainTxtEx.m_plainTextDataList == null) + if (gifData.m_plainTextExList == null) { - plainTxtEx.m_plainTextDataList = new List(); + gifData.m_plainTextExList = new List(); } - plainTxtEx.m_plainTextDataList.Add(plainTextDataBlock); + gifData.m_plainTextExList.Add(plainTxtEx); } - if (gifData.m_plainTextExList == null) + private static void SetApplicationExtension(byte[] gifBytes, ref int byteIndex, ref GifData gifData) { - gifData.m_plainTextExList = new List(); - } - gifData.m_plainTextExList.Add(plainTxtEx); - } + // Extension Introducer(1 Byte) + // 0x21 + gifData.m_appEx.m_extensionIntroducer = gifBytes[byteIndex]; + byteIndex++; - private static void SetApplicationExtension(byte[] gifBytes, ref int byteIndex, ref GifData gifData) - { - // Extension Introducer(1 Byte) - // 0x21 - gifData.m_appEx.m_extensionIntroducer = gifBytes[byteIndex]; - byteIndex++; - - // Extension Label(1 Byte) - // 0xff - gifData.m_appEx.m_extensionLabel = gifBytes[byteIndex]; - byteIndex++; - - // Block Size(1 Byte) - // 0x0b - gifData.m_appEx.m_blockSize = gifBytes[byteIndex]; - byteIndex++; - - // Application Identifier(8 Bytes) - gifData.m_appEx.m_appId1 = gifBytes[byteIndex]; - byteIndex++; - gifData.m_appEx.m_appId2 = gifBytes[byteIndex]; - byteIndex++; - gifData.m_appEx.m_appId3 = gifBytes[byteIndex]; - byteIndex++; - gifData.m_appEx.m_appId4 = gifBytes[byteIndex]; - byteIndex++; - gifData.m_appEx.m_appId5 = gifBytes[byteIndex]; - byteIndex++; - gifData.m_appEx.m_appId6 = gifBytes[byteIndex]; - byteIndex++; - gifData.m_appEx.m_appId7 = gifBytes[byteIndex]; - byteIndex++; - gifData.m_appEx.m_appId8 = gifBytes[byteIndex]; - byteIndex++; - - // Application Authentication Code(3 Bytes) - gifData.m_appEx.m_appAuthCode1 = gifBytes[byteIndex]; - byteIndex++; - gifData.m_appEx.m_appAuthCode2 = gifBytes[byteIndex]; - byteIndex++; - gifData.m_appEx.m_appAuthCode3 = gifBytes[byteIndex]; - byteIndex++; - - // Block Size & Application Data List - while (true) - { - // Block Size (1 Byte) - byte blockSize = gifBytes[byteIndex]; + // Extension Label(1 Byte) + // 0xff + gifData.m_appEx.m_extensionLabel = gifBytes[byteIndex]; byteIndex++; - if (blockSize == 0x00) - { - // Block Terminator(1 Byte) - break; - } + // Block Size(1 Byte) + // 0x0b + gifData.m_appEx.m_blockSize = gifBytes[byteIndex]; + byteIndex++; + + // Application Identifier(8 Bytes) + gifData.m_appEx.m_appId1 = gifBytes[byteIndex]; + byteIndex++; + gifData.m_appEx.m_appId2 = gifBytes[byteIndex]; + byteIndex++; + gifData.m_appEx.m_appId3 = gifBytes[byteIndex]; + byteIndex++; + gifData.m_appEx.m_appId4 = gifBytes[byteIndex]; + byteIndex++; + gifData.m_appEx.m_appId5 = gifBytes[byteIndex]; + byteIndex++; + gifData.m_appEx.m_appId6 = gifBytes[byteIndex]; + byteIndex++; + gifData.m_appEx.m_appId7 = gifBytes[byteIndex]; + byteIndex++; + gifData.m_appEx.m_appId8 = gifBytes[byteIndex]; + byteIndex++; - var appDataBlock = new ApplicationExtension.ApplicationDataBlock(); - appDataBlock.m_blockSize = blockSize; + // Application Authentication Code(3 Bytes) + gifData.m_appEx.m_appAuthCode1 = gifBytes[byteIndex]; + byteIndex++; + gifData.m_appEx.m_appAuthCode2 = gifBytes[byteIndex]; + byteIndex++; + gifData.m_appEx.m_appAuthCode3 = gifBytes[byteIndex]; + byteIndex++; - // Application Data(n Byte) - appDataBlock.m_applicationData = new byte[appDataBlock.m_blockSize]; - for (int i = 0; i < appDataBlock.m_applicationData.Length; i++) + // Block Size & Application Data List + while (true) { - appDataBlock.m_applicationData[i] = gifBytes[byteIndex]; + // Block Size (1 Byte) + byte blockSize = gifBytes[byteIndex]; byteIndex++; - } - if (gifData.m_appEx.m_appDataList == null) - { - gifData.m_appEx.m_appDataList = new List(); + if (blockSize == 0x00) + { + // Block Terminator(1 Byte) + break; + } + + var appDataBlock = new ApplicationExtension.ApplicationDataBlock(); + appDataBlock.m_blockSize = blockSize; + + // Application Data(n Byte) + appDataBlock.m_applicationData = new byte[appDataBlock.m_blockSize]; + for (int i = 0; i < appDataBlock.m_applicationData.Length; i++) + { + appDataBlock.m_applicationData[i] = gifBytes[byteIndex]; + byteIndex++; + } + + if (gifData.m_appEx.m_appDataList == null) + { + gifData.m_appEx.m_appDataList = new List(); + } + gifData.m_appEx.m_appDataList.Add(appDataBlock); } - gifData.m_appEx.m_appDataList.Add(appDataBlock); } } -} +} \ No newline at end of file diff --git a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifImage.cs b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifImage.cs index f96e91a..cce53da 100644 --- a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifImage.cs +++ b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/UniGifImage.cs @@ -11,347 +11,351 @@ This software is released under the MIT License. using UnityEngine; using UnityEngine.UI; using UnityEngine.Networking; +using BeatSaberDrinkWater.UniGif.Utility; -/// -/// Texture Animation from GIF image -/// -public class UniGifImage : MonoBehaviour +namespace BeatSaberDrinkWater.UniGif { /// - /// This component state + /// Texture Animation from GIF image /// - public enum State + public class UniGifImage : MonoBehaviour { - None, - Loading, - Ready, - Playing, - Pause, - } - - // Target row image - [SerializeField] - private RawImage m_rawImage; - // Image Aspect Controller - [SerializeField] - private UniGifImageAspectController m_imgAspectCtrl; - // Textures filter mode - [SerializeField] - private FilterMode m_filterMode = FilterMode.Point; - // Textures wrap mode - [SerializeField] - private TextureWrapMode m_wrapMode = TextureWrapMode.Clamp; - // Load from url on start - [SerializeField] - private bool m_loadOnStart; - // GIF image url (WEB or StreamingAssets path) - [SerializeField] - private string m_loadOnStartUrl; - // Rotating on loading - [SerializeField] - private bool m_rotateOnLoading; - // Debug log flag - [SerializeField] - private bool m_outputDebugLog; - - // Decoded GIF texture list - private List m_gifTextureList; - // Delay time - private float m_delayTime; - // Texture index - private int m_gifTextureIndex; - // loop counter - private int m_nowLoopCount; - - /// - /// Now state - /// - public State nowState - { - get; - private set; - } - - /// - /// Animation loop count (0 is infinite) - /// - public int loopCount - { - get; - private set; - } + /// + /// This component state + /// + public enum State + { + None, + Loading, + Ready, + Playing, + Pause, + } - /// - /// Texture width (px) - /// - public int width - { - get; - private set; - } + // Target row image + [SerializeField] + private RawImage m_rawImage; + // Image Aspect Controller + [SerializeField] + private UniGifImageAspectController m_imgAspectCtrl; + // Textures filter mode + [SerializeField] + private FilterMode m_filterMode = FilterMode.Point; + // Textures wrap mode + [SerializeField] + private TextureWrapMode m_wrapMode = TextureWrapMode.Clamp; + // Load from url on start + [SerializeField] + private bool m_loadOnStart; + // GIF image url (WEB or StreamingAssets path) + [SerializeField] + private string m_loadOnStartUrl; + // Rotating on loading + [SerializeField] + private bool m_rotateOnLoading; + // Debug log flag + [SerializeField] + private bool m_outputDebugLog; + + // Decoded GIF texture list + private List m_gifTextureList; + // Delay time + private float m_delayTime; + // Texture index + private int m_gifTextureIndex; + // loop counter + private int m_nowLoopCount; + + /// + /// Now state + /// + public State nowState + { + get; + private set; + } - /// - /// Texture height (px) - /// - public int height - { - get; - private set; - } + /// + /// Animation loop count (0 is infinite) + /// + public int loopCount + { + get; + private set; + } - private void Start() - { - if (m_rawImage == null) + /// + /// Texture width (px) + /// + public int width { - m_rawImage = GetComponent(); + get; + private set; } - if (m_loadOnStart) + + /// + /// Texture height (px) + /// + public int height { - SetGifFromUrl(m_loadOnStartUrl); + get; + private set; } - } - private void OnDestroy() - { - Clear(); - } + private void Start() + { + if (m_rawImage == null) + { + m_rawImage = GetComponent(); + } + if (m_loadOnStart) + { + SetGifFromUrl(m_loadOnStartUrl); + } + } - private void Update() - { - switch (nowState) + private void OnDestroy() { - case State.None: - break; + Clear(); + } - case State.Loading: - if (m_rotateOnLoading) - { - transform.Rotate(0f, 0f, 30f * Time.deltaTime, Space.Self); - } - break; + private void Update() + { + switch (nowState) + { + case State.None: + break; - case State.Ready: - break; + case State.Loading: + if (m_rotateOnLoading) + { + transform.Rotate(0f, 0f, 30f * Time.deltaTime, Space.Self); + } + break; - case State.Playing: - if (m_rawImage == null || m_gifTextureList == null || m_gifTextureList.Count <= 0) - { - return; - } - if (m_delayTime > Time.time) - { - return; - } - // Change texture - m_gifTextureIndex++; - if (m_gifTextureIndex >= m_gifTextureList.Count) - { - m_gifTextureIndex = 0; + case State.Ready: + break; - if (loopCount > 0) + case State.Playing: + if (m_rawImage == null || m_gifTextureList == null || m_gifTextureList.Count <= 0) + { + return; + } + if (m_delayTime > Time.time) { - m_nowLoopCount++; - if (m_nowLoopCount >= loopCount) + return; + } + // Change texture + m_gifTextureIndex++; + if (m_gifTextureIndex >= m_gifTextureList.Count) + { + m_gifTextureIndex = 0; + + if (loopCount > 0) { - Stop(); - return; + m_nowLoopCount++; + if (m_nowLoopCount >= loopCount) + { + Stop(); + return; + } } } - } - m_rawImage.texture = m_gifTextureList[m_gifTextureIndex].m_texture2d; - m_delayTime = Time.time + m_gifTextureList[m_gifTextureIndex].m_delaySec; - break; - - case State.Pause: - break; - - default: - break; - } - } - - /// - /// Set GIF texture from url - /// - /// GIF image url (WEB or StreamingAssets path) - /// Auto play after decode - public void SetGifFromUrl(string url, bool autoPlay = true) - { - StartCoroutine(SetGifFromUrlCoroutine(url, autoPlay)); - } + m_rawImage.texture = m_gifTextureList[m_gifTextureIndex].m_texture2d; + m_delayTime = Time.time + m_gifTextureList[m_gifTextureIndex].m_delaySec; + break; - /// - /// Set GIF texture from url - /// - /// GIF image url (WEB or StreamingAssets path) - /// Auto play after decode - /// IEnumerator - public IEnumerator SetGifFromUrlCoroutine(string url, bool autoPlay = true) - { - if (string.IsNullOrEmpty(url)) - { - Debug.LogError("URL is nothing."); - yield break; - } + case State.Pause: + break; - if (nowState == State.Loading) - { - Debug.LogWarning("Already loading."); - yield break; + default: + break; + } } - nowState = State.Loading; - string path; - if (url.StartsWith("http")) + /// + /// Set GIF texture from url + /// + /// GIF image url (WEB or StreamingAssets path) + /// Auto play after decode + public void SetGifFromUrl(string url, bool autoPlay = true) { - // from WEB - path = url; - } - else - { - // from StreamingAssets - path = Path.Combine("file:///" + Application.streamingAssetsPath, url); + StartCoroutine(SetGifFromUrlCoroutine(url, autoPlay)); } - // Load file - using (UnityWebRequest www = new UnityWebRequest(path)) + /// + /// Set GIF texture from url + /// + /// GIF image url (WEB or StreamingAssets path) + /// Auto play after decode + /// IEnumerator + public IEnumerator SetGifFromUrlCoroutine(string url, bool autoPlay = true) { - yield return www; - - if (string.IsNullOrEmpty(www.error) == false) + if (string.IsNullOrEmpty(url)) { - Debug.LogError("File load error.\n" + www.error); - nowState = State.None; + Debug.LogError("URL is nothing."); yield break; } - Clear(); + if (nowState == State.Loading) + { + Debug.LogWarning("Already loading."); + yield break; + } nowState = State.Loading; - // Get GIF textures - www.downloadHandler = new DownloadHandlerBuffer(); - yield return www.SendWebRequest(); - yield return StartCoroutine(UniGif.GetTextureListCoroutine(www.downloadHandler.data, (gifTexList, loopCount, width, height) => + string path; + if (url.StartsWith("http")) { - if (gifTexList != null) + // from WEB + path = url; + } + else + { + // from StreamingAssets + path = Path.Combine("file:///" + Application.streamingAssetsPath, url); + } + + // Load file + using (UnityWebRequest www = new UnityWebRequest(path)) + { + yield return www; + + if (string.IsNullOrEmpty(www.error) == false) { - m_gifTextureList = gifTexList; - this.loopCount = loopCount; - this.width = width; - this.height = height; - nowState = State.Ready; + Debug.LogError("File load error.\n" + www.error); + nowState = State.None; + yield break; + } - m_imgAspectCtrl.FixAspectRatio(width, height); + Clear(); + nowState = State.Loading; - if (m_rotateOnLoading) + // Get GIF textures + www.downloadHandler = new DownloadHandlerBuffer(); + yield return www.SendWebRequest(); + yield return StartCoroutine(UniGif.GetTextureListCoroutine(www.downloadHandler.data, (gifTexList, loopCount, width, height) => + { + if (gifTexList != null) { - transform.localEulerAngles = Vector3.zero; - } + m_gifTextureList = gifTexList; + this.loopCount = loopCount; + this.width = width; + this.height = height; + nowState = State.Ready; + + m_imgAspectCtrl.FixAspectRatio(width, height); - if (autoPlay) + if (m_rotateOnLoading) + { + transform.localEulerAngles = Vector3.zero; + } + + if (autoPlay) + { + Play(); + } + } + else { - Play(); + Debug.LogError("Gif texture get error."); + nowState = State.None; } - } - else - { - Debug.LogError("Gif texture get error."); - nowState = State.None; - } - }, - m_filterMode, m_wrapMode, m_outputDebugLog)); + }, + m_filterMode, m_wrapMode, m_outputDebugLog)); + } } - } - /// - /// Clear GIF texture - /// - public void Clear() - { - if (m_rawImage != null) + /// + /// Clear GIF texture + /// + public void Clear() { - m_rawImage.texture = null; - } + if (m_rawImage != null) + { + m_rawImage.texture = null; + } - if (m_gifTextureList != null) - { - for (int i = 0; i < m_gifTextureList.Count; i++) + if (m_gifTextureList != null) { - if (m_gifTextureList[i] != null) + for (int i = 0; i < m_gifTextureList.Count; i++) { - if (m_gifTextureList[i].m_texture2d != null) + if (m_gifTextureList[i] != null) { - Destroy(m_gifTextureList[i].m_texture2d); - m_gifTextureList[i].m_texture2d = null; + if (m_gifTextureList[i].m_texture2d != null) + { + Destroy(m_gifTextureList[i].m_texture2d); + m_gifTextureList[i].m_texture2d = null; + } + m_gifTextureList[i] = null; } - m_gifTextureList[i] = null; } + m_gifTextureList.Clear(); + m_gifTextureList = null; } - m_gifTextureList.Clear(); - m_gifTextureList = null; - } - - nowState = State.None; - } - /// - /// Play GIF animation - /// - public void Play() - { - if (nowState != State.Ready) - { - Debug.LogWarning("State is not READY."); - return; + nowState = State.None; } - if (m_rawImage == null || m_gifTextureList == null || m_gifTextureList.Count <= 0) + + /// + /// Play GIF animation + /// + public void Play() { - Debug.LogError("Raw Image or GIF Texture is nothing."); - return; + if (nowState != State.Ready) + { + Debug.LogWarning("State is not READY."); + return; + } + if (m_rawImage == null || m_gifTextureList == null || m_gifTextureList.Count <= 0) + { + Debug.LogError("Raw Image or GIF Texture is nothing."); + return; + } + nowState = State.Playing; + m_rawImage.texture = m_gifTextureList[0].m_texture2d; + m_delayTime = Time.time + m_gifTextureList[0].m_delaySec; + m_gifTextureIndex = 0; + m_nowLoopCount = 0; } - nowState = State.Playing; - m_rawImage.texture = m_gifTextureList[0].m_texture2d; - m_delayTime = Time.time + m_gifTextureList[0].m_delaySec; - m_gifTextureIndex = 0; - m_nowLoopCount = 0; - } - /// - /// Stop GIF animation - /// - public void Stop() - { - if (nowState != State.Playing && nowState != State.Pause) + /// + /// Stop GIF animation + /// + public void Stop() { - Debug.LogWarning("State is not Playing and Pause."); - return; + if (nowState != State.Playing && nowState != State.Pause) + { + Debug.LogWarning("State is not Playing and Pause."); + return; + } + nowState = State.Ready; } - nowState = State.Ready; - } - /// - /// Pause GIF animation - /// - public void Pause() - { - if (nowState != State.Playing) + /// + /// Pause GIF animation + /// + public void Pause() { - Debug.LogWarning("State is not Playing."); - return; + if (nowState != State.Playing) + { + Debug.LogWarning("State is not Playing."); + return; + } + nowState = State.Pause; } - nowState = State.Pause; - } - /// - /// Resume GIF animation - /// - public void Resume() - { - if (nowState != State.Pause) + /// + /// Resume GIF animation + /// + public void Resume() { - Debug.LogWarning("State is not Pause."); - return; + if (nowState != State.Pause) + { + Debug.LogWarning("State is not Pause."); + return; + } + nowState = State.Playing; } - nowState = State.Playing; } } \ No newline at end of file diff --git a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/Utility/UniGifImageAspectController.cs b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/Utility/UniGifImageAspectController.cs index eb47d80..74f86bf 100644 --- a/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/Utility/UniGifImageAspectController.cs +++ b/BeatSaberDrinkWater/BeatSaberDrinkWater/UniGif/Utility/UniGifImageAspectController.cs @@ -7,29 +7,31 @@ This software is released under the MIT License. using UnityEngine; -[ExecuteInEditMode] -public class UniGifImageAspectController : MonoBehaviour +namespace BeatSaberDrinkWater.UniGif.Utility { - public int m_originalWidth; - public int m_originalHeight; + [ExecuteInEditMode] + public class UniGifImageAspectController : MonoBehaviour + { + public int m_originalWidth; + public int m_originalHeight; - public bool m_fixOnUpdate; + public bool m_fixOnUpdate; - private Vector2 m_lastSize = Vector2.zero; - private Vector2 m_newSize = Vector2.zero; + private Vector2 m_lastSize = Vector2.zero; + private Vector2 m_newSize = Vector2.zero; - private RectTransform m_rectTransform; + private RectTransform m_rectTransform; - public RectTransform rectTransform - { - get + public RectTransform rectTransform { - return m_rectTransform != null ? m_rectTransform : (m_rectTransform = GetComponent()); + get + { + return m_rectTransform != null ? m_rectTransform : (m_rectTransform = GetComponent()); + } } - } - private void Update() - { + private void Update() + { #if UNITY_EDITOR if (Application.isPlaying == false) { @@ -38,52 +40,53 @@ private void Update() } #endif - if (m_fixOnUpdate) - { - FixAspectRatio(); + if (m_fixOnUpdate) + { + FixAspectRatio(); + } } - } - public void FixAspectRatio(int originalWidth = -1, int originalHeight = -1) - { - bool forceUpdate = false; - if (originalWidth > 0 && originalHeight > 0) - { - m_originalWidth = originalWidth; - m_originalHeight = originalHeight; - forceUpdate = true; - } - if (m_originalWidth <= 0 || m_originalHeight <= 0) + public void FixAspectRatio(int originalWidth = -1, int originalHeight = -1) { - return; - } + bool forceUpdate = false; + if (originalWidth > 0 && originalHeight > 0) + { + m_originalWidth = originalWidth; + m_originalHeight = originalHeight; + forceUpdate = true; + } + if (m_originalWidth <= 0 || m_originalHeight <= 0) + { + return; + } - bool changeX; - if (forceUpdate || m_lastSize.x != rectTransform.sizeDelta.x) - { - changeX = true; - } - else if (m_lastSize.y != rectTransform.sizeDelta.y) - { - changeX = false; - } - else - { - return; - } + bool changeX; + if (forceUpdate || m_lastSize.x != rectTransform.sizeDelta.x) + { + changeX = true; + } + else if (m_lastSize.y != rectTransform.sizeDelta.y) + { + changeX = false; + } + else + { + return; + } - if (changeX) - { - float ratio = rectTransform.sizeDelta.x / m_originalWidth; - m_newSize.Set(rectTransform.sizeDelta.x, m_originalHeight * ratio); - } - else - { - float ratio = rectTransform.sizeDelta.y / m_originalHeight; - m_newSize.Set(m_originalWidth * ratio, rectTransform.sizeDelta.y); - } - rectTransform.sizeDelta = m_newSize; + if (changeX) + { + float ratio = rectTransform.sizeDelta.x / m_originalWidth; + m_newSize.Set(rectTransform.sizeDelta.x, m_originalHeight * ratio); + } + else + { + float ratio = rectTransform.sizeDelta.y / m_originalHeight; + m_newSize.Set(m_originalWidth * ratio, rectTransform.sizeDelta.y); + } + rectTransform.sizeDelta = m_newSize; - m_lastSize = rectTransform.sizeDelta; + m_lastSize = rectTransform.sizeDelta; + } } } \ No newline at end of file