Generally, the data read by the camera is in yuv422 format. If you want to support digital zoom, You need to scale the data. Of course, the specific point should be the zoom operation, because we all partially zoomed in the acquired image, which is called digital zoom.
During the test, we tried a lot of different methods, including gdiplus, opencv, IPPI, and self-compiled yuv422-based interpolation operations.
Here we will briefly introduce the scaling operations based on gdiplus, opencv, and IPPI. gdiplus and opencv can only be operated on yuv444. Therefore, we need to convert yuv422 to yuv444. With yuv422 and yuv444, it is easy to get and fast. through gdiplus, opencv scales yuv444 and converts the scaled yuv444 to yuv422 to complete the scaling process. IPPI provides the zooming function on yuv422, which can be used for zooming.
The specific scaling is as follows:
Gdiplus:
Int zoomin (byte * poridata, int width, int height, crect rect) // yuv444 <br/>{< br/> bitmapinfoheader bmih; <br/> memset (& bmih, 0, sizeof (bitmapinfoheader); <br/> bmih. bisize = sizeof (bitmapinfoheader); <br/> bmih. biwidth = width; <br/> bmih. biheight = height; <br/> bmih. biplanes = 1; <br/> bmih. bibitcount = 24; <br/> bmih. bisizeimage = width * height * bmih. bibitcount/8; <br/> bitmap * pbitmap = bitmap: frombitmapinfo (bitmapinfo *) & bmih, poridata ); <br/> bitmap * ptemp = pbitmap-> clone (rect. left, height-rect.bottom, rect. width (), rect. height (), pbitmap-> getpixelformat (); <br/> graphics gph (pbitmap); <br/> gph. drawimage (ptemp, 0, 0, width, height); <br/> Delete ptemp; <br/> Delete pbitmap; <br/> return 0; <br/>}
Opencv:
Yuv4222yuv444 (pyuv422, pyuv444, iwidth, iheight); <br/> If (! Pzoomsrciplimg) <br/>{< br/> pzoomsrciplimg = cvcreateimage (cvsize (iwidth, iheight), ipl_depth_8u, 3); <br/>}< br/> If) <br/>{< br/> memcpy (pzoomsrciplimg-> imagedata, pyuv444, g_iwidth * g_iheight * 3); <br/> cvsetimageroi (pzoomsrciplimg, cvrect (drawrect. left, drawrect. top, drawrect. width (), drawrect. height (); <br/>}< br/> If (! Pzoomdstiplimg) <br/>{< br/> pzoomdstiplimg = cvcreateimage (cvsize (iwidth, iheight), weight, 3); <br/>}< br/> cvresize (pzoomsrciplimg, values, cv_inter_linear); <br/> memcpy (pyuv444, pzoomdstiplimg-> imagedata, iwidth * iheight * 3); <br/> values (pyuv444, pyuv422, iwidth, iheight ); <br/> cvresetimageroi (pzoomsrciplimg); <br/>
IPPI:
Ippisize srcsize; <br/> srcsize. width = iwidth; <br/> srcsize. height = iheight; <br/> ippirect srcroi; <br/> srcroi. X = (drawrect. left> 2) <1; <br/> srcroi. y = drawrect. top; <br/> srcroi. width = (drawrect. width ()> 1) <1; <br/> srcroi. height = (drawrect. height ()> 1) <1; <br/> ippisize dstsize; <br/> dstsize. width = iwidth; <br/> dstsize. height = iheight; <br/> double xfactor = double (dstsize. width)/srcroi. width; <br/> double yfactor = double (dstsize. height)/srcroi. height; <br/> values (pyuv422src, srcsize, g_iwidth * 2, srcroi, pyuv422dst, iwidth * 2, dstsize, xfactor, yfactor, ippi_inter_linear ); <br/> memcpy (g_pyuv422src, g_pyuv422dst, g_iwidth * g_iheight * 2); <br/>
In the above method, drawrect is the desired zoom area, iwidth, and iheight are the scaled width and height (assuming they are consistent with the overall width and height of the original image, that is, zooming part of the image to all)
Using bilinear interpolation, I wrote a zooming code based on yuv422. Considering the computing workload, the efficiency cannot be compared with the above Code (which needs to be optimized)
Based on the above algorithm, gdiplus is similar to opencv, and IPPI is faster than gdiplus and opencv. IPPI and opencv are software packages provided by Intel.
Zooming Based on yuv422:
Int yuvzoomin (void * pyuv, int width, int height, crect rect) <br/>{< br/> If (rect. Width () % 2! = 0) <br/>{< br/> rect. Left ++; <br/>}< br/> If (rect. Left % 2! = 0) <br/>{< br/> rect. left ++; <br/> rect. right ++; <br/>}< br/> byte * pzoomindata = new byte [width * height * 2]; <br/> memset (pzoomindata, 0, width * height * 2); <br/> double scale = (double) (rect. right-rect.left)/width; <br/> byte * poriyuv = (byte *) pyuv; <br/> byte * pzooninyuv = (byte *) pzoomindata; <br/> double indexi, indexj, U, V; <br/> int roundi, roundj; <br/> int left, right, rectwidth, preu, Prev; <br/> left = (rect. left> 1) <1; <br/> right = (rect. right> 1) <1; <br/> rectwidth = right-left; <br/> for (INT I = 0; I <peight; ++ I) <br/> {<br/> for (Int J = 0; j <width; ++ J) <br/> {<br/> roundi = I * rectwidth/width; <br/> roundj = J * rectwidth/width; <br/> indexi = I * scale; <br/> indexj = J * scale; <br/> roundi = (INT) indexi; <br/> roundj = (INT) indexj; <br/> U = indexi-roundi; <br/> V = indexj-roundj; <br/> If (J % 2 = 0) <br/> {<br/> indexi = I * scale; <br/> indexj = J * scale; <br/> roundi = (INT) indexi; <br/> roundj = (INT) indexj; <br/> U = indexi-roundi; <br/> V = indexj-roundj; <br/> If (roundj % 2 = 0) <br/> {<br/> * (pzooninyuv + I * width * 2 + J * 2) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj) * 2) * (1-u) * (1-V) <br/> + (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj) * 2 + 2) * (1-u) * V) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj) * 2) * (1-V) * u) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj) * 2 + 2) * u * V )); <br/> * (pzooninyuv + I * width * 2 + J * 2 + 1) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj) * 2 + 1) * (1-u) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj) * 2 + 1) * U )); <br/> * (pzooninyuv + I * width * 2 + J * 2 + 3) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj) * 2 + 3) * (1-u) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj) * 2 + 3) * U )); <br/>}< br/> else <br/> {<br/> * (pzooninyuv + I * width * 2 + J * 2) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundJ-1) * 2 + 2) * (1-u) * (1-V )) <br/> + (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj + 1) * 2) * (1-u) * V) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundJ-1) * 2 + 2) * (1-V) * U) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj + 1) * 2) * u * V )); <br/> * (pzooninyuv + I * width * 2 + J * 2 + 1) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundJ-1) * 2 + 1) * (1-u) * (1-V )) <br/> + (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj + 1) * 2 + 1) * (1-u) * V) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundJ-1) * 2 + 1) * (1-V) * U) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj + 1) * 2 + 1) * u * V )); <br/> * (pzooninyuv + I * width * 2 + J * 2 + 3) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundJ-1) * 2 + 3) * (1-u) * (1-V )) <br/> + (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj + 1) * 2 + 3) * (1-u) * V) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundJ-1) * 2 + 3) * (1-V) * U) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj + 1) * 2 + 3) * u * V )); <br/>}< br/> else <br/> {<br/> indexi = I * scale; <br/> indexj = J * scale; <br/> roundi = (INT) indexi; <br/> roundj = (INT) indexj; <br/> U = indexi-roundi; <br/> V = indexj-roundj; <br/> preu = * (pzooninyuv + I * width * 2 + J * 2-1 ); <br/> Prev = * (pzooninyuv + I * width * 2 + J * 2 + 1); <br/> If (roundj % 2 = 0) <br/> {<br/> * (pzooninyuv + I * width * 2 + J * 2) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj) * 2) * (1-u) * (1-V) <br/> + (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj) * 2 + 2) * (1-u) * V) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj) * 2) * (1-V) * u) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj) * 2 + 2) * u * V )); <br/> * (pzooninyuv + I * width * 2 + J * 2-1) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj) * 2 + 1) * (1-u) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj) * 2 + 1) * U )); <br/> * (pzooninyuv + I * width * 2 + J * 2 + 1) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj) * 2 + 3) * (1-u) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj) * 2 + 3) * U )); <br/> * (pzooninyuv + I * width * 2 + J * 2-1) = (* (pzooninyuv + I * width * 2 + J * 2-1) + preu)> 1; <br/> * (pzooninyuv + I * width * 2 + J * 2 + 1) = (* (pzooninyuv + I * width * 2 + J * 2 + 1) + PREV)> 1; <br/>}< br/> else <br/> {<br/> * (pzooninyuv + I * width * 2 + J * 2) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundJ-1) * 2 + 2) * (1-u) * (1-V )) <br/> + (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj + 1) * 2) * (1-u) * V) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundJ-1) * 2 + 2) * (1-V) * U) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj + 1) * 2) * u * V )); <br/> * (pzooninyuv + I * width * 2 + J * 2-1) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundJ-1) * 2 + 1) * (1-u) * (1-V )) <br/> + (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj + 1) * 2 + 1) * (1-u) * V) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundJ-1) * 2 + 1) * (1-V) * U) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj + 1) * 2 + 1) * u * V )); <br/> * (pzooninyuv + I * width * 2 + J * 2 + 1) = (byte) (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundJ-1) * 2 + 3) * (1-u) * (1-V )) <br/> + (* (poriyuv + (rect. top + roundi) * width * 2 + (left + roundj + 1) * 2 + 3) * (1-u) * V) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundJ-1) * 2 + 3) * (1-V) * U) <br/> + (* (poriyuv + (rect. top + roundi + 1) * width * 2 + (left + roundj + 1) * 2 + 3) * u * V )); <br/> * (pzooninyuv + I * width * 2 + J * 2-1) = (* (pzooninyuv + I * width * 2 + J * 2-1) + preu)> 1; <br/> * (pzooninyuv + I * width * 2 + J * 2 + 1) = (* (pzooninyuv + I * width * 2 + J * 2 + 1) + PREV)> 1; <br/>}< br/> memcpy (pyuv, pzooninyuv, width * height * 2 ); <br/> Delete [] pzooninyuv; <br/> return 0; <br/>}< br/>
Tests can be used, and there are some problems with the speed. If you have any improvement ideas, contact me directly. Haha
Mosesyuan at gmail dot com