PDA

View Full Version : تبدیل مقادیر RGB به پیکسل یا یک عکس



mvb_mehran
شنبه 26 مرداد 1392, 18:55 عصر
سلام
من مقادیر RGB دارم میخوام بهعکس تبدیلشون کنم باید چیکار کنم؟؟
لطفا کمکم کنید
پیشاپیش ممنون

arefba
شنبه 26 مرداد 1392, 19:27 عصر
به سادگی
http://bytes.com/topic/c-sharp/answers/883553-converting-rgb-bytes-valid-image

مهرداد صفا
یک شنبه 27 مرداد 1392, 03:25 صبح
سلام
من مقادیر RGB دارم میخوام بهعکس تبدیلشون کنم باید چیکار کنم؟؟
لطفا کمکم کنید
پیشاپیش ممنون


با سلام.
مواد لازم:
- کلاسهای موجود در namespace های System.Drawing و System.Drawing.Imaging:


using System.Drawing;
using System.Drawing.Imaging;

- تابع RtlMoveMemory یا CopyMemory برای انتقال یکجای یک مقدار از حافظه مثل آرایه به یک قسمت دیگر (یک عدد):

[System.Runtime.InteropServices.DllImport("kernel32")]
static extern void RtlMoveMemory(IntPtr destination,ref byte source,int count);

در اصل این تابع دو اشاره گر یا IntPtr برای آدرسهای مقصد و منبع می گیرد که چون ما قصد داریم یک آرایه بایت را کپی کنیم آگومنت دوم را به شکل ref تعریف کردیم که در واقع همان آدرس متغیر به تابع ارسال خواهد شد. شما بسته به سلیقه و نیاز خود می توانید از:

System.Runtime.InteropServices.Marshal.Copy
استفاده کنید که در این صورت باید تغییراتی هم در کد ایجاد کنید.
- یک آرایه سه بعدی از byte که مقادی داده های rgb را در خود نگاه می دارد:


byte[width,height,2] pixels;
توجه داشته باشید که ترتیب رنگها باید به صورت برعکس (bgr) در آرایه قرار داده شوند. به عنوان مثال اگر مقدار rgb اولین پیکسل برابر:

rgb(150,100,50) باشد باید به این ترتیب در آرایه قرار بگیرند:


pixels[0,0,0]=50;//b
pixels(0,0,1]=100;//g
pixels(0,0,2]=150;//r


- یک bitmap که قرار است مقادیر rgb به آن انتقال پیدا کنند با طول و عرض به مقدار لازم:


Bitmap DestinationBitmap=new Bitmap(width,height);


حالا داده ها را از منبع که ممکن است فایل یا هر چیزی باشد به آرایه منتقل کنید.
در اینجا ما صرفا تمام پیکسلها را به رنگ آبی (rgb(0,0,255)) تغییر می دهیم:


for(int i=0;i<width;i++)
for(int j=0;j<height;j++)
pixels(i,j,0)=255;

با استفاده از متود Bitmap.LockBits داده های مربوط به Bitmap را قفل می کنیم تا gc به طور خودکار آنها را جا به جا نکند:


BitmapData data = DestinationBitmap.LockBits(new Rectangle(0, 0,width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

همانطور که میبینید مقدار برگشتی این متود یک شی از System.Drawing.Imaging.BitmapData است. به عنوان اولین آرگومنت یک Rectangle به طول و عرض DestinationBitmap ایجاد کردیم، در واقع با این عمل تمام پیکسلهای تصویر را lock کردیم. با مقداردهی دومین آرگومنت مشخص کردیم که قصد خواندن و نوشتن فضای حافظه مربوط به DestinationBitmap را داریم و سومین آرگومنت مشخص کننده نوع داده هاست.
به نظر می رسد مقدمات کار فراهم شده و زمان کپی کردن آرایه در حافظه مربوط به DestinationBitmap است. خصوصیت Scan0 از کلاس BitmapData آدرس اولین خانه از حافظه Bitmap را دارد، یعنی دقیقا جایی که داده های درون آرایه باید به آنجا کپی شوند. به این شکل با استفاده از تابع RtlMoveMemory آرایه را کپی می کنیم:

RtlMoveMemory(data.Scan0, ref pixels[0, 0, 0], pixels.Length);
[/CSHARP'

Bitmap مورد نظر شما آمادست. فقط قبل از مصرف حافظه قفل شده را UnLock کنید تا حافظه به طور خودکار و به خوبی مدیریت شود:
[CSHARP]
DestinationBitmap.UnlockBits(data);


نمونه کد کامل:

//in the name of god
//صل الله علی محمد و آله

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
[System.Runtime.InteropServices.DllImport("kernel32")]
static extern void RtlMoveMemory(IntPtr destination,ref byte source,int count);
public Form1()
{
InitializeComponent();
this.Size = Screen.PrimaryScreen.Bounds.Size;
Bitmap FormBitmap = new Bitmap(this.Width, this.Height);
byte[, ,] pixels = new byte[this.Width, this.Height, 3];
for(int i =0;i<this.Width;i++)
for (int j = 0; j < this.Height; j++)
pixels[i, j, 0] = 255;

BitmapData data = FormBitmap.LockBits(new Rectangle(0, 0, this.Width, this.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
RtlMoveMemory(data.Scan0, ref pixels[0, 0, 0], pixels.Length);
FormBitmap.UnlockBits(data);
this.BackgroundImage = FormBitmap;
}
}
}


سوالی بود بفرمایید.

mvb_mehran
یک شنبه 27 مرداد 1392, 14:22 عصر
بسیار ممنون از راهنماییهاتون
وقتی پیکسل های یک عکس ومیخونم به این شکل است :
Color [A=255, R=254, G=255, B=255]
میخوام همین مقادیر رو به عکس تبدیل کنم باز.
لطفا کدی بنویسید که پیکسل های یک عکس و بخونه و بعد همون پیکسل ها رو به عکس تبدیل و در جای دیگه ذخیره کنه. ممنون

مهرداد صفا
یک شنبه 27 مرداد 1392, 23:31 عصر
بسیار ممنون از راهنماییهاتون
وقتی پیکسل های یک عکس ومیخونم به این شکل است :
Color [A=255, R=254, G=255, B=255]
میخوام همین مقادیر رو به عکس تبدیل کنم باز.
لطفا کدی بنویسید که پیکسل های یک عکس و بخونه و بعد همون پیکسل ها رو به عکس تبدیل و در جای دیگه ذخیره کنه. ممنون

خواهش می کنم.
در این صورت داده ها به شکل argb هستند و bitmap هم باید 32bpp باشد.
برای گرفتن داده ها از bitmap یک بار دیگر تابع RtlMoveMemory را این بار با یک نام دیگر و به شکل زیر تعریف کنید:


[System.Runtime.InteropServices.DllImport("kernel32", EntryPoint = "RtlMoveMemory")]
static extern void CopyMemory2(ref byte destination, IntPtr source, int count);

آرایه مقصد هم باید به شکل زیر تعریف شود:

byte[width,height,4] pixels....

سپس متود LockBits مربوط به bitmap منبع را اجرا کنید و مانند مثال قبلی ولی این بار با تابع CopyMemory2 داده ها را از اولین خانه در حافظه به آرایه ای که تعریف کردید کپی نید. داده ها به صورت bgra در آرایه کپی خواهند شد. در آخر متود Unlockbits مربوط به bitmap منبع را اجرا کنید.