PDA

View Full Version : سوال: اشاره گر در vb.net



R_BABAZADEH
پنج شنبه 03 مرداد 1387, 13:57 عصر
می خواستم بدونم چه جوری میشه با pointerتو vb.net کار کرد,یه تابع برای کار بر روی اشاره گر وجود داره اسمش هم marshal هستش.
ولی نمی دونم چه جوری میشه به خونه بعدیش اشاره کرد؟

__H2__
پنج شنبه 03 مرداد 1387, 17:01 عصر
سلام
Marshal یک کلاس است، یک کلاس ایستا.
یک سری متد هم برای عملیات های مارشالینگ و کست های موضعی دارد.

مثلاً با متدهای این کلاس میتوانید یک ساختار Structure را به یک آرایه بایتی تبدیل کنید یا بلعکس.
یا میتوان اطلاعات را در نقطه خاص و مجازی در RAM ریخت و خواند.



ولی نمی دونم چه جوری میشه به خونه بعدیش اشاره کرد؟

یعنی چی؟

چه کار میخواهید بکنبد که فکر میکنید کلاسس فوق مشکل شما را حل میکند.
چون معمولاً نیازی نمیشود. در ذات وقتی یک متغییری از نوع یک کلاس تعریف میکنید، ان متغییر اشره گر است یا باکلمه کلیدی ByRef میتوانید پارامترهای ورودی توابع را اشاره گری به داده اصلی تعریف کنید.

یعنی منظورم آن است که شاید کاری که شما نیاز دارید، به سادگی ممکن باشد و نیاز به هیچ نوع مارشالینگی هم نباشد.

BAHAL_KEYHAN
جمعه 04 مرداد 1387, 22:32 عصر
اگه با c++ کار کرده باشید منظورمو می فهمید!اشاره گر در واقع یه متغیر هستش که خیلی شبیه integer هستش بخاطر اینکه میشه اونو با یک عدد صحیح جمع کرد یا منها کرد,در واقع با این کار میشه به خونه های بعدی یا قبلی که که از نظر ذخیر تو memory هستند اشاره کرد.ولی اینجا اصلآ intptr یه کلاسیه که در درونش ادرس یک خونه خواص وجود داره ولی ما نمی تونیم اونو +1 کنیم که به خونه ی بعد اون ادرس تو memory اشاره کنیم.
من می خوام با تابع bitmapdata و استفاده از تابع scan0 موجود تو تابع که اشاره گر ی که به pixel اول عکس اشاره می کنه ارایه میده رو عکس یه کاری کنم.البته این هم در نظر بگیر که خونه ی بعدی حافظه به pixel دوم اشاره میکنه.

__H2__
شنبه 05 مرداد 1387, 16:32 عصر
سلام
عزیز جان، به حد کافی با ++C و اسمبلی کار کردم که منظور ایشان را متوجه شوم.
ولی مشکل اینجا است که اغلب موارد افراد کاری را میخواهند از راه نادرستی انجام دهند، مثل همین عکس که گفتید!
این اصلاً و به هیچ وجه راهش نیست و منظور من هم همین بوده، یعنی در دات نت معمولاً به یک اشاره گر واقعی مثل ++C نیاز نمیشود و افراد هم که یک تجربه ای در ++C داشته اند، تا گیر میکنند، فکر میکنند چاره هر مشکلی در اشاره گرهای ++C است.
ولی این کار با ذات کدهای مدیریت شده چندان همگن نیست و حتماً راه مدیریت شده و منطقی برای آن کار وجود دارد، و باید دنبالش راه مدیرت شده اش باشید.

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

راه منطقی این کار در دات نت، لود کردن تصویر در شی Bitmap آنگاه شما متدهای GetPixel و SetPixel دارید که به شما اجازه میدهد به رنگ یک پیکسل بر اساس x و y نقطه مورد نظر دسترسی پیدا کنید.

BAHAL_KEYHAN
شنبه 05 مرداد 1387, 23:42 عصر
بهترین روش برای این کارو خودم خوب بلدم,البته سو تفاهم نشه قصد بی حرمتی ندارم راه شما هم درسته,ولی get pixel بصورت سخت افزاری کار درستی نیس چون که میاد با یه سری عملیات رنگ pixel بر می گردونه و این کار اگه بخواد رو تک تک pixel ها انجام بشه خیلی طول میکشه,ولی اگه بخوای با pointer ای که بهpixelهای عکس به صورت سخت افزاری اشاره می کنه می تونی با سرعت نور البته نسبت به روش قبل کار کنی.بعد مشکل من هم حل شد
(ptr = IntPtr.op_Explicit(ptr.ToInt32 + 1
اینجوری ptr به ادرس بعدی اشاره میکنه
بعدش هم انقدر تابع وکلاس هستش که برنامه کنترل شده باشه
مثل stride که تعداد byte های یک scanline بر می گردونه.

__H2__
یک شنبه 06 مرداد 1387, 21:49 عصر
سلام
در مورد سرعت متاسفانه در این مورد دفاعی از کد مدیریت شده نمیتوانم بکنم... !
البته لازم به ذکر است که اصل بدنه کد متد GetPixel اصلاً مربوط به دات نت نیست و مربوط به API به نام GdipBitmapGetPixel میشود. که بیشک سرعت پردازشی به اندازه سیستم پردازش تصویر مبتنی بر اشاره گر واقعی نخواهد داشت.
ولی بحث همگن بودن همچنان وجود دارد.




(ptr = IntPtr.op_Explicit(ptr.ToInt32 + 1

ولی تازه متوجه شدم مشکلتان کجابوده!
و حالا که اینقدر سرعت برایتان مهم است، میتوانم حداقل یک کمک کوچک بکنم که حضورمان در تاپیک چندان کشک نبوده باشد!

تابعی را که با نام op_Explicit شما فراخوانی کرده اید، در واقع در کد داخلی اش از IntPtr یک وهله جدید میسازد و شما میتوانید این کار را دستی انجام دهید، بدون فراخانی یک متد و Call اضافه


ptr = New System.IntPtr(ptr.ToInt32 + 1)

یعنی کد فوق الذکر، همان کد شما است که در بدنه op_Explicit اجرا میشود، ولی اینجا بدون فراخوانی یک Function مستقیماً اجرا شده و به نظر من زیباتر و قابل فهم تر هم است.

موفق باشید.

naeeme
دوشنبه 07 مرداد 1387, 09:40 صبح
این نمونه کد هم برای دسترسی به پیکسلها در یک تصویر هست.( این کد در داخل MSDN وجود داره)




Dim bmp As New Bitmap(".\test.bmp")

' Specify a pixel format.
Dim pxf As PixelFormat = Pixelformat.Format24bppRgb

' Lock the bitmap's bits.
Dim rect As Rectangle = New Rectangle(0,0,bmp.Width,Bmp.Height)
Dim bmpData As BitmapData = bmp.LockBits(rect, _
ImageLockMOde.ReadWrite, pxf)

'Get the address of the first line of the bitmap.
Dim ptr As IntPtr = bmpData.Scan0

' Declare an array to hold the bytes of the bitmap.
Dim numBytes as Integer = bmp.Width * bmp.Height * 3
Dim rgbValues(numBytes) As Byte

' Copy the RGB values into the array.
Marshal.Copy(ptr, rgbValues, 0, numBytes)

' Manipulate the bitmap, such as changing the
' blue value for every other pixel in the the bitmap.
For counter As Integer = 0 To rgbValues.Length Step 6
rgbValues(counter) = 255
Next counter

' Copy the RGB values back to the bitmap
Marshal.Copy(rgbValues, 0, ptr, numBytes)

' Unlock the bits.
bmp.UnlockBits(bmpData)


' Draw the modified image.
e.Graphics.DrawImage(bmp, 0, 0)

e.Graphics.Dispose()


اما یه نکته! من هیچ وقت این روش رو توصیه نمی کنم! خودم ازش می خواستم استفاده کنم اما یه دردسر داشت! براساس یک دوره که هیچوقت نتونستم رابطه اش با عرض تصویر رو پیدا کنم، هر n بیت یک بیت داریم که در تصویر دیده نمیشه! به همین دلیل از این روش برای تولید تصویر نمیشه استفاده کرد اما برای ویرایش تصویر براساس رنگ( مثلا تبدیل تمام رنگهای قرمز به سبز) میشه ازش استفده کرد و بسیار سریعتر از getpixel و setpixel هست.

BAHAL_KEYHAN
شنبه 12 مرداد 1387, 18:48 عصر
تابعی هست که طول یک scanlineرو بر می گردونهو اگر اونو منهای widthتصویر کنید تعداد byteهایی که نشان گر pixel نیستند را بدست آورید اون تابع وتابعstrideدر کلاسbitmapdata.البته باید ذکر کنم که این byteها در هنتهای هر lineهستند.

Microsoft.net
شنبه 12 مرداد 1387, 21:46 عصر
اگه با c++ کار کرده باشید منظورمو می فهمید!اشاره گر در واقع یه متغیر هستش که خیلی شبیه integer هستش بخاطر اینکه میشه اونو با یک عدد صحیح جمع کرد یا منها کرد,در واقع با این کار میشه به خونه های بعدی یا قبلی که که از نظر ذخیر تو memory هستند اشاره کرد.ولی اینجا اصلآ intptr یه کلاسیه که در درونش ادرس یک خونه خواص وجود داره ولی ما نمی تونیم اونو +1 کنیم که به خونه ی بعد اون ادرس تو memory اشاره کنیم.
من می خوام با تابع bitmapdata و استفاده از تابع scan0 موجود تو تابع که اشاره گر ی که به pixel اول عکس اشاره می کنه ارایه میده رو عکس یه کاری کنم.البته این هم در نظر بگیر که خونه ی بعدی حافظه به pixel دوم اشاره میکنه.

در نسل جدید زبانهای برنامه سازی خیلی از صاحب نظران علوم نرم افزاری اصل وجودی اشاره گر ها رو زیر سوال برده اند و اکثر ایراداتی رو که به استفاده از اشاره گر ها گرفته اند ثابت شده . لذا روند توسعه زبانهای برنامه نویسی نسل جدید به محدود کردن استفاده از اشاره گرها و استفاده از روشهای جایگزین بوده