libjpeg implements yuv420p to jpg on arm board

 

In the previous blog, it was written that the conversion code in pure C language can only be converted under linux (ubuntu16.04)

Link: http://www.cnblogs.com/zhq-blog/p/8832157.html

But now it needs to be executed on the arm board, emmmmm...

 

I found the following information on the Internet, there are those using ffmpeg, libjpeg, libjpeg-trubo

Here is libjpeg to implement

 

The first is to cross-compile the libjpeg library on Linux

Here is a reference to a blog (pro-test available):

https://blog.csdn.net/lihui126/article/details/43057147

Then copy the compiled dynamic link library to the arm board

 

After the compilation environment is installed, the conversion program for libjpeg must be written.

This is also a reference to a blog:

https://blog.csdn.net/yixianfeng41/article/details/52181578

 

It mainly uses the function yuv420p_to_jpeg() inside

 1 int yuv420p_to_jpeg(const char * filename, const char* pdata,int image_width,int image_height, int quality)  
 2 {     
 3     struct jpeg_compress_struct cinfo;    
 4     struct jpeg_error_mgr jerr;    
 5     cinfo.err = jpeg_std_error(&jerr);    
 6     jpeg_create_compress(&cinfo);    
 7   
 8     FILE * outfile;    // target file    
 9     if ((outfile = fopen(filename, "wb")) == NULL) {    
10         fprintf(stderr, "can't open %s\n", filename);    
11         exit(1);    
12     }    
13     jpeg_stdio_dest(&cinfo, outfile);    
14   
15     cinfo.image_width = image_width;  // image width and height, in pixels    
16     cinfo.image_height = image_height;    
17     cinfo.input_components = 3;    // # of color components per pixel    
18     cinfo.in_color_space = JCS_YCbCr;  //colorspace of input image    
19     jpeg_set_defaults(&cinfo);    
20     jpeg_set_quality(&cinfo, quality, TRUE );    
21   
22     //////////////////////////////    
23     //  cinfo.raw_data_in = TRUE;    
24     cinfo.jpeg_color_space = JCS_YCbCr;    
25     cinfo.comp_info[0].h_samp_factor = 2;    
26     cinfo.comp_info[0].v_samp_factor = 2;    
27     /////////////////////////    
28   
29     jpeg_start_compress(&cinfo, TRUE);    
30   
31     JSAMPROW row_pointer[1];  
32   
33     unsigned char *yuvbuf;  
34     if((yuvbuf=(unsigned char *)malloc(image_width*3))!=NULL)  
35         memset(yuvbuf,0,image_width*3);  
36   
37     unsigned char *ybase,*ubase;  
38     ybase=pdata;  
39     ubase=pdata+image_width*image_height;    
40     int j=0;  
41     while (cinfo.next_scanline < cinfo.image_height)   
42     {  
43         int idx=0;  
44         for(int i=0;i<image_width;i++)  
45         {   
46             yuvbuf[idx++]=ybase[i + j * image_width];  
47             yuvbuf[idx++]=ubase[j/2 * image_width+(i/2)*2];  
48             yuvbuf[idx++]=ubase[j/2 * image_width+(i/2)*2+1];      
49         }  
50         row_pointer[0] = yuvbuf;  
51         jpeg_write_scanlines(&cinfo, row_pointer, 1);  
52         j++;  
53     }  
54     jpeg_finish_compress(&cinfo);    
55     jpeg_destroy_compress(&cinfo);    
56     fclose(outfile);    
57     return 0;    
58 }  

Explain the meaning of some parameters:

filename -- the name of the output file (see clearly, it is the output!!! That is xxx.jpg )

pData -- the data of the input file ( in yuv420sp format !! Don't be fooled by the function name!!!)

 

Since the pictures I took are in yuv420 format, the above function cannot be used directly

There are two options to choose from:

1. Select the yuv420p_to_yuv420sp() function in the blog above to perform format conversion, and then call the yuv420p_to_jpeg() function

2. It is to modify the way of reading data inside the yuv420p_to_jpeg() function (modified from the original yuv420sp format to yuv420p format)

 

Since I am very lazy, I chose the first option:

But when using the yuv420p_to_yuv420sp() function in the above blog, I found that there is a problem with the conversion process

The original code was:

 1 int yuv420p_to_yuv420sp(unsigned char * yuv420p,unsigned char* yuv420sp,int width,int height)  
 2 {  
 3     if(yuv420p==NULL)  
 4         return;  
 5     int i=0,j=0;  
 6     //Y  
 7     for(i=0;i<width*height;i++)  
 8     {  
 9         yuv420sp[i]=yuv420p[i];  
10     }  
11   
12     int m=0,n=0;  
13     for(int j=0;j<width*height/2;j++)  
14     {  
15         if(j%2==0)  
16            yuv420sp[j+width*height]=yuv420p[m++];  
17         else  
18            yuv420sp[j+width*height]=yuv420p[n++];  
19     }  
20 }  

            YUV420SP YUV420P

The values ​​of m and n above are wrong, because for YUV420SP and YUV420P, the previous Y data is the same, so it can be directly assigned through the previous loop

However, when modifying the sequence of UV format data later, according to the above writing method, m=0, n=0 at the beginning, so yuv420p[0] needs to be assigned, but yuv420p[0] is obviously the data of the Y part, and cannot be assigned for UV

Therefore, this part of the code needs to be modified as follows:

 1     int yuv420p_to_yuv420sp(unsigned char * yuv420p,unsigned char* yuv420sp,int width,int height)  
 2     {  
 3         if(yuv420p==NULL)  
 4             return 0;  
 5         int i=0,j=0;  
 6         //Y  
 7         for(i=0;i<width*height;i++)  
 8         {  
 9             yuv420sp[i]=yuv420p[i];  
10         }  
11       
12         int m=0,n=0;  
13         for(j=0;j<width*height/2;j++)  
14         {  
15             if(j%2==0)  
16           {
17                  yuv420sp[j+width*height]=yuv420p[width*height+m];  
18               m++;
19           }
20             else 
21           {
22                    yuv420sp[j+width*height]=yuv420p[width*height*5/4+n];  
23                 n++;
24           } 
25         }  
26     } 

After this modification, there is no problem

 

Then add #include <jpeglib.h> in the main function file, remember to add the -ljpeg parameter at the end when compiling

You can convert data files in YUV420p format

 

Note:

Because the executable file cannot be executed on the arm board I use (even the ordinary helloworld program cannot be executed after cross-compiling)

So I used the -static parameter to compile statically when compiling

But I encountered a problem in static compilation: arm-none-linux-gnueabi/bin/ld: cannot find -ljpeg collect2: ld returned 1 exit status (not during dynamic compilation)

This problem is actually due to the fact that there is no static link library file libjpeg.a that contains the libjpeg library in the cross-compiled path.

Copy the static link library libjpeg.a you compiled to the lib directory of arm-none-linux-gcc and then perform static compilation again.

 

The code has been uploaded to github (including complete code and test files), the link is as follows:

https://github.com/quinncy/yuv2jpg_linux_libjpeg

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324518376&siteId=291194637