优化自定义IDCT计算

时间:2019-01-12 20:48:56

标签: c++ image optimization jpeg

对于图像格式,我必须像压缩一样解码jpeg。这些步骤非常标准,但是颜色编码和产生的IDCT值似乎略有不同(我认为我不是专家)。这就是为什么使用标准JPEG库产生无效结果的原因,我不得不自己实现。

现在我对表演并不满意。通过执行一些不更改数据的缓存来优化天真的方法后,我需要约150ms才能解码1024x1024图像。其中120毫秒用在idct函数中,该函数如下所示:

float idctHelper(const int16_t *inBlock, int32_t u, int32_t v, int32_t blockWidth, int32_t blockHeight) {
    glm::vec<4, float, glm::packed_lowp> vec1{};
    glm::vec<4, float, glm::packed_lowp> vec2{};
    glm::vec<4, float, glm::packed_lowp> vec3{};

    float result = 0.0f;
    for (auto y = 0; y < blockHeight; ++y) {
        for (auto x = 0; x < blockWidth; x += 4) {
            const auto idx = (v * 8 + u) * 64 + y * 8 + x;
            vec1 = glm::vec<4, float, glm::packed_lowp>(inBlock[y * blockWidth + x], inBlock[y * blockWidth + x + 1], inBlock[y * blockWidth + x + 2], inBlock[y * blockWidth + x + 3]);
            vec2 = glm::vec<4, float, glm::packed_lowp>(idctLookup[idx], idctLookup[idx + 1], idctLookup[idx + 2], idctLookup[idx + 3]);
            vec3 = vec1 * vec2;
            result += vec3.x + vec3.y + vec3.z + vec3.w;
        }
    }

    return result;
}

template<typename T, typename U = T>
U clamp(T value, T min, T max) {
    return static_cast<U>(std::min<T>(std::max<T>(value, min), max));
}

void idct(int16_t *outBlock, int16_t *inBlock, bool isLuminance, int32_t blockWidth = 8, int32_t blockHeight = 8) {
    for (auto y = 0; y < blockHeight; ++y) {
        for (auto x = 0; x < blockWidth; ++x) {
            auto value = static_cast<int16_t>(std::round(
                    0.25f * idctHelper(inBlock, x, y, blockWidth, blockHeight)));
            if (isLuminance) {
                value = clamp<int16_t>(static_cast<int16_t>(value + 128), 0, 255);
            } else {
                value = clamp<int16_t>(value, -256, 255);
            }

            outBlock[y * blockWidth + x] = value;
        }
    }
}

如您所见,我试图(可能)使用SIMD和低精度运算来加快idctHelper的速度,但是现在我迷失在继续优化的地方。我真的很感谢任何想法或提示。

0 个答案:

没有答案