PDA

View Full Version : سوال: کاهش Quality عکس با کد



Zabi42
شنبه 15 خرداد 1389, 01:06 صبح
با سلام
می خوام یه تصویر کاربر upload کنه و من با کد در Quality تصویر رو کاهش بدم تا حجم عکس کاهش پیدا کنه و در سرور ذخیره کنم چطور می تونم این کارو بکنم؟؟؟
تو نت راجه بهش سرچ زدم و یه چیزایی پیدا کردم ولی چون با این کدها تا حالا کار نکردم بعضی از توابعشو نفهمیدم چی کار میکنن مثل تابع ImageCodecInfo و تابع EncoderParameter ؟؟؟

hamedsabzian
شنبه 15 خرداد 1389, 01:17 صبح
System.Drawing.Image img=System.Drawing.Image.FromFile("oldFileName");
img.Save("newFileName"+"jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
تبدیل فرمت که همراه با فشرده گی می باشد.

Zabi42
شنبه 15 خرداد 1389, 03:55 صبح
اقای HamedSabzian ممنون از پاسختون
حالا اگه کدی رو که باهاش میشه quality عکس رو هم تغییر داد و بگید ممنون میشم

hamedsabzian
شنبه 15 خرداد 1389, 04:40 صبح
private void btnReduce_Click(object sender, EventArgs e)
{
// Reset the progress bar
prgReduce.Value = 0;
// Show the FolderBrowserDialog where the user selects where to save the files
if (fbdSave.ShowDialog() == DialogResult.OK)
{
// We will store the correct image in this object
ImageCodecInfo iciJpegCodec = null;
// This will specify the image quality to the encoder
EncoderParameter epQuality = new EncoderParameter(System.Drawing.Imaging.Encoder.Qu ality, (int)numQual.Value);
// Get all image codecs that are available
ImageCodecInfo[] iciCodecs = ImageCodecInfo.GetImageEncoders();
// Store the quality parameter in the list of encoder parameters
EncoderParameters epParameters = new EncoderParameters(1);
epParameters.Param[0] = epQuality;
// Loop through all the image codecs
for (int i = 0; i < iciCodecs.Length; i++)
{
// Until the one that we are interested in is found, which is image/jpeg
if (iciCodecs[i].MimeType == "image/jpeg")
{
iciJpegCodec = iciCodecs[i];
break;
}
}
// Loop through the files in the list
foreach (string strFile in lstPhotos.Items)
{
// Take another step on the progress bar
prgReduce.PerformStep();
// Create a new Image object from the current file
Image newImage = Image.FromFile(strFile);
// Get the file information again, this time we want to find out the extension
FileInfo fiPicture = new FileInfo(strFile);
// Save the new file at the selected path with the specified encoder parameters, and reuse the same file name
newImage.Save(fbdSave.SelectedPath + "\\" + fiPicture.Name, iciJpegCodec, epParameters);
}
}
// Open the folder containing the new items
System.Diagnostics.Process.Start(fbdSave.SelectedP ath.ToString());
}
http://itprojectsforyou.com/Reducing-JPEG-Picture-Quality-using-Csharp.php

hamedsabzian
شنبه 15 خرداد 1389, 04:53 صبح
توی خط 11 یک نمونه از EncoderParametr می سازه که مشخصش کیفیته( می تونه چیزای دیگه ای مثل فشردگی و ... هم باشه) و برای اون یک میزان با یک عدد مشخص می کنه.
بقیش واضحه...
توی خط 37 موقع ذخیره کردن عکس پارامترهایی(کیفیت، فشردگی،...) که می خواد عکس بر اساس اونا ذخیره بشه رو به همراه فرمت عکس ( Jpeg یا Gif یا ...) و نام فایل جدید رو ارسال می کنه.

Zabi42
شنبه 15 خرداد 1389, 17:37 عصر
اقای HamidSabzi باز هم تشکر برای توجه و پاسختون
دقیقا من هم تو جستجویی که تو نت کردم همین مثال رو پیدا کرده بودم و چون تا حالا از این توابع استفاده نکردم نمیدونم که خیلی از اونها چی کار میکنن حالا اگه امکانش هست الگوریتم کلی برنامه رو برام توضیح بدید یا اگه در مورد توابعی که توی این مثال هست توضیح یا مطلب اموزشی دارید برام بذارید
باز هم ممنون از لطفتون

hamedsabzian
شنبه 15 خرداد 1389, 21:59 عصر
کد Comment داره!!!
همه ی کد بالا قراره یک عکس با فرمت Jpeg رو با پارامتر Quality جدیدی ذخیره کنه.
هدف نهایی خط 37 می باشد.
ابتدا اون رو توضیح میدم.
عکس رو با سه پارامتر دوباره ذخیره کرده، اسم فایل که واضحه، دومین پارامتر ImageCodecInfo در واقع مشخص کننده ی فرمت ذخیره سازی می باشد که همان طور که در پست های قبلی گفتم می تونه Jpeg ، Gif ، Png و .. باشه، سومین ورودی که یک آرایه از نوع پارامترهای ذخیره سازی (EncodeParameter) عکسه. این ارایه میتونه حاوی پارامتر های مختلفی مثل ColorDepth و Compression و Version و Quality و .... که برای فرمت های( Encode) مختلف معنی دارن.
حالا کلیت الگوریتم اینطوریه که یک شی ImageCodecInfo تعریف میکنه. خط 9.
یک EncoderParameter تعریف می کنه و اون رو با دو پارامتر می سازه اولی مشخص کننده ی نوع پارامتر که اینجا Quality هست و دومین پارامتر که یک عدد برای مشخص کردن میزان این پارامتر. خط 11.
همه ی Encoder هایی که توی سیستم موجود هست رو می گیره. خط 13 ( می خواد از توی اونها Jpeg رو به دست بیاره و عکس رو دوباره با اون ذخیره کنه)
یه آرایه از نوع EncoderParameters تعریف میکنه و توی اون شیی رو که در خط 11 تعریف میکنه توش میریزه که بعدا همین رو بره به تابع Save. خط 15 و 16.
فرمت Jpeg رو پیدا می کنه از توی فرمت هایی که از سیستم گرفته. و میریزه توی شیی که در خط 9 تعریف کرده. خط 18 تا 26.
کیفیت همه ی فایلایی رو که انتخاب شده تغییر میده و ذخیره می کنه. خط 26 تا 39.

Zabi42
یک شنبه 16 خرداد 1389, 04:14 صبح
اقای HamidSabzi واقعا ممنون از توضیحتون

Zabi42
پنج شنبه 20 خرداد 1389, 19:42 عصر
دوستان من کدهای بالا رو به صورت زیر تو برنامم نوشتم ولی خط اخرش error داره


FileUpload1.PostedFile.SaveAs(path + FileUpload1.FileName);


// We will store the correct image codec in this object
ImageCodecInfo iciJpegCodec = null;
// This will specify the image quality to the encoder
EncoderParameter epQuality = new EncoderParameter(System.Drawing.Imaging.Encoder.Qu ality, (int)20);
// Get all image codecs that are available
ImageCodecInfo[] iciCodecs = ImageCodecInfo.GetImageEncoders();
// Store the quality parameter in the list of encoder parameters
EncoderParameters epParameters = new EncoderParameters(1);
epParameters.Param[0] = epQuality;
// Loop through all the image codecs
for (int i = 0; i < iciCodecs.Length; i++)
{
// Until the one that we are interested in is found, which is image/jpeg
if (iciCodecs[i].MimeType == "image/jpeg")
{
iciJpegCodec = iciCodecs[i];
break;
}
}
// Create a new Image object from the current file
System.Drawing.Image newImage = System.Drawing.Image.FromFile(Context.Server.MapPa th(FileUpload1.FileName));
// Get the file information again, this time we want to find out the extension
FileInfo fiPicture = new FileInfo(Context.Server.MapPath(FileUpload1.FileNa me));
// Save the new file at the selected path with the specified encoder parameters, and reuse the same file name
newImage.Save(Server.MapPath("~/Image") + fiPicture.Name, iciJpegCodec, epParameters);
}

error رو خط newImage.Save هستش
error:Parameter is not valid.

hamedsabzian
پنج شنبه 20 خرداد 1389, 20:44 عصر
(int)20
رو با 20L جایگزین کن!
اگه باز هم Erorr میده، ببین کدوم parameter ولید نیست؟

Zabi42
جمعه 21 خرداد 1389, 00:46 صبح
20L دادم بازم همون Error رو داد
من زیاد بلد نیستم با توابع مربوط به عکس و فایل کار کنم
کدهام درسته؟؟؟؟

hamedsabzian
جمعه 21 خرداد 1389, 01:39 صبح
کد رو تغییر دادم در قالب یه نمونه برنامه.
امتحان کردم، جواب می ده!

Zabi42
جمعه 21 خرداد 1389, 15:03 عصر
اقای HamidSabzi خیلی خیلی تشکر می کنم از اینکه کمکم کردی و وقت گذاشتید


توی پروژه ی من فرض کنید هر کاربر یه البوم عکس داره و من میخوام برای هر کاربر یه فولدری همنام با نام کاربری اون درسرور بسازم به همین منظور وقتی کاربر log in میکنه نام کاربری اون را در یک cooki یا session ذخیره میکنم و میخوام وقتی کاربر دکمه ی upload رو زد اول فولدرهای روی سرور چک بشه که فولدری با نام مثلا علی در سرور وجود داره یا نه که درصورت موجود بودن فولدر علی عکسهای کاربر درون ان upload بشه واگر نبود یک فولدر با نام علی در سرور ایجاد بشه و بعد عکس ها درون فولدر جدید upload بشه برای این کار چطوری می تونم اون شرط رو بزارم ؟؟؟ وچطور میتونم فولدر متناسب با نام کاربر در سرور ایجاد کنم؟؟؟
و با توجه به کدهایی که در مثال بالا هست چطور میتونیم عکسی رو که Quality ان را تغییر دادیم اندازش رو هم تغییر بدیم مثلا 100*100بشه؟؟؟؟؟ در این رابطه توی نت خیلی جستجو کردم ولی متاسفانه چون توابع مربوط به فایل و عکس رو باهاش کار نکردم و چیز زیادی راجع بهشون نمیدونم نتونستم از کدهایی که پیدا کردم استفاده کنم و اونهارو متناسب با کار خودم تغییر بدم
اگر مطلب اموزشی فارسی در این رابطه هم دارید ممنون میشم برام بذارید تا کمتر سوال کنم و کمتر مزاحمتون شم

hamedsabzian
جمعه 21 خرداد 1389, 17:01 عصر
ساختن یک فولدر برای عکس های هر کاربر کار درستی نیست! بهتره همه ی عکس ها در یک مسیر باشند، و شما در DB ذخیره کنید که کدام عکس مربوط به چه کسی است. مثلا یه جدول که یک کلید خارجی داره که UserName کاربره و یه فیلد دیگه که اسم عکس (یا مسیر کامل) رو نگه میداره. خیلی بهتره!
برای Resize عکس در هنگام ذخیره کردن، Resize واقعی هنگام نمایش (Thumbnail) و ذخیره سازی، کد بالا رو کامل کردم و گذاشتم.
سعی کن با استفاده ازشون، متوجه بشی هر خطش چه کار می کنه!
برای ساختن پوشه:
System.IO.Directory.CreateDirectory("DirPath");
موفق باشید!

hamedsabzian
جمعه 21 خرداد 1389, 19:27 عصر
اقای HamidSabzi
درست: hamedsabzian.

Zabi42
دوشنبه 24 خرداد 1389, 02:38 صبح
سلام اقا HamidSabzian ببخشید اسمتونو اشتباه نوشتم
من اون مثالتونو بررسی کردم و در اون از تابع
GetThumbnailImage استفاده کرده بودید که گویا از توابع asp هست و به زیبایی حجم عکس رو پایین میاره فقط مشکل اینجاست که quality رو خیلی پایین میاره و کیفیت عکس رو بهم میریزه اگه میشد مثل مثال قبلی مقدار تغییر quality دست خودمون بود و عکس رو هم thubnail میکرد خیلی عالی میشد

hamedsabzian
دوشنبه 24 خرداد 1389, 02:47 صبح
سلام GetThumbnailImage کیفیت رو کم یا زیاد نمیکنه. فقط به اندازه ای که می خوایم در میاره.
فرض کنید روی یک عکس خیلی Zoom کنید، خوب کیفیتش رو از دست میده و راه حلش هم اینه که خیلی Zoom نکنید.
البته عکس رو وقتی jpg می کنید، ذاتا کیفیتش پاینتر میاد.

Zabi42
دوشنبه 24 خرداد 1389, 02:58 صبح
یعنی اگه بخوایم از GetThubnailImage استفاده کنیم و نخوایم کیفیت عکسمون خیلی افت کنه باید به فرمت غیر jpeg ذخیره کنیم؟؟؟

hamedsabzian
دوشنبه 24 خرداد 1389, 03:31 صبح
لزوما نه. اگه یه عکسی رو بیش از حد بزرگ با کوچک کنید و نسبت طول و عرضش رو به هم بزنید، کیفیت چیزی که می بینید نامناسبه.
بسته به مورد استفاده تون داره. در PNG و BMP کیفیت عکس کم نمیشه. توی BMP حجم خیلی زیاده، PNG خوبه ولی بازم حجمش از JPG بیشتره. اما توی WEB چون مهمه که حجم کم باشه از GIF و JPG استفاده میشه.

nafasak
جمعه 11 تیر 1389, 23:05 عصر
لزوما نه. اگه یه عکسی رو بیش از حد بزرگ با کوچک کنید و نسبت طول و عرضش رو به هم بزنید، کیفیت چیزی که می بینید نامناسبه.
بسته به مورد استفاده تون داره. در PNG و BMP کیفیت عکس کم نمیشه. توی BMP حجم خیلی زیاده، PNG خوبه ولی بازم حجمش از JPG بیشتره. اما توی WEB چون مهمه که حجم کم باشه از GIF و JPG استفاده میشه.
حامد جان،
چطور میشه با کیفیت ابتدایی فایل، سایزش رو تغییر داد؟

من مقدار Quality رو 100 و 100L قرار دادم ولی تحت هر شرایطی کیفیت به همون مقدار 20L پایین میاد.
حتی وقتی سایز رو تغییر نمیدم.