示例#1
0
        /// <summary>
        /// Resizes this player according to the predefined scale mode and the clip's aspect ratio.
        /// </summary>
        /// <param name="clip">Clip.</param>
        void Resize(AnimatedClip clip)
        {
            if (clip == null)
            {
                Debug.LogError("Could not resize player: clip is null.");
                return;
            }

            if (_scaleMode == ClipPlayerScaleMode.None)
            {
                return;
            }
            else
            {
                float aspectRatio = (float)clip.Width / clip.Height;

                if (_scaleMode == ClipPlayerScaleMode.AutoHeight)
                {
                    rt.sizeDelta = new Vector2(rt.sizeDelta.x, rt.sizeDelta.x / aspectRatio);
                }
                else if (_scaleMode == ClipPlayerScaleMode.AutoWidth)
                {
                    rt.sizeDelta = new Vector2(rt.sizeDelta.y * aspectRatio, rt.sizeDelta.y);
                }
            }
        }
示例#2
0
        IEnumerator CRPlay(AnimatedClip clip, float startDelay, bool loop)
        {
            float timePerFrame = 1f / clip.FramePerSecond;
            bool  hasDelayed   = false;

            do
            {
                for (int i = 0; i < clip.Frames.Length; i++)
                {
                    rawImage.texture = clip.Frames[i];
                    yield return(new WaitForSeconds(timePerFrame));

                    // Wait at the 1st frame if startDelay is required
                    if (startDelay > 0 && !hasDelayed && i == 0)
                    {
                        hasDelayed = true;
                        yield return(new WaitForSeconds(startDelay));
                    }

                    // Standby if paused
                    if (isPaused)
                    {
                        yield return(null);
                    }
                }
            } while (loop);
        }
示例#3
0
            private void DecodeProc(object param)
            {
                DecodeProcParams request = (DecodeProcParams)param;
                List <FrameData> frames  = new List <FrameData>();
                int width  = 0;
                int height = 0;

                GifStream gifStream = new GifStream(request.filePath);
                int       readFrame = 0;

                while (gifStream.HasMoreData)
                {
                    if (readFrame >= request.frameToRead && request.frameToRead > 0)
                    {
                        break;
                    }
                    switch (gifStream.CurrentToken)
                    {
                    case GifStream.Token.Image:
                        var image = gifStream.ReadImage();
                        width  = gifStream.Header.width;
                        height = gifStream.Header.height;
                        Color32[] copiedColors = new Color32[image.colors.Length];
                        image.colors.CopyTo(copiedColors, 0);
                        frames.Add(new FrameData()
                        {
                            colors = copiedColors,
                            delay  = image.DelaySeconds
                        });
                        readFrame++;
                        break;

                    default:
                        gifStream.SkipToken();
                        break;
                    }
                }
                gifStream.Dispose();

                request.runner.RunInMainThread(() =>
                {
                    Texture2D[] textures = new Texture2D[frames.Count];
                    int fps         = 2;
                    float totalTime = 0;
                    for (int i = 0; i < frames.Count; i++)
                    {
                        textures[i]      = new Texture2D(width, height, TextureFormat.ARGB32, false, false);
                        textures[i].name = i.ToString();
                        textures[i].SetPixels32(frames[i].colors);
                        textures[i].Apply();
                        totalTime += frames[i].delay;
                        fps        = Mathf.RoundToInt(frames.Count / totalTime);
                    }
                    animatedClip = new AnimatedClip(width, height, fps, textures);
                    IsCompleted  = true;
                    request.runner.DestroySelf();
                });
            }
示例#4
0
文件: Gif.cs 项目: akil03/bx
 /// <summary>
 /// Plays the clip on the specified clip player.
 /// </summary>
 /// <param name="player">Player.</param>
 /// <param name="clip">Clip.</param>
 /// <param name="startDelay">Optional delay before the playing starts.</param>
 /// <param name="loop">If set to <c>true</c> loop indefinitely.</param>
 public static void PlayClip(IClipPlayer player, AnimatedClip clip, float startDelay = 0, bool loop = true)
 {
     if (player == null)
     {
         Debug.LogError("Player is null.");
         return;
     }
     else
     {
         player.Play(clip, startDelay, loop);
     }
 }
示例#5
0
文件: Gif.cs 项目: akil03/bx
        /// <summary>
        /// Stops recording on the specified recorder.
        /// </summary>
        /// <returns>The recorded clip.</returns>
        /// <param name="recorder">Recorder.</param>
        public static AnimatedClip StopRecording(Recorder recorder)
        {
            AnimatedClip clip = null;

            if (recorder == null)
            {
                Debug.LogError("StopRecording FAILED: recorder is null.");
            }
            else
            {
                clip = recorder.Stop();
            }

            return(clip);
        }
示例#6
0
        /// <summary>
        /// Play the specified clip.
        /// </summary>
        /// <param name="clip">Clip.</param>
        /// <param name="startDelay">Optional delay before the playing starts.</param>
        /// <param name="loop">If set to <c>true</c> loop indefinitely.</param>
        public void Play(AnimatedClip clip, float startDelay = 0, bool loop = true)
        {
            if (clip == null || clip.Frames.Length == 0 || clip.IsDisposed())
            {
                Debug.LogError("Attempted to play an empty or disposed clip.");
                return;
            }

            Stop();
            Resize(clip);
            isPaused = false;

            playCoroutine = CRPlay(clip, startDelay, loop);
            StartCoroutine(playCoroutine);
        }
示例#7
0
文件: Gif.cs 项目: akil03/bx
        /// <summary>
        /// Exports a GIF image from the provided clip.
        /// Allows setting looping mode of the output image.
        /// </summary>
        /// <param name="clip">The clip to export to GIF format.</param>
        /// <param name="filename">Filename to save the output GIF.</param>
        /// <param name="loop">-1 to disable, 0 to loop indefinitely, >0 to loop a set number of times.</param>
        /// <param name="quality">Quality setting for the exported image. Inputs will be clamped between 1 and 100. Bigger values mean better quality but slightly longer processing time. 80 is generally a good value in terms of time-quality balance.</param>
        /// <param name="threadPriority">Priority of the GIF encoding thread.</param>
        /// <param name="exportProgressCallback">Export progress callback: 1st parameter is the provided clip, 2nd parameter is the export progress from 0 to 1.</param>
        /// <param name="exportCompletedCallback">Export completed callback: 1st parameter is the provided clip, 2nd parameter is the filepath of the exported GIF.</param>
        public static void ExportGif(AnimatedClip clip, string filename, int loop, int quality, System.Threading.ThreadPriority threadPriority, Action <AnimatedClip, float> exportProgressCallback, Action <AnimatedClip, string> exportCompletedCallback)
        {
            if (clip == null || clip.Frames.Length == 0 || clip.IsDisposed())
            {
                Debug.LogError("Attempted to export GIF from an empty or disposed clip.");
                return;
            }

            if (String.IsNullOrEmpty(filename))
            {
                Debug.LogError("Exporting GIF failed: filename is null or empty.");
                return;
            }

            // Start the actual export process
            Instance.StartCoroutine(CRExportGif(clip, filename, loop, quality, threadPriority, exportProgressCallback, exportCompletedCallback));
        }
示例#8
0
        /// <summary>
        /// Stops recording.
        /// </summary>
        /// <returns>The recorded clip, which could be empty if the recording was not started.</returns>
        public AnimatedClip Stop()
        {
            _state = RecorderState.Stopped;

            if (recordedFrames.Count == 0)
            {
                Debug.LogWarning("Nothing recorded, an empty clip will be returned.");
            }

            var clip = new AnimatedClip(_width, _height, _framePerSecond, recordedFrames.ToArray());

            // Since we return the clip, we also hand over the control of frame data to the holder of that clip
            // (e.g. the frames can be destroyed without our knowledge), therefore we should not hold any references to this data.
            recordedFrames.Clear();

            return(clip);
        }
示例#9
0
        /// <summary>
        /// Resizes this player according to the predefined scale mode and the clip's aspect ratio.
        /// </summary>
        /// <param name="clip">Clip.</param>
        void Resize(AnimatedClip clip)
        {
            if (_scaleMode == ClipPlayerScaleMode.None)
            {
                return;
            }
            else
            {
                float aspectRatio = (float)clip.Width / clip.Height;
                var   scale       = transform.localScale;

                if (_scaleMode == ClipPlayerScaleMode.AutoHeight)
                {
                    scale.y = scale.x / aspectRatio;
                }
                else if (_scaleMode == ClipPlayerScaleMode.AutoWidth)
                {
                    scale.x = scale.y * aspectRatio;
                }

                transform.localScale = scale;
            }
        }
示例#10
0
文件: Gif.cs 项目: akil03/bx
        // GIF exporting coroutine: preprocess the image data then send it to native code (mobile) or a worker thread (other platforms) to export GIF file.
        static IEnumerator CRExportGif(AnimatedClip clip, string filename, int loop, int quality, System.Threading.ThreadPriority threadPriority, Action <AnimatedClip, float> exportProgressCallback, Action <AnimatedClip, string> exportCompletedCallback)
        {
            // The encoder don't want loop to be < -1
            if (loop < -1)
            {
                loop = -1;
            }

            // Compute the NeuQuant sample factor from the inverse of the quality value.
            // Note that NeuQuant prefers values in range [1,30] so we'll also scale the factor to that range.
            int sampleFac = Mathf.RoundToInt(Mathf.Lerp(30, 1, (float)(Mathf.Clamp(quality, 1, 100)) / 100));

            // Construct filepath
            string folder;

            #if UNITY_EDITOR
            folder = Application.dataPath; // Assets folder
            #else
            folder = Application.persistentDataPath;
            #endif

            string filepath = System.IO.Path.Combine(folder, filename + ".gif");

            // Construct a new export task
            var exportTask = new GifExportTask();
            exportTask.taskId    = curExportId++; // assign this task a unique id
            exportTask.clip      = clip;
            exportTask.imageData = null;
            exportTask.filepath  = filepath;
            exportTask.loop      = loop;
            exportTask.sampleFac = sampleFac;
            exportTask.exportProgressCallback  = exportProgressCallback;
            exportTask.exportCompletedCallback = exportCompletedCallback;
            exportTask.workerPriority          = threadPriority;
            exportTask.isExporting             = true;
            exportTask.isDone   = false;
            exportTask.progress = 0;

            // Add task to the list with its unique id key
            gifExportTasks.Add(exportTask.taskId, exportTask);

            yield return(null);

            // Create a temporary texture to read RenderTexture data
            Texture2D temp = new Texture2D(clip.Width, clip.Height, TextureFormat.RGB24, false);
            temp.hideFlags  = HideFlags.HideAndDontSave;
            temp.wrapMode   = TextureWrapMode.Clamp;
            temp.filterMode = FilterMode.Bilinear;
            temp.anisoLevel = 0;

            // On iOS and Android, the GIF encoding is done in native code.
            // In Unity editor (and other platforms), we use Moments encoder for testing purpose.
            #if UNITY_EDITOR || (!UNITY_IOS && !UNITY_ANDROID)
            // Converts to GIF frames
            List <GifFrame> frames = new List <GifFrame>(clip.Frames.Length);
            for (int i = 0; i < clip.Frames.Length; i++)
            {
                RenderTexture source = clip.Frames[i];
                RenderTexture.active = source;
                temp.ReadPixels(new Rect(0, 0, source.width, source.height), 0, 0);
                temp.Apply();
                RenderTexture.active = null;

                GifFrame frame = new GifFrame()
                {
                    Width = temp.width, Height = temp.height, Data = temp.GetPixels32()
                };
                frames.Add(frame);

                OnGifPreProcessing(exportTask.taskId, (float)i / clip.Frames.Length);
                yield return(null);
            }

            // Setup a worker thread and let it do its magic
            GifEncoder encoder = new GifEncoder(loop, sampleFac);
            encoder.SetDelay(Mathf.RoundToInt(1000f / clip.FramePerSecond));
            Worker worker = new Worker(
                exportTask.taskId,
                threadPriority,
                frames,
                encoder,
                filepath,
                OnGifExportProgress,
                OnGifExportCompleted);

            worker.Start();
            #else
            // Allocate an array to hold the serialized image data
            exportTask.imageData = new Color32[clip.Frames.Length][];

            // Construct the serialized image data, note that texture data is layered down-top, so flip it
            for (int i = 0; i < clip.Frames.Length; i++)
            {
                var source = clip.Frames[i];
                RenderTexture.active = source;
                temp.ReadPixels(new Rect(0, 0, source.width, source.height), 0, 0);
                temp.Apply();
                RenderTexture.active = null;

                // Get the frame's pixel data
                exportTask.imageData[i] = temp.GetPixels32();

                // Call the preprocessing handler directly
                float progress = (float)i / clip.Frames.Length;
                OnGifPreProcessing(exportTask.taskId, progress);

                yield return(null);
            }

            #if UNITY_IOS
            iOSNativeGif.ExportGif(exportTask);
            #elif UNITY_ANDROID
            AndroidNativeGif.ExportGif(exportTask);
            #endif
            #endif  // UNITY_EDITOR || (!UNITY_IOS && !UNITY_ANDROID)

            // Dispose the temporary texture
            Destroy(temp);
        }
示例#11
0
文件: Gif.cs 项目: akil03/bx
 /// <summary>
 /// Exports a GIF image from the provided clip.
 /// </summary>
 /// <param name="clip">The clip to export to GIF format.</param>
 /// <param name="filename">Filename to save the output GIF.</param>
 /// <param name="quality">Quality setting for the exported image. Inputs will be clamped between 1 and 100. Bigger values mean better quality but slightly longer processing time. 80 is generally a good value in terms of time-quality balance.</param>
 /// <param name="threadPriority">Thread priority to use when exporting GIF file.</param>
 /// <param name="exportProgressCallback">Export progress callback: 1st parameter is the provided clip, 2nd parameter is the export progress from 0 to 1.</param>
 /// <param name="exportCompletedCallback">Export completed callback: 1st parameter is the provided clip, 2nd parameter is the filepath of the exported GIF.</param>
 public static void ExportGif(AnimatedClip clip, string filename, int quality, System.Threading.ThreadPriority threadPriority, Action <AnimatedClip, float> exportProgressCallback, Action <AnimatedClip, string> exportCompletedCallback)
 {
     ExportGif(clip, filename, 0, quality, threadPriority, exportProgressCallback, exportCompletedCallback);
 }