c - 如何在不牺牲其功能的情况下将该函数拆分为更小的函数?

标签 c refactoring jpeg mjpeg

我从here获取了MJPEG解码的代码我正在尝试将 IDCT 的代码拆分为更小的函数。

原代码中的IDCT函数如下:

void IDCT(int32_t *input, uint8_t *output) {
    int32_t Y[64];
    int32_t k, l;

    for (k = 0; k < 8; k++) {
        for (l = 0; l < 8; l++) Y(k, l) = SCALE(input[(k << 3) + l], S_BITS);
        idct_1d(&Y(k, 0));
    }

    for (l = 0; l < 8; l++) {
        int32_t Yc[8];

        for (k = 0; k < 8; k++) Yc[k] = Y(k, l);

        idct_1d(Yc);

        for (k = 0; k < 8; k++) {
            int32_t r = 128 + DESCALE(Yc[k], S_BITS + 3);
            r = r > 0 ? (r < 255 ? r : 255) : 0;
            X(k, l) = r;
        }
    }
}

更多功能详情请参见this链接。

我能够通过以下方式进一步分解此代码:

在X方向:

void IDCTforX(int32_t *input, uint8_t *output) {

    int32_t Y[64];
    int32_t k, l;
    int32_t Yc[8];

    for (k = 0; k < 8; k++) {
        for (l = 0; l < 8; l++)
        {
            Y(k, l) = SCALE(input[(k << 3) + l], S_BITS);
        }
    }
}

void IDCTfor1dim(int32_t *input, uint8_t *output)
{
int32_t Y[64];
    int32_t k, l;
    int32_t Yc[8];

    for (k= 0; k < 8; k++)
    {
        idct_1d(&Y(k, 0));
    }
}

在 Y 方向:

void IDCTforY(int32_t *input, uint8_t *output) {

int32_t Y[64];
int32_t k, l;

for (l = 0; l < 8; l++) {
    int32_t Yc[8];
        for (k = 0; k < 8; k++)
        {
        Yc[k] = Y(k, l);
        }

        idct_1d(Yc);

    for (k = 0; k < 8; k++) {                   
    int32_t r = 128 + DESCALE(Yc[k], S_BITS + 3);
    r = r > 0 ? (r < 255 ? r : 255) : 0;
    X(k, l) = r;
    }
}

DESCALE的代码如下:

static inline int32_t DESCALE (int32_t x, int32_t n)
{
    return (x + (1 << (n - 1)) - (x < 0)) >> n;
}

按照上面所示的方式重新组织 IDCT 会得到与原始代码相同的输出。但是,按照以下方式重新组织 IDCTforY 的代码后,我得到了模糊的图像:

 void IDCTforY(int32_t *input, uint8_t *output) {

 int32_t Y[64];
  int32_t k, l;
int32_t Yc[8];

  for (l = 0; l < 8; l++) {

   for (k = 0; k < 8; k++)
    {
    Yc[k] = Y(k, l);
    }

    idct_1d(Yc);
    }
    //Running the loop for de-scaling separately....

  for (l = 0; l < 8; l++) {
  for (k = 0; k < 8; k++) {   
   int32_t r = 128 + DESCALE(Yc[k], S_BITS + 3);
    r = r > 0 ? (r < 255 ? r : 255) : 0;
    X(k, l) = r;
   }
    }
}

我的输出帧与上面的代码如下所示:

enter image description here

JPEG解码中图像模糊是什么意思?

如何以不损害代码性质的方式拆分 IDCTforY

最佳答案

函数 IDCT() 声明数组 Y[],该数组在所有 for 循环之间传输数据。在重构的代码中,每个函数都声明自己的 Y[] 数组。您对 Yc[] 数组犯了同样的错误。将数组设为全局并查看代码是否运行。

编辑2017_08-28

给 Yc[] 一个额外的维度:

void IDCTforY(int32_t *input, uint8_t *output) 
{
  int32_t Y[64];
  int32_t k, l;
  int32_t Yc[8][8];

  for (l = 0; l < 8; l++) 
  {
      for (k = 0; k < 8; k++)
          Yc[l][k] = Y(k, l);
      idct_1d(Yc[l]);
   }

   //Running the loop for de-scaling separately....

   for (l = 0; l < 8; l++) 
   {
       for (k = 0; k < 8; k++) 
       {   
           int32_t r = 128 + DESCALE(Yc[l][k], S_BITS + 3);
           r = r > 0 ? (r < 255 ? r : 255) : 0;
           X(k, l) = r;
       }
   }
}

编辑于2017-08-29

我无法解释光学效应,但你破坏了数据流。原来的代码是这样的:

for (l = 0; l < 8; l++) 
{
    int32_t Yc[8];

    Fill(Yc);

    idct_1d(Yc);

    Descale_and_WriteOut(Yc);
}

你创造了它:

int32_t Yc[8];
for (l = 0; l < 8; l++) 
{
    Fill(Yc);
    idct_1d(Yc);
}
for (l = 0; l < 8; l++) 
{
  Descale_and_WriteOut(Yc);
}

您会看到,只有输入和处理循环的最后一次迭代的结果才会传递到输出循环。我在 Yc[][] 中为每个 l 迭代提供了自己的内存。

关于c - 如何在不牺牲其功能的情况下将该函数拆分为更小的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45901912/

相关文章:

c - 用于嵌入式系统的 C 中最快的数组查找算法?

c++ - 禁用为 C/++ 中的某些行生成调试符号?

c - "Repassing"函数参数

c# - 有一个只有属性的类可以用于重构目的吗?

perl - 如何使用 Perl 在 Windows 上将 WMF 图像转换为 PNG 或 JPG?

delphi - 如何使用Delphi写入超过物理RAM的巨大JPEG?

C - AVL 树旋转实现上的空指针问题

.net - 如何重构在 .NET 中序列化的类?

c# - 使用 LinkSprite JPEG 彩色相机拍照

C#:简化许多类似的隐式运算符方法