none
處理利用for each 取出由不同類別的集合包裝起來的集合問題 RRS feed

  • 問題

  • 小弟設計了一個方法 要回傳這個方法的集合  

    以下是這個方法代碼:

      Public Function 抓取某顏色視圖(ByVal pic As PictureBox, ByVal 顏色 As String) As percolor
    
    
    
            Dim bmpImg As New Bitmap(pic.Image)
            Dim percolors As New percolor
            i = 1
    
            FastPixel.LockBMP(bmpImg)
            For x座標 = 0 To pic.Width - 1
                For y座標 = 0 To pic.Height - 1
    
                    'if 像素點顏色匹配顏色
                    percolors.x座標.Add(x座標)
                    percolors.y座標.Add(y座標)
                    percolors.color.Add(Color.FromArgb(Convert.ToInt32(FastPixel.GetR(x座標, y座標)), Convert.ToInt32(FastPixel.GetG(x座標, y座標)), Convert.ToInt32(FastPixel.GetB(x座標, y座標))))
                    'endif
    
                Next
            Next
    
            Return percolors
    
      End Function
    
    'percolor 是由不同的類別集合包裝起來的類
    
    Public Class percolor
    
        Public x座標 As List(Of Integer)
        Public y座標 As List(Of Integer)
        Public color As List(Of Color)
    
    End Class
    
    
    '主程式:
    
     Dim percolor As New percolor
    
     For Each x As Object In percolor.x座標
    
    bitmap1.SetPixel(x,y:=,color:=)
    
            Next


    寫到主程式下面就卡住了

    我想讓主程式這裡能同時的一筆一筆將資料導回去 

    也就是說我希望它是能像下面這樣的邏輯寫法

    For Each s As Object In percolor
    
    bitmap1.SetPixel(s.x座標,s.y座標,s.color)
    
            Next


    可是偏偏好像這裡就是少了什麼  不能這樣編寫  想請大大們提供一下解法  謝謝

    2013年1月6日 下午 01:57

解答

  • 一時間想不出寫法  剛剛突然靈光一現 想出怎麼寫了

    應該是像下面這樣吧

       Structure percolor
            Dim x座標 As Integer
            Dim y座標 As Integer
            Dim color As Color
    
        End Structure
    
    
    
    Public Function 抓取某顏色視圖(ByVal pic As PictureBox, ByVal 顏色 As String) As List(Of percolor)
    
      Dim bmpImg As New Bitmap(pic.Image)
            Dim percolorx As New List(Of percolor)
            Dim percolors As New percolor
            i = 1
    
            FastPixel.LockBMP(bmpImg)
     For x座標 = 0 To pic.Width - 1
                For y座標 = 0 To pic.Height - 1
    
                    'if 像素點顏色匹配顏色
                    percolors.x座標 = x座標
                    percolors.y座標 = y座標
                    percolors.color = Color.FromArgb(Convert.ToInt32(FastPixel.GetR(x座標, y座標)), Convert.ToInt32(FastPixel.GetG(x座標, y座標)), Convert.ToInt32(FastPixel.GetB(x座標, y座標)))
                    'endif
                    percolorx.Add(percolors)
                    percolors = Nothing
    
                Next
            Next
    
            Return percolorx
        End Function
    
     
    '主程式
    
    For Each s As percolor In 顏色識別學習.抓取某顏色視圖(Me.PictureBox1, Me.ComboBox1.Text)
    
                bitmap1.SetPixel(s.x座標, s.y座標, s.color)
    
            Next
    

    2013年1月6日 下午 03:24
  • Windows 的座標系統是左上角為 0,0 ,x 軸向右為正,y 軸向下為正。

    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    • 已標示為解答 向恩 2013年3月3日 上午 02:30
    2013年3月2日 下午 03:24

所有回覆

  • For Each 只能用在 IEnumerable(Of T) 的物件,你的 percolor 又不是陣列或集合,當然不能這樣用。

    學習不是查個 Google 套個書上的範例就算了,而是去熟悉了解每個程式碼背後的意義,否則就算學個幾百年,它也不會是你的。

      • 小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
      • 雲端學堂Facebook: http://www.facebook.com/studyazure

    2013年1月6日 下午 02:37
    版主
  • 一時間想不出寫法  剛剛突然靈光一現 想出怎麼寫了

    應該是像下面這樣吧

       Structure percolor
            Dim x座標 As Integer
            Dim y座標 As Integer
            Dim color As Color
    
        End Structure
    
    
    
    Public Function 抓取某顏色視圖(ByVal pic As PictureBox, ByVal 顏色 As String) As List(Of percolor)
    
      Dim bmpImg As New Bitmap(pic.Image)
            Dim percolorx As New List(Of percolor)
            Dim percolors As New percolor
            i = 1
    
            FastPixel.LockBMP(bmpImg)
     For x座標 = 0 To pic.Width - 1
                For y座標 = 0 To pic.Height - 1
    
                    'if 像素點顏色匹配顏色
                    percolors.x座標 = x座標
                    percolors.y座標 = y座標
                    percolors.color = Color.FromArgb(Convert.ToInt32(FastPixel.GetR(x座標, y座標)), Convert.ToInt32(FastPixel.GetG(x座標, y座標)), Convert.ToInt32(FastPixel.GetB(x座標, y座標)))
                    'endif
                    percolorx.Add(percolors)
                    percolors = Nothing
    
                Next
            Next
    
            Return percolorx
        End Function
    
     
    '主程式
    
    For Each s As percolor In 顏色識別學習.抓取某顏色視圖(Me.PictureBox1, Me.ComboBox1.Text)
    
                bitmap1.SetPixel(s.x座標, s.y座標, s.color)
    
            Next
    

    2013年1月6日 下午 03:24
  • 圖形處理上一般不會這樣用。

    若沒有非全彩需求,先做 DrawImage 畫到全彩空白同大小 Bitmap

    LockBits 後,可以得到一維顏色陣列

    若有非全彩需求,配合全彩需求設定單點結構或位元組數,其他宣告成長整數或 4 bytes 組成的 Argb 結構

    依據尺寸宣告成二維陣列

    Buffer.BlockCopy 就可以得到 2dPoints(y, x)


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年1月9日 下午 04:25
  • 請問一下  心冷大大  您這裡用的這個Buffer.BlockCopy   這個東西 

    代表的是 它這些資料是存在哪裡做處理阿?

    是記憶體嗎?  還是硬碟中的Buffer  還是顯卡上阿?

    2013年1月12日 下午 12:42
  • MSDN 上的 Buffer.BlockCopy 就有範例了,他只是包裝 API CopyMemory 。

    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年1月13日 下午 02:33
  • 看不太懂以下這個範例是什麼意思 ??   可以請大大稍微解釋一下嗎?

    在下列範例中,名為 arr 之陣列中位元組 0-16 的值會複製到位元組 12-28。不論重疊範圍為何,來源位元組的值都會順利複製完成。

    Const INT_SIZE As Integer = 4
    Dim arr() As Integer = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }
    Buffer.BlockCopy(arr, 0 * INT_SIZE, arr, 3 * INT_SIZE, 4 * INT_SIZE)
    For Each value As Integer In arr
       Console.Write("{0}  ", value)
    Next
    ' The example displays the following output:
    '       2  4  6  2  4  6  8  16  18  20      


    • 已編輯 向恩 2013年1月14日 下午 01:12
    2013年1月14日 下午 01:11
  • 將陣列 0 ~ 3 的元素,複製到 3 ~ 7 的位置。

    一般通常不會自己複製到自己身上就是了。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年1月14日 下午 04:50
  • 我的疑問是這個範例總共有十個元素 分別是 

    2, 4, 6, 8, 10, 12, 14, 16, 18, 20

    為什麼從0~16 複製到 12~28

    數值是變成

     2  4  6  2  4  6  8  16  18  20    
    2013年1月14日 下午 07:08
  • 您好,

    從0的位置(也就是2)開始copy,copy 4個int ,所以是2, 4, 6, 8

    所以就變成了

    2, 4, 6, 2, 4, 6, 8, 16, 18, 20


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2013年1月14日 下午 09:30
  • 因為 BlockCopy 是以 Byte 為單位。 Integer 是 4 bytes, 0 ~ 9 個 Integer 就是對應到 0 ~ 39 bytes 。

    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年1月15日 上午 12:14
  • 圖形處理上一般不會這樣用。

    若沒有非全彩需求,先做 DrawImage 畫到全彩空白同大小 Bitmap

    LockBits 後,可以得到一維顏色陣列

    若有非全彩需求,配合全彩需求設定單點結構或位元組數,其他宣告成長整數或 4 bytes 組成的 Argb 結構

    依據尺寸宣告成二維陣列

    Buffer.BlockCopy 就可以得到 2dPoints(y, x)


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    心冷大大  我找到的這塊快速模組中的這塊代碼

     Function LockBMP(ByVal bmp As Bitmap) As Boolean
            Try
                Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height) '矩形物件,定義影像範圍
                bmpData = bmp.LockBits(rect, Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat) '鎖定影像區記憶體(暫時不接受作業系統的移動)
                ptr = bmpData.Scan0 '影像區塊的記憶體指標
                L = bmpData.Stride '每一影像列的長度(bytes)
                Bpx = L \ bmp.Width '每一像素的位元組數(3或4)
                n = L * bmp.Height '影像總位元組數
                ReDim rgb(n - 1) '宣告影像副本資料陣列
                System.Runtime.InteropServices.Marshal.Copy(ptr, rgb, 0, n) '拷貝點陣圖資料到副本陣列
                Return True
            Catch ex As Exception
                Return False
            End Try
        End Function

    這塊東西是不是就是如您描述類似的用法呢?
    2013年1月16日 下午 04:54
  • 類似。

    rgb 陣列的型別還須確認。全彩圖是 4 bytes ,由於你有 x, y 需求,將 rgb 陣列宣告為二維陣列較方便。

    一維通常是灰階、二階化這類,與座標無關的較方便。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年1月17日 下午 01:25
  • 我想確認一下 就是比如說我現在有一組顏色 它是紅色好了  我確認了它的R G B 三原色  然後我要從一張圖片中

    將這張圖片具有紅色的部分 將這些紅色給抽離出來  並打印到RIC控鍵上

    我原本的思路是打算用知道R G B的色值去分類出來  但是用byte的處理方式是?

    如我用上面的代碼來改

    1.設立單點結構

     Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height) '矩形物件,定義影像範圍

      我有很多組深淺不同的紅色 所以要設定許多組的這樣的紅色單點結構  是要設立許多組這個東西?

    2.成立二維陣列

    dim Q(POINT,rect) 

    這個二維陣列就是包含座標點的資訊還有這些不同的單點結構所組成的二維陣列沒錯吧?


    • 已編輯 向恩 2013年1月20日 上午 05:11
    2013年1月20日 上午 05:09
  • 先看懂 MSDN 線上手冊的範例,他是處理藍色:

    http://msdn.microsoft.com/zh-tw/library/ms229672.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1

    上面範例是處理 24 位元全彩,一般我偏向 32 位元全彩。請注意上面網址最上方的連結:Format32bppRgb

    一般來說圖檔在32位元全彩模式下 (含 Windows 需在全彩) 是 Argb

    所以通常宣告成:

    <System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack:=1)> _

    Structure myColorArgb

       Dim Alpha As Byte

       Dim Red As Byte

       Dim Green As Byte 

       Dim Blue As Byte

    End Structure

    ...

    ' 我印象中是先 Y 後 X

    ReDim arrColor(Height -1, Width - 1) As myColorArgb

    用 arrColor 取代 rgbValues

    再透過

    arrColor(y, x).Red 讀值即可。

    紅色單點結構是啥?看不懂。單點幹嘛用 Rect ?點線面,點是點,面是面,請解釋清楚,不要自己取名詞後還要讓網友猜。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年1月20日 上午 06:54
  • 不好意思 對這些東西的概念還不夠清楚  經大大你這樣提醒之後 才知道這些知識面

    目前我試著拿您給的連接的範例  下去做更改及測試

    又發現了一個問題 就是它這邊有用到Marshal.Copy (IntPtr, Byte[], Int32, Int32)

    這個指令  它處理的是一維的byte陣列 

    那我把這個二維的byte陣列帶進來 就出錯了 

    如下:

    Marshal.Copy(ptr, arrColor(bmp.Height - 1, bmp.Width - 1).Blue, 0, numBytes)

    它顯示:

    錯誤 1 多載解析失敗,因為具備這些引數的 'Copy' 不存在,故無法呼叫:
        'Public Shared Sub Copy(source As System.IntPtr, destination() As System.IntPtr, startIndex As Integer, length As Integer)': 型別 'Byte' 的值無法轉換成 '1-維陣列屬於 System.IntPtr'。

    這些是顯示這個指令不能處理二維的byte 請問這邊可以用哪個指令來取代呢?

    2013年1月21日 下午 03:47
  • 以下這些回應和原題目 (foreach) 好像差很多。

    請另題發問。


    學習不是查個 Google 套個書上的範例就算了,而是去熟悉了解每個程式碼背後的意義,否則就算學個幾百年,它也不會是你的。

      • 小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
      • 雲端學堂Facebook: http://www.facebook.com/studyazure

    2013年1月22日 上午 01:00
    版主
  • 我目前我要設計方向就是要設計一支  可以將一張圖片 我指定的某種顏色 將此顏色  從這張圖片給分類出來 當然這個顏色包含了深淺

    所以思路是 先將某顏色的RGB分別轉換成byte型別的結構體  然後用lockbits 取出其對應的座標及RGB byte型別的資料 再進行處理 

    然後將此顏色給打印在PIC控鍵上  

    據網友給小弟的資訊  如下:

    '---------------------------------------------------------

    先看懂 MSDN 線上手冊的範例,他是處理藍色:

    http://msdn.microsoft.com/zh-tw/library/ms229672.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1

    上面範例是處理 24 位元全彩,一般我偏向 32 位元全彩。請注意上面網址最上方的連結:Format32bppRgb

    一般來說圖檔在32位元全彩模式下 (含 Windows 需在全彩) 是 Argb

    所以通常宣告成:

    <System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential, Pack:=1)> _

    Structure myColorArgb

       Dim Alpha As Byte

       Dim Red As Byte

       Dim Green As Byte 

       Dim Blue As Byte

    End Structure

    ...

    ' 我印象中是先 Y 後 X

    ReDim arrColor(Height -1, Width - 1) As myColorArgb

    用 arrColor 取代 rgbValues

    再透過

    arrColor(y, x).Red 讀值即可。                   但發現這個範例裡所有的指令是處理一維陣列的

    '-----------------------------------------------------------

    我試著整合這些訊息    然後改寫成代碼  

    Imports System
    Imports System.Drawing
    Imports System.Drawing.Imaging
    Imports System.Runtime.InteropServices
    Imports System.Windows.Forms
    
    
    Public Class Form1
    
        Structure myColorArgb
    
            Dim Alpha As Byte
    
            Dim Red As Byte
    
            Dim Green As Byte
    
            Dim Blue As Byte
    
        End Structure
        'Call method from OnPaint.
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            LockUnlockBits(e)
        End Sub
    
        Private Sub LockUnlockBits(ByVal e As PaintEventArgs)
            Dim bmp As New Bitmap("C:\Users\tom\Desktop\企鵝.jpg")
    
            ' Specify a pixel format.
            Dim pxf As PixelFormat = PixelFormat.Format32bppRgb
    
            ' 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 numBytes As Integer = bmpData.Stride * bmp.Height
            Dim rgbValues(numBytes) As Byte
            Dim arrColor(bmp.Height - 1, bmp.Width - 1) As myColorArgb
    
            ' Copy the RGB values into the array.
            Marshal.Copy(ptr, arrColor(bmp.Height - 1, bmp.Width - 1).Blue, 0, numBytes)
            Marshal.Copy(ptr, arrColor(bmp.Height - 1, bmp.Width - 1).Red, 0, numBytes)
            Marshal.Copy(ptr, arrColor(bmp.Height - 1, bmp.Width - 1).Green, 0, numBytes)
    
            Dim tx As myColorArgb
            tx.Blue = 255
    
            For x = 0 To bmp.Height - 1
                For y = 0 To bmp.Width - 1
                    If tx.Blue = arrColor(y, x).Blue And tx.Green = arrColor(y, x).Green And tx.Red = arrColor(y, x).Red Then
                        arrColor(y, x).Blue = 0
                        arrColor(y, x).Red = 0
                        arrColor(y, x).Green = 0
                    End If
                Next
            Next
    
            Marshal.Copy(arrColor(bmp.Height - 1, bmp.Width - 1).Blue.ToString, 0, ptr, numBytes)
            Marshal.Copy(arrColor(bmp.Height - 1, bmp.Width - 1).Red.ToString, 0, ptr, numBytes)
            Marshal.Copy(arrColor(bmp.Height - 1, bmp.Width - 1).Green.ToString, 0, ptr, numBytes)
    
    
    
    
            bmp.UnlockBits(bmpData)
    
    
            ' Draw the modified image.
            e.Graphics.DrawImage(bmp, 0, 0)
    
            e.Graphics.Dispose()
        End Sub
    
    End Class
    

    目前我這邊產生的一個最大的問題是  Marshal.Copy  無法去處理二維陣列  所以這邊我想再請教一下

    這邊該如何去處理二維陣列byte型別的資料呢?   

    2013年1月22日 下午 01:42
  • 看不懂 
    底下這樣不行嗎?

            Dim rgbValues(numBytes - 1) As Byte
            Marshal.Copy(ptr, rgbValues, 0, numBytes)
    
            Dim tx As myColorArgb
            tx.Blue = 255
    
            For i = 0 To numBytes - 1 Step 4
                If tx.Blue = rgbValues(i) And tx.Green = rgbValues(i + 1) And tx.Red = rgbValues(i + 2) Then
                    rgbValues(i) = 0
                    rgbValues(i + 1) = 0
                    rgbValues(i + 2) = 0
    
                End If
            Next
    
            Marshal.Copy(rgbValues, 0, ptr, numBytes)



    以下為簽名檔,如果你愛拉椅子坐那就是你的問題。
    先查MSDN文件庫
    再用GOOGLE搜尋
    才到論壇來發問

    這是論壇不是技術支援中心
    沒有人得無償解答你的問題

    在標題或文章註明很急
    不會增加網友回覆速度

    2013年1月23日 上午 05:04
  • 基本上同一問題應該在同一篇。

    當你看同一篇時,一開始就會看到,用:Buffer.BlockCopy

    這個才能把一維陣列複製到二維陣列。

    也在那篇說過,這個等同於 API 的 CopyMemory


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年1月23日 下午 03:11
  • 不好意思  版主小朱說 小弟的議題跟原本的主題篇題了 要我開另一個問題討論

    處理利用for each 取出由不同類別的集合包裝起來的集合問題

    所以相關的內容要參照上面的連結

    稍微google一下 利用Buffer.BlockCopy 處理二維的範例

      Dim bData(,) As Byte = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}
    
            Dim baData() As Byte = New Byte(bData.Length) {}
    
            Buffer.BlockCopy(bData, 0, baData, 0, bData.Length)
    

    搞了點代碼出來  研究一下 有問題再上來發問

    2013年1月24日 下午 12:51
  • 所以你的問題是在Buffer.BlockCopy還是圖形處理?

    以下為簽名檔,如果你愛拉椅子坐那就是你的問題。
    先查MSDN文件庫
    再用GOOGLE搜尋
    才到論壇來發問

    這是論壇不是技術支援中心
    沒有人得無償解答你的問題

    在標題或文章註明很急
    不會增加網友回覆速度

    2013年1月25日 上午 10:04
  • 看不懂 
    底下這樣不行嗎?

            Dim rgbValues(numBytes - 1) As Byte
            Marshal.Copy(ptr, rgbValues, 0, numBytes)
    
            Dim tx As myColorArgb
            tx.Blue = 255
    
            For i = 0 To numBytes - 1 Step 4
                If tx.Blue = rgbValues(i) And tx.Green = rgbValues(i + 1) And tx.Red = rgbValues(i + 2) Then
                    rgbValues(i) = 0
                    rgbValues(i + 1) = 0
                    rgbValues(i + 2) = 0
    
                End If
            Next
    
            Marshal.Copy(rgbValues, 0, ptr, numBytes)



    以下為簽名檔,如果你愛拉椅子坐那就是你的問題。
    先查MSDN文件庫
    再用GOOGLE搜尋
    才到論壇來發問

    這是論壇不是技術支援中心
    沒有人得無償解答你的問題

    在標題或文章註明很急
    不會增加網友回覆速度

    這個寫法是處理一維的  但圖面是二維的平面 用x,y 座標去定義每個像素點 用一維怎麼夠呢? 所以當然是不行的

    2013年2月1日 下午 02:12
  • 心冷大大 我今天把代碼搞出來了 稍微理解了您的意思 

    但不曉得為什麼影像會是跑出下面這個 

    代碼我貼上來 您看一下吧

    Private Sub LockUnlockBits(ByVal e As PaintEventArgs) Dim bmp As New Bitmap("C:\Users\tom\Desktop\企鵝.jpg") Dim pxf As PixelFormat = PixelFormat.Format32bppRgb ' 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 numBytes As Integer = bmpData.Stride * bmp.Height '影像佔據的位元組數 Dim rgbValues(numBytes) As Byte '影像可存取的副本陣列 Dim arrColor(Height - 1, Width - 1) As myColorArgb '用 arrColor 取代 rgbValues ' Copy the RGB values into the array. Marshal.Copy(ptr, rgbValues, 0, numBytes) Buffer.BlockCopy(rgbValues, 0, arrColor, 0, numBytes) '將影像存取到一維陣列的資料用 arrColor 取代 rgbValues ' Manipulate the bitmap, such as changing the ' blue value for every other pixel in the the bitmap. '------------------------- '像素點中有像素值b為255的狀況將此像素點取出,其他顏色設為白色 For x = 0 To bmp.Height - 1 For y = 0 To bmp.Width - 1 If Not arrColor(y, x).Blue = 255 And arrColor(y, x).Green = 0 And arrColor(y, x).Red = 0 Then arrColor(y, x).Blue = 0 arrColor(y, x).Red = 0 arrColor(y, x).Green = 0

     arrColor(y, x).Alpha = 0 End If Next Next '------------------------- ' Copy the RGB values back to the bitmap Buffer.BlockCopy(arrColor, 0, rgbValues, 0, numBytes) 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() End Sub



    • 已編輯 向恩 2013年2月1日 下午 09:51
    2013年2月1日 下午 09:50
  • 建議這兩篇併回去在一起,比較不會亂掉。

    查了一下我先前寫過的程式碼,發現結構拷貝是 VB6 在用的。VBNET 不支援結構拷貝,因此要做到這樣的判斷,很麻煩,還不如回去用陣列。

    1. 結構處理方式麻煩在下面這樣

          Dim pnt As IntPtr
          Dim arrColor(bmp.Height - 1, bmp.Width - 1) As myColorArgb
          For y = 0 To bmpData.Height - 1
             For x = 0 To bmpData.Width - 1
                pnt = New IntPtr(ptr.ToInt32 + (bmpData.Stride * y) + (4 * x))
                arrColor(y, x) = Runtime.InteropServices.Marshal.PtrToStructure(pnt, GetType(myColorArgb))
             Next
          Next
          For x = 0 To bmp.Height - 1
             For y = 0 To bmp.Width - 1
                If Not arrColor(y, x).Blue = 255 And arrColor(y, x).Green = 0 And arrColor(y, x).Red = 0 Then
                   arrColor(y, x).Blue = 0
                   arrColor(y, x).Red = 0
                   arrColor(y, x).Green = 0
                   arrColor(y, x).Alpha = 0
                End If
             Next
          Next
    ' ... 略

    2. 所以偷懶改用 2 維整數陣列

          Dim findColor As Int32 = Color.FromArgb(255, 0, 0, 255).ToArgb
          Dim replaceColor As Int32 = Color.FromArgb(0, 0, 0, 0).ToArgb
          Dim intColor(bmp.Height - 1, bmp.Width - 1) As Int32
          Buffer.BlockCopy(rgbValues, 0, intColor, 0, numBytes)
          For x = 0 To bmp.Height - 1
             For y = 0 To bmp.Width - 1
                If intColor(y, x) And findColor < findColor Then
                   intColor(y, x) = replaceColor
                End If
             Next
          Next
          Buffer.BlockCopy(intColor, 0, rgbValues, 0, numBytes)
          Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, numBytes)

    3. 從你程式碼還可以再偷懶,把 rgbValues 拿掉,改用一維 intColor

          Dim lenColor = numBytes / 4
          Dim intColor(lenColor - 1) As Int32
          Runtime.InteropServices.Marshal.Copy(ptr, intColor, 0, lenColor)
          For x = 0 To intColor.Length - 1
             If intColor(x) And findColor < findColor Then
                intColor(x) = replaceColor
             End If
          Next
          Runtime.InteropServices.Marshal.Copy(intColor, 0, ptr, lenColor)

    另外你的順序不對,以上面方案 3 為例:

          Dim pxf As Imaging.PixelFormat = Imaging.PixelFormat.Format32bppArgb
          Dim bmpSource As New Bitmap("D:\Temp\Test.png")
          Dim bmp As New Bitmap(bmpSource.Width, bmpSource.Height, pxf)
          Dim g As Graphics = Drawing.Graphics.FromImage(bmp)
          g.PageUnit = GraphicsUnit.Pixel
          g.DrawImage(bmpSource, 0, 0, bmpSource.Width, bmpSource.Height)
          g.Dispose()
          ' Lock the bitmap's bits.
          Dim rect As Rectangle = New Rectangle(0, 0, bmp.Width, bmp.Height)
          Dim bmpData As Imaging.BitmapData = bmp.LockBits(rect, Imaging.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 numBytes As Integer = bmpData.Stride * bmp.Height '影像佔據的位元組數
    ' 上面方案 3
          ' Unlock the bits.
          bmp.UnlockBits(bmpData)
          ' 例如改完後用 PictureBox1
          PictureBox1.Image = bmp

    最後你要做顏色判斷的話,不要用 jpg 格式,jpg 會做破壞性混色運算,所以大部分都不會是純色,也不是原先的顏色,用 png 或 bitmap 才比較妥當。

    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年2月2日 下午 02:59
  • 不好意思 將問題併回去 恐怕得請教一下小朱大大的意見 小弟我沒這個權限 XD

    回到主題  請問一下心冷大大 我提出的這個影像處理的問題 恐怕是比較簡易的

    可以使用一維陣列就可以達成了  那我想請教一下什麼場合下用非得用到二維才能處理呢?

    我最終的目的其實是想要做影像辨識這個東西  我目前接觸過影像辨識的資訊

    我提一個較完整的例子 比如說 我去設定一個需要辨識的圖形  比如說是一部紅車

    然後這個辨識圖片夾雜紅車和其他顏色的車包含著它的背景  我要讓這支程式具有辨識這張圖片裡有我設定要辨識的紅車就通知使用者

    且我要讓這部紅車的顏色容許在誤差範圍內可以辨識  像這種案例適用二維還是一維呢? 具體還需要哪些技巧才能處理呢?

    2013年2月3日 上午 02:27
  • ...

    到這邊:http://ndltd.ncl.edu.tw/

    關鍵字:影像識別

    勾選 不限欄位

    找到跟你有關的來唸。

    基本上都是先做 R to V ,再透過特徵向量識別。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年2月3日 下午 12:20
  • 小弟又碰到困難了  上來這邊再發問一下

    目前我正在嘗試從一張圖中  去擷取這張圖的一個矩形區塊出來

    然後在另一個窗口中呈現  我是直接拿市面上已經有做好的模組來進行截圖的

    程式上傳到我的skydrive 請各位參考:

    點此連結

      Private Sub PictureBox_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint '只要在pic滑過去就會觸發事件
    
            Dim NEWBITMAP As New Bitmap(PictureBox1.Image)
            If c = 2 Then
                With e.Graphics
    
                    '------------------------------------
                    '問題區塊
                    Dim R(mdq.X - mdp.X, mdq.Y - mdp.Y) As Byte
                    Dim G(mdq.X - mdp.X, mdq.Y - mdp.Y) As Byte
                    Dim B(mdq.X - mdp.X, mdq.Y - mdp.Y) As Byte
    
                    'newpart.Image
                    FastPixel.LockBMP(NEWBITMAP)
                    For i = mdp.X To mdq.X
                        For j = mdp.Y To mdq.Y
    
                            R(i, j) = FastPixel.GetC(i, j, 1) '取得紅
                            G(i, j) = FastPixel.GetC(i, j, 2) '取得綠
                            B(i, j) = FastPixel.GetC(i, j, 3) '取得藍
    
                        Next
                    Next
                    For I = 0 To mdq.X - mdp.X
                        For J = 0 To mdq.Y - mdp.Y
                            FastPixel.SetP(I, J, R(I, J), G(I, J), B(I, J))
                        Next
                    Next
                    FastPixel.UnLockBMP(NEWBITMAP)
                    Dim newcolor As New Form2
                    newcolor.PictureBox1.Image = NEWBITMAP
                    newcolor.Show()
                    '問題區塊
                    '-----------------------------------
                    '.DrawRectangle(Pens.Black, 矩形區塊)
                    .DrawLine(Pens.Black, mdp.X, mdp.Y, mdq.X, mdp.Y)
                    .DrawLine(Pens.Black, mdp.X, mdp.Y, mdp.X, mdq.Y)
                    .DrawLine(Pens.Black, mdp.X, mdq.Y, mdq.X, mdq.Y)
                    .DrawLine(Pens.Black, mdq.X, mdp.Y, mdq.X, mdq.Y)
    
                End With
            End If
    
        End Sub

    目前問題主要出在 我做記號的地方 

     '問題區塊

    拿掉這塊我做記號的地方那塊程式 畫一個矩形時還算正常

    我不曉得為什麼這邊會導致圖面無法顯示


    • 已編輯 向恩 2013年2月24日 下午 03:50
    2013年2月24日 下午 03:49
  • FAQ

    先把 Paint 事件相關討論看完吧。

    http://social.msdn.microsoft.com/Search/zh-TW/?Refinement=112&query=Paint%20%e8%a8%98%e6%86%b6%e9%ab%94

    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。


    2013年2月24日 下午 05:23
  • 這個問題 主要跟釋放記憶體有關係嗎?  我有稍微改一下代碼  我換成用bitmap.clone 的方法去擷取區塊

    然後利用 Dispose的方法 用完就立即釋放記憶體的位置

    目前去框選區塊的功能是有出來了 也跑出了新的窗口  但不曉得為什麼抓的矩形圖形

    就是跟框選的區塊對不上  偶然還有打一個大叉叉的狀況出現 但似乎比較少了

    檔案上傳 請各位大大幫忙看一下吧 這是什麼問題?

    點此下載

    2013年2月25日 下午 04:12
  • 跟記憶體關係不大。

    而是你用的是 Paint 事件,Paint 事件本來就會被螢幕更新影響。所以只要一觸發 Paint 事件,你的圖形就會重畫。

    當你的滑鼠在上面移動時,Paint 事件就會不斷的被重複觸發,不斷被觸發下,你就一直重畫,後面畫啥已經不重要了,因為根本來不及畫。

    若希望不要一直重畫,就是在記憶體內繪圖,再把記憶體圖檔指給你的 PictureBox ,這樣情況下根本不使用 Paint 事件,只有畫過一次,系統觸發的 Paint 事件重畫範圍就只有滑鼠下方,肉眼根本無法分辨。

    所以關鍵字只需要 Paint 記憶體 ,就一堆相關討論。

    所以,你需要看看 Petzold 的書,有中譯本,你可以先看 VBNET / WPF 系列的,這邊因為在高階環境下,細節不會太多,但該有的觀念都有,最後回頭看 Windows 程式開發指南第五版,這本完全從 Windows 底層 API 去看問題,你就知道 Paint 事件到底是怎麼回事,沒事別在 Paint 事件畫圖,Paint 事件是給入門者跟高階者開發用,簡單的說就是只有非常簡單且需要即時更新、隨時重複的變更用 Paint 事件處理,其他一律不用 Paint 事件,避免造成效能損耗。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年2月25日 下午 04:51
  • Petzold  的書 小弟還沒接觸過

    查了一下Petzold  原來他是微軟的傳奇人物阿 XD  長見識了

    我想買幾本他的書放在我身邊當隨身參考的資料 可以請心冷大大幫我鑑定一下嗎?

    我目前在天龍找到這兩本:    

    1.微軟 Windows Presentation Foundation 程式設計指南

    2.Windows 程式設計 (Programming Windows, 5/e)

    不曉得您講的是不是這兩本?

    2013年2月26日 上午 12:21
  • 您好 心冷大大  目前小弟遇到兩個問題

    我將paint事件中原本會去觸發跑出矩形區塊的代碼 改到PictureBox1_MouseUp的事件中

    記憶體繪圖這件事發生在PictureBox1_MouseUp的事件 但是我用單步下去測的時候

    是可以分割出矩形區塊出來 但是整個建置之後開始測試 又不行了這是第一個問題

    第二個問題是不曉得為什麼我要分割出來的矩形區塊不曉得為什麼沒match到我框選的區塊

    檔案連結

    2013年2月27日 下午 02:17
  • 書本 1 可以的話,先找 VBNET 那本。

    書本 2 是推薦給所有寫 Windows 程式設計,不分語言的書。

    只要在討論區請貼精簡後程式碼。不是每個人都有空去下載你的程式碼來看,很簡單,根本找不到你一堆程式碼中問題的重點,而且,會讓人不爽,讓網友變成免費的義工,而不是討論的對象。

    你目前貼出來的程式碼看起來只要呼叫 DrawImage 即可。

    在 MouseDown 與 MouseUp 中找出 選取框 後,用 DrawImage 指定來源位置,畫到目標位置,完全用不到 Lock 這玩意。

    選取框也有一些既有討論,例如:

    http://social.msdn.microsoft.com/Forums/zh-TW/232/thread/5cb75e38-7345-427a-b276-c1d6e62567b8

    http://social.msdn.microsoft.com/Forums/zh-HK/232/thread/a2de72d9-7689-479a-ae81-7b34da43f53c

    本版置頂公告推薦的範例也是。

    搜尋 選取框 也可以找到既有討論。

    論壇置頂公告有下面這段,我覺得你後面的問題就是邏輯沒講,繞了一大段路不知道在幹嘛:

    張貼文章應注意事項及應提供資訊

    提問時請將原始目的及執行邏輯說明清楚

    很多網友會認為他只要把他認為需要討論的問題貼出來即可,但在論壇上常常見到問題本身已經陷入誤區,又沒有把原始要解決的狀況說明清楚,然後整串討論在誤區糾纏不休,不是要繞路走就是搞到最後無解。

    例如:原始目的可能是將圖檔另存為 TIF 格式,在 .Net framework 只要呼叫 Image.SaveFile 即可,但是有時會發生最後在討論 TIF 圖檔格式、寫入二進位檔結構等狀況。也有很多是 Windows 權限設定問題被當成 bug 或程式碼內容討論,提問者只會回復這段程式碼不行執行,卻不知道把錯誤訊息說清楚。

    完整明確的說明原始問題及執行邏輯後,再來進入程式碼討論,避免從邏輯就是錯的,造成程式碼討論無意義的窘況,節省提問者與網友間彼此的時間。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年2月27日 下午 03:02
  • 不好意思 上傳程式的時候沒想這麼多  我了解您的意思了 

    我用繪圖的方式講解一次這裡的動作邏輯

    圖示:

    我目前就是要做圖示的動作  但是這部分的動作是有問題的  

    第一個問題是用單步測試加下斷點的時候去測試這個動作 可以動作  可是編譯好檔案 不下斷點時 這個動作就不能做了

    第二個問題是我在單步測試的條件下去測試框選的動作  框選出來的矩形區塊在Form2呈現時  卻不是我框選的那個區域範圍

    以下是我目前的代碼:

     Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
          Handles PictureBox1.MouseDown
            
                mdp = e.Location '起始點
                c += 1
    
        End Sub
    
        Private Sub PictureBox_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint '只要在pic滑過去就會觸發事件
    
    
            If c = 2 Then
                With e.Graphics
                    .DrawLine(Pens.Black, mdp.X, mdp.Y, mdq.X, mdp.Y)
                    .DrawLine(Pens.Black, mdp.X, mdp.Y, mdp.X, mdq.Y)
                    .DrawLine(Pens.Black, mdp.X, mdq.Y, mdq.X, mdq.Y)
                    .DrawLine(Pens.Black, mdq.X, mdp.Y, mdq.X, mdq.Y)
                    c = 0
                End With
            End If
    
        End Sub
    
        Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    
    
            PictureBox1.Invalidate()
    
    
        End Sub
    
        Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
            Handles PictureBox1.MouseUp
    
            mdq = e.Location
            Dim NEWBITMAP As New Bitmap(PictureBox1.Image)
            Dim cloneBitmap As Bitmap
            Dim newpic As New Form2
    
            Dim xpoint, ypoint As Integer '左上角座標點
            c += 1
            If c = 2 Then
    
    
                '------------------------------------
                '問題區塊
    
                'NEWBITMAP.Clone()
                If mdp.X > mdq.X And mdp.Y > mdq.Y Then
                    xpoint = mdq.X
                    ypoint = mdp.Y
                ElseIf mdp.X > mdq.X And mdq.Y > mdp.Y Then
                    xpoint = mdq.X
                    ypoint = mdq.Y
                ElseIf mdp.X < mdq.X And mdp.Y < mdq.Y Then
                    xpoint = mdp.X
                    ypoint = mdq.Y
                ElseIf mdp.X < mdq.X And mdp.Y > mdq.Y Then
                    xpoint = mdp.X
                    ypoint = mdp.Y
                End If
    
    
                Dim format As PixelFormat = NEWBITMAP.PixelFormat
    
                Dim W, H As Integer
    
                W = Math.Abs(mdq.X - mdp.X)
                H = Math.Abs(mdq.Y - mdp.Y)
                Dim acpart As New Rectangle(xpoint, ypoint, W, H)
                cloneBitmap = NEWBITMAP.Clone(acpart, format)
                newpic.PictureBox1.Image = cloneBitmap
    
    
                '問題區塊
                '-----------------------------------
                '.DrawRectangle(Pens.Black, 矩形區塊)
    
                newpic.Show()
                c = 0
                acpart = Nothing
    
            End If
            NEWBITMAP = Nothing
            newpic = Nothing
    
    
        End Sub

    心冷大大您說可以用 DrawImage  等等我試著修改這部分的代碼 再測試看看好了

    2013年2月28日 上午 04:26
  • DrawImage 所有多型的連結,凡是有寫指定的部分,都可以用,看你熟啥:

    http://msdn.microsoft.com/zh-tw/library/system.drawing.graphics.drawimage.aspx

    前面建議你用 Shape 控制項來代替框線,如果不會自己寫,可以用 VB2008 以後內建的 PowerPacks 裡面有。這樣你只要管兩個座標,MouseDown 的 pStart ,MouseOver/MouseUp 的 pEnd ,再把左上角設給 Shape 的 Top, Left ,右下角設進去,框線完全不用畫圖。

    http://msdn.microsoft.com/zh-tw/library/microsoft.visualbasic.powerpacks.shape.aspx


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年2月28日 下午 01:09
  • 心冷大大 您好 我捨棄了paint事件的方法 改用畫布和Bitmap Clone方法來達成這些功能

    功能是出來了 但是框選出來後 跑出form2的矩形範圍 複製不對 我不曉得這部分我的邏輯哪邊錯誤了

    修改代碼如下:

      

      Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim bmp As New Bitmap(PictureBox1.Width, PictureBox1.Height)
            Dim g As Graphics = Graphics.FromImage(bmp)
            g.Clear(Color.White)
            PictureBox1.Image = bmp
            c = 4

        End Sub
        Dim mdp, mdq As Point  '座標點
        Dim x, y, c As New Integer  '取得x,y座標


        Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
          Handles PictureBox1.MouseDown
            
                mdp = e.Location '起始點
            c += 1

        End Sub

    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove PictureBox1.Invalidate() End Sub Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles PictureBox1.MouseUp Dim G As Graphics = PictureBox1.CreateGraphics mdq = e.Location Dim NEWBITMAP As New Bitmap(PictureBox1.Image) Dim cloneBitmap As Bitmap Dim newpic As New Form2 Dim xpoint, ypoint As Integer '左上角座標點 c += 1 If c = 3 Then If mdp.X > mdq.X And mdp.Y > mdq.Y Then xpoint = mdq.X ypoint = mdp.Y ElseIf mdp.X > mdq.X And mdq.Y > mdp.Y Then xpoint = mdq.X ypoint = mdq.Y ElseIf mdp.X < mdq.X And mdp.Y < mdq.Y Then xpoint = mdp.X ypoint = mdq.Y ElseIf mdp.X < mdq.X And mdp.Y > mdq.Y Then xpoint = mdp.X ypoint = mdp.Y End If Dim format As PixelFormat = NEWBITMAP.PixelFormat Dim W, H As Integer W = Math.Abs(mdq.X - mdp.X) H = Math.Abs(mdq.Y - mdp.Y) Dim acpart As New Rectangle(xpoint, ypoint, W, H) If Not W = 0 Or H = 0 Then cloneBitmap = NEWBITMAP.Clone(acpart, format) newpic.PictureBox1.Image = cloneBitmap End If With G .DrawLine(Pens.Black, mdp.X, mdp.Y, mdq.X, mdp.Y) .DrawLine(Pens.Black, mdp.X, mdp.Y, mdp.X, mdq.Y) .DrawLine(Pens.Black, mdp.X, mdq.Y, mdq.X, mdq.Y) .DrawLine(Pens.Black, mdq.X, mdp.Y, mdq.X, mdq.Y) End With newpic.Show() acpart = Nothing c = 1 End If NEWBITMAP = Nothing newpic = Nothing G.Dispose() End Sub



    • 已編輯 向恩 2013年3月1日 上午 09:07
    2013年3月1日 上午 08:44
  • 	Private bMouseDown As Boolean = False
    	Private pStart, pEnd, pNow As Drawing.PointD
    #Region "事件"
    	<System.ComponentModel.Description("選擇範圍框的改變完成")> Public Event SelectRectChanged(ByVal sender As Object)
    	Protected Sub OnSelectRectChanged()
    		RaiseEvent SelectRectChanged(Me)
    	End Sub
    #End Region
    	Private Overloads Function SetSelectRect(ByVal rect As Drawing.RectangleD) As Drawing.RectangleD
    		With shpSelectRect
    			.SuspendLayout()
    			.Location = rect.Location.ToPoint
    			.Size = rect.Size.ToSize
    			.ResumeLayout(False)
    			.PerformLayout()
    			If .Size.Width <> 0 OrElse .Size.Height <> 0 Then .Visible = True
    		End With
    		OnSelectRectChanged()
    		Return rect
    	End Function
    	Private Overloads Function SetSelectRect(ByVal Point1 As Drawing.PointD, ByVal Point2 As Drawing.PointD) As Drawing.RectangleD
    		Dim rect As New Drawing.RectangleD(Point1, Point2)
    		SetSelectRect(rect)
    		Return rect
    	End Function
    	Private Sub ZoomImage_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
    		Select Case e.Button
    			Case MouseButtons.Left
    				bMouseDown = True
    				shpSelectRect.Visible = False
    				pStart.SetPoint(e.Location)
    				pEnd = pStart				
    		End Select
    	End Sub
    	Private Sub ZoomImage_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
    		If e.Button = Windows.Forms.MouseButtons.Left Then
    			If bMouseDown Then
    				pEnd.SetPoint(e.Location)
    				SetSelectRect(pStart, pEnd)
    			End If
    		End If
    	End Sub
    	Private Sub ZoomImage_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
    		Select Case e.Button
    			Case MouseButtons.Left
    				If bMouseDown Then
    					bMouseDown = False
    					pEnd.SetPoint(e.Location)
    					Dim rect As Drawing.RectangleD = SetSelectRect(pStart, pEnd)
    					pStart = rect.Location
    					pEnd = rect.Offset
    				End If
    		End Select
    	End Sub


    我的作法如上面所見。我是把它封裝成一個控制項,當選取框做完後,主動向上層發出 SelectRectChanged 事件,這樣選取框只要做一次,就可以應用在很多地方。

    我應用會用到 GIS ,所以上面的 PointD / RectangleD 是仿造 .Net 內建類別 Point / Rectangle 做出倍經度版來用,當事件往上層傳遞後,若為圖片,直接套用,若為 GIS 座標。或是已經放大一定尺寸的圖形,擁有自訂座標後,就可以正確換算出座標位置。

    我不知道你 c=xxx 要幹嘛...

    一般會透過

    xpoint = Math.Min(mdp.x, mdq.x)

    ypoint = Math.Min(mdp.y, mdq.y)

    之類來精簡程式碼,讓你那堆 x, y 的 If / ElseIf 消失。

    W / H 通常包含邊界,以你的程式碼來說,應該要 +1 。

    另外,你在 MouseUp 做繪圖,滑鼠一動,選取框會消掉,而在 .Net 緩衝區開啟,及繪圖座標系統的混和下畫的選取框可能會閃動,或受繪圖座標系統干擾,無法明確判斷你的位置計算與畫出來的有沒有一致。用控制項的好處是不受繪圖座標系統干擾。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年3月1日 下午 06:11
  • 混合下並沒有心冷大大您描述的閃動問題 選取框在滑鼠在圖片滑過之下的確會取消掉 這點是小弟故意這樣設計的

    因為form2跑出來後會覆蓋到form1上 所以小弟就依此特性去進行比對 

    目前最後的問題  小弟已經解決了 

    代碼改成這樣框選的區塊已經正確了

      xpoint = Math.Min(mdp.X, mdq.X)
      ypoint = Math.Min(mdp.Y, mdq.Y)
    
    
    Dim acpart As New Rectangle(xpoint, ypoint, W, H)


    http://msdn.microsoft.com/zh-tw/library/9wcdy991.aspx

    只不過為什麼msdn明明說明是寫說 xpoint,ypoint這邊要指定左上角

    那照它的說明上應該是

    xpoint= Math.Min(mdp.x,mdq.y)

    ypoint=Math.Max(mdp.x,mdq.y)

    這樣才對吧 不太理解 這邊的說明為什麼會跟代碼有所出入



    2013年3月2日 上午 10:14
  • X軸值跟Y軸值比?這好比西瓜跟蘋果比,怎麼想都是你的比較怪。


    以下為簽名檔,如果你愛拉椅子坐那就是你的問題。
    先查MSDN文件庫
    再用GOOGLE搜尋
    才到論壇來發問

    這是論壇不是技術支援中心
    沒有人得無償解答你的問題

    在標題或文章註明很急
    不會增加網友回覆速度

    2013年3月2日 下午 12:21
  • Windows 的座標系統是左上角為 0,0 ,x 軸向右為正,y 軸向下為正。

    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    • 已標示為解答 向恩 2013年3月3日 上午 02:30
    2013年3月2日 下午 03:24
  • 標題已經和內文討論完全偏離了....

    學習不是查個 Google 套個書上的範例就算了,而是去熟悉了解每個程式碼背後的意義,否則就算學個幾百年,它也不會是你的。

      • 小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
      • 雲端學堂Facebook: http://www.facebook.com/studyazure

    2013年3月2日 下午 03:35
    版主
  • 因為討論到後面才知道樓主的需求,所以造成根本不需要 LockBits ... 只需要 DrawImage ...


    論壇是網友平等互助 保證解答請至 微軟技術支援服務


    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。

    2013年3月3日 上午 10:06