Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 |

 

  Вопрос: Как Рисование мышью Добавлено: 02.07.10 12:10  

Автор вопроса:  ilgar
Ребята у меня маленькая проблема.
Вроде бы ни чего трудного, но......
Ситуация такая.
В WINDOWS форме стоит PictureBox.
На нем с мышкой рисую кривые.
А как сохранить рисунок в файле jpeg ?

Ответить

  Ответы Всего ответов: 3  

Номер ответа: 1
Автор ответа:
 VβÐUηìt



Вопросов: 246
Ответов: 3333
 Web-сайт: смекаешь.рф
 Профиль | | #1
Добавлено: 02.07.10 12:51
WINDOWS большими буквами. Мне это нравится.

http://www.google.ru/search?client=opera&rls=ru&q=%D0%A1%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D1%8C+JPG+%D0%B2+VB6&sourceid=opera&ie=utf-8&oe=utf-8

Ответить

Номер ответа: 2
Автор ответа:
 AWP



ICQ: 345685652 

Вопросов: 96
Ответов: 1212
 Web-сайт: xawp.narod.ru
 Профиль | | #2
Добавлено: 02.07.10 16:42
вот тебе конкретный класс
  1. Option Explicit
  2. Option Base 0
  3.  
  4. 'Class Name:   cJpeg.cls  "JPEG Encoder Class"
  5. 'Author:       John Korejwa  <korejwa@tiac.net>
  6. 'Version:      0.9 beta  [26 / November / 2003]
  7. '
  8. '
  9. 'Legal:
  10. '        This class is intended for and was uploaded to www.planetsourcecode.com
  11. '
  12. '        This product includes JPEG compression code developed by John Korejwa.  <korejwa@tiac.net>
  13. '        Source code, written in Visual Basic, is freely available for non-commercial,
  14. '        non-profit use at www.planetsourcecode.com.
  15. '
  16. '
  17. 'Credits:
  18. '        Special thanks to Barry G., a government research scientist who took an interest in my
  19. '        steganography software and research in late 1999.  I never met Barry in person, but he
  20. '        was kind enough to buy and mail me a book with the ISO DIS 10918-1 JPEG standard.
  21. '
  22. '
  23. 'Description:  This class contains code for compressing pictures, sampled via hDC, into
  24. '              baseline .JPG files.  Please report any errors or unusual behavior to the email
  25. '              address above.
  26. '
  27. 'Dependencies: None
  28. '
  29.  
  30.  
  31. 'JPEG Marker Constants                (Note: VB compiler does not compile unused constants)
  32.                                       'Non-Differential Huffman Coding
  33. Private Const SOF0    As Long = &HC0& 'Baseline DCT
  34. 'Private Const SOF1    As Long = &HC1& 'Extended sequential DCT
  35. 'Private Const SOF2    As Long = &HC2& 'Progressive DCT
  36. 'Private Const SOF3    As Long = &HC3& 'Spatial (sequential) lossless
  37.                                       'Differential Huffman coding
  38. 'Private Const SOF5    As Long = &HC5& 'Differential sequential DCT
  39. 'Private Const SOF6    As Long = &HC6& 'Differential progressive DCT
  40. 'Private Const SOF7    As Long = &HC7& 'Differential spatial
  41.                                       'Non-Differential arithmetic coding
  42. 'Private Const jpg     As Long = &HC8& 'Reserved for JPEG extentions
  43. 'Private Const SOF9    As Long = &HC9& 'Extended sequential DCT
  44. 'Private Const SOF10   As Long = &HCA& 'Progressive DCT
  45. 'Private Const SOF11   As Long = &HCB& 'Spatial (sequential) lossless
  46.                                       'Differential arithmetic coding
  47. 'Private Const SOF13   As Long = &HCD& 'Differential sequential DCT
  48. 'Private Const SOF14   As Long = &HCE& 'Differential progressive DCT
  49. 'Private Const SOF15   As Long = &HCF& 'Differential Spatial
  50.                                       'Other Markers
  51. Private Const DHT     As Long = &HC4& 'Define Huffman tables
  52. 'Private Const DAC     As Long = &HCC& 'Define arithmetic coding conditioning(s)
  53. 'Private Const RSTm    As Long = &HD0& 'Restart with modulo 8 count "m"
  54. 'Private Const RSTm2   As Long = &HD7& 'to 'Restart with modulo 8 count "m"
  55. Private Const SOI     As Long = &HD8& 'Start of image
  56. Private Const EOI     As Long = &HD9& 'End of image
  57. Private Const SOS     As Long = &HDA& 'Start of scan
  58. Private Const DQT     As Long = &HDB& 'Define quantization table(s)
  59. 'Private Const DNL     As Long = &HDC& 'Define number of lines
  60. 'Private Const DRI     As Long = &HDD& 'Define restart interval
  61. 'Private Const DHP     As Long = &HDE& 'Define hierarchical progression
  62. 'Private Const EXP     As Long = &HDF& 'Expand reference components
  63. 'Private Const APP0    As Long = &HE0& 'Reserved for application segments
  64. 'Private Const APPF    As Long = &HEF& '  to Reserved for application segments
  65. 'Private Const JPGn    As Long = &HF0& 'Reserved for JPEG Extentions
  66. 'Private Const JPGn2   As Long = &HFD& '  to Reserved for JPEG Extentions
  67. Private Const COM     As Long = &HFE& 'Comment
  68. 'Private Const RESm    As Long = &H2&  'Reserved
  69. 'Private Const RESm2   As Long = &HBF& '  to Reserved
  70. 'Private Const TEM     As Long = &H1&  'For temporary use in arithmetic coding
  71.  
  72. 'Consider these arrays of constants.
  73. 'They are initialized with the class and do not change.
  74. Private QLumin(63)    As Integer 'Standard Luminance   Quantum (for 50% quality)
  75. Private QChrom(63)    As Integer 'Standard Chrominance Quantum (for 50% quality)
  76. Private FDCTScale(7)  As Double  'Constants for scaling FDCT Coefficients
  77. Private IDCTScale(7)  As Double  'Constants for scaling IDCT Coefficients
  78. Private ZigZag(7, 7)  As Long    'Zig Zag order of 8X8 block of samples
  79.  
  80. 'API constants
  81. 'Private Const BLACKONWHITE    As Long = 1 'nStretchMode constants for
  82. Private Const COLORONCOLOR    As Long = 3 '  SetStretchBltMode() API function
  83. Private Const HALFTONE        As Long = 4 'HALFTONE not supported in Win 95, 98, ME
  84.  
  85. Private Const BI_RGB          As Long = 0
  86. Private Const DIB_RGB_COLORS  As Long = 0
  87.  
  88.  
  89. 'Variable types needed for DIBSections.
  90. Private Type SAFEARRAYBOUND
  91.     cElements         As Long
  92.     lLbound           As Long
  93. End Type
  94. Private Type SAFEARRAY2D
  95.     cDims             As Integer
  96.     fFeatures         As Integer
  97.     cbElements        As Long
  98.     cLocks            As Long
  99.     pvData            As Long
  100.     Bounds(0 To 1)    As SAFEARRAYBOUND
  101. End Type
  102. Private Type RGBQUAD
  103.     rgbBlue           As Byte
  104.     rgbGreen          As Byte
  105.     rgbRed            As Byte
  106.     rgbReserved       As Byte
  107. End Type
  108. Private Type BITMAPINFOHEADER
  109.     biSize            As Long
  110.     biWidth           As Long
  111.     biHeight          As Long
  112.     biPlanes          As Integer
  113.     biBitCount        As Integer
  114.     biCompression     As Long
  115.     biSizeImage       As Long
  116.     biXPelsPerMeter   As Long
  117.     biYPelsPerMeter   As Long
  118.     biClrUsed         As Long
  119.     biClrImportant    As Long
  120. End Type
  121. Private Type BITMAPINFO
  122.     bmiHeader         As BITMAPINFOHEADER
  123.     bmiColors         As RGBQUAD
  124. End Type
  125.  
  126. 'API needed for creating DIBSections for sampling and pixel access.
  127. Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
  128. Private Declare Function CreateDIBSection2 Lib "gdi32" Alias "CreateDIBSection" (ByVal hdc As Long, pBitmapInfo As BITMAPINFO, ByVal un As Long, lplpVoid As Long, ByVal handle As Long, ByVal dw As Long) As Long   'lplpVoid changed to ByRef
  129. Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
  130. Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
  131. Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
  132. 'Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
  133. Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
  134. Private Declare Function SetStretchBltMode Lib "gdi32" (ByVal hdc As Long, ByVal nStretchMode As Long) As Long
  135. Private Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
  136. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
  137.  
  138. 'Custom variable types used for this JPEG encoding implementation
  139. Private Type QUANTIZATIONTABLE
  140.     Qk(63)            As Integer 'Quantization Values
  141.     FScale(63)        As Single  'Multiplication values to scale and Quantize   FDCT output
  142.     IScale(63)        As Single  'Multiplication values to scale and DeQuantize IDCT input
  143. End Type
  144. Private Type HUFFMANTABLE
  145.     Bits(15)          As Byte    'Number of huffman codes of length i+1
  146.     HUFFVAL(255)      As Byte    'Huffman symbol values
  147.     EHUFSI(255)       As Long    'Huffman code size for symbol i
  148.     EHUFCO(255)       As Long    'Huffman code      for symbol i
  149.     MINCODE(15)       As Long    '
  150.     MAXCODE(15)       As Long    'Largest code value for length i+1
  151. End Type
  152. Private Type COMPONENT
  153.     Ci                As Long    'Component ID                       [0-255]
  154.     Hi                As Long    'Horizontal Sampling Factor         [1-4]
  155.     Vi                As Long    'Vertical   Sampling Factor         [1-4]
  156.     Tqi               As Long    'Quantization Table Select          [0-3]
  157.     Data()            As Integer 'DCT Coefficients
  158. End Type
  159.  
  160. Private PP            As Long    'Sample Precision [8, 12]
  161. Private YY            As Long    'Number of lines             [Image Height]
  162. Private XX            As Long    'Number of samples per line  [Image Width]
  163. Private Nf            As Long    'Number of components in Frame
  164.  
  165. Private HMax          As Long    'Maximum horizontal sampling frequency
  166. Private VMax          As Long    'Maximum vertical   sampling frequency
  167.  
  168. Private m_Data()      As Byte    'JPEG File Data
  169. Private m_Chr         As Long    'Current Character in m_Data
  170. Private m_Ptr         As Long    'Byte index in m_Data
  171. Private m_Bit         As Long    'Bit  index in m_Chr
  172.  
  173. Private m_Block(7, 7) As Single  'Buffer for calculating DCT
  174.  
  175. Private QTable(3)     As QUANTIZATIONTABLE  '4 Quantization Tables
  176. Private HuffDC(3)     As HUFFMANTABLE       '4 DC Huffman Tables
  177. Private HuffAC(3)     As HUFFMANTABLE       '4 AC Huffman Tables
  178. Private Comp()        As COMPONENT          'Scan Components
  179.  
  180. Private m_Quality     As Long
  181. Private m_Comment     As String
  182.  
  183.  
  184.  
  185. '========================================================================================
  186. '              D I S C R E T E   C O S I N E   T R A N S F O R M A T I O N
  187. '========================================================================================
  188. Private Sub FDCT()
  189.     Static t0   As Single 'Given an 8X8 block of discretely sampled values [m_Block(0-7, 0-7)],
  190.     Static t1   As Single 'replace them with their (scaled) Forward Discrete Cosine Transformation values.
  191.     Static t2   As Single '80 (+64) multiplications and 464 additions are needed.
  192.     Static t3   As Single 'Values are scaled on output, meaning that each of the 64 elements must be
  193.     Static t4   As Single 'multiplied by constants for a final FDCT.  These final constants are combined
  194.     Static t5   As Single 'with Quantization constants, so a final 64 multiplications combine the
  195.     Static t6   As Single 'completion of the FDCT and Quantization in one step.
  196.     Static t7   As Single
  197.     Static t8   As Single
  198.     Static I    As Long
  199.  
  200.     For I = 0 To 7                  'Process 1D FDCT on each row
  201.         t0 = m_Block(I, 0) + m_Block(I, 7)
  202.         t1 = m_Block(I, 0) - m_Block(I, 7)
  203.         t2 = m_Block(I, 1) + m_Block(I, 6)
  204.         t3 = m_Block(I, 1) - m_Block(I, 6)
  205.         t4 = m_Block(I, 2) + m_Block(I, 5)
  206.         t5 = m_Block(I, 2) - m_Block(I, 5)
  207.         t6 = m_Block(I, 3) + m_Block(I, 4)
  208.         t7 = m_Block(I, 3) - m_Block(I, 4)
  209.  
  210.         t7 = t7 + t5
  211.         t8 = t0 - t6
  212.         t6 = t6 + t0
  213.         t0 = t2 + t4
  214.         t2 = (t2 - t4 + t8) * 0.707106781186548   'Cos(2# * PI / 8#)
  215.         t4 = t1 + t3
  216.         t3 = (t3 + t5) * 0.707106781186548        'Cos(2# * PI / 8#)
  217.         t5 = (t4 - t7) * 0.382683432365091        'Cos(3# * PI / 8#)
  218.         t7 = t7 * 0.541196100146196 - t5          'Cos(PI / 8#) - Cos(3# * PI / 8#)
  219.         t4 = t4 * 1.30656296487638 - t5           'Cos(PI / 8#) + Cos(3# * PI / 8#)
  220.         t5 = t1 + t3
  221.         t1 = t1 - t3
  222.  
  223.         m_Block(I, 0) = t6 + t0
  224.         m_Block(I, 4) = t6 - t0
  225.         m_Block(I, 1) = t5 + t4
  226.         m_Block(I, 7) = t5 - t4
  227.         m_Block(I, 2) = t8 + t2
  228.         m_Block(I, 6) = t8 - t2
  229.         m_Block(I, 5) = t1 + t7
  230.         m_Block(I, 3) = t1 - t7
  231.     Next I
  232.  
  233.     For I = 0 To 7                   'Process 1D FDCT on each column
  234.         t0 = m_Block(0, I) + m_Block(7, I)
  235.         t1 = m_Block(0, I) - m_Block(7, I)
  236.         t2 = m_Block(1, I) + m_Block(6, I)
  237.         t3 = m_Block(1, I) - m_Block(6, I)
  238.         t4 = m_Block(2, I) + m_Block(5, I)
  239.         t5 = m_Block(2, I) - m_Block(5, I)
  240.         t6 = m_Block(3, I) + m_Block(4, I)
  241.         t7 = m_Block(3, I) - m_Block(4, I)
  242.  
  243.         t7 = t7 + t5
  244.         t8 = t0 - t6
  245.         t6 = t6 + t0
  246.         t0 = t2 + t4
  247.         t2 = (t2 - t4 + t8) * 0.707106781186548   'Cos(2# * PI / 8#)
  248.         t4 = t1 + t3
  249.         t3 = (t3 + t5) * 0.707106781186548        'Cos(2# * PI / 8#)
  250.         t5 = (t4 - t7) * 0.382683432365091        'Cos(3# * PI / 8#)
  251.         t7 = t7 * 0.541196100146196 - t5          'Cos(PI / 8#) - Cos(3# * PI / 8#)
  252.         t4 = t4 * 1.30656296487638 - t5           'Cos(PI / 8#) + Cos(3# * PI / 8#)
  253.         t5 = t1 + t3
  254.         t1 = t1 - t3
  255.  
  256.         m_Block(0, I) = t6 + t0
  257.         m_Block(4, I) = t6 - t0
  258.         m_Block(1, I) = t5 + t4
  259.         m_Block(7, I) = t5 - t4
  260.         m_Block(2, I) = t8 + t2
  261.         m_Block(6, I) = t8 - t2
  262.         m_Block(5, I) = t1 + t7
  263.         m_Block(3, I) = t1 - t7
  264.     Next I
  265. End Sub
  266.  
  267.  
  268.  
  269.  
  270. '================================================================================
  271. '                 H U F F M A N   T A B L E   G E N E R A T I O N
  272. '================================================================================
  273. Private Sub OptimizeHuffman(TheHuff As HUFFMANTABLE, freq() As Long)
  274. 'Generate optimized values for BITS and HUFFVAL in a HUFFMANTABLE
  275. 'based on symbol frequency counts.  freq must be dimensioned freq(0-256)
  276. 'and contain counts of symbols 0-255.  freq is destroyed in this procedure.
  277.     Dim I              As Long
  278.     Dim J              As Long
  279.     Dim k              As Long
  280.     Dim n              As Long
  281.     Dim V1             As Long
  282.     Dim V2             As Long
  283.     Dim others(256)    As Long
  284.     Dim codesize(256)  As Long
  285.     Dim Bits(256)      As Long
  286.     Dim swp            As Long
  287.     Dim swp2           As Long
  288.  
  289.  
  290.     For I = 0 To 256  'Initialize others to -1, (this value terminates chain of indicies)
  291.         others(I) = -1
  292.     Next I
  293.     freq(256) = 1     'Add dummy symbol to guarantee no code will be all '1' bits
  294.  
  295.    'Generate codesize()   [find huffman code sizes]
  296.     Do 'do loop for (#non-zero-frequencies - 1) times
  297.         V1 = -1                            'find highest v1 for      least value of freq(v1)>0
  298.         V2 = -1                            'find highest v2 for next least value of freq(v2)>0
  299.         swp = 2147483647 'Max Long variable
  300.         swp2 = 2147483647
  301.         For I = 0 To 256
  302.             If freq(I) <> 0 Then
  303.                 If (freq(I) <= swp2) Then
  304.                     If (freq(I) <= swp) Then
  305.                         swp2 = swp
  306.                         V2 = V1
  307.                         swp = freq(I)
  308.                         V1 = I
  309.                     Else
  310.                         swp2 = freq(I)
  311.                         V2 = I
  312.                     End If
  313.                 End If
  314.             End If
  315.         Next I
  316.         If V2 = -1 Then
  317.             freq(V1) = 0 'all elements in freq are now set to zero
  318.             Exit Do      'done
  319.         End If
  320.         freq(V1) = freq(V1) + freq(V2)     'merge the two branches
  321.         freq(V2) = 0
  322.         codesize(V1) = codesize(V1) + 1    'Increment all codesizes in v1's branch
  323.         While (others(V1) >= 0)
  324.             V1 = others(V1)
  325.             codesize(V1) = codesize(V1) + 1
  326.         Wend
  327.         others(V1) = V2                    'chain v2 onto v1's branch
  328.         codesize(V2) = codesize(V2) + 1    'Increment all codesizes in v2's branch
  329.         While (others(V2) >= 0)
  330.             V2 = others(V2)
  331.             codesize(V2) = codesize(V2) + 1
  332.         Wend
  333.     Loop
  334.  
  335.    'Count BITS  [find the number of codes of each size]
  336.     n = 0
  337.     For I = 0 To 256
  338.         If codesize(I) <> 0 Then
  339.             Bits(codesize(I)) = Bits(codesize(I)) + 1
  340.             If n < codesize(I) Then n = codesize(I)    'Keep track of largest codesize
  341.         End If
  342.     Next I
  343.  
  344.    'Adjust BITS  [limit code lengths to 16 bits]
  345.     I = n
  346.     While I > 16
  347.         While Bits(I) > 0
  348.             For J = I - 2 To 1 Step -1        'Since symbols are paired for the longest Huffman
  349.                 If Bits(J) > 0 Then Exit For  'code, the symbols are removed from this length
  350.             Next J                            'category two at a time.  The prefix for the pair
  351.             Bits(I) = Bits(I) - 2             '(which is one bit shorter) is allocated to one
  352.             Bits(I - 1) = Bits(I - 1) + 1     'of the pair;  then, (skipping the BITS entry for
  353.             Bits(J + 1) = Bits(J + 1) + 2     'that prefix length) a code word from the next
  354.             Bits(J) = Bits(J) - 1             'shortest non-zero BITS entry is converted into
  355.         Wend                                  'a prefix for two code words one bit longer.
  356.         I = I - 1
  357.     Wend
  358.     Bits(I) = Bits(I) - 1                  'Remove dummy symbol code from the code length count
  359.  
  360.    'Copy BITS and HUFFVAL to the HUFFMANTABLE  [HUFFVAL sorted by code length, then by value]
  361.     With TheHuff
  362.         For I = 1 To 16
  363.             .Bits(I - 1) = Bits(I)
  364.         Next I
  365.         k = 0
  366.         For I = 1 To n
  367.             For J = 0 To 255
  368.                 If codesize(J) = I Then
  369.                     .HUFFVAL(k) = J
  370.                     k = k + 1
  371.                 End If
  372.             Next J
  373.         Next I
  374.     End With
  375.  
  376. End Sub
  377. Private Sub ExpandHuffman(TheHuff As HUFFMANTABLE, Optional MaxSymbol As Long = 255)
  378. 'Given a HUFFMANTABLE with valid BITS and HUFFVAL, generate tables for
  379. 'EHUFCO, EHUFSI, MAXCODE, and MINCODE so the table may be used for compression
  380. 'and/or decompression.  In JPEG, MaxSymbol is 255 for an AC Huffman Table.  For
  381. 'DC Tables, MaxSymbol is 11 for PP=8 bit precission, or 15 for PP=12 bit precission.
  382.     Dim I          As Long 'Index for BITS
  383.     Dim J          As Long 'Index for HUFFVAL
  384.     Dim k          As Long 'Index for last HUFFVAL of length (i+1)
  385.     Dim si         As Long 'Huffman code size  ( =2^i )
  386.     Dim code       As Long 'Huffman code
  387.     Dim symbol     As Long 'Huffman symbol
  388.  
  389.  
  390.     With TheHuff
  391.  
  392.         For I = 0 To 255
  393.            .EHUFSI(I) = 0      'Clear existing values so we can
  394.            .EHUFCO(I) = -1     'check for duplicate huffman symbols
  395.         Next I
  396.  
  397.         J = 0
  398.         si = 1
  399.         code = 0
  400.         For I = 0 To 15
  401.             k = J + .Bits(I)
  402.             If k > 256 Then Err.Raise 1, , "Bad Huffman Table" 'more than 256 symbols
  403.             If J = k Then 'no codes of length i+1
  404.                .MINCODE(I) = J - code
  405.                .MAXCODE(I) = -1
  406.             Else
  407.                .MINCODE(I) = J - code
  408.                 While J < k
  409.                     symbol = .HUFFVAL(J)  'read symbol, make sure it's valid
  410.                     If symbol > MaxSymbol Then Err.Raise 1, , "Bad Huffman Table"   'invalid symbol
  411.                     If .EHUFCO(symbol) >= 0 Then Err.Raise 1, , "Bad Huffman Table" 'duplicate symbol
  412.                    .EHUFSI(symbol) = si    'assign code for symbol
  413.                    .EHUFCO(symbol) = code
  414.                     code = code + 1
  415.                     J = J + 1
  416.                 Wend
  417.                .MAXCODE(I) = code - 1
  418.             End If
  419.             si = si * 2
  420.             If code >= si Then Err.Raise 1, , "Bad Huffman Table" 'code does not fit into available bits
  421.             code = code * 2
  422.         Next I
  423.         If J = 0 Then Err.Raise 1, , "Bad Huffman Table" 'No huffman symbols???
  424.     End With
  425.  
  426. End Sub
  427.  
  428.  
  429.  
  430.  
  431. '================================================================================
  432. '                           E N T R O P Y   C O D I N G
  433. '================================================================================
  434. Private Sub WriteBitsBegin()
  435.     m_Chr = 0
  436.     m_Bit = 128
  437. End Sub
  438. Private Sub WriteBitsEnd()
  439.     If m_Bit <> 128 Then WriteBits m_Bit, -1
  440. End Sub
  441. Private Sub WriteBits(ByVal si As Long, code As Long)
  442.     While si > 0
  443.         If (code And si) <> 0 Then m_Chr = (m_Chr Or m_Bit)
  444.         If m_Bit = 1 Then            'We completed a byte ...
  445.             m_Data(m_Ptr) = m_Chr    '    add it to the stream
  446.             If m_Chr = 255 Then      'Pad a zero byte and advance pointer
  447.                 m_Data(m_Ptr + 1) = 0
  448.                 m_Ptr = m_Ptr + 2
  449.             Else                     'just advance pointer
  450.                 m_Ptr = m_Ptr + 1
  451.             End If
  452.             m_Chr = 0                'clear byte buffer and reset bit index
  453.             m_Bit = 128
  454.         Else                         'increment to next bit position to write
  455.             m_Bit = m_Bit \ 2
  456.         End If
  457.         si = si \ 2
  458.     Wend
  459. End Sub
  460.  
  461. Private Sub EncodeCoefficients(Data() As Integer, P As Long, Pred As Long, Td As Long, Ta As Long)
  462. 'Use Huffman tables to compress a block of 64 quantized DCT coefficients to the local
  463. 'm_Data() byte array.  The coefficients are input in the data() array starting at index p.
  464. 'Pred is the predictor for the DC coefficient.  Td and Ta are indexes to the local DC and AC
  465. 'Huffman Tables to use.
  466.     Dim R     As Long
  467.     Dim rs    As Long
  468.     Dim si    As Long
  469.     Dim code  As Long
  470.     Dim p2    As Long
  471.  
  472.     p2 = P + 64
  473.  
  474.     code = Data(P) - Pred
  475.     Pred = Data(P)
  476.     P = P + 1
  477.  
  478.     si = 1
  479.     rs = 0
  480.     If code < 0 Then
  481.         Do While si <= -code
  482.             si = si * 2
  483.             rs = rs + 1
  484.         Loop
  485.         code = code - 1
  486.     Else
  487.         Do While si <= code
  488.             si = si * 2
  489.             rs = rs + 1
  490.         Loop
  491.     End If
  492.     si = si \ 2
  493.     WriteBits HuffDC(Td).EHUFSI(rs), HuffDC(Td).EHUFCO(rs) 'append symbol for size category
  494.     WriteBits si, code                                     'append diff
  495.  
  496.     With HuffAC(Ta)
  497.         R = 0
  498.         Do
  499.             If Data(P) = 0 Then
  500.                  R = R + 1
  501.             Else
  502.                 While R > 15
  503.                     WriteBits .EHUFSI(240), .EHUFCO(240) 'append RUN16 (a run of 16 zeros)
  504.                     R = R - 16
  505.                 Wend
  506.                 code = Data(P)
  507.                 rs = R * 16
  508.                 si = 1
  509.                 If code < 0 Then
  510.                     Do While si <= -code
  511.                         si = si * 2
  512.                         rs = rs + 1
  513.                     Loop
  514.                     code = code - 1
  515.                 Else
  516.                     Do While si <= code
  517.                         si = si * 2
  518.                         rs = rs + 1
  519.                     Loop
  520.                 End If
  521.                 si = si \ 2
  522.                 WriteBits .EHUFSI(rs), .EHUFCO(rs) 'append run length, size category
  523.                 WriteBits si, code                 'append AC value
  524.                 R = 0
  525.             End If
  526.             P = P + 1
  527.         Loop While P < p2 'should be equal on exit
  528.         If R <> 0 Then WriteBits .EHUFSI(0), .EHUFCO(0) 'append EOB (end of block)
  529.     End With
  530.  
  531. End Sub
  532.  
  533.  
  534.  
  535.  
  536. '========================================================================================
  537. '                      C O L L E C T I N G   S T A T I S T I C S
  538. '========================================================================================
  539. 'These procedures collect statistics of run-length and size categories of DCT coefficients
  540. 'so optimized Huffman tables can be generated to compress them.
  541. Private Sub CollectStatisticsAC(Data() As Integer, freqac() As Long)
  542.     Dim code As Long
  543.     Dim n    As Long 'Number of coefficients in data()
  544.     Dim P    As Long 'Index for current data() coefficient
  545.     Dim p2   As Long
  546.     Dim R    As Long 'Run length of zeros
  547.     Dim rs   As Long 'Run-length/Size-category Symbol
  548.  
  549.  
  550.     n = UBound(Data) + 1
  551.     P = 0
  552.     While P <> n
  553.         P = P + 1     'Skip DC coefficient
  554.         p2 = P + 63   '63 AC coefficients
  555.  
  556.         R = 0
  557.         While P <> p2
  558.             If Data(P) = 0 Then
  559.                  R = R + 1
  560.             Else
  561.                 While R > 15
  562.                     freqac(240) = freqac(240) + 1  'RUN16 Symbol
  563.                     R = R - 16
  564.                 Wend
  565.                 code = Data(P)
  566.                 If code < 0 Then 'rs = number of bits needed for code
  567.                     rs = Int((Log(-code) * 1.442695040889)) + 1   '1/log(2)  (+ error correction)
  568.                 ElseIf code > 0 Then
  569.                     rs = Int((Log(code) * 1.442695040889)) + 1    '1/log(2)  (+ error correction)
  570.                 Else
  571.                     rs = 0
  572.                 End If
  573.  
  574.                 rs = (R * 16) Or rs
  575.                 freqac(rs) = freqac(rs) + 1        'Run-length/Size-category Symbol
  576.                 R = 0
  577.             End If
  578.             P = P + 1
  579.         Wend
  580.         If R <> 0 Then freqac(0) = freqac(0) + 1   'EOB Symbol
  581.     Wend
  582.  
  583. End Sub
  584. Private Sub CollectStatisticsDCNonInterleaved(Data() As Integer, freqdc() As Long)
  585.     Dim Diff  As Long     'DC Difference
  586.     Dim Pred  As Long     'DC Predictor
  587.     Dim n     As Long     'Number of coefficients in data()
  588.     Dim P     As Long     'Index for current data() coefficient
  589.     Dim S     As Long     'Size category for Diff
  590.  
  591.  
  592.     n = UBound(Data) + 1
  593.     P = 0
  594.     Pred = 0
  595.     While P <> n
  596.         Diff = Data(P) - Pred
  597.         Pred = Data(P)
  598.  
  599.         If Diff < 0 Then 's = number of bits needed for Diff
  600.             S = Int((Log(-Diff) * 1.442695040889)) + 1   '1/log(2)  (+ error correction)
  601.         ElseIf Diff > 0 Then
  602.             S = Int((Log(Diff) * 1.442695040889)) + 1    '1/log(2) + (error correction)
  603.         Else
  604.             S = 0
  605.         End If
  606.  
  607.         freqdc(S) = freqdc(S) + 1
  608.         P = P + 64
  609.     Wend
  610.  
  611. End Sub
  612. Private Sub CollectStatisticsDCInterleaved(Data() As Integer, freqdc() As Long, Hi As Long, Vi As Long)
  613.     Dim P()       As Long     'Index to .data in component f for scanline g
  614.     Dim f         As Long      'Index counter  (component)
  615.     Dim G         As Long      'Index counter  (sampling factor, vertical)
  616.     Dim H         As Long      'Index counter  (sampling factor, horizontal)
  617.     Dim I         As Long      'Index counter  (MCU horizontal)
  618.     Dim J         As Long      'Index counter  (MCU vertical)
  619.     Dim n         As Long      'Number of coefficients in data()
  620.     Dim S         As Long      'Size category for Diff
  621.     Dim Diff      As Long      'DC Difference
  622.     Dim Pred      As Long      'DC Predictor
  623.     Dim pLF       As Long      'Line Feed for p in data
  624.     Dim MCUr      As Long      'Number of complete 8X8 blocks in rightmost MCU
  625.     Dim MCUx      As Long      'Number of MCUs per scanline
  626.     Dim MCUy      As Long      'Number of MCU scanlines
  627.  
  628.  
  629.     n = UBound(Data) + 1
  630.     ReDim P(Vi - 1)
  631.  
  632.  
  633.     MCUx = (XX + 8 * HMax - 1) \ (8 * HMax)
  634.     MCUy = (YY + 8 * VMax - 1) \ (8 * VMax)
  635.  
  636.     H = (-Int(-XX * Hi / HMax) + 7) \ 8  'Width of scanline in data (MCUs)
  637.  
  638.     For G = 0 To Vi - 1                  'Initialize .data pointers
  639.         P(G) = 64 * H * G
  640.     Next G
  641.     pLF = 64 * H * (Vi - 1)              'Initialize .data pointer advancer
  642.  
  643.     MCUr = (H Mod Hi)                    'Number of complete 8X8 Blocks in rightmost MCU
  644.     If MCUr = 0 Then MCUr = Hi
  645.  
  646.     For J = 1 To MCUy - 1
  647.  
  648.        'MCUs across a scanline
  649.         For I = 1 To MCUx - 1
  650.         For G = 1 To Vi
  651.         For H = 1 To Hi
  652.  
  653.         Diff = Data(P(G - 1)) - Pred
  654.         Pred = Data(P(G - 1))
  655.         P(G - 1) = P(G - 1) + 64
  656.         If Diff < 0 Then 's = number of bits needed for Diff
  657.             S = Int((Log(-Diff) * 1.442695040889)) + 1   '1/log(2)  (+ error correction)
  658.         ElseIf Diff > 0 Then
  659.             S = Int((Log(Diff) * 1.442695040889)) + 1    '1/log(2) + (error correction)
  660.         Else
  661.             S = 0
  662.         End If
  663.         freqdc(S) = freqdc(S) + 1
  664.  
  665.         Next H
  666.         Next G
  667.         Next I
  668.  
  669.        'Rightmost MCU
  670.         For G = 1 To Vi
  671.         For H = 1 To Hi
  672.         If H > MCUr Then  'Pad with dummy block
  673.             S = 0
  674.         Else
  675.             Diff = Data(P(G - 1)) - Pred
  676.             Pred = Data(P(G - 1))
  677.             P(G - 1) = P(G - 1) + 64
  678.  
  679.             If Diff < 0 Then
  680.                 S = Int((Log(-Diff) * 1.442695040889)) + 1
  681.             ElseIf Diff > 0 Then
  682.                 S = Int((Log(Diff) * 1.442695040889)) + 1
  683.             Else
  684.                 S = 0
  685.             End If
  686.         End If
  687.         freqdc(S) = freqdc(S) + 1
  688.         Next H
  689.         Next G
  690.  
  691.        'Advance data pointers
  692.         For G = 0 To Vi - 1
  693.             P(G) = P(G) + pLF
  694.         Next G
  695.     Next J
  696.  
  697.  
  698.    'Bottommost MCU Scanline
  699.     For I = 1 To MCUx
  700.     For G = 1 To Vi
  701.     For H = 1 To Hi
  702.     If P(G - 1) >= n Or (I = MCUx And H > MCUr) Then 'Pad with dummy block
  703.         S = 0
  704.     Else
  705.         Diff = Data(P(G - 1)) - Pred
  706.         Pred = Data(P(G - 1))
  707.         P(G - 1) = P(G - 1) + 64
  708.  
  709.         If Diff < 0 Then
  710.             S = Int((Log(-Diff) * 1.442695040889)) + 1
  711.         ElseIf Diff > 0 Then
  712.             S = Int((Log(Diff) * 1.442695040889)) + 1
  713.         Else
  714.             S = 0
  715.         End If
  716.     End If
  717.     freqdc(S) = freqdc(S) + 1
  718.     Next H
  719.     Next G
  720.     Next I
  721.  
  722. End Sub
  723.  
  724.  
  725.  
  726.  
  727. '========================================================================================
  728. '                                Q U A N T I Z A T I O N
  729. '========================================================================================
  730. Private Sub ExpandDQT(Tqi As Long)
  731.     Dim I          As Long
  732.     Dim J          As Long
  733.     Dim k          As Byte
  734.     Dim maxvalue   As Long
  735.  
  736.     With QTable(Tqi)
  737.         If PP = 12 Then
  738.             maxvalue = 65535
  739.         Else
  740.             maxvalue = 255
  741.         End If
  742.  
  743.         For I = 0 To 7
  744.             For J = 0 To 7
  745.                 k = ZigZag(I, J)
  746.                 If .Qk(k) < 1 Or .Qk(k) > maxvalue Then Err.Raise 1, , "Bad Quantization Table"
  747.                .FScale(k) = FDCTScale(I) * FDCTScale(J) / CDbl(.Qk(k))
  748.             Next J
  749.         Next I
  750.     End With
  751.  
  752. End Sub
  753. Private Sub Quantize(Data() As Integer, P As Long, FScale() As Single)
  754.     Dim I As Long  'Take 8X8 block of unscaled DCT coefficients [m_Block(0-7, 0-7)],
  755.     Dim J As Long  'Scale, Quantize, and store the results in data() array of
  756.     Dim T As Long  'COMPONENT in Zig Zag order at index p
  757.  
  758.  
  759.     For J = 0 To 7
  760.         For I = 0 To 7
  761.             T = ZigZag(I, J)
  762.             Data(P + T) = m_Block(I, J) * FScale(T)
  763.         Next I
  764.     Next J
  765.     P = P + 64
  766.  
  767. End Sub
  768. Friend Property Let Quality(vData As Long)
  769. 'The JPEG compression standard does not have a formal definition for image Quality.
  770. 'This implementation defines Quality as an integer value between 1 and 100, and
  771. 'generates quantization tables based on the value given.
  772. '
  773. 'Quality < 50  -  Poor image quality with high compression
  774. 'Quality = 75  -  Good quality pictures for displaying on a monitor or web page ... typical for general use
  775. 'Quality = 92  -  High quality with non-optimal compression ... Appropriate for printing ... [typical digital camera "max quality" setting]
  776. 'Quality > 95  -  Wasteful ... very poor compression with little image quality improvement.  Use 24-bit BMP TrueColor if you need quality this high.
  777.  
  778.     Dim I           As Long
  779.     Dim qvalue      As Long
  780.     Dim maxvalue    As Long
  781.     Dim scalefactor As Long
  782.  
  783.     maxvalue = 255 '32767 if 16 bit quantum is allowed
  784.  
  785.     If vData > 0 And vData <= 100 Then
  786.         m_Quality = vData
  787.  
  788.         If (m_Quality < 50) Then
  789.             If m_Quality <= 0 Then
  790.                 scalefactor = 5000
  791.             Else
  792.                 scalefactor = 5000 / m_Quality
  793.             End If
  794.         Else
  795.             If m_Quality > 100 Then
  796.                 scalefactor = 0
  797.             Else
  798.                 scalefactor = 200 - m_Quality * 2
  799.             End If
  800.         End If
  801.  
  802.         With QTable(0)
  803.             For I = 0 To 63
  804.                 qvalue = (QLumin(I) * scalefactor + 50) / 100
  805.                 If qvalue <= 0 Then
  806.                     qvalue = 1
  807.                 ElseIf qvalue > maxvalue Then
  808.                     qvalue = maxvalue
  809.                 End If
  810.                 .Qk(I) = qvalue
  811.             Next I
  812.         End With
  813.         With QTable(1)
  814.             For I = 0 To 63
  815.                 qvalue = (QChrom(I) * scalefactor + 50) / 100
  816.                 If qvalue <= 0 Then
  817.                     qvalue = 1
  818.                 ElseIf qvalue > maxvalue Then
  819.                     qvalue = maxvalue
  820.                 End If
  821.                 .Qk(I) = qvalue
  822.             Next I
  823.         End With
  824.  
  825.         ExpandDQT 0
  826.         ExpandDQT 1
  827.     End If
  828.  
  829. End Property
  830. Friend Property Get Quality() As Long
  831.     Quality = m_Quality
  832. End Property
  833.  
  834.  
  835.  
  836.  
  837.  
  838. '================================================================================
  839. '                           I M A G E   S A M P L I N G
  840. '================================================================================
  841. Friend Sub SetSamplingFrequencies(H1 As Long, V1 As Long, H2 As Long, V2 As Long, H3 As Long, V3 As Long)
  842.  
  843. 'This class always samples and compresses pictures in YCbCr colorspace.  The first component, Y,
  844. 'represents the Luminance of the pixels.  This is "how bright" a pixel is.  The Cb and Cr
  845. 'components are Chrominance, which is a measure of how far from neutral-white (toward a color)
  846. 'a pixel is.  The human visual sensory system can discriminate Luminance differences about
  847. 'twice as well as it can discriminate Chrominance differences.
  848. '
  849. 'Virtually all JPEG files are in YCbCr colorspace.  Other JPEG compliant colorspaces exist, but
  850. 'they are used in specialty equipment.  For example, people in the astronomy or medical fields
  851. 'choose colorspaces that best record the information they are interested in, and don't care about
  852. 'how pretty the picture looks to a person when displayed on a computer monitor.
  853. '[Apple/Machintosh sometimes uses a four component colorspace, but that colorspace is rare and
  854. 'not widely supported]
  855. '
  856. 'Sampling frequencies define how often each component is sampled.  Higher frequencies store more
  857. 'information, while lower frequencies store less.  Typically, sampling frequencies are set at
  858. '2,2, 1,1, 1,1.  This corresponds to the human visual sensory system.  The first component,
  859. 'Luminance, is sampled twice as much because our eyes notice differences in Luminance quite easily.
  860. 'The two Chrominance components are sampled half as much as because our eyes can't distinguish
  861. 'the difference in color changes as well.  One Luminance value is sampled for every pixel, and
  862. 'one Chrominance value is sampled for each 2X2 block of pixels.
  863. '
  864. 'Digital cameras typically record at sampling frequencies of 1,1, 1,1, 1,1.  This samples every
  865. 'pixel for all three components.  The quality of the picture is a little better when viewed by
  866. 'a person, but the compression benefits drop significantly.  If the picture to be compressed
  867. 'is from a Scanner or Digital camera, and you plan on printing it in the future, and storage
  868. 'space is not a problem, then sampling at these frequencies makes sense.  Otherwise, if you only
  869. 'plan on using the picture to display on a monitor or a web page, [2,2, 1,1, 1,1] makes the
  870. 'most sense.
  871. '
  872. 'The JPEG standard specifies that sampling frequencies may range from 1-4 for each component
  873. 'in both directions.  However, if any component has a sampling frequency of '3', and another
  874. 'component has a coresponding sampling frequency of '2' or '4', the downsampling process
  875. 'will map fractional pixels to sample values.  This is leagal in the JPEG standard, and this
  876. 'class will compress fractional pixel samplings, but this is not widely supported.  It is
  877. 'highly recommended to AVOID SAMPLING FACTORS OF 3 for maximum compatability with JPEG decoders.
  878. '
  879. 'Some JPEG encoders avoid the fractional pixel problem by only allowing the end user to pick
  880. 'a "sub-sampling" value.  In such "Sub Sampling" schemes, all Chrominance frequencies are set
  881. 'to one, and the (one or two) sub-sampling value(s) specify Luminance frequencies.
  882. '
  883. 'There should *never* be an error raised if you are using this class correctly.  It should
  884. 'not be possible for the end user to specify illegal sampling frequency values!
  885. '[For tinkerers - If you delete the error raising code and specify illegal sampling
  886. 'frequencies, this class will procede to create a non-JPEG compliant file with the values
  887. 'specified]
  888.  
  889.     Dim I As Long
  890.  
  891.     If H1 < 1 Or H1 > 4 Then Err.Raise 1, , "Invalid Sampling Value"
  892.     If V1 < 1 Or V1 > 4 Then Err.Raise 1, , "Invalid Sampling Value"
  893.  
  894.     If (H2 Or H3 Or V2 Or V3) = 0 Then  'if H2,H3,V2,V3 are all zero ...
  895.         Nf = 1         'Luminance only.
  896.         ReDim Comp(0)
  897.         Comp(0).Hi = 1 'Set up for sampling Greyscale
  898.         Comp(0).Vi = 1 '(Black and White picture)
  899.     Else
  900.         If H2 < 1 Or H2 > 4 Then Err.Raise 1, , "Invalid Sampling Value"
  901.         If H3 < 1 Or H3 > 4 Then Err.Raise 1, , "Invalid Sampling Value"
  902.         If V2 < 1 Or V2 > 4 Then Err.Raise 1, , "Invalid Sampling Value"
  903.         If V3 < 1 Or V3 > 4 Then Err.Raise 1, , "Invalid Sampling Value"
  904.         Nf = 3         'YCbCr
  905.         ReDim Comp(2)
  906.         Comp(0).Hi = H1
  907.         Comp(0).Vi = V1
  908.         Comp(0).Tqi = 0
  909.         Comp(1).Hi = H2
  910.         Comp(1).Vi = V2
  911.         Comp(1).Tqi = 1
  912.         Comp(2).Hi = H3
  913.         Comp(2).Vi = V3
  914.         Comp(2).Tqi = 1
  915.     End If
  916.  
  917.     HMax = -1
  918.     VMax = -1
  919.     For I = 0 To Nf - 1 'determine max h, v sampling factors
  920.         If HMax < Comp(I).Hi Then HMax = Comp(I).Hi
  921.         If VMax < Comp(I).Vi Then VMax = Comp(I).Vi
  922.     Next I
  923.  
  924. End Sub
  925.  
  926. Friend Function SampleHDC(ByVal lHDC As Long, lWidth As Long, lHeight As Long, Optional lSrcLeft As Long, Optional lSrcTop As Long) As Long
  927. 'Given a valid hDC and dimensions, generate component samplings of an Image.
  928. 'A DIBSection is created to hold Sample(s) of the Image, from which the Image is
  929. 'decomposed into YCbCr components.
  930. 'Returns: 0 = Success
  931. '         1 = API error while generating a DIBSection
  932.     Dim hDIb       As Long    'Handle to the DIBSection
  933.     Dim hBmpOld    As Long    'Handle to the old bitmap in the DC, for clear up
  934.     Dim hdc        As Long    'Handle to the Device context holding the DIBSection
  935.     Dim lPtr       As Long    'Address of memory pointing to the DIBSection's bits
  936.     Dim BI         As BITMAPINFO 'Type containing the Bitmap information
  937.     Dim sA         As SAFEARRAY2D
  938.     Dim Pixel()    As Byte   'Byte array containing pixel data
  939.     Dim f          As Long   'Index counter for components
  940.     Dim qp         As Long   'Index for quantized FDCT value (in component data)
  941.     Dim rm         As Single 'Scale factor for red   pixel when converting RGB->YCbCr
  942.     Dim gm         As Single 'Scale factor for green pixel when converting RGB->YCbCr
  943.     Dim bm         As Single 'Scale factor for blue  pixel when converting RGB->YCbCr
  944.     Dim S          As Single 'Level shift value             for converting RGB->YCbCr
  945.     Dim xi         As Long   'Sample width
  946.     Dim yi         As Long   'Sample height
  947.     Dim xi2        As Long   'Sample width  (for previous component)
  948.     Dim yi2        As Long   'Sample height (for previous component)
  949.     Dim xi8        As Long   'Sample width  (padded to 8 pixel barrier)
  950.     Dim yi8        As Long   'Sample height (padded to 8 pixel barrier)
  951.     Dim i0         As Long   'Left index of an 8X8 block of pixels
  952.     Dim j0         As Long   'Top  index of an 8X8 block of pixels
  953.     Dim I          As Long   'Pixel Index (Horizontal)
  954.     Dim J          As Long   'Pixel Index (Vertical)
  955.     Dim P          As Long   'DCT Index (horizontal)
  956.     Dim q          As Long   'DCT Index (vertical)
  957.  
  958.  
  959.     PP = 8
  960.     YY = lHeight
  961.     XX = lWidth
  962.  
  963.    'Create a DIBSection to store Sampling(s) of the Image
  964.     hdc = CreateCompatibleDC(0)
  965.     If hdc = 0 Then
  966.         SampleHDC = 1 'CreateCompatibleDC() API Failure
  967.     Else
  968.         With BI.bmiHeader
  969.             .biSize = Len(BI.bmiHeader)
  970.             .biWidth = (lWidth + 7) And &HFFFFFFF8   '8 byte barrier for 8X8 data units
  971.             .biHeight = (lHeight + 7) And &HFFFFFFF8
  972.             .biPlanes = 1
  973.             .biBitCount = 24
  974.             .biCompression = BI_RGB
  975.             .biSizeImage = ((.biWidth * 3 + 3) And &HFFFFFFFC) * .biHeight '4 byte barrier
  976.         End With
  977.         hDIb = CreateDIBSection2(hdc, BI, DIB_RGB_COLORS, lPtr, 0, 0)
  978.         If hDIb = 0 Then
  979.             SampleHDC = 1 'CreateDIBSection2() API Failure
  980.         Else
  981.             With sA                        'This code copies the pointer of the 2-D bitmap
  982.                 .cbElements = 1            'pixel data to the pointer of the Pixel() array.
  983.                 .cDims = 2                 'This allows you to read/modify the pixel data
  984.                 .Bounds(0).lLbound = 0     'as if it were stored in the Pixel() array.
  985.                 .Bounds(0).cElements = BI.bmiHeader.biHeight
  986.                 .Bounds(1).lLbound = 0
  987.                 .Bounds(1).cElements = ((BI.bmiHeader.biWidth * 3 + 3) And &HFFFFFFFC)
  988.                 .pvData = lPtr             'Note that this is extreamly efficient, since it copies
  989.             End With                       'a pointer to the data, and not the data itself.
  990.             hBmpOld = SelectObject(hdc, hDIb) 'Select DIBSection into DC
  991.             If SetStretchBltMode(hdc, HALFTONE) = 0 Then SetStretchBltMode hdc, COLORONCOLOR
  992.  
  993.  
  994.     For f = 0 To Nf - 1
  995.         Select Case f 'Select scaling factors for RGB->YCbCr conversion for this component
  996.         Case 0 'Luminance
  997.             rm = 0.299
  998.             gm = 0.587
  999.             bm = 0.114
  1000.             S = -128
  1001.         Case 1 'Chrominance [Blue-Yellow]
  1002.             rm = -0.16874
  1003.             gm = -0.33126
  1004.             bm = 0.5
  1005.             S = 0
  1006.         Case 2 'Chrominance [Red-Green]
  1007.             rm = 0.5
  1008.             gm = -0.41869
  1009.             bm = -0.08131
  1010.             S = 0
  1011.         End Select
  1012.  
  1013.         With Comp(f)
  1014.            .Ci = f + 1 'Assign an ID to this component
  1015.  
  1016.             xi = -Int(-XX * .Hi / HMax)        'determine Sample dimensions
  1017.             yi = -Int(-YY * .Vi / VMax)
  1018.             xi8 = ((xi + 7) And &HFFFFFFF8)    'Sample dimensions with 8X8 barrier
  1019.             yi8 = ((yi + 7) And &HFFFFFFF8)
  1020.             ReDim .Data(xi8 * yi8 - 1)
  1021.  
  1022.             If xi8 <> xi2 Or yi8 <> yi2 Then  'We need to Sample the Image
  1023.                 If xi = XX And yi = YY Then 'Just copy the image to our DIBSection
  1024.                     BitBlt hdc, 0, BI.bmiHeader.biHeight - yi8, xi, yi, lHDC, lSrcLeft, lSrcTop, vbSrcCopy
  1025.                 Else                        'Resample/Resize the Image
  1026.                     StretchBlt hdc, 0, BI.bmiHeader.biHeight - yi8, xi, yi, lHDC, lSrcLeft, lSrcTop, lWidth, lHeight, vbSrcCopy
  1027.                 End If
  1028.                 For I = xi To xi8 - 1  'Pad right of Sample to 8 block barrier
  1029.                     BitBlt hdc, I, BI.bmiHeader.biHeight - yi8, 1, yi, hdc, I - 1, BI.bmiHeader.biHeight - yi8, vbSrcCopy
  1030.                 Next I
  1031.                 For J = BI.bmiHeader.biHeight - (yi8 - yi) To BI.bmiHeader.biHeight - 1 'Pad bottom of Sample to 8 block barrier
  1032.                     BitBlt hdc, 0, J, xi8, 1, hdc, 0, J - 1, vbSrcCopy
  1033.                 Next J
  1034.             End If
  1035.             xi2 = xi8
  1036.             yi2 = yi8
  1037.             qp = 0 'Reset output Quantized FDCT Coefficient Index
  1038.  
  1039.            'Read 8X8 blocks of pixels, convert from RGB->YCbCr colorspace, FDCT and Quantize
  1040.            'the data, store the results in .data of this component
  1041.             CopyMemory ByVal VarPtrArray(Pixel), VarPtr(sA), 4& 'Get Pixel array descriptor
  1042.             J = yi8 - 1
  1043.             While J > 0               'Scan from top to bottom (j = -1 after loop)
  1044.                 I = 0
  1045.                 j0 = J
  1046.                 While I < 3 * xi8     'Scan from left to right (i = 3*xi8 after loop)
  1047.                     J = j0
  1048.                     i0 = I
  1049.                     For P = 0 To 7    'Get 8X8 block of level shifted YCbCr values
  1050.                         I = i0
  1051.                         For q = 0 To 7
  1052.                             m_Block(q, P) = rm * Pixel(I + 2, J) + _
  1053.                                             gm * Pixel(I + 1, J) + _
  1054.                                             bm * Pixel(I, J) + S
  1055.                             I = I + 3
  1056.                         Next q
  1057.                         J = J - 1
  1058.                     Next P
  1059.                     FDCT                               'Calculate the FDCT
  1060.                     Quantize .Data, qp, QTable(.Tqi).FScale   'Quantize, and store in DCT buffer
  1061.                 Wend
  1062.             Wend
  1063.             CopyMemory ByVal VarPtrArray(Pixel), 0&, 4 'Clear the Pixel array descriptor
  1064.         End With
  1065.     Next f
  1066.  
  1067.  
  1068.             SelectObject hdc, hBmpOld 'Select CompatibleDC  (unselect DIBSection)
  1069.             DeleteObject hDIb         'Delete DIBSection
  1070.         End If
  1071.         DeleteObject hdc              'Delete CompatibleDC
  1072.     End If
  1073.  
  1074. End Function
  1075.  
  1076.  
  1077.  
  1078. Friend Property Let Comment(Value As String)
  1079.    'Assigning a value to this property will add the text Comment to the JPEG file.
  1080.     If Len(Value) > 65535 Then Err.Raise 1, , "Illegal Comment Length"
  1081.     m_Comment = Value
  1082. End Property
  1083. Friend Property Get Comment() As String
  1084.     Comment = m_Comment
  1085. End Property
  1086.  
  1087.  
  1088.  
  1089.  
  1090. '================================================================================
  1091. '                         E M I T I N G   M A R K E R S
  1092. '================================================================================
  1093. Private Sub InsertJFIF()
  1094.     If m_Ptr + 17 > UBound(m_Data) Then Err.Raise 9 'Copymemory will write past bounds of m_Data()
  1095.  
  1096.     CopyMemory m_Data(m_Ptr + 0), &H1000E0FF, 4&    'APP0 Marker, Length(APP0)=16
  1097.     CopyMemory m_Data(m_Ptr + 4), &H4649464A, 4&    '"JFIF"
  1098.     CopyMemory m_Data(m_Ptr + 8), &H10100, 4&       '"/0", Version Major=1, Version Minor=1
  1099.                                                     'Units=0  [0=pixel, 1=dpi, 2=dots/cm]
  1100.     CopyMemory m_Data(m_Ptr + 12), &H1000100, 4&    'Horizontal pixel density = 1 (dot per pixel)
  1101.                                                     'Vertical   pixel density = 1 (dot per pixel)
  1102.     CopyMemory m_Data(m_Ptr + 16), &H0&, 2&         'Thumbnail horizontal pixel count = 0
  1103.     m_Ptr = m_Ptr + 18                              'Thumbnail vertical   pixel count = 0
  1104.  
  1105. End Sub
  1106. Private Sub InsertSOF(SOFMarker As Long)
  1107.     Dim I   As Long 'Insert a Start Of Frame marker segment
  1108.     Dim lx  As Long 'PP, YY, XX, Nf, and Ci,Hi,Vi,Tqi, must already be set
  1109.  
  1110.     lx = 8 + 3 * Nf
  1111.     m_Data(m_Ptr) = 255                    'SOF
  1112.     m_Data(m_Ptr + 1) = SOFMarker And 255
  1113.     m_Data(m_Ptr + 2) = lx \ 256           'Frame Header Length
  1114.     m_Data(m_Ptr + 3) = lx And 255
  1115.     m_Data(m_Ptr + 4) = PP                 'Sample precision [8, 12]
  1116.     m_Data(m_Ptr + 5) = YY \ 256           'Number of Lines
  1117.     m_Data(m_Ptr + 6) = YY And 255
  1118.     m_Data(m_Ptr + 7) = XX \ 256           'Number of samples per line
  1119.     m_Data(m_Ptr + 8) = XX And 255
  1120.     m_Data(m_Ptr + 9) = Nf                 'Number of image components in frame
  1121.     m_Ptr = m_Ptr + 10
  1122.     For I = 0 To Nf - 1                      'For each component ...
  1123.         With Comp(I)
  1124.             m_Data(m_Ptr) = .Ci                  'Component identifier
  1125.             m_Data(m_Ptr + 1) = .Hi * 16 Or .Vi  'Horizontal/Vertical sampling factors
  1126.             m_Data(m_Ptr + 2) = .Tqi             'Quantization table selector
  1127.         End With
  1128.         m_Ptr = m_Ptr + 3
  1129.     Next I
  1130. End Sub
  1131. Private Sub InsertCOM(TheComment As String)
  1132.     Dim I As Long
  1133.     Dim lx As Long
  1134.  
  1135.     lx = Len(TheComment) + 2
  1136.     If lx > 2 Then
  1137.         m_Data(m_Ptr) = 255               'COM marker
  1138.         m_Data(m_Ptr + 1) = COM
  1139.         m_Data(m_Ptr + 2) = lx \ 256      'COM marker segment length
  1140.         m_Data(m_Ptr + 3) = lx And 255
  1141.         m_Ptr = m_Ptr + 4
  1142.         For I = 1 To Len(TheComment)      'Comment text
  1143.             m_Data(m_Ptr) = Asc(Mid$(TheComment, I, 1))
  1144.             m_Ptr = m_Ptr + 1
  1145.         Next I
  1146.     End If
  1147. End Sub
  1148. Private Sub InsertDQT(ByVal MarkerPos As Long, Tqi As Long)
  1149.     Dim I As Long 'Call with MarkerPos = m_Ptr to insert a single table with its own DQT marker
  1150.                   'Call multiple times with the same MarkerPos to include
  1151.                   'multiple tables under the same DQT marker
  1152.  
  1153.     If m_Ptr < MarkerPos + 4 Then 'Insert Marker
  1154.         m_Ptr = MarkerPos + 4
  1155.         m_Data(m_Ptr - 4) = 255
  1156.         m_Data(m_Ptr - 3) = DQT
  1157.     End If
  1158.     With QTable(Tqi)
  1159.         For I = 0 To 63
  1160.             If .Qk(I) > 255 Then Exit For
  1161.         Next I
  1162.         If I = 64 Then              '8 bit precision
  1163.             m_Data(m_Ptr) = Tqi
  1164.             m_Ptr = m_Ptr + 1
  1165.             For I = 0 To 63
  1166.                 m_Data(m_Ptr) = .Qk(I)
  1167.                 m_Ptr = m_Ptr + 1
  1168.             Next I
  1169.         Else                        '16 bit precision
  1170.             If PP <> 12 Then Err.Raise 1, , "Illegal precission in Quantization Table"
  1171.             m_Data(m_Ptr) = Tqi Or 16
  1172.             m_Ptr = m_Ptr + 1
  1173.             For I = 0 To 63
  1174.                 m_Data(m_Ptr) = .Qk(I) \ 256
  1175.                 m_Data(m_Ptr + 1) = .Qk(I) And 255
  1176.                 m_Ptr = m_Ptr + 2
  1177.             Next I
  1178.         End If
  1179.     End With
  1180.  
  1181.     m_Data(MarkerPos + 2) = (m_Ptr - MarkerPos - 2) \ 256& 'Insert Marker segment length
  1182.     m_Data(MarkerPos + 3) = (m_Ptr - MarkerPos - 2) And 255&
  1183. End Sub
  1184. Private Sub InsertDHT(ByVal MarkerPos As Long, HIndex As Long, IsAC As Boolean)
  1185.     Dim I As Long 'Call with MarkerPos = m_Ptr to insert a single table with its own DHT marker
  1186.     Dim J As Long 'Call multiple times with the same MarkerPos to include
  1187.                   'multiple tables under the same DHT marker
  1188.  
  1189.     If m_Ptr < MarkerPos + 4 Then 'Insert Marker
  1190.         m_Ptr = MarkerPos + 4
  1191.         m_Data(m_Ptr - 4) = 255
  1192.         m_Data(m_Ptr - 3) = DHT
  1193.     End If
  1194.     If IsAC Then
  1195.         With HuffAC(HIndex)
  1196.             m_Data(m_Ptr) = HIndex Or 16
  1197.             m_Ptr = m_Ptr + 1
  1198.             J = 0
  1199.             For I = 0 To 15
  1200.                 m_Data(m_Ptr) = .Bits(I)
  1201.                 m_Ptr = m_Ptr + 1
  1202.                 J = J + .Bits(I)
  1203.             Next I
  1204.             For I = 0 To J - 1
  1205.                 m_Data(m_Ptr) = .HUFFVAL(I)
  1206.                 m_Ptr = m_Ptr + 1
  1207.             Next I
  1208.         End With
  1209.     Else
  1210.         With HuffDC(HIndex)
  1211.             m_Data(m_Ptr) = HIndex
  1212.             m_Ptr = m_Ptr + 1
  1213.             J = 0
  1214.             For I = 0 To 15
  1215.                 m_Data(m_Ptr) = .Bits(I)
  1216.                 m_Ptr = m_Ptr + 1
  1217.                 J = J + .Bits(I)
  1218.             Next I
  1219.             For I = 0 To J - 1
  1220.                 m_Data(m_Ptr) = .HUFFVAL(I)
  1221.                 m_Ptr = m_Ptr + 1
  1222.             Next I
  1223.         End With
  1224.     End If
  1225.  
  1226.     m_Data(MarkerPos + 2) = (m_Ptr - MarkerPos - 2) \ 256& 'Insert Marker segment length
  1227.     m_Data(MarkerPos + 3) = (m_Ptr - MarkerPos - 2) And 255&
  1228. End Sub
  1229. Private Sub InsertMarker(TheMarker As Long)
  1230.     m_Data(m_Ptr) = 255
  1231.     m_Data(m_Ptr + 1) = TheMarker
  1232.     m_Ptr = m_Ptr + 2
  1233. End Sub
  1234.  
  1235.  
  1236.  
  1237.  
  1238. '================================================================================
  1239. '                           E M I T I N G   S C A N S
  1240. '================================================================================
  1241. Private Sub InsertSOSNonInterleaved(CompIndex As Long, Td As Long, Ta As Long)
  1242. 'Insert an SOS marker and scan data for a non-interleaved Sequential scan.
  1243.     Dim P         As Long     'Index to .data in component
  1244.     Dim n         As Long
  1245.     Dim Pred      As Long     'Predictor for DC coefficient
  1246.  
  1247.  
  1248.    'Insert SOS Marker Segment
  1249.     m_Data(m_Ptr) = 255                          'SOS Marker
  1250.     m_Data(m_Ptr + 1) = SOS
  1251.     m_Data(m_Ptr + 2) = 8 \ 256                  'Marker Segment Length
  1252.     m_Data(m_Ptr + 3) = 8 And 255
  1253.     m_Data(m_Ptr + 4) = 1                        'Ns     - Number of components in Scan [1-4]
  1254.     m_Ptr = m_Ptr + 5
  1255.     m_Data(m_Ptr) = Comp(CompIndex).Ci           'Csj    - Component ID
  1256.     m_Data(m_Ptr + 1) = Td * 16 Or Ta            'Td, Ta - DC, AC entropy coder selector
  1257.     m_Ptr = m_Ptr + 2
  1258.     m_Data(m_Ptr) = 0                            'Ss     - Start of spectral selection
  1259.     m_Data(m_Ptr + 1) = 63                       'Se     - End of spectral selection
  1260.     m_Data(m_Ptr + 2) = 0                        'Ah, Al - Successive approximation bit high/low
  1261.     m_Ptr = m_Ptr + 3
  1262.  
  1263.    'Insert non-interleaved sequential entropy coded data
  1264.     With Comp(CompIndex)
  1265.  
  1266.         P = 0
  1267.         n = UBound(.Data) + 1
  1268.         Pred = 0
  1269.  
  1270.         WriteBitsBegin
  1271.         While P <> n
  1272.             EncodeCoefficients .Data, P, Pred, Td, Ta
  1273.         Wend
  1274.         WriteBitsEnd
  1275.  
  1276.     End With
  1277.  
  1278. End Sub
  1279.  
  1280. Private Sub InsertSOSInterleaved(CompIndex() As Long, Td() As Long, Ta() As Long, FirstIndex As Long, SecondIndex As Long)
  1281. 'Insert an SOS marker and scan data for an interleaved Sequential scan.
  1282.  
  1283.     Dim f         As Long      'Index counter  (component)
  1284.     Dim G         As Long      'Index counter  (sampling factor, vertical)
  1285.     Dim H         As Long      'Index counter  (sampling factor, horizontal)
  1286.     Dim I         As Long      'Index counter  (MCU horizontal)
  1287.     Dim J         As Long      'Index counter  (MCU vertical)
  1288.     Dim lx        As Long      'Marker Segment Length
  1289.     Dim Ns        As Long      'Number of components in Scan [1-4]
  1290.     Dim MCUx      As Long      'Number of MCUs per scanline
  1291.     Dim MCUy      As Long      'Number of MCU scanlines
  1292.  
  1293.     Dim P()        As Long     'Index to .data in component f for scanline g
  1294.     Dim pLF()      As Long     'Line Feed for p in .data for component f
  1295.     Dim Pred()     As Long     'Predictor for DC coefficient in component f
  1296.     Dim MCUr()     As Long     'Number of complete 8X8 blocks in rightmost MCU for component f
  1297.     Dim Pad64(63)  As Integer  '8X8 padding block for completing MCUs
  1298.  
  1299.  
  1300.     Ns = SecondIndex - FirstIndex + 1
  1301.     lx = 6 + 2 * Ns
  1302.  
  1303.    'Insert SOS Marker Segment
  1304.     m_Data(m_Ptr) = 255                          'SOS Marker
  1305.     m_Data(m_Ptr + 1) = SOS
  1306.     m_Data(m_Ptr + 2) = lx \ 256                 'Marker Segment Length
  1307.     m_Data(m_Ptr + 3) = lx And 255
  1308.     m_Data(m_Ptr + 4) = Ns                       'Ns     - Number of components in Scan [1-4]
  1309.     m_Ptr = m_Ptr + 5
  1310.     For I = FirstIndex To SecondIndex
  1311.         m_Data(m_Ptr) = Comp(CompIndex(I)).Ci   'Csj
  1312.         m_Data(m_Ptr + 1) = Td(I) * 16 Or Ta(I) 'Td, Ta
  1313.         m_Ptr = m_Ptr + 2
  1314.     Next I
  1315.     m_Data(m_Ptr) = 0                            'Ss     - Start of spectral selection
  1316.     m_Data(m_Ptr + 1) = 63                       'Se     - End of spectral selection
  1317.     m_Data(m_Ptr + 2) = 0                        'Ah, Al - Successive approximation bit high/low
  1318.     m_Ptr = m_Ptr + 3
  1319.  
  1320.  
  1321.    'Insert interleaved sequential entropy coded data
  1322.     ReDim P(FirstIndex To SecondIndex, VMax - 1)
  1323.     ReDim Pred(FirstIndex To SecondIndex)
  1324.     ReDim pLF(FirstIndex To SecondIndex)
  1325.     ReDim MCUr(FirstIndex To SecondIndex)
  1326.  
  1327.     MCUx = (XX + 8 * HMax - 1) \ (8 * HMax)
  1328.     MCUy = (YY + 8 * VMax - 1) \ (8 * VMax)
  1329.  
  1330.     For f = FirstIndex To SecondIndex
  1331.         With Comp(CompIndex(f))
  1332.             H = (-Int(-XX * .Hi / HMax) + 7) \ 8  'Width of scanline in .data (MCUs)
  1333.  
  1334.             For G = 0 To .Vi - 1                  'Initialize .data pointers
  1335.                 P(f, G) = 64 * H * G
  1336.             Next G
  1337.             pLF(f) = 64 * H * (.Vi - 1)           'Initialize .data pointer advancer
  1338.  
  1339.             MCUr(f) = (H Mod .Hi)                 'Number of complete 8X8 Blocks in rightmost MCU
  1340.             If MCUr(f) = 0 Then MCUr(f) = .Hi
  1341.         End With
  1342.     Next f
  1343.  
  1344.     WriteBitsBegin
  1345.     For J = 1 To MCUy - 1
  1346.  
  1347.        'Encode MCUs across a scanline
  1348.         For I = 1 To MCUx - 1
  1349.         For f = FirstIndex To SecondIndex '0 To Ns - 1
  1350.         With Comp(CompIndex(f))
  1351.         For G = 1 To .Vi
  1352.         For H = 1 To .Hi
  1353.         EncodeCoefficients .Data, P(f, G - 1), Pred(f), Td(f), Ta(f)
  1354.         Next H
  1355.         Next G
  1356.         End With
  1357.         Next f
  1358.         Next I
  1359.  
  1360.        'Encode Rightmost MCU
  1361.         For f = FirstIndex To SecondIndex '0 To Ns - 1
  1362.         With Comp(CompIndex(f))
  1363.         For G = 1 To .Vi
  1364.         For H = 1 To .Hi
  1365.         If H > MCUr(f) Then 'Pad with dummy block
  1366.             Pad64(0) = Pred(f)
  1367.             EncodeCoefficients Pad64, 0, Pred(f), Td(f), Ta(f)
  1368.         Else
  1369.             EncodeCoefficients .Data, P(f, G - 1), Pred(f), Td(f), Ta(f)
  1370.         End If
  1371.         Next H
  1372.         Next G
  1373.         End With
  1374.         Next f
  1375.  
  1376.        'Advance .data pointers
  1377.         For f = FirstIndex To SecondIndex
  1378.         For G = 0 To Comp(CompIndex(f)).Vi - 1
  1379.         P(f, G) = P(f, G) + pLF(f)
  1380.         Next G
  1381.         Next f
  1382.      Next J
  1383.  
  1384.    'Encode Bottommost MCU Scanline
  1385.     For I = 1 To MCUx
  1386.     For f = FirstIndex To SecondIndex
  1387.     With Comp(CompIndex(f))
  1388.     For G = 1 To .Vi
  1389.     For H = 1 To .Hi
  1390.     If P(f, G - 1) > UBound(.Data) Or (I = MCUx And H > MCUr(f)) Then 'Pad with dummy block
  1391.         Pad64(0) = Pred(f)
  1392.         EncodeCoefficients Pad64, 0, Pred(f), Td(f), Ta(f)
  1393.     Else
  1394.         EncodeCoefficients .Data, P(f, G - 1), Pred(f), Td(f), Ta(f)
  1395.     End If
  1396.     Next H
  1397.     Next G
  1398.     End With
  1399.     Next f
  1400.     Next I
  1401.  
  1402.     WriteBitsEnd
  1403.  
  1404. End Sub
  1405.  
  1406. Private Sub InsertSequentialScans(CompIndex() As Long, Td() As Long, Ta() As Long, FirstIndex As Long, SecondIndex As Long)
  1407. 'Insert scan components CompIndex(FirstIndex) to CompIndex(SecondIndex) sequentially in compliance
  1408. 'with JPEG rules.  Components are interleaved whenever possible to emit as few scans as possible.
  1409.  
  1410.     Dim f            As Long       'First Index
  1411.     Dim G            As Long       'Second Index
  1412.     Dim Nb           As Long       'Number of 8X8 blocks in MCU
  1413.     Const MaxNb      As Long = 10  'Max 8X8 blocks in MCU  (10 for JPEG compliance)
  1414.     Dim flag         As Boolean    'True when ready to insert scan(s)
  1415.  
  1416.     f = FirstIndex
  1417.     G = FirstIndex
  1418.     Nb = 0
  1419.     flag = False
  1420.     While f <= SecondIndex
  1421.  
  1422.         Nb = Nb + Comp(CompIndex(G)).Hi * Comp(CompIndex(G)).Vi
  1423.         G = G + 1
  1424.  
  1425.         If Nb > MaxNb Then
  1426.             flag = True
  1427.             If f <> G - 1 Then G = G - 1
  1428.         Else
  1429.             If (G - f) = 3 Or G > SecondIndex Then flag = True
  1430.         End If
  1431.  
  1432.         If flag Then
  1433.             If f = G - 1 Then
  1434.                 InsertSOSNonInterleaved CompIndex(f), Td(f), Ta(f)
  1435.             Else
  1436.                 InsertSOSInterleaved CompIndex, Td, Ta, f, G - 1
  1437.             End If
  1438.             Nb = 0
  1439.             f = G
  1440.             flag = False
  1441.         End If
  1442.     Wend
  1443.  
  1444. End Sub
  1445.  
  1446.  
  1447.  
  1448.  
  1449.  
  1450. '========================================================================================
  1451. '                               W R I T I N G   F I L E
  1452. '========================================================================================
  1453. Private Function OptimizeHuffmanTables(CompIndex() As Long, Td() As Long, Ta() As Long, FirstIndex As Long, SecondIndex As Long) As Long
  1454. 'Optimize Huffman tables for the component indexes given.
  1455. 'Returns an estimate of the number of bytes needed for entropy coded data.
  1456. 'Estimate assumes a single scan, and entropy coded FF bytes are not followed by a zero stuff byte.
  1457.  
  1458.     Dim f            As Long      'First Index
  1459.     Dim G            As Long      'Second Index
  1460.     Dim I            As Long
  1461.     Dim J            As Long
  1462.     Dim k            As Long      'Total bytes required for entropy coded data
  1463.     Dim k1           As Long
  1464.     Dim k2           As Long
  1465.     Dim Nb           As Long      'Number of 8X8 blocks in MCU
  1466.     Const MaxNb      As Long = 10 'Max 8X8 blocks in MCU  (10 for JPEG compliance)
  1467.     Dim freq(256)    As Long      'frequency count for optimizing Huffman tables
  1468.     Dim freq2()      As Long      'copy of freq, used for calcultating entropy coded data size
  1469.     Dim IsInter()    As Boolean   'True if component i will be interleaved
  1470.     Dim TdUsed()     As Boolean   'True if HuffDC(i) is used
  1471.     Dim TaUsed()     As Boolean   'True if HuffAC(i) is used
  1472.     Dim flag         As Boolean   'True when ready to include scan(s)
  1473.  
  1474.     ReDim IsInter(FirstIndex To SecondIndex)
  1475.     ReDim TaUsed(3)
  1476.     ReDim TdUsed(3)
  1477.  
  1478.  
  1479.    'Determine which components will be interleaved by InsertSequentialScans(), which tables are used
  1480.     f = FirstIndex
  1481.     G = FirstIndex
  1482.     Nb = 0
  1483.     flag = False
  1484.     While f <= SecondIndex
  1485.  
  1486.         Nb = Nb + Comp(CompIndex(G)).Hi * Comp(CompIndex(G)).Vi
  1487.         G = G + 1
  1488.  
  1489.         If Nb > MaxNb Then
  1490.             flag = True
  1491.             If f <> G - 1 Then G = G - 1
  1492.         Else
  1493.             If (G - f) = 3 Or G > SecondIndex Then flag = True
  1494.         End If
  1495.  
  1496.         If flag Then
  1497.             If f = G - 1 Then
  1498.                     TdUsed(Td(f)) = True
  1499.                     TaUsed(Ta(f)) = True
  1500.                     IsInter(f) = False
  1501.             Else
  1502.                 For I = f To G - 1
  1503.                     TdUsed(Td(I)) = True
  1504.                     TaUsed(Ta(I)) = True
  1505.                     IsInter(I) = True
  1506.                 Next I
  1507.             End If
  1508.             Nb = 0
  1509.             f = G
  1510.             flag = False
  1511.         End If
  1512.     Wend
  1513.  
  1514.  
  1515.    'Optimize huffman tables for the scan sequence
  1516.     For I = 0 To 3
  1517.         If TdUsed(I) Then
  1518.             For f = FirstIndex To SecondIndex
  1519.                 With Comp(CompIndex(f))
  1520.                     If Td(f) = I Then
  1521.                         If IsInter(f) Then
  1522.                             CollectStatisticsDCInterleaved .Data, freq, .Hi, .Vi
  1523.                         Else
  1524.                             CollectStatisticsDCNonInterleaved .Data, freq
  1525.                         End If
  1526.                     End If
  1527.                 End With
  1528.             Next f
  1529.  
  1530.            'Optimize and create this DC table
  1531.             'freq2 = freq
  1532.             ReDim freq2(0 To 256)
  1533.             CopyMemory freq2(0), freq(0), 1024
  1534.             OptimizeHuffman HuffDC(I), freq
  1535.             ExpandHuffman HuffDC(I), IIf(PP = 12, 15, 11)
  1536.  
  1537.            'Calculate compressed data size and add to total k
  1538.             For J = 0 To 15
  1539.                 If freq2(J) <> 0 Then
  1540.                     k1 = J + Int(Log(HuffDC(I).EHUFSI(J)) * 1.442695040889) + 1 'Length of size category, in bits
  1541.                     k2 = k2 + freq2(J) * k1                                     'Sum all occurances of this coefficient, in bits
  1542.                     k = k + k2 \ 8                                              'add to byte count
  1543.                     k2 = k2 Mod 8                                               'preserve remaining bits
  1544.                 End If
  1545.             Next J
  1546.  
  1547.         End If
  1548.         If TaUsed(I) Then
  1549.             For f = FirstIndex To SecondIndex
  1550.                 If Td(f) = I Then CollectStatisticsAC Comp(CompIndex(f)).Data, freq
  1551.             Next f
  1552.  
  1553.            'Optimize and create this AC table
  1554.             'freq2 = freq
  1555.             ReDim freq2(0 To 256)
  1556.             CopyMemory freq2(0), freq(0), 1024
  1557.             OptimizeHuffman HuffAC(I), freq
  1558.             ExpandHuffman HuffAC(I), 255
  1559.  
  1560.            'Calculate compressed data size and add to total k
  1561.             For J = 0 To 255
  1562.                 If freq2(J) <> 0 Then
  1563.                     k1 = (J And 15) + Int(Log(HuffAC(I).EHUFSI(J)) * 1.442695040889) + 1 'Length of size category, in bits
  1564.                     k2 = k2 + freq2(J) * k1                                              'Sum all occurances of this coefficient, in bits
  1565.                     k = k + k2 \ 8                                                       'add to byte count
  1566.                     k2 = k2 Mod 8                                                        'preserve remaining bits
  1567.                 End If
  1568.             Next J
  1569.  
  1570.         End If
  1571.     Next I
  1572.  
  1573.     If (k2 Mod 8) <> 0 Then k = k + 1
  1574.     OptimizeHuffmanTables = k
  1575.  
  1576. End Function
  1577.  
  1578.  
  1579.  
  1580. Friend Function SaveFile(FileName As String) As Long
  1581.     Dim CompIndex()  As Long 'Indexes of Components to be included
  1582.     Dim Td()         As Long 'DC Huffman Table Selectors
  1583.     Dim Ta()         As Long 'AC Huffman Table Selectors
  1584.     Dim FileNum      As Integer
  1585.     Dim I            As Long
  1586.  
  1587.  
  1588.     If Len(FileName) = 0 Then
  1589.         SaveFile = 1         'FileName not given
  1590.     Else
  1591.         If (Len(Dir(FileName, vbNormal Or vbReadOnly Or vbHidden Or vbSystem Or vbArchive)) > 0) Then
  1592.             SaveFile = 2     'File already exists
  1593.         Else
  1594.  
  1595.  
  1596.     ReDim CompIndex(Nf - 1)
  1597.     ReDim Td(Nf - 1)
  1598.     ReDim Ta(Nf - 1)
  1599.  
  1600.     For I = 0 To Nf - 1
  1601.         CompIndex(I) = I
  1602.         Td(I) = IIf(I = 0, 0, 1)
  1603.         Ta(I) = IIf(I = 0, 0, 1)
  1604.     Next I
  1605.  
  1606.     I = OptimizeHuffmanTables(CompIndex, Td, Ta, 0, Nf - 1)
  1607.  
  1608.    'Estimate maximum possible file size needed
  1609.     I = 1.3 * I + 1000 + Len(m_Comment)
  1610.     ReDim m_Data(I)
  1611.     m_Ptr = 0
  1612.  
  1613.     InsertMarker SOI                                   'SOI - Start of Image
  1614.     InsertJFIF                                         'JFIF
  1615.  
  1616.     If Len(m_Comment) > 0 Then InsertCOM m_Comment     'COM - Comment
  1617.     'InsertCOM "JPEG Encoder Class" & vbCrLf & "Written by John Korejwa <korejwa@tiac.net>" & vbCrLf & "Visual Basic sourcecode available at planetsourcecode.com"
  1618.  
  1619.     InsertDQT m_Ptr, 0                                 'DQT - Define Quantization Tables
  1620.     If Nf > 1 Then InsertDQT m_Ptr, 1
  1621.  
  1622.     InsertSOF SOF0                                     'SOF - Start of Frame
  1623.  
  1624.     InsertDHT m_Ptr, 0, False                          'DHT - Define Huffman Tables
  1625.     InsertDHT m_Ptr, 0, True
  1626.     If Nf > 1 Then
  1627.         InsertDHT m_Ptr, 1, False
  1628.         InsertDHT m_Ptr, 1, True
  1629.     End If
  1630.  
  1631.     InsertSequentialScans CompIndex, Td, Ta, 0, Nf - 1 'SOS - Scan Data
  1632.     InsertMarker EOI                                   'EOI - End of Image
  1633.  
  1634.    'Size the final byte array and write to file
  1635.     ReDim Preserve m_Data(m_Ptr - 1)
  1636.     FileNum = FreeFile
  1637.     Open FileName For Binary Access Write As FileNum
  1638.         Put #FileNum, , m_Data
  1639.     Close FileNum
  1640.     Erase m_Data
  1641.  
  1642.  
  1643.         End If
  1644.     End If
  1645.  
  1646. End Function
  1647.  
  1648.  
  1649.  
  1650.  
  1651. '========================================================================================
  1652. '                         C L A S S   I N I T I A L I Z A T I O N
  1653. '========================================================================================
  1654. Private Sub Class_Initialize()
  1655.     Dim I As Long
  1656.     Dim J As Long
  1657.     Dim dx As Long
  1658.     Dim zz As Long
  1659.  
  1660.     I = 0                   'Initialize the ZigZag() array, which maps out the
  1661.     J = 0                   '  zig-zag sequence of quantized DCT coefficients
  1662.     dx = 1                  '  in approximately low to high spatial frequencies
  1663.     For zz = 0 To 63
  1664.         ZigZag(I, J) = zz
  1665.         I = I + dx
  1666.         J = J - dx
  1667.         If I > 7 Then              '  0   1   5   6  14  15  27  28
  1668.             I = 7                  '  2   4   7  13  16  26  29  42
  1669.             J = J + 2              '  3   8  12  17  25  30  41  43
  1670.             dx = -1                '  9  11  18  24  31  40  44  53
  1671.         ElseIf J > 7 Then          ' 10  19  23  32  39  45  52  54
  1672.             J = 7                  ' 20  22  33  38  46  51  55  60
  1673.             I = I + 2              ' 21  34  37  47  50  56  59  61
  1674.             dx = 1                 ' 35  36  48  49  57  58  62  63
  1675.         ElseIf I < 0 Then
  1676.             I = 0 'check (j>7) first
  1677.             dx = 1
  1678.         ElseIf J < 0 Then
  1679.             J = 0
  1680.             dx = -1
  1681.         End If
  1682.     Next zz
  1683.  
  1684.    'Luminance Quantization table for Quality = 50
  1685.     QLumin(0) = 16:   QLumin(1) = 11:   QLumin(2) = 12:   QLumin(3) = 14
  1686.     QLumin(4) = 12:   QLumin(5) = 10:   QLumin(6) = 16:   QLumin(7) = 14
  1687.     QLumin(8) = 13:   QLumin(9) = 14:   QLumin(10) = 18:  QLumin(11) = 17
  1688.     QLumin(12) = 16:  QLumin(13) = 19:  QLumin(14) = 24:  QLumin(15) = 40
  1689.     QLumin(16) = 26:  QLumin(17) = 24:  QLumin(18) = 22:  QLumin(19) = 22
  1690.     QLumin(20) = 24:  QLumin(21) = 49:  QLumin(22) = 35:  QLumin(23) = 37
  1691.     QLumin(24) = 29:  QLumin(25) = 40:  QLumin(26) = 58:  QLumin(27) = 51
  1692.     QLumin(28) = 61:  QLumin(29) = 60:  QLumin(30) = 57:  QLumin(31) = 51
  1693.     QLumin(32) = 56:  QLumin(33) = 55:  QLumin(34) = 64:  QLumin(35) = 72
  1694.     QLumin(36) = 92:  QLumin(37) = 78:  QLumin(38) = 64:  QLumin(39) = 68
  1695.     QLumin(40) = 87:  QLumin(41) = 69:  QLumin(42) = 55:  QLumin(43) = 56
  1696.     QLumin(44) = 80:  QLumin(45) = 109: QLumin(46) = 81:  QLumin(47) = 87
  1697.     QLumin(48) = 95:  QLumin(49) = 98:  QLumin(50) = 103: QLumin(51) = 104
  1698.     QLumin(52) = 103: QLumin(53) = 62:  QLumin(54) = 77:  QLumin(55) = 113
  1699.     QLumin(56) = 121: QLumin(57) = 112: QLumin(58) = 100: QLumin(59) = 120
  1700.     QLumin(60) = 92:  QLumin(61) = 101: QLumin(62) = 103: QLumin(63) = 99
  1701.  
  1702.    'Chrominance Quantization table for Quality = 50
  1703.     QChrom(0) = 17:   QChrom(1) = 18:   QChrom(2) = 18:   QChrom(3) = 24
  1704.     QChrom(4) = 21:   QChrom(5) = 24:   QChrom(6) = 47:   QChrom(7) = 26
  1705.     QChrom(8) = 26:   QChrom(9) = 47:   QChrom(10) = 99:  QChrom(11) = 66
  1706.     QChrom(12) = 56:  QChrom(13) = 66:  QChrom(14) = 99:  QChrom(15) = 99
  1707.     QChrom(16) = 99:  QChrom(17) = 99:  QChrom(18) = 99:  QChrom(19) = 99
  1708.     QChrom(20) = 99:  QChrom(21) = 99:  QChrom(22) = 99:  QChrom(23) = 99
  1709.     QChrom(24) = 99:  QChrom(25) = 99:  QChrom(26) = 99:  QChrom(27) = 99
  1710.     QChrom(28) = 99:  QChrom(29) = 99:  QChrom(30) = 99:  QChrom(31) = 99
  1711.     QChrom(32) = 99:  QChrom(33) = 99:  QChrom(34) = 99:  QChrom(35) = 99
  1712.     QChrom(36) = 99:  QChrom(37) = 99:  QChrom(38) = 99:  QChrom(39) = 99
  1713.     QChrom(40) = 99:  QChrom(41) = 99:  QChrom(42) = 99:  QChrom(43) = 99
  1714.     QChrom(44) = 99:  QChrom(45) = 99:  QChrom(46) = 99:  QChrom(47) = 99
  1715.     QChrom(48) = 99:  QChrom(49) = 99:  QChrom(50) = 99:  QChrom(51) = 99
  1716.     QChrom(52) = 99:  QChrom(53) = 99:  QChrom(54) = 99:  QChrom(55) = 99
  1717.     QChrom(56) = 99:  QChrom(57) = 99:  QChrom(58) = 99:  QChrom(59) = 99
  1718.     QChrom(60) = 99:  QChrom(61) = 99:  QChrom(62) = 99:  QChrom(63) = 99
  1719.  
  1720.  
  1721.     FDCTScale(0) = 0.353553390593273     '0.25 / Cos(4 / 16 * PI)
  1722.     FDCTScale(1) = 0.25489778955208      '0.25 / Cos(1 / 16 * PI)
  1723.     FDCTScale(2) = 0.270598050073098     '0.25 / Cos(2 / 16 * PI)
  1724.     FDCTScale(3) = 0.300672443467523     '0.25 / Cos(3 / 16 * PI)
  1725.     FDCTScale(4) = 0.353553390593273     '0.25 / Cos(4 / 16 * PI)
  1726.     FDCTScale(5) = 0.449988111568207     '0.25 / Cos(5 / 16 * PI)
  1727.     FDCTScale(6) = 0.653281482438186     '0.25 / Cos(6 / 16 * PI)
  1728.     FDCTScale(7) = 1.28145772387074      '0.25 / Cos(7 / 16 * PI)
  1729.  
  1730.     SetSamplingFrequencies 2, 2, 1, 1, 1, 1
  1731.     Quality = 75
  1732.  
  1733. End Sub
  1734.  
  1735. 'ADDED BY SCINER - lenar2003@mail.ru
  1736. '30/10/2004 5:00
  1737. Public Function SaveToJpeg(ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal Width As Long, ByVal Height As Long, ByVal JpegFile As String, Optional ByVal JpegQuality As Long = 20, Optional ByVal Progressive As Boolean = True, Optional ByVal GrayScale As Boolean = False, Optional SamplingWidth As Long = 1, Optional ByVal CommentText As String = "SCINSpy - Created by SCINER: lenar2003@mail.ru") As Boolean
  1738.   'Returns: True = Success
  1739.  
  1740.   Dim Ret As Long
  1741.   
  1742.   Me.Comment = CommentText
  1743.   Me.Quality = JpegQuality
  1744.  
  1745.   If GrayScale Then
  1746.     If Progressive Then
  1747.       Me.SetSamplingFrequencies 4, 4, 0, 0, 0, 0
  1748.     Else
  1749.       Me.SetSamplingFrequencies 1, 1, 0, 0, 0, 0
  1750.     End If
  1751.   Else
  1752.     If Progressive Then
  1753.       Me.SetSamplingFrequencies 4, 4, SamplingWidth, SamplingWidth, SamplingWidth, SamplingWidth
  1754.     Else
  1755.       Me.SetSamplingFrequencies 1, 1, SamplingWidth, SamplingWidth, SamplingWidth, SamplingWidth
  1756.     End If
  1757.   End If
  1758.  
  1759.   Ret = Me.SampleHDC(hdc, Width, Height, X, Y)
  1760.   
  1761.   If Ret = 0 Then Me.SaveFile JpegFile
  1762.   SaveToJpeg = Ret = 0
  1763.   
  1764.   End Function

Ответить

Номер ответа: 3
Автор ответа:
 ilgar



Вопросов: 2
Ответов: 1
 Профиль | | #3 Добавлено: 02.07.10 17:02
Код такой маленкий
Не ужели другой пути нет ???
*****************************************

Imports System.Drawing.Imaging
Imports System.IO

Public Class Form1
    Private m_Drawing As Boolean = False
    Private m_LastPoint As Point = Nothing
    ;Dim gr As Graphics

    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        If Not m_Drawing Then Exit Sub

        gr.DrawLine(Pens.Yellow, m_LastPoint, New Point(e.X, e.Y))
        m_LastPoint = New Point(e.X, e.Y)

    End Sub

    Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
        m_Drawing = True
        m_LastPoint = New Point(e.X, e.Y)
        'Dim gr As Graphics = Me.PictureBox1.CreateGraphics()
        'gr.Clear(Me.PictureBox1.BackColor)
    End Sub

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

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        gr = Me.PictureBox1.CreateGraphics()
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        'PictureBox1.Image.Save("C:\Test.bmp", System.Drawing.Imaging.ImageFormat.Bmp)

        'Dim bm As New System.Drawing.Bitmap(PictureBox1.Image, 200, 150)
        'bm.Save("123.jpg", ImageFormat.Jpeg)
        ;Dim ms As New MemoryStream()
        PictureBox1.Image.Save(ms, ImageFormat.Jpeg)


    End Sub
End Class

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам