Beispiel #1
0
        /// <summary>
        ///     Runs the process to optimize the image.
        /// </summary>
        /// <param name="stream">        </param>
        /// <param name="algorithm">
        ///     Default is auto depend on file extension, others is force algorithm
        /// </param>
        /// <param name="qualityPercent">
        ///     Quality of image after compress, 0 is default it mean auto quality by image type
        /// </param>
        /// <param name="timeout">        TimeoutMillisecond of process in millisecond </param>
        /// <returns> The Task containing processing information. </returns>
        /// <exception cref="ArgumentException"> stream is invalid image format </exception>
        private static ImageCompressResult Process(MemoryStream stream, CompressAlgorithm algorithm, int qualityPercent = 0, int timeout = 0)
        {
            bool isValidImage = ImageCompressorHelper.TryGetCompressImageType(stream, out var imageType);

            if (!isValidImage || imageType == CompressImageType.Invalid)
            {
                throw new ArgumentException($"{nameof(stream)} is invalid image format", nameof(stream));
            }

            // Create a source temporary file with the correct extension.
            var filePath = FileHelper.CreateTempFile(stream, imageType.AsString(EnumFormat.Description), out _);

            ImageCompressResult imageCompressResult = Process(filePath, algorithm, qualityPercent, timeout);

            if (imageCompressResult != null)
            {
                // update file type, because in process not update it
                imageCompressResult.FileType = imageType;
            }

            // Cleanup temp file
            FileHelper.SafeDelete(filePath);

            return(imageCompressResult);
        }
Beispiel #2
0
        /// <summary>
        ///     Runs the process to optimize the image.
        /// </summary>
        /// <param name="inputPath">     </param>
        /// <param name="outputPath">    </param>
        /// <param name="qualityPercent"></param>
        /// <param name="timeout">       </param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"> input path is invalid image format </exception>
        public static ImageCompressResult Compress(string inputPath, string outputPath, int qualityPercent = 0, int timeout = ImageCompressorConstants.TimeoutMillisecond)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                using (FileStream file = new FileStream(inputPath, FileMode.Open, FileAccess.Read))
                {
                    // Copy file to stream

                    file.Position = 0;

                    file.CopyTo(stream);

                    // Do compress
                    ImageCompressResult imageCompressResult = Compress(stream, qualityPercent, timeout);

                    // Save to file
                    imageCompressResult?.ResultFileStream.Save(outputPath);

                    return(imageCompressResult);
                }
            }
        }
Beispiel #3
0
        /// <summary>
        ///     Runs the process to optimize the image.
        /// </summary>
        /// <param name="stream">         The source image stream. </param>
        /// <param name="qualityPercent">
        ///     Quality of image after compress, 0 is default it mean auto quality by image type
        /// </param>
        /// <param name="timeout">        TimeoutMillisecond of process in millisecond </param>
        /// <returns> The Task containing processing information. </returns>
        /// <exception cref="ArgumentException"> stream is invalid image format </exception>
        public static ImageCompressResult Compress(MemoryStream stream, int qualityPercent = 0, int timeout = ImageCompressorConstants.TimeoutMillisecond)
        {
            // Create new stopwatch.
            Stopwatch stopwatch = new Stopwatch();

            bool isValidImage = ImageCompressorHelper.TryGetCompressImageType(stream, out var imageType);

            if (!isValidImage || imageType == CompressImageType.Invalid)
            {
                throw new ArgumentException($"{nameof(stream)} is invalid image format", nameof(stream));
            }

            // Handle default value
            qualityPercent = ImageCompressorHelper.GetQualityPercent(qualityPercent, imageType);

            ImageCompressResult imageCompressResult = null;

            // Begin timing.
            stopwatch.Start();

            bool isCanOptimize = false;

            switch (imageType)
            {
            case CompressImageType.Png:
            {
                while (qualityPercent > 0)
                {
                    imageCompressResult = Process(stream, CompressAlgorithm.PngPrimary, qualityPercent, timeout);

                    if (imageCompressResult == null || (imageCompressResult.PercentSaving > 0 && imageCompressResult.PercentSaving < 100))
                    {
                        isCanOptimize = true;

                        break;
                    }

                    qualityPercent -= 10;
                }

                // if quality percent < 0 then try compress by png secondary algorithm (this
                // algorithm not related to quality percent)
                if (!isCanOptimize)
                {
                    imageCompressResult = Process(stream, CompressAlgorithm.PngSecondary, qualityPercent, timeout);
                }

                break;
            }

            case CompressImageType.Jpeg:
            {
                while (qualityPercent > 0)
                {
                    imageCompressResult = Process(stream, CompressAlgorithm.Jpeg, qualityPercent, timeout);

                    if (imageCompressResult == null || (imageCompressResult.PercentSaving > 0 && imageCompressResult.PercentSaving < 100))
                    {
                        isCanOptimize = true;

                        break;
                    }

                    qualityPercent -= 10;
                }

                break;
            }

            case CompressImageType.Gif:
            {
                while (qualityPercent > 0)
                {
                    imageCompressResult = Process(stream, CompressAlgorithm.Gif, qualityPercent, timeout);

                    if (imageCompressResult == null || (imageCompressResult.PercentSaving > 0 && imageCompressResult.PercentSaving < 100))
                    {
                        isCanOptimize = true;

                        break;
                    }

                    qualityPercent -= 10;
                }

                break;
            }
            }

            // Stop timing.
            stopwatch.Stop();

            // if cannot at all, return null

            if (imageCompressResult == null)
            {
                return(null);
            }

            if (imageCompressResult.PercentSaving > 0 && imageCompressResult.PercentSaving < 100)
            {
                // update total millisecond took only
                imageCompressResult.TotalMillisecondsTook = stopwatch.ElapsedMilliseconds;
            }
            else
            {
                // update total millisecond took
                imageCompressResult.TotalMillisecondsTook = stopwatch.ElapsedMilliseconds;

                // Cannot optimize Use origin for destination => update file size and stream
                imageCompressResult.CompressedFileSize = imageCompressResult.OriginalFileSize;

                // Copy origin steam to result
                imageCompressResult.ResultFileStream.SetLength(0);

                stream.Position = 0;

                stream.CopyTo(imageCompressResult.ResultFileStream);
            }

            imageCompressResult.QualityPercent = isCanOptimize ? qualityPercent : 100;

            return(imageCompressResult);
        }
Beispiel #4
0
        /// <summary>
        ///     Runs the process to optimize the image.
        /// </summary>
        /// <param name="filePath">       The source file. </param>
        /// <param name="algorithm">
        ///     Default is auto depend on file extension, others is force algorithm
        /// </param>
        /// <param name="qualityPercent">
        ///     Quality of image after compress, 0 is default it mean auto quality by image type
        /// </param>
        /// <param name="timeout">        TimeoutMillisecond of process in millisecond </param>
        /// <returns> The Task containing processing information. </returns>
        /// <exception cref="ArgumentException">
        ///     file path is invalid, argument of command is invalid
        /// </exception>
        /// <exception cref="NotSupportedException">
        ///     Some security policies don't allow execution of programs in this way
        /// </exception>
        private static ImageCompressResult Process(string filePath, CompressAlgorithm algorithm, int qualityPercent = 0, int timeout = 0)
        {
            ImageCompressorHelper.CheckFilePath(filePath);

            long fileSizeBeforeCompress = new FileInfo(filePath).Length;

            ImageCompressResult imageCompressResult = null;

            var processInfo = new ProcessStartInfo("cmd")
            {
                WorkingDirectory       = ImageCompressorBootstrapper.Instance.WorkingPath,
                Arguments              = GetArguments(filePath, out var fileTempPath, algorithm, qualityPercent),
                UseShellExecute        = false,
                CreateNoWindow         = true,
                WindowStyle            = ProcessWindowStyle.Hidden,
                RedirectStandardOutput = false,
                RedirectStandardError  = false,
            };

            if (IsProcessRunAsUser)
            {
                System.Security.SecureString runAsPassword = new System.Security.SecureString();

                foreach (char c in ProcessRunAsPassword)
                {
                    runAsPassword.AppendChar(c);
                }

                processInfo.UserName = ProcessRunAsUserName;

                processInfo.Password = runAsPassword;
            }

            if (string.IsNullOrWhiteSpace(processInfo.Arguments))
            {
                throw new ArgumentException($"Command {nameof(processInfo.Arguments)} is empty", $"{nameof(processInfo.Arguments)}");
            }

            int elapsedTime = 0;

            bool eventHandled = false;

            try
            {
                Process process = new Process
                {
                    StartInfo           = processInfo,
                    EnableRaisingEvents = true
                };

                process.Exited += (sender, args) =>
                {
                    // Done compress
                    imageCompressResult = new ImageCompressResult(filePath, fileSizeBeforeCompress);
                    process.Dispose();
                    eventHandled = true;

                    // Remove temp file if have
                    FileHelper.SafeDelete(fileTempPath);
                };

                process.Start();
            }
            catch (System.ComponentModel.Win32Exception ex)
            {
                throw new NotSupportedException("Some security policies don't allow execution of programs in this way", ex);
            }

            // Wait for Exited event, but not more than config timeout time.
            const int sleepAmount = 100;

            while (!eventHandled)
            {
                elapsedTime += sleepAmount;

                if (elapsedTime > timeout && timeout > 0)
                {
                    break;
                }

                Thread.Sleep(sleepAmount);
            }

            // update compress result stream
            if (imageCompressResult != null)
            {
                FileHelper.WriteToStream(filePath, imageCompressResult.ResultFileStream);
            }
            return(imageCompressResult);
        }