2016-10-10 8 views
0

Я написал тестовую программу на C в Visual Studio 2015 для тестирования TurboJPEG-API libjpeg-turbo.API TurboJPEG из libjpeg-turbo-1.5.1-vc.exe производит неправильный вывод

В этой тестовой программе я создаю изображение 800x800 RGB пикселей и записываю это на диск. Когда я использую TJSAMP_GRAY в функции tjCompress2 получаемое изображение на диске выглядит хорошо:

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 для меньших данных.) Я также написал C# -Program, используя библиотеку turbojpeg.dll через P-Invoke. Эта программа производит достоверный вывод.

Вопрос: Где моя вина?

Источник-код в вопросе:

#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; 
}