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

📄 huffyuv.cpp

📁 mpeg2的颜色转换程序,由BEN完成
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      int scaled_y = (y1+y2 - 32) * int(255.0/219.0*32768+0.5);
      int b_y = ((rgb[0]+rgb[3]) << 15) - scaled_y;
      yuv[1] = Clip((b_y >> 10) * int(1/2.018*1024+0.5) + 0x800000);  // u
      int r_y = ((rgb[2]+rgb[5]) << 15) - scaled_y;
      yuv[3] = Clip((r_y >> 10) * int(1/1.596*1024+0.5) + 0x800000);  // v
      yuv += 4;
      rgb += 6;
    }
  }
}


DWORD CodecInst::CompressEnd() {
  if (yuy2_buffer) {
    delete[] yuy2_buffer;
    yuy2_buffer = 0;
  }
  if (median_buffer) {
    delete[] median_buffer;
    median_buffer = 0;
  }
  if (rgb_buffer) {
    delete[] rgb_buffer;
    rgb_buffer = 0;
  }
  return ICERR_OK;
}


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

static bool CanDecompress(LPBITMAPINFOHEADER lpbiIn) {
  int intype = GetBitmapType(lpbiIn);
  if (intype < 0)
    return IsLegalMethod(GetMethod(lpbiIn), intype != -1);
  else
    return (intype == 1 || intype == 2);
}


static bool CanDecompress(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
  if (!lpbiOut)
    return CanDecompress(lpbiIn);

  // must be 1:1 (no stretching)
  if (lpbiOut && (lpbiOut->biWidth != lpbiIn->biWidth || lpbiOut->biHeight != lpbiIn->biHeight))
    return false;

  int intype = GetBitmapType(lpbiIn);
  int outtype = GetBitmapType(lpbiOut);

  if (intype < 0) {
    if (!IsLegalMethod(GetMethod(lpbiIn), intype != -1))
      return false;
  }

  switch (intype) {
    case -1:
      // YUY2, RGB-24, RGB-32 output for compressed YUY2
      return (outtype == 1 || outtype == 3 || outtype == 4);
    case -2: case 1: case 2:
      // RGB-24, RGB-32 output only for YUY2/UYVY and compressed RGB
      return (outtype == 3 || outtype == 4);
    case -3:
      // RGB-32 output for compressed RGBA
      return (outtype == 4);
    default:
      return false;
  }
}

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


DWORD CodecInst::DecompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
  Msg("DecompressQuery: input = %s, output = %s\n", &PrintBitmapType(lpbiIn), &PrintBitmapType(lpbiOut));
  return CanDecompress(lpbiIn, lpbiOut) ? ICERR_OK : ICERR_BADFORMAT;
}


// This function should return "the output format which preserves the most
// information."  However, I now provide the option to return RGB format
// instead, since some programs treat the default format as the ONLY format.

DWORD CodecInst::DecompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {

  // if lpbiOut == NULL, then return the size required to hold an output format struct
  if (lpbiOut == NULL)
    return sizeof(BITMAPINFOHEADER);

  if (!CanDecompress(lpbiIn))
    return ICERR_BADFORMAT;

  *lpbiOut = *lpbiIn;
  lpbiOut->biSize = sizeof(BITMAPINFOHEADER);
  lpbiOut->biPlanes = 1;

  int intype = GetBitmapType(lpbiIn);
  if (intype == -3) {
    lpbiOut->biBitCount = 32;   // RGBA
    lpbiOut->biCompression = 0;
    lpbiOut->biSizeImage = lpbiIn->biWidth * lpbiIn->biHeight * 4;
  } else if (intype == -2 || intype == 1 || intype == 2 || SuggestRGB()) {
    lpbiOut->biBitCount = 24;   // RGB
    lpbiOut->biCompression = 0;
    lpbiOut->biSizeImage = lpbiIn->biWidth * lpbiIn->biHeight * 3;
  } else {
    lpbiOut->biBitCount = 16;       // YUY2
    lpbiOut->biCompression = FOURCC_YUY2;
    lpbiOut->biSizeImage = lpbiIn->biWidth * lpbiIn->biHeight * 2;
  }

  return ICERR_OK;
}


const unsigned char* InitializeDecodeTable(const unsigned char* hufftable, unsigned char* shift, DecodeTable* decode_table) {
  unsigned add_shifted[256];
  hufftable = InitializeShiftAddTables(hufftable, shift, add_shifted);
  char code_lengths[256];
  char code_firstbits[256];
  char table_lengths[32];
  memset(table_lengths,-1,32);
  int all_zero_code=-1;
  for (int i=0; i<256; ++i) {
    if (add_shifted[i]) {
      for (int firstbit=31; firstbit>=0; firstbit--) {
        if (add_shifted[i] & (1<<firstbit)) {
          code_firstbits[i] = firstbit;
          int length = shift[i] - (32-firstbit);
          code_lengths[i] = length;
          table_lengths[firstbit] = max(table_lengths[firstbit], length);
          break;
        }
      }
    } else {
      all_zero_code = i;
    }
  }
  unsigned char* p = decode_table->table_data;
  *p++ = 31;
  *p++ = all_zero_code;
  for (int j=0; j<32; ++j) {
    if (table_lengths[j] == -1) {
      decode_table->table_pointers[j] = decode_table->table_data;
    } else {
      decode_table->table_pointers[j] = p;
      *p++ = j-table_lengths[j];
      p += 1<<table_lengths[j];
    }
  }
  for (int k=0; k<256; ++k) {
    if (add_shifted[k]) {
      int firstbit = code_firstbits[k];
      int val = add_shifted[k] - (1<<firstbit);
      unsigned char* table = decode_table->table_pointers[firstbit];
      memset(&table[1+(val>>table[0])],
        k, 1<<(table_lengths[firstbit]-code_lengths[k]));
    }
  }
  return hufftable;
}


const unsigned char* InitializeDecodeTables(const unsigned char* hufftable) {
  hufftable = InitializeDecodeTable(hufftable, decode1_shift, &decode1);
  hufftable = InitializeDecodeTable(hufftable, decode2_shift, &decode2);
  hufftable = InitializeDecodeTable(hufftable, decode3_shift, &decode3);
  return hufftable;
}


DWORD CodecInst::DecompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
  Msg("DecompressBegin: input = %s, output = %s\n", &PrintBitmapType(lpbiIn), &PrintBitmapType(lpbiOut));

  DecompressEnd();  // free resources if necessary

  if (!CanDecompress(lpbiIn, lpbiOut))
    return ICERR_BADFORMAT;

  decompressing = true;

  int intype = GetBitmapType(lpbiIn);
  int outtype = GetBitmapType(lpbiOut);
  int method = GetMethod(lpbiIn);

  if (intype < 0) {
    InitializeDecodeTables(GetEmbeddedHuffmanTable(lpbiIn));
    decode_table_owner = this;
  }

  // allocate buffer if decompressing HFYU->YUY2->RGB
  if (intype == -1 && outtype >= 3)
    decompress_yuy2_buffer = new unsigned char[lpbiIn->biWidth * lpbiIn->biHeight * 2];

  InitClip();

  swapfields = !!GetPrivateProfileInt("debug", "decomp_swap_fields", false, "huffyuv.ini");

  return ICERR_OK;
}


static DWORD ConvertYUY2toRGB(LPBITMAPINFOHEADER lpbiOutput, void* _src, void* _dst) {
  const unsigned char* src = (const unsigned char*)_src;
  unsigned char* dst = (unsigned char*)_dst;
  int stride = lpbiOutput->biWidth * 2;
  const unsigned char* src_end = src + stride*lpbiOutput->biHeight;
  if (lpbiOutput->biBitCount == 32)
    mmx_YUY2toRGB32(src, dst, src_end, stride);
  else
    mmx_YUY2toRGB24(src, dst, src_end, stride);
  return ICERR_OK;
}

static DWORD ConvertUYVYtoRGB(LPBITMAPINFOHEADER lpbiOutput, void* _src, void* _dst) {
  const unsigned char* src = (const unsigned char*)_src;
  unsigned char* dst = (unsigned char*)_dst;
  int stride = lpbiOutput->biWidth * 2;
  const unsigned char* src_end = src + stride*lpbiOutput->biHeight;
  if (lpbiOutput->biBitCount == 32)
    mmx_UYVYtoRGB32(src, dst, src_end, stride);
  else
    mmx_UYVYtoRGB24(src, dst, src_end, stride);
  return ICERR_OK;
}


DWORD CodecInst::Decompress(ICDECOMPRESS* icinfo, DWORD dwSize) {

  // If you insert a Huffyuv-compressed AVI to a Premiere project and then
  // drag it on to the timeline, the following dialogue occurs:
  //
  // 1. Premiere calls ICDecompressBegin, asking Huffyuv to decompress
  //    to a bitmap with different dimensions than the compressed frame.
  //
  // 2. Huffyuv can't resize, so it returns ICERR_BADFORMAT.
  //
  // 3. Premiere calls ICDecompress without making another call to
  //    ICDecompressBegin.
  //
  // Therefore I now check for this case and compensate for Premiere's
  // negligence by making the DecompressBegin call myself.

  if (!decompressing) {
    DWORD retval = DecompressBegin(icinfo->lpbiInput, icinfo->lpbiOutput);
    if (retval != ICERR_OK)
      return retval;
  }

  icinfo->lpbiOutput->biSizeImage = (icinfo->lpbiOutput->biWidth * icinfo->lpbiOutput->biHeight * icinfo->lpbiOutput->biBitCount) >> 3;

  int intype = GetBitmapType(icinfo->lpbiInput);
  if (intype < 0) {
    int method = GetMethod(icinfo->lpbiInput);
    int outtype = GetBitmapType(icinfo->lpbiOutput);

    if (decode_table_owner != this) {
      InitializeDecodeTables(GetEmbeddedHuffmanTable(icinfo->lpbiInput));
      decode_table_owner = this;
    }

    const unsigned long* const in = (unsigned long*)icinfo->lpInput;
    unsigned char* const out = (unsigned char*)icinfo->lpOutput;

    if (intype == -1) {   // decompressing HFYU16
      int stride = icinfo->lpbiOutput->biWidth * 2;
      const int size = stride * icinfo->lpbiOutput->biHeight;
      if (icinfo->lpbiOutput->biHeight > 288) stride *= 2;      // if image is interlaced, double stride so fields are treated separately

      unsigned char* const yuy2 = outtype>1 ? decompress_yuy2_buffer : out;

      if (method == methodMedian) {
        asm_DecompressHFYU16(in, yuy2, yuy2+size);
        asm_MedianRestore(yuy2, yuy2+size, stride);
      }
      else {
        asm_DecompressHFYU16Delta(in, yuy2, yuy2+size);
        if (method == methodGrad)
          mmx_RowAccum(yuy2, yuy2+size, stride);
      }

      if (outtype>1)    // HFYU16->RGB
        ConvertYUY2toRGB(icinfo->lpbiOutput, yuy2, out);
    }
    else {   // decompressing HFYU24/HFYU32
      int stride = (icinfo->lpbiOutput->biWidth * icinfo->lpbiOutput->biBitCount) >> 3;
      const int size = stride * icinfo->lpbiOutput->biHeight;
      if (icinfo->lpbiOutput->biHeight > 288) stride *= 2;      // if image is interlaced, double stride so fields are treated separately
      if (intype == -2) {   // HFYU24->RGB
        if (outtype == 4) {
          if (method == methodLeft || method == methodOld)
            asm_DecompressHFYU24To32Delta(in, out, out+size);
          else
            asm_DecompressHFYU24To32DeltaDecorrelate(in, out, out+size);
        } else {
          if (method == methodLeft || method == methodOld)
            asm_DecompressHFYU24To24Delta(in, out, out+size);
          else
            asm_DecompressHFYU24To24DeltaDecorrelate(in, out, out+size);
        }
      }
      else if (intype == -3) {    // HFYU32->RGBA
        if (method == methodLeft || method == methodOld)
          asm_DecompressHFYU32To32Delta(in, out, out+size);
        else
          asm_DecompressHFYU32To32DeltaDecorrelate(in, out, out+size);
      }
      else
        return ICERR_BADFORMAT;

      if ((method&~flagDecorrelate) == methodGrad)
        mmx_RowAccum(out, out+size, stride);
    }

    if (swapfields && icinfo->lpbiOutput->biHeight > 288)
      asm_SwapFields(out, out+icinfo->lpbiOutput->biSizeImage,
       (icinfo->lpbiOutput->biWidth * icinfo->lpbiOutput->biBitCount) >> 3);

    return ICERR_OK;
  }
  else if (intype == 1) {   // YUY2->RGB
    return ConvertYUY2toRGB(icinfo->lpbiOutput, icinfo->lpInput, icinfo->lpOutput);
  }
  else if (intype == 2) {   // UYVY->RGB
    return ConvertUYVYtoRGB(icinfo->lpbiOutput, icinfo->lpInput, icinfo->lpOutput);
  }
  else
    return ICERR_BADFORMAT;
}


// palette-mapped output only
DWORD CodecInst::DecompressGetPalette(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
  return ICERR_BADFORMAT;
}


DWORD CodecInst::DecompressEnd() {
  if (decompress_yuy2_buffer) {
    delete[] decompress_yuy2_buffer;
    decompress_yuy2_buffer = 0;
  }
  decompressing = false;
  return ICERR_OK;
}

⌨️ 快捷键说明

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