Пример #1
0
        private async Task UpdateThumbStatus(Image image, ImageProcessResult conversionResult)
        {
            Logging.LogTrace($" - Updating metadata for {image.ImageId}");
            try
            {
                using var db = new ImageContext();

                if (image.MetaData != null)
                {
                    db.Attach(image.MetaData);
                    image.MetaData.ThumbLastUpdated = DateTime.UtcNow;
                    db.ImageMetaData.Update(image.MetaData);
                }
                else
                {
                    var metadata = new ImageMetaData
                    {
                        ImageId          = image.ImageId,
                        ThumbLastUpdated = DateTime.UtcNow
                    };
                    db.ImageMetaData.Add(metadata);
                    image.MetaData = metadata;
                }

                await db.SaveChangesAsync("ThumbUpdate");
            }
            catch (Exception ex)
            {
                Logging.LogWarning($"Unable to update DB thumb for ID {image.ImageId}: {ex.Message}");
            }
        }
Пример #2
0
        /// 对云上数据进行图片处理
        public void ProcessWithPicOperation()
        {
            string bucket  = "examplebucket-1250000000"; //存储桶,格式:BucketName-APPID
            string key     = "exampleobject";            //对象键
            string srcPath = @"temp-source-file";        //本地文件绝对路径
            //.cssg-snippet-body-start:[process-with-pic-operation]
            JObject o = new JObject();

            // 不返回原图
            o["is_pic_info"] = 0;
            JArray  rules = new JArray();
            JObject rule  = new JObject();

            rule["bucket"] = bucket;
            rule["fileid"] = "desample_photo.jpg";
            //处理参数,规则参见:https://cloud.tencent.com/document/product/460/19017
            rule["rule"] = "imageMogr2/thumbnail/400x400";
            rules.Add(rule);
            o["rules"] = rules;
            string ruleString = o.ToString(Formatting.None);

            ImageProcessRequest request = new ImageProcessRequest(bucket, key, ruleString);
            ImageProcessResult  result  = cosXml.ImageProcess(request);
            //.cssg-snippet-body-end
        }
Пример #3
0
        /// <summary>
        /// Resize using SixLabors ImageSharp, which can do 100 images in about 59s (2020 MacBook Air i5)
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destFiles"></param>
        public async Task <ImageProcessResult> CreateThumbs(FileInfo source, IDictionary <FileInfo, ThumbConfig> destFiles)
        {
            var       result = new ImageProcessResult();
            Stopwatch load   = new Stopwatch("ImageSharpLoad");

            // Image.Load(string path) is a shortcut for our default type.
            // Other pixel formats use Image.Load<TPixel>(string path))
            using var image = await Image.LoadAsync <Rgba32>(source.FullName);

            load.Stop();

            // We've got the image in memory. Create the hash.
            result.ImageHash = GetHash(image);

            Stopwatch orient = new Stopwatch("ImageSharpOrient");

            image.Mutate(x => x.AutoOrient());

            orient.Stop();

            Stopwatch thumbs = new Stopwatch("ImageSharpThumbs");

            foreach (var pair in destFiles)
            {
                var dest   = pair.Key;
                var config = pair.Value;
                var mode   = ResizeMode.Max;

                var size = new Size {
                    Height = config.height, Width = config.width
                };

                Logging.LogTrace("Generating thumbnail for {0}: {1}x{2}", source.Name, size.Width, size.Height);

                if (config.cropToRatio)
                {
                    // For the smallest thumbs, we crop to fix the aspect exactly.
                    mode = ResizeMode.Crop;
                }

                var opts = new ResizeOptions {
                    Mode    = mode, Size = size,
                    Sampler = KnownResamplers.Lanczos8
                };

                // Note, we don't clone and resize from the original image, because that's expensive.
                // So we always resize the previous image, which will be faster for each iteration
                // because each previous image is progressively smaller.
                image.Mutate(x => x.Resize(opts));
                await image.SaveAsync(dest.FullName);

                result.ThumbsGenerated = true;
            }

            thumbs.Stop();

            return(result);
        }
Пример #4
0
        public void ImageProcess()
        {
            string key = photoKey;

            JObject o = new JObject();

            // 返回原图
            o["is_pic_info"] = 1;
            JArray  rules = new JArray();
            JObject rule  = new JObject();

            rule["bucket"] = bucket;
            rule["fileid"] = "desample_photo.png";
            //处理参数,规则参见:https://cloud.tencent.com/document/product/460/19017
            rule["rule"] = "imageMogr2/thumbnail/400x400";
            rules.Add(rule);
            o["rules"] = rules;
            string ruleString = o.ToString(Formatting.None);

            ImageProcessRequest request = new ImageProcessRequest(bucket, key, ruleString);

            ImageProcessResult result = QCloudServer.Instance().cosXml.ImageProcess(request);
            var uploadResult          = result.uploadResult;

            // Console.WriteLine(result.GetResultInfo());
            Assert.IsNotEmpty((result.GetResultInfo()));
            Assert.True(result.IsSuccessful());
            Assert.NotNull(uploadResult);

            Assert.NotNull(uploadResult.originalInfo);
            Assert.NotNull(uploadResult.originalInfo.ETag);
            Assert.NotNull(uploadResult.originalInfo.Key);
            Assert.NotNull(uploadResult.originalInfo.Location);
            Assert.NotNull(uploadResult.originalInfo.imageInfo.Ave);
            Assert.NotNull(uploadResult.originalInfo.imageInfo.Format);
            Assert.NotNull(uploadResult.originalInfo.imageInfo.Orientation);
            Assert.NotZero(uploadResult.originalInfo.imageInfo.Width);
            Assert.NotZero(uploadResult.originalInfo.imageInfo.Height);
            Assert.NotZero(uploadResult.originalInfo.imageInfo.Quality);

            Assert.NotNull(uploadResult.processResults);
            Assert.NotZero(uploadResult.processResults.results.Count);
            Assert.True(uploadResult.processResults.results[0].Width <= 400);
            Assert.True(uploadResult.processResults.results[0].Height <= 400);
            Assert.NotNull(uploadResult.processResults.results[0].ETag);
            Assert.NotNull(uploadResult.processResults.results[0].Format);
            Assert.NotNull(uploadResult.processResults.results[0].Key);
            Assert.NotNull(uploadResult.processResults.results[0].Location);
            Assert.NotZero(uploadResult.processResults.results[0].Quality);
            Assert.NotZero(uploadResult.processResults.results[0].Size);
            Assert.Zero(uploadResult.processResults.results[0].WatermarkStatus);
        }
Пример #5
0
        /// <summary>
        /// Resize using SkiaSharp - this can do 100 images in about 30s (2020 i5 MacBook Air).
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destFiles"></param>
        public Task <ImageProcessResult> CreateThumbs(FileInfo source, IDictionary <FileInfo, ThumbConfig> destFiles)
        {
            Stopwatch          load, hashThumb, scale, save, thumbs;
            ImageProcessResult result = new ImageProcessResult {
                ThumbsGenerated = false
            };

            try
            {
                thumbs = new Stopwatch("GenThumbs");

                int desiredWidth = destFiles.Max(x => x.Value.width);

                load = new Stopwatch("LoadThumb");
                using var sourceBitmap = LoadOrientedBitmap(source, desiredWidth);
                load.Stop();

                hashThumb        = new Stopwatch("HashThumb");
                result.ImageHash = GetHash(sourceBitmap);
                hashThumb.Stop();

                // Dropping this from High to Low doesn't have that much of an effect
                // in terms of image quality.
                var quality   = SKFilterQuality.Medium;
                var srcBitmap = sourceBitmap;

                foreach (var pair in destFiles.OrderByDescending(x => x.Value.width))
                {
                    var dest   = pair.Key;
                    var config = pair.Value;

                    scale = new Stopwatch("ScaleThumb");

                    float widthScaleFactor = (float)srcBitmap.Width / (float)config.width;
                    float heighScaleFactor = (float)srcBitmap.Height / (float)config.height;
                    float scaleFactor      = Math.Min(widthScaleFactor, heighScaleFactor);

                    using var scaledImage = new SKBitmap((int)(srcBitmap.Width / scaleFactor), (int)(srcBitmap.Height / scaleFactor));
                    srcBitmap.ScalePixels(scaledImage.PeekPixels(), quality);

                    var cropSize = new SKSize {
                        Height = config.height, Width = config.width
                    };
                    using var cropped = config.cropToRatio ? Crop(scaledImage, cropSize) : scaledImage;

                    using SKData data = cropped.Encode(SKEncodedImageFormat.Jpeg, 90);

                    scale.Stop();
                    save = new Stopwatch("SaveThumb");
                    // TODO: For configs flagged batchcreate == false, perhaps don't write to disk
                    // and just pass back the stream?
                    using (var stream = new FileStream(dest.FullName, FileMode.Create, FileAccess.Write))
                        data.SaveTo(stream);
                    save.Stop();

                    // Now, use the previous scaled image as the basis for the
                    // next smaller thumbnail. This should reduce processing
                    // time as we only work on the large image on the first
                    // iteration
                    if (destFiles.Count > 1)
                    {
                        srcBitmap = scaledImage.Copy();
                    }

                    result.ThumbsGenerated = true;
                    // TODO: Dispose

                    if (pair.Value.size == ThumbSize.ExtraLarge)
                    {
                        Logging.Log($"{pair.Value.size} thumb created for {source.Name} [load: {load.ElapsedTime}ms, scale: {scale.ElapsedTime}ms, save: {save.ElapsedTime}ms]");
                    }
                }

                thumbs.Stop();
            }
            catch (Exception ex)
            {
                Logging.Log($"Exception during Thumbnail processing: {ex.Message}");
                throw;
            }

            return(Task.FromResult(result));
        }
Пример #6
0
        /// <summary>
        /// Convert the files to thumbnails by shelling out to either ImageMagick
        /// or the faster GraphicsMagick.
        /// </summary>
        /// <param name="source">Source.</param>
        /// <param name="sizes">Sizes.</param>
        public async Task <ImageProcessResult> CreateThumbs(FileInfo source, IDictionary <FileInfo, ThumbConfig> destFiles)
        {
            // This processor doesn't support hash creation
            ImageProcessResult result = new ImageProcessResult {
                ThumbsGenerated = false, ImageHash = string.Empty
            };

            // Some useful unsharp and quality settings, plus by defining the max size of the JPEG, it
            // makes imagemagic more efficient with its memory allocation, so significantly faster.
            string args;
            string exeToUse  = s_useGraphicsMagick ? graphicsMagickExe : imageMagickExe;
            int    maxHeight = destFiles.Max(x => x.Value.height);
            int    maxWidth  = destFiles.Max(x => x.Value.width);

            if (s_useGraphicsMagick)
            {
                args = string.Format(" convert -size {0}x{1} \"{2}\" -quality 90  -unsharp 0.5x0.5+1.25+0.0 ", maxHeight, maxWidth, source.FullName);
            }
            else
            {
                args = string.Format(" -define jpeg:size={0}x{1} \"{2}\" -quality 90 -unsharp 0.5x0.5+1.25+0.0 ", maxHeight, maxWidth, source.FullName);
            }

            FileInfo?altSource = null;

            List <string> argsList = new List <string>();

            // First pre-check whether the thumbs exist - don't want to create them if they don't.
            foreach (var pair in destFiles.OrderByDescending(x => x.Value.width))
            {
                var dest   = pair.Key;
                var config = pair.Value;

                // File didn't exist, so add it to the command-line.
                if (s_useGraphicsMagick)
                {
                    argsList.Add(string.Format("-thumbnail {0}x{1} -auto-orient -write \"{2}\" ", config.height, config.width, dest.FullName));
                }
                else
                {
                    argsList.Add(string.Format("-thumbnail {0}x{1} -auto-orient -write \"{2}\" ", config.height, config.width, dest.FullName));
                }
            }

            if (argsList.Any())
            {
                var lastArg = argsList.Last();
                lastArg = lastArg.Replace(" -write ", " ");
                argsList[argsList.Count() - 1] = lastArg;

                args += string.Join(" ", argsList);

                if (altSource != null)
                {
                    source = altSource;
                    Logging.LogVerbose("File {0} exists - using it as source for smaller thumbs.", altSource.Name);
                }

                Logging.LogVerbose("Converting file {0}", source);

                Process process = new Process();

                process.StartInfo.FileName               = exeToUse;
                process.StartInfo.Arguments              = args;
                process.StartInfo.RedirectStandardError  = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.UseShellExecute        = false;
                process.OutputDataReceived              += Process_OutputDataReceived;
                process.ErrorDataReceived += Process_OutputDataReceived;

                try
                {
                    Logging.LogVerbose("  Executing: {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);

                    bool success = process.Start();

                    if (success)
                    {
                        process.BeginErrorReadLine();
                        process.BeginOutputReadLine();
                        await process.WaitForExitAsync();

                        if (process.ExitCode == 0)
                        {
                            result.ThumbsGenerated = true;
                            Logging.LogVerbose("Execution complete.");
                        }
                        else
                        {
                            throw new Exception("Failed");
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logging.LogError("Conversion failed. Unable to start process: {0}", ex.Message);
                    Logging.LogError($"Failed commandline was: {exeToUse} {args}");
                }
            }
            else
            {
                Logging.LogVerbose("Thumbs already exist in all resolutions. Skipping...");
            }

            return(result);
        }
Пример #7
0
        /// <summary>
        /// Resize using SkiaSharp - this can do 100 images in about 30s (2020 i5 MacBook Air).
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destFiles"></param>
        public Task <ImageProcessResult> CreateThumbs(FileInfo source, IDictionary <FileInfo, ThumbConfig> destFiles)
        {
            ImageProcessResult result = new ImageProcessResult {
                ThumbsGenerated = false
            };

            try
            {
                int desiredWidth = destFiles.Max(x => x.Value.width);

                using var sourceBitmap = LoadOrientedBitmap(source, desiredWidth);

                result.ImageHash = GetHash(sourceBitmap);

                Stopwatch thumbs = new Stopwatch("SkiaSharpThumbs");

                // Dropping this from High to Low doesn't have that much of an effect
                // in terms of performance.
                var quality   = SKFilterQuality.Low;
                var srcBitmap = sourceBitmap;

                foreach (var pair in destFiles.OrderByDescending(x => x.Value.width))
                {
                    var dest   = pair.Key;
                    var config = pair.Value;

                    float widthScaleFactor = (float)srcBitmap.Width / (float)config.width;
                    float heighScaleFactor = (float)srcBitmap.Height / (float)config.height;
                    float scaleFactor      = Math.Min(widthScaleFactor, heighScaleFactor);

                    using var scaledImage = new SKBitmap((int)(srcBitmap.Width / scaleFactor), (int)(srcBitmap.Height / scaleFactor));
                    srcBitmap.ScalePixels(scaledImage.PeekPixels(), quality);

                    var cropSize = new SKSize {
                        Height = config.height, Width = config.width
                    };
                    using var cropped = config.cropToRatio ? Crop(scaledImage, cropSize) : scaledImage;

                    using SKData data = cropped.Encode(SKEncodedImageFormat.Jpeg, 90);

                    using (var stream = new FileStream(dest.FullName, FileMode.Create, FileAccess.Write))
                        data.SaveTo(stream);

                    // Now, use the previous scaled image as the basis for the
                    // next smaller thumbnail. This should reduce processing
                    // time as we only work on the large image on the first
                    // iteration
                    srcBitmap = scaledImage.Copy();

                    result.ThumbsGenerated = true;
                    // TODO: Dispose
                }

                thumbs.Stop();
            }
            catch (Exception ex)
            {
                Logging.Log($"Exception during Skia processing: {ex.Message}");
                throw;
            }

            return(Task.FromResult(result));
        }