به نام خدا
سلام!
در حال ساخت یک برنامه بودم دیدم که خیلی از حجم رم کامپیوتر صرف عکس هایی میشه که در حافظه بارگذاری میشه! حتی اگه عکس شما بی کیفیت ترین عکس و کم حجمترین عکس ممکن باشه با با کیفیت ترین حجم و پرحجمترین عکس با سایز مساوی توی رم یه مقدار رو اشغال میکنن و اونم به خاظره اینه که همشون به بیتمپ bitMap تبدیل میشن! یعنی شما میتونید بگید که یک عکس 10 در 10 با هر کیفیتی چقدر حجم اشغال میکنه! برای محاسبه این مثال تعداد کل پیکسا ها رو به دست میاریم! که در این مثال 10*10 میشه 100 پیکسل و میدونیم هر پیکسل شامل سه رنگ RGB هست که هر کدوم 8 بیت دارند در نتیجه حالت رنگ بندی ما 24 بیتی هست! و یعنی هر پیکسل 3 بایت اختصاص داده میشه! در نتیجه هر عکس که 10 در 10 باشه قطعا حجم فایل bitMap اون (تقریبا) 300 بایت هست!
خوب قرار شد بگیم چه کار کنیم که تا وقتی آبجکت ما در صفحه نشون داده نشده عکسش لود نشه!
راستش یه تابع به نام paint هست که هر وقت قرار باشه که آبجکت ما مثلا UserControl رسم بشه این تابع صدا زده میشه (یک event هست) من از این استفاده کردم! و گفتم اگه خواست رسم بشه! (در چه صورت یک آبجکت رسم میشه؟ درصورتی که مثلا اسکرول بشه که بخوایم اون آبجکتمون رو ببینیم! پس ویندوز میاد و اونو رسم میکنه و تابع رو اجرا میکنه) ما توی تابع میگیم که اگه آبجکت ما توی صفحه قابل دیدن هست (یعنی تا جایی اسکرول شده که بشه اونو دید) حالا بیا عکس رو لود کن!


        private void ّFunctionName_Paint (object sender, PaintEventArgs e)
        {
            if (!isPainted) // if isPainted was false paint it!
            {
                if (lControl.IsControlVisibleToUser(panel1))
                {
                    using (Bitmap img = new Bitmap(picturePath))
                    {
                        CoverPictureBoxInit(resizeImage(img, new Size(img.Width / (100 / 30), img.Height / (100 / 30))));
                    }
                    this.Paint -= (this.FunctionName_Paint );
                    isPainted = true;
                }
            }
        }

در کد بالا isPainted یک bool هست که میخوایم ببینیم آیا این آبجکت هنوز رسم شده یا نه که پیشفرض اون روی flase هست!
lControl یک کلاس هست که به شکل زیر نوشته شده!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
namespace electrobo
{
    class lControl
    {
        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        internal struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
            public int Width { get { return this.Right - this.Left; } }
            public int Height { get { return this.Bottom - this.Top; } }
        }
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        internal static extern bool GetUpdateRect(IntPtr hWnd, ref RECT rect, bool bErase);
        public static bool IsControlVisibleToUser(Control control)
        {
            control.Invalidate();
            Rectangle bounds = control.Bounds;
            RECT rect = new RECT { Left = bounds.Left, Right = bounds.Right, Top = bounds.Top, Bottom = bounds.Bottom };
            return GetUpdateRect(control.Handle, ref rect, false);
        }
    }
}

panel1 هم اون چیزی هست که میخوایم ببینیم برای کاربر قابل نمایش هست یا نه!
بعد میگه اگه panel1 نشون داده شده! با استفاده از تابع CoverPictureBoxInit اون picturebox که میخوایم نشون بدیم به panel1 اضافه میشه و عکسش هم از به عنوان آرگومان تابع به صورت Image گرفته میشه!
اون using هم که نوشتم برای اینه که بدون اینکه عکس به طور کامل ذخیره بشه! عکس مورد نظر بیاد و سایز رو همونجا تغییر بدیم و نمایش بدیم که اینکار به شدت توی فضای رم تاثیر داره و پیشنهاد میکنم شمام استفاده کنید تا حجم کمتری از رم رو برای عکس های کوچیک اشغال کنید!
برای اینکه بتونید استفاده کنید تابع resizeImage هم براتون میزارم:
        public static Image resizeImage(Image imgToResize, Size size)
        {
            return (Image)(new Bitmap(imgToResize, size));
        }

اینم اون چیزی که شد:
امیدوارم مفید بوده باشه!
موفق باشید
یا علی مدد...!