home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH4 / SRC / COMPLEM.FRM (.txt) < prev    next >
Encoding:
Visual Basic Form  |  1997-01-03  |  16.7 KB  |  518 lines

  1. VERSION 4.00
  2. Begin VB.Form ComplementForm 
  3.    Caption         =   "Complement"
  4.    ClientHeight    =   4725
  5.    ClientLeft      =   1320
  6.    ClientTop       =   1350
  7.    ClientWidth     =   4695
  8.    Height          =   5415
  9.    Left            =   1260
  10.    LinkTopic       =   "Form1"
  11.    ScaleHeight     =   315
  12.    ScaleMode       =   3  'Pixel
  13.    ScaleWidth      =   313
  14.    Top             =   720
  15.    Width           =   4815
  16.    Begin VB.CommandButton CmdComplement 
  17.       Caption         =   "Complement"
  18.       Enabled         =   0   'False
  19.       Height          =   495
  20.       Left            =   1920
  21.       TabIndex        =   4
  22.       Top             =   4200
  23.       Width           =   1095
  24.    End
  25.    Begin VB.PictureBox FromSwin 
  26.       Height          =   3855
  27.       Left            =   0
  28.       ScaleHeight     =   253
  29.       ScaleMode       =   3  'Pixel
  30.       ScaleWidth      =   293
  31.       TabIndex        =   2
  32.       Top             =   0
  33.       Width           =   4455
  34.       Begin VB.PictureBox FromPict 
  35.          AutoRedraw      =   -1  'True
  36.          AutoSize        =   -1  'True
  37.          Height          =   1905
  38.          Left            =   0
  39.          ScaleHeight     =   123
  40.          ScaleMode       =   3  'Pixel
  41.          ScaleWidth      =   88
  42.          TabIndex        =   3
  43.          Top             =   0
  44.          Width           =   1380
  45.       End
  46.    End
  47.    Begin VB.HScrollBar FromHBar 
  48.       Enabled         =   0   'False
  49.       Height          =   255
  50.       Left            =   0
  51.       TabIndex        =   1
  52.       Top             =   3840
  53.       Width           =   4485
  54.    End
  55.    Begin VB.VScrollBar FromVBar 
  56.       Enabled         =   0   'False
  57.       Height          =   3855
  58.       Left            =   4440
  59.       TabIndex        =   0
  60.       Top             =   0
  61.       Width           =   255
  62.    End
  63.    Begin MSComDlg.CommonDialog FileDialog 
  64.       Left            =   4200
  65.       Top             =   3600
  66.       _Version        =   65536
  67.       _ExtentX        =   847
  68.       _ExtentY        =   847
  69.       _StockProps     =   0
  70.       CancelError     =   -1  'True
  71.    End
  72.    Begin VB.Menu mnuFile 
  73.       Caption         =   "&File"
  74.       Begin VB.Menu mnuFileLoad 
  75.          Caption         =   "&Load..."
  76.          Shortcut        =   ^L
  77.       End
  78.       Begin VB.Menu mnuFileSep2 
  79.          Caption         =   "-"
  80.       End
  81.       Begin VB.Menu mnuFileExit 
  82.          Caption         =   "E&xit"
  83.       End
  84.    End
  85. Attribute VB_Name = "ComplementForm"
  86. Attribute VB_Creatable = False
  87. Attribute VB_Exposed = False
  88. Option Explicit
  89. Dim SysPalSize As Integer
  90. Dim NumStaticColors As Integer
  91. Dim StaticColor1 As Integer
  92. Dim StaticColor2 As Integer
  93. Dim bytes() As Byte
  94. Dim wid As Long
  95. Dim hgt As Long
  96. Dim LogPal As Integer
  97. Dim palentry(0 To 255) As PALETTEENTRY
  98. ' ************************************************
  99. ' Complement the image.
  100. ' ************************************************
  101. Private Sub CmdComplement_Click()
  102. Dim i As Integer
  103.     ' Complement the logical palette color values.
  104.     For i = StaticColor1 + 1 To StaticColor2 - 1
  105.         With palentry(i)
  106.             .peRed = 255 - .peRed
  107.             .peGreen = 255 - .peGreen
  108.             .peBlue = 255 - .peBlue
  109.             .peFlags = PC_NOCOLLAPSE
  110.         End With
  111.     Next i
  112.     i = SetPaletteEntries(LogPal, StaticColor1 + 1, StaticColor2 - StaticColor1 - 1, palentry(StaticColor1 + 1))
  113.     i = RealizePalette(FromPict.hdc)
  114. End Sub
  115. ' ***********************************************
  116. ' Load the control's palette so the non-static
  117. ' colors are grays. Map the logical palette to
  118. ' match the system palette. Convert the image to
  119. ' use the non-static grays.
  120. ' Set the following module global variables.
  121. '   LogPal      Image logical palette handle.
  122. '   palentry()  Image logical palette entries.
  123. '   wid         Width of image.
  124. '   hgt         Height of image.
  125. '   bytes(1 To wid, 1 To hgt)
  126. '               Image pixel values.
  127. ' ***********************************************
  128. Sub MatchGrayPalette(pic As Control)
  129. Dim sys(0 To 255) As PALETTEENTRY
  130. Dim i As Integer
  131. Dim bm As BITMAP
  132. Dim hbm As Integer
  133. Dim status As Long
  134. Dim X As Integer
  135. Dim Y As Integer
  136. Dim gray As Single
  137. Dim dgray As Single
  138. Dim c As Integer
  139. Dim clr As Integer
  140.     ' Make sure pic has the foreground palette.
  141.     pic.ZOrder
  142.     i = RealizePalette(pic.hdc)
  143.     DoEvents
  144.     ' Get the system palette entries.
  145.     i = GetSystemPaletteEntries(pic.hdc, 0, SysPalSize, sys(0))
  146.         
  147.     ' Get the image pixels.
  148.     hbm = pic.Image
  149.     status = GetObject(hbm, BITMAP_SIZE, bm)
  150.     wid = bm.bmWidthBytes
  151.     hgt = bm.bmHeight
  152.     ReDim bytes(1 To wid, 1 To hgt)
  153.     status = GetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  154.     ' Make the logical palette as big as possible.
  155.     LogPal = pic.Picture.hPal
  156.     If ResizePalette(LogPal, SysPalSize) = 0 Then
  157.         Beep
  158.         MsgBox "Error resizing logical palette.", _
  159.             vbExclamation
  160.         Exit Sub
  161.     End If
  162.     ' Blank the non-static colors.
  163.     For i = 0 To StaticColor1
  164.         palentry(i) = sys(i)
  165.     Next i
  166.     For i = StaticColor1 + 1 To StaticColor2 - 1
  167.         With palentry(i)
  168.             .peRed = 0
  169.             .peGreen = 0
  170.             .peBlue = 0
  171.             .peFlags = PC_NOCOLLAPSE
  172.         End With
  173.     Next i
  174.     For i = StaticColor2 To 255
  175.         palentry(i) = sys(i)
  176.     Next i
  177.     i = SetPaletteEntries(LogPal, 0, SysPalSize, palentry(0))
  178.     ' Insert the non-static grays.
  179.     gray = 0
  180.     dgray = 255 / (StaticColor2 - StaticColor1 - 2)
  181.     For i = StaticColor1 + 1 To StaticColor2 - 1
  182.         c = gray
  183.         gray = gray + dgray
  184.         With palentry(i)
  185.             .peRed = c
  186.             .peGreen = c
  187.             .peBlue = c
  188.         End With
  189.     Next i
  190.     i = SetPaletteEntries(LogPal, StaticColor1 + 1, StaticColor2 - StaticColor1 - 1, palentry(StaticColor1 + 1))
  191.     ' Recreate the image using the new colors.
  192.     For Y = 1 To hgt
  193.         For X = 1 To wid
  194.             clr = bytes(X, Y)
  195.             With sys(clr)
  196.                 c = (CInt(.peRed) + .peGreen + .peBlue) / 3
  197.             End With
  198.             bytes(X, Y) = NearestNonstaticGray(c)
  199.         Next X
  200.     Next Y
  201.     status = SetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  202.     ' Realize the gray palette.
  203.     i = RealizePalette(pic.hdc)
  204.     pic.Refresh
  205. End Sub
  206. ' ************************************************
  207. ' Return the index of the nonstatic color closest
  208. ' to the given color value.
  209. ' ************************************************
  210. Function NearestNonstaticColor(ByVal r As Integer, ByVal g As Integer, ByVal b As Integer) As Integer
  211. Dim best_i As Integer
  212. Dim best_dist As Long
  213. Dim dist As Long
  214. Dim dr As Long
  215. Dim dg As Long
  216. Dim db As Long
  217. Dim i As Integer
  218.     best_dist = 1000000
  219.     For i = StaticColor1 + 1 To StaticColor2 - 1
  220.         With palentry(i)
  221.             dr = r - .peRed
  222.             dg = g - .peGreen
  223.             db = b - .peBlue
  224.             dist = dr * dr + dg * dg + db * db
  225.         End With
  226.         If best_dist > dist Then
  227.             best_i = i
  228.             best_dist = dist
  229.         End If
  230.     Next i
  231.     NearestNonstaticColor = best_i
  232. End Function
  233. ' ************************************************
  234. ' Return the index of the nonstatic gray closest
  235. ' to the given value (assuming the non-static
  236. ' colors are a gray scale created by
  237. ' MatchGrayPalette).
  238. ' ************************************************
  239. Function NearestNonstaticGray(c As Integer) As Integer
  240. Dim dgray As Single
  241.     If c < 0 Then
  242.         c = 0
  243.     ElseIf c > 255 Then
  244.         c = 255
  245.     End If
  246.     dgray = 255 / (StaticColor2 - StaticColor1 - 2)
  247.     NearestNonstaticGray = c / dgray + StaticColor1 + 1
  248. End Function
  249. ' ***********************************************
  250. ' Load the control's palette so it matches the
  251. ' the system palette. Remap any of the image's
  252. ' pixels that use static colors to non-static
  253. ' colors.
  254. ' Set the following module global variables.
  255. '   LogPal      Image logical palette handle.
  256. '   palentry()  Image logical palette entries.
  257. '   wid         Width of image.
  258. '   hgt         Height of image.
  259. '   bytes(1 To wid, 1 To hgt)
  260. '               Image pixel values.
  261. ' ***********************************************
  262. Sub MatchColorPalette(pic As Control)
  263. Dim sys(0 To 255) As PALETTEENTRY
  264. Dim i As Integer
  265. Dim bm As BITMAP
  266. Dim hbm As Integer
  267. Dim status As Long
  268. Dim X As Integer
  269. Dim Y As Integer
  270. Dim clr As Integer
  271.     ' Make sure pic has the foreground palette.
  272.     pic.ZOrder
  273.     i = RealizePalette(pic.hdc)
  274.     DoEvents
  275.     ' Get the system palette entries.
  276.     i = GetSystemPaletteEntries(pic.hdc, 0, SysPalSize, sys(0))
  277.             
  278.     ' Make the logical palette as big as possible.
  279.     LogPal = pic.Picture.hPal
  280.     If ResizePalette(LogPal, SysPalSize) = 0 Then
  281.         Beep
  282.         MsgBox "Error resizing logical palette.", _
  283.             vbExclamation
  284.         Exit Sub
  285.     End If
  286.     ' Blank the non-static colors.
  287.     For i = 0 To StaticColor1
  288.         palentry(i) = sys(i)
  289.     Next i
  290.     For i = StaticColor1 + 1 To StaticColor2 - 1
  291.         With palentry(i)
  292.             .peRed = 0
  293.             .peGreen = 0
  294.             .peBlue = 0
  295.             .peFlags = PC_NOCOLLAPSE
  296.         End With
  297.     Next i
  298.     For i = StaticColor2 To 255
  299.         palentry(i) = sys(i)
  300.     Next i
  301.     i = SetPaletteEntries(LogPal, 0, SysPalSize, palentry(0))
  302.     ' Insert the non-static colors.
  303.     For i = StaticColor1 + 1 To StaticColor2 - 1
  304.         palentry(i) = sys(i)
  305.         palentry(i).peFlags = PC_NOCOLLAPSE
  306.     Next i
  307.     i = SetPaletteEntries(LogPal, StaticColor1 + 1, StaticColor2 - StaticColor1 - 1, palentry(StaticColor1 + 1))
  308.     ' Realize the new palette.
  309.     i = RealizePalette(pic.hdc)
  310.     ' Get the image pixels.
  311.     hbm = pic.Image
  312.     status = GetObject(hbm, BITMAP_SIZE, bm)
  313.     wid = bm.bmWidthBytes
  314.     hgt = bm.bmHeight
  315.     ReDim bytes(1 To wid, 1 To hgt)
  316.     status = GetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  317.     ' Remap any pixels using static colors.
  318.     For Y = 1 To hgt
  319.         For X = 1 To wid
  320.             clr = bytes(X, Y)
  321.             If clr <= StaticColor1 Or clr >= StaticColor2 Then
  322.                 With sys(clr)
  323.                     bytes(X, Y) = _
  324.                         NearestNonstaticColor( _
  325.                         .peRed, .peGreen, .peBlue)
  326.                 End With
  327.             End If
  328.         Next X
  329.     Next Y
  330.     ' Update the image's pixel values.
  331.     status = SetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  332.     pic.Refresh
  333. End Sub
  334. ' ***********************************************
  335. ' Load the indicated file and prepare to work
  336. ' with its palette.
  337. ' ***********************************************
  338. Sub LoadFromPict(fname As String)
  339. Dim status As Long
  340.     On Error GoTo LoadFileError
  341.     FromPict.Picture = LoadPicture(fname)
  342.     On Error GoTo 0
  343.         
  344.     FromHBar.Enabled = False
  345.     FromVBar.Enabled = False
  346.     CmdComplement.Enabled = False
  347.     DoEvents
  348.     MatchColorPalette FromPict
  349.     FromPict.Move 0, 0
  350.     ResetScrollBars
  351.     CmdComplement.Enabled = True
  352.     Caption = "Complement [" & fname & "]"
  353.     Exit Sub
  354. LoadFileError:
  355.     Beep
  356.     MsgBox "Error loading file " & fname & "." & _
  357.         vbCrLf & Error$
  358.     Exit Sub
  359. End Sub
  360. ' ***********************************************
  361. ' Set the Max and LargeChange properties for the
  362. ' image scroll bars.
  363. ' ***********************************************
  364. Sub ResetScrollBars()
  365.     ' FromHBar.
  366.     FromHBar.Value = 0
  367.     If FromSwin.ScaleWidth >= FromPict.Width Then
  368.         FromHBar.Enabled = False
  369.     Else
  370.         FromHBar.Max = FromPict.Width - FromSwin.ScaleWidth
  371.         FromHBar.LargeChange = FromSwin.ScaleWidth
  372.         FromHBar.Enabled = True
  373.     End If
  374.     ' FromVBar.
  375.     FromVBar.Value = 0
  376.     If FromSwin.ScaleHeight >= FromPict.Height Then
  377.         FromVBar.Enabled = False
  378.     Else
  379.         FromVBar.Max = FromPict.Height - FromSwin.ScaleHeight
  380.         FromVBar.LargeChange = FromSwin.ScaleHeight
  381.         FromVBar.Enabled = True
  382.     End If
  383. End Sub
  384. ' ***********************************************
  385. ' Give the form and all the picture boxes an
  386. ' hourglass cursor.
  387. ' ***********************************************
  388. Sub WaitStart()
  389.     MousePointer = vbHourglass
  390.     FromPict.MousePointer = vbHourglass
  391.     DoEvents
  392. End Sub
  393. ' ***********************************************
  394. ' Restore the mouse pointers for the form and all
  395. ' the picture boxes.
  396. ' ***********************************************
  397. Sub WaitEnd()
  398.     MousePointer = vbDefault
  399.     FromPict.MousePointer = vbDefault
  400. End Sub
  401. Private Sub Form_Load()
  402.     ' Make sure the screen supports palettes.
  403.     If Not GetDeviceCaps(hdc, RASTERCAPS) And RC_PALETTE Then
  404.         Beep
  405.         MsgBox "This monitor does not support palettes.", _
  406.             vbCritical
  407.         End
  408.     End If
  409.     ' Get system palette size and # static colors.
  410.     SysPalSize = GetDeviceCaps(hdc, SIZEPALETTE)
  411.     NumStaticColors = GetDeviceCaps(hdc, NUMRESERVED)
  412.     StaticColor1 = NumStaticColors \ 2 - 1
  413.     StaticColor2 = SysPalSize - NumStaticColors \ 2
  414.     ' Remove the borders from FromPict.
  415.     FromPict.BorderStyle = vbTransparent
  416.     ' Make sure FromPict has control.
  417.     FromPict.ZOrder
  418. End Sub
  419. ' ***********************************************
  420. ' Make the picture as large as possible.
  421. ' ***********************************************
  422. Private Sub Form_Resize()
  423. Const GAP = 4
  424. Dim hgt As Single
  425. Dim wid As Single
  426.     If WindowState = vbMinimized Then Exit Sub
  427.         
  428.     hgt = ScaleHeight - FromHBar.Height - 1 - _
  429.         CmdComplement.Height - 2 * GAP
  430.     wid = ScaleWidth - FromVBar.Width - 1
  431.     ' Place FromSwin and its scroll bars.
  432.     FromSwin.Move 0, 0, wid, hgt
  433.     FromVBar.Move _
  434.         FromSwin.Left + FromSwin.Width + 1, _
  435.         0, FromVBar.Width, hgt
  436.     FromHBar.Move _
  437.         FromSwin.Left, FromSwin.Height + 1, _
  438.         wid
  439.     CmdComplement.Move _
  440.         (ScaleWidth - CmdComplement.Width) / 2, _
  441.         FromHBar.Top + FromHBar.Height + GAP
  442.     ResetScrollBars
  443. End Sub
  444. Private Sub Form_Unload(Cancel As Integer)
  445.     End
  446. End Sub
  447. ' ***********************************************
  448. ' Move FromPict within FromSwin.
  449. ' ***********************************************
  450. Private Sub FromHBar_Change()
  451.     FromPict.Left = -FromHBar.Value
  452. End Sub
  453. ' ***********************************************
  454. ' Move FromPict within FromSwin.
  455. ' ***********************************************
  456. Private Sub FromHBar_Scroll()
  457.     FromPict.Left = -FromHBar.Value
  458. End Sub
  459. ' ************************************************
  460. ' Present a message indicating the pixel's palette
  461. ' index and color value.
  462. ' ************************************************
  463. Private Sub FromPict_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  464.     If X > wid Or Y > hgt Then Exit Sub
  465.     With palentry(bytes(X, Y))
  466.         MsgBox "Palette index:" & Str$(bytes(X, Y)) & _
  467.             vbCrLf & "Red:  " & Str$(.peRed) & _
  468.             vbCrLf & "Green:" & Str$(.peGreen) & _
  469.             vbCrLf & "Blue: " & Str$(.peBlue)
  470.     End With
  471. End Sub
  472. ' ***********************************************
  473. ' Load a new image file.
  474. ' ***********************************************
  475. Private Sub mnuFileLoad_Click()
  476. Dim fname As String
  477.     ' Allow the user to pick a file.
  478.     On Error Resume Next
  479.     FileDialog.filename = "*.BMP;*.ICO;*.RLE;*.WMF;*.DIB"
  480.     FileDialog.Flags = cdlOFNFileMustExist + cdlOFNHideReadOnly
  481.     FileDialog.ShowOpen
  482.     If Err.Number = cdlCancel Then
  483.         Exit Sub
  484.     ElseIf Err.Number <> 0 Then
  485.         Beep
  486.         MsgBox "Error selecting file.", , vbExclamation
  487.         Exit Sub
  488.     End If
  489.     On Error GoTo 0
  490.     fname = Trim$(FileDialog.filename)
  491.     FileDialog.InitDir = Left$(fname, Len(fname) _
  492.         - Len(FileDialog.FileTitle) - 1)
  493.     ' Load the picture.
  494.     WaitStart
  495.     DoEvents
  496.     LoadFromPict fname
  497.     WaitEnd
  498. End Sub
  499. ' ***********************************************
  500. ' End the application. (See also the QueryUnload
  501. ' event.)
  502. ' ***********************************************
  503. Private Sub mnuFileExit_Click()
  504.     Unload Me
  505. End Sub
  506. ' ***********************************************
  507. ' Move FromPict within FromSwin.
  508. ' ***********************************************
  509. Private Sub FromVBar_Change()
  510.     FromPict.Top = -FromVBar.Value
  511. End Sub
  512. ' ***********************************************
  513. ' Move FromPict within FromSwin.
  514. ' ***********************************************
  515. Private Sub FromVBar_Scroll()
  516.     FromPict.Top = -FromVBar.Value
  517. End Sub
  518.