تغییر اندازه عکس به همراه افزودن لوگو در دات نت

برای انتشار عکس روی وب نیاز هست تغییراتی از قبلی اندازه (طولی و عرضی) یا کیفیت عکس و یا قرار دادن نشان یا لوگوی خود ایجاد کنیم. اما اینکار را اگر بخواهیم برای تعداد محدودی عکس انجام دهیم شاید زمان زیادی صرف نشود ولی تعداد عکسها که بالاتر میرود انجام اینکار خیلی زمان زیادی را از ما میگیرد. برای همین یک برنامه ساده و در عین حال کاربردی نیاز هست.

 

 

در مسئله ای که پیش رو داشتم وقتی تعداد عکسها زیاد بود به مشکل پر شدن RAM برخورد کردم و با استفاده از کتابخانه‌ای که در ادامه معرفی کردم و یکمی سفارشی سازی، مشکل را حل کردم.

 

کتابخانه استفاده شده در این برنامه ImageProcessor در محیط دات نت هست: اینجا

 

public void ResizeAndWatermarkImages(string source = "", string destination = "", 
int width = 800, int height = 600, int quality = 70,
string watermarkText = "", string fontName = "Arial", int fontSize = 10,
FontStyle fontStyle = FontStyle.Bold, bool dropShadow = true, Color watermarkColor = default(Color))
{

    if (!string.IsNullOrEmpty(source) && !string.IsNullOrEmpty(destination))
    {
	    // هدف ما تبدیل هر نوع عکسی به jpg هست
        ISupportedImageFormat format = new JpegFormat();
        FontFamily waterMarkFont = new FontFamily(fontName);

        Font waterMarkFontForFindPosition = new Font(fontName, fontSize, fontStyle);

        var photoBytes = File.ReadAllBytes(source); // change imagePath with a valid image path

        //حفظ مقیاس طول و عرض عکس
        var tempBitmap = new Bitmap(source);
        var ratioX = (double)width / tempBitmap.Width;
        var ratioY = (double)height / tempBitmap.Height;
        var ratio = Math.Min(ratioX, ratioY);

        var newWidth = (int)(tempBitmap.Width * ratio);
        var newHeight = (int)(tempBitmap.Height * ratio);

        var size = new Size(newWidth, newHeight);

        //تعیین جای متن مورد نظر روی عکس
        var imageTemp = Image.FromFile(source);
        var graphicsTemp = Graphics.FromImage(new Bitmap(imageTemp, size));

        var sz = graphicsTemp.MeasureString(watermarkText, waterMarkFontForFindPosition);

        var x = (int)(newWidth - sz.Width) / 2;
        var y = (int)(newHeight - sz.Height) - 10;

        var position = new Point();
        if (x < y)
        {
            position.X = x + 15;
            position.Y = y;
        }

        else
        {
            position.X = x;
            position.Y = y;
        }

        // استفاده از کتابخانه مورد نظر
        using (var inStream = new MemoryStream(photoBytes))
        {
            using (var outStream = new MemoryStream())
            {
                using (var imageFactory = new ImageFactory(preserveExifData: true))
                {
                    imageFactory.Load(inStream)
                        .Resize(size)
                        .Watermark(new TextLayer()
                        {
                            DropShadow = true,
                            FontFamily = waterMarkFont,
                            Text = watermarkText,
                            Style = fontStyle,
                            FontColor = watermarkColor,
                            Position = position,
                            FontSize = fontSize,
                        })
                        .Format(format)
                        .Quality(quality)
                        .Save(outStream);

                    imageFactory.Save(destination);
                }
            }
        }

        graphicsTemp.Dispose();
        tempBitmap.Dispose();
        imageTemp.Dispose();
    }
}

همانطور که در تابع بالا میبینید برای سفارشی کردن تابع مورد نظر تمامی ورودی های لازم را گرفتیم و اما نکته مهم و مورد نظر برای سرعت بخشیدن به تبدیل عکسها این است که از دستور Parallel.Foreach استفاده کنیم. چون به صورت همزمان چندین Thread را برای این کار به فایلها اختصاص میدهد.

 

var sourceFiles = Directory.GetFiles(txt_source.Text.Trim());
progressBar1.Minimum = 0;
progressBar1.Maximum = sourceFiles.Length;

Task.Run(delegate
{
    Parallel.ForEach(sourceFiles, sourcefile =>
    {
        var destinationFile = txt_dest.Text.Trim() + Path.GetFileName(sourcefile);
        _resizeAndWaterMark.ResizeAndWatermarkImages(sourcefile, destinationFile, 800, 600, 70, "AminMohamadi.ir", "Arial", 13, FontStyle.Bold, true, Color.White);

        BeginInvoke((Action) delegate
        {
            this.progressBar1.Value++;
            this.lbl_status.Text = @"Processing " + progressBar1.Value + @"/" + progressBar1.Maximum;
        });
    });
});
    

به طور مثال برای تبدیل 1290 عکس حدود 2:40 وقت صرف شد.

 

لینک کلی پروژه: اینجا

 


نظرات

برای نظر دادن کافیست وارد حساب کاربری خود شوید.