home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 4_2005-2006.ISO / data / Zips / RGB_-__YUV2008747252006.psc / Form1.frm < prev    next >
Text File  |  2006-07-25  |  12KB  |  329 lines

  1. VERSION 5.00
  2. Begin VB.Form frmMain 
  3.    Caption         =   "RGB -> YUV -> RGB"
  4.    ClientHeight    =   8190
  5.    ClientLeft      =   195
  6.    ClientTop       =   1605
  7.    ClientWidth     =   10200
  8.    LinkTopic       =   "Form1"
  9.    ScaleHeight     =   8190
  10.    ScaleWidth      =   10200
  11.    Begin VB.CommandButton cmdProcess 
  12.       Caption         =   "go"
  13.       Height          =   495
  14.       Left            =   5160
  15.       TabIndex        =   6
  16.       Top             =   240
  17.       Width           =   2775
  18.    End
  19.    Begin VB.PictureBox picYUV 
  20.       Appearance      =   0  'Flat
  21.       AutoRedraw      =   -1  'True
  22.       AutoSize        =   -1  'True
  23.       BackColor       =   &H80000005&
  24.       BorderStyle     =   0  'None
  25.       ForeColor       =   &H80000008&
  26.       Height          =   3630
  27.       Left            =   5040
  28.       ScaleHeight     =   3630
  29.       ScaleWidth      =   4830
  30.       TabIndex        =   4
  31.       Top             =   4200
  32.       Width           =   4830
  33.    End
  34.    Begin VB.PictureBox picY 
  35.       Appearance      =   0  'Flat
  36.       AutoRedraw      =   -1  'True
  37.       AutoSize        =   -1  'True
  38.       BackColor       =   &H80000005&
  39.       BorderStyle     =   0  'None
  40.       ForeColor       =   &H80000008&
  41.       Height          =   3630
  42.       Left            =   120
  43.       ScaleHeight     =   3630
  44.       ScaleWidth      =   4830
  45.       TabIndex        =   2
  46.       Top             =   4200
  47.       Width           =   4830
  48.    End
  49.    Begin VB.PictureBox picSource 
  50.       Appearance      =   0  'Flat
  51.       AutoSize        =   -1  'True
  52.       BackColor       =   &H80000005&
  53.       BorderStyle     =   0  'None
  54.       ForeColor       =   &H80000008&
  55.       Height          =   3600
  56.       Left            =   120
  57.       ScaleHeight     =   3600
  58.       ScaleWidth      =   4800
  59.       TabIndex        =   0
  60.       Top             =   240
  61.       Width           =   4800
  62.    End
  63.    Begin VB.Label Label3 
  64.       Alignment       =   2  'Center
  65.       Caption         =   "YUV -> RGB"
  66.       Height          =   255
  67.       Left            =   5040
  68.       TabIndex        =   5
  69.       Top             =   3960
  70.       Width           =   4815
  71.    End
  72.    Begin VB.Label Label2 
  73.       Alignment       =   2  'Center
  74.       Caption         =   "Y (Luma)"
  75.       Height          =   255
  76.       Left            =   120
  77.       TabIndex        =   3
  78.       Top             =   3960
  79.       Width           =   4815
  80.    End
  81.    Begin VB.Label Label1 
  82.       Alignment       =   2  'Center
  83.       Caption         =   "Source image"
  84.       Height          =   255
  85.       Left            =   120
  86.       TabIndex        =   1
  87.       Top             =   0
  88.       Width           =   4815
  89.    End
  90. End
  91. Attribute VB_Name = "frmMain"
  92. Attribute VB_GlobalNameSpace = False
  93. Attribute VB_Creatable = False
  94. Attribute VB_PredeclaredId = True
  95. Attribute VB_Exposed = False
  96. Option Explicit
  97. '
  98. ' Code written by Marius Hudea. Permission to use this code in your projects granted
  99. ' as long as my contribution is mentioned somewhere. You should optimize the conversion routines
  100. ' if you plan to use them in something that needs speed.
  101. '
  102. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
  103. Private Declare Function SetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal Y As Long, ByVal crColor As Long) As Long
  104. Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal Y As Long) As Long
  105.  
  106. Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Any) As Long
  107. Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
  108. Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
  109. Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
  110.  
  111. Private Const CREATE_NEW As Long = 1
  112. Private Const CREATE_ALWAYS As Long = 2
  113. Private Const OPEN_EXISTING As Long = 3
  114. Private Const OPEN_ALWAYS As Long = 4
  115. Private Const OPEN_IF_EXISTS As Long = (&H1)
  116. Private Const INVALID_HANDLE_VALUE As Long = -1
  117. Private Const FILE_BEGIN As Long = 0
  118. Private Const FILE_END As Long = 2
  119. Private Const FILE_SHARE_READ As Long = &H1
  120. Private Const FILE_SHARE_WRITE As Long = &H2
  121. Private Const GENERIC_WRITE As Long = &H40000000
  122. Private Const GENERIC_READ As Long = &H80000000
  123.  
  124. Private Type typeRGBQuad
  125.  R As Byte
  126.  G As Byte
  127.  B As Byte
  128.  x As Byte ' reserved
  129. End Type
  130.  
  131. Private Type typeYUV
  132.  Y As Byte ' Luminance
  133.  U As Byte ' Chroma b (Cb)
  134.  V As Byte ' Chroma r (Cr)
  135. End Type
  136.  
  137. Private imgRGB() As typeRGBQuad
  138. Private imgRGB2() As typeRGBQuad
  139. Private imgYUV() As typeYUV
  140.  
  141. 'Conversion routines for RGB->YUV and YUV->RGB
  142. '
  143. ' coefficients        Rec.601 Rec.709 FCC
  144. ' Kr : Red channel    0.299   0.2125  0.3
  145. ' Kg : Green channel  0.587   0.7154  0.59
  146. ' Kb : Blue channel   0.114   0.0721  0.11
  147. '
  148. ' 601 is the standard that is used.
  149. '
  150. ' The formulas look scary, but really they're not. Stand back and relax.
  151. '
  152. 'y - 16 = (Kr*219/255)*r + (Kg*219/255)*g + (Kb*219/255)*b
  153. 'u - 128 = - Kr*112/255*r/(1-Kb) - Kg*112/255*g/(1-Kb) + 112/255*b
  154. 'v - 128 = 112/255*r - Kg*112/255*g/(1-Kr) - Kb*112/255*b/(1-Kr)
  155. '
  156. ' for more information check :
  157. '
  158. ' http://www.avisynth.org/mediawiki/wiki/Color_conversions
  159. ' http://www.intersil.com/data/an/an9717.pdf
  160.  
  161. '
  162. 'This function is used to make sure computed values fall within the standard ranges.
  163. ' Y = 16..235 ; U,V = 16..240; R,G,B = 0..255
  164. '
  165. Private Function CheckRange(min As Byte, max As Byte, val As Long) As Byte
  166. If val < min Then
  167.   CheckRange = min: Exit Function
  168. End If
  169. If val > max Then
  170.   CheckRange = max: Exit Function
  171. End If
  172. CheckRange = CByte(val)
  173. End Function
  174.  
  175. Private Sub cmdProcess_Click()
  176. Dim i As Long
  177. Dim j As Long
  178. Dim imgw As Long
  179. Dim imgh As Long
  180. Dim pixel As Long
  181. Dim R As Byte
  182. Dim G As Byte
  183. Dim B As Byte
  184. Dim Y As Byte
  185. Dim U As Byte
  186. Dim V As Byte
  187.  
  188. Dim handle As Long
  189. Dim bwrote As Long
  190.  
  191. Dim x(1 To 8, 0 To 255) As Double
  192.  
  193. 'Determine the width and height of the source image
  194. imgw = picSource.Width \ Screen.TwipsPerPixelX - 1
  195. imgh = picSource.Height \ Screen.TwipsPerPixelY - 1
  196.  
  197. ReDim imgRGB(0 To imgw, 0 To imgh)                      ' original RGB image
  198. ReDim imgYUV(0 To imgw, 0 To imgh)                      ' original in YUV format
  199. ReDim imgRGB2(0 To imgw, 0 To imgh)                     ' YUV converted back to RGB
  200.  
  201. 'read the file to memory for faster operation
  202. For j = 0 To imgh
  203.  For i = 0 To imgw
  204.   pixel = GetPixel(picSource.hdc, i, j)                 ' gets the color of a pixel
  205.   CopyMemory imgRGB(i, j), pixel, 4                     ' copies the 4 bytes at once into the typeRGBQuad
  206.  Next i
  207. Next j
  208.  
  209. 'convert to YUV (YCbCr)
  210. ' Formulas pasted again, to be easier to understand what happens
  211. ' Kr = 0.299 Kg = 0.587 Kb = 0.114
  212. '
  213. 'y - 16 = (Kr*219/255)*r + (Kg*219/255)*g + (Kb*219/255)*b
  214. 'u - 128 = - Kr*112/255*r/(1-Kb) - Kg*112/255*g/(1-Kb) + 112/255*b
  215. 'v - 128 = 112/255*r - Kg*112/255*g/(1-Kr) - Kb*112/255*b/(1-Kr)
  216. '
  217. ' As you see, there are a lot of fractions and multiplications.
  218. ' If we have large images or a sequence of images, it would be wise to
  219. ' compute everything from the start and just create some small tables
  220. ' with the results. Our ecuations will become :
  221.  
  222. 'Y = Y = 0.257R┤ + 0.504G┤ + 0.098B┤ + 16
  223. 'U = Cb = -0.148R┤ - 0.291G┤ + 0.439B┤ + 128
  224. 'V = Cr = 0.439R┤ - 0.368G┤ - 0.071B┤ + 128
  225.  
  226. For i = 0 To 255
  227.   x(1, i) = 0.257 * i   ' 0.299 * 219/255 = 0.25678 = 0.257
  228.   x(2, i) = 0.504 * i   ' 0.587 * 219/255 = 0.5041 = 0.504
  229.   x(3, i) = 0.098 * i   ' you should get the ideea by now
  230.   x(4, i) = 0.148 * i
  231.   x(5, i) = 0.291 * i
  232.   x(6, i) = 0.439 * i
  233.   x(7, i) = 0.368 * i
  234.   x(8, i) = 0.071 * i
  235. Next i
  236.  
  237. ' Now, we can actually use the tables created above to convert the image to yuv
  238. For j = 0 To imgh
  239.  For i = 0 To imgw
  240.   R = imgRGB(i, j).R    ' this is extra but this way it's easier to read the formulas later on
  241.   G = imgRGB(i, j).G
  242.   B = imgRGB(i, j).B
  243.   imgYUV(i, j).Y = CheckRange(16, 235, Round(x(1, R) + x(2, G) + x(3, B), 0) + 16)
  244.   imgYUV(i, j).U = CheckRange(16, 240, Round(-x(4, R) - x(5, G) + x(6, B), 0) + 128)
  245.   imgYUV(i, j).V = CheckRange(16, 240, Round(x(6, R) - x(7, G) - x(8, B), 0) + 128)
  246.  Next i
  247. Next j
  248. '
  249. ' The image is now converted in YUV and stored in the array.
  250. ' The backwards process uses the following formulas to convert from YUV to RGB
  251. '
  252. 'R = 1.164(Y - 16) + 1.596(Cr - 128)
  253. 'G = 1.164(Y - 16) - 0.813(Cr - 128) - 0.392(Cb - 128)
  254. 'B = 1.164(Y - 16) + 2.017(Cb - 128)
  255. '
  256. 'Like before, we're going to build tables that will ease the process.
  257. 'You will maybe notice that I start from 0 instead of 16 (Y,U,V start from 16), this is just to be on
  258. 'the safe side. We're not trying to make the fastest and most optimized code here.
  259. '
  260. For i = 0 To 255
  261.  x(1, i) = 1.164 * (i - 16)
  262.  x(2, i) = 1.596 * (i - 128)
  263.  x(3, i) = 0.813 * (i - 128)
  264.  x(4, i) = 0.392 * (i - 128)
  265.  x(5, i) = 2.017 * (i - 128)
  266. Next i
  267. '
  268. ' Now, we can actually use the tables created above to convert the image back to RGB
  269. '
  270. For j = 0 To imgh
  271.  For i = 0 To imgw
  272.   Y = imgYUV(i, j).Y
  273.   U = imgYUV(i, j).U
  274.   V = imgYUV(i, j).V
  275.   imgRGB2(i, j).R = CheckRange(0, 255, Round(x(1, Y) + x(2, V), 0))
  276.   imgRGB2(i, j).G = CheckRange(0, 255, Round(x(1, Y) - x(3, V) - x(4, U), 0))
  277.   imgRGB2(i, j).B = CheckRange(0, 255, Round(x(1, Y) + x(5, U), 0))
  278.  Next i
  279. Next j
  280. '
  281. ' Now,let's do some nice drawings to see what we have done.
  282. ' A nice grayscale image can be obtained by using the luma component in the YUV format
  283. ' as red,green and blue
  284. '
  285. For j = 0 To imgh
  286.  For i = 0 To imgw
  287.  Y = imgYUV(i, j).Y
  288.   SetPixel picY.hdc, i, j, RGB(Y, Y, Y)
  289.  Next i
  290. Next j
  291. picY.Refresh
  292.  
  293. '
  294. ' In the second picture box, we'll draw the RGB image obtained from YUV.
  295. ' If you use Print Screen and zoom at pixel level , you'll see that some pixels in
  296. ' the RGB image obtained from YUV are not *exactly* the same as the ones in the RGB image.
  297. ' This is normal, it's a very very small sacrifice, almost unnoticeable.
  298. ' All video conversion as a first step in converting the images to
  299. ' YUY2 (HuffYUV) or YV12 (DVD, MPG, XVID)
  300. '
  301.  
  302. For j = 0 To imgh
  303.  For i = 0 To imgw
  304.   SetPixel picYUV.hdc, i, j, RGB(imgRGB2(i, j).R, imgRGB2(i, j).G, imgRGB2(i, j).B)
  305.  Next i
  306. Next j
  307. picYUV.Refresh
  308.  
  309. 'We're going to create a file on the disk with the YUV conversion results.
  310. ' Open the file
  311. handle = CreateFile("c:\testyuv.bin", GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, CREATE_ALWAYS, 0&, 0&)
  312. For j = 0 To imgh
  313.  For i = 0 To imgw
  314.   WriteFile handle, imgYUV(i, j).Y, 1, bwrote, 0&
  315.   WriteFile handle, imgYUV(i, j).U, 1, bwrote, 0&
  316.   WriteFile handle, imgYUV(i, j).V, 1, bwrote, 0&
  317.  Next i
  318. Next j
  319.  
  320. CloseHandle handle  'file can now be closed.
  321.  
  322. MsgBox "Done"
  323. End Sub
  324.  
  325. Private Sub Form_Load()
  326. On Error Resume Next
  327. picSource.Picture = LoadPicture(App.Path & IIf(Right(App.Path, 1) = "\", "", "\") & "picture.bmp")
  328. End Sub
  329.