Для формата изображения я должен декодировать сжатие в формате JPEG. Шаги довольно стандартные, однако цветовое кодирование и полученные значения IDCT, кажется, немного отличаются (я думаю, я не эксперт). Вот почему, кажется, использование стандартной библиотеки JPEG дало неверные результаты, и мне пришлось реализовать ее самостоятельно.
Теперь я не очень доволен выступлением. После оптимизации наивного подхода путем выполнения некоторого кэширования данных, которое не изменяется, мне нужно ~ 150 мсек для декодирования изображения 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
, но теперь я немного растерян, где я могу продолжать оптимизировать это. Буду очень признателен за любую идею или подсказку.