zoukankan      html  css  js  c++  java
  • 应用libjpeg提取jpeg质量因子

    http://blog.csdn.net/lzhq28/article/details/7775222

    [cpp] view plain copy
     
     print?
    1. data = new BYTE [cinfo.image_width*cinfo.image_height*cinfo.num_components];  


    基本思路:利用开源库实现对jpeg的解压缩以直接提取量化表,根据标准量化表和所提取量化表编写算法实现质量因子的求算。

    步骤一:使用libjpeg库实现对jpeg的解压缩并提取量化表

    参照:http://www.vckbase.com/index.php/wv/1488.html

    步骤如下:

    1、声明并初始化解压缩对象,同时制定错误信息管理器

    [cpp] view plain copy
     
     print?
    1. struct jpeg_decompress_struct cinfo;  
    2. struct jpeg_error_mgr jerr;  
    3. cinfo.err = jpeg_std_error(&jerr);  
    4. jpeg_create_decompress(&cinfo);  

    2、打开jpg图像文件,并指定为解压缩对象的源文件

     

    [cpp] view plain copy
     
     print?
    1. FILE *f = fopen(strSourceFileName,"rb");  
    2.   
    3. if (f==NULL)  
    [cpp] view plain copy
     
     print?
    1. {  
    2.   
    3.     printf("Open file error! ");  
    4.   
    5.     return;  
    [cpp] view plain copy
     
     print?
    1. }  
    2.   
    3. jpeg_stdio_src(&cinfo, f);  

    3、读取图像信息

    [cpp] view plain copy
     
     print?
    1. jpeg_read_header(&cinfo, TRUE);  

    4、根据图像信息申请一个图像缓冲区

    [cpp] view plain copy
     
     print?
    1. data = new BYTE [cinfo.image_width*cinfo.image_height*cinfo.num_components];  

    5、开始解压缩
     

    [cpp] view plain copy
     
     print?
    1. jpeg_start_decompress(&cinfo);  
    2.   
    3. JSAMPROW row_pointer[1];  
    4.   
    5. while (cinfo.output_scanline < cinfo.output_height)  
    6.   
    7. {  
    8.   
    9.     row_pointer[0] = &data[(cinfo.output_height - cinfo.output_scanline-1)*cinfo.image_width*cinfo.num_components];  
    10.   
    11.     jpeg_read_scanlines(&cinfo,row_pointer ,  
    12.   
    13.                            1);  
    14.   
    15. }  
    16.   
    17. jpeg_finish_decompress(&cinfo);  


     

    6:获取解压缩后的量化表

    [cpp] view plain copy
     
     print?
    1. GetQualityTabl(&cinfo,QualTabl,1);//获取解压缩后的量化表  

    7:释放资源

    [cpp] view plain copy
     
     print?
    1. jpeg_destroy_decompress(&cinfo);  
    2.   
    3. fclose(f);  

    步骤二:根据标准量化表和所提取的量化表求出质量因子

    注解:由于质量因子为1到100的整数,所以可以采用遍历的方式查出质量因子

    1:在libjpeg库中jcparam.c中复制标准量化表

    亮度量化表:  

    [cpp] view plain copy
     
     print?
    1. static const unsigned int std_luminance_quant_tbl[64] = {  
    2.   
    3.   16,  11,  10,  16,  24,  40,  51,  61,  
    4.   
    5.   12,  12,  14,  19,  26,  58,  60,  55,  
    6.   
    7.   14,  13,  16,  24,  40,  57,  69,  56,  
    8.   
    9.   14,  17,  22,  29,  51,  87,  80,  62,  
    10.   
    11.   18,  22,  37,  56,  68, 109, 103,  77,  
    12.   
    13.   24,  35,  55,  64,  81, 104, 113,  92,  
    14.   
    15.   49,  64,  78,  87, 103, 121, 120, 101,  
    16.   
    17.   72,  92,  95,  98, 112, 100, 103,  99  
    18.   
    19. };  


    色度量化表:

    [cpp] view plain copy
     
     print?
    1. static const unsigned int std_chrominance_quant_tbl[64] = {  
    2.   
    3.   17,  18,  24,  47,  99,  99,  99,  99,  
    4.   
    5.   18,  21,  26,  66,  99,  99,  99,  99,  
    6.   
    7.   24,  26,  56,  99,  99,  99,  99,  99,  
    8.   
    9.   47,  66,  99,  99,  99,  99,  99,  99,  
    10.   
    11.   99,  99,  99,  99,  99,  99,  99,  99,  
    12.   
    13.   99,  99,  99,  99,  99,  99,  99,  99,  
    14.   
    15.   99,  99,  99,  99,  99,  99,  99,  99,  
    16.   
    17.   99,  99,  99,  99,  99,  99,  99,  99  
    18.   
    19. };  

    2:创建从质量因子从1到100所对应的两种量化表,并将其存入一维数组中(按从左到右,从上到下,先亮度后色度的顺序进行存储),其中对质量因子的量化表和质量因子的关系请预读jcparam.c中的jpeg_set_quality()和jpeg_add_quant_table()函数。

    [cpp] view plain copy
     
     print?
    1. for(int quality=1;quality<=100;quality++)  
    2.   
    3. {  
    4.   
    5.         if(quality<=0)  
    6.   
    7.                quality = 1;  
    8.   
    9.         if(quality > 100)  
    10.   
    11.                quality = 100;  
    12.   
    13.         if(quality<50)  
    14.   
    15.                scale_factor=5000 / quality;  
    16.   
    17.         else   
    18.   
    19.                scale_factor= 200 - quality*2;  
    20.   
    21.    
    22.   
    23.         for(int j=0;j<2;j++)  
    24.   
    25.         {  
    26.   
    27.                for(int i=0;i<64;i++)  
    28.   
    29.                {  
    30.   
    31.           
    32.   
    33.                        if(j==0)  
    34.   
    35.                        {  
    36.   
    37.                                temp=((long) std_luminance_quant_tbl[i]*scale_factor+ 50L)/100L;  
    38.   
    39.                                if (temp <= 0L) temp = 1L;  
    40.   
    41.                                if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */  
    42.   
    43.                                if(temp>255)  
    44.   
    45.                                   temp = 255L;  
    46.   
    47.                                AllQualTabls[quality-1][i]=(UINT16) temp;  
    48.   
    49.                        }  
    50.   
    51.                        if(j==1)  
    52.   
    53.                        {  
    54.   
    55.                                temp=((long) std_chrominance_quant_tbl[i]*scale_factor+ 50L)/100L;  
    56.   
    57.                                if (temp <= 0L) temp = 1L;  
    58.   
    59.                                if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */  
    60.   
    61.                                if(temp>255)  
    62.   
    63.                                   temp = 255L;  
    64.   
    65.                                AllQualTabls[quality-1][64+i]=(UINT16) temp;  
    66.   
    67.                        }  
    68.   
    69.                }  
    70.   
    71.         }  
    72.   
    73. }  



    3:遍历上述所得二维数组与所得量化表进行匹配,得到质量因子

    [cpp] view plain copy
     
     print?
    1. for(int tmp=99;tmp>=0;tmp--)//逆序寻找,因为一般质量因子都大于50  
    2.   
    3. {  
    4.   
    5.         for(int j=0;j<128;j++)  
    6.   
    7.         {  
    8.   
    9.                if( (QualTabl[j]==AllQualTabls[tmp][j])&&(j==127))  
    10.   
    11.                {  
    12.   
    13.                        //Q_Factor=tmp;  
    14.   
    15.                        count++;//满足条件的质量因子的数量加1  
    16.   
    17.                        if(tmp>final)//选择最大满足条件的最大的质量因子  
    18.   
    19.                                final=tmp;  
    20.   
    21.                }  
    22.   
    23.                else if(QualTabl[j]!=AllQualTabls[tmp][j])  
    24.   
    25.                        break;//发现不相等的项将跳出该循环进入下一个循环(质量因子不同)。  
    26.   
    27.    
    28.   
    29.         }  
    30.   
    31. }  


     

    源程序:

    1:解压缩JPEG图片

    [cpp] view plain copy
     
     print?
    1. unsigned char * DeJpeg(char * JpegName,int QualTabl[128],int AllQualTabls[100][128],int *Factor)//解压jpeg格式图片并显示相应的量化表,并已指针参数形式传递Factor的值,并返回RGB(unsigned char)数据的指针  
    2.   
    3. {  
    4.   
    5.    
    6.   
    7.         FILE *openJpeg;  
    8.   
    9.         unsigned char *data;   //存放解压后的数据  
    10.   
    11.         unsigned char *jpgbuf;      //存放解压后一行图像数据  
    12.   
    13.         int row_stride;        //定义每行的字节数  
    14.   
    15.         struct jpeg_decompress_struct cinfo;  
    16.   
    17.     struct jpeg_error_mgr jerr;  
    18.   
    19.         cinfo.err = jpeg_std_error(&jerr);  
    20.   
    21.         jpeg_create_decompress(&cinfo);//声明并初始化解压缩对象  
    22.   
    23.    
    24.   
    25.         openJpeg=fopen(JpegName,"rb");//二进制模式读取jpeg文件  
    26.   
    27.    
    28.   
    29.         if(openJpeg==NULL) //二进制模式读取  
    30.   
    31.         {  
    32.   
    33.                printf("error: cannot open  the file ");  
    34.   
    35.                return NULL;  
    36.   
    37.         }//打开jpeg图片  
    38.   
    39.    
    40.   
    41.         jpeg_stdio_src(&cinfo, openJpeg);//指定解压对象的源文件  
    42.   
    43.         jpeg_read_header(&cinfo, TRUE);//读取文件信息,将图像的缺省的信息填充到cinfo结构中比便程序使用  
    44.   
    45.         jpeg_start_decompress(&cinfo);//开始接压缩  
    46.   
    47.           
    48.   
    49.         data=(unsigned char *)malloc(cinfo.output_width* cinfo.output_components*cinfo.output_width);//动态分配数据存储内存  
    50.   
    51.         memset(data,0,cinfo.output_width*cinfo.output_width*cinfo.output_components);//设置图像数据初值为0  
    52.   
    53.         jpgbuf = (unsigned char *) malloc(cinfo.output_width *cinfo.output_components);//动态分配缓存内存  
    54.   
    55.         memset(jpgbuf,0,cinfo.output_width*cinfo.output_components);//为缓存内存设置初值  
    56.   
    57.    
    58.   
    59.         row_stride = cinfo.output_width * cinfo.output_components; //计算每行所需的空间,字节为单位  
    60.   
    61.         while (cinfo.output_scanline < cinfo.output_height)  
    62.   
    63.         {  
    64.   
    65.                int line=cinfo.output_scanline;//当前行数  
    66.   
    67.    
    68.   
    69.                (void) jpeg_read_scanlines(&cinfo, &jpgbuf, 1);//执行该操作读取第line行数据,cinfo.output_scanline将加一,指向下一个要扫描的行  
    70.   
    71.    
    72.   
    73.                for(int i=0;i< cinfo.output_width;i++)//循环将存储在jpgbuf缓存区的数据放入data中  
    74.   
    75.                        {         
    76.   
    77.                                data[line*row_stride+i*cinfo.output_components+0]=jpgbuf[i*3];  
    78.   
    79.                                data[line*row_stride+i*cinfo.output_components+1]=jpgbuf[i*3+1];  
    80.   
    81.                                data[line*row_stride+i*cinfo.output_components+2]=jpgbuf[i*3+2];  
    82.   
    83. #ifdef DEBUG__  
    84.   
    85.         //printf("(%d,%d,%d),(%d,%d)",jpgbuf[i*3],jpgbuf[i*3+1],jpgbuf[i*3+2],line,i);//打印图像数据  
    86.   
    87. #endif     
    88.   
    89.                         }  
    90.   
    91.    
    92.   
    93.         }  
    94.   
    95.    
    96.   
    97.         GetQualityTabl(&cinfo,QualTabl,1);//获取解压缩后的量化表  
    98.   
    99.    
    100.   
    101.         *Factor=GetFactor(QualTabl,AllQualTabls,Q_FACTOR);//获取质量因子  
    102.   
    103.    
    104.   
    105.    
    106.   
    107.         jpeg_finish_decompress(&cinfo);//完成解压过程  
    108.   
    109.           
    110.   
    111.         jpeg_destroy_decompress(&cinfo);//释放cinfo  
    112.   
    113.    
    114.   
    115.         free(jpgbuf);//释放缓存  
    116.   
    117.         fclose(openJpeg);  
    118.   
    119.         return data;  
    120.   
    121.    
    122.   
    123. }  



    2:遍历寻找质量因子

    [cpp] view plain copy
     
     print?
    1. int GetFactor(int QualTabl[128],int AllQualTabls[100][128],int testFactor)//通过将得到的向量表(以一维维数组存储)和实验中所有情况的数组进行匹配(????是否存在与多个数组相匹配情况)  
    2.   
    3. {  
    4.   
    5.    
    6.   
    7.           
    8.   
    9. /* These are the sample quantization tables given in JPEG spec section K.1. 
    10.  
    11.  * The spec says that the values given produce "good" quality, and 
    12.  
    13.  * when divided by 2, "very good" quality. 
    14.  
    15.  */  
    16.   
    17. static const unsigned int std_luminance_quant_tbl[64] = {  
    18.   
    19.   16,  11,  10,  16,  24,  40,  51,  61,  
    20.   
    21.   12,  12,  14,  19,  26,  58,  60,  55,  
    22.   
    23.   14,  13,  16,  24,  40,  57,  69,  56,  
    24.   
    25.   14,  17,  22,  29,  51,  87,  80,  62,  
    26.   
    27.   18,  22,  37,  56,  68, 109, 103,  77,  
    28.   
    29.   24,  35,  55,  64,  81, 104, 113,  92,  
    30.   
    31.   49,  64,  78,  87, 103, 121, 120, 101,  
    32.   
    33.   72,  92,  95,  98, 112, 100, 103,  99  
    34.   
    35. };  
    36.   
    37. static const unsigned int std_chrominance_quant_tbl[64] = {  
    38.   
    39.   17,  18,  24,  47,  99,  99,  99,  99,  
    40.   
    41.   18,  21,  26,  66,  99,  99,  99,  99,  
    42.   
    43.   24,  26,  56,  99,  99,  99,  99,  99,  
    44.   
    45.   47,  66,  99,  99,  99,  99,  99,  99,  
    46.   
    47.   99,  99,  99,  99,  99,  99,  99,  99,  
    48.   
    49.   99,  99,  99,  99,  99,  99,  99,  99,  
    50.   
    51.   99,  99,  99,  99,  99,  99,  99,  99,  
    52.   
    53.   99,  99,  99,  99,  99,  99,  99,  99  
    54.   
    55. };  
    56.   
    57. long temp;//存储临时的质量因子  
    58.   
    59. int scale_factor=0;//默认值为0,品质因子最高  
    60.   
    61. //int Q_Factor=-1;//寻找到的质量因子,默认值为-1,表示没找到  
    62.   
    63. int count=0;//记录量化表相同的质量因子的个数  
    64.   
    65. int final=-2;//如果有多个质量因子满足条件,将选择最大的那个。-1表示没找到  
    66.   
    67.    
    68.   
    69.    
    70.   
    71. for(int quality=1;quality<=100;quality++)  
    72.   
    73. {  
    74.   
    75.         if(quality<=0)  
    76.   
    77.                quality = 1;  
    78.   
    79.         if(quality > 100)  
    80.   
    81.                quality = 100;  
    82.   
    83.         if(quality<50)  
    84.   
    85.                scale_factor=5000 / quality;  
    86.   
    87.         else   
    88.   
    89.                scale_factor= 200 - quality*2;  
    90.   
    91.    
    92.   
    93.         for(int j=0;j<2;j++)  
    94.   
    95.         {  
    96.   
    97.                for(int i=0;i<64;i++)  
    98.   
    99.                {  
    100.   
    101.           
    102.   
    103.                        if(j==0)  
    104.   
    105.                        {  
    106.   
    107.                                temp=((long) std_luminance_quant_tbl[i]*scale_factor+ 50L)/100L;  
    108.   
    109.                                if (temp <= 0L) temp = 1L;  
    110.   
    111.                                if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */  
    112.   
    113.                                if(temp>255)  
    114.   
    115.                                   temp = 255L;  
    116.   
    117.                                AllQualTabls[quality-1][i]=(UINT16) temp;  
    118.   
    119.                        }  
    120.   
    121.                        if(j==1)  
    122.   
    123.                        {  
    124.   
    125.                                temp=((long) std_chrominance_quant_tbl[i]*scale_factor+ 50L)/100L;  
    126.   
    127.                                if (temp <= 0L) temp = 1L;  
    128.   
    129.                                if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */  
    130.   
    131.                                if(temp>255)  
    132.   
    133.                                   temp = 255L;  
    134.   
    135.                                AllQualTabls[quality-1][64+i]=(UINT16) temp;  
    136.   
    137.                        }  
    138.   
    139.                }  
    140.   
    141.         }  
    142.   
    143. }  
    144.   
    145. //int testNum=testFactor-1;  
    146.   
    147.    
    148.   
    149.    
    150.   
    151.    
    152.   
    153. for(int tmp=99;tmp>=0;tmp--)//逆序寻找,因为一般质量因子都大于50  
    154.   
    155. {  
    156.   
    157.         for(int j=0;j<128;j++)  
    158.   
    159.         {  
    160.   
    161.                if( (QualTabl[j]==AllQualTabls[tmp][j])&&(j==127))  
    162.   
    163.                {  
    164.   
    165.                        //Q_Factor=tmp;  
    166.   
    167.                        count++;//满足条件的质量因子的数量加1  
    168.   
    169.                        if(tmp>final)//选择最大满足条件的最大的质量因子  
    170.   
    171.                                final=tmp;  
    172.   
    173.                }  
    174.   
    175.                else if(QualTabl[j]!=AllQualTabls[tmp][j])  
    176.   
    177.                        break;//发现不相等的项将跳出该循环进入下一个循环(质量因子不同)。  
    178.   
    179.    
    180.   
    181.         }  
    182.   
    183. }  
    184.   
    185. #ifdef DEBUG__  
    186.   
    187. printf("比较得出质量因子为:%d ",final+1);  
    188.   
    189. printf("与之量化表相等所对应的质量因子的个数:%d ",count);  
    190.   
    191. printf("任意键继续 ");  
    192.   
    193. getchar();  
    194.   
    195. #endif  
    196.   
    197.    
    198.   
    199. #ifdef DEBUG__  
    200.   
    201. if(final!=-2)  
    202.   
    203. {  
    204.   
    205.                printf("quantization table of luminance:the quality is %d  ",final+1);//输出CI通道的量化表  
    206.   
    207.    
    208.   
    209.                if(testFactor<=0)  
    210.   
    211.                        testFactor=1;  
    212.   
    213.                if(testFactor>100)  
    214.   
    215.                        testFactor=100;//保障质量因子在1-100之间  
    216.   
    217.    
    218.   
    219.                for (int i = 0; i <64; ++i)  
    220.   
    221.                {  
    222.   
    223.                        printf("% 4d ",  AllQualTabls[final][i]);  
    224.   
    225.                        if ((i + 1) % 8 == 0)  
    226.   
    227.                        printf(" ");  
    228.   
    229.                }  
    230.   
    231.                printf("quantization table of chrominance ,the quality is %d:  ",final+1);//输出CI通道的量化表  
    232.   
    233.                for (int i = 0; i <64; ++i)  
    234.   
    235.                {  
    236.   
    237.                        printf("% 4d ", AllQualTabls[final][64+i]);  
    238.   
    239.                        if ((i + 1) % 8 == 0)  
    240.   
    241.                        printf(" ");  
    242.   
    243.                }  
    244.   
    245.         printf("任意键继续 ");  
    246.   
    247.         getchar();  
    248.   
    249. }  
    250.   
    251. else   
    252.   
    253. {  
    254.   
    255.         printf("没有找到匹配的向量表  任意键继续 ");  
    256.   
    257.           
    258.   
    259.         getchar();  
    260.   
    261. }  
    262.   
    263. #endif  
    264.   
    265.         return final+1;  
    266.   
    267. }  


    相关阅读:

    C 实现BMP 转换为JPG 附源代码

     [置顶] C实现jpg转换为BMP 附源文件

     
    利用Opencv读取JPEG文件的压缩信息(量化表)
    http://blog.csdn.net/williams0/article/details/51143582

    OpenCV(Open Source Computer Vision Library)是一个强大的开源计算机视觉库,里面包含了许多非常有用的图像处理算法,由于在学习中需要提取JPEG图像文件的压缩信息,比如压缩的量化表、量化的DCT系数矩阵等。一开始我使用的是最新的libjpeg(IJG9)和opencv,在使用时发现两者会有冲突,原因是opencv的一些读入图像的函数会调用libjpeg,调用的libjpeg(libjpeg6.2)被集成在opencv中,而加载libjpeg9.2时会和libjpeg6.2冲突,故运行程序时经常弹出libjpeg版本错误的信息 。

    为解决这个问题,我调用opencv中的libjpeg来读取jpeg的压缩信息,下面粘上代码:

    [cpp] view plain copy
     
    1. #include <opencv2/core/core.hpp>  
    2. #include <opencv2/highgui/highgui.hpp>  
    3. #include <opencv2/opencv.hpp>  
    4. #include <stdio.h>  
    5. #include <iostream>  
    6. #include <stdlib.h>  
    7. #include <iostream>  
    8. #include <setjmp.h>  
    9. #include <jerror.h>  
    10. #include <jpeglib.h>  
    11.   
    12. using namespace std;  
    13. using namespace cv;  
    14.   
    15. int DeJpeg(string JpegName,int q_table[64])//解压jpeg格式图片并显示相应的量化表,并已指针参数形式传递Factor的值,并返回RGB(unsigned char)数据的指针  
    16.   
    17. {  
    18.   
    19.   
    20.   
    21.         FILE *openJpeg;  
    22.   
    23.   
    24.   
    25.         struct  jpeg_decompress_struct cinfo;  
    26.         struct jpeg_error_mgr jerr;  
    27.         JQUANT_TBL *quant_ptr;  
    28.   
    29.         cinfo.err = jpeg_std_error(&jerr);  
    30.   
    31.         jpeg_create_decompress(&cinfo);//声明并初始化解压缩对象  
    32.   
    33.         openJpeg=fopen(JpegName.c_str(),"rb");//二进制模式读取jpeg文件  
    34.   
    35.         if(openJpeg==NULL) //二进制模式读取  
    36.         {  
    37.             printf("error: cannot open  the file ");  
    38.               return NULL;  
    39.         }//打开jpeg图片  
    40.   
    41.         jpeg_stdio_src(&cinfo, openJpeg);//指定解压对象的源文件  
    42.         jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);  
    43.         jpeg_read_header(&cinfo, TRUE);//读取文件信息,将图像的缺省的信息填充到cinfo结构中比便程序使用  
    44.   
    45.         //jpeg_destroy_decompress(&cinfo);//释放cinfo  
    46.   
    47.         //------------------------------------------------------  
    48.         //int q_table[64];  
    49.         if (cinfo.quant_tbl_ptrs[0] != NULL) {  
    50.             quant_ptr = cinfo.quant_tbl_ptrs[0];  
    51.             for (unsigned int i = 0; i < DCTSIZE; i++)  
    52.               for (unsigned int j = 0; j < DCTSIZE; j++){  
    53.                 q_table[j*DCTSIZE+i] = (int) quant_ptr->quantval[i*DCTSIZE+j];  
    54.                 cout<<q_table[j*DCTSIZE+i]<<" ";}  
    55.         }  
    56.         //int QualTabl[128];  
    57.         jpeg_destroy_decompress(&cinfo);  
    58.   
    59.   
    60.         fclose(openJpeg);  
    61.   
    62.         return 1;  
    63.      
    64.   
    65.   
    66.   
    67. }  
    68. int main(){  
    69.     Mat img = imread("./ucid00001.jpg",0);  
    70.   
    71.     int Q_table[64];  
    72.     DeJpeg("./ucid00001.jpg",Q_table);  
    73.     for(int i=0;i<DCTSIZE2;i++){  
    74.         cout<<Q_table[i]<<" ";  
    75.     }  
    76.      imshow("Hi",img);  
    77.     waitKey(0);  
    78. }  
  • 相关阅读:
    Linux -- nginx
    Linux--虚拟环境
    Linux用户权限指令, 定时任务等指令
    Linux的基础命令, django的安装与使用
    .net与Java的WebService互调
    C#中的动态特性
    LINQ之路(3):LINQ扩展
    LINQ之路(2):LINQ to SQL本质
    LINQ之路(1):LINQ基础
    LINQ之路系列文章导读
  • 原文地址:https://www.cnblogs.com/jukan/p/7127700.html
Copyright © 2011-2022 走看看