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

📄 subsample.c

📁 Motion JPEG编解码器源代码
💻 C
字号:
/* * subsample.c:  Routines to do chroma subsampling.  ("Work In Progress") * * *  Copyright (C) 2001 Matthew J. Marjanovic <maddog@mir.com> * * *  This program is free software; you can redistribute it and/or *  modify it under the terms of the GNU General Public License *  as published by the Free Software Foundation; either version 2 *  of the License, or (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. * */#include <config.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <mjpeg_types.h>#include "subsample.h"/************************************************************************* * Chroma Subsampling *************************************************************************//* vertical/horizontal interstitial siting * *    Y   Y   Y   Y *      C       C *    Y   Y   Y   Y * *    Y   Y   Y   Y *      C       C *    Y   Y   Y   Y * */static void ss_444_to_420jpeg(uint8_t *buffer, int width, int height){  uint8_t *in0, *in1, *out;  int x, y;  in0 = buffer;  in1 = buffer + width;  out = buffer;  for (y = 0; y < height; y += 2) {    for (x = 0; x < width; x += 2) {      *out = (in0[0] + in0[1] + in1[0] + in1[1]) >> 2;      in0 += 2;      in1 += 2;      out++;    }    in0 += width;    in1 += width;  }}/* vertical/horizontal interstitial siting * *    Y   Y   Y   Y *      C       C       C      inm *    Y   Y   Y   Y            *                   *    Y   Y   Y - Y           out0 *      C     | C |     C      in0 *    Y   Y   Y - Y           out1 * * *      C       C       C      inp * * *  Each iteration through the loop reconstitutes one 2x2 block of  *   pixels from the "surrounding" 3x3 block of samples... *  Boundary conditions are handled by cheap reflection; i.e. the *   center sample is simply reused. *               */             #define BLANK_CRB in0[1]#if 1 /* triangle/linear filter (otherwise, use the lame box filter) */static void ss_420jpeg_to_444(uint8_t *buffer, int width, int height){  uint8_t *inm, *in0, *inp, *out0, *out1;  uint8_t cmm, cm0, cmp, c0m, c00, c0p, cpm, cp0, cpp;  int x, y;  static uint8_t *saveme = NULL;  static int saveme_size = 0;  if (width > saveme_size) {    free(saveme);    saveme_size = width;    saveme = malloc(saveme_size * sizeof(saveme[0]));    assert(saveme != NULL);  }  memcpy(saveme, buffer, width);  in0 = buffer + (width * height / 4) - 2;  inm = in0 - width/2;  inp = in0 + width/2;  out1 = buffer + (width * height) - 1;  out0 = out1 - width;  for (y = height; y > 0; y -= 2) {    if (y == 2) {      in0 = saveme + width/2 - 2;      inp = in0 + width/2;    }    for (x = width; x > 0; x -= 2) {#if 0      if ((x == 2) && (y == 2)) {	cmm = in0[1];	cm0 = in0[1];	cmp = in0[2];	c0m = in0[1];	c0p = in0[2];	cpm = inp[1];	cp0 = inp[1];	cpp = inp[2];      } else if ((x == 2) && (y == height)) {	cmm = inm[1];	cm0 = inm[1];	cmp = inm[2];	c0m = in0[1];	c0p = in0[2];	cpm = in0[1];	cp0 = in0[1];	cpp = in0[2];      } else if ((x == width) && (y == height)) {	cmm = inm[0];	cm0 = inm[1];	cmp = inm[1];	c0m = in0[0];	c0p = in0[1];	cpm = in0[0];	cp0 = in0[1];	cpp = in0[1];      } else if ((x == width) && (y == 2)) {	cmm = in0[0];	cm0 = (y == 2) ? BLANK_CRB : inm[1];      cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2];      c0m = (x == 2) ? BLANK_CRB : in0[0];      c0p = (x == width) ? BLANK_CRB : in0[2];      cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0];      cp0 = (y == height) ? BLANK_CRB : inp[1];      cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2];      } else if (x == 2) {      cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0];      cm0 = (y == 2) ? BLANK_CRB : inm[1];      cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2];      c0m = (x == 2) ? BLANK_CRB : in0[0];      c0p = (x == width) ? BLANK_CRB : in0[2];      cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0];      cp0 = (y == height) ? BLANK_CRB : inp[1];      cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2];      } else if (y == 2) {      cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0];      cm0 = (y == 2) ? BLANK_CRB : inm[1];      cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2];      c0m = (x == 2) ? BLANK_CRB : in0[0];      c0p = (x == width) ? BLANK_CRB : in0[2];      cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0];      cp0 = (y == height) ? BLANK_CRB : inp[1];      cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2];      } else if (x == width) {      cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0];      cm0 = (y == 2) ? BLANK_CRB : inm[1];      cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2];      c0m = (x == 2) ? BLANK_CRB : in0[0];      c0p = (x == width) ? BLANK_CRB : in0[2];      cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0];      cp0 = (y == height) ? BLANK_CRB : inp[1];      cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2];      } else if (y == height) {      cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0];      cm0 = (y == 2) ? BLANK_CRB : inm[1];      cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2];      c0m = (x == 2) ? BLANK_CRB : in0[0];      c0p = (x == width) ? BLANK_CRB : in0[2];      cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0];      cp0 = (y == height) ? BLANK_CRB : inp[1];      cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2];      } else {      cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0];      cm0 = (y == 2) ? BLANK_CRB : inm[1];      cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2];      c0m = (x == 2) ? BLANK_CRB : in0[0];      c0p = (x == width) ? BLANK_CRB : in0[2];      cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0];      cp0 = (y == height) ? BLANK_CRB : inp[1];      cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2];      }      c00 = in0[1];      cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0];      cm0 = (y == 2) ? BLANK_CRB : inm[1];      cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2];      c0m = (x == 2) ? BLANK_CRB : in0[0];      c0p = (x == width) ? BLANK_CRB : in0[2];      cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0];      cp0 = (y == height) ? BLANK_CRB : inp[1];      cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2];#else      cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0];      cm0 = (y == 2) ? BLANK_CRB : inm[1];      cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2];      c0m = (x == 2) ? BLANK_CRB : in0[0];      c00 = in0[1];      c0p = (x == width) ? BLANK_CRB : in0[2];      cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0];      cp0 = (y == height) ? BLANK_CRB : inp[1];      cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2];#endif      inm--;      in0--;      inp--;      *(out1--) = (1*cpp + 3*(cp0+c0p) + 9*c00 + 8) >> 4;      *(out1--) = (1*cpm + 3*(cp0+c0m) + 9*c00 + 8) >> 4;      *(out0--) = (1*cmp + 3*(cm0+c0p) + 9*c00 + 8) >> 4;      *(out0--) = (1*cmm + 3*(cm0+c0m) + 9*c00 + 8) >> 4;    }    out1 -= width;    out0 -= width;  }}#elsestatic void ss_420jpeg_to_444(uint8_t *buffer, int width, int height){  uint8_t *in, *out0, *out1;  int x, y;  in = buffer + (width * height / 4) - 1;  out1 = buffer + (width * height) - 1;  out0 = out1 - width;  for (y = height - 1; y >= 0; y -= 2) {    for (x = width - 1; x >= 0; x -=2) {      uint8_t val = *(in--);      *(out1--) = val;      *(out1--) = val;      *(out0--) = val;      *(out0--) = val;    }    out0 -= width;    out1 -= width;  }}#endif      /* vertical intersitial siting; horizontal cositing * *    Y   Y   Y   Y *    C       C *    Y   Y   Y   Y * *    Y   Y   Y   Y *    C       C *    Y   Y   Y   Y * * [1,2,1] kernel for horizontal subsampling: * *    inX[0] [1] [2] *        |   |   | *    C   C   C   C *         \  |  / *          \ | / *            C */static void ss_444_to_420mpeg2(uint8_t *buffer, int width, int height){  uint8_t *in0, *in1, *out;  int x, y;  in0 = buffer;          /* points to */  in1 = buffer + width;  /* second of pair of lines */  out = buffer;  for (y = 0; y < height; y += 2) {    /* first column boundary condition -- just repeat it to right */    *out = (in0[0] + (2 * in0[0]) + in0[1] +	    in1[0] + (2 * in1[0]) + in1[1]) >> 3;    out++;    in0++;    in1++;    /* rest of columns just loop */    for (x = 2; x < width; x += 2) {      *out = (in0[0] + (2 * in0[1]) + in0[2] +	      in1[0] + (2 * in1[1]) + in1[2]) >> 3;      in0 += 2;      in1 += 2;      out++;    }    in0 += width + 1;    in1 += width + 1;  }}      int chroma_sub_implemented(int mode){  switch (mode) {  case Y4M_CHROMA_420JPEG:  case Y4M_CHROMA_420MPEG2:  case Y4M_CHROMA_444:    return 1; /* yes, supported */  case Y4M_CHROMA_420PALDV:  case Y4M_CHROMA_422:  case Y4M_CHROMA_411:  case Y4M_CHROMA_444ALPHA:  case Y4M_CHROMA_MONO:  default:    return 0; /* no, unsupported */  }}void chroma_subsample(int mode, uint8_t *ycbcr[], int width, int height){  switch (mode) {  case Y4M_CHROMA_444:  case Y4M_CHROMA_444ALPHA:  case Y4M_CHROMA_MONO:    break;  case Y4M_CHROMA_420JPEG:    ss_444_to_420jpeg(ycbcr[1], width, height);    ss_444_to_420jpeg(ycbcr[2], width, height);    break;  case Y4M_CHROMA_420MPEG2:    ss_444_to_420mpeg2(ycbcr[1], width, height);    ss_444_to_420mpeg2(ycbcr[2], width, height);    break;  default:    break;  }}int chroma_super_implemented(int mode){  switch (mode) {  case Y4M_CHROMA_420JPEG:  case Y4M_CHROMA_444:    return 1; /* yes, supported */  case Y4M_CHROMA_420MPEG2:  case Y4M_CHROMA_420PALDV:  case Y4M_CHROMA_422:  case Y4M_CHROMA_411:  case Y4M_CHROMA_444ALPHA:  case Y4M_CHROMA_MONO:  default:    return 0; /* no, unsupported */  }}void chroma_supersample(int mode, uint8_t *ycbcr[], int width, int height){  switch (mode) {  case Y4M_CHROMA_444:  case Y4M_CHROMA_444ALPHA:  case Y4M_CHROMA_MONO:    break;  case Y4M_CHROMA_420JPEG:    ss_420jpeg_to_444(ycbcr[1], width, height);    ss_420jpeg_to_444(ycbcr[2], width, height);    break;  case Y4M_CHROMA_420MPEG2:    //    ss_420mpeg2_to_444(ycbcr[1], width, height);    //    ss_420mpeg2_to_444(ycbcr[2], width, height);    //    exit(4);    //    break;  default:    break;  }}

⌨️ 快捷键说明

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