none
繪圖問題 RRS feed

  • 問題

  • 我想從d:\1.bmp圖檔先匯到 PictureBox1裡之後進行繪圖動作,先畫出紅色的框,因為框線並不會一次就劃到正確的位置所以會有重覆性動作,等到畫出正確的紅色框之後換色筆((綠色))再繪製另一個框,所以在picturebox1中的這一張圖就會有二個框分別為紅色與綠色,之後再存回d:\1.bmp中,請問我該如何寫此概念的程式呢?因為第一次寫繪圖的程式,試了幾次碰到很多問題,我在PictureBox1_MouseUp下寫了一段程式

                'Dim myBitmap As New Bitmap("D:\1.bmp")
                'Dim p As New Pen(pencolor, HScrollBar1.Value)
                'up = New Point(e.X, e.Y)
                'r = New Rectangle(Math.Min(up.X, down.X), _
                '  Math.Min(up.Y, down.Y), Math.Abs(up.X - down.X), _
                '  Math.Abs(up.Y - down.Y))
                'Dim g As Graphics = Graphics.FromImage(myBitmap)
                'g.DrawRectangle(p, r)
                'PictureBox1.Image = myBitmap
                'PictureBox1.Refresh()
                'PictureBox1.Dispose()
                'g.Dispose() : g.Dispose()
    先以紅色筆畫出正確的框線沒有問題,但就沒辦法在畫出紅色框後換綠色筆再進行繪製了!!而且如果再存回D:\1.bmp中的話會出現「在 GDI+ 中發生泛用錯誤」是因為d槽中已經有了同一個檔名了嗎?我有試著想要先刪掉d:\1.bmp檔,但會出現「檔名有另一個處理程序正在使用中,沒辦法存取此檔案」的錯誤訊息,請問我該如何進行修改呢?

    2007年4月20日 上午 01:48

解答

所有回覆

  • 先載入到 MemoryStream ,再從 MemoryStream 讀入 PictureBox ,就不會鎖定檔案。先前已有討論:

    http://forums.microsoft.com/MSDN-CHT/Search/Search.aspx?words=Image+MemoryStream&localechoice=31748&SiteID=14&searchscope=allforums

     

    你程式碼都加上註解標記,不知道你哪裡有問題。也不知道「但就沒辦法在畫出紅色框後換綠色筆再進行繪製了」是什麼意思。

    2007年4月20日 上午 02:58
    版主
  • 璉大:我之前有試過您的方式,以下是我依您的方式寫的程式

    Dim fs As IO.FileStream = New IO.FileStream("D:\1.bmp", IO.FileMode.Open)
            Dim nLen As Integer = fs.Length - 1
            Dim arrBytes(nLen) As Byte
            Dim ms As MemoryStream = New MemoryStream
            fs.Read(arrBytes, 0, nLen)
            fs.Close()
            ms.Write(arrBytes, 0, nLen)
            PictureBox1.Image = Image.FromStream(ms)<<------------------------會在這一行出現「其他資訊: 在 GDI+ 中發生泛用錯誤。」
            ms.Close()

    不好意思,沒注意到我之前貼的程式碼有加上註記,而我上一篇貼的意思是說,依我上一篇中的程式RUN執行的結果會是只能以紅色色筆來繪製框線((一開始就預設pencolor = Color.Red))我在另一個換色彩的Button上寫下

        pencolor = Color.GreenYellow

    但之後要在 PictureBox1繪製時卻只會顯示出綠色框線,之前的紅色框色卻不見了!!我想是因為我在PictureBox1_MouseUp下有一行Dim fs As IO.FileStream = New IO.FileStream("D:\1.bmp", IO.FileMode.Open)所以它會抓最原始的圖檔,之前畫紅色框的圖片因為沒有存回去,所以它還是原始的圖片,但我想要的是「之前完成的紅框線+綠框線存回D:\1.bmp」

    P.S我發現會不會是我的.Net Framework是1.1版本的問題呢?所以有很多屬性是沒有辦法使用的,.Net Framework是1.1版本又該如何改寫呢?

     

    2007年4月20日 上午 03:59
  • 你先用小畫家開那張圖,存為全彩色試試看。

    在 .Net 1.1 有很多圖檔在 Stream 內無法正確辨識,這個問題在 .Net 2.0 已經改善。

     

    若仍要使用 .Net 1.1 ,可以先用 Image.FromFile(path) 後,用 DrawImage 畫到 PictureBox ,就可以把這個 Image 釋放,檔案就不會鎖定。


    另外,要看你怎樣處理你的事件,VBNET 不像 VB6 會幫你儲存,所以你要同時畫,或是其他作法,前面有討論,可搜尋繪圖,例如說這篇:

    http://forums.microsoft.com/msdn-cht/ShowPost.aspx?PostID=1297399&SiteID=14

    2007年4月20日 上午 09:01
    版主
  • 我看了很多有關DrawImage的文章,但還是看不太懂,請問我用 DrawImage 畫到 PictureBox 之後,又該如何在它指向myBitmap,使它可以在picturebox1上使用DrawRectangle呢?

                Dim myBitmap As New Bitmap("????")

              Dim p As New Pen(Color.BlueViolet, 3)

               r = New Rectangle(Math.Min(up.X, down.X), _
                  Math.Min(up.Y, down.Y), Math.Abs(up.X - down.X), _
                  Math.Abs(up.Y - down.Y))
                Dim cg As Graphics = Graphics.FromImage(myBitmap)
                cg.DrawRectangle(p, r)
                PictureBox1.Image = myBitmap

    p.s另外,請問又該如何儲存呢?

    2007年4月23日 上午 08:33
  • 你直接畫在 PictureBox 上時,Graphics 就應該由 PictureBox.Image 來產生,並非是 myBitmap 產生。

     

    若你要先畫在記憶體中,才是先建立一個 bitmap ,然後把 Image 畫到這個 bitmap 上,不畫在 PictureBox 上。

    你的 ? ? ? 應該填的是 bitmap 的大小,要跟原尺寸一樣的話,就用原圖的 Width, Height 來用。

    http://msdn2.microsoft.com/zh-tw/library/7we6s1x3(VS.80).aspx

    2007年4月23日 上午 09:06
    版主
  • 我現在遇到另一個難題,我沒辦法以Graphics做儲存,以下是我寫的程式:

    Dim fm As Graphics
                fm = PictureBox1.CreateGraphics
                Dim p As New Pen(Color.Red, 3)
                r = New Rectangle(Math.Min(up.X, down.X), _
                  Math.Min(up.Y, down.Y), Math.Abs(up.X - down.X), _
                  Math.Abs(up.Y - down.Y))
                 PictureBox1.Refresh()
                Dim img As Image
                img = Image.FromFile("D:\1.bmp")
               ((Save程式????))        
                fm.Dispose()
                img.Dispose()
    fm不能直接做存儲的動作,請問我該加什麼程式呢?

    2007年4月24日 上午 03:49
  • 你應該多翻線上手冊...

    存檔功能是在 Image 類別上。你從 PictureBox 建立 Graphic ,就應該呼叫 PictureBox.Image.Save

    2007年4月24日 上午 03:59
    版主
  • 我試過以PictureBox1.Image.Save("D:\A.bmp"),但如此只能Save原始的來源檔-->>img = Image.FromFile(" D:\1.bmp")

    沒辦法SAVE之後有畫框線的圖片

    2007年4月25日 上午 12:54
  • ?

    你不是用 DrawImage 畫到 PictureBox 上嗎?

     

    我一直沒看到你有呼叫 DrawImage 。

     

    我自己習慣是開個 Image 來畫,直接畫在 PictureBox 上會受顯示卡速度影響,所以畫在記憶體中的 Image 後,再指給 PictureBox 。

    2007年4月25日 上午 02:47
    版主
  • 我又將我的程式做了修改

    Imports System.IO
    Imports System.Drawing

    Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp

               Dim d As Image
                    d = Image.FromFile("D:\1.bmp")
                    Dim fm As Graphics
                    fm = PictureBox1.CreateGraphics
                    fm.Clear(Color.Transparent) '清除圖片
                    PictureBox1.Image = d
                    fm = System.Drawing.Graphics.FromImage(d)
                    fm.DrawImage(PictureBox1.Image, 0, 0, d.Size.Width, d.Size.Height) '將picturebox內的圖片在載入
                    up = New Point(e.X, e.Y)
                    r = New Rectangle(Math.Min(up.X, down.X), Math.Min(up.Y, down.Y), Math.Abs(up.X - down.X), Math.Abs(up.Y - down.Y))
                    fm.DrawRectangle(Pens.Black, r) '畫矩形
                    PictureBox1.Refresh()
                    PictureBox1.Image.Save("D:\A.bmp")
                    d.Dispose()<<------------------------------------------會發生使用無效的參數。
                    fm.Dispose()

    END Sub
     但,我一定要將它的資源給釋放掉!!才可以之後將D:\1.bmp給刪除!!請問我少了什麼程式呢?

    2007年4月25日 上午 03:30
  • 用 DrawImage 就是不要直接把 d 給 PictureBox 參照用,參照時就會鎖檔,以前這篇就寫過了:

    回覆:請問刪除檔案時發生檔案使用中....

     

    所以你這兩句都會造成參照鎖檔:

    PictureBox1.Image = d
      fm = System.Drawing.Graphics.FromImage(d)

     

    請直接刪掉,當 DrawImage 呼叫完,就可以直接呼叫 d.Dispose()

    2007年4月25日 上午 07:41
    版主
  • 但我把您說的二句給拿掉後,卻沒有辦法劃出框線

      Dim d As Image
                    d = Image.FromFile("D:\1.bmp")
                    Dim fm As Graphics
                    fm = PictureBox1.CreateGraphics
                    fm.Clear(Color.Transparent) '清除圖片
                    'PictureBox1.Image = d
                    'fm = System.Drawing.Graphics.FromImage(d)
                    fm.DrawImage(PictureBox1.Image, 0, 0, d.Size.Width, d.Size.Height) '將picturebox內的圖片在載入
                    up = New Point(e.X, e.Y)
                    r = New Rectangle(Math.Min(up.X, down.X), Math.Min(up.Y, down.Y), Math.Abs(up.X - down.X), Math.Abs(up.Y - down.Y))
                    fm.DrawRectangle(Pens.Black, r) '畫矩形
                    PictureBox1.Refresh()
                    PictureBox1.Image.Save("D:\A.bmp")
                    d.Dispose()
                    fm.Dispose()

     

    另外我再次修改了一下是可以畫出黑色框線,如以下的程式,但它儲存到D:\A.bmp的檔案卻還是來源的圖片,並沒有save畫好的黑色框線,另外如果切換其他的視窗的話,黑色框色會不見:

      Dim d As Image
                    d = Image.FromFile("\\Fls-hlo01\M100\M180\FQM標準量測\IQC標準量測暫存區\picture\1.bmp")
                    Dim fm As Graphics
                    fm = PictureBox1.CreateGraphics
                    'fm.Clear(Color.Transparent) '清除圖片
                    PictureBox1.Refresh()
                    'PictureBox1.Image = d
                    'fm = System.Drawing.Graphics.FromImage(d)
                    fm.DrawImage(PictureBox1.Image, 0, 0, d.Size.Width, d.Size.Height) '將picturebox內的圖片在載入
                    up = New Point(e.X, e.Y)
                    r = New Rectangle(Math.Min(up.X, down.X), Math.Min(up.Y, down.Y), Math.Abs(up.X - down.X), Math.Abs(up.Y - down.Y))

                    fm.DrawRectangle(Pens.Black, r) '畫矩形
                    'PictureBox1.Refresh()
                    PictureBox1.Image.Save("D:\A.bmp")
                    d.Dispose()
                    fm.Dispose()

    2007年4月25日 上午 10:00
  • 請多拜讀線上手冊:

    fm.DrawImage(PictureBox1.Image, 0, 0, d.Size.Width, d.Size.Height) '將picturebox內的圖片在載入

     

    這句中,fm 是從 PictureBox 建立的,這時候 PictureBox 是空的,把空的畫在空的上,你能有底圖圖片我還覺得更奇怪...

     

    至少這時來源應該是 d 吧?這樣才能把 d 畫到 PictureBox 上啊~

    fm.DrawImage(d.Image, 0, 0, d.Size.Width, d.Size.Height)

    2007年4月25日 上午 10:23
    版主
  • 我試過用

    fm.DrawImage(d.Image, 0, 0, d.Size.Width, d.Size.Height)

    但~~還是沒辦法save畫出的黑框><"到底是我少了什麼程式呢?

     Dim d As Image
                    d = Image.FromFile("D:\1.bmp")
                    Dim fm As Graphics
                    fm = PictureBox1.CreateGraphics
                     PictureBox1.Refresh()
                     fm.DrawImage(d, 0, 0, d.Size.Width, d.Size.Height) '將picturebox內的圖片在載入
                    up = New Point(e.X, e.Y)
                    r = New Rectangle(Math.Min(up.X, down.X), Math.Min(up.Y, down.Y), Math.Abs(up.X - down.X), Math.Abs(up.Y - down.Y))

                    fm.DrawRectangle(Pens.Black, r) '畫矩形
                    'PictureBox1.Refresh()
                    PictureBox1.Image.Save("D:\A.bmp")
                    d.Dispose()
                    fm.Dispose()

    D:\A.bmp<<------還是沒有黑色框線,且只要切換其他視窗後,form上的點色框線就會不見

    2007年4月25日 上午 10:31
  • 測了一下,這樣可以跑:


    程式碼
      

    Dim d As Image = Image.FromFile("F:\Temp\wordpad.png")

    Dim bmp As New Bitmap(d.Width, d.Height)

    Dim g As Graphics = Drawing.Graphics.FromImage(bmp)

    g.DrawImage(d, 0, 0, d.Size.Width, d.Size.Height)

    d.Dispose()

    g.DrawRectangle(Pens.Red, 10, 10, 200, 100)

    g.Dispose()

    PictureBox1.Image = bmp

    PictureBox1.Image.Save("F:\Temp\wordpad.png", Imaging.ImageFormat.Png) 

     

    2007年4月25日 下午 01:38
    版主
  • 真的很感激您~~~~~~很不好意思一直麻煩您^^"我會再努力的!!!!謝謝謝謝~~~~~~~~
    2007年4月26日 上午 01:12