123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603 |
- /*
- UniGif
- Copyright (c) 2015 WestHillApps (Hironari Nishioka)
- This software is released under the MIT License.
- http://opensource.org/licenses/mit-license.php
- */
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- public static partial class UniGif
- {
- /// <summary>
- /// Set GIF data
- /// </summary>
- /// <param name="gifBytes">GIF byte data</param>
- /// <param name="gifData">ref GIF data</param>
- /// <param name="debugLog">Debug log flag</param>
- /// <returns>Result</returns>
- private static bool SetGifData(byte[] gifBytes, ref GifData gifData, bool debugLog)
- {
- if (debugLog)
- {
- Debug.Log("SetGifData Start.");
- }
- if (gifBytes == null || gifBytes.Length <= 0)
- {
- Debug.LogError("bytes is nothing.");
- return false;
- }
- int byteIndex = 0;
- 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 (debugLog)
- {
- gifData.Dump();
- Debug.Log("SetGifData Finish.");
- }
- 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'))
- {
- 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 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)
- {
- 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;
- }
- // Sort Flag(1 Bit)
- gifData.m_sortFlag = (gifBytes[10] & 8) == 8; // 0b00001000
- // Size of Global Color Table(3 Bits)
- int val = (gifBytes[10] & 7) + 1;
- gifData.m_sizeOfGlobalColorTable = (int)Math.Pow(2, val);
- }
- // Background Color Index(1 Byte)
- gifData.m_bgColorIndex = gifBytes[11];
- // Pixel Aspect Ratio(1 Byte)
- gifData.m_pixelAspectRatio = gifBytes[12];
- byteIndex = 13;
- if (gifData.m_globalColorTableFlag)
- {
- // Global Color Table(0~255×3 Bytes)
- gifData.m_globalColorTable = new List<byte[]>();
- 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);
- }
- return true;
- }
- private static bool SetGifBlock(byte[] gifBytes, ref int byteIndex, ref GifData gifData)
- {
- try
- {
- int lastIndex = 0;
- while (true)
- {
- int nowIndex = byteIndex;
- if (gifBytes[nowIndex] == 0x2c)
- {
- // 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;
- }
- if (lastIndex == nowIndex)
- {
- Debug.LogError("Infinite loop error.");
- return false;
- }
- lastIndex = nowIndex;
- }
- }
- catch (Exception ex)
- {
- Debug.LogError(ex.Message);
- return false;
- }
- return true;
- }
- 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 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 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;
- // 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
- // Sort Flag(1 Bit)
- ib.m_sortFlag = (gifBytes[byteIndex] & 32) == 32; // 0b00100000
- // 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);
- byteIndex++;
- }
- if (ib.m_localColorTableFlag)
- {
- // Local Color Table(0~255×3 Bytes)
- ib.m_localColorTable = new List<byte[]>();
- 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);
- }
- // 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];
- byteIndex++;
- if (blockSize == 0x00)
- {
- // Block Terminator(1 Byte)
- break;
- }
- 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<ImageBlock.ImageDataBlock>();
- }
- ib.m_imageDataList.Add(imageDataBlock);
- }
- if (gifData.m_imageBlockList == null)
- {
- gifData.m_imageBlockList = new List<ImageBlock>();
- }
- gifData.m_imageBlockList.Add(ib);
- }
- 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++;
- // Graphic Control Label(1 Byte)
- // 0xf9
- gcEx.m_graphicControlLabel = 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;
- }
- // User Input Flag(1 Bit)
- // Unknown
- // Transparent Color Flag(1 Bit)
- gcEx.m_transparentColorFlag = (gifBytes[byteIndex] & 1) == 1; // 0b00000001
- byteIndex++;
- }
- // Delay Time(2 Bytes)
- gcEx.m_delayTime = BitConverter.ToUInt16(gifBytes, byteIndex);
- byteIndex += 2;
- // Transparent Color Index(1 Byte)
- gcEx.m_transparentColorIndex = gifBytes[byteIndex];
- byteIndex++;
- // Block Terminator(1 Byte)
- gcEx.m_blockTerminator = gifBytes[byteIndex];
- byteIndex++;
- if (gifData.m_graphicCtrlExList == null)
- {
- gifData.m_graphicCtrlExList = new List<GraphicControlExtension>();
- }
- 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++;
- // Comment Label(1 Byte)
- // 0xfe
- commentEx.m_commentLabel = gifBytes[byteIndex];
- byteIndex++;
- // Block Size & Comment Data List
- while (true)
- {
- // 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;
- // 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<CommentExtension.CommentDataBlock>();
- }
- commentEx.m_commentDataList.Add(commentDataBlock);
- }
- if (gifData.m_commentExList == null)
- {
- gifData.m_commentExList = new List<CommentExtension>();
- }
- gifData.m_commentExList.Add(commentEx);
- }
- private static void SetPlainTextExtension(byte[] gifBytes, ref int byteIndex, ref GifData gifData)
- {
- 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++;
- // Block Size(1 Byte)
- // 0x0c
- plainTxtEx.m_blockSize = gifBytes[byteIndex];
- byteIndex++;
- // Text Grid Left Position(2 Bytes)
- // Not supported
- byteIndex += 2;
- // Text Grid Top Position(2 Bytes)
- // Not supported
- byteIndex += 2;
- // Text Grid Width(2 Bytes)
- // Not supported
- byteIndex += 2;
- // Text Grid Height(2 Bytes)
- // Not supported
- byteIndex += 2;
- // Character Cell Width(1 Bytes)
- // Not supported
- byteIndex++;
- // Character Cell Height(1 Bytes)
- // Not supported
- byteIndex++;
- // Text Foreground Color Index(1 Bytes)
- // Not supported
- byteIndex++;
- // Text Background Color Index(1 Bytes)
- // Not supported
- byteIndex++;
- // Block Size & Plain Text Data List
- while (true)
- {
- // Block Size(1 Byte)
- byte blockSize = gifBytes[byteIndex];
- byteIndex++;
- if (blockSize == 0x00)
- {
- // Block Terminator(1 Byte)
- break;
- }
- 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<PlainTextExtension.PlainTextDataBlock>();
- }
- plainTxtEx.m_plainTextDataList.Add(plainTextDataBlock);
- }
- if (gifData.m_plainTextExList == null)
- {
- gifData.m_plainTextExList = new List<PlainTextExtension>();
- }
- gifData.m_plainTextExList.Add(plainTxtEx);
- }
- 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];
- byteIndex++;
- 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<ApplicationExtension.ApplicationDataBlock>();
- }
- gifData.m_appEx.m_appDataList.Add(appDataBlock);
- }
- }
- }
|