⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 huffyuv.cpp

📁 mpeg2的颜色转换程序,由BEN完成
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Huffyuv v2.1.1, by Ben Rudiak-Gould.
// http://www.math.berkeley.edu/~benrg/huffyuv.html
//
// Based on MSYUV sample code, which is:
// Copyright (c) 1993 Microsoft Corporation.
// All Rights Reserved.
//
// Changes copyright 2000 Ben Rudiak-Gould, and distributed under
// the terms of the GNU General Public License, v2 or later.  See
// http://www.gnu.org/copyleft/gpl.html.
//
// I edit these files in 10-point Verdana, a proportionally-spaced font.
// You may notice formatting oddities if you use a monospaced font.
//


#include "huffyuv.h"
#include "huffyuv_a.h"
#include "resource.h"

#include <crtdbg.h>


TCHAR szDescription[] = TEXT("Huffyuv v2.1.1");
TCHAR szName[]        = TEXT("Huffyuv");

#define VERSION         0x00020001      // 2.1


/********************************************************************
********************************************************************/

// these tables are generated at runtime from the data in tables.cpp

unsigned char encode1_shift[256];
unsigned encode1_add_shifted[256];
unsigned char encode2_shift[256];
unsigned encode2_add_shifted[256];
unsigned char encode3_shift[256];
unsigned encode3_add_shifted[256];

unsigned char decode1_shift[256];
unsigned char decode2_shift[256];
unsigned char decode3_shift[256];
DecodeTable decode1, decode2, decode3;

CodecInst *encode_table_owner, *decode_table_owner;

/********************************************************************
********************************************************************/

void Msg(const char fmt[], ...) {
  static int debug = GetPrivateProfileInt("debug", "log", 0, "huffyuv.ini");
  if (!debug) return;

  DWORD written;
  char buf[2000];
  va_list val;
  
  va_start(val, fmt);
  wvsprintf(buf, fmt, val);

  const COORD _80x50 = {80,50};
  static BOOL startup = (AllocConsole(), SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), _80x50));
  WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), buf, lstrlen(buf), &written, 0);
}


int AppFlags() {
  static int flags = -1;
  if (flags < 0) {
    flags = 0;
    TCHAR apppath[MAX_PATH];
    if (GetModuleFileName(NULL, apppath, MAX_PATH)) {
      TCHAR* appname = strrchr(apppath, '\\');
      appname = appname ? appname+1 : apppath;
      Msg("App name is %s; ", appname);
      if (!lstrcmpi(appname, TEXT("premiere.exe")))
        flags = 1;
      if (!lstrcmpi(appname, TEXT("veditor.exe")))
        flags = 1;
      if (!lstrcmpi(appname, TEXT("avi2mpg2_vfw.exe")))
        flags = 1;
      if (!lstrcmpi(appname, TEXT("bink.exe")))
        flags = 1;
      if (!lstrcmpi(appname, TEXT("afterfx.exe")))
        flags = 2;
      Msg("flags=%d\n", flags);
    }
  }
  return flags;
}

bool SuggestRGB() {
  return !!GetPrivateProfileInt("debug", "rgboutput", AppFlags()&1, "huffyuv.ini");
}

bool AllowRGBA() {
  return !!GetPrivateProfileInt("general", "enable_rgba", AppFlags()&2, "huffyuv.ini");
}


/********************************************************************
********************************************************************/

CodecInst* Open(ICOPEN* icinfo) {
  if (icinfo && icinfo->fccType != ICTYPE_VIDEO)
      return NULL;

  CodecInst* pinst = new CodecInst();

  if (icinfo) icinfo->dwError = pinst ? ICERR_OK : ICERR_MEMORY;

  return pinst;
}

DWORD Close(CodecInst* pinst) {
//    delete pinst;       // this caused problems when deleting at app close time
    return 1;
}

/********************************************************************
********************************************************************/

enum {
  methodLeft=0, methodGrad=1, methodMedian=2,
  methodConvertToYUY2=-1, methodOld=-2,
  flagDecorrelate=64
};

int ConvertOldMethod(int bitcount) {
  switch (bitcount&7) {
    case 1: return methodLeft;
    case 2: return methodLeft|flagDecorrelate;
    case 3: return (bitcount>=24) ? methodGrad+flagDecorrelate : methodGrad;
    case 4: return methodMedian;
    default: return methodOld;
  }
}

static inline int GetMethod(LPBITMAPINFOHEADER lpbi) {
  if (lpbi->biCompression == FOURCC_HFYU) {
    if (lpbi->biBitCount & 7)
      return ConvertOldMethod(lpbi->biBitCount);
    else if (lpbi->biSize > sizeof(BITMAPINFOHEADER))
      return *((unsigned char*)lpbi + sizeof(BITMAPINFOHEADER));
  }
  return methodOld;
}

static inline int GetBitCount(LPBITMAPINFOHEADER lpbi) {
  if (lpbi->biCompression == FOURCC_HFYU && lpbi->biSize > sizeof(BITMAPINFOHEADER)+1) {
    int bpp_override = *((char*)lpbi + sizeof(BITMAPINFOHEADER) + 1);
    if (bpp_override)
      return bpp_override;
  }
  return lpbi->biBitCount;
}

struct MethodName { int method; const char* name; };
MethodName yuv_method_names[] = {
  { methodLeft, "Predict left (fastest)" },
  { methodGrad, "Predict gradient" },
  { methodMedian, "Predict median (best)" }
};
MethodName rgb_method_names[] = {
  { methodLeft, "Predict left/no decorr. (fastest)" },
  { methodLeft+flagDecorrelate, "Predict left" },
  { methodGrad+flagDecorrelate, "Predict gradient (best)" },
  { methodConvertToYUY2, "<-- Convert to YUY2" }
};

bool IsLegalMethod(int method, bool rgb) {
  if (rgb) {
    return (method == methodOld || method == methodLeft
     || method == methodLeft+flagDecorrelate || method == methodGrad+flagDecorrelate);
  }
  else {
    return (method == methodOld || method == methodLeft
     || method == methodGrad || method == methodMedian);
  }
}

/********************************************************************
********************************************************************/

BOOL CodecInst::QueryAbout() { return TRUE; }

static BOOL CALLBACK AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  if (uMsg == WM_COMMAND) {
    switch (LOWORD(wParam)) {
    case IDOK:
      EndDialog(hwndDlg, 0);
      break;
    case IDC_HOMEPAGE:
      ShellExecute(NULL, NULL, "http://www.math.berkeley.edu/~benrg/huffyuv.html", NULL, NULL, SW_SHOW);
      break;
    case IDC_EMAIL:
      ShellExecute(NULL, NULL, "mailto:benrg@math.berkeley.edu", NULL, NULL, SW_SHOW);
      break;
    }
  }
  return FALSE;
}

DWORD CodecInst::About(HWND hwnd) {
  DialogBox(hmoduleHuffyuv, MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDialogProc);
  return ICERR_OK;
}

static BOOL CALLBACK ConfigureDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {

  if (uMsg == WM_INITDIALOG) {

    HWND hctlYUY2Method = GetDlgItem(hwndDlg, IDC_YUY2METHOD);
    int yuy2method = GetPrivateProfileInt("general", "yuy2method", methodMedian, "huffyuv.ini");
    for (int i = 0; i < sizeof(yuv_method_names)/sizeof(yuv_method_names[0]); ++i) {
      SendMessage(hctlYUY2Method, CB_ADDSTRING, 0, (LPARAM)yuv_method_names[i].name);
      if (yuv_method_names[i].method == yuy2method)
        SendMessage(hctlYUY2Method, CB_SETCURSEL, i, 0);
    }

    HWND hctlRGBMethod = GetDlgItem(hwndDlg, IDC_RGBMETHOD);
    int rgbmethod = GetPrivateProfileInt("general", "rgbmethod", methodGrad+flagDecorrelate, "huffyuv.ini");
    for (int j = 0; j < sizeof(rgb_method_names)/sizeof(rgb_method_names[0]); ++j) {
      SendMessage(hctlRGBMethod, CB_ADDSTRING, 0, (LPARAM)rgb_method_names[j].name);
      if (rgb_method_names[j].method == rgbmethod)
        SendMessage(hctlRGBMethod, CB_SETCURSEL, j, 0);
    }

    CheckDlgButton(hwndDlg, IDC_RGBOUTPUT,
      GetPrivateProfileInt("debug", "rgboutput", false, "huffyuv.ini") ? BST_CHECKED : BST_UNCHECKED);
    CheckDlgButton(hwndDlg, IDC_RGBA,
      GetPrivateProfileInt("general", "enable_rgba", false, "huffyuv.ini") ? BST_CHECKED : BST_UNCHECKED);
    CheckDlgButton(hwndDlg, IDC_SWAPFIELDS,
      GetPrivateProfileInt("debug", "decomp_swap_fields", false, "huffyuv.ini") ? BST_CHECKED : BST_UNCHECKED);
    CheckDlgButton(hwndDlg, IDC_LOG,
      GetPrivateProfileInt("debug", "log", false, "huffyuv.ini") ? BST_CHECKED : BST_UNCHECKED);
  }

  else if (uMsg == WM_COMMAND) {

    switch (LOWORD(wParam)) {

    case IDOK:
      {
        char methodstring[4];
        wsprintf(methodstring, "%d",
          yuv_method_names[SendMessage(GetDlgItem(hwndDlg, IDC_YUY2METHOD), CB_GETCURSEL, 0, 0)].method);
        WritePrivateProfileString("general", "yuy2method", methodstring, "huffyuv.ini");
        wsprintf(methodstring, "%d",
          rgb_method_names[SendMessage(GetDlgItem(hwndDlg, IDC_RGBMETHOD), CB_GETCURSEL, 0, 0)].method);
        WritePrivateProfileString("general", "rgbmethod", methodstring, "huffyuv.ini");
      }
      WritePrivateProfileString("debug", "rgboutput",
        (IsDlgButtonChecked(hwndDlg, IDC_RGBOUTPUT) == BST_CHECKED) ? "1" : NULL, "huffyuv.ini");
      WritePrivateProfileString("general", "enable_rgba",
        (IsDlgButtonChecked(hwndDlg, IDC_RGBA) == BST_CHECKED) ? "1" : NULL, "huffyuv.ini");
      WritePrivateProfileString("debug", "decomp_swap_fields",
        (IsDlgButtonChecked(hwndDlg, IDC_SWAPFIELDS) == BST_CHECKED) ? "1" : "0", "huffyuv.ini");
      WritePrivateProfileString("debug", "log",
        (IsDlgButtonChecked(hwndDlg, IDC_LOG) == BST_CHECKED) ? "1" : "0", "huffyuv.ini");

    case IDCANCEL:
      EndDialog(hwndDlg, 0);
      break;

    default:
      return AboutDialogProc(hwndDlg, uMsg, wParam, lParam);    // handle email and home-page buttons
    }
  }
  return FALSE;
}

BOOL CodecInst::QueryConfigure() { return TRUE; }

DWORD CodecInst::Configure(HWND hwnd) {
  DialogBox(hmoduleHuffyuv, MAKEINTRESOURCE(IDD_CONFIGURE), hwnd, ConfigureDialogProc);
  return ICERR_OK;
}


/********************************************************************
********************************************************************/


// we have no state information which needs to be stored

DWORD CodecInst::GetState(LPVOID pv, DWORD dwSize) { return 0; }

DWORD CodecInst::SetState(LPVOID pv, DWORD dwSize) { return 0; }


DWORD CodecInst::GetInfo(ICINFO* icinfo, DWORD dwSize) {
  if (icinfo == NULL)
    return sizeof(ICINFO);

  if (dwSize < sizeof(ICINFO))
    return 0;

  icinfo->dwSize            = sizeof(ICINFO);
  icinfo->fccType           = ICTYPE_VIDEO;
  icinfo->fccHandler        = FOURCC_HFYU;
  icinfo->dwFlags           = 0;

  icinfo->dwVersion         = VERSION;
  icinfo->dwVersionICM      = ICVERSION;
  MultiByteToWideChar(CP_ACP, 0, szDescription, -1, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR));
  MultiByteToWideChar(CP_ACP, 0, szName, -1, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR));

  return sizeof(ICINFO);
}


/********************************************************************
********************************************************************/


struct PrintBitmapType {
  char s[32];
  PrintBitmapType(LPBITMAPINFOHEADER lpbi) {
    if (!lpbi)
      strcpy(s,  "(null)");
    else {
      *(DWORD*)s = lpbi->biCompression;
      s[4] = 0;
      if (!isalnum(s[0]) || !isalnum(s[1]) || !isalnum(s[2]) || !isalnum(s[3]))
        wsprintfA(s, "%x", lpbi->biCompression);
      wsprintfA(strchr(s, 0), ", %d bits", GetBitCount(lpbi));
      if (lpbi->biCompression == FOURCC_HFYU && !(lpbi->biBitCount&7) && lpbi->biSize > sizeof(BITMAPINFOHEADER))
        wsprintfA(strchr(s, 0), ", method %d", *((unsigned char*)lpbi + sizeof(BITMAPINFOHEADER)));
    }
  }
};


// fast clipping of values to unsigned char range

static unsigned char clip[896];

static void InitClip() {
  memset(clip, 0, 320);
  for (int i=0; i<256; ++i) clip[i+320] = i;
  memset(clip+320+256, 255, 320);
}

static inline unsigned char Clip(int x)
  { return clip[320 + ((x+0x8000) >> 16)]; }


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -