예제 #1
0
        public ProcessImageResult ProcessImage(ProcessImageQuery query)
        {
            Guard.NotNull(query, nameof(query));

            ValidateQuery(query);

            var watch = new Stopwatch();

            byte[] inBuffer = null;

            try
            {
                watch.Start();

                using (var processor = new ImageFactory(preserveExifData: false, fixGamma: false))
                {
                    var source = query.Source;

                    // Load source
                    if (source is byte[] b)
                    {
                        inBuffer = b;
                    }
                    else if (source is Stream s)
                    {
                        inBuffer = s.ToByteArray();
                    }
                    else if (source is Image img)
                    {
                        processor.Load(img);
                    }
                    else if (source is string str)
                    {
                        var path = NormalizePath(str);
                        using (var fs = File.OpenRead(path))
                        {
                            inBuffer = fs.ToByteArray();
                        }
                    }
                    else
                    {
                        throw new ProcessImageException("Invalid source type '{0}' in query.".FormatInvariant(query.Source.GetType().FullName), query);
                    }

                    if (inBuffer != null)
                    {
                        processor.Load(inBuffer);
                    }

                    // Pre-process event
                    _eventPublisher.Publish(new ImageProcessingEvent(query, processor));

                    var result = new ProcessImageResult
                    {
                        Query          = query,
                        SourceWidth    = processor.Image.Width,
                        SourceHeight   = processor.Image.Height,
                        SourceMimeType = processor.CurrentImageFormat.MimeType
                    };

                    // Core processing
                    ProcessImageCore(query, processor, out var fxApplied);

                    // Create & prepare result
                    var outStream = new MemoryStream();
                    processor.Save(outStream);

                    var fmt = processor.CurrentImageFormat;
                    result.FileExtension = fmt.DefaultExtension == "jpeg" ? "jpg" : fmt.DefaultExtension;
                    result.MimeType      = fmt.MimeType;

                    result.HasAppliedVisualEffects = fxApplied;
                    result.Width  = processor.Image.Width;
                    result.Height = processor.Image.Height;

                    if (inBuffer != null)
                    {
                        // Check whether it is more beneficial to return the source instead of the result.
                        // Prefer result only if its size is smaller than the source size.
                        // Result size may be larger if a high-compressed image has been uploaded.
                        // During image processing the source compression algorithm gets lost and the image may be larger in size
                        // after encoding with default encoders.
                        var compare =
                            // only when image was not altered visually...
                            !fxApplied
                            // ...size has not changed
                            && result.Width == result.SourceWidth &&
                            result.Height == result.SourceHeight
                            // ...and format has not changed
                            && result.MimeType == result.SourceMimeType;

                        if (compare && inBuffer.LongLength <= outStream.GetBuffer().LongLength)
                        {
                            // Source is smaller. Throw away result and get back to source.
                            outStream.Dispose();
                            result.OutputStream = new MemoryStream(inBuffer, 0, inBuffer.Length, true, true);
                        }
                    }

                    // Set output stream
                    if (result.OutputStream == null)
                    {
                        result.OutputStream = outStream;
                    }

                    // Post-process event
                    _eventPublisher.Publish(new ImageProcessedEvent(query, processor, result));

                    result.OutputStream.Position = 0;

                    result.ProcessTimeMs = watch.ElapsedMilliseconds;

                    return(result);
                }
            }
            catch (Exception ex)
            {
                var pex = new ProcessImageException(query, ex);
                Logger.Error(pex);
                throw pex;
            }
            finally
            {
                if (query.DisposeSource && query.Source is IDisposable source)
                {
                    source.Dispose();
                }

                watch.Stop();
                _totalProcessingTime += watch.ElapsedMilliseconds;
            }
        }
예제 #2
0
 public ImageProcessedEvent(ProcessImageQuery query, ImageFactory processor, ProcessImageResult result)
 {
     Query     = query;
     Processor = processor;
     Result    = result;
 }
        public ProcessImageResult ProcessImage(ProcessImageQuery query, bool disposeOutput = true)
        {
            Guard.NotNull(query, nameof(query));

            ValidateQuery(query);

            var         watch  = new Stopwatch();
            SourceImage source = null;

            try
            {
                watch.Start();

                // Load source
                source = LoadImage(query);

                // Pre-process event
                _eventPublisher.Publish(new ImageProcessingEvent(query, source.Image));

                var result = new ProcessImageResult
                {
                    Query               = query,
                    SourceWidth         = source.Image.Width,
                    SourceHeight        = source.Image.Height,
                    SourceMimeType      = source.Format.DefaultMimeType,
                    DisposeOutputStream = disposeOutput
                };

                // Core processing
                ProcessImageCore(query, source.Image, out var fxApplied);

                // Create & prepare result
                //var outStream = new MemoryStream();
                //source.Image.Save(outStream, source.Format); // TODO: outFormat
                var dest = SaveImage(source, query);

                var fmt = dest.Format;
                result.FileExtension = fmt.FileExtensions.First();
                result.MimeType      = fmt.DefaultMimeType;

                result.HasAppliedVisualEffects = fxApplied;
                result.Width  = source.Image.Width;
                result.Height = source.Image.Height;

                if (source.Length > 0)
                {
                    // Check whether it is more beneficial to return the source instead of the result.
                    // Prefer result only if its size is smaller than the source size.
                    // Result size may be larger if a high-compressed image has been uploaded.
                    // During image processing the source compression algorithm gets lost and the image may be larger in size
                    // after encoding with default encoders.
                    var compare =
                        // only when image was not altered visually...
                        !fxApplied
                        // ...size has not changed
                        && result.Width == result.SourceWidth &&
                        result.Height == result.SourceHeight
                        // ...and format has not changed
                        && result.MimeType == result.SourceMimeType;

                    if (compare && source.Length <= dest.OutStream.Length)
                    {
                        // Source is smaller. Throw away result and get back to source.
                        dest.OutStream.Dispose();
                        dest.OutStream         = null;
                        source.Stream.Position = 0;
                        result.OutputStream    = source.Stream;
                    }
                }

                // Set output stream
                if (result.OutputStream == null)
                {
                    result.OutputStream = dest.OutStream;
                }

                // Post-process event
                _eventPublisher.Publish(new ImageProcessedEvent(query, source.Image, result));

                result.OutputStream.Position = 0;

                result.ProcessTimeMs = watch.ElapsedMilliseconds;

                return(result);
            }
            catch (Exception ex)
            {
                throw new ProcessImageException(query, ex);
            }
            finally
            {
                if (source?.Image != null)
                {
                    source?.Image.Dispose();
                }

                if (source?.Stream != null && query.DisposeSource)
                {
                    source?.Stream.Dispose();
                }

                watch.Stop();
                _totalProcessingTime += watch.ElapsedMilliseconds;
            }
        }
        public ProcessImageResult ProcessImage(ProcessImageQuery query)
        {
            Guard.NotNull(query, nameof(query));

            ValidateQuery(query);

            var watch = new Stopwatch();

            try
            {
                watch.Start();

                using (var processor = new ImageFactory(preserveExifData: false, fixGamma: false))
                {
                    var source = query.Source;

                    // Load source
                    if (source is byte[])
                    {
                        processor.Load((byte[])source);
                    }
                    else if (source is Stream)
                    {
                        processor.Load((Stream)source);
                    }
                    else if (source is Image)
                    {
                        processor.Load((Image)source);
                    }
                    else if (source is string)
                    {
                        // TODO: (mc) map virtual pathes
                        processor.Load((string)source);
                    }
                    else
                    {
                        throw new ProcessImageException("Invalid source type '{0}' in query.".FormatInvariant(query.Source.GetType().FullName), query);
                    }

                    // Pre-process event
                    _eventPublisher.Publish(new ImageProcessingEvent(query, processor));

                    var result = new ProcessImageResult
                    {
                        Query        = query,
                        SourceWidth  = processor.Image.Width,
                        SourceHeight = processor.Image.Height
                    };

                    // Core processing
                    ProcessImageCore(query, processor);

                    // Create & prepare result
                    var outStream = new MemoryStream();
                    processor.Save(outStream);

                    result.Width         = processor.Image.Width;
                    result.Height        = processor.Image.Height;
                    result.FileExtension = processor.CurrentImageFormat.DefaultExtension;
                    result.MimeType      = processor.CurrentImageFormat.MimeType;
                    result.OutputStream  = outStream;

                    // Post-process event
                    _eventPublisher.Publish(new ImageProcessedEvent(query, processor, result));

                    result.ProcessTimeMs = watch.ElapsedMilliseconds;

                    return(result);
                }
            }
            catch (Exception ex)
            {
                var pex = new ProcessImageException(query, ex);
                Logger.Error(pex);
                throw pex;
            }
            finally
            {
                if (query.DisposeSource && query.Source is IDisposable)
                {
                    ((IDisposable)query.Source).Dispose();
                }

                watch.Stop();
                _totalProcessingTime += watch.ElapsedMilliseconds;
            }
        }
예제 #5
0
 public ImageProcessedEvent(ProcessImageQuery query, ProcessImageResult result)
 {
     Query  = query;
     Result = result;
 }