دستکاری تصاویر در ASP.NET

در دات نت همیشه کارهای بزرگ را می‌توان با چند خط کوتاه، برنامه‌ی ساده انجام داد. یکی از این کارها ترسیم و دستکاری تصاویر است. در این مقاله سعی می‌کنیم دستکاری تصاویر با دات نت را با هم مرور کنیم. یاد آور می‌شوم که مقاله‌ای در باب ترسیم، با نام گرافیک در ASP.NET توسط دوست خوبمان آقای مجتبی کیانی قبلا در سایت منتشر شده است که مطالعه آن به شما پیشنهاد می‌کنم.

در دات نت ترسیم یک تصویر همیشه با استفاده از شیئی از کلاس Graphics روی می‌دهد. و می‌دانیم متد DrawImage از این کلاس، متدی غنی برای اجرای کارهای گیج کننده گرافیکی به صورت خیلی ساده است. متد دیگری نیز با نام DrawImageUnscaled وجود دارد که این متد فقط وقتی مورد استفاده قرار می‌گیرد که مستطیل‌های منبع و مقصد همسان باشند.

قبل از هرچیز برای ترسیم باید بدانیم:
?- همیشه یک مستطیل مقصد وجود دارد (در حقیقت مساحتی که تصویر داخل آن کپی میشود).
?- همیشه یک مستطیل منبع وجود دارد که ممکن است تمام یا بخشی از تصویر اولیه را در بر بگیرد (در حقیقت مساحتی از تصویر اولیه که می‌خواهیم کپی شود).
?- مستطیل مقصد ممکن است کوچکتر یا بزرگتر مستطیل منبع باشد (در این صورت اندازه تصویر ایحاد شده با اندازه تصویر اولیه فرق خواهد کرد).

همینطور دانستن نکات زیر برای ترسیم به ما کمک میکند:
?- به هنگام ترسیم تصویر می‌توان با استفاده از ImageAttributes در تصویر تغییراتی داد، در این صورت بسیاری از عملیات پیچیده ترسیم به راحتی ممکن می‌گردد.
?- شیئی از کلاسGraphics می‌تواند برای تغییر اندازه نیز استفاده شود، همینطور این شیئ دارای فیلترهای الحاقی میباشد که بر کیفیت و سیمای تصویر اثر میگذارند.

در مثال‌های زیر می‌بینیم که چطور متد DrawImage مورد استفاده قرار میگیرد. "myGraphics" شئی از کلاس graphics و "img" تصویری که در حافظه ذخیره شده است فرض شود. شما می‌توانید عملکرد هرقسمت را به ترتیب در مثال نمونه همراه این مقاله مشاهده کنید (توجه داشته باشید که چون این نمونه مثال روی دستگاه شما فایل result.jpg را می‌نویسد، ممکن است هنگام اجرا با ایراد امنیتی روبرو شوید، در این صورت به سند readme.doc در بین فایل‌های مثال رجوع کنید).

?- یک کپی مستقیم از تصویر:

myGraphics.DrawImage(img,)

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

?- کپی با اندازه های متفاوت:

myGraphics.DrawImage(img,BiggerRectangle)

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

?- انتخاب قسمتی از عکس اولیه:

DistRectangle=new Rectangle(100,100,10,10)// مستطیل مقصد
myGraphics.DrawImage(img, DistRectangle,75,40,10,10,GraphicsUnit.Pixel)

این مثال نشان می‌دهد که میتوان مستطیل منبع (یا مقصد) را مستقیما در پارامترهای DrawImage تعریف کرد. در ضمن در مورد GraphicsUnit، به یاد داشته باشیم که همیشه واحد گرافیک Pixel است. در مثال بالا مستطیل مقصد نیز به اندازه مستطیل منبع است. اما اگر بخواهیم اندازه قسمت کپی شده را تغییر دهیم باید مستطیل مقصد را با اندازه‌ای متفاوت از مستطیل منبع تعریف کنیم.

?- انتخاب قسمتی از عکس اولیه و اعمال تغییر اندازه:

DistRectangle =new Rectangle(10,20,120,40) )// مستطیل مقصد
SourRectangle =new Rectangle(75,40,10,10) )// مستطیل منبع
myGraphics.DrawImage(img, DistRectangle, SourRectangle,GraphicsUnit.Pixel)

چرخاندن (Rotating) و تغییر صورت (transformation) یک تصویر نیز توسط شیئی از Graphics کلاس مقدور است. برای transformation باید یک ماتریس تعریف کنید. در این مثال، ما تصویر را به اندازه 30 درجه در جهت خلاف عقربه های ساعت می‌چرخانیم.


?- چرخاندن با مقیاس درجه:

Matrix mx = new Matrix();
mx.Rotate(-30);
myGraphics.Transform = mx;
myGraphics.DrawImage(img,new Point(100,50));

یا می‌توانید به شکل زیر تغییر اندازه و چرخاندن را انجام دهید.

?- چرخاندن با مقیاس طول و عرض:

Matrix mx = new Matrix();
mx.Translate(20.0F, 10.0F);
myGraphics.MultiplyTransform(mx);
myGraphics.RotateTransform(20.0F);

در این مثال 20.2F و 10.0F به ترتیب X و Yای هستند که به صورت ماترس ترجمه می‌شوند.

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

?- ایجاد حالت آینه‌ای:

Rectangle DistRectangle = new Rectangle(50,50,320,240);
Rectangle SourRectangle= new Rectangle(0, img.Height, img.Width,- img.Height);
myGraphics.DrawImage(img,DistRectangle,SourRectangle,GraphicsUnit.Pixel);

ترسیم تصویرهای شفاف توسط کلاس ImageAttributes انجام می‌شود. چنین شیئی میتواند یک ColorMatrix در خود ذخیره کند که توسط آن میتوان alphaی یک تصویر را هنگام ترسیم تغییر داد. از میان تمام propertyها میتوان به ColorMatrix.Matrix33 اشاره کرد که شما را قادر میکند کاملا شفافیت یک تصویر را تنظیم کنید.

?- ترسیم های شفاف:

myGraphics.DrawImage(img1,new Point(0,0));
ImageAttributes ia = new ImageAttributes();
ColorMatrix cm = new ColorMatrix();
cm.Matrix33=0.5f;
ia.SetColorMatrix(cm);
myGraphics.DrawImage(img2,new Rectangle(0, 0, img2.Width, img2.Height ), 0, 0, img2.Width, img2.Height, GraphicsUnit.Pixel, ia);

?- ایجاد Thumbnail از یک تصویر:
مطلب دیگری که خوب است در باره آن مختصری بحث شود ایجاد Thumbnail از یک تصویر است. اگرچه در این روش از شئی از Graphics استفاده نمی‌شود اما بجاست که استفاده از این روش برای کوچک کردن عکس ها با روش (شماره ??) مورد مقایسه قرار گیرد. Thumbnailها تصویرهای کوچکی هستند که معمولا در گالری‌های تصویر برای پیش نمایش با اندازه کوچک و به تعداد زیاد در یک صفحه نمایش داده می‌شوند. برای تولید آن از روش زیر استفاده می‌کنیم:

System.Drawing.Image.GetThumbnailImageAbort myCallBack = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
System.Drawing.Image imgResizedImage = MainPic.GetThumbnailImage(360,270,myCallBack,IntPtr.Zero);

پارامترها:
به ترتیب از چپ به راست: (عرض، طول، callback و callbackData) هستند که callback یک نماینده برای Image.GetThumbnailImageAbort است. در نگارش 1.0 +GDI، نماینده عملا مورد استفاده قرار نمی‌گیرد. اما شما حتماً باید یک نماینده بسازید و آن را به یک مرجع منتصب کنید (برنامه نمونه را نگاه کنید). callbackData نیز همیشه IntPtr.Zero است.

اگر تصویر اولیه، در خود Thumbnail به صورت ذخیره شده داشته باشد این متد آن را به اندازه خواسته شده تغییر اندازه می‌دهد و در غیر این صورت این متد با کوچک کردن سایز تصویر اصلی Thumbnail می‌سازد. برای ایجاد تصویرهایی با اندازه کوچک (برای مثال 120 در 120) این متد بسیار کار آمد است اما در صورتی که بخواهیم تصویر را در اندازه های بزرگ تری کوچک کنیم، احتمال افت کیفیت برای تصویرها وجود خواهد داشت. در این حالت توصیه می‌شود که تصویر اصلی را با استفاده ازDrawImage کوچک کنید. روش زیر برای تغییر اندازه تصویرها در اندازه‌های بزرگتر روشی کارآمدتر است.

??- تغییر اندازه:

System.Drawing.Image NewImage = new System.Drawing.Bitmap(300,300);
System.Drawing.Graphics NewImageGraphics = System.Drawing.Graphics.FromImage(NewImage);
Rectangle DistRectangle = new Rectangle(0,0,NewImage.Width,NewImage.Height);
Rectangle SourRectangle = new Rectangle(0,0,my1stImage.Width,my1stImage.Height);
NewImageGraphics.DrawImage(my1stImage,DistRectangle,SourRectangle,GraphicsUnit.Pixel);

در این روش یک Image جدید با نام NewImage را از نوع Bitmap و با اندازه های دلخواه تعریف کردیم و در حقیقت یک کپی از تصویر اولیه را با مستطیل منبع هم اندازه تصویر اولیه روی تصویر جدید با اندازه مستطیل مقصد هم اندازه تصویر جدید ترسیم کردیم.
تمام مباحث به ترتیب در برنامه‌ای گرد آورده شده است. این برنامه دو تصویر را از روی دستگاه شما (سرور) می‌خواند و حاصل هر مرحله را در تصویری با نام result.jpg ذخیره میکند و آن را نمایش می‌دهد. برای اجرای این برنامه کافی است IIS و NET Framework. روی دستگاه شما نصب شده باشد.