2016-10-10 31 views
0

我在Visual Studio 2015的C語言中編寫了一個用於測試libjpeg-turbo TurboJPEG-API的測試程序。來自libjpeg-turbo-1.5.1-vc.exe的TurboJPEG API產生錯誤的輸出

在此測試程序中,我生成一個800x800 RGB像素的圖像並將其寫入磁盤。當我在tjCompress2功能使用TJSAMP_GRAY磁盤上生成的圖像看起來不錯:

TJSAMP_GRAY output of TurboJPEG API from libjpeg-turbo version 1.5.1.

當我使用TJSAMP_444而不是圖像看起來weired:

TJSAMP_444 output of TurboJPEG API from libjpeg-turbo version 1.5.1.

但是,這兩個圖像可以不會在Adobe Photoshop中打開,而是在MS-Paint,Chrome或Internet Explorer中打開。除TJSAMP_GRAY以外的所有其他選項都會生成一幅圖像,同時質量設置爲100,TJSAMP_GRAY會導致輸出結果。 (本文中的圖像通過屏幕快照複製並保存爲png以獲取較小的數據。)我還通過P-Invoke使用turbojpeg.dll庫編寫了C#程序。該程序正在生成有效的輸出。

問題:我的錯在哪裏?

的源代碼中的問題:

#include <stdio.h> 
#include <io.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
#include "turbojpeg.h" 

unsigned char buffer[800 * 800 * 3]; 

int main(int argc, char** argv) 
{ 
    unsigned long size = 0; 

    unsigned char* compressedImage = NULL; 

    for (int x = 0; x < 800; x++) 
     for (int y = 0; y < 800; y++) 
     { 
      switch ((x/80) % 3) 
      { 
      case 0: 
       buffer[(y * 800 + x) * 3] = 255; 
       buffer[(y * 800 + x) * 3 + 1] = 0; 
       buffer[(y * 800 + x) * 3 + 2] = 0; 
       break; 
      case 1: 
       buffer[(y * 800 + x) * 3] = 0; 
       buffer[(y * 800 + x) * 3 + 1] = 255; 
       buffer[(y * 800 + x) * 3 + 2] = 0; 
       break; 
      case 2: 
       buffer[(y * 800 + x) * 3] = 0; 
       buffer[(y * 800 + x) * 3 + 1] = 0; 
       buffer[(y * 800 + x) * 3 + 2] = 255; 
       break; 
      } 
     } 

    tjhandle compressor = tjInitCompress(); 

    compressedImage = tjAlloc(1024 * 1024 * 4); 

    size = 1024 * 1024 * 4; 

    tjCompress2(compressor, buffer, 800, 0, 800, TJPF_RGB, &compressedImage, &size, TJSAMP_444, 80, TJFLAG_NOREALLOC | TJFLAG_ACCURATEDCT); 

    tjDestroy(compressor); 

    int handle = _wopen(L"D:\\file.jpeg", _O_CREAT | _O_WRONLY | _O_TRUNC, _S_IREAD | _S_IWRITE); 

    printf("LENGTH=%ld\n", size); 

    if (_write(handle, compressedImage, size) != size) 
     printf("Write Error.\n"); 

    _close(handle); 

    tjFree(compressedImage); 

    return 0; 
} 

只要是完整的,測試C#源代碼,它工作正常:

class Program 
{ 
    [DllImport("turbojpeg", CallingConvention = CallingConvention.Cdecl)] 
    private static extern IntPtr tjInitCompress(); 

    [DllImport("turbojpeg", CallingConvention = CallingConvention.Cdecl)] 
    private static extern IntPtr tjAlloc(int bytes); 

    [DllImport("turbojpeg", CallingConvention = CallingConvention.Cdecl)] 
    private static extern int tjCompress2(IntPtr handle, IntPtr srcBuf, int width, int pitch, int height, int pixelFormat, ref IntPtr jpegBuf, ref ulong jpegSize, int jpegSubsamp, int jpegQual, int flags); 

    [DllImport("turbojpeg", CallingConvention = CallingConvention.Cdecl)] 
    private static extern int tjDestroy(IntPtr handle); 

    [DllImport("turbojpeg", CallingConvention = CallingConvention.Cdecl)] 
    private static extern void tjFree(IntPtr buffer); 

    static void Main(string[] args) 
    { 
     ulong size = 1024 * 1024 * 4; 

     byte[] buffer = new byte[800 * 800 * 3]; 

     for (int x = 0; x < 800; x++) 
      for (int y = 0; y < 800; y++) 
      { 
       switch ((x/80) % 3) 
       { 
        case 0: 
         buffer[(y * 800 + x) * 3] = 255; 
         buffer[(y * 800 + x) * 3 + 1] = 0; 
         buffer[(y * 800 + x) * 3 + 2] = 0; 
         break; 
        case 1: 
         buffer[(y * 800 + x) * 3] = 0; 
         buffer[(y * 800 + x) * 3 + 1] = 255; 
         buffer[(y * 800 + x) * 3 + 2] = 0; 
         break; 
        case 2: 
         buffer[(y * 800 + x) * 3] = 0; 
         buffer[(y * 800 + x) * 3 + 1] = 0; 
         buffer[(y * 800 + x) * 3 + 2] = 255; 
         break; 
       } 
      } 

     IntPtr umBuffer = Marshal.AllocHGlobal(800 * 800 * 3); 
     Marshal.Copy(buffer, 0, umBuffer, 800 * 800 * 3); 

     IntPtr compressor = tjInitCompress(); 

     IntPtr compressedImage = tjAlloc(1024 * 1024 * 4); 

     tjCompress2(compressor, umBuffer, 800, 0, 800, 0, ref compressedImage, ref size, 0, 80, 5 * 1024); 

     byte[] mCPData = new byte[size]; 

     Marshal.Copy(compressedImage, mCPData, 0, (int)size); 

     System.IO.File.WriteAllBytes("D:\\managed.jpeg", mCPData); 

     tjFree(compressedImage); 

     Marshal.FreeHGlobal(umBuffer); 
    } 
} 

回答

0

_wopen -Line缺少_O_BINARY。所以,在項目配置或libjpeg-turbo TurboJPEG-API中沒有錯誤。只是,寫入光盤的輸出被解釋爲編碼文本,因此被_write功能或一些底層實例修改。

正確的源代碼將是:

#include <stdio.h> 
#include <io.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
#include "turbojpeg.h" 

unsigned char buffer[800 * 800 * 3]; 

int main(int argc, char** argv) 
{ 
    unsigned long size = 0; 

    unsigned char* compressedImage = NULL; 

    for (int x = 0; x < 800; x++) 
     for (int y = 0; y < 800; y++) 
     { 
      switch ((x/80) % 3) 
      { 
      case 0: 
       buffer[(y * 800 + x) * 3] = 255; 
       buffer[(y * 800 + x) * 3 + 1] = 0; 
       buffer[(y * 800 + x) * 3 + 2] = 0; 
       break; 
      case 1: 
       buffer[(y * 800 + x) * 3] = 0; 
       buffer[(y * 800 + x) * 3 + 1] = 255; 
       buffer[(y * 800 + x) * 3 + 2] = 0; 
       break; 
      case 2: 
       buffer[(y * 800 + x) * 3] = 0; 
       buffer[(y * 800 + x) * 3 + 1] = 0; 
       buffer[(y * 800 + x) * 3 + 2] = 255; 
       break; 
      } 
     } 

    tjhandle compressor = tjInitCompress(); 

    compressedImage = tjAlloc(1024 * 1024 * 4); 

    size = 1024 * 1024 * 4; 

    tjCompress2(compressor, buffer, 800, 0, 800, TJPF_RGB, &compressedImage, &size, TJSAMP_444, 80, TJFLAG_NOREALLOC | TJFLAG_ACCURATEDCT); 

    tjDestroy(compressor); 

    int handle = _wopen(L"D:\\file.jpeg", _O_CREAT | _O_WRONLY | _O_TRUNC | _O_BINARY, _S_IREAD | _S_IWRITE); 

    printf("LENGTH=%ld\n", size); 

    if (_write(handle, compressedImage, size) != size) 
     printf("Write Error.\n"); 

    _close(handle); 

    tjFree(compressedImage); 

    return 0; 
}