home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 3_2004-2005.ISO / Data / Zips / image_conv1744395122004.psc / imageconverter / Class / GIF.cls < prev   
Text File  |  2004-05-12  |  14KB  |  455 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "GIF"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Attribute VB_Ext_KEY = "SavedWithClassBuilder" ,"Yes"
  15. Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
  16. ' Class for Saving VB StdPicture object (BMP) in GIF format
  17. '
  18. ' Written by Arkadiy Olovyannikov
  19. '
  20. ' This software is FREEWARE. You may use it as you see fit for
  21. ' your own projects but you may not re-sell the original or the
  22. ' source code.
  23. '
  24. ' No warranty express or implied, is given as to the use of this
  25. ' program. Use at your own risk.
  26.  
  27. ' This sample was written for education purposes. 'GIF' and
  28. ' 'Graphics Interchange Format' are trademarks of Compuserve,
  29. ' Inc., an H&R Block Company.
  30.  
  31. Option Explicit
  32.  
  33. '============BITMAP STAFF========================
  34. Private Type RGBTRIPLE
  35.     rgbRed As Byte
  36.     rgbGreen As Byte
  37.     rgbBlue As Byte
  38. End Type
  39.  
  40. Private Type RGBQUAD
  41.     rgbBlue As Byte
  42.     rgbGreen As Byte
  43.     rgbRed As Byte
  44.     rgbReserved As Byte
  45. End Type
  46.  
  47. Private Type BITMAPINFOHEADER '40 bytes
  48.     biSize As Long
  49.     biWidth As Long
  50.     biHeight As Long
  51.     biPlanes As Integer
  52.     biBitCount As Integer
  53.     biCompression As Long
  54.     biSizeImage As Long
  55.     biXPelsPerMeter As Long
  56.     biYPelsPerMeter As Long
  57.     biClrUsed As Long
  58.     biClrImportant As Long
  59. End Type
  60.  
  61. Private Type BITMAPINFO256
  62.     bmiHeader As BITMAPINFOHEADER
  63.     bmiColors(0 To 255) As RGBQUAD
  64. End Type
  65.  
  66. Private Type BITMAP '14 bytes
  67.     bmType As Long
  68.     bmWidth As Long
  69.     bmHeight As Long
  70.     bmWidthBytes As Long
  71.     bmPlanes As Integer
  72.     bmBitsPixel As Integer
  73.     bmBits As Long
  74. End Type
  75.  
  76. Private Const BI_RGB = 0&
  77.  
  78. Private Declare Function CreateDCAsNull Lib "gdi32" Alias "CreateDCA" (ByVal lpDriverName As String, lpDeviceName _
  79.     As Any, lpOutput As Any, lpInitData As Any) As Long
  80. Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long
  81. Private Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, _
  82.     lpObject As Any) As Long
  83. Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long
  84. Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth _
  85.     As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As _
  86.     Long) As Long
  87. Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long
  88. Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
  89. Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As _
  90.     Long, ByVal nNumScans As Long, lpBits As Any, lpbi As BITMAPINFO256, ByVal wUsage As Long) As Long
  91. Private Declare Function CreateDIBSection256 Lib "gdi32" Alias "CreateDIBSection" (ByVal hDC As Long, pBitmapInfo _
  92.     As BITMAPINFO256, ByVal un As Long, lplpVoid As Long, ByVal handle As Long, ByVal dw As Long) As Long
  93. Private Const DIB_RGB_COLORS = 0
  94.  
  95. Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) _
  96.     As Long
  97. '============================GIF STAFF================
  98.  
  99. Private Type GifScreenDescriptor
  100.     logical_screen_width As Integer
  101.     logical_screen_height As Integer
  102.     Flags As Byte
  103.     background_color_index As Byte
  104.     pixel_aspect_ratio As Byte
  105. End Type
  106.  
  107. Private Type GifImageDescriptor
  108.     Left As Integer
  109.     Top As Integer
  110.     Width As Integer
  111.     Height As Integer
  112.     Format As Byte 'ImageFormat
  113. End Type
  114. '========Added by Wolfgang Goetz for transparent GIFs=====
  115. Private Type CONTROLBLOCK '(April 8., 2002 --> Wolfgang Goetz)
  116.     Blocksize As Byte
  117.     Flags As Byte
  118.     Delay As Integer
  119.     TransParent_Color As Byte
  120.     Terminator As Byte
  121. End Type
  122. Private Const GIF89a = "GIF89a"
  123. Private Const CtrlIntro As Byte = &H21
  124. Private Const CtrlLabel As Byte = &HF9
  125. '========================================================
  126. Const GIF87a = "GIF87a"
  127.  
  128. Const GifTerminator As Byte = &H3B
  129. Const ImageSeparator As Byte = &H2C
  130. Const CHAR_BIT = 8
  131. Const CodeSize As Byte = 9
  132. Const ClearCode = 256
  133. Const EndCode  As Integer = 257
  134. Const FirstCode = 258
  135. Const LastCode As Integer = 511
  136. Const MAX_CODE = LastCode - FirstCode
  137.  
  138. Private colTable As New Collection
  139. Private fn As Integer
  140. Private gifPalette(0 To 255) As RGBTRIPLE
  141. Private bit_position As Integer
  142. Private code_count As Integer
  143. Private data_buffer(255) As Byte
  144. Private aPower2(31) As Long
  145. Private picWidth As Long
  146. Private  picHeight As Long
  147. Private IsBusy As Boolean
  148. Public Event Progress(ByVal Percents As Integer)
  149.  
  150.  
  151. Public Function SaveGIF(ByVal pic As StdPicture, ByVal sFileName As String, Optional hDC As Long = 0, Optional _
  152.         UseTrans As Boolean = False, Optional ByVal TransColor As Long = 0) As Boolean
  153.     If IsBusy Then Exit Function
  154.   Dim scr As GifScreenDescriptor
  155.   Dim  im As GifImageDescriptor
  156.   Dim bi As BITMAPINFO256
  157.   Dim  bm As BITMAP
  158.   Dim hDCScn As Long
  159.   Dim  OldObj As Long
  160.   Dim  Src_hDc As Long
  161.   Dim hDib256 As Long
  162.   Dim  hDC256 As Long
  163.   Dim  OldObj256 As Long
  164.   Dim buf() As Byte
  165.   Dim  data As Byte
  166.   Dim  TransIndex As Byte
  167.   Dim i As Long
  168.   Dim  j As Long
  169.   Dim  clr As Long
  170.   Dim bFound As Boolean
  171.   Dim intCode As Integer
  172.   Dim  nCount  As Integer
  173.   Dim sPrefix As String
  174.   Dim  sByte As String
  175.   Dim tempPic As StdPicture
  176.     IsBusy = True
  177.     'get image size and allocate buffer memory
  178.     Call GetObjectAPI(pic, Len(bm), bm)
  179.     picWidth = bm.bmWidth
  180.     picHeight = bm.bmHeight
  181.     ReDim buf(CLng(((picWidth + 3) \ 4) * 4), picHeight) As Byte
  182.     'Prepare DC for paintings
  183.     hDCScn = CreateDCAsNull("DISPLAY", ByVal 0&, ByVal 0&, ByVal 0&)
  184.     hDC256 = CreateCompatibleDC(hDCScn)
  185.     If hDC = 0 Then
  186.         Src_hDc = CreateCompatibleDC(hDCScn)
  187.         OldObj = SelectObject(Src_hDc, pic)
  188.     Else
  189.         Src_hDc = hDC
  190.     End If
  191.     DeleteDC hDCScn
  192.     
  193.     'Since GIF works only with 256 colors, reduce color depth to 256
  194.     'This sample use simpliest HalfTone palette to reduce color depth
  195.     'If you want advanced color manipulation with web-safe palettes or
  196.     'optimal palette with the specified number of colors using octree
  197.     'quantisation, visit http://vbaccelerator.com/codelib/gfx/octree.htm
  198.     
  199.     If bm.bmBitsPixel <> 8 Then hDib256 = CreateDib256(hDC256, bi)
  200.     If hDib256 <> 0 Then
  201.         OldObj256 = SelectObject(hDC256, hDib256)
  202.         Call BitBlt(hDC256, 0, 0, picWidth, picHeight, Src_hDc, 0, 0, vbSrcCopy)
  203.         For i = 0 To picHeight - 1
  204.             Call GetDIBits(hDC256, hDib256, i, 1, buf(0, picHeight - i), bi, 0)
  205.         Next
  206.     Else
  207.         With bi.bmiHeader
  208.             .biSize = Len(bi.bmiHeader)
  209.             .biWidth = picWidth
  210.             .biHeight = picHeight
  211.             .biPlanes = 1
  212.             .biBitCount = 8
  213.             .biCompression = BI_RGB
  214.         End With
  215.         For i = 0 To picHeight - 1
  216.             Call GetDIBits(Src_hDc, pic, i, 1, buf(0, picHeight - i), bi, 0)
  217.         Next
  218.     End If
  219.     'Fill gif file info
  220.     For i = 0 To 255
  221.         gifPalette(i).rgbBlue = bi.bmiColors(i).rgbBlue
  222.         gifPalette(i).rgbGreen = bi.bmiColors(i).rgbGreen
  223.         gifPalette(i).rgbRed = bi.bmiColors(i).rgbRed
  224.         If Not bFound Then
  225.             clr = RGB(gifPalette(i).rgbRed, gifPalette(i).rgbGreen, gifPalette(i).rgbBlue)
  226.             If clr = TransColor Then
  227.                 TransIndex = i: bFound = True
  228.             End If
  229.         End If
  230.     Next
  231.     '   If TransColor = 0 Then TransIndex = 0
  232.     scr.background_color_index = 0
  233.     scr.Flags = &HF7 '256-color gif with global color map
  234.     scr.pixel_aspect_ratio = 0
  235.     
  236.     im.Format = &H7 'GlobalNonInterlaced
  237.     im.Height = picHeight
  238.     im.Width = picWidth
  239.     
  240.     If FileExists(sFileName) Then
  241.         SetAttr sFileName, vbNormal
  242.         
  243.         Kill sFileName
  244.     End If
  245.     fn = FreeFile
  246.     Open sFileName For Binary As fn
  247.     'Write GIF header and header info
  248.     If UseTrans = True Then '(April 8., 2002 --> Wolfgang Goetz)
  249.         Put #fn, , GIF89a
  250.     Else
  251.         Put #fn, , GIF87a
  252.     End If
  253.     Put #fn, , scr
  254.     Put #fn, , gifPalette
  255.     '(April 8., 2002 --> Wolfgang Goetz)
  256.     If UseTrans = True Then
  257.         Put #fn, , CtrlIntro
  258.         Put #fn, , CtrlLabel
  259.         Dim cb As CONTROLBLOCK
  260.         cb.Blocksize = 4 'Always 4
  261.         cb.Flags = 9 'Packed = 00001001 (If Bit 0 = 1: Use Transparency)
  262.         cb.Delay = 0
  263.         cb.TransParent_Color = TransIndex
  264.         cb.Terminator = 0 'Always 0
  265.         Put #fn, , cb
  266.     End If
  267.     Put #fn, , ImageSeparator
  268.     Put #fn, , im
  269.     data = CodeSize - 1
  270.     Put #fn, , data
  271.     data_buffer(0) = 0
  272.     bit_position = CHAR_BIT
  273.     'Process pixels data using LZW/GIF compression
  274.     For i = 1 To picHeight
  275.         Reinitialize
  276.         sPrefix = ""
  277.         intCode = buf(0, i)
  278.         On Error Resume Next
  279.         For j = 1 To picWidth - 1
  280.             sByte = MyFormat(buf(j, i))
  281.             sPrefix = sPrefix & sByte
  282.             intCode = colTable(sPrefix)
  283.             If Err <> 0 Then 'Prefix wasn't in collection - save it and output code
  284.                 nCount = colTable.count
  285.                 If nCount = MAX_CODE Then Reinitialize
  286.                 colTable.Add nCount + FirstCode, sPrefix
  287.                 OutputBits intCode, CodeSize
  288.                 sPrefix = sByte
  289.                 intCode = buf(j, i)
  290.                 Err.Clear
  291.             End If
  292.         Next
  293.         OutputBits intCode, CodeSize
  294.         If i Mod 10 = 0 Then
  295.             RaiseEvent Progress(i * 100 / picHeight)
  296.             DoEvents
  297.         End If
  298.     Next
  299.     OutputCode (EndCode)
  300.     For i = 0 To data_buffer(0)
  301.         Put #fn, , data_buffer(i)
  302.     Next
  303.     data = 0
  304.     Put #fn, , data
  305.     Put #fn, , GifTerminator
  306.     Close fn
  307.     Erase buf
  308.     If hDC = 0 Then
  309.         SelectObject Src_hDc, OldObj
  310.         DeleteDC Src_hDc
  311.     End If
  312.     SelectObject hDC256, OldObj256
  313.     DeleteObject hDib256
  314.     DeleteDC hDC256
  315.     SaveGIF = True
  316.     IsBusy = False
  317. End Function
  318.  
  319. Private Sub OutputBits(Value As Integer, count As Integer)
  320.   Dim i As Integer
  321.   Dim  bit As Integer
  322.     Do While i < count
  323.         If bit_position = CHAR_BIT Then
  324.             If data_buffer(0) = 255 Then
  325.                 Put #fn, , data_buffer
  326.                 data_buffer(0) = 1
  327.             Else
  328.                 data_buffer(0) = data_buffer(0) + 1
  329.             End If
  330.             data_buffer(data_buffer(0)) = 0
  331.             bit_position = 0
  332.         End If
  333.         bit = Sgn(Power2(i) And Value)
  334.         If bit > 0 Then data_buffer(data_buffer(0)) = Power2(bit_position) Or data_buffer(data_buffer(0))
  335.         i = i + 1: bit_position = bit_position + 1
  336.     Loop
  337. End Sub
  338.  
  339. Private Sub OutputCode(code As Integer)
  340.     code_count = code_count + 1
  341.     If code_count > LastCode Then
  342.         code_count = FirstCode
  343.         Call OutputBits(ClearCode, CodeSize)
  344.         ClearTable
  345.     End If
  346.     Call OutputBits(code, CodeSize)
  347. End Sub
  348.  
  349. Private Sub ClearTable()
  350.     Set colTable = Nothing
  351.     Set colTable = New Collection
  352. End Sub
  353.  
  354. Private Sub Reinitialize()
  355.     ClearTable
  356.     Call OutputBits(ClearCode, CodeSize)
  357. End Sub
  358.  
  359. Private Function FileExists(ByVal strPathName As String) As Boolean
  360.   Dim af As Long
  361.     af = GetFileAttributes(strPathName)
  362.     FileExists = (af <> -1)
  363. End Function
  364.  
  365. Private Function Power2(ByVal i As Integer) As Long
  366.     If aPower2(0) = 0 Then
  367.         aPower2(0) = &H1&
  368.         aPower2(1) = &H2&
  369.         aPower2(2) = &H4&
  370.         aPower2(3) = &H8&
  371.         aPower2(4) = &H10&
  372.         aPower2(5) = &H20&
  373.         aPower2(6) = &H40&
  374.         aPower2(7) = &H80&
  375.         aPower2(8) = &H100&
  376.         aPower2(9) = &H200&
  377.         aPower2(10) = &H400&
  378.         aPower2(11) = &H800&
  379.         aPower2(12) = &H1000&
  380.         aPower2(13) = &H2000&
  381.         aPower2(14) = &H4000&
  382.         aPower2(15) = &H8000&
  383.         aPower2(16) = &H10000
  384.         aPower2(17) = &H20000
  385.         aPower2(18) = &H40000
  386.         aPower2(19) = &H80000
  387.         aPower2(20) = &H100000
  388.         aPower2(21) = &H200000
  389.         aPower2(22) = &H400000
  390.         aPower2(23) = &H800000
  391.         aPower2(24) = &H1000000
  392.         aPower2(25) = &H2000000
  393.         aPower2(26) = &H4000000
  394.         aPower2(27) = &H8000000
  395.         aPower2(28) = &H10000000
  396.         aPower2(29) = &H20000000
  397.         aPower2(30) = &H40000000
  398.         aPower2(31) = &H80000000
  399.     End If
  400.     Power2 = aPower2(i)
  401. End Function
  402.  
  403. Private Function MyFormat(ByVal s As String) As String
  404.     MyFormat = Right$("00" & s, 3)
  405. End Function
  406.  
  407. Private Function CreateDib256(ByVal h_Dc As Long, bi As BITMAPINFO256) As Long
  408.   Dim lScanSize As Long
  409.   Dim lptr As Long
  410.   Dim  lIndex As Long
  411.   Dim r As Long
  412.   Dim  g As Long
  413.   Dim  b As Long
  414.   Dim rA As Long
  415.   Dim  gA As Long
  416.   Dim  bA As Long
  417.     With bi.bmiHeader
  418.         .biSize = Len(bi.bmiHeader)
  419.         .biWidth = picWidth
  420.         .biHeight = picHeight
  421.         .biPlanes = 1
  422.         .biBitCount = 8
  423.         .biCompression = BI_RGB
  424.         lScanSize = (picWidth + picWidth Mod 4)
  425.         .biSizeImage = lScanSize * picHeight
  426.     End With
  427.     ' Halftone 256 colour palette
  428.     For b = 0 To &H100 Step &H40
  429.         If b = &H100 Then
  430.             bA = b - 1
  431.         Else
  432.             bA = b
  433.         End If
  434.         For g = 0 To &H100 Step &H40
  435.             If g = &H100 Then
  436.                 gA = g - 1
  437.             Else
  438.                 gA = g
  439.             End If
  440.             For r = 0 To &H100 Step &H40
  441.                 If r = &H100 Then
  442.                     rA = r - 1
  443.                 Else
  444.                     rA = r
  445.                 End If
  446.                 With bi.bmiColors(lIndex)
  447.                     .rgbRed = rA: .rgbGreen = gA: .rgbBlue = bA
  448.                 End With
  449.                 lIndex = lIndex + 1
  450.             Next r
  451.         Next g
  452.     Next b
  453.     CreateDib256 = CreateDIBSection256(h_Dc, bi, DIB_RGB_COLORS, lptr, 0, 0)
  454. End Function
  455.