Spaces:
Runtime error
Runtime error
优化Token溢出时的处理
Browse files- config.py +2 -0
- crazy_functions/test_project/cpp/longcode/jpgd.cpp +3276 -0
- crazy_functions/test_project/cpp/longcode/jpge.cpp +1049 -0
- crazy_functions/test_project/cpp/longcode/prod_cons.h +433 -0
- crazy_functions/高级功能函数模板.py +1 -1
- functional_crazy.py +7 -6
- main.py +62 -43
- predict.py +9 -3
- toolbox.py +12 -13
config.py
CHANGED
@@ -23,6 +23,8 @@ else:
|
|
23 |
|
24 |
|
25 |
# [step 3]>> 以下配置可以优化体验,但大部分场合下并不需要修改
|
|
|
|
|
26 |
|
27 |
# 发送请求到OpenAI后,等待多久判定为超时
|
28 |
TIMEOUT_SECONDS = 25
|
|
|
23 |
|
24 |
|
25 |
# [step 3]>> 以下配置可以优化体验,但大部分场合下并不需要修改
|
26 |
+
# 对话窗的高度
|
27 |
+
CHATBOT_HEIGHT = 1117
|
28 |
|
29 |
# 发送请求到OpenAI后,等待多久判定为超时
|
30 |
TIMEOUT_SECONDS = 25
|
crazy_functions/test_project/cpp/longcode/jpgd.cpp
ADDED
@@ -0,0 +1,3276 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// jpgd.cpp - C++ class for JPEG decompression.
|
2 |
+
// Public domain, Rich Geldreich <[email protected]>
|
3 |
+
// Last updated Apr. 16, 2011
|
4 |
+
// Alex Evans: Linear memory allocator (taken from jpge.h).
|
5 |
+
//
|
6 |
+
// Supports progressive and baseline sequential JPEG image files, and the most common chroma subsampling factors: Y, H1V1, H2V1, H1V2, and H2V2.
|
7 |
+
//
|
8 |
+
// Chroma upsampling quality: H2V2 is upsampled in the frequency domain, H2V1 and H1V2 are upsampled using point sampling.
|
9 |
+
// Chroma upsampling reference: "Fast Scheme for Image Size Change in the Compressed Domain"
|
10 |
+
// http://vision.ai.uiuc.edu/~dugad/research/dct/index.html
|
11 |
+
|
12 |
+
#include "jpgd.h"
|
13 |
+
#include <string.h>
|
14 |
+
|
15 |
+
#include <assert.h>
|
16 |
+
// BEGIN EPIC MOD
|
17 |
+
#define JPGD_ASSERT(x) { assert(x); CA_ASSUME(x); } (void)0
|
18 |
+
// END EPIC MOD
|
19 |
+
|
20 |
+
#ifdef _MSC_VER
|
21 |
+
#pragma warning (disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
|
22 |
+
#endif
|
23 |
+
|
24 |
+
// Set to 1 to enable freq. domain chroma upsampling on images using H2V2 subsampling (0=faster nearest neighbor sampling).
|
25 |
+
// This is slower, but results in higher quality on images with highly saturated colors.
|
26 |
+
#define JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING 1
|
27 |
+
|
28 |
+
#define JPGD_TRUE (1)
|
29 |
+
#define JPGD_FALSE (0)
|
30 |
+
|
31 |
+
#define JPGD_MAX(a,b) (((a)>(b)) ? (a) : (b))
|
32 |
+
#define JPGD_MIN(a,b) (((a)<(b)) ? (a) : (b))
|
33 |
+
|
34 |
+
namespace jpgd {
|
35 |
+
|
36 |
+
static inline void *jpgd_malloc(size_t nSize) { return FMemory::Malloc(nSize); }
|
37 |
+
static inline void jpgd_free(void *p) { FMemory::Free(p); }
|
38 |
+
|
39 |
+
// BEGIN EPIC MOD
|
40 |
+
//@UE3 - use UE3 BGRA encoding instead of assuming RGBA
|
41 |
+
// stolen from IImageWrapper.h
|
42 |
+
enum ERGBFormatJPG
|
43 |
+
{
|
44 |
+
Invalid = -1,
|
45 |
+
RGBA = 0,
|
46 |
+
BGRA = 1,
|
47 |
+
Gray = 2,
|
48 |
+
};
|
49 |
+
static ERGBFormatJPG jpg_format;
|
50 |
+
// END EPIC MOD
|
51 |
+
|
52 |
+
// DCT coefficients are stored in this sequence.
|
53 |
+
static int g_ZAG[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 };
|
54 |
+
|
55 |
+
enum JPEG_MARKER
|
56 |
+
{
|
57 |
+
M_SOF0 = 0xC0, M_SOF1 = 0xC1, M_SOF2 = 0xC2, M_SOF3 = 0xC3, M_SOF5 = 0xC5, M_SOF6 = 0xC6, M_SOF7 = 0xC7, M_JPG = 0xC8,
|
58 |
+
M_SOF9 = 0xC9, M_SOF10 = 0xCA, M_SOF11 = 0xCB, M_SOF13 = 0xCD, M_SOF14 = 0xCE, M_SOF15 = 0xCF, M_DHT = 0xC4, M_DAC = 0xCC,
|
59 |
+
M_RST0 = 0xD0, M_RST1 = 0xD1, M_RST2 = 0xD2, M_RST3 = 0xD3, M_RST4 = 0xD4, M_RST5 = 0xD5, M_RST6 = 0xD6, M_RST7 = 0xD7,
|
60 |
+
M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_DNL = 0xDC, M_DRI = 0xDD, M_DHP = 0xDE, M_EXP = 0xDF,
|
61 |
+
M_APP0 = 0xE0, M_APP15 = 0xEF, M_JPG0 = 0xF0, M_JPG13 = 0xFD, M_COM = 0xFE, M_TEM = 0x01, M_ERROR = 0x100, RST0 = 0xD0
|
62 |
+
};
|
63 |
+
|
64 |
+
enum JPEG_SUBSAMPLING { JPGD_GRAYSCALE = 0, JPGD_YH1V1, JPGD_YH2V1, JPGD_YH1V2, JPGD_YH2V2 };
|
65 |
+
|
66 |
+
#define CONST_BITS 13
|
67 |
+
#define PASS1_BITS 2
|
68 |
+
#define SCALEDONE ((int32)1)
|
69 |
+
|
70 |
+
#define FIX_0_298631336 ((int32)2446) /* FIX(0.298631336) */
|
71 |
+
#define FIX_0_390180644 ((int32)3196) /* FIX(0.390180644) */
|
72 |
+
#define FIX_0_541196100 ((int32)4433) /* FIX(0.541196100) */
|
73 |
+
#define FIX_0_765366865 ((int32)6270) /* FIX(0.765366865) */
|
74 |
+
#define FIX_0_899976223 ((int32)7373) /* FIX(0.899976223) */
|
75 |
+
#define FIX_1_175875602 ((int32)9633) /* FIX(1.175875602) */
|
76 |
+
#define FIX_1_501321110 ((int32)12299) /* FIX(1.501321110) */
|
77 |
+
#define FIX_1_847759065 ((int32)15137) /* FIX(1.847759065) */
|
78 |
+
#define FIX_1_961570560 ((int32)16069) /* FIX(1.961570560) */
|
79 |
+
#define FIX_2_053119869 ((int32)16819) /* FIX(2.053119869) */
|
80 |
+
#define FIX_2_562915447 ((int32)20995) /* FIX(2.562915447) */
|
81 |
+
#define FIX_3_072711026 ((int32)25172) /* FIX(3.072711026) */
|
82 |
+
|
83 |
+
#define DESCALE(x,n) (((x) + (SCALEDONE << ((n)-1))) >> (n))
|
84 |
+
#define DESCALE_ZEROSHIFT(x,n) (((x) + (128 << (n)) + (SCALEDONE << ((n)-1))) >> (n))
|
85 |
+
|
86 |
+
#define MULTIPLY(var, cnst) ((var) * (cnst))
|
87 |
+
|
88 |
+
#define CLAMP(i) ((static_cast<uint>(i) > 255) ? (((~i) >> 31) & 0xFF) : (i))
|
89 |
+
|
90 |
+
// Compiler creates a fast path 1D IDCT for X non-zero columns
|
91 |
+
template <int NONZERO_COLS>
|
92 |
+
struct Row
|
93 |
+
{
|
94 |
+
static void idct(int* pTemp, const jpgd_block_t* pSrc)
|
95 |
+
{
|
96 |
+
// ACCESS_COL() will be optimized at compile time to either an array access, or 0.
|
97 |
+
#define ACCESS_COL(x) (((x) < NONZERO_COLS) ? (int)pSrc[x] : 0)
|
98 |
+
|
99 |
+
const int z2 = ACCESS_COL(2), z3 = ACCESS_COL(6);
|
100 |
+
|
101 |
+
const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
|
102 |
+
const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
|
103 |
+
const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
|
104 |
+
|
105 |
+
const int tmp0 = (ACCESS_COL(0) + ACCESS_COL(4)) << CONST_BITS;
|
106 |
+
const int tmp1 = (ACCESS_COL(0) - ACCESS_COL(4)) << CONST_BITS;
|
107 |
+
|
108 |
+
const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
|
109 |
+
|
110 |
+
const int atmp0 = ACCESS_COL(7), atmp1 = ACCESS_COL(5), atmp2 = ACCESS_COL(3), atmp3 = ACCESS_COL(1);
|
111 |
+
|
112 |
+
const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3;
|
113 |
+
const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602);
|
114 |
+
|
115 |
+
const int az1 = MULTIPLY(bz1, - FIX_0_899976223);
|
116 |
+
const int az2 = MULTIPLY(bz2, - FIX_2_562915447);
|
117 |
+
const int az3 = MULTIPLY(bz3, - FIX_1_961570560) + bz5;
|
118 |
+
const int az4 = MULTIPLY(bz4, - FIX_0_390180644) + bz5;
|
119 |
+
|
120 |
+
const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3;
|
121 |
+
const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4;
|
122 |
+
const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3;
|
123 |
+
const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4;
|
124 |
+
|
125 |
+
pTemp[0] = DESCALE(tmp10 + btmp3, CONST_BITS-PASS1_BITS);
|
126 |
+
pTemp[7] = DESCALE(tmp10 - btmp3, CONST_BITS-PASS1_BITS);
|
127 |
+
pTemp[1] = DESCALE(tmp11 + btmp2, CONST_BITS-PASS1_BITS);
|
128 |
+
pTemp[6] = DESCALE(tmp11 - btmp2, CONST_BITS-PASS1_BITS);
|
129 |
+
pTemp[2] = DESCALE(tmp12 + btmp1, CONST_BITS-PASS1_BITS);
|
130 |
+
pTemp[5] = DESCALE(tmp12 - btmp1, CONST_BITS-PASS1_BITS);
|
131 |
+
pTemp[3] = DESCALE(tmp13 + btmp0, CONST_BITS-PASS1_BITS);
|
132 |
+
pTemp[4] = DESCALE(tmp13 - btmp0, CONST_BITS-PASS1_BITS);
|
133 |
+
}
|
134 |
+
};
|
135 |
+
|
136 |
+
template <>
|
137 |
+
struct Row<0>
|
138 |
+
{
|
139 |
+
static void idct(int* pTemp, const jpgd_block_t* pSrc)
|
140 |
+
{
|
141 |
+
#ifdef _MSC_VER
|
142 |
+
pTemp; pSrc;
|
143 |
+
#endif
|
144 |
+
}
|
145 |
+
};
|
146 |
+
|
147 |
+
template <>
|
148 |
+
struct Row<1>
|
149 |
+
{
|
150 |
+
static void idct(int* pTemp, const jpgd_block_t* pSrc)
|
151 |
+
{
|
152 |
+
const int dcval = (pSrc[0] << PASS1_BITS);
|
153 |
+
|
154 |
+
pTemp[0] = dcval;
|
155 |
+
pTemp[1] = dcval;
|
156 |
+
pTemp[2] = dcval;
|
157 |
+
pTemp[3] = dcval;
|
158 |
+
pTemp[4] = dcval;
|
159 |
+
pTemp[5] = dcval;
|
160 |
+
pTemp[6] = dcval;
|
161 |
+
pTemp[7] = dcval;
|
162 |
+
}
|
163 |
+
};
|
164 |
+
|
165 |
+
// Compiler creates a fast path 1D IDCT for X non-zero rows
|
166 |
+
template <int NONZERO_ROWS>
|
167 |
+
struct Col
|
168 |
+
{
|
169 |
+
static void idct(uint8* pDst_ptr, const int* pTemp)
|
170 |
+
{
|
171 |
+
// ACCESS_ROW() will be optimized at compile time to either an array access, or 0.
|
172 |
+
#define ACCESS_ROW(x) (((x) < NONZERO_ROWS) ? pTemp[x * 8] : 0)
|
173 |
+
|
174 |
+
const int z2 = ACCESS_ROW(2);
|
175 |
+
const int z3 = ACCESS_ROW(6);
|
176 |
+
|
177 |
+
const int z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
|
178 |
+
const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
|
179 |
+
const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
|
180 |
+
|
181 |
+
const int tmp0 = (ACCESS_ROW(0) + ACCESS_ROW(4)) << CONST_BITS;
|
182 |
+
const int tmp1 = (ACCESS_ROW(0) - ACCESS_ROW(4)) << CONST_BITS;
|
183 |
+
|
184 |
+
const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
|
185 |
+
|
186 |
+
const int atmp0 = ACCESS_ROW(7), atmp1 = ACCESS_ROW(5), atmp2 = ACCESS_ROW(3), atmp3 = ACCESS_ROW(1);
|
187 |
+
|
188 |
+
const int bz1 = atmp0 + atmp3, bz2 = atmp1 + atmp2, bz3 = atmp0 + atmp2, bz4 = atmp1 + atmp3;
|
189 |
+
const int bz5 = MULTIPLY(bz3 + bz4, FIX_1_175875602);
|
190 |
+
|
191 |
+
const int az1 = MULTIPLY(bz1, - FIX_0_899976223);
|
192 |
+
const int az2 = MULTIPLY(bz2, - FIX_2_562915447);
|
193 |
+
const int az3 = MULTIPLY(bz3, - FIX_1_961570560) + bz5;
|
194 |
+
const int az4 = MULTIPLY(bz4, - FIX_0_390180644) + bz5;
|
195 |
+
|
196 |
+
const int btmp0 = MULTIPLY(atmp0, FIX_0_298631336) + az1 + az3;
|
197 |
+
const int btmp1 = MULTIPLY(atmp1, FIX_2_053119869) + az2 + az4;
|
198 |
+
const int btmp2 = MULTIPLY(atmp2, FIX_3_072711026) + az2 + az3;
|
199 |
+
const int btmp3 = MULTIPLY(atmp3, FIX_1_501321110) + az1 + az4;
|
200 |
+
|
201 |
+
int i = DESCALE_ZEROSHIFT(tmp10 + btmp3, CONST_BITS+PASS1_BITS+3);
|
202 |
+
pDst_ptr[8*0] = (uint8)CLAMP(i);
|
203 |
+
|
204 |
+
i = DESCALE_ZEROSHIFT(tmp10 - btmp3, CONST_BITS+PASS1_BITS+3);
|
205 |
+
pDst_ptr[8*7] = (uint8)CLAMP(i);
|
206 |
+
|
207 |
+
i = DESCALE_ZEROSHIFT(tmp11 + btmp2, CONST_BITS+PASS1_BITS+3);
|
208 |
+
pDst_ptr[8*1] = (uint8)CLAMP(i);
|
209 |
+
|
210 |
+
i = DESCALE_ZEROSHIFT(tmp11 - btmp2, CONST_BITS+PASS1_BITS+3);
|
211 |
+
pDst_ptr[8*6] = (uint8)CLAMP(i);
|
212 |
+
|
213 |
+
i = DESCALE_ZEROSHIFT(tmp12 + btmp1, CONST_BITS+PASS1_BITS+3);
|
214 |
+
pDst_ptr[8*2] = (uint8)CLAMP(i);
|
215 |
+
|
216 |
+
i = DESCALE_ZEROSHIFT(tmp12 - btmp1, CONST_BITS+PASS1_BITS+3);
|
217 |
+
pDst_ptr[8*5] = (uint8)CLAMP(i);
|
218 |
+
|
219 |
+
i = DESCALE_ZEROSHIFT(tmp13 + btmp0, CONST_BITS+PASS1_BITS+3);
|
220 |
+
pDst_ptr[8*3] = (uint8)CLAMP(i);
|
221 |
+
|
222 |
+
i = DESCALE_ZEROSHIFT(tmp13 - btmp0, CONST_BITS+PASS1_BITS+3);
|
223 |
+
pDst_ptr[8*4] = (uint8)CLAMP(i);
|
224 |
+
}
|
225 |
+
};
|
226 |
+
|
227 |
+
template <>
|
228 |
+
struct Col<1>
|
229 |
+
{
|
230 |
+
static void idct(uint8* pDst_ptr, const int* pTemp)
|
231 |
+
{
|
232 |
+
int dcval = DESCALE_ZEROSHIFT(pTemp[0], PASS1_BITS+3);
|
233 |
+
const uint8 dcval_clamped = (uint8)CLAMP(dcval);
|
234 |
+
pDst_ptr[0*8] = dcval_clamped;
|
235 |
+
pDst_ptr[1*8] = dcval_clamped;
|
236 |
+
pDst_ptr[2*8] = dcval_clamped;
|
237 |
+
pDst_ptr[3*8] = dcval_clamped;
|
238 |
+
pDst_ptr[4*8] = dcval_clamped;
|
239 |
+
pDst_ptr[5*8] = dcval_clamped;
|
240 |
+
pDst_ptr[6*8] = dcval_clamped;
|
241 |
+
pDst_ptr[7*8] = dcval_clamped;
|
242 |
+
}
|
243 |
+
};
|
244 |
+
|
245 |
+
static const uint8 s_idct_row_table[] =
|
246 |
+
{
|
247 |
+
1,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0, 2,1,0,0,0,0,0,0, 2,1,1,0,0,0,0,0, 2,2,1,0,0,0,0,0, 3,2,1,0,0,0,0,0, 4,2,1,0,0,0,0,0, 4,3,1,0,0,0,0,0,
|
248 |
+
4,3,2,0,0,0,0,0, 4,3,2,1,0,0,0,0, 4,3,2,1,1,0,0,0, 4,3,2,2,1,0,0,0, 4,3,3,2,1,0,0,0, 4,4,3,2,1,0,0,0, 5,4,3,2,1,0,0,0, 6,4,3,2,1,0,0,0,
|
249 |
+
6,5,3,2,1,0,0,0, 6,5,4,2,1,0,0,0, 6,5,4,3,1,0,0,0, 6,5,4,3,2,0,0,0, 6,5,4,3,2,1,0,0, 6,5,4,3,2,1,1,0, 6,5,4,3,2,2,1,0, 6,5,4,3,3,2,1,0,
|
250 |
+
6,5,4,4,3,2,1,0, 6,5,5,4,3,2,1,0, 6,6,5,4,3,2,1,0, 7,6,5,4,3,2,1,0, 8,6,5,4,3,2,1,0, 8,7,5,4,3,2,1,0, 8,7,6,4,3,2,1,0, 8,7,6,5,3,2,1,0,
|
251 |
+
8,7,6,5,4,2,1,0, 8,7,6,5,4,3,1,0, 8,7,6,5,4,3,2,0, 8,7,6,5,4,3,2,1, 8,7,6,5,4,3,2,2, 8,7,6,5,4,3,3,2, 8,7,6,5,4,4,3,2, 8,7,6,5,5,4,3,2,
|
252 |
+
8,7,6,6,5,4,3,2, 8,7,7,6,5,4,3,2, 8,8,7,6,5,4,3,2, 8,8,8,6,5,4,3,2, 8,8,8,7,5,4,3,2, 8,8,8,7,6,4,3,2, 8,8,8,7,6,5,3,2, 8,8,8,7,6,5,4,2,
|
253 |
+
8,8,8,7,6,5,4,3, 8,8,8,7,6,5,4,4, 8,8,8,7,6,5,5,4, 8,8,8,7,6,6,5,4, 8,8,8,7,7,6,5,4, 8,8,8,8,7,6,5,4, 8,8,8,8,8,6,5,4, 8,8,8,8,8,7,5,4,
|
254 |
+
8,8,8,8,8,7,6,4, 8,8,8,8,8,7,6,5, 8,8,8,8,8,7,6,6, 8,8,8,8,8,7,7,6, 8,8,8,8,8,8,7,6, 8,8,8,8,8,8,8,6, 8,8,8,8,8,8,8,7, 8,8,8,8,8,8,8,8,
|
255 |
+
};
|
256 |
+
|
257 |
+
static const uint8 s_idct_col_table[] = { 1, 1, 2, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 };
|
258 |
+
|
259 |
+
void idct(const jpgd_block_t* pSrc_ptr, uint8* pDst_ptr, int block_max_zag)
|
260 |
+
{
|
261 |
+
JPGD_ASSERT(block_max_zag >= 1);
|
262 |
+
JPGD_ASSERT(block_max_zag <= 64);
|
263 |
+
|
264 |
+
if (block_max_zag == 1)
|
265 |
+
{
|
266 |
+
int k = ((pSrc_ptr[0] + 4) >> 3) + 128;
|
267 |
+
k = CLAMP(k);
|
268 |
+
k = k | (k<<8);
|
269 |
+
k = k | (k<<16);
|
270 |
+
|
271 |
+
for (int i = 8; i > 0; i--)
|
272 |
+
{
|
273 |
+
*(int*)&pDst_ptr[0] = k;
|
274 |
+
*(int*)&pDst_ptr[4] = k;
|
275 |
+
pDst_ptr += 8;
|
276 |
+
}
|
277 |
+
return;
|
278 |
+
}
|
279 |
+
|
280 |
+
int temp[64];
|
281 |
+
|
282 |
+
const jpgd_block_t* pSrc = pSrc_ptr;
|
283 |
+
int* pTemp = temp;
|
284 |
+
|
285 |
+
const uint8* pRow_tab = &s_idct_row_table[(block_max_zag - 1) * 8];
|
286 |
+
int i;
|
287 |
+
for (i = 8; i > 0; i--, pRow_tab++)
|
288 |
+
{
|
289 |
+
switch (*pRow_tab)
|
290 |
+
{
|
291 |
+
case 0: Row<0>::idct(pTemp, pSrc); break;
|
292 |
+
case 1: Row<1>::idct(pTemp, pSrc); break;
|
293 |
+
case 2: Row<2>::idct(pTemp, pSrc); break;
|
294 |
+
case 3: Row<3>::idct(pTemp, pSrc); break;
|
295 |
+
case 4: Row<4>::idct(pTemp, pSrc); break;
|
296 |
+
case 5: Row<5>::idct(pTemp, pSrc); break;
|
297 |
+
case 6: Row<6>::idct(pTemp, pSrc); break;
|
298 |
+
case 7: Row<7>::idct(pTemp, pSrc); break;
|
299 |
+
case 8: Row<8>::idct(pTemp, pSrc); break;
|
300 |
+
}
|
301 |
+
|
302 |
+
pSrc += 8;
|
303 |
+
pTemp += 8;
|
304 |
+
}
|
305 |
+
|
306 |
+
pTemp = temp;
|
307 |
+
|
308 |
+
const int nonzero_rows = s_idct_col_table[block_max_zag - 1];
|
309 |
+
for (i = 8; i > 0; i--)
|
310 |
+
{
|
311 |
+
switch (nonzero_rows)
|
312 |
+
{
|
313 |
+
case 1: Col<1>::idct(pDst_ptr, pTemp); break;
|
314 |
+
case 2: Col<2>::idct(pDst_ptr, pTemp); break;
|
315 |
+
case 3: Col<3>::idct(pDst_ptr, pTemp); break;
|
316 |
+
case 4: Col<4>::idct(pDst_ptr, pTemp); break;
|
317 |
+
case 5: Col<5>::idct(pDst_ptr, pTemp); break;
|
318 |
+
case 6: Col<6>::idct(pDst_ptr, pTemp); break;
|
319 |
+
case 7: Col<7>::idct(pDst_ptr, pTemp); break;
|
320 |
+
case 8: Col<8>::idct(pDst_ptr, pTemp); break;
|
321 |
+
}
|
322 |
+
|
323 |
+
pTemp++;
|
324 |
+
pDst_ptr++;
|
325 |
+
}
|
326 |
+
}
|
327 |
+
|
328 |
+
void idct_4x4(const jpgd_block_t* pSrc_ptr, uint8* pDst_ptr)
|
329 |
+
{
|
330 |
+
int temp[64];
|
331 |
+
int* pTemp = temp;
|
332 |
+
const jpgd_block_t* pSrc = pSrc_ptr;
|
333 |
+
|
334 |
+
for (int i = 4; i > 0; i--)
|
335 |
+
{
|
336 |
+
Row<4>::idct(pTemp, pSrc);
|
337 |
+
pSrc += 8;
|
338 |
+
pTemp += 8;
|
339 |
+
}
|
340 |
+
|
341 |
+
pTemp = temp;
|
342 |
+
for (int i = 8; i > 0; i--)
|
343 |
+
{
|
344 |
+
Col<4>::idct(pDst_ptr, pTemp);
|
345 |
+
pTemp++;
|
346 |
+
pDst_ptr++;
|
347 |
+
}
|
348 |
+
}
|
349 |
+
|
350 |
+
// Retrieve one character from the input stream.
|
351 |
+
inline uint jpeg_decoder::get_char()
|
352 |
+
{
|
353 |
+
// Any bytes remaining in buffer?
|
354 |
+
if (!m_in_buf_left)
|
355 |
+
{
|
356 |
+
// Try to get more bytes.
|
357 |
+
prep_in_buffer();
|
358 |
+
// Still nothing to get?
|
359 |
+
if (!m_in_buf_left)
|
360 |
+
{
|
361 |
+
// Pad the end of the stream with 0xFF 0xD9 (EOI marker)
|
362 |
+
int t = m_tem_flag;
|
363 |
+
m_tem_flag ^= 1;
|
364 |
+
if (t)
|
365 |
+
return 0xD9;
|
366 |
+
else
|
367 |
+
return 0xFF;
|
368 |
+
}
|
369 |
+
}
|
370 |
+
|
371 |
+
uint c = *m_pIn_buf_ofs++;
|
372 |
+
m_in_buf_left--;
|
373 |
+
|
374 |
+
return c;
|
375 |
+
}
|
376 |
+
|
377 |
+
// Same as previous method, except can indicate if the character is a pad character or not.
|
378 |
+
inline uint jpeg_decoder::get_char(bool *pPadding_flag)
|
379 |
+
{
|
380 |
+
if (!m_in_buf_left)
|
381 |
+
{
|
382 |
+
prep_in_buffer();
|
383 |
+
if (!m_in_buf_left)
|
384 |
+
{
|
385 |
+
*pPadding_flag = true;
|
386 |
+
int t = m_tem_flag;
|
387 |
+
m_tem_flag ^= 1;
|
388 |
+
if (t)
|
389 |
+
return 0xD9;
|
390 |
+
else
|
391 |
+
return 0xFF;
|
392 |
+
}
|
393 |
+
}
|
394 |
+
|
395 |
+
*pPadding_flag = false;
|
396 |
+
|
397 |
+
uint c = *m_pIn_buf_ofs++;
|
398 |
+
m_in_buf_left--;
|
399 |
+
|
400 |
+
return c;
|
401 |
+
}
|
402 |
+
|
403 |
+
// Inserts a previously retrieved character back into the input buffer.
|
404 |
+
inline void jpeg_decoder::stuff_char(uint8 q)
|
405 |
+
{
|
406 |
+
*(--m_pIn_buf_ofs) = q;
|
407 |
+
m_in_buf_left++;
|
408 |
+
}
|
409 |
+
|
410 |
+
// Retrieves one character from the input stream, but does not read past markers. Will continue to return 0xFF when a marker is encountered.
|
411 |
+
inline uint8 jpeg_decoder::get_octet()
|
412 |
+
{
|
413 |
+
bool padding_flag;
|
414 |
+
int c = get_char(&padding_flag);
|
415 |
+
|
416 |
+
if (c == 0xFF)
|
417 |
+
{
|
418 |
+
if (padding_flag)
|
419 |
+
return 0xFF;
|
420 |
+
|
421 |
+
c = get_char(&padding_flag);
|
422 |
+
if (padding_flag)
|
423 |
+
{
|
424 |
+
stuff_char(0xFF);
|
425 |
+
return 0xFF;
|
426 |
+
}
|
427 |
+
|
428 |
+
if (c == 0x00)
|
429 |
+
return 0xFF;
|
430 |
+
else
|
431 |
+
{
|
432 |
+
stuff_char(static_cast<uint8>(c));
|
433 |
+
stuff_char(0xFF);
|
434 |
+
return 0xFF;
|
435 |
+
}
|
436 |
+
}
|
437 |
+
|
438 |
+
return static_cast<uint8>(c);
|
439 |
+
}
|
440 |
+
|
441 |
+
// Retrieves a variable number of bits from the input stream. Does not recognize markers.
|
442 |
+
inline uint jpeg_decoder::get_bits(int num_bits)
|
443 |
+
{
|
444 |
+
if (!num_bits)
|
445 |
+
return 0;
|
446 |
+
|
447 |
+
uint i = m_bit_buf >> (32 - num_bits);
|
448 |
+
|
449 |
+
if ((m_bits_left -= num_bits) <= 0)
|
450 |
+
{
|
451 |
+
m_bit_buf <<= (num_bits += m_bits_left);
|
452 |
+
|
453 |
+
uint c1 = get_char();
|
454 |
+
uint c2 = get_char();
|
455 |
+
m_bit_buf = (m_bit_buf & 0xFFFF0000) | (c1 << 8) | c2;
|
456 |
+
|
457 |
+
m_bit_buf <<= -m_bits_left;
|
458 |
+
|
459 |
+
m_bits_left += 16;
|
460 |
+
|
461 |
+
JPGD_ASSERT(m_bits_left >= 0);
|
462 |
+
}
|
463 |
+
else
|
464 |
+
m_bit_buf <<= num_bits;
|
465 |
+
|
466 |
+
return i;
|
467 |
+
}
|
468 |
+
|
469 |
+
// Retrieves a variable number of bits from the input stream. Markers will not be read into the input bit buffer. Instead, an infinite number of all 1's will be returned when a marker is encountered.
|
470 |
+
inline uint jpeg_decoder::get_bits_no_markers(int num_bits)
|
471 |
+
{
|
472 |
+
if (!num_bits)
|
473 |
+
return 0;
|
474 |
+
|
475 |
+
uint i = m_bit_buf >> (32 - num_bits);
|
476 |
+
|
477 |
+
if ((m_bits_left -= num_bits) <= 0)
|
478 |
+
{
|
479 |
+
m_bit_buf <<= (num_bits += m_bits_left);
|
480 |
+
|
481 |
+
if ((m_in_buf_left < 2) || (m_pIn_buf_ofs[0] == 0xFF) || (m_pIn_buf_ofs[1] == 0xFF))
|
482 |
+
{
|
483 |
+
uint c1 = get_octet();
|
484 |
+
uint c2 = get_octet();
|
485 |
+
m_bit_buf |= (c1 << 8) | c2;
|
486 |
+
}
|
487 |
+
else
|
488 |
+
{
|
489 |
+
m_bit_buf |= ((uint)m_pIn_buf_ofs[0] << 8) | m_pIn_buf_ofs[1];
|
490 |
+
m_in_buf_left -= 2;
|
491 |
+
m_pIn_buf_ofs += 2;
|
492 |
+
}
|
493 |
+
|
494 |
+
m_bit_buf <<= -m_bits_left;
|
495 |
+
|
496 |
+
m_bits_left += 16;
|
497 |
+
|
498 |
+
JPGD_ASSERT(m_bits_left >= 0);
|
499 |
+
}
|
500 |
+
else
|
501 |
+
m_bit_buf <<= num_bits;
|
502 |
+
|
503 |
+
return i;
|
504 |
+
}
|
505 |
+
|
506 |
+
// Decodes a Huffman encoded symbol.
|
507 |
+
inline int jpeg_decoder::huff_decode(huff_tables *pH)
|
508 |
+
{
|
509 |
+
int symbol;
|
510 |
+
|
511 |
+
// Check first 8-bits: do we have a complete symbol?
|
512 |
+
if ((symbol = pH->look_up[m_bit_buf >> 24]) < 0)
|
513 |
+
{
|
514 |
+
// Decode more bits, use a tree traversal to find symbol.
|
515 |
+
int ofs = 23;
|
516 |
+
do
|
517 |
+
{
|
518 |
+
symbol = pH->tree[-(int)(symbol + ((m_bit_buf >> ofs) & 1))];
|
519 |
+
ofs--;
|
520 |
+
} while (symbol < 0);
|
521 |
+
|
522 |
+
get_bits_no_markers(8 + (23 - ofs));
|
523 |
+
}
|
524 |
+
else
|
525 |
+
get_bits_no_markers(pH->code_size[symbol]);
|
526 |
+
|
527 |
+
return symbol;
|
528 |
+
}
|
529 |
+
|
530 |
+
// Decodes a Huffman encoded symbol.
|
531 |
+
inline int jpeg_decoder::huff_decode(huff_tables *pH, int& extra_bits)
|
532 |
+
{
|
533 |
+
int symbol;
|
534 |
+
|
535 |
+
// Check first 8-bits: do we have a complete symbol?
|
536 |
+
if ((symbol = pH->look_up2[m_bit_buf >> 24]) < 0)
|
537 |
+
{
|
538 |
+
// Use a tree traversal to find symbol.
|
539 |
+
int ofs = 23;
|
540 |
+
do
|
541 |
+
{
|
542 |
+
symbol = pH->tree[-(int)(symbol + ((m_bit_buf >> ofs) & 1))];
|
543 |
+
ofs--;
|
544 |
+
} while (symbol < 0);
|
545 |
+
|
546 |
+
get_bits_no_markers(8 + (23 - ofs));
|
547 |
+
|
548 |
+
extra_bits = get_bits_no_markers(symbol & 0xF);
|
549 |
+
}
|
550 |
+
else
|
551 |
+
{
|
552 |
+
JPGD_ASSERT(((symbol >> 8) & 31) == pH->code_size[symbol & 255] + ((symbol & 0x8000) ? (symbol & 15) : 0));
|
553 |
+
|
554 |
+
if (symbol & 0x8000)
|
555 |
+
{
|
556 |
+
get_bits_no_markers((symbol >> 8) & 31);
|
557 |
+
extra_bits = symbol >> 16;
|
558 |
+
}
|
559 |
+
else
|
560 |
+
{
|
561 |
+
int code_size = (symbol >> 8) & 31;
|
562 |
+
int num_extra_bits = symbol & 0xF;
|
563 |
+
int bits = code_size + num_extra_bits;
|
564 |
+
if (bits <= (m_bits_left + 16))
|
565 |
+
extra_bits = get_bits_no_markers(bits) & ((1 << num_extra_bits) - 1);
|
566 |
+
else
|
567 |
+
{
|
568 |
+
get_bits_no_markers(code_size);
|
569 |
+
extra_bits = get_bits_no_markers(num_extra_bits);
|
570 |
+
}
|
571 |
+
}
|
572 |
+
|
573 |
+
symbol &= 0xFF;
|
574 |
+
}
|
575 |
+
|
576 |
+
return symbol;
|
577 |
+
}
|
578 |
+
|
579 |
+
// Tables and macro used to fully decode the DPCM differences.
|
580 |
+
static const int s_extend_test[16] = { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
|
581 |
+
static const int s_extend_offset[16] = { 0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047, -4095, -8191, -16383, -32767 };
|
582 |
+
static const int s_extend_mask[] = { 0, (1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7), (1<<8), (1<<9), (1<<10), (1<<11), (1<<12), (1<<13), (1<<14), (1<<15), (1<<16) };
|
583 |
+
#define HUFF_EXTEND(x,s) ((x) < s_extend_test[s] ? (x) + s_extend_offset[s] : (x))
|
584 |
+
|
585 |
+
// Clamps a value between 0-255.
|
586 |
+
inline uint8 jpeg_decoder::clamp(int i)
|
587 |
+
{
|
588 |
+
if (static_cast<uint>(i) > 255)
|
589 |
+
i = (((~i) >> 31) & 0xFF);
|
590 |
+
|
591 |
+
return static_cast<uint8>(i);
|
592 |
+
}
|
593 |
+
|
594 |
+
namespace DCT_Upsample
|
595 |
+
{
|
596 |
+
struct Matrix44
|
597 |
+
{
|
598 |
+
typedef int Element_Type;
|
599 |
+
enum { NUM_ROWS = 4, NUM_COLS = 4 };
|
600 |
+
|
601 |
+
Element_Type v[NUM_ROWS][NUM_COLS];
|
602 |
+
|
603 |
+
inline int rows() const { return NUM_ROWS; }
|
604 |
+
inline int cols() const { return NUM_COLS; }
|
605 |
+
|
606 |
+
inline const Element_Type & at(int r, int c) const { return v[r][c]; }
|
607 |
+
inline Element_Type & at(int r, int c) { return v[r][c]; }
|
608 |
+
|
609 |
+
inline Matrix44() { }
|
610 |
+
|
611 |
+
inline Matrix44& operator += (const Matrix44& a)
|
612 |
+
{
|
613 |
+
for (int r = 0; r < NUM_ROWS; r++)
|
614 |
+
{
|
615 |
+
at(r, 0) += a.at(r, 0);
|
616 |
+
at(r, 1) += a.at(r, 1);
|
617 |
+
at(r, 2) += a.at(r, 2);
|
618 |
+
at(r, 3) += a.at(r, 3);
|
619 |
+
}
|
620 |
+
return *this;
|
621 |
+
}
|
622 |
+
|
623 |
+
inline Matrix44& operator -= (const Matrix44& a)
|
624 |
+
{
|
625 |
+
for (int r = 0; r < NUM_ROWS; r++)
|
626 |
+
{
|
627 |
+
at(r, 0) -= a.at(r, 0);
|
628 |
+
at(r, 1) -= a.at(r, 1);
|
629 |
+
at(r, 2) -= a.at(r, 2);
|
630 |
+
at(r, 3) -= a.at(r, 3);
|
631 |
+
}
|
632 |
+
return *this;
|
633 |
+
}
|
634 |
+
|
635 |
+
friend inline Matrix44 operator + (const Matrix44& a, const Matrix44& b)
|
636 |
+
{
|
637 |
+
Matrix44 ret;
|
638 |
+
for (int r = 0; r < NUM_ROWS; r++)
|
639 |
+
{
|
640 |
+
ret.at(r, 0) = a.at(r, 0) + b.at(r, 0);
|
641 |
+
ret.at(r, 1) = a.at(r, 1) + b.at(r, 1);
|
642 |
+
ret.at(r, 2) = a.at(r, 2) + b.at(r, 2);
|
643 |
+
ret.at(r, 3) = a.at(r, 3) + b.at(r, 3);
|
644 |
+
}
|
645 |
+
return ret;
|
646 |
+
}
|
647 |
+
|
648 |
+
friend inline Matrix44 operator - (const Matrix44& a, const Matrix44& b)
|
649 |
+
{
|
650 |
+
Matrix44 ret;
|
651 |
+
for (int r = 0; r < NUM_ROWS; r++)
|
652 |
+
{
|
653 |
+
ret.at(r, 0) = a.at(r, 0) - b.at(r, 0);
|
654 |
+
ret.at(r, 1) = a.at(r, 1) - b.at(r, 1);
|
655 |
+
ret.at(r, 2) = a.at(r, 2) - b.at(r, 2);
|
656 |
+
ret.at(r, 3) = a.at(r, 3) - b.at(r, 3);
|
657 |
+
}
|
658 |
+
return ret;
|
659 |
+
}
|
660 |
+
|
661 |
+
static inline void add_and_store(jpgd_block_t* pDst, const Matrix44& a, const Matrix44& b)
|
662 |
+
{
|
663 |
+
for (int r = 0; r < 4; r++)
|
664 |
+
{
|
665 |
+
pDst[0*8 + r] = static_cast<jpgd_block_t>(a.at(r, 0) + b.at(r, 0));
|
666 |
+
pDst[1*8 + r] = static_cast<jpgd_block_t>(a.at(r, 1) + b.at(r, 1));
|
667 |
+
pDst[2*8 + r] = static_cast<jpgd_block_t>(a.at(r, 2) + b.at(r, 2));
|
668 |
+
pDst[3*8 + r] = static_cast<jpgd_block_t>(a.at(r, 3) + b.at(r, 3));
|
669 |
+
}
|
670 |
+
}
|
671 |
+
|
672 |
+
static inline void sub_and_store(jpgd_block_t* pDst, const Matrix44& a, const Matrix44& b)
|
673 |
+
{
|
674 |
+
for (int r = 0; r < 4; r++)
|
675 |
+
{
|
676 |
+
pDst[0*8 + r] = static_cast<jpgd_block_t>(a.at(r, 0) - b.at(r, 0));
|
677 |
+
pDst[1*8 + r] = static_cast<jpgd_block_t>(a.at(r, 1) - b.at(r, 1));
|
678 |
+
pDst[2*8 + r] = static_cast<jpgd_block_t>(a.at(r, 2) - b.at(r, 2));
|
679 |
+
pDst[3*8 + r] = static_cast<jpgd_block_t>(a.at(r, 3) - b.at(r, 3));
|
680 |
+
}
|
681 |
+
}
|
682 |
+
};
|
683 |
+
|
684 |
+
const int FRACT_BITS = 10;
|
685 |
+
const int SCALE = 1 << FRACT_BITS;
|
686 |
+
|
687 |
+
typedef int Temp_Type;
|
688 |
+
#define D(i) (((i) + (SCALE >> 1)) >> FRACT_BITS)
|
689 |
+
#define F(i) ((int)((i) * SCALE + .5f))
|
690 |
+
|
691 |
+
// Any decent C++ compiler will optimize this at compile time to a 0, or an array access.
|
692 |
+
#define AT(c, r) ((((c)>=NUM_COLS)||((r)>=NUM_ROWS)) ? 0 : pSrc[(c)+(r)*8])
|
693 |
+
|
694 |
+
// NUM_ROWS/NUM_COLS = # of non-zero rows/cols in input matrix
|
695 |
+
template<int NUM_ROWS, int NUM_COLS>
|
696 |
+
struct P_Q
|
697 |
+
{
|
698 |
+
static void calc(Matrix44& P, Matrix44& Q, const jpgd_block_t* pSrc)
|
699 |
+
{
|
700 |
+
// 4x8 = 4x8 times 8x8, matrix 0 is constant
|
701 |
+
const Temp_Type X000 = AT(0, 0);
|
702 |
+
const Temp_Type X001 = AT(0, 1);
|
703 |
+
const Temp_Type X002 = AT(0, 2);
|
704 |
+
const Temp_Type X003 = AT(0, 3);
|
705 |
+
const Temp_Type X004 = AT(0, 4);
|
706 |
+
const Temp_Type X005 = AT(0, 5);
|
707 |
+
const Temp_Type X006 = AT(0, 6);
|
708 |
+
const Temp_Type X007 = AT(0, 7);
|
709 |
+
const Temp_Type X010 = D(F(0.415735f) * AT(1, 0) + F(0.791065f) * AT(3, 0) + F(-0.352443f) * AT(5, 0) + F(0.277785f) * AT(7, 0));
|
710 |
+
const Temp_Type X011 = D(F(0.415735f) * AT(1, 1) + F(0.791065f) * AT(3, 1) + F(-0.352443f) * AT(5, 1) + F(0.277785f) * AT(7, 1));
|
711 |
+
const Temp_Type X012 = D(F(0.415735f) * AT(1, 2) + F(0.791065f) * AT(3, 2) + F(-0.352443f) * AT(5, 2) + F(0.277785f) * AT(7, 2));
|
712 |
+
const Temp_Type X013 = D(F(0.415735f) * AT(1, 3) + F(0.791065f) * AT(3, 3) + F(-0.352443f) * AT(5, 3) + F(0.277785f) * AT(7, 3));
|
713 |
+
const Temp_Type X014 = D(F(0.415735f) * AT(1, 4) + F(0.791065f) * AT(3, 4) + F(-0.352443f) * AT(5, 4) + F(0.277785f) * AT(7, 4));
|
714 |
+
const Temp_Type X015 = D(F(0.415735f) * AT(1, 5) + F(0.791065f) * AT(3, 5) + F(-0.352443f) * AT(5, 5) + F(0.277785f) * AT(7, 5));
|
715 |
+
const Temp_Type X016 = D(F(0.415735f) * AT(1, 6) + F(0.791065f) * AT(3, 6) + F(-0.352443f) * AT(5, 6) + F(0.277785f) * AT(7, 6));
|
716 |
+
const Temp_Type X017 = D(F(0.415735f) * AT(1, 7) + F(0.791065f) * AT(3, 7) + F(-0.352443f) * AT(5, 7) + F(0.277785f) * AT(7, 7));
|
717 |
+
const Temp_Type X020 = AT(4, 0);
|
718 |
+
const Temp_Type X021 = AT(4, 1);
|
719 |
+
const Temp_Type X022 = AT(4, 2);
|
720 |
+
const Temp_Type X023 = AT(4, 3);
|
721 |
+
const Temp_Type X024 = AT(4, 4);
|
722 |
+
const Temp_Type X025 = AT(4, 5);
|
723 |
+
const Temp_Type X026 = AT(4, 6);
|
724 |
+
const Temp_Type X027 = AT(4, 7);
|
725 |
+
const Temp_Type X030 = D(F(0.022887f) * AT(1, 0) + F(-0.097545f) * AT(3, 0) + F(0.490393f) * AT(5, 0) + F(0.865723f) * AT(7, 0));
|
726 |
+
const Temp_Type X031 = D(F(0.022887f) * AT(1, 1) + F(-0.097545f) * AT(3, 1) + F(0.490393f) * AT(5, 1) + F(0.865723f) * AT(7, 1));
|
727 |
+
const Temp_Type X032 = D(F(0.022887f) * AT(1, 2) + F(-0.097545f) * AT(3, 2) + F(0.490393f) * AT(5, 2) + F(0.865723f) * AT(7, 2));
|
728 |
+
const Temp_Type X033 = D(F(0.022887f) * AT(1, 3) + F(-0.097545f) * AT(3, 3) + F(0.490393f) * AT(5, 3) + F(0.865723f) * AT(7, 3));
|
729 |
+
const Temp_Type X034 = D(F(0.022887f) * AT(1, 4) + F(-0.097545f) * AT(3, 4) + F(0.490393f) * AT(5, 4) + F(0.865723f) * AT(7, 4));
|
730 |
+
const Temp_Type X035 = D(F(0.022887f) * AT(1, 5) + F(-0.097545f) * AT(3, 5) + F(0.490393f) * AT(5, 5) + F(0.865723f) * AT(7, 5));
|
731 |
+
const Temp_Type X036 = D(F(0.022887f) * AT(1, 6) + F(-0.097545f) * AT(3, 6) + F(0.490393f) * AT(5, 6) + F(0.865723f) * AT(7, 6));
|
732 |
+
const Temp_Type X037 = D(F(0.022887f) * AT(1, 7) + F(-0.097545f) * AT(3, 7) + F(0.490393f) * AT(5, 7) + F(0.865723f) * AT(7, 7));
|
733 |
+
|
734 |
+
// 4x4 = 4x8 times 8x4, matrix 1 is constant
|
735 |
+
P.at(0, 0) = X000;
|
736 |
+
P.at(0, 1) = D(X001 * F(0.415735f) + X003 * F(0.791065f) + X005 * F(-0.352443f) + X007 * F(0.277785f));
|
737 |
+
P.at(0, 2) = X004;
|
738 |
+
P.at(0, 3) = D(X001 * F(0.022887f) + X003 * F(-0.097545f) + X005 * F(0.490393f) + X007 * F(0.865723f));
|
739 |
+
P.at(1, 0) = X010;
|
740 |
+
P.at(1, 1) = D(X011 * F(0.415735f) + X013 * F(0.791065f) + X015 * F(-0.352443f) + X017 * F(0.277785f));
|
741 |
+
P.at(1, 2) = X014;
|
742 |
+
P.at(1, 3) = D(X011 * F(0.022887f) + X013 * F(-0.097545f) + X015 * F(0.490393f) + X017 * F(0.865723f));
|
743 |
+
P.at(2, 0) = X020;
|
744 |
+
P.at(2, 1) = D(X021 * F(0.415735f) + X023 * F(0.791065f) + X025 * F(-0.352443f) + X027 * F(0.277785f));
|
745 |
+
P.at(2, 2) = X024;
|
746 |
+
P.at(2, 3) = D(X021 * F(0.022887f) + X023 * F(-0.097545f) + X025 * F(0.490393f) + X027 * F(0.865723f));
|
747 |
+
P.at(3, 0) = X030;
|
748 |
+
P.at(3, 1) = D(X031 * F(0.415735f) + X033 * F(0.791065f) + X035 * F(-0.352443f) + X037 * F(0.277785f));
|
749 |
+
P.at(3, 2) = X034;
|
750 |
+
P.at(3, 3) = D(X031 * F(0.022887f) + X033 * F(-0.097545f) + X035 * F(0.490393f) + X037 * F(0.865723f));
|
751 |
+
// 40 muls 24 adds
|
752 |
+
|
753 |
+
// 4x4 = 4x8 times 8x4, matrix 1 is constant
|
754 |
+
Q.at(0, 0) = D(X001 * F(0.906127f) + X003 * F(-0.318190f) + X005 * F(0.212608f) + X007 * F(-0.180240f));
|
755 |
+
Q.at(0, 1) = X002;
|
756 |
+
Q.at(0, 2) = D(X001 * F(-0.074658f) + X003 * F(0.513280f) + X005 * F(0.768178f) + X007 * F(-0.375330f));
|
757 |
+
Q.at(0, 3) = X006;
|
758 |
+
Q.at(1, 0) = D(X011 * F(0.906127f) + X013 * F(-0.318190f) + X015 * F(0.212608f) + X017 * F(-0.180240f));
|
759 |
+
Q.at(1, 1) = X012;
|
760 |
+
Q.at(1, 2) = D(X011 * F(-0.074658f) + X013 * F(0.513280f) + X015 * F(0.768178f) + X017 * F(-0.375330f));
|
761 |
+
Q.at(1, 3) = X016;
|
762 |
+
Q.at(2, 0) = D(X021 * F(0.906127f) + X023 * F(-0.318190f) + X025 * F(0.212608f) + X027 * F(-0.180240f));
|
763 |
+
Q.at(2, 1) = X022;
|
764 |
+
Q.at(2, 2) = D(X021 * F(-0.074658f) + X023 * F(0.513280f) + X025 * F(0.768178f) + X027 * F(-0.375330f));
|
765 |
+
Q.at(2, 3) = X026;
|
766 |
+
Q.at(3, 0) = D(X031 * F(0.906127f) + X033 * F(-0.318190f) + X035 * F(0.212608f) + X037 * F(-0.180240f));
|
767 |
+
Q.at(3, 1) = X032;
|
768 |
+
Q.at(3, 2) = D(X031 * F(-0.074658f) + X033 * F(0.513280f) + X035 * F(0.768178f) + X037 * F(-0.375330f));
|
769 |
+
Q.at(3, 3) = X036;
|
770 |
+
// 40 muls 24 adds
|
771 |
+
}
|
772 |
+
};
|
773 |
+
|
774 |
+
template<int NUM_ROWS, int NUM_COLS>
|
775 |
+
struct R_S
|
776 |
+
{
|
777 |
+
static void calc(Matrix44& R, Matrix44& S, const jpgd_block_t* pSrc)
|
778 |
+
{
|
779 |
+
// 4x8 = 4x8 times 8x8, matrix 0 is constant
|
780 |
+
const Temp_Type X100 = D(F(0.906127f) * AT(1, 0) + F(-0.318190f) * AT(3, 0) + F(0.212608f) * AT(5, 0) + F(-0.180240f) * AT(7, 0));
|
781 |
+
const Temp_Type X101 = D(F(0.906127f) * AT(1, 1) + F(-0.318190f) * AT(3, 1) + F(0.212608f) * AT(5, 1) + F(-0.180240f) * AT(7, 1));
|
782 |
+
const Temp_Type X102 = D(F(0.906127f) * AT(1, 2) + F(-0.318190f) * AT(3, 2) + F(0.212608f) * AT(5, 2) + F(-0.180240f) * AT(7, 2));
|
783 |
+
const Temp_Type X103 = D(F(0.906127f) * AT(1, 3) + F(-0.318190f) * AT(3, 3) + F(0.212608f) * AT(5, 3) + F(-0.180240f) * AT(7, 3));
|
784 |
+
const Temp_Type X104 = D(F(0.906127f) * AT(1, 4) + F(-0.318190f) * AT(3, 4) + F(0.212608f) * AT(5, 4) + F(-0.180240f) * AT(7, 4));
|
785 |
+
const Temp_Type X105 = D(F(0.906127f) * AT(1, 5) + F(-0.318190f) * AT(3, 5) + F(0.212608f) * AT(5, 5) + F(-0.180240f) * AT(7, 5));
|
786 |
+
const Temp_Type X106 = D(F(0.906127f) * AT(1, 6) + F(-0.318190f) * AT(3, 6) + F(0.212608f) * AT(5, 6) + F(-0.180240f) * AT(7, 6));
|
787 |
+
const Temp_Type X107 = D(F(0.906127f) * AT(1, 7) + F(-0.318190f) * AT(3, 7) + F(0.212608f) * AT(5, 7) + F(-0.180240f) * AT(7, 7));
|
788 |
+
const Temp_Type X110 = AT(2, 0);
|
789 |
+
const Temp_Type X111 = AT(2, 1);
|
790 |
+
const Temp_Type X112 = AT(2, 2);
|
791 |
+
const Temp_Type X113 = AT(2, 3);
|
792 |
+
const Temp_Type X114 = AT(2, 4);
|
793 |
+
const Temp_Type X115 = AT(2, 5);
|
794 |
+
const Temp_Type X116 = AT(2, 6);
|
795 |
+
const Temp_Type X117 = AT(2, 7);
|
796 |
+
const Temp_Type X120 = D(F(-0.074658f) * AT(1, 0) + F(0.513280f) * AT(3, 0) + F(0.768178f) * AT(5, 0) + F(-0.375330f) * AT(7, 0));
|
797 |
+
const Temp_Type X121 = D(F(-0.074658f) * AT(1, 1) + F(0.513280f) * AT(3, 1) + F(0.768178f) * AT(5, 1) + F(-0.375330f) * AT(7, 1));
|
798 |
+
const Temp_Type X122 = D(F(-0.074658f) * AT(1, 2) + F(0.513280f) * AT(3, 2) + F(0.768178f) * AT(5, 2) + F(-0.375330f) * AT(7, 2));
|
799 |
+
const Temp_Type X123 = D(F(-0.074658f) * AT(1, 3) + F(0.513280f) * AT(3, 3) + F(0.768178f) * AT(5, 3) + F(-0.375330f) * AT(7, 3));
|
800 |
+
const Temp_Type X124 = D(F(-0.074658f) * AT(1, 4) + F(0.513280f) * AT(3, 4) + F(0.768178f) * AT(5, 4) + F(-0.375330f) * AT(7, 4));
|
801 |
+
const Temp_Type X125 = D(F(-0.074658f) * AT(1, 5) + F(0.513280f) * AT(3, 5) + F(0.768178f) * AT(5, 5) + F(-0.375330f) * AT(7, 5));
|
802 |
+
const Temp_Type X126 = D(F(-0.074658f) * AT(1, 6) + F(0.513280f) * AT(3, 6) + F(0.768178f) * AT(5, 6) + F(-0.375330f) * AT(7, 6));
|
803 |
+
const Temp_Type X127 = D(F(-0.074658f) * AT(1, 7) + F(0.513280f) * AT(3, 7) + F(0.768178f) * AT(5, 7) + F(-0.375330f) * AT(7, 7));
|
804 |
+
const Temp_Type X130 = AT(6, 0);
|
805 |
+
const Temp_Type X131 = AT(6, 1);
|
806 |
+
const Temp_Type X132 = AT(6, 2);
|
807 |
+
const Temp_Type X133 = AT(6, 3);
|
808 |
+
const Temp_Type X134 = AT(6, 4);
|
809 |
+
const Temp_Type X135 = AT(6, 5);
|
810 |
+
const Temp_Type X136 = AT(6, 6);
|
811 |
+
const Temp_Type X137 = AT(6, 7);
|
812 |
+
// 80 muls 48 adds
|
813 |
+
|
814 |
+
// 4x4 = 4x8 times 8x4, matrix 1 is constant
|
815 |
+
R.at(0, 0) = X100;
|
816 |
+
R.at(0, 1) = D(X101 * F(0.415735f) + X103 * F(0.791065f) + X105 * F(-0.352443f) + X107 * F(0.277785f));
|
817 |
+
R.at(0, 2) = X104;
|
818 |
+
R.at(0, 3) = D(X101 * F(0.022887f) + X103 * F(-0.097545f) + X105 * F(0.490393f) + X107 * F(0.865723f));
|
819 |
+
R.at(1, 0) = X110;
|
820 |
+
R.at(1, 1) = D(X111 * F(0.415735f) + X113 * F(0.791065f) + X115 * F(-0.352443f) + X117 * F(0.277785f));
|
821 |
+
R.at(1, 2) = X114;
|
822 |
+
R.at(1, 3) = D(X111 * F(0.022887f) + X113 * F(-0.097545f) + X115 * F(0.490393f) + X117 * F(0.865723f));
|
823 |
+
R.at(2, 0) = X120;
|
824 |
+
R.at(2, 1) = D(X121 * F(0.415735f) + X123 * F(0.791065f) + X125 * F(-0.352443f) + X127 * F(0.277785f));
|
825 |
+
R.at(2, 2) = X124;
|
826 |
+
R.at(2, 3) = D(X121 * F(0.022887f) + X123 * F(-0.097545f) + X125 * F(0.490393f) + X127 * F(0.865723f));
|
827 |
+
R.at(3, 0) = X130;
|
828 |
+
R.at(3, 1) = D(X131 * F(0.415735f) + X133 * F(0.791065f) + X135 * F(-0.352443f) + X137 * F(0.277785f));
|
829 |
+
R.at(3, 2) = X134;
|
830 |
+
R.at(3, 3) = D(X131 * F(0.022887f) + X133 * F(-0.097545f) + X135 * F(0.490393f) + X137 * F(0.865723f));
|
831 |
+
// 40 muls 24 adds
|
832 |
+
// 4x4 = 4x8 times 8x4, matrix 1 is constant
|
833 |
+
S.at(0, 0) = D(X101 * F(0.906127f) + X103 * F(-0.318190f) + X105 * F(0.212608f) + X107 * F(-0.180240f));
|
834 |
+
S.at(0, 1) = X102;
|
835 |
+
S.at(0, 2) = D(X101 * F(-0.074658f) + X103 * F(0.513280f) + X105 * F(0.768178f) + X107 * F(-0.375330f));
|
836 |
+
S.at(0, 3) = X106;
|
837 |
+
S.at(1, 0) = D(X111 * F(0.906127f) + X113 * F(-0.318190f) + X115 * F(0.212608f) + X117 * F(-0.180240f));
|
838 |
+
S.at(1, 1) = X112;
|
839 |
+
S.at(1, 2) = D(X111 * F(-0.074658f) + X113 * F(0.513280f) + X115 * F(0.768178f) + X117 * F(-0.375330f));
|
840 |
+
S.at(1, 3) = X116;
|
841 |
+
S.at(2, 0) = D(X121 * F(0.906127f) + X123 * F(-0.318190f) + X125 * F(0.212608f) + X127 * F(-0.180240f));
|
842 |
+
S.at(2, 1) = X122;
|
843 |
+
S.at(2, 2) = D(X121 * F(-0.074658f) + X123 * F(0.513280f) + X125 * F(0.768178f) + X127 * F(-0.375330f));
|
844 |
+
S.at(2, 3) = X126;
|
845 |
+
S.at(3, 0) = D(X131 * F(0.906127f) + X133 * F(-0.318190f) + X135 * F(0.212608f) + X137 * F(-0.180240f));
|
846 |
+
S.at(3, 1) = X132;
|
847 |
+
S.at(3, 2) = D(X131 * F(-0.074658f) + X133 * F(0.513280f) + X135 * F(0.768178f) + X137 * F(-0.375330f));
|
848 |
+
S.at(3, 3) = X136;
|
849 |
+
// 40 muls 24 adds
|
850 |
+
}
|
851 |
+
};
|
852 |
+
} // end namespace DCT_Upsample
|
853 |
+
|
854 |
+
// Unconditionally frees all allocated m_blocks.
|
855 |
+
void jpeg_decoder::free_all_blocks()
|
856 |
+
{
|
857 |
+
m_pStream = NULL;
|
858 |
+
for (mem_block *b = m_pMem_blocks; b; )
|
859 |
+
{
|
860 |
+
mem_block *n = b->m_pNext;
|
861 |
+
jpgd_free(b);
|
862 |
+
b = n;
|
863 |
+
}
|
864 |
+
m_pMem_blocks = NULL;
|
865 |
+
}
|
866 |
+
|
867 |
+
// This method handles all errors.
|
868 |
+
// It could easily be changed to use C++ exceptions.
|
869 |
+
void jpeg_decoder::stop_decoding(jpgd_status status)
|
870 |
+
{
|
871 |
+
m_error_code = status;
|
872 |
+
free_all_blocks();
|
873 |
+
longjmp(m_jmp_state, status);
|
874 |
+
|
875 |
+
// we shouldn't get here as longjmp shouldn't return, but we put it here to make it explicit
|
876 |
+
// that this function doesn't return, otherwise we get this error:
|
877 |
+
//
|
878 |
+
// error : function declared 'noreturn' should not return
|
879 |
+
exit(1);
|
880 |
+
}
|
881 |
+
|
882 |
+
void *jpeg_decoder::alloc(size_t nSize, bool zero)
|
883 |
+
{
|
884 |
+
nSize = (JPGD_MAX(nSize, 1) + 3) & ~3;
|
885 |
+
char *rv = NULL;
|
886 |
+
for (mem_block *b = m_pMem_blocks; b; b = b->m_pNext)
|
887 |
+
{
|
888 |
+
if ((b->m_used_count + nSize) <= b->m_size)
|
889 |
+
{
|
890 |
+
rv = b->m_data + b->m_used_count;
|
891 |
+
b->m_used_count += nSize;
|
892 |
+
break;
|
893 |
+
}
|
894 |
+
}
|
895 |
+
if (!rv)
|
896 |
+
{
|
897 |
+
int capacity = JPGD_MAX(32768 - 256, (nSize + 2047) & ~2047);
|
898 |
+
mem_block *b = (mem_block*)jpgd_malloc(sizeof(mem_block) + capacity);
|
899 |
+
if (!b) stop_decoding(JPGD_NOTENOUGHMEM);
|
900 |
+
b->m_pNext = m_pMem_blocks; m_pMem_blocks = b;
|
901 |
+
b->m_used_count = nSize;
|
902 |
+
b->m_size = capacity;
|
903 |
+
rv = b->m_data;
|
904 |
+
}
|
905 |
+
if (zero) memset(rv, 0, nSize);
|
906 |
+
return rv;
|
907 |
+
}
|
908 |
+
|
909 |
+
void jpeg_decoder::word_clear(void *p, uint16 c, uint n)
|
910 |
+
{
|
911 |
+
uint8 *pD = (uint8*)p;
|
912 |
+
const uint8 l = c & 0xFF, h = (c >> 8) & 0xFF;
|
913 |
+
while (n)
|
914 |
+
{
|
915 |
+
pD[0] = l; pD[1] = h; pD += 2;
|
916 |
+
n--;
|
917 |
+
}
|
918 |
+
}
|
919 |
+
|
920 |
+
// Refill the input buffer.
|
921 |
+
// This method will sit in a loop until (A) the buffer is full or (B)
|
922 |
+
// the stream's read() method reports and end of file condition.
|
923 |
+
void jpeg_decoder::prep_in_buffer()
|
924 |
+
{
|
925 |
+
m_in_buf_left = 0;
|
926 |
+
m_pIn_buf_ofs = m_in_buf;
|
927 |
+
|
928 |
+
if (m_eof_flag)
|
929 |
+
return;
|
930 |
+
|
931 |
+
do
|
932 |
+
{
|
933 |
+
int bytes_read = m_pStream->read(m_in_buf + m_in_buf_left, JPGD_IN_BUF_SIZE - m_in_buf_left, &m_eof_flag);
|
934 |
+
if (bytes_read == -1)
|
935 |
+
stop_decoding(JPGD_STREAM_READ);
|
936 |
+
|
937 |
+
m_in_buf_left += bytes_read;
|
938 |
+
} while ((m_in_buf_left < JPGD_IN_BUF_SIZE) && (!m_eof_flag));
|
939 |
+
|
940 |
+
m_total_bytes_read += m_in_buf_left;
|
941 |
+
|
942 |
+
// Pad the end of the block with M_EOI (prevents the decompressor from going off the rails if the stream is invalid).
|
943 |
+
// (This dates way back to when this decompressor was written in C/asm, and the all-asm Huffman decoder did some fancy things to increase perf.)
|
944 |
+
word_clear(m_pIn_buf_ofs + m_in_buf_left, 0xD9FF, 64);
|
945 |
+
}
|
946 |
+
|
947 |
+
// Read a Huffman code table.
|
948 |
+
void jpeg_decoder::read_dht_marker()
|
949 |
+
{
|
950 |
+
int i, index, count;
|
951 |
+
uint8 huff_num[17];
|
952 |
+
uint8 huff_val[256];
|
953 |
+
|
954 |
+
uint num_left = get_bits(16);
|
955 |
+
|
956 |
+
if (num_left < 2)
|
957 |
+
stop_decoding(JPGD_BAD_DHT_MARKER);
|
958 |
+
|
959 |
+
num_left -= 2;
|
960 |
+
|
961 |
+
while (num_left)
|
962 |
+
{
|
963 |
+
index = get_bits(8);
|
964 |
+
|
965 |
+
huff_num[0] = 0;
|
966 |
+
|
967 |
+
count = 0;
|
968 |
+
|
969 |
+
for (i = 1; i <= 16; i++)
|
970 |
+
{
|
971 |
+
huff_num[i] = static_cast<uint8>(get_bits(8));
|
972 |
+
count += huff_num[i];
|
973 |
+
}
|
974 |
+
|
975 |
+
if (count > 255)
|
976 |
+
stop_decoding(JPGD_BAD_DHT_COUNTS);
|
977 |
+
|
978 |
+
for (i = 0; i < count; i++)
|
979 |
+
huff_val[i] = static_cast<uint8>(get_bits(8));
|
980 |
+
|
981 |
+
i = 1 + 16 + count;
|
982 |
+
|
983 |
+
if (num_left < (uint)i)
|
984 |
+
stop_decoding(JPGD_BAD_DHT_MARKER);
|
985 |
+
|
986 |
+
num_left -= i;
|
987 |
+
|
988 |
+
if ((index & 0x10) > 0x10)
|
989 |
+
stop_decoding(JPGD_BAD_DHT_INDEX);
|
990 |
+
|
991 |
+
index = (index & 0x0F) + ((index & 0x10) >> 4) * (JPGD_MAX_HUFF_TABLES >> 1);
|
992 |
+
|
993 |
+
if (index >= JPGD_MAX_HUFF_TABLES)
|
994 |
+
stop_decoding(JPGD_BAD_DHT_INDEX);
|
995 |
+
|
996 |
+
if (!m_huff_num[index])
|
997 |
+
m_huff_num[index] = (uint8 *)alloc(17);
|
998 |
+
|
999 |
+
if (!m_huff_val[index])
|
1000 |
+
m_huff_val[index] = (uint8 *)alloc(256);
|
1001 |
+
|
1002 |
+
m_huff_ac[index] = (index & 0x10) != 0;
|
1003 |
+
memcpy(m_huff_num[index], huff_num, 17);
|
1004 |
+
memcpy(m_huff_val[index], huff_val, 256);
|
1005 |
+
}
|
1006 |
+
}
|
1007 |
+
|
1008 |
+
// Read a quantization table.
|
1009 |
+
void jpeg_decoder::read_dqt_marker()
|
1010 |
+
{
|
1011 |
+
int n, i, prec;
|
1012 |
+
uint num_left;
|
1013 |
+
uint temp;
|
1014 |
+
|
1015 |
+
num_left = get_bits(16);
|
1016 |
+
|
1017 |
+
if (num_left < 2)
|
1018 |
+
stop_decoding(JPGD_BAD_DQT_MARKER);
|
1019 |
+
|
1020 |
+
num_left -= 2;
|
1021 |
+
|
1022 |
+
while (num_left)
|
1023 |
+
{
|
1024 |
+
n = get_bits(8);
|
1025 |
+
prec = n >> 4;
|
1026 |
+
n &= 0x0F;
|
1027 |
+
|
1028 |
+
if (n >= JPGD_MAX_QUANT_TABLES)
|
1029 |
+
stop_decoding(JPGD_BAD_DQT_TABLE);
|
1030 |
+
|
1031 |
+
if (!m_quant[n])
|
1032 |
+
m_quant[n] = (jpgd_quant_t *)alloc(64 * sizeof(jpgd_quant_t));
|
1033 |
+
|
1034 |
+
// read quantization entries, in zag order
|
1035 |
+
for (i = 0; i < 64; i++)
|
1036 |
+
{
|
1037 |
+
temp = get_bits(8);
|
1038 |
+
|
1039 |
+
if (prec)
|
1040 |
+
temp = (temp << 8) + get_bits(8);
|
1041 |
+
|
1042 |
+
m_quant[n][i] = static_cast<jpgd_quant_t>(temp);
|
1043 |
+
}
|
1044 |
+
|
1045 |
+
i = 64 + 1;
|
1046 |
+
|
1047 |
+
if (prec)
|
1048 |
+
i += 64;
|
1049 |
+
|
1050 |
+
if (num_left < (uint)i)
|
1051 |
+
stop_decoding(JPGD_BAD_DQT_LENGTH);
|
1052 |
+
|
1053 |
+
num_left -= i;
|
1054 |
+
}
|
1055 |
+
}
|
1056 |
+
|
1057 |
+
// Read the start of frame (SOF) marker.
|
1058 |
+
void jpeg_decoder::read_sof_marker()
|
1059 |
+
{
|
1060 |
+
int i;
|
1061 |
+
uint num_left;
|
1062 |
+
|
1063 |
+
num_left = get_bits(16);
|
1064 |
+
|
1065 |
+
if (get_bits(8) != 8) /* precision: sorry, only 8-bit precision is supported right now */
|
1066 |
+
stop_decoding(JPGD_BAD_PRECISION);
|
1067 |
+
|
1068 |
+
m_image_y_size = get_bits(16);
|
1069 |
+
|
1070 |
+
if ((m_image_y_size < 1) || (m_image_y_size > JPGD_MAX_HEIGHT))
|
1071 |
+
stop_decoding(JPGD_BAD_HEIGHT);
|
1072 |
+
|
1073 |
+
m_image_x_size = get_bits(16);
|
1074 |
+
|
1075 |
+
if ((m_image_x_size < 1) || (m_image_x_size > JPGD_MAX_WIDTH))
|
1076 |
+
stop_decoding(JPGD_BAD_WIDTH);
|
1077 |
+
|
1078 |
+
m_comps_in_frame = get_bits(8);
|
1079 |
+
|
1080 |
+
if (m_comps_in_frame > JPGD_MAX_COMPONENTS)
|
1081 |
+
stop_decoding(JPGD_TOO_MANY_COMPONENTS);
|
1082 |
+
|
1083 |
+
if (num_left != (uint)(m_comps_in_frame * 3 + 8))
|
1084 |
+
stop_decoding(JPGD_BAD_SOF_LENGTH);
|
1085 |
+
|
1086 |
+
for (i = 0; i < m_comps_in_frame; i++)
|
1087 |
+
{
|
1088 |
+
m_comp_ident[i] = get_bits(8);
|
1089 |
+
m_comp_h_samp[i] = get_bits(4);
|
1090 |
+
m_comp_v_samp[i] = get_bits(4);
|
1091 |
+
m_comp_quant[i] = get_bits(8);
|
1092 |
+
}
|
1093 |
+
}
|
1094 |
+
|
1095 |
+
// Used to skip unrecognized markers.
|
1096 |
+
void jpeg_decoder::skip_variable_marker()
|
1097 |
+
{
|
1098 |
+
uint num_left;
|
1099 |
+
|
1100 |
+
num_left = get_bits(16);
|
1101 |
+
|
1102 |
+
if (num_left < 2)
|
1103 |
+
stop_decoding(JPGD_BAD_VARIABLE_MARKER);
|
1104 |
+
|
1105 |
+
num_left -= 2;
|
1106 |
+
|
1107 |
+
while (num_left)
|
1108 |
+
{
|
1109 |
+
get_bits(8);
|
1110 |
+
num_left--;
|
1111 |
+
}
|
1112 |
+
}
|
1113 |
+
|
1114 |
+
// Read a define restart interval (DRI) marker.
|
1115 |
+
void jpeg_decoder::read_dri_marker()
|
1116 |
+
{
|
1117 |
+
if (get_bits(16) != 4)
|
1118 |
+
stop_decoding(JPGD_BAD_DRI_LENGTH);
|
1119 |
+
|
1120 |
+
m_restart_interval = get_bits(16);
|
1121 |
+
}
|
1122 |
+
|
1123 |
+
// Read a start of scan (SOS) marker.
|
1124 |
+
void jpeg_decoder::read_sos_marker()
|
1125 |
+
{
|
1126 |
+
uint num_left;
|
1127 |
+
int i, ci, n, c, cc;
|
1128 |
+
|
1129 |
+
num_left = get_bits(16);
|
1130 |
+
|
1131 |
+
n = get_bits(8);
|
1132 |
+
|
1133 |
+
m_comps_in_scan = n;
|
1134 |
+
|
1135 |
+
num_left -= 3;
|
1136 |
+
|
1137 |
+
if ( (num_left != (uint)(n * 2 + 3)) || (n < 1) || (n > JPGD_MAX_COMPS_IN_SCAN) )
|
1138 |
+
stop_decoding(JPGD_BAD_SOS_LENGTH);
|
1139 |
+
|
1140 |
+
for (i = 0; i < n; i++)
|
1141 |
+
{
|
1142 |
+
cc = get_bits(8);
|
1143 |
+
c = get_bits(8);
|
1144 |
+
num_left -= 2;
|
1145 |
+
|
1146 |
+
for (ci = 0; ci < m_comps_in_frame; ci++)
|
1147 |
+
if (cc == m_comp_ident[ci])
|
1148 |
+
break;
|
1149 |
+
|
1150 |
+
if (ci >= m_comps_in_frame)
|
1151 |
+
stop_decoding(JPGD_BAD_SOS_COMP_ID);
|
1152 |
+
|
1153 |
+
m_comp_list[i] = ci;
|
1154 |
+
m_comp_dc_tab[ci] = (c >> 4) & 15;
|
1155 |
+
m_comp_ac_tab[ci] = (c & 15) + (JPGD_MAX_HUFF_TABLES >> 1);
|
1156 |
+
}
|
1157 |
+
|
1158 |
+
m_spectral_start = get_bits(8);
|
1159 |
+
m_spectral_end = get_bits(8);
|
1160 |
+
m_successive_high = get_bits(4);
|
1161 |
+
m_successive_low = get_bits(4);
|
1162 |
+
|
1163 |
+
if (!m_progressive_flag)
|
1164 |
+
{
|
1165 |
+
m_spectral_start = 0;
|
1166 |
+
m_spectral_end = 63;
|
1167 |
+
}
|
1168 |
+
|
1169 |
+
num_left -= 3;
|
1170 |
+
|
1171 |
+
while (num_left) /* read past whatever is num_left */
|
1172 |
+
{
|
1173 |
+
get_bits(8);
|
1174 |
+
num_left--;
|
1175 |
+
}
|
1176 |
+
}
|
1177 |
+
|
1178 |
+
// Finds the next marker.
|
1179 |
+
int jpeg_decoder::next_marker()
|
1180 |
+
{
|
1181 |
+
uint c, bytes;
|
1182 |
+
|
1183 |
+
bytes = 0;
|
1184 |
+
|
1185 |
+
do
|
1186 |
+
{
|
1187 |
+
do
|
1188 |
+
{
|
1189 |
+
bytes++;
|
1190 |
+
c = get_bits(8);
|
1191 |
+
} while (c != 0xFF);
|
1192 |
+
|
1193 |
+
do
|
1194 |
+
{
|
1195 |
+
c = get_bits(8);
|
1196 |
+
} while (c == 0xFF);
|
1197 |
+
|
1198 |
+
} while (c == 0);
|
1199 |
+
|
1200 |
+
// If bytes > 0 here, there where extra bytes before the marker (not good).
|
1201 |
+
|
1202 |
+
return c;
|
1203 |
+
}
|
1204 |
+
|
1205 |
+
// Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is
|
1206 |
+
// encountered.
|
1207 |
+
int jpeg_decoder::process_markers()
|
1208 |
+
{
|
1209 |
+
int c;
|
1210 |
+
|
1211 |
+
for ( ; ; )
|
1212 |
+
{
|
1213 |
+
c = next_marker();
|
1214 |
+
|
1215 |
+
switch (c)
|
1216 |
+
{
|
1217 |
+
case M_SOF0:
|
1218 |
+
case M_SOF1:
|
1219 |
+
case M_SOF2:
|
1220 |
+
case M_SOF3:
|
1221 |
+
case M_SOF5:
|
1222 |
+
case M_SOF6:
|
1223 |
+
case M_SOF7:
|
1224 |
+
// case M_JPG:
|
1225 |
+
case M_SOF9:
|
1226 |
+
case M_SOF10:
|
1227 |
+
case M_SOF11:
|
1228 |
+
case M_SOF13:
|
1229 |
+
case M_SOF14:
|
1230 |
+
case M_SOF15:
|
1231 |
+
case M_SOI:
|
1232 |
+
case M_EOI:
|
1233 |
+
case M_SOS:
|
1234 |
+
{
|
1235 |
+
return c;
|
1236 |
+
}
|
1237 |
+
case M_DHT:
|
1238 |
+
{
|
1239 |
+
read_dht_marker();
|
1240 |
+
break;
|
1241 |
+
}
|
1242 |
+
// No arithmitic support - dumb patents!
|
1243 |
+
case M_DAC:
|
1244 |
+
{
|
1245 |
+
stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT);
|
1246 |
+
break;
|
1247 |
+
}
|
1248 |
+
case M_DQT:
|
1249 |
+
{
|
1250 |
+
read_dqt_marker();
|
1251 |
+
break;
|
1252 |
+
}
|
1253 |
+
case M_DRI:
|
1254 |
+
{
|
1255 |
+
read_dri_marker();
|
1256 |
+
break;
|
1257 |
+
}
|
1258 |
+
//case M_APP0: /* no need to read the JFIF marker */
|
1259 |
+
|
1260 |
+
case M_JPG:
|
1261 |
+
case M_RST0: /* no parameters */
|
1262 |
+
case M_RST1:
|
1263 |
+
case M_RST2:
|
1264 |
+
case M_RST3:
|
1265 |
+
case M_RST4:
|
1266 |
+
case M_RST5:
|
1267 |
+
case M_RST6:
|
1268 |
+
case M_RST7:
|
1269 |
+
case M_TEM:
|
1270 |
+
{
|
1271 |
+
stop_decoding(JPGD_UNEXPECTED_MARKER);
|
1272 |
+
break;
|
1273 |
+
}
|
1274 |
+
default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
|
1275 |
+
{
|
1276 |
+
skip_variable_marker();
|
1277 |
+
break;
|
1278 |
+
}
|
1279 |
+
}
|
1280 |
+
}
|
1281 |
+
}
|
1282 |
+
|
1283 |
+
// Finds the start of image (SOI) marker.
|
1284 |
+
// This code is rather defensive: it only checks the first 512 bytes to avoid
|
1285 |
+
// false positives.
|
1286 |
+
void jpeg_decoder::locate_soi_marker()
|
1287 |
+
{
|
1288 |
+
uint lastchar, thischar;
|
1289 |
+
uint bytesleft;
|
1290 |
+
|
1291 |
+
lastchar = get_bits(8);
|
1292 |
+
|
1293 |
+
thischar = get_bits(8);
|
1294 |
+
|
1295 |
+
/* ok if it's a normal JPEG file without a special header */
|
1296 |
+
|
1297 |
+
if ((lastchar == 0xFF) && (thischar == M_SOI))
|
1298 |
+
return;
|
1299 |
+
|
1300 |
+
bytesleft = 4096; //512;
|
1301 |
+
|
1302 |
+
for ( ; ; )
|
1303 |
+
{
|
1304 |
+
if (--bytesleft == 0)
|
1305 |
+
stop_decoding(JPGD_NOT_JPEG);
|
1306 |
+
|
1307 |
+
lastchar = thischar;
|
1308 |
+
|
1309 |
+
thischar = get_bits(8);
|
1310 |
+
|
1311 |
+
if (lastchar == 0xFF)
|
1312 |
+
{
|
1313 |
+
if (thischar == M_SOI)
|
1314 |
+
break;
|
1315 |
+
else if (thischar == M_EOI) // get_bits will keep returning M_EOI if we read past the end
|
1316 |
+
stop_decoding(JPGD_NOT_JPEG);
|
1317 |
+
}
|
1318 |
+
}
|
1319 |
+
|
1320 |
+
// Check the next character after marker: if it's not 0xFF, it can't be the start of the next marker, so the file is bad.
|
1321 |
+
thischar = (m_bit_buf >> 24) & 0xFF;
|
1322 |
+
|
1323 |
+
if (thischar != 0xFF)
|
1324 |
+
stop_decoding(JPGD_NOT_JPEG);
|
1325 |
+
}
|
1326 |
+
|
1327 |
+
// Find a start of frame (SOF) marker.
|
1328 |
+
void jpeg_decoder::locate_sof_marker()
|
1329 |
+
{
|
1330 |
+
locate_soi_marker();
|
1331 |
+
|
1332 |
+
int c = process_markers();
|
1333 |
+
|
1334 |
+
switch (c)
|
1335 |
+
{
|
1336 |
+
case M_SOF2:
|
1337 |
+
m_progressive_flag = JPGD_TRUE;
|
1338 |
+
case M_SOF0: /* baseline DCT */
|
1339 |
+
case M_SOF1: /* extended sequential DCT */
|
1340 |
+
{
|
1341 |
+
read_sof_marker();
|
1342 |
+
break;
|
1343 |
+
}
|
1344 |
+
case M_SOF9: /* Arithmitic coding */
|
1345 |
+
{
|
1346 |
+
stop_decoding(JPGD_NO_ARITHMITIC_SUPPORT);
|
1347 |
+
break;
|
1348 |
+
}
|
1349 |
+
default:
|
1350 |
+
{
|
1351 |
+
stop_decoding(JPGD_UNSUPPORTED_MARKER);
|
1352 |
+
break;
|
1353 |
+
}
|
1354 |
+
}
|
1355 |
+
}
|
1356 |
+
|
1357 |
+
// Find a start of scan (SOS) marker.
|
1358 |
+
int jpeg_decoder::locate_sos_marker()
|
1359 |
+
{
|
1360 |
+
int c;
|
1361 |
+
|
1362 |
+
c = process_markers();
|
1363 |
+
|
1364 |
+
if (c == M_EOI)
|
1365 |
+
return JPGD_FALSE;
|
1366 |
+
else if (c != M_SOS)
|
1367 |
+
stop_decoding(JPGD_UNEXPECTED_MARKER);
|
1368 |
+
|
1369 |
+
read_sos_marker();
|
1370 |
+
|
1371 |
+
return JPGD_TRUE;
|
1372 |
+
}
|
1373 |
+
|
1374 |
+
// Reset everything to default/uninitialized state.
|
1375 |
+
void jpeg_decoder::init(jpeg_decoder_stream *pStream)
|
1376 |
+
{
|
1377 |
+
m_pMem_blocks = NULL;
|
1378 |
+
m_error_code = JPGD_SUCCESS;
|
1379 |
+
m_ready_flag = false;
|
1380 |
+
m_image_x_size = m_image_y_size = 0;
|
1381 |
+
m_pStream = pStream;
|
1382 |
+
m_progressive_flag = JPGD_FALSE;
|
1383 |
+
|
1384 |
+
memset(m_huff_ac, 0, sizeof(m_huff_ac));
|
1385 |
+
memset(m_huff_num, 0, sizeof(m_huff_num));
|
1386 |
+
memset(m_huff_val, 0, sizeof(m_huff_val));
|
1387 |
+
memset(m_quant, 0, sizeof(m_quant));
|
1388 |
+
|
1389 |
+
m_scan_type = 0;
|
1390 |
+
m_comps_in_frame = 0;
|
1391 |
+
|
1392 |
+
memset(m_comp_h_samp, 0, sizeof(m_comp_h_samp));
|
1393 |
+
memset(m_comp_v_samp, 0, sizeof(m_comp_v_samp));
|
1394 |
+
memset(m_comp_quant, 0, sizeof(m_comp_quant));
|
1395 |
+
memset(m_comp_ident, 0, sizeof(m_comp_ident));
|
1396 |
+
memset(m_comp_h_blocks, 0, sizeof(m_comp_h_blocks));
|
1397 |
+
memset(m_comp_v_blocks, 0, sizeof(m_comp_v_blocks));
|
1398 |
+
|
1399 |
+
m_comps_in_scan = 0;
|
1400 |
+
memset(m_comp_list, 0, sizeof(m_comp_list));
|
1401 |
+
memset(m_comp_dc_tab, 0, sizeof(m_comp_dc_tab));
|
1402 |
+
memset(m_comp_ac_tab, 0, sizeof(m_comp_ac_tab));
|
1403 |
+
|
1404 |
+
m_spectral_start = 0;
|
1405 |
+
m_spectral_end = 0;
|
1406 |
+
m_successive_low = 0;
|
1407 |
+
m_successive_high = 0;
|
1408 |
+
m_max_mcu_x_size = 0;
|
1409 |
+
m_max_mcu_y_size = 0;
|
1410 |
+
m_blocks_per_mcu = 0;
|
1411 |
+
m_max_blocks_per_row = 0;
|
1412 |
+
m_mcus_per_row = 0;
|
1413 |
+
m_mcus_per_col = 0;
|
1414 |
+
m_expanded_blocks_per_component = 0;
|
1415 |
+
m_expanded_blocks_per_mcu = 0;
|
1416 |
+
m_expanded_blocks_per_row = 0;
|
1417 |
+
m_freq_domain_chroma_upsample = false;
|
1418 |
+
|
1419 |
+
memset(m_mcu_org, 0, sizeof(m_mcu_org));
|
1420 |
+
|
1421 |
+
m_total_lines_left = 0;
|
1422 |
+
m_mcu_lines_left = 0;
|
1423 |
+
m_real_dest_bytes_per_scan_line = 0;
|
1424 |
+
m_dest_bytes_per_scan_line = 0;
|
1425 |
+
m_dest_bytes_per_pixel = 0;
|
1426 |
+
|
1427 |
+
memset(m_pHuff_tabs, 0, sizeof(m_pHuff_tabs));
|
1428 |
+
|
1429 |
+
memset(m_dc_coeffs, 0, sizeof(m_dc_coeffs));
|
1430 |
+
memset(m_ac_coeffs, 0, sizeof(m_ac_coeffs));
|
1431 |
+
memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
|
1432 |
+
|
1433 |
+
m_eob_run = 0;
|
1434 |
+
|
1435 |
+
memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
|
1436 |
+
|
1437 |
+
m_pIn_buf_ofs = m_in_buf;
|
1438 |
+
m_in_buf_left = 0;
|
1439 |
+
m_eof_flag = false;
|
1440 |
+
m_tem_flag = 0;
|
1441 |
+
|
1442 |
+
memset(m_in_buf_pad_start, 0, sizeof(m_in_buf_pad_start));
|
1443 |
+
memset(m_in_buf, 0, sizeof(m_in_buf));
|
1444 |
+
memset(m_in_buf_pad_end, 0, sizeof(m_in_buf_pad_end));
|
1445 |
+
|
1446 |
+
m_restart_interval = 0;
|
1447 |
+
m_restarts_left = 0;
|
1448 |
+
m_next_restart_num = 0;
|
1449 |
+
|
1450 |
+
m_max_mcus_per_row = 0;
|
1451 |
+
m_max_blocks_per_mcu = 0;
|
1452 |
+
m_max_mcus_per_col = 0;
|
1453 |
+
|
1454 |
+
memset(m_last_dc_val, 0, sizeof(m_last_dc_val));
|
1455 |
+
m_pMCU_coefficients = NULL;
|
1456 |
+
m_pSample_buf = NULL;
|
1457 |
+
|
1458 |
+
m_total_bytes_read = 0;
|
1459 |
+
|
1460 |
+
m_pScan_line_0 = NULL;
|
1461 |
+
m_pScan_line_1 = NULL;
|
1462 |
+
|
1463 |
+
// Ready the input buffer.
|
1464 |
+
prep_in_buffer();
|
1465 |
+
|
1466 |
+
// Prime the bit buffer.
|
1467 |
+
m_bits_left = 16;
|
1468 |
+
m_bit_buf = 0;
|
1469 |
+
|
1470 |
+
get_bits(16);
|
1471 |
+
get_bits(16);
|
1472 |
+
|
1473 |
+
for (int i = 0; i < JPGD_MAX_BLOCKS_PER_MCU; i++)
|
1474 |
+
m_mcu_block_max_zag[i] = 64;
|
1475 |
+
}
|
1476 |
+
|
1477 |
+
#define SCALEBITS 16
|
1478 |
+
#define ONE_HALF ((int) 1 << (SCALEBITS-1))
|
1479 |
+
#define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5f))
|
1480 |
+
|
1481 |
+
// Create a few tables that allow us to quickly convert YCbCr to RGB.
|
1482 |
+
void jpeg_decoder::create_look_ups()
|
1483 |
+
{
|
1484 |
+
for (int i = 0; i <= 255; i++)
|
1485 |
+
{
|
1486 |
+
int k = i - 128;
|
1487 |
+
m_crr[i] = ( FIX(1.40200f) * k + ONE_HALF) >> SCALEBITS;
|
1488 |
+
m_cbb[i] = ( FIX(1.77200f) * k + ONE_HALF) >> SCALEBITS;
|
1489 |
+
m_crg[i] = (-FIX(0.71414f)) * k;
|
1490 |
+
m_cbg[i] = (-FIX(0.34414f)) * k + ONE_HALF;
|
1491 |
+
}
|
1492 |
+
}
|
1493 |
+
|
1494 |
+
// This method throws back into the stream any bytes that where read
|
1495 |
+
// into the bit buffer during initial marker scanning.
|
1496 |
+
void jpeg_decoder::fix_in_buffer()
|
1497 |
+
{
|
1498 |
+
// In case any 0xFF's where pulled into the buffer during marker scanning.
|
1499 |
+
JPGD_ASSERT((m_bits_left & 7) == 0);
|
1500 |
+
|
1501 |
+
if (m_bits_left == 16)
|
1502 |
+
stuff_char( (uint8)(m_bit_buf & 0xFF));
|
1503 |
+
|
1504 |
+
if (m_bits_left >= 8)
|
1505 |
+
stuff_char( (uint8)((m_bit_buf >> 8) & 0xFF));
|
1506 |
+
|
1507 |
+
stuff_char((uint8)((m_bit_buf >> 16) & 0xFF));
|
1508 |
+
stuff_char((uint8)((m_bit_buf >> 24) & 0xFF));
|
1509 |
+
|
1510 |
+
m_bits_left = 16;
|
1511 |
+
get_bits_no_markers(16);
|
1512 |
+
get_bits_no_markers(16);
|
1513 |
+
}
|
1514 |
+
|
1515 |
+
void jpeg_decoder::transform_mcu(int mcu_row)
|
1516 |
+
{
|
1517 |
+
jpgd_block_t* pSrc_ptr = m_pMCU_coefficients;
|
1518 |
+
uint8* pDst_ptr = m_pSample_buf + mcu_row * m_blocks_per_mcu * 64;
|
1519 |
+
|
1520 |
+
for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
|
1521 |
+
{
|
1522 |
+
idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]);
|
1523 |
+
pSrc_ptr += 64;
|
1524 |
+
pDst_ptr += 64;
|
1525 |
+
}
|
1526 |
+
}
|
1527 |
+
|
1528 |
+
static const uint8 s_max_rc[64] =
|
1529 |
+
{
|
1530 |
+
17, 18, 34, 50, 50, 51, 52, 52, 52, 68, 84, 84, 84, 84, 85, 86, 86, 86, 86, 86,
|
1531 |
+
102, 118, 118, 118, 118, 118, 118, 119, 120, 120, 120, 120, 120, 120, 120, 136,
|
1532 |
+
136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
|
1533 |
+
136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136
|
1534 |
+
};
|
1535 |
+
|
1536 |
+
void jpeg_decoder::transform_mcu_expand(int mcu_row)
|
1537 |
+
{
|
1538 |
+
jpgd_block_t* pSrc_ptr = m_pMCU_coefficients;
|
1539 |
+
uint8* pDst_ptr = m_pSample_buf + mcu_row * m_expanded_blocks_per_mcu * 64;
|
1540 |
+
|
1541 |
+
// Y IDCT
|
1542 |
+
int mcu_block;
|
1543 |
+
for (mcu_block = 0; mcu_block < m_expanded_blocks_per_component; mcu_block++)
|
1544 |
+
{
|
1545 |
+
idct(pSrc_ptr, pDst_ptr, m_mcu_block_max_zag[mcu_block]);
|
1546 |
+
pSrc_ptr += 64;
|
1547 |
+
pDst_ptr += 64;
|
1548 |
+
}
|
1549 |
+
|
1550 |
+
// Chroma IDCT, with upsampling
|
1551 |
+
jpgd_block_t temp_block[64];
|
1552 |
+
|
1553 |
+
for (int i = 0; i < 2; i++)
|
1554 |
+
{
|
1555 |
+
DCT_Upsample::Matrix44 P, Q, R, S;
|
1556 |
+
|
1557 |
+
JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] >= 1);
|
1558 |
+
JPGD_ASSERT(m_mcu_block_max_zag[mcu_block] <= 64);
|
1559 |
+
|
1560 |
+
switch (s_max_rc[m_mcu_block_max_zag[mcu_block++] - 1])
|
1561 |
+
{
|
1562 |
+
case 1*16+1:
|
1563 |
+
DCT_Upsample::P_Q<1, 1>::calc(P, Q, pSrc_ptr);
|
1564 |
+
DCT_Upsample::R_S<1, 1>::calc(R, S, pSrc_ptr);
|
1565 |
+
break;
|
1566 |
+
case 1*16+2:
|
1567 |
+
DCT_Upsample::P_Q<1, 2>::calc(P, Q, pSrc_ptr);
|
1568 |
+
DCT_Upsample::R_S<1, 2>::calc(R, S, pSrc_ptr);
|
1569 |
+
break;
|
1570 |
+
case 2*16+2:
|
1571 |
+
DCT_Upsample::P_Q<2, 2>::calc(P, Q, pSrc_ptr);
|
1572 |
+
DCT_Upsample::R_S<2, 2>::calc(R, S, pSrc_ptr);
|
1573 |
+
break;
|
1574 |
+
case 3*16+2:
|
1575 |
+
DCT_Upsample::P_Q<3, 2>::calc(P, Q, pSrc_ptr);
|
1576 |
+
DCT_Upsample::R_S<3, 2>::calc(R, S, pSrc_ptr);
|
1577 |
+
break;
|
1578 |
+
case 3*16+3:
|
1579 |
+
DCT_Upsample::P_Q<3, 3>::calc(P, Q, pSrc_ptr);
|
1580 |
+
DCT_Upsample::R_S<3, 3>::calc(R, S, pSrc_ptr);
|
1581 |
+
break;
|
1582 |
+
case 3*16+4:
|
1583 |
+
DCT_Upsample::P_Q<3, 4>::calc(P, Q, pSrc_ptr);
|
1584 |
+
DCT_Upsample::R_S<3, 4>::calc(R, S, pSrc_ptr);
|
1585 |
+
break;
|
1586 |
+
case 4*16+4:
|
1587 |
+
DCT_Upsample::P_Q<4, 4>::calc(P, Q, pSrc_ptr);
|
1588 |
+
DCT_Upsample::R_S<4, 4>::calc(R, S, pSrc_ptr);
|
1589 |
+
break;
|
1590 |
+
case 5*16+4:
|
1591 |
+
DCT_Upsample::P_Q<5, 4>::calc(P, Q, pSrc_ptr);
|
1592 |
+
DCT_Upsample::R_S<5, 4>::calc(R, S, pSrc_ptr);
|
1593 |
+
break;
|
1594 |
+
case 5*16+5:
|
1595 |
+
DCT_Upsample::P_Q<5, 5>::calc(P, Q, pSrc_ptr);
|
1596 |
+
DCT_Upsample::R_S<5, 5>::calc(R, S, pSrc_ptr);
|
1597 |
+
break;
|
1598 |
+
case 5*16+6:
|
1599 |
+
DCT_Upsample::P_Q<5, 6>::calc(P, Q, pSrc_ptr);
|
1600 |
+
DCT_Upsample::R_S<5, 6>::calc(R, S, pSrc_ptr);
|
1601 |
+
break;
|
1602 |
+
case 6*16+6:
|
1603 |
+
DCT_Upsample::P_Q<6, 6>::calc(P, Q, pSrc_ptr);
|
1604 |
+
DCT_Upsample::R_S<6, 6>::calc(R, S, pSrc_ptr);
|
1605 |
+
break;
|
1606 |
+
case 7*16+6:
|
1607 |
+
DCT_Upsample::P_Q<7, 6>::calc(P, Q, pSrc_ptr);
|
1608 |
+
DCT_Upsample::R_S<7, 6>::calc(R, S, pSrc_ptr);
|
1609 |
+
break;
|
1610 |
+
case 7*16+7:
|
1611 |
+
DCT_Upsample::P_Q<7, 7>::calc(P, Q, pSrc_ptr);
|
1612 |
+
DCT_Upsample::R_S<7, 7>::calc(R, S, pSrc_ptr);
|
1613 |
+
break;
|
1614 |
+
case 7*16+8:
|
1615 |
+
DCT_Upsample::P_Q<7, 8>::calc(P, Q, pSrc_ptr);
|
1616 |
+
DCT_Upsample::R_S<7, 8>::calc(R, S, pSrc_ptr);
|
1617 |
+
break;
|
1618 |
+
case 8*16+8:
|
1619 |
+
DCT_Upsample::P_Q<8, 8>::calc(P, Q, pSrc_ptr);
|
1620 |
+
DCT_Upsample::R_S<8, 8>::calc(R, S, pSrc_ptr);
|
1621 |
+
break;
|
1622 |
+
default:
|
1623 |
+
JPGD_ASSERT(false);
|
1624 |
+
}
|
1625 |
+
|
1626 |
+
DCT_Upsample::Matrix44 a(P + Q); P -= Q;
|
1627 |
+
DCT_Upsample::Matrix44& b = P;
|
1628 |
+
DCT_Upsample::Matrix44 c(R + S); R -= S;
|
1629 |
+
DCT_Upsample::Matrix44& d = R;
|
1630 |
+
|
1631 |
+
DCT_Upsample::Matrix44::add_and_store(temp_block, a, c);
|
1632 |
+
idct_4x4(temp_block, pDst_ptr);
|
1633 |
+
pDst_ptr += 64;
|
1634 |
+
|
1635 |
+
DCT_Upsample::Matrix44::sub_and_store(temp_block, a, c);
|
1636 |
+
idct_4x4(temp_block, pDst_ptr);
|
1637 |
+
pDst_ptr += 64;
|
1638 |
+
|
1639 |
+
DCT_Upsample::Matrix44::add_and_store(temp_block, b, d);
|
1640 |
+
idct_4x4(temp_block, pDst_ptr);
|
1641 |
+
pDst_ptr += 64;
|
1642 |
+
|
1643 |
+
DCT_Upsample::Matrix44::sub_and_store(temp_block, b, d);
|
1644 |
+
idct_4x4(temp_block, pDst_ptr);
|
1645 |
+
pDst_ptr += 64;
|
1646 |
+
|
1647 |
+
pSrc_ptr += 64;
|
1648 |
+
}
|
1649 |
+
}
|
1650 |
+
|
1651 |
+
// Loads and dequantizes the next row of (already decoded) coefficients.
|
1652 |
+
// Progressive images only.
|
1653 |
+
void jpeg_decoder::load_next_row()
|
1654 |
+
{
|
1655 |
+
int i;
|
1656 |
+
jpgd_block_t *p;
|
1657 |
+
jpgd_quant_t *q;
|
1658 |
+
int mcu_row, mcu_block, row_block = 0;
|
1659 |
+
int component_num, component_id;
|
1660 |
+
int block_x_mcu[JPGD_MAX_COMPONENTS];
|
1661 |
+
|
1662 |
+
memset(block_x_mcu, 0, JPGD_MAX_COMPONENTS * sizeof(int));
|
1663 |
+
|
1664 |
+
for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
|
1665 |
+
{
|
1666 |
+
int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0;
|
1667 |
+
|
1668 |
+
for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
|
1669 |
+
{
|
1670 |
+
component_id = m_mcu_org[mcu_block];
|
1671 |
+
q = m_quant[m_comp_quant[component_id]];
|
1672 |
+
|
1673 |
+
p = m_pMCU_coefficients + 64 * mcu_block;
|
1674 |
+
|
1675 |
+
jpgd_block_t* pAC = coeff_buf_getp(m_ac_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
|
1676 |
+
jpgd_block_t* pDC = coeff_buf_getp(m_dc_coeffs[component_id], block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
|
1677 |
+
p[0] = pDC[0];
|
1678 |
+
memcpy(&p[1], &pAC[1], 63 * sizeof(jpgd_block_t));
|
1679 |
+
|
1680 |
+
for (i = 63; i > 0; i--)
|
1681 |
+
if (p[g_ZAG[i]])
|
1682 |
+
break;
|
1683 |
+
|
1684 |
+
m_mcu_block_max_zag[mcu_block] = i + 1;
|
1685 |
+
|
1686 |
+
for ( ; i >= 0; i--)
|
1687 |
+
if (p[g_ZAG[i]])
|
1688 |
+
p[g_ZAG[i]] = static_cast<jpgd_block_t>(p[g_ZAG[i]] * q[i]);
|
1689 |
+
|
1690 |
+
row_block++;
|
1691 |
+
|
1692 |
+
if (m_comps_in_scan == 1)
|
1693 |
+
block_x_mcu[component_id]++;
|
1694 |
+
else
|
1695 |
+
{
|
1696 |
+
if (++block_x_mcu_ofs == m_comp_h_samp[component_id])
|
1697 |
+
{
|
1698 |
+
block_x_mcu_ofs = 0;
|
1699 |
+
|
1700 |
+
if (++block_y_mcu_ofs == m_comp_v_samp[component_id])
|
1701 |
+
{
|
1702 |
+
block_y_mcu_ofs = 0;
|
1703 |
+
|
1704 |
+
block_x_mcu[component_id] += m_comp_h_samp[component_id];
|
1705 |
+
}
|
1706 |
+
}
|
1707 |
+
}
|
1708 |
+
}
|
1709 |
+
|
1710 |
+
if (m_freq_domain_chroma_upsample)
|
1711 |
+
transform_mcu_expand(mcu_row);
|
1712 |
+
else
|
1713 |
+
transform_mcu(mcu_row);
|
1714 |
+
}
|
1715 |
+
|
1716 |
+
if (m_comps_in_scan == 1)
|
1717 |
+
m_block_y_mcu[m_comp_list[0]]++;
|
1718 |
+
else
|
1719 |
+
{
|
1720 |
+
for (component_num = 0; component_num < m_comps_in_scan; component_num++)
|
1721 |
+
{
|
1722 |
+
component_id = m_comp_list[component_num];
|
1723 |
+
|
1724 |
+
m_block_y_mcu[component_id] += m_comp_v_samp[component_id];
|
1725 |
+
}
|
1726 |
+
}
|
1727 |
+
}
|
1728 |
+
|
1729 |
+
// Restart interval processing.
|
1730 |
+
void jpeg_decoder::process_restart()
|
1731 |
+
{
|
1732 |
+
int i;
|
1733 |
+
int c = 0;
|
1734 |
+
|
1735 |
+
// Align to a byte boundry
|
1736 |
+
// FIXME: Is this really necessary? get_bits_no_markers() never reads in markers!
|
1737 |
+
//get_bits_no_markers(m_bits_left & 7);
|
1738 |
+
|
1739 |
+
// Let's scan a little bit to find the marker, but not _too_ far.
|
1740 |
+
// 1536 is a "fudge factor" that determines how much to scan.
|
1741 |
+
for (i = 1536; i > 0; i--)
|
1742 |
+
if (get_char() == 0xFF)
|
1743 |
+
break;
|
1744 |
+
|
1745 |
+
if (i == 0)
|
1746 |
+
stop_decoding(JPGD_BAD_RESTART_MARKER);
|
1747 |
+
|
1748 |
+
for ( ; i > 0; i--)
|
1749 |
+
if ((c = get_char()) != 0xFF)
|
1750 |
+
break;
|
1751 |
+
|
1752 |
+
if (i == 0)
|
1753 |
+
stop_decoding(JPGD_BAD_RESTART_MARKER);
|
1754 |
+
|
1755 |
+
// Is it the expected marker? If not, something bad happened.
|
1756 |
+
if (c != (m_next_restart_num + M_RST0))
|
1757 |
+
stop_decoding(JPGD_BAD_RESTART_MARKER);
|
1758 |
+
|
1759 |
+
// Reset each component's DC prediction values.
|
1760 |
+
memset(&m_last_dc_val, 0, m_comps_in_frame * sizeof(uint));
|
1761 |
+
|
1762 |
+
m_eob_run = 0;
|
1763 |
+
|
1764 |
+
m_restarts_left = m_restart_interval;
|
1765 |
+
|
1766 |
+
m_next_restart_num = (m_next_restart_num + 1) & 7;
|
1767 |
+
|
1768 |
+
// Get the bit buffer going again...
|
1769 |
+
|
1770 |
+
m_bits_left = 16;
|
1771 |
+
get_bits_no_markers(16);
|
1772 |
+
get_bits_no_markers(16);
|
1773 |
+
}
|
1774 |
+
|
1775 |
+
static inline int dequantize_ac(int c, int q) { c *= q; return c; }
|
1776 |
+
|
1777 |
+
// Decodes and dequantizes the next row of coefficients.
|
1778 |
+
void jpeg_decoder::decode_next_row()
|
1779 |
+
{
|
1780 |
+
int row_block = 0;
|
1781 |
+
|
1782 |
+
for (int mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
|
1783 |
+
{
|
1784 |
+
if ((m_restart_interval) && (m_restarts_left == 0))
|
1785 |
+
process_restart();
|
1786 |
+
|
1787 |
+
jpgd_block_t* p = m_pMCU_coefficients;
|
1788 |
+
for (int mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++, p += 64)
|
1789 |
+
{
|
1790 |
+
int component_id = m_mcu_org[mcu_block];
|
1791 |
+
jpgd_quant_t* q = m_quant[m_comp_quant[component_id]];
|
1792 |
+
|
1793 |
+
int r, s;
|
1794 |
+
s = huff_decode(m_pHuff_tabs[m_comp_dc_tab[component_id]], r);
|
1795 |
+
s = HUFF_EXTEND(r, s);
|
1796 |
+
|
1797 |
+
m_last_dc_val[component_id] = (s += m_last_dc_val[component_id]);
|
1798 |
+
|
1799 |
+
p[0] = static_cast<jpgd_block_t>(s * q[0]);
|
1800 |
+
|
1801 |
+
int prev_num_set = m_mcu_block_max_zag[mcu_block];
|
1802 |
+
|
1803 |
+
huff_tables *pH = m_pHuff_tabs[m_comp_ac_tab[component_id]];
|
1804 |
+
|
1805 |
+
int k;
|
1806 |
+
for (k = 1; k < 64; k++)
|
1807 |
+
{
|
1808 |
+
int extra_bits;
|
1809 |
+
s = huff_decode(pH, extra_bits);
|
1810 |
+
|
1811 |
+
r = s >> 4;
|
1812 |
+
s &= 15;
|
1813 |
+
|
1814 |
+
if (s)
|
1815 |
+
{
|
1816 |
+
if (r)
|
1817 |
+
{
|
1818 |
+
if ((k + r) > 63)
|
1819 |
+
stop_decoding(JPGD_DECODE_ERROR);
|
1820 |
+
|
1821 |
+
if (k < prev_num_set)
|
1822 |
+
{
|
1823 |
+
int n = JPGD_MIN(r, prev_num_set - k);
|
1824 |
+
int kt = k;
|
1825 |
+
while (n--)
|
1826 |
+
p[g_ZAG[kt++]] = 0;
|
1827 |
+
}
|
1828 |
+
|
1829 |
+
k += r;
|
1830 |
+
}
|
1831 |
+
|
1832 |
+
s = HUFF_EXTEND(extra_bits, s);
|
1833 |
+
|
1834 |
+
JPGD_ASSERT(k < 64);
|
1835 |
+
|
1836 |
+
p[g_ZAG[k]] = static_cast<jpgd_block_t>(dequantize_ac(s, q[k])); //s * q[k];
|
1837 |
+
}
|
1838 |
+
else
|
1839 |
+
{
|
1840 |
+
if (r == 15)
|
1841 |
+
{
|
1842 |
+
if ((k + 16) > 64)
|
1843 |
+
stop_decoding(JPGD_DECODE_ERROR);
|
1844 |
+
|
1845 |
+
if (k < prev_num_set)
|
1846 |
+
{
|
1847 |
+
int n = JPGD_MIN(16, prev_num_set - k);
|
1848 |
+
int kt = k;
|
1849 |
+
while (n--)
|
1850 |
+
{
|
1851 |
+
JPGD_ASSERT(kt <= 63);
|
1852 |
+
p[g_ZAG[kt++]] = 0;
|
1853 |
+
}
|
1854 |
+
}
|
1855 |
+
|
1856 |
+
k += 16 - 1; // - 1 because the loop counter is k
|
1857 |
+
// BEGIN EPIC MOD
|
1858 |
+
JPGD_ASSERT(k < 64 && p[g_ZAG[k]] == 0);
|
1859 |
+
// END EPIC MOD
|
1860 |
+
}
|
1861 |
+
else
|
1862 |
+
break;
|
1863 |
+
}
|
1864 |
+
}
|
1865 |
+
|
1866 |
+
if (k < prev_num_set)
|
1867 |
+
{
|
1868 |
+
int kt = k;
|
1869 |
+
while (kt < prev_num_set)
|
1870 |
+
p[g_ZAG[kt++]] = 0;
|
1871 |
+
}
|
1872 |
+
|
1873 |
+
m_mcu_block_max_zag[mcu_block] = k;
|
1874 |
+
|
1875 |
+
row_block++;
|
1876 |
+
}
|
1877 |
+
|
1878 |
+
if (m_freq_domain_chroma_upsample)
|
1879 |
+
transform_mcu_expand(mcu_row);
|
1880 |
+
else
|
1881 |
+
transform_mcu(mcu_row);
|
1882 |
+
|
1883 |
+
m_restarts_left--;
|
1884 |
+
}
|
1885 |
+
}
|
1886 |
+
|
1887 |
+
// YCbCr H1V1 (1x1:1:1, 3 m_blocks per MCU) to RGB
|
1888 |
+
void jpeg_decoder::H1V1Convert()
|
1889 |
+
{
|
1890 |
+
int row = m_max_mcu_y_size - m_mcu_lines_left;
|
1891 |
+
uint8 *d = m_pScan_line_0;
|
1892 |
+
uint8 *s = m_pSample_buf + row * 8;
|
1893 |
+
|
1894 |
+
for (int i = m_max_mcus_per_row; i > 0; i--)
|
1895 |
+
{
|
1896 |
+
for (int j = 0; j < 8; j++)
|
1897 |
+
{
|
1898 |
+
int y = s[j];
|
1899 |
+
int cb = s[64+j];
|
1900 |
+
int cr = s[128+j];
|
1901 |
+
|
1902 |
+
if (jpg_format == ERGBFormatJPG::BGRA)
|
1903 |
+
{
|
1904 |
+
d[0] = clamp(y + m_cbb[cb]);
|
1905 |
+
d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
|
1906 |
+
d[2] = clamp(y + m_crr[cr]);
|
1907 |
+
d[3] = 255;
|
1908 |
+
}
|
1909 |
+
else
|
1910 |
+
{
|
1911 |
+
d[0] = clamp(y + m_crr[cr]);
|
1912 |
+
d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
|
1913 |
+
d[2] = clamp(y + m_cbb[cb]);
|
1914 |
+
d[3] = 255;
|
1915 |
+
}
|
1916 |
+
d += 4;
|
1917 |
+
}
|
1918 |
+
|
1919 |
+
s += 64*3;
|
1920 |
+
}
|
1921 |
+
}
|
1922 |
+
|
1923 |
+
// YCbCr H2V1 (2x1:1:1, 4 m_blocks per MCU) to RGB
|
1924 |
+
void jpeg_decoder::H2V1Convert()
|
1925 |
+
{
|
1926 |
+
int row = m_max_mcu_y_size - m_mcu_lines_left;
|
1927 |
+
uint8 *d0 = m_pScan_line_0;
|
1928 |
+
uint8 *y = m_pSample_buf + row * 8;
|
1929 |
+
uint8 *c = m_pSample_buf + 2*64 + row * 8;
|
1930 |
+
|
1931 |
+
for (int i = m_max_mcus_per_row; i > 0; i--)
|
1932 |
+
{
|
1933 |
+
for (int l = 0; l < 2; l++)
|
1934 |
+
{
|
1935 |
+
for (int j = 0; j < 4; j++)
|
1936 |
+
{
|
1937 |
+
int cb = c[0];
|
1938 |
+
int cr = c[64];
|
1939 |
+
|
1940 |
+
int rc = m_crr[cr];
|
1941 |
+
int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
|
1942 |
+
int bc = m_cbb[cb];
|
1943 |
+
|
1944 |
+
int yy = y[j<<1];
|
1945 |
+
if (jpg_format == ERGBFormatJPG::BGRA)
|
1946 |
+
{
|
1947 |
+
d0[0] = clamp(yy+bc);
|
1948 |
+
d0[1] = clamp(yy+gc);
|
1949 |
+
d0[2] = clamp(yy+rc);
|
1950 |
+
d0[3] = 255;
|
1951 |
+
yy = y[(j<<1)+1];
|
1952 |
+
d0[4] = clamp(yy+bc);
|
1953 |
+
d0[5] = clamp(yy+gc);
|
1954 |
+
d0[6] = clamp(yy+rc);
|
1955 |
+
d0[7] = 255;
|
1956 |
+
}
|
1957 |
+
else
|
1958 |
+
{
|
1959 |
+
d0[0] = clamp(yy+rc);
|
1960 |
+
d0[1] = clamp(yy+gc);
|
1961 |
+
d0[2] = clamp(yy+bc);
|
1962 |
+
d0[3] = 255;
|
1963 |
+
yy = y[(j<<1)+1];
|
1964 |
+
d0[4] = clamp(yy+rc);
|
1965 |
+
d0[5] = clamp(yy+gc);
|
1966 |
+
d0[6] = clamp(yy+bc);
|
1967 |
+
d0[7] = 255;
|
1968 |
+
}
|
1969 |
+
|
1970 |
+
d0 += 8;
|
1971 |
+
|
1972 |
+
c++;
|
1973 |
+
}
|
1974 |
+
y += 64;
|
1975 |
+
}
|
1976 |
+
|
1977 |
+
y += 64*4 - 64*2;
|
1978 |
+
c += 64*4 - 8;
|
1979 |
+
}
|
1980 |
+
}
|
1981 |
+
|
1982 |
+
// YCbCr H2V1 (1x2:1:1, 4 m_blocks per MCU) to RGB
|
1983 |
+
void jpeg_decoder::H1V2Convert()
|
1984 |
+
{
|
1985 |
+
int row = m_max_mcu_y_size - m_mcu_lines_left;
|
1986 |
+
uint8 *d0 = m_pScan_line_0;
|
1987 |
+
uint8 *d1 = m_pScan_line_1;
|
1988 |
+
uint8 *y;
|
1989 |
+
uint8 *c;
|
1990 |
+
|
1991 |
+
if (row < 8)
|
1992 |
+
y = m_pSample_buf + row * 8;
|
1993 |
+
else
|
1994 |
+
y = m_pSample_buf + 64*1 + (row & 7) * 8;
|
1995 |
+
|
1996 |
+
c = m_pSample_buf + 64*2 + (row >> 1) * 8;
|
1997 |
+
|
1998 |
+
for (int i = m_max_mcus_per_row; i > 0; i--)
|
1999 |
+
{
|
2000 |
+
for (int j = 0; j < 8; j++)
|
2001 |
+
{
|
2002 |
+
int cb = c[0+j];
|
2003 |
+
int cr = c[64+j];
|
2004 |
+
|
2005 |
+
int rc = m_crr[cr];
|
2006 |
+
int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
|
2007 |
+
int bc = m_cbb[cb];
|
2008 |
+
|
2009 |
+
int yy = y[j];
|
2010 |
+
if (jpg_format == ERGBFormatJPG::BGRA)
|
2011 |
+
{
|
2012 |
+
d0[0] = clamp(yy+bc);
|
2013 |
+
d0[1] = clamp(yy+gc);
|
2014 |
+
d0[2] = clamp(yy+rc);
|
2015 |
+
d0[3] = 255;
|
2016 |
+
yy = y[8+j];
|
2017 |
+
d1[0] = clamp(yy+bc);
|
2018 |
+
d1[1] = clamp(yy+gc);
|
2019 |
+
d1[2] = clamp(yy+rc);
|
2020 |
+
d1[3] = 255;
|
2021 |
+
}
|
2022 |
+
else
|
2023 |
+
{
|
2024 |
+
d0[0] = clamp(yy+rc);
|
2025 |
+
d0[1] = clamp(yy+gc);
|
2026 |
+
d0[2] = clamp(yy+bc);
|
2027 |
+
d0[3] = 255;
|
2028 |
+
yy = y[8+j];
|
2029 |
+
d1[0] = clamp(yy+rc);
|
2030 |
+
d1[1] = clamp(yy+gc);
|
2031 |
+
d1[2] = clamp(yy+bc);
|
2032 |
+
d1[3] = 255;
|
2033 |
+
}
|
2034 |
+
|
2035 |
+
d0 += 4;
|
2036 |
+
d1 += 4;
|
2037 |
+
}
|
2038 |
+
|
2039 |
+
y += 64*4;
|
2040 |
+
c += 64*4;
|
2041 |
+
}
|
2042 |
+
}
|
2043 |
+
|
2044 |
+
// YCbCr H2V2 (2x2:1:1, 6 m_blocks per MCU) to RGB
|
2045 |
+
void jpeg_decoder::H2V2Convert()
|
2046 |
+
{
|
2047 |
+
int row = m_max_mcu_y_size - m_mcu_lines_left;
|
2048 |
+
uint8 *d0 = m_pScan_line_0;
|
2049 |
+
uint8 *d1 = m_pScan_line_1;
|
2050 |
+
uint8 *y;
|
2051 |
+
uint8 *c;
|
2052 |
+
|
2053 |
+
if (row < 8)
|
2054 |
+
y = m_pSample_buf + row * 8;
|
2055 |
+
else
|
2056 |
+
y = m_pSample_buf + 64*2 + (row & 7) * 8;
|
2057 |
+
|
2058 |
+
c = m_pSample_buf + 64*4 + (row >> 1) * 8;
|
2059 |
+
|
2060 |
+
for (int i = m_max_mcus_per_row; i > 0; i--)
|
2061 |
+
{
|
2062 |
+
for (int l = 0; l < 2; l++)
|
2063 |
+
{
|
2064 |
+
for (int j = 0; j < 8; j += 2)
|
2065 |
+
{
|
2066 |
+
int cb = c[0];
|
2067 |
+
int cr = c[64];
|
2068 |
+
|
2069 |
+
int rc = m_crr[cr];
|
2070 |
+
int gc = ((m_crg[cr] + m_cbg[cb]) >> 16);
|
2071 |
+
int bc = m_cbb[cb];
|
2072 |
+
|
2073 |
+
int yy = y[j];
|
2074 |
+
if (jpg_format == ERGBFormatJPG::BGRA)
|
2075 |
+
{
|
2076 |
+
d0[0] = clamp(yy+bc);
|
2077 |
+
d0[1] = clamp(yy+gc);
|
2078 |
+
d0[2] = clamp(yy+rc);
|
2079 |
+
d0[3] = 255;
|
2080 |
+
yy = y[j+1];
|
2081 |
+
d0[4] = clamp(yy+bc);
|
2082 |
+
d0[5] = clamp(yy+gc);
|
2083 |
+
d0[6] = clamp(yy+rc);
|
2084 |
+
d0[7] = 255;
|
2085 |
+
yy = y[j+8];
|
2086 |
+
d1[0] = clamp(yy+bc);
|
2087 |
+
d1[1] = clamp(yy+gc);
|
2088 |
+
d1[2] = clamp(yy+rc);
|
2089 |
+
d1[3] = 255;
|
2090 |
+
yy = y[j+8+1];
|
2091 |
+
d1[4] = clamp(yy+bc);
|
2092 |
+
d1[5] = clamp(yy+gc);
|
2093 |
+
d1[6] = clamp(yy+rc);
|
2094 |
+
d1[7] = 255;
|
2095 |
+
}
|
2096 |
+
else
|
2097 |
+
{
|
2098 |
+
d0[0] = clamp(yy+rc);
|
2099 |
+
d0[1] = clamp(yy+gc);
|
2100 |
+
d0[2] = clamp(yy+bc);
|
2101 |
+
d0[3] = 255;
|
2102 |
+
yy = y[j+1];
|
2103 |
+
d0[4] = clamp(yy+rc);
|
2104 |
+
d0[5] = clamp(yy+gc);
|
2105 |
+
d0[6] = clamp(yy+bc);
|
2106 |
+
d0[7] = 255;
|
2107 |
+
yy = y[j+8];
|
2108 |
+
d1[0] = clamp(yy+rc);
|
2109 |
+
d1[1] = clamp(yy+gc);
|
2110 |
+
d1[2] = clamp(yy+bc);
|
2111 |
+
d1[3] = 255;
|
2112 |
+
yy = y[j+8+1];
|
2113 |
+
d1[4] = clamp(yy+rc);
|
2114 |
+
d1[5] = clamp(yy+gc);
|
2115 |
+
d1[6] = clamp(yy+bc);
|
2116 |
+
d1[7] = 255;
|
2117 |
+
}
|
2118 |
+
|
2119 |
+
d0 += 8;
|
2120 |
+
d1 += 8;
|
2121 |
+
|
2122 |
+
c++;
|
2123 |
+
}
|
2124 |
+
y += 64;
|
2125 |
+
}
|
2126 |
+
|
2127 |
+
y += 64*6 - 64*2;
|
2128 |
+
c += 64*6 - 8;
|
2129 |
+
}
|
2130 |
+
}
|
2131 |
+
|
2132 |
+
// Y (1 block per MCU) to 8-bit grayscale
|
2133 |
+
void jpeg_decoder::gray_convert()
|
2134 |
+
{
|
2135 |
+
int row = m_max_mcu_y_size - m_mcu_lines_left;
|
2136 |
+
uint8 *d = m_pScan_line_0;
|
2137 |
+
uint8 *s = m_pSample_buf + row * 8;
|
2138 |
+
|
2139 |
+
for (int i = m_max_mcus_per_row; i > 0; i--)
|
2140 |
+
{
|
2141 |
+
*(uint *)d = *(uint *)s;
|
2142 |
+
*(uint *)(&d[4]) = *(uint *)(&s[4]);
|
2143 |
+
|
2144 |
+
s += 64;
|
2145 |
+
d += 8;
|
2146 |
+
}
|
2147 |
+
}
|
2148 |
+
|
2149 |
+
void jpeg_decoder::expanded_convert()
|
2150 |
+
{
|
2151 |
+
int row = m_max_mcu_y_size - m_mcu_lines_left;
|
2152 |
+
|
2153 |
+
uint8* Py = m_pSample_buf + (row / 8) * 64 * m_comp_h_samp[0] + (row & 7) * 8;
|
2154 |
+
|
2155 |
+
uint8* d = m_pScan_line_0;
|
2156 |
+
|
2157 |
+
for (int i = m_max_mcus_per_row; i > 0; i--)
|
2158 |
+
{
|
2159 |
+
for (int k = 0; k < m_max_mcu_x_size; k += 8)
|
2160 |
+
{
|
2161 |
+
const int Y_ofs = k * 8;
|
2162 |
+
const int Cb_ofs = Y_ofs + 64 * m_expanded_blocks_per_component;
|
2163 |
+
const int Cr_ofs = Y_ofs + 64 * m_expanded_blocks_per_component * 2;
|
2164 |
+
for (int j = 0; j < 8; j++)
|
2165 |
+
{
|
2166 |
+
int y = Py[Y_ofs + j];
|
2167 |
+
int cb = Py[Cb_ofs + j];
|
2168 |
+
int cr = Py[Cr_ofs + j];
|
2169 |
+
|
2170 |
+
if (jpg_format == ERGBFormatJPG::BGRA)
|
2171 |
+
{
|
2172 |
+
d[0] = clamp(y + m_cbb[cb]);
|
2173 |
+
d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
|
2174 |
+
d[2] = clamp(y + m_crr[cr]);
|
2175 |
+
d[3] = 255;
|
2176 |
+
}
|
2177 |
+
else
|
2178 |
+
{
|
2179 |
+
d[0] = clamp(y + m_crr[cr]);
|
2180 |
+
d[1] = clamp(y + ((m_crg[cr] + m_cbg[cb]) >> 16));
|
2181 |
+
d[2] = clamp(y + m_cbb[cb]);
|
2182 |
+
d[3] = 255;
|
2183 |
+
}
|
2184 |
+
|
2185 |
+
d += 4;
|
2186 |
+
}
|
2187 |
+
}
|
2188 |
+
|
2189 |
+
Py += 64 * m_expanded_blocks_per_mcu;
|
2190 |
+
}
|
2191 |
+
}
|
2192 |
+
|
2193 |
+
// Find end of image (EOI) marker, so we can return to the user the exact size of the input stream.
|
2194 |
+
void jpeg_decoder::find_eoi()
|
2195 |
+
{
|
2196 |
+
if (!m_progressive_flag)
|
2197 |
+
{
|
2198 |
+
// Attempt to read the EOI marker.
|
2199 |
+
//get_bits_no_markers(m_bits_left & 7);
|
2200 |
+
|
2201 |
+
// Prime the bit buffer
|
2202 |
+
m_bits_left = 16;
|
2203 |
+
get_bits(16);
|
2204 |
+
get_bits(16);
|
2205 |
+
|
2206 |
+
// The next marker _should_ be EOI
|
2207 |
+
process_markers();
|
2208 |
+
}
|
2209 |
+
|
2210 |
+
m_total_bytes_read -= m_in_buf_left;
|
2211 |
+
}
|
2212 |
+
|
2213 |
+
int jpeg_decoder::decode(const void** pScan_line, uint* pScan_line_len)
|
2214 |
+
{
|
2215 |
+
if ((m_error_code) || (!m_ready_flag))
|
2216 |
+
return JPGD_FAILED;
|
2217 |
+
|
2218 |
+
if (m_total_lines_left == 0)
|
2219 |
+
return JPGD_DONE;
|
2220 |
+
|
2221 |
+
if (m_mcu_lines_left == 0)
|
2222 |
+
{
|
2223 |
+
if (setjmp(m_jmp_state))
|
2224 |
+
return JPGD_FAILED;
|
2225 |
+
|
2226 |
+
if (m_progressive_flag)
|
2227 |
+
load_next_row();
|
2228 |
+
else
|
2229 |
+
decode_next_row();
|
2230 |
+
|
2231 |
+
// Find the EOI marker if that was the last row.
|
2232 |
+
if (m_total_lines_left <= m_max_mcu_y_size)
|
2233 |
+
find_eoi();
|
2234 |
+
|
2235 |
+
m_mcu_lines_left = m_max_mcu_y_size;
|
2236 |
+
}
|
2237 |
+
|
2238 |
+
if (m_freq_domain_chroma_upsample)
|
2239 |
+
{
|
2240 |
+
expanded_convert();
|
2241 |
+
*pScan_line = m_pScan_line_0;
|
2242 |
+
}
|
2243 |
+
else
|
2244 |
+
{
|
2245 |
+
switch (m_scan_type)
|
2246 |
+
{
|
2247 |
+
case JPGD_YH2V2:
|
2248 |
+
{
|
2249 |
+
if ((m_mcu_lines_left & 1) == 0)
|
2250 |
+
{
|
2251 |
+
H2V2Convert();
|
2252 |
+
*pScan_line = m_pScan_line_0;
|
2253 |
+
}
|
2254 |
+
else
|
2255 |
+
*pScan_line = m_pScan_line_1;
|
2256 |
+
|
2257 |
+
break;
|
2258 |
+
}
|
2259 |
+
case JPGD_YH2V1:
|
2260 |
+
{
|
2261 |
+
H2V1Convert();
|
2262 |
+
*pScan_line = m_pScan_line_0;
|
2263 |
+
break;
|
2264 |
+
}
|
2265 |
+
case JPGD_YH1V2:
|
2266 |
+
{
|
2267 |
+
if ((m_mcu_lines_left & 1) == 0)
|
2268 |
+
{
|
2269 |
+
H1V2Convert();
|
2270 |
+
*pScan_line = m_pScan_line_0;
|
2271 |
+
}
|
2272 |
+
else
|
2273 |
+
*pScan_line = m_pScan_line_1;
|
2274 |
+
|
2275 |
+
break;
|
2276 |
+
}
|
2277 |
+
case JPGD_YH1V1:
|
2278 |
+
{
|
2279 |
+
H1V1Convert();
|
2280 |
+
*pScan_line = m_pScan_line_0;
|
2281 |
+
break;
|
2282 |
+
}
|
2283 |
+
case JPGD_GRAYSCALE:
|
2284 |
+
{
|
2285 |
+
gray_convert();
|
2286 |
+
*pScan_line = m_pScan_line_0;
|
2287 |
+
|
2288 |
+
break;
|
2289 |
+
}
|
2290 |
+
}
|
2291 |
+
}
|
2292 |
+
|
2293 |
+
*pScan_line_len = m_real_dest_bytes_per_scan_line;
|
2294 |
+
|
2295 |
+
m_mcu_lines_left--;
|
2296 |
+
m_total_lines_left--;
|
2297 |
+
|
2298 |
+
return JPGD_SUCCESS;
|
2299 |
+
}
|
2300 |
+
|
2301 |
+
// Creates the tables needed for efficient Huffman decoding.
|
2302 |
+
void jpeg_decoder::make_huff_table(int index, huff_tables *pH)
|
2303 |
+
{
|
2304 |
+
int p, i, l, si;
|
2305 |
+
uint8 huffsize[257];
|
2306 |
+
uint huffcode[257];
|
2307 |
+
uint code;
|
2308 |
+
uint subtree;
|
2309 |
+
int code_size;
|
2310 |
+
int lastp;
|
2311 |
+
int nextfreeentry;
|
2312 |
+
int currententry;
|
2313 |
+
|
2314 |
+
pH->ac_table = m_huff_ac[index] != 0;
|
2315 |
+
|
2316 |
+
p = 0;
|
2317 |
+
|
2318 |
+
for (l = 1; l <= 16; l++)
|
2319 |
+
{
|
2320 |
+
for (i = 1; i <= m_huff_num[index][l]; i++)
|
2321 |
+
huffsize[p++] = static_cast<uint8>(l);
|
2322 |
+
}
|
2323 |
+
|
2324 |
+
huffsize[p] = 0;
|
2325 |
+
|
2326 |
+
lastp = p;
|
2327 |
+
|
2328 |
+
code = 0;
|
2329 |
+
si = huffsize[0];
|
2330 |
+
p = 0;
|
2331 |
+
|
2332 |
+
while (huffsize[p])
|
2333 |
+
{
|
2334 |
+
while (huffsize[p] == si)
|
2335 |
+
{
|
2336 |
+
huffcode[p++] = code;
|
2337 |
+
code++;
|
2338 |
+
}
|
2339 |
+
|
2340 |
+
code <<= 1;
|
2341 |
+
si++;
|
2342 |
+
}
|
2343 |
+
|
2344 |
+
memset(pH->look_up, 0, sizeof(pH->look_up));
|
2345 |
+
memset(pH->look_up2, 0, sizeof(pH->look_up2));
|
2346 |
+
memset(pH->tree, 0, sizeof(pH->tree));
|
2347 |
+
memset(pH->code_size, 0, sizeof(pH->code_size));
|
2348 |
+
|
2349 |
+
nextfreeentry = -1;
|
2350 |
+
|
2351 |
+
p = 0;
|
2352 |
+
|
2353 |
+
while (p < lastp)
|
2354 |
+
{
|
2355 |
+
i = m_huff_val[index][p];
|
2356 |
+
code = huffcode[p];
|
2357 |
+
code_size = huffsize[p];
|
2358 |
+
|
2359 |
+
pH->code_size[i] = static_cast<uint8>(code_size);
|
2360 |
+
|
2361 |
+
if (code_size <= 8)
|
2362 |
+
{
|
2363 |
+
code <<= (8 - code_size);
|
2364 |
+
|
2365 |
+
for (l = 1 << (8 - code_size); l > 0; l--)
|
2366 |
+
{
|
2367 |
+
JPGD_ASSERT(i < 256);
|
2368 |
+
|
2369 |
+
pH->look_up[code] = i;
|
2370 |
+
|
2371 |
+
bool has_extrabits = false;
|
2372 |
+
int extra_bits = 0;
|
2373 |
+
int num_extra_bits = i & 15;
|
2374 |
+
|
2375 |
+
int bits_to_fetch = code_size;
|
2376 |
+
if (num_extra_bits)
|
2377 |
+
{
|
2378 |
+
int total_codesize = code_size + num_extra_bits;
|
2379 |
+
if (total_codesize <= 8)
|
2380 |
+
{
|
2381 |
+
has_extrabits = true;
|
2382 |
+
extra_bits = ((1 << num_extra_bits) - 1) & (code >> (8 - total_codesize));
|
2383 |
+
JPGD_ASSERT(extra_bits <= 0x7FFF);
|
2384 |
+
bits_to_fetch += num_extra_bits;
|
2385 |
+
}
|
2386 |
+
}
|
2387 |
+
|
2388 |
+
if (!has_extrabits)
|
2389 |
+
pH->look_up2[code] = i | (bits_to_fetch << 8);
|
2390 |
+
else
|
2391 |
+
pH->look_up2[code] = i | 0x8000 | (extra_bits << 16) | (bits_to_fetch << 8);
|
2392 |
+
|
2393 |
+
code++;
|
2394 |
+
}
|
2395 |
+
}
|
2396 |
+
else
|
2397 |
+
{
|
2398 |
+
subtree = (code >> (code_size - 8)) & 0xFF;
|
2399 |
+
|
2400 |
+
currententry = pH->look_up[subtree];
|
2401 |
+
|
2402 |
+
if (currententry == 0)
|
2403 |
+
{
|
2404 |
+
pH->look_up[subtree] = currententry = nextfreeentry;
|
2405 |
+
pH->look_up2[subtree] = currententry = nextfreeentry;
|
2406 |
+
|
2407 |
+
nextfreeentry -= 2;
|
2408 |
+
}
|
2409 |
+
|
2410 |
+
code <<= (16 - (code_size - 8));
|
2411 |
+
|
2412 |
+
for (l = code_size; l > 9; l--)
|
2413 |
+
{
|
2414 |
+
if ((code & 0x8000) == 0)
|
2415 |
+
currententry--;
|
2416 |
+
|
2417 |
+
if (pH->tree[-currententry - 1] == 0)
|
2418 |
+
{
|
2419 |
+
pH->tree[-currententry - 1] = nextfreeentry;
|
2420 |
+
|
2421 |
+
currententry = nextfreeentry;
|
2422 |
+
|
2423 |
+
nextfreeentry -= 2;
|
2424 |
+
}
|
2425 |
+
else
|
2426 |
+
currententry = pH->tree[-currententry - 1];
|
2427 |
+
|
2428 |
+
code <<= 1;
|
2429 |
+
}
|
2430 |
+
|
2431 |
+
if ((code & 0x8000) == 0)
|
2432 |
+
currententry--;
|
2433 |
+
|
2434 |
+
pH->tree[-currententry - 1] = i;
|
2435 |
+
}
|
2436 |
+
|
2437 |
+
p++;
|
2438 |
+
}
|
2439 |
+
}
|
2440 |
+
|
2441 |
+
// Verifies the quantization tables needed for this scan are available.
|
2442 |
+
void jpeg_decoder::check_quant_tables()
|
2443 |
+
{
|
2444 |
+
for (int i = 0; i < m_comps_in_scan; i++)
|
2445 |
+
if (m_quant[m_comp_quant[m_comp_list[i]]] == NULL)
|
2446 |
+
stop_decoding(JPGD_UNDEFINED_QUANT_TABLE);
|
2447 |
+
}
|
2448 |
+
|
2449 |
+
// Verifies that all the Huffman tables needed for this scan are available.
|
2450 |
+
void jpeg_decoder::check_huff_tables()
|
2451 |
+
{
|
2452 |
+
for (int i = 0; i < m_comps_in_scan; i++)
|
2453 |
+
{
|
2454 |
+
if ((m_spectral_start == 0) && (m_huff_num[m_comp_dc_tab[m_comp_list[i]]] == NULL))
|
2455 |
+
stop_decoding(JPGD_UNDEFINED_HUFF_TABLE);
|
2456 |
+
|
2457 |
+
if ((m_spectral_end > 0) && (m_huff_num[m_comp_ac_tab[m_comp_list[i]]] == NULL))
|
2458 |
+
stop_decoding(JPGD_UNDEFINED_HUFF_TABLE);
|
2459 |
+
}
|
2460 |
+
|
2461 |
+
for (int i = 0; i < JPGD_MAX_HUFF_TABLES; i++)
|
2462 |
+
if (m_huff_num[i])
|
2463 |
+
{
|
2464 |
+
if (!m_pHuff_tabs[i])
|
2465 |
+
m_pHuff_tabs[i] = (huff_tables *)alloc(sizeof(huff_tables));
|
2466 |
+
|
2467 |
+
make_huff_table(i, m_pHuff_tabs[i]);
|
2468 |
+
}
|
2469 |
+
}
|
2470 |
+
|
2471 |
+
// Determines the component order inside each MCU.
|
2472 |
+
// Also calcs how many MCU's are on each row, etc.
|
2473 |
+
void jpeg_decoder::calc_mcu_block_order()
|
2474 |
+
{
|
2475 |
+
int component_num, component_id;
|
2476 |
+
int max_h_samp = 0, max_v_samp = 0;
|
2477 |
+
|
2478 |
+
for (component_id = 0; component_id < m_comps_in_frame; component_id++)
|
2479 |
+
{
|
2480 |
+
if (m_comp_h_samp[component_id] > max_h_samp)
|
2481 |
+
max_h_samp = m_comp_h_samp[component_id];
|
2482 |
+
|
2483 |
+
if (m_comp_v_samp[component_id] > max_v_samp)
|
2484 |
+
max_v_samp = m_comp_v_samp[component_id];
|
2485 |
+
}
|
2486 |
+
|
2487 |
+
for (component_id = 0; component_id < m_comps_in_frame; component_id++)
|
2488 |
+
{
|
2489 |
+
m_comp_h_blocks[component_id] = ((((m_image_x_size * m_comp_h_samp[component_id]) + (max_h_samp - 1)) / max_h_samp) + 7) / 8;
|
2490 |
+
m_comp_v_blocks[component_id] = ((((m_image_y_size * m_comp_v_samp[component_id]) + (max_v_samp - 1)) / max_v_samp) + 7) / 8;
|
2491 |
+
}
|
2492 |
+
|
2493 |
+
if (m_comps_in_scan == 1)
|
2494 |
+
{
|
2495 |
+
m_mcus_per_row = m_comp_h_blocks[m_comp_list[0]];
|
2496 |
+
m_mcus_per_col = m_comp_v_blocks[m_comp_list[0]];
|
2497 |
+
}
|
2498 |
+
else
|
2499 |
+
{
|
2500 |
+
m_mcus_per_row = (((m_image_x_size + 7) / 8) + (max_h_samp - 1)) / max_h_samp;
|
2501 |
+
m_mcus_per_col = (((m_image_y_size + 7) / 8) + (max_v_samp - 1)) / max_v_samp;
|
2502 |
+
}
|
2503 |
+
|
2504 |
+
if (m_comps_in_scan == 1)
|
2505 |
+
{
|
2506 |
+
m_mcu_org[0] = m_comp_list[0];
|
2507 |
+
|
2508 |
+
m_blocks_per_mcu = 1;
|
2509 |
+
}
|
2510 |
+
else
|
2511 |
+
{
|
2512 |
+
m_blocks_per_mcu = 0;
|
2513 |
+
|
2514 |
+
for (component_num = 0; component_num < m_comps_in_scan; component_num++)
|
2515 |
+
{
|
2516 |
+
int num_blocks;
|
2517 |
+
|
2518 |
+
component_id = m_comp_list[component_num];
|
2519 |
+
|
2520 |
+
num_blocks = m_comp_h_samp[component_id] * m_comp_v_samp[component_id];
|
2521 |
+
|
2522 |
+
while (num_blocks--)
|
2523 |
+
m_mcu_org[m_blocks_per_mcu++] = component_id;
|
2524 |
+
}
|
2525 |
+
}
|
2526 |
+
}
|
2527 |
+
|
2528 |
+
// Starts a new scan.
|
2529 |
+
int jpeg_decoder::init_scan()
|
2530 |
+
{
|
2531 |
+
if (!locate_sos_marker())
|
2532 |
+
return JPGD_FALSE;
|
2533 |
+
|
2534 |
+
calc_mcu_block_order();
|
2535 |
+
|
2536 |
+
check_huff_tables();
|
2537 |
+
|
2538 |
+
check_quant_tables();
|
2539 |
+
|
2540 |
+
memset(m_last_dc_val, 0, m_comps_in_frame * sizeof(uint));
|
2541 |
+
|
2542 |
+
m_eob_run = 0;
|
2543 |
+
|
2544 |
+
if (m_restart_interval)
|
2545 |
+
{
|
2546 |
+
m_restarts_left = m_restart_interval;
|
2547 |
+
m_next_restart_num = 0;
|
2548 |
+
}
|
2549 |
+
|
2550 |
+
fix_in_buffer();
|
2551 |
+
|
2552 |
+
return JPGD_TRUE;
|
2553 |
+
}
|
2554 |
+
|
2555 |
+
// Starts a frame. Determines if the number of components or sampling factors
|
2556 |
+
// are supported.
|
2557 |
+
void jpeg_decoder::init_frame()
|
2558 |
+
{
|
2559 |
+
int i;
|
2560 |
+
|
2561 |
+
if (m_comps_in_frame == 1)
|
2562 |
+
{
|
2563 |
+
if ((m_comp_h_samp[0] != 1) || (m_comp_v_samp[0] != 1))
|
2564 |
+
stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
|
2565 |
+
|
2566 |
+
m_scan_type = JPGD_GRAYSCALE;
|
2567 |
+
m_max_blocks_per_mcu = 1;
|
2568 |
+
m_max_mcu_x_size = 8;
|
2569 |
+
m_max_mcu_y_size = 8;
|
2570 |
+
}
|
2571 |
+
else if (m_comps_in_frame == 3)
|
2572 |
+
{
|
2573 |
+
if ( ((m_comp_h_samp[1] != 1) || (m_comp_v_samp[1] != 1)) ||
|
2574 |
+
((m_comp_h_samp[2] != 1) || (m_comp_v_samp[2] != 1)) )
|
2575 |
+
stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
|
2576 |
+
|
2577 |
+
if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1))
|
2578 |
+
{
|
2579 |
+
m_scan_type = JPGD_YH1V1;
|
2580 |
+
|
2581 |
+
m_max_blocks_per_mcu = 3;
|
2582 |
+
m_max_mcu_x_size = 8;
|
2583 |
+
m_max_mcu_y_size = 8;
|
2584 |
+
}
|
2585 |
+
else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1))
|
2586 |
+
{
|
2587 |
+
m_scan_type = JPGD_YH2V1;
|
2588 |
+
m_max_blocks_per_mcu = 4;
|
2589 |
+
m_max_mcu_x_size = 16;
|
2590 |
+
m_max_mcu_y_size = 8;
|
2591 |
+
}
|
2592 |
+
else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 2))
|
2593 |
+
{
|
2594 |
+
m_scan_type = JPGD_YH1V2;
|
2595 |
+
m_max_blocks_per_mcu = 4;
|
2596 |
+
m_max_mcu_x_size = 8;
|
2597 |
+
m_max_mcu_y_size = 16;
|
2598 |
+
}
|
2599 |
+
else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2))
|
2600 |
+
{
|
2601 |
+
m_scan_type = JPGD_YH2V2;
|
2602 |
+
m_max_blocks_per_mcu = 6;
|
2603 |
+
m_max_mcu_x_size = 16;
|
2604 |
+
m_max_mcu_y_size = 16;
|
2605 |
+
}
|
2606 |
+
else
|
2607 |
+
stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS);
|
2608 |
+
}
|
2609 |
+
else
|
2610 |
+
stop_decoding(JPGD_UNSUPPORTED_COLORSPACE);
|
2611 |
+
|
2612 |
+
m_max_mcus_per_row = (m_image_x_size + (m_max_mcu_x_size - 1)) / m_max_mcu_x_size;
|
2613 |
+
m_max_mcus_per_col = (m_image_y_size + (m_max_mcu_y_size - 1)) / m_max_mcu_y_size;
|
2614 |
+
|
2615 |
+
// These values are for the *destination* pixels: after conversion.
|
2616 |
+
if (m_scan_type == JPGD_GRAYSCALE)
|
2617 |
+
m_dest_bytes_per_pixel = 1;
|
2618 |
+
else
|
2619 |
+
m_dest_bytes_per_pixel = 4;
|
2620 |
+
|
2621 |
+
m_dest_bytes_per_scan_line = ((m_image_x_size + 15) & 0xFFF0) * m_dest_bytes_per_pixel;
|
2622 |
+
|
2623 |
+
m_real_dest_bytes_per_scan_line = (m_image_x_size * m_dest_bytes_per_pixel);
|
2624 |
+
|
2625 |
+
// Initialize two scan line buffers.
|
2626 |
+
m_pScan_line_0 = (uint8 *)alloc(m_dest_bytes_per_scan_line, true);
|
2627 |
+
if ((m_scan_type == JPGD_YH1V2) || (m_scan_type == JPGD_YH2V2))
|
2628 |
+
m_pScan_line_1 = (uint8 *)alloc(m_dest_bytes_per_scan_line, true);
|
2629 |
+
|
2630 |
+
m_max_blocks_per_row = m_max_mcus_per_row * m_max_blocks_per_mcu;
|
2631 |
+
|
2632 |
+
// Should never happen
|
2633 |
+
if (m_max_blocks_per_row > JPGD_MAX_BLOCKS_PER_ROW)
|
2634 |
+
stop_decoding(JPGD_ASSERTION_ERROR);
|
2635 |
+
|
2636 |
+
// Allocate the coefficient buffer, enough for one MCU
|
2637 |
+
m_pMCU_coefficients = (jpgd_block_t*)alloc(m_max_blocks_per_mcu * 64 * sizeof(jpgd_block_t));
|
2638 |
+
|
2639 |
+
for (i = 0; i < m_max_blocks_per_mcu; i++)
|
2640 |
+
m_mcu_block_max_zag[i] = 64;
|
2641 |
+
|
2642 |
+
m_expanded_blocks_per_component = m_comp_h_samp[0] * m_comp_v_samp[0];
|
2643 |
+
m_expanded_blocks_per_mcu = m_expanded_blocks_per_component * m_comps_in_frame;
|
2644 |
+
m_expanded_blocks_per_row = m_max_mcus_per_row * m_expanded_blocks_per_mcu;
|
2645 |
+
// Freq. domain chroma upsampling is only supported for H2V2 subsampling factor.
|
2646 |
+
// BEGIN EPIC MOD
|
2647 |
+
#if JPGD_SUPPORT_FREQ_DOMAIN_UPSAMPLING
|
2648 |
+
m_freq_domain_chroma_upsample = (m_expanded_blocks_per_mcu == 4*3);
|
2649 |
+
#else
|
2650 |
+
m_freq_domain_chroma_upsample = 0;
|
2651 |
+
#endif
|
2652 |
+
// END EPIC MOD
|
2653 |
+
|
2654 |
+
if (m_freq_domain_chroma_upsample)
|
2655 |
+
m_pSample_buf = (uint8 *)alloc(m_expanded_blocks_per_row * 64);
|
2656 |
+
else
|
2657 |
+
m_pSample_buf = (uint8 *)alloc(m_max_blocks_per_row * 64);
|
2658 |
+
|
2659 |
+
m_total_lines_left = m_image_y_size;
|
2660 |
+
|
2661 |
+
m_mcu_lines_left = 0;
|
2662 |
+
|
2663 |
+
create_look_ups();
|
2664 |
+
}
|
2665 |
+
|
2666 |
+
// The coeff_buf series of methods originally stored the coefficients
|
2667 |
+
// into a "virtual" file which was located in EMS, XMS, or a disk file. A cache
|
2668 |
+
// was used to make this process more efficient. Now, we can store the entire
|
2669 |
+
// thing in RAM.
|
2670 |
+
jpeg_decoder::coeff_buf* jpeg_decoder::coeff_buf_open(int block_num_x, int block_num_y, int block_len_x, int block_len_y)
|
2671 |
+
{
|
2672 |
+
coeff_buf* cb = (coeff_buf*)alloc(sizeof(coeff_buf));
|
2673 |
+
|
2674 |
+
cb->block_num_x = block_num_x;
|
2675 |
+
cb->block_num_y = block_num_y;
|
2676 |
+
cb->block_len_x = block_len_x;
|
2677 |
+
cb->block_len_y = block_len_y;
|
2678 |
+
cb->block_size = (block_len_x * block_len_y) * sizeof(jpgd_block_t);
|
2679 |
+
cb->pData = (uint8 *)alloc(cb->block_size * block_num_x * block_num_y, true);
|
2680 |
+
return cb;
|
2681 |
+
}
|
2682 |
+
|
2683 |
+
inline jpgd_block_t *jpeg_decoder::coeff_buf_getp(coeff_buf *cb, int block_x, int block_y)
|
2684 |
+
{
|
2685 |
+
JPGD_ASSERT((block_x < cb->block_num_x) && (block_y < cb->block_num_y));
|
2686 |
+
return (jpgd_block_t *)(cb->pData + block_x * cb->block_size + block_y * (cb->block_size * cb->block_num_x));
|
2687 |
+
}
|
2688 |
+
|
2689 |
+
// The following methods decode the various types of m_blocks encountered
|
2690 |
+
// in progressively encoded images.
|
2691 |
+
void jpeg_decoder::decode_block_dc_first(jpeg_decoder *pD, int component_id, int block_x, int block_y)
|
2692 |
+
{
|
2693 |
+
int s, r;
|
2694 |
+
jpgd_block_t *p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y);
|
2695 |
+
|
2696 |
+
if ((s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_dc_tab[component_id]])) != 0)
|
2697 |
+
{
|
2698 |
+
r = pD->get_bits_no_markers(s);
|
2699 |
+
s = HUFF_EXTEND(r, s);
|
2700 |
+
}
|
2701 |
+
|
2702 |
+
pD->m_last_dc_val[component_id] = (s += pD->m_last_dc_val[component_id]);
|
2703 |
+
|
2704 |
+
p[0] = static_cast<jpgd_block_t>(s << pD->m_successive_low);
|
2705 |
+
}
|
2706 |
+
|
2707 |
+
void jpeg_decoder::decode_block_dc_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y)
|
2708 |
+
{
|
2709 |
+
if (pD->get_bits_no_markers(1))
|
2710 |
+
{
|
2711 |
+
jpgd_block_t *p = pD->coeff_buf_getp(pD->m_dc_coeffs[component_id], block_x, block_y);
|
2712 |
+
|
2713 |
+
p[0] |= (1 << pD->m_successive_low);
|
2714 |
+
}
|
2715 |
+
}
|
2716 |
+
|
2717 |
+
void jpeg_decoder::decode_block_ac_first(jpeg_decoder *pD, int component_id, int block_x, int block_y)
|
2718 |
+
{
|
2719 |
+
int k, s, r;
|
2720 |
+
|
2721 |
+
if (pD->m_eob_run)
|
2722 |
+
{
|
2723 |
+
pD->m_eob_run--;
|
2724 |
+
return;
|
2725 |
+
}
|
2726 |
+
|
2727 |
+
jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
|
2728 |
+
|
2729 |
+
for (k = pD->m_spectral_start; k <= pD->m_spectral_end; k++)
|
2730 |
+
{
|
2731 |
+
s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]);
|
2732 |
+
|
2733 |
+
r = s >> 4;
|
2734 |
+
s &= 15;
|
2735 |
+
|
2736 |
+
if (s)
|
2737 |
+
{
|
2738 |
+
if ((k += r) > 63)
|
2739 |
+
pD->stop_decoding(JPGD_DECODE_ERROR);
|
2740 |
+
|
2741 |
+
r = pD->get_bits_no_markers(s);
|
2742 |
+
s = HUFF_EXTEND(r, s);
|
2743 |
+
|
2744 |
+
p[g_ZAG[k]] = static_cast<jpgd_block_t>(s << pD->m_successive_low);
|
2745 |
+
}
|
2746 |
+
else
|
2747 |
+
{
|
2748 |
+
if (r == 15)
|
2749 |
+
{
|
2750 |
+
if ((k += 15) > 63)
|
2751 |
+
pD->stop_decoding(JPGD_DECODE_ERROR);
|
2752 |
+
}
|
2753 |
+
else
|
2754 |
+
{
|
2755 |
+
pD->m_eob_run = 1 << r;
|
2756 |
+
|
2757 |
+
if (r)
|
2758 |
+
pD->m_eob_run += pD->get_bits_no_markers(r);
|
2759 |
+
|
2760 |
+
pD->m_eob_run--;
|
2761 |
+
|
2762 |
+
break;
|
2763 |
+
}
|
2764 |
+
}
|
2765 |
+
}
|
2766 |
+
}
|
2767 |
+
|
2768 |
+
void jpeg_decoder::decode_block_ac_refine(jpeg_decoder *pD, int component_id, int block_x, int block_y)
|
2769 |
+
{
|
2770 |
+
int s, k, r;
|
2771 |
+
int p1 = 1 << pD->m_successive_low;
|
2772 |
+
int m1 = (-1) << pD->m_successive_low;
|
2773 |
+
jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
|
2774 |
+
|
2775 |
+
k = pD->m_spectral_start;
|
2776 |
+
|
2777 |
+
if (pD->m_eob_run == 0)
|
2778 |
+
{
|
2779 |
+
for ( ; k <= pD->m_spectral_end; k++)
|
2780 |
+
{
|
2781 |
+
s = pD->huff_decode(pD->m_pHuff_tabs[pD->m_comp_ac_tab[component_id]]);
|
2782 |
+
|
2783 |
+
r = s >> 4;
|
2784 |
+
s &= 15;
|
2785 |
+
|
2786 |
+
if (s)
|
2787 |
+
{
|
2788 |
+
if (s != 1)
|
2789 |
+
pD->stop_decoding(JPGD_DECODE_ERROR);
|
2790 |
+
|
2791 |
+
if (pD->get_bits_no_markers(1))
|
2792 |
+
s = p1;
|
2793 |
+
else
|
2794 |
+
s = m1;
|
2795 |
+
}
|
2796 |
+
else
|
2797 |
+
{
|
2798 |
+
if (r != 15)
|
2799 |
+
{
|
2800 |
+
pD->m_eob_run = 1 << r;
|
2801 |
+
|
2802 |
+
if (r)
|
2803 |
+
pD->m_eob_run += pD->get_bits_no_markers(r);
|
2804 |
+
|
2805 |
+
break;
|
2806 |
+
}
|
2807 |
+
}
|
2808 |
+
|
2809 |
+
do
|
2810 |
+
{
|
2811 |
+
// BEGIN EPIC MOD
|
2812 |
+
JPGD_ASSERT(k < 64);
|
2813 |
+
// END EPIC MOD
|
2814 |
+
|
2815 |
+
jpgd_block_t *this_coef = p + g_ZAG[k];
|
2816 |
+
|
2817 |
+
if (*this_coef != 0)
|
2818 |
+
{
|
2819 |
+
if (pD->get_bits_no_markers(1))
|
2820 |
+
{
|
2821 |
+
if ((*this_coef & p1) == 0)
|
2822 |
+
{
|
2823 |
+
if (*this_coef >= 0)
|
2824 |
+
*this_coef = static_cast<jpgd_block_t>(*this_coef + p1);
|
2825 |
+
else
|
2826 |
+
*this_coef = static_cast<jpgd_block_t>(*this_coef + m1);
|
2827 |
+
}
|
2828 |
+
}
|
2829 |
+
}
|
2830 |
+
else
|
2831 |
+
{
|
2832 |
+
if (--r < 0)
|
2833 |
+
break;
|
2834 |
+
}
|
2835 |
+
|
2836 |
+
k++;
|
2837 |
+
|
2838 |
+
} while (k <= pD->m_spectral_end);
|
2839 |
+
|
2840 |
+
if ((s) && (k < 64))
|
2841 |
+
{
|
2842 |
+
p[g_ZAG[k]] = static_cast<jpgd_block_t>(s);
|
2843 |
+
}
|
2844 |
+
}
|
2845 |
+
}
|
2846 |
+
|
2847 |
+
if (pD->m_eob_run > 0)
|
2848 |
+
{
|
2849 |
+
for ( ; k <= pD->m_spectral_end; k++)
|
2850 |
+
{
|
2851 |
+
// BEGIN EPIC MOD
|
2852 |
+
JPGD_ASSERT(k < 64);
|
2853 |
+
// END EPIC MOD
|
2854 |
+
|
2855 |
+
jpgd_block_t *this_coef = p + g_ZAG[k];
|
2856 |
+
|
2857 |
+
if (*this_coef != 0)
|
2858 |
+
{
|
2859 |
+
if (pD->get_bits_no_markers(1))
|
2860 |
+
{
|
2861 |
+
if ((*this_coef & p1) == 0)
|
2862 |
+
{
|
2863 |
+
if (*this_coef >= 0)
|
2864 |
+
*this_coef = static_cast<jpgd_block_t>(*this_coef + p1);
|
2865 |
+
else
|
2866 |
+
*this_coef = static_cast<jpgd_block_t>(*this_coef + m1);
|
2867 |
+
}
|
2868 |
+
}
|
2869 |
+
}
|
2870 |
+
}
|
2871 |
+
|
2872 |
+
pD->m_eob_run--;
|
2873 |
+
}
|
2874 |
+
}
|
2875 |
+
|
2876 |
+
// Decode a scan in a progressively encoded image.
|
2877 |
+
void jpeg_decoder::decode_scan(pDecode_block_func decode_block_func)
|
2878 |
+
{
|
2879 |
+
int mcu_row, mcu_col, mcu_block;
|
2880 |
+
int block_x_mcu[JPGD_MAX_COMPONENTS], m_block_y_mcu[JPGD_MAX_COMPONENTS];
|
2881 |
+
|
2882 |
+
memset(m_block_y_mcu, 0, sizeof(m_block_y_mcu));
|
2883 |
+
|
2884 |
+
for (mcu_col = 0; mcu_col < m_mcus_per_col; mcu_col++)
|
2885 |
+
{
|
2886 |
+
int component_num, component_id;
|
2887 |
+
|
2888 |
+
memset(block_x_mcu, 0, sizeof(block_x_mcu));
|
2889 |
+
|
2890 |
+
for (mcu_row = 0; mcu_row < m_mcus_per_row; mcu_row++)
|
2891 |
+
{
|
2892 |
+
int block_x_mcu_ofs = 0, block_y_mcu_ofs = 0;
|
2893 |
+
|
2894 |
+
if ((m_restart_interval) && (m_restarts_left == 0))
|
2895 |
+
process_restart();
|
2896 |
+
|
2897 |
+
for (mcu_block = 0; mcu_block < m_blocks_per_mcu; mcu_block++)
|
2898 |
+
{
|
2899 |
+
component_id = m_mcu_org[mcu_block];
|
2900 |
+
|
2901 |
+
decode_block_func(this, component_id, block_x_mcu[component_id] + block_x_mcu_ofs, m_block_y_mcu[component_id] + block_y_mcu_ofs);
|
2902 |
+
|
2903 |
+
if (m_comps_in_scan == 1)
|
2904 |
+
block_x_mcu[component_id]++;
|
2905 |
+
else
|
2906 |
+
{
|
2907 |
+
if (++block_x_mcu_ofs == m_comp_h_samp[component_id])
|
2908 |
+
{
|
2909 |
+
block_x_mcu_ofs = 0;
|
2910 |
+
|
2911 |
+
if (++block_y_mcu_ofs == m_comp_v_samp[component_id])
|
2912 |
+
{
|
2913 |
+
block_y_mcu_ofs = 0;
|
2914 |
+
block_x_mcu[component_id] += m_comp_h_samp[component_id];
|
2915 |
+
}
|
2916 |
+
}
|
2917 |
+
}
|
2918 |
+
}
|
2919 |
+
|
2920 |
+
m_restarts_left--;
|
2921 |
+
}
|
2922 |
+
|
2923 |
+
if (m_comps_in_scan == 1)
|
2924 |
+
m_block_y_mcu[m_comp_list[0]]++;
|
2925 |
+
else
|
2926 |
+
{
|
2927 |
+
for (component_num = 0; component_num < m_comps_in_scan; component_num++)
|
2928 |
+
{
|
2929 |
+
component_id = m_comp_list[component_num];
|
2930 |
+
m_block_y_mcu[component_id] += m_comp_v_samp[component_id];
|
2931 |
+
}
|
2932 |
+
}
|
2933 |
+
}
|
2934 |
+
}
|
2935 |
+
|
2936 |
+
// Decode a progressively encoded image.
|
2937 |
+
void jpeg_decoder::init_progressive()
|
2938 |
+
{
|
2939 |
+
int i;
|
2940 |
+
|
2941 |
+
if (m_comps_in_frame == 4)
|
2942 |
+
stop_decoding(JPGD_UNSUPPORTED_COLORSPACE);
|
2943 |
+
|
2944 |
+
// Allocate the coefficient buffers.
|
2945 |
+
for (i = 0; i < m_comps_in_frame; i++)
|
2946 |
+
{
|
2947 |
+
m_dc_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 1, 1);
|
2948 |
+
m_ac_coeffs[i] = coeff_buf_open(m_max_mcus_per_row * m_comp_h_samp[i], m_max_mcus_per_col * m_comp_v_samp[i], 8, 8);
|
2949 |
+
}
|
2950 |
+
|
2951 |
+
for ( ; ; )
|
2952 |
+
{
|
2953 |
+
int dc_only_scan, refinement_scan;
|
2954 |
+
pDecode_block_func decode_block_func;
|
2955 |
+
|
2956 |
+
if (!init_scan())
|
2957 |
+
break;
|
2958 |
+
|
2959 |
+
dc_only_scan = (m_spectral_start == 0);
|
2960 |
+
refinement_scan = (m_successive_high != 0);
|
2961 |
+
|
2962 |
+
if ((m_spectral_start > m_spectral_end) || (m_spectral_end > 63))
|
2963 |
+
stop_decoding(JPGD_BAD_SOS_SPECTRAL);
|
2964 |
+
|
2965 |
+
if (dc_only_scan)
|
2966 |
+
{
|
2967 |
+
if (m_spectral_end)
|
2968 |
+
stop_decoding(JPGD_BAD_SOS_SPECTRAL);
|
2969 |
+
}
|
2970 |
+
else if (m_comps_in_scan != 1) /* AC scans can only contain one component */
|
2971 |
+
stop_decoding(JPGD_BAD_SOS_SPECTRAL);
|
2972 |
+
|
2973 |
+
if ((refinement_scan) && (m_successive_low != m_successive_high - 1))
|
2974 |
+
stop_decoding(JPGD_BAD_SOS_SUCCESSIVE);
|
2975 |
+
|
2976 |
+
if (dc_only_scan)
|
2977 |
+
{
|
2978 |
+
if (refinement_scan)
|
2979 |
+
decode_block_func = decode_block_dc_refine;
|
2980 |
+
else
|
2981 |
+
decode_block_func = decode_block_dc_first;
|
2982 |
+
}
|
2983 |
+
else
|
2984 |
+
{
|
2985 |
+
if (refinement_scan)
|
2986 |
+
decode_block_func = decode_block_ac_refine;
|
2987 |
+
else
|
2988 |
+
decode_block_func = decode_block_ac_first;
|
2989 |
+
}
|
2990 |
+
|
2991 |
+
decode_scan(decode_block_func);
|
2992 |
+
|
2993 |
+
m_bits_left = 16;
|
2994 |
+
get_bits(16);
|
2995 |
+
get_bits(16);
|
2996 |
+
}
|
2997 |
+
|
2998 |
+
m_comps_in_scan = m_comps_in_frame;
|
2999 |
+
|
3000 |
+
for (i = 0; i < m_comps_in_frame; i++)
|
3001 |
+
m_comp_list[i] = i;
|
3002 |
+
|
3003 |
+
calc_mcu_block_order();
|
3004 |
+
}
|
3005 |
+
|
3006 |
+
void jpeg_decoder::init_sequential()
|
3007 |
+
{
|
3008 |
+
if (!init_scan())
|
3009 |
+
stop_decoding(JPGD_UNEXPECTED_MARKER);
|
3010 |
+
}
|
3011 |
+
|
3012 |
+
void jpeg_decoder::decode_start()
|
3013 |
+
{
|
3014 |
+
init_frame();
|
3015 |
+
|
3016 |
+
if (m_progressive_flag)
|
3017 |
+
init_progressive();
|
3018 |
+
else
|
3019 |
+
init_sequential();
|
3020 |
+
}
|
3021 |
+
|
3022 |
+
void jpeg_decoder::decode_init(jpeg_decoder_stream *pStream)
|
3023 |
+
{
|
3024 |
+
init(pStream);
|
3025 |
+
locate_sof_marker();
|
3026 |
+
}
|
3027 |
+
|
3028 |
+
jpeg_decoder::jpeg_decoder(jpeg_decoder_stream *pStream)
|
3029 |
+
{
|
3030 |
+
if (setjmp(m_jmp_state))
|
3031 |
+
return;
|
3032 |
+
decode_init(pStream);
|
3033 |
+
}
|
3034 |
+
|
3035 |
+
int jpeg_decoder::begin_decoding()
|
3036 |
+
{
|
3037 |
+
if (m_ready_flag)
|
3038 |
+
return JPGD_SUCCESS;
|
3039 |
+
|
3040 |
+
if (m_error_code)
|
3041 |
+
return JPGD_FAILED;
|
3042 |
+
|
3043 |
+
if (setjmp(m_jmp_state))
|
3044 |
+
return JPGD_FAILED;
|
3045 |
+
|
3046 |
+
decode_start();
|
3047 |
+
|
3048 |
+
m_ready_flag = true;
|
3049 |
+
|
3050 |
+
return JPGD_SUCCESS;
|
3051 |
+
}
|
3052 |
+
|
3053 |
+
jpeg_decoder::~jpeg_decoder()
|
3054 |
+
{
|
3055 |
+
free_all_blocks();
|
3056 |
+
}
|
3057 |
+
|
3058 |
+
jpeg_decoder_file_stream::jpeg_decoder_file_stream()
|
3059 |
+
{
|
3060 |
+
m_pFile = NULL;
|
3061 |
+
m_eof_flag = false;
|
3062 |
+
m_error_flag = false;
|
3063 |
+
}
|
3064 |
+
|
3065 |
+
void jpeg_decoder_file_stream::close()
|
3066 |
+
{
|
3067 |
+
if (m_pFile)
|
3068 |
+
{
|
3069 |
+
fclose(m_pFile);
|
3070 |
+
m_pFile = NULL;
|
3071 |
+
}
|
3072 |
+
|
3073 |
+
m_eof_flag = false;
|
3074 |
+
m_error_flag = false;
|
3075 |
+
}
|
3076 |
+
|
3077 |
+
jpeg_decoder_file_stream::~jpeg_decoder_file_stream()
|
3078 |
+
{
|
3079 |
+
close();
|
3080 |
+
}
|
3081 |
+
|
3082 |
+
bool jpeg_decoder_file_stream::open(const char *Pfilename)
|
3083 |
+
{
|
3084 |
+
close();
|
3085 |
+
|
3086 |
+
m_eof_flag = false;
|
3087 |
+
m_error_flag = false;
|
3088 |
+
|
3089 |
+
#if defined(_MSC_VER)
|
3090 |
+
m_pFile = NULL;
|
3091 |
+
fopen_s(&m_pFile, Pfilename, "rb");
|
3092 |
+
#else
|
3093 |
+
m_pFile = fopen(Pfilename, "rb");
|
3094 |
+
#endif
|
3095 |
+
return m_pFile != NULL;
|
3096 |
+
}
|
3097 |
+
|
3098 |
+
int jpeg_decoder_file_stream::read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag)
|
3099 |
+
{
|
3100 |
+
if (!m_pFile)
|
3101 |
+
return -1;
|
3102 |
+
|
3103 |
+
if (m_eof_flag)
|
3104 |
+
{
|
3105 |
+
*pEOF_flag = true;
|
3106 |
+
return 0;
|
3107 |
+
}
|
3108 |
+
|
3109 |
+
if (m_error_flag)
|
3110 |
+
return -1;
|
3111 |
+
|
3112 |
+
int bytes_read = static_cast<int>(fread(pBuf, 1, max_bytes_to_read, m_pFile));
|
3113 |
+
if (bytes_read < max_bytes_to_read)
|
3114 |
+
{
|
3115 |
+
if (ferror(m_pFile))
|
3116 |
+
{
|
3117 |
+
m_error_flag = true;
|
3118 |
+
return -1;
|
3119 |
+
}
|
3120 |
+
|
3121 |
+
m_eof_flag = true;
|
3122 |
+
*pEOF_flag = true;
|
3123 |
+
}
|
3124 |
+
|
3125 |
+
return bytes_read;
|
3126 |
+
}
|
3127 |
+
|
3128 |
+
bool jpeg_decoder_mem_stream::open(const uint8 *pSrc_data, uint size)
|
3129 |
+
{
|
3130 |
+
close();
|
3131 |
+
m_pSrc_data = pSrc_data;
|
3132 |
+
m_ofs = 0;
|
3133 |
+
m_size = size;
|
3134 |
+
return true;
|
3135 |
+
}
|
3136 |
+
|
3137 |
+
int jpeg_decoder_mem_stream::read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag)
|
3138 |
+
{
|
3139 |
+
*pEOF_flag = false;
|
3140 |
+
|
3141 |
+
if (!m_pSrc_data)
|
3142 |
+
return -1;
|
3143 |
+
|
3144 |
+
uint bytes_remaining = m_size - m_ofs;
|
3145 |
+
if ((uint)max_bytes_to_read > bytes_remaining)
|
3146 |
+
{
|
3147 |
+
max_bytes_to_read = bytes_remaining;
|
3148 |
+
*pEOF_flag = true;
|
3149 |
+
}
|
3150 |
+
|
3151 |
+
memcpy(pBuf, m_pSrc_data + m_ofs, max_bytes_to_read);
|
3152 |
+
m_ofs += max_bytes_to_read;
|
3153 |
+
|
3154 |
+
return max_bytes_to_read;
|
3155 |
+
}
|
3156 |
+
|
3157 |
+
unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream, int *width, int *height, int *actual_comps, int req_comps)
|
3158 |
+
{
|
3159 |
+
if (!actual_comps)
|
3160 |
+
return NULL;
|
3161 |
+
*actual_comps = 0;
|
3162 |
+
|
3163 |
+
if ((!pStream) || (!width) || (!height) || (!req_comps))
|
3164 |
+
return NULL;
|
3165 |
+
|
3166 |
+
if ((req_comps != 1) && (req_comps != 3) && (req_comps != 4))
|
3167 |
+
return NULL;
|
3168 |
+
|
3169 |
+
jpeg_decoder decoder(pStream);
|
3170 |
+
if (decoder.get_error_code() != JPGD_SUCCESS)
|
3171 |
+
return NULL;
|
3172 |
+
|
3173 |
+
const int image_width = decoder.get_width(), image_height = decoder.get_height();
|
3174 |
+
*width = image_width;
|
3175 |
+
*height = image_height;
|
3176 |
+
*actual_comps = decoder.get_num_components();
|
3177 |
+
|
3178 |
+
if (decoder.begin_decoding() != JPGD_SUCCESS)
|
3179 |
+
return NULL;
|
3180 |
+
|
3181 |
+
const int dst_bpl = image_width * req_comps;
|
3182 |
+
|
3183 |
+
uint8 *pImage_data = (uint8*)jpgd_malloc(dst_bpl * image_height);
|
3184 |
+
if (!pImage_data)
|
3185 |
+
return NULL;
|
3186 |
+
|
3187 |
+
for (int y = 0; y < image_height; y++)
|
3188 |
+
{
|
3189 |
+
const uint8* pScan_line = 0;
|
3190 |
+
uint scan_line_len;
|
3191 |
+
if (decoder.decode((const void**)&pScan_line, &scan_line_len) != JPGD_SUCCESS)
|
3192 |
+
{
|
3193 |
+
jpgd_free(pImage_data);
|
3194 |
+
return NULL;
|
3195 |
+
}
|
3196 |
+
|
3197 |
+
uint8 *pDst = pImage_data + y * dst_bpl;
|
3198 |
+
|
3199 |
+
if (((req_comps == 4) && (decoder.get_num_components() == 3)) ||
|
3200 |
+
((req_comps == 1) && (decoder.get_num_components() == 1)))
|
3201 |
+
{
|
3202 |
+
memcpy(pDst, pScan_line, dst_bpl);
|
3203 |
+
}
|
3204 |
+
else if (decoder.get_num_components() == 1)
|
3205 |
+
{
|
3206 |
+
if (req_comps == 3)
|
3207 |
+
{
|
3208 |
+
for (int x = 0; x < image_width; x++)
|
3209 |
+
{
|
3210 |
+
uint8 luma = pScan_line[x];
|
3211 |
+
pDst[0] = luma;
|
3212 |
+
pDst[1] = luma;
|
3213 |
+
pDst[2] = luma;
|
3214 |
+
pDst += 3;
|
3215 |
+
}
|
3216 |
+
}
|
3217 |
+
else
|
3218 |
+
{
|
3219 |
+
for (int x = 0; x < image_width; x++)
|
3220 |
+
{
|
3221 |
+
uint8 luma = pScan_line[x];
|
3222 |
+
pDst[0] = luma;
|
3223 |
+
pDst[1] = luma;
|
3224 |
+
pDst[2] = luma;
|
3225 |
+
pDst[3] = 255;
|
3226 |
+
pDst += 4;
|
3227 |
+
}
|
3228 |
+
}
|
3229 |
+
}
|
3230 |
+
else if (decoder.get_num_components() == 3)
|
3231 |
+
{
|
3232 |
+
if (req_comps == 1)
|
3233 |
+
{
|
3234 |
+
const int YR = 19595, YG = 38470, YB = 7471;
|
3235 |
+
for (int x = 0; x < image_width; x++)
|
3236 |
+
{
|
3237 |
+
int r = pScan_line[x*4+0];
|
3238 |
+
int g = pScan_line[x*4+1];
|
3239 |
+
int b = pScan_line[x*4+2];
|
3240 |
+
*pDst++ = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
|
3241 |
+
}
|
3242 |
+
}
|
3243 |
+
else
|
3244 |
+
{
|
3245 |
+
for (int x = 0; x < image_width; x++)
|
3246 |
+
{
|
3247 |
+
pDst[0] = pScan_line[x*4+0];
|
3248 |
+
pDst[1] = pScan_line[x*4+1];
|
3249 |
+
pDst[2] = pScan_line[x*4+2];
|
3250 |
+
pDst += 3;
|
3251 |
+
}
|
3252 |
+
}
|
3253 |
+
}
|
3254 |
+
}
|
3255 |
+
|
3256 |
+
return pImage_data;
|
3257 |
+
}
|
3258 |
+
|
3259 |
+
// BEGIN EPIC MOD
|
3260 |
+
unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data, int src_data_size, int *width, int *height, int *actual_comps, int req_comps, int format)
|
3261 |
+
{
|
3262 |
+
jpg_format = (ERGBFormatJPG)format;
|
3263 |
+
// EMD EPIC MOD
|
3264 |
+
jpgd::jpeg_decoder_mem_stream mem_stream(pSrc_data, src_data_size);
|
3265 |
+
return decompress_jpeg_image_from_stream(&mem_stream, width, height, actual_comps, req_comps);
|
3266 |
+
}
|
3267 |
+
|
3268 |
+
unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename, int *width, int *height, int *actual_comps, int req_comps)
|
3269 |
+
{
|
3270 |
+
jpgd::jpeg_decoder_file_stream file_stream;
|
3271 |
+
if (!file_stream.open(pSrc_filename))
|
3272 |
+
return NULL;
|
3273 |
+
return decompress_jpeg_image_from_stream(&file_stream, width, height, actual_comps, req_comps);
|
3274 |
+
}
|
3275 |
+
|
3276 |
+
} // namespace jpgd
|
crazy_functions/test_project/cpp/longcode/jpge.cpp
ADDED
@@ -0,0 +1,1049 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// jpge.cpp - C++ class for JPEG compression.
|
2 |
+
// Public domain, Rich Geldreich <[email protected]>
|
3 |
+
// v1.01, Dec. 18, 2010 - Initial release
|
4 |
+
// v1.02, Apr. 6, 2011 - Removed 2x2 ordered dither in H2V1 chroma subsampling method load_block_16_8_8(). (The rounding factor was 2, when it should have been 1. Either way, it wasn't helping.)
|
5 |
+
// v1.03, Apr. 16, 2011 - Added support for optimized Huffman code tables, optimized dynamic memory allocation down to only 1 alloc.
|
6 |
+
// Also from Alex Evans: Added RGBA support, linear memory allocator (no longer needed in v1.03).
|
7 |
+
// v1.04, May. 19, 2012: Forgot to set m_pFile ptr to NULL in cfile_stream::close(). Thanks to Owen Kaluza for reporting this bug.
|
8 |
+
// Code tweaks to fix VS2008 static code analysis warnings (all looked harmless).
|
9 |
+
// Code review revealed method load_block_16_8_8() (used for the non-default H2V1 sampling mode to downsample chroma) somehow didn't get the rounding factor fix from v1.02.
|
10 |
+
|
11 |
+
#include "jpge.h"
|
12 |
+
|
13 |
+
#include <stdlib.h>
|
14 |
+
#include <string.h>
|
15 |
+
#if PLATFORM_WINDOWS
|
16 |
+
#include <malloc.h>
|
17 |
+
#endif
|
18 |
+
|
19 |
+
#define JPGE_MAX(a,b) (((a)>(b))?(a):(b))
|
20 |
+
#define JPGE_MIN(a,b) (((a)<(b))?(a):(b))
|
21 |
+
|
22 |
+
namespace jpge {
|
23 |
+
|
24 |
+
static inline void *jpge_malloc(size_t nSize) { return FMemory::Malloc(nSize); }
|
25 |
+
static inline void jpge_free(void *p) { FMemory::Free(p);; }
|
26 |
+
|
27 |
+
// Various JPEG enums and tables.
|
28 |
+
enum { M_SOF0 = 0xC0, M_DHT = 0xC4, M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_APP0 = 0xE0 };
|
29 |
+
enum { DC_LUM_CODES = 12, AC_LUM_CODES = 256, DC_CHROMA_CODES = 12, AC_CHROMA_CODES = 256, MAX_HUFF_SYMBOLS = 257, MAX_HUFF_CODESIZE = 32 };
|
30 |
+
|
31 |
+
static uint8 s_zag[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 };
|
32 |
+
static int16 s_std_lum_quant[64] = { 16,11,12,14,12,10,16,14,13,14,18,17,16,19,24,40,26,24,22,22,24,49,35,37,29,40,58,51,61,60,57,51,56,55,64,72,92,78,64,68,87,69,55,56,80,109,81,87,95,98,103,104,103,62,77,113,121,112,100,120,92,101,103,99 };
|
33 |
+
static int16 s_std_croma_quant[64] = { 17,18,18,24,21,24,47,26,26,47,99,66,56,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99 };
|
34 |
+
static uint8 s_dc_lum_bits[17] = { 0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0 };
|
35 |
+
static uint8 s_dc_lum_val[DC_LUM_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 };
|
36 |
+
static uint8 s_ac_lum_bits[17] = { 0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d };
|
37 |
+
static uint8 s_ac_lum_val[AC_LUM_CODES] =
|
38 |
+
{
|
39 |
+
0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,
|
40 |
+
0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
|
41 |
+
0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
|
42 |
+
0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,
|
43 |
+
0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
|
44 |
+
0xf9,0xfa
|
45 |
+
};
|
46 |
+
static uint8 s_dc_chroma_bits[17] = { 0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0 };
|
47 |
+
static uint8 s_dc_chroma_val[DC_CHROMA_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 };
|
48 |
+
static uint8 s_ac_chroma_bits[17] = { 0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77 };
|
49 |
+
static uint8 s_ac_chroma_val[AC_CHROMA_CODES] =
|
50 |
+
{
|
51 |
+
0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
|
52 |
+
0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,
|
53 |
+
0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
|
54 |
+
0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,
|
55 |
+
0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
|
56 |
+
0xf9,0xfa
|
57 |
+
};
|
58 |
+
|
59 |
+
// Low-level helper functions.
|
60 |
+
template <class T> inline void clear_obj(T &obj) { memset(&obj, 0, sizeof(obj)); }
|
61 |
+
|
62 |
+
const int YR = 19595, YG = 38470, YB = 7471, CB_R = -11059, CB_G = -21709, CB_B = 32768, CR_R = 32768, CR_G = -27439, CR_B = -5329;
|
63 |
+
static inline uint8 clamp(int i) { if (static_cast<uint>(i) > 255U) { if (i < 0) i = 0; else if (i > 255) i = 255; } return static_cast<uint8>(i); }
|
64 |
+
|
65 |
+
static void RGB_to_YCC(uint8* pDst, const uint8 *pSrc, int num_pixels)
|
66 |
+
{
|
67 |
+
for ( ; num_pixels; pDst += 3, pSrc += 3, num_pixels--)
|
68 |
+
{
|
69 |
+
const int r = pSrc[0], g = pSrc[1], b = pSrc[2];
|
70 |
+
pDst[0] = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
|
71 |
+
pDst[1] = clamp(128 + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16));
|
72 |
+
pDst[2] = clamp(128 + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16));
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
static void RGB_to_Y(uint8* pDst, const uint8 *pSrc, int num_pixels)
|
77 |
+
{
|
78 |
+
for ( ; num_pixels; pDst++, pSrc += 3, num_pixels--)
|
79 |
+
pDst[0] = static_cast<uint8>((pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) >> 16);
|
80 |
+
}
|
81 |
+
|
82 |
+
static void RGBA_to_YCC(uint8* pDst, const uint8 *pSrc, int num_pixels)
|
83 |
+
{
|
84 |
+
for ( ; num_pixels; pDst += 3, pSrc += 4, num_pixels--)
|
85 |
+
{
|
86 |
+
const int r = pSrc[0], g = pSrc[1], b = pSrc[2];
|
87 |
+
pDst[0] = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
|
88 |
+
pDst[1] = clamp(128 + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16));
|
89 |
+
pDst[2] = clamp(128 + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16));
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
static void RGBA_to_Y(uint8* pDst, const uint8 *pSrc, int num_pixels)
|
94 |
+
{
|
95 |
+
for ( ; num_pixels; pDst++, pSrc += 4, num_pixels--)
|
96 |
+
pDst[0] = static_cast<uint8>((pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) >> 16);
|
97 |
+
}
|
98 |
+
|
99 |
+
static void Y_to_YCC(uint8* pDst, const uint8* pSrc, int num_pixels)
|
100 |
+
{
|
101 |
+
for( ; num_pixels; pDst += 3, pSrc++, num_pixels--) { pDst[0] = pSrc[0]; pDst[1] = 128; pDst[2] = 128; }
|
102 |
+
}
|
103 |
+
|
104 |
+
// Forward DCT - DCT derived from jfdctint.
|
105 |
+
#define CONST_BITS 13
|
106 |
+
#define ROW_BITS 2
|
107 |
+
#define DCT_DESCALE(x, n) (((x) + (((int32)1) << ((n) - 1))) >> (n))
|
108 |
+
#define DCT_MUL(var, c) (static_cast<int16>(var) * static_cast<int32>(c))
|
109 |
+
#define DCT1D(s0, s1, s2, s3, s4, s5, s6, s7) \
|
110 |
+
int32 t0 = s0 + s7, t7 = s0 - s7, t1 = s1 + s6, t6 = s1 - s6, t2 = s2 + s5, t5 = s2 - s5, t3 = s3 + s4, t4 = s3 - s4; \
|
111 |
+
int32 t10 = t0 + t3, t13 = t0 - t3, t11 = t1 + t2, t12 = t1 - t2; \
|
112 |
+
int32 u1 = DCT_MUL(t12 + t13, 4433); \
|
113 |
+
s2 = u1 + DCT_MUL(t13, 6270); \
|
114 |
+
s6 = u1 + DCT_MUL(t12, -15137); \
|
115 |
+
u1 = t4 + t7; \
|
116 |
+
int32 u2 = t5 + t6, u3 = t4 + t6, u4 = t5 + t7; \
|
117 |
+
int32 z5 = DCT_MUL(u3 + u4, 9633); \
|
118 |
+
t4 = DCT_MUL(t4, 2446); t5 = DCT_MUL(t5, 16819); \
|
119 |
+
t6 = DCT_MUL(t6, 25172); t7 = DCT_MUL(t7, 12299); \
|
120 |
+
u1 = DCT_MUL(u1, -7373); u2 = DCT_MUL(u2, -20995); \
|
121 |
+
u3 = DCT_MUL(u3, -16069); u4 = DCT_MUL(u4, -3196); \
|
122 |
+
u3 += z5; u4 += z5; \
|
123 |
+
s0 = t10 + t11; s1 = t7 + u1 + u4; s3 = t6 + u2 + u3; s4 = t10 - t11; s5 = t5 + u2 + u4; s7 = t4 + u1 + u3;
|
124 |
+
|
125 |
+
static void DCT2D(int32 *p)
|
126 |
+
{
|
127 |
+
int32 c, *q = p;
|
128 |
+
for (c = 7; c >= 0; c--, q += 8)
|
129 |
+
{
|
130 |
+
int32 s0 = q[0], s1 = q[1], s2 = q[2], s3 = q[3], s4 = q[4], s5 = q[5], s6 = q[6], s7 = q[7];
|
131 |
+
DCT1D(s0, s1, s2, s3, s4, s5, s6, s7);
|
132 |
+
q[0] = s0 << ROW_BITS; q[1] = DCT_DESCALE(s1, CONST_BITS-ROW_BITS); q[2] = DCT_DESCALE(s2, CONST_BITS-ROW_BITS); q[3] = DCT_DESCALE(s3, CONST_BITS-ROW_BITS);
|
133 |
+
q[4] = s4 << ROW_BITS; q[5] = DCT_DESCALE(s5, CONST_BITS-ROW_BITS); q[6] = DCT_DESCALE(s6, CONST_BITS-ROW_BITS); q[7] = DCT_DESCALE(s7, CONST_BITS-ROW_BITS);
|
134 |
+
}
|
135 |
+
for (q = p, c = 7; c >= 0; c--, q++)
|
136 |
+
{
|
137 |
+
int32 s0 = q[0*8], s1 = q[1*8], s2 = q[2*8], s3 = q[3*8], s4 = q[4*8], s5 = q[5*8], s6 = q[6*8], s7 = q[7*8];
|
138 |
+
DCT1D(s0, s1, s2, s3, s4, s5, s6, s7);
|
139 |
+
q[0*8] = DCT_DESCALE(s0, ROW_BITS+3); q[1*8] = DCT_DESCALE(s1, CONST_BITS+ROW_BITS+3); q[2*8] = DCT_DESCALE(s2, CONST_BITS+ROW_BITS+3); q[3*8] = DCT_DESCALE(s3, CONST_BITS+ROW_BITS+3);
|
140 |
+
q[4*8] = DCT_DESCALE(s4, ROW_BITS+3); q[5*8] = DCT_DESCALE(s5, CONST_BITS+ROW_BITS+3); q[6*8] = DCT_DESCALE(s6, CONST_BITS+ROW_BITS+3); q[7*8] = DCT_DESCALE(s7, CONST_BITS+ROW_BITS+3);
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
struct sym_freq { uint m_key, m_sym_index; };
|
145 |
+
|
146 |
+
// Radix sorts sym_freq[] array by 32-bit key m_key. Returns ptr to sorted values.
|
147 |
+
static inline sym_freq* radix_sort_syms(uint num_syms, sym_freq* pSyms0, sym_freq* pSyms1)
|
148 |
+
{
|
149 |
+
const uint cMaxPasses = 4;
|
150 |
+
uint32 hist[256 * cMaxPasses]; clear_obj(hist);
|
151 |
+
for (uint i = 0; i < num_syms; i++) { uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; hist[256*2 + ((freq >> 16) & 0xFF)]++; hist[256*3 + ((freq >> 24) & 0xFF)]++; }
|
152 |
+
sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1;
|
153 |
+
uint total_passes = cMaxPasses; while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
|
154 |
+
for (uint pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
|
155 |
+
{
|
156 |
+
const uint32* pHist = &hist[pass << 8];
|
157 |
+
uint offsets[256], cur_ofs = 0;
|
158 |
+
for (uint i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
|
159 |
+
for (uint i = 0; i < num_syms; i++)
|
160 |
+
pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
|
161 |
+
sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t;
|
162 |
+
}
|
163 |
+
return pCur_syms;
|
164 |
+
}
|
165 |
+
|
166 |
+
// calculate_minimum_redundancy() originally written by: Alistair Moffat, [email protected], Jyrki Katajainen, [email protected], November 1996.
|
167 |
+
static void calculate_minimum_redundancy(sym_freq *A, int n)
|
168 |
+
{
|
169 |
+
int root, leaf, next, avbl, used, dpth;
|
170 |
+
if (n==0) return; else if (n==1) { A[0].m_key = 1; return; }
|
171 |
+
A[0].m_key += A[1].m_key; root = 0; leaf = 2;
|
172 |
+
for (next=1; next < n-1; next++)
|
173 |
+
{
|
174 |
+
if (leaf>=n || A[root].m_key<A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = next; } else A[next].m_key = A[leaf++].m_key;
|
175 |
+
if (leaf>=n || (root<next && A[root].m_key<A[leaf].m_key)) { A[next].m_key += A[root].m_key; A[root++].m_key = next; } else A[next].m_key += A[leaf++].m_key;
|
176 |
+
}
|
177 |
+
A[n-2].m_key = 0;
|
178 |
+
for (next=n-3; next>=0; next--) A[next].m_key = A[A[next].m_key].m_key+1;
|
179 |
+
avbl = 1; used = dpth = 0; root = n-2; next = n-1;
|
180 |
+
while (avbl>0)
|
181 |
+
{
|
182 |
+
while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; }
|
183 |
+
while (avbl>used) { A[next--].m_key = dpth; avbl--; }
|
184 |
+
avbl = 2*used; dpth++; used = 0;
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
// Limits canonical Huffman code table's max code size to max_code_size.
|
189 |
+
static void huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
|
190 |
+
{
|
191 |
+
if (code_list_len <= 1) return;
|
192 |
+
|
193 |
+
for (int i = max_code_size + 1; i <= MAX_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
|
194 |
+
|
195 |
+
uint32 total = 0;
|
196 |
+
for (int i = max_code_size; i > 0; i--)
|
197 |
+
total += (((uint32)pNum_codes[i]) << (max_code_size - i));
|
198 |
+
|
199 |
+
while (total != (1UL << max_code_size))
|
200 |
+
{
|
201 |
+
pNum_codes[max_code_size]--;
|
202 |
+
for (int i = max_code_size - 1; i > 0; i--)
|
203 |
+
{
|
204 |
+
if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
|
205 |
+
}
|
206 |
+
total--;
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
// Generates an optimized offman table.
|
211 |
+
void jpeg_encoder::optimize_huffman_table(int table_num, int table_len)
|
212 |
+
{
|
213 |
+
sym_freq syms0[MAX_HUFF_SYMBOLS], syms1[MAX_HUFF_SYMBOLS];
|
214 |
+
syms0[0].m_key = 1; syms0[0].m_sym_index = 0; // dummy symbol, assures that no valid code contains all 1's
|
215 |
+
int num_used_syms = 1;
|
216 |
+
const uint32 *pSym_count = &m_huff_count[table_num][0];
|
217 |
+
for (int i = 0; i < table_len; i++)
|
218 |
+
if (pSym_count[i]) { syms0[num_used_syms].m_key = pSym_count[i]; syms0[num_used_syms++].m_sym_index = i + 1; }
|
219 |
+
sym_freq* pSyms = radix_sort_syms(num_used_syms, syms0, syms1);
|
220 |
+
calculate_minimum_redundancy(pSyms, num_used_syms);
|
221 |
+
|
222 |
+
// Count the # of symbols of each code size.
|
223 |
+
int num_codes[1 + MAX_HUFF_CODESIZE]; clear_obj(num_codes);
|
224 |
+
for (int i = 0; i < num_used_syms; i++)
|
225 |
+
num_codes[pSyms[i].m_key]++;
|
226 |
+
|
227 |
+
const uint JPGE_CODE_SIZE_LIMIT = 16; // the maximum possible size of a JPEG Huffman code (valid range is [9,16] - 9 vs. 8 because of the dummy symbol)
|
228 |
+
huffman_enforce_max_code_size(num_codes, num_used_syms, JPGE_CODE_SIZE_LIMIT);
|
229 |
+
|
230 |
+
// Compute m_huff_bits array, which contains the # of symbols per code size.
|
231 |
+
clear_obj(m_huff_bits[table_num]);
|
232 |
+
for (int i = 1; i <= (int)JPGE_CODE_SIZE_LIMIT; i++)
|
233 |
+
m_huff_bits[table_num][i] = static_cast<uint8>(num_codes[i]);
|
234 |
+
|
235 |
+
// Remove the dummy symbol added above, which must be in largest bucket.
|
236 |
+
for (int i = JPGE_CODE_SIZE_LIMIT; i >= 1; i--)
|
237 |
+
{
|
238 |
+
if (m_huff_bits[table_num][i]) { m_huff_bits[table_num][i]--; break; }
|
239 |
+
}
|
240 |
+
|
241 |
+
// Compute the m_huff_val array, which contains the symbol indices sorted by code size (smallest to largest).
|
242 |
+
for (int i = num_used_syms - 1; i >= 1; i--)
|
243 |
+
m_huff_val[table_num][num_used_syms - 1 - i] = static_cast<uint8>(pSyms[i].m_sym_index - 1);
|
244 |
+
}
|
245 |
+
|
246 |
+
// JPEG marker generation.
|
247 |
+
void jpeg_encoder::emit_byte(uint8 i)
|
248 |
+
{
|
249 |
+
m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_obj(i);
|
250 |
+
}
|
251 |
+
|
252 |
+
void jpeg_encoder::emit_word(uint i)
|
253 |
+
{
|
254 |
+
emit_byte(uint8(i >> 8)); emit_byte(uint8(i & 0xFF));
|
255 |
+
}
|
256 |
+
|
257 |
+
void jpeg_encoder::emit_marker(int marker)
|
258 |
+
{
|
259 |
+
emit_byte(uint8(0xFF)); emit_byte(uint8(marker));
|
260 |
+
}
|
261 |
+
|
262 |
+
// Emit JFIF marker
|
263 |
+
void jpeg_encoder::emit_jfif_app0()
|
264 |
+
{
|
265 |
+
emit_marker(M_APP0);
|
266 |
+
emit_word(2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1);
|
267 |
+
emit_byte(0x4A); emit_byte(0x46); emit_byte(0x49); emit_byte(0x46); /* Identifier: ASCII "JFIF" */
|
268 |
+
emit_byte(0);
|
269 |
+
emit_byte(1); /* Major version */
|
270 |
+
emit_byte(1); /* Minor version */
|
271 |
+
emit_byte(0); /* Density unit */
|
272 |
+
emit_word(1);
|
273 |
+
emit_word(1);
|
274 |
+
emit_byte(0); /* No thumbnail image */
|
275 |
+
emit_byte(0);
|
276 |
+
}
|
277 |
+
|
278 |
+
// Emit quantization tables
|
279 |
+
void jpeg_encoder::emit_dqt()
|
280 |
+
{
|
281 |
+
for (int i = 0; i < ((m_num_components == 3) ? 2 : 1); i++)
|
282 |
+
{
|
283 |
+
emit_marker(M_DQT);
|
284 |
+
emit_word(64 + 1 + 2);
|
285 |
+
emit_byte(static_cast<uint8>(i));
|
286 |
+
for (int j = 0; j < 64; j++)
|
287 |
+
emit_byte(static_cast<uint8>(m_quantization_tables[i][j]));
|
288 |
+
}
|
289 |
+
}
|
290 |
+
|
291 |
+
// Emit start of frame marker
|
292 |
+
void jpeg_encoder::emit_sof()
|
293 |
+
{
|
294 |
+
emit_marker(M_SOF0); /* baseline */
|
295 |
+
emit_word(3 * m_num_components + 2 + 5 + 1);
|
296 |
+
emit_byte(8); /* precision */
|
297 |
+
emit_word(m_image_y);
|
298 |
+
emit_word(m_image_x);
|
299 |
+
emit_byte(m_num_components);
|
300 |
+
for (int i = 0; i < m_num_components; i++)
|
301 |
+
{
|
302 |
+
emit_byte(static_cast<uint8>(i + 1)); /* component ID */
|
303 |
+
emit_byte((m_comp_h_samp[i] << 4) + m_comp_v_samp[i]); /* h and v sampling */
|
304 |
+
emit_byte(i > 0); /* quant. table num */
|
305 |
+
}
|
306 |
+
}
|
307 |
+
|
308 |
+
// Emit Huffman table.
|
309 |
+
void jpeg_encoder::emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag)
|
310 |
+
{
|
311 |
+
emit_marker(M_DHT);
|
312 |
+
|
313 |
+
int length = 0;
|
314 |
+
for (int i = 1; i <= 16; i++)
|
315 |
+
length += bits[i];
|
316 |
+
|
317 |
+
emit_word(length + 2 + 1 + 16);
|
318 |
+
emit_byte(static_cast<uint8>(index + (ac_flag << 4)));
|
319 |
+
|
320 |
+
for (int i = 1; i <= 16; i++)
|
321 |
+
emit_byte(bits[i]);
|
322 |
+
|
323 |
+
for (int i = 0; i < length; i++)
|
324 |
+
emit_byte(val[i]);
|
325 |
+
}
|
326 |
+
|
327 |
+
// Emit all Huffman tables.
|
328 |
+
void jpeg_encoder::emit_dhts()
|
329 |
+
{
|
330 |
+
emit_dht(m_huff_bits[0+0], m_huff_val[0+0], 0, false);
|
331 |
+
emit_dht(m_huff_bits[2+0], m_huff_val[2+0], 0, true);
|
332 |
+
if (m_num_components == 3)
|
333 |
+
{
|
334 |
+
emit_dht(m_huff_bits[0+1], m_huff_val[0+1], 1, false);
|
335 |
+
emit_dht(m_huff_bits[2+1], m_huff_val[2+1], 1, true);
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
// emit start of scan
|
340 |
+
void jpeg_encoder::emit_sos()
|
341 |
+
{
|
342 |
+
emit_marker(M_SOS);
|
343 |
+
emit_word(2 * m_num_components + 2 + 1 + 3);
|
344 |
+
emit_byte(m_num_components);
|
345 |
+
for (int i = 0; i < m_num_components; i++)
|
346 |
+
{
|
347 |
+
emit_byte(static_cast<uint8>(i + 1));
|
348 |
+
if (i == 0)
|
349 |
+
emit_byte((0 << 4) + 0);
|
350 |
+
else
|
351 |
+
emit_byte((1 << 4) + 1);
|
352 |
+
}
|
353 |
+
emit_byte(0); /* spectral selection */
|
354 |
+
emit_byte(63);
|
355 |
+
emit_byte(0);
|
356 |
+
}
|
357 |
+
|
358 |
+
// Emit all markers at beginning of image file.
|
359 |
+
void jpeg_encoder::emit_markers()
|
360 |
+
{
|
361 |
+
emit_marker(M_SOI);
|
362 |
+
emit_jfif_app0();
|
363 |
+
emit_dqt();
|
364 |
+
emit_sof();
|
365 |
+
emit_dhts();
|
366 |
+
emit_sos();
|
367 |
+
}
|
368 |
+
|
369 |
+
// Compute the actual canonical Huffman codes/code sizes given the JPEG huff bits and val arrays.
|
370 |
+
void jpeg_encoder::compute_huffman_table(uint *codes, uint8 *code_sizes, uint8 *bits, uint8 *val)
|
371 |
+
{
|
372 |
+
int i, l, last_p, si;
|
373 |
+
uint8 huff_size[257];
|
374 |
+
uint huff_code[257];
|
375 |
+
uint code;
|
376 |
+
|
377 |
+
int p = 0;
|
378 |
+
for (l = 1; l <= 16; l++)
|
379 |
+
for (i = 1; i <= bits[l]; i++)
|
380 |
+
huff_size[p++] = (char)l;
|
381 |
+
|
382 |
+
huff_size[p] = 0; last_p = p; // write sentinel
|
383 |
+
|
384 |
+
code = 0; si = huff_size[0]; p = 0;
|
385 |
+
|
386 |
+
while (huff_size[p])
|
387 |
+
{
|
388 |
+
while (huff_size[p] == si)
|
389 |
+
huff_code[p++] = code++;
|
390 |
+
code <<= 1;
|
391 |
+
si++;
|
392 |
+
}
|
393 |
+
|
394 |
+
memset(codes, 0, sizeof(codes[0])*256);
|
395 |
+
memset(code_sizes, 0, sizeof(code_sizes[0])*256);
|
396 |
+
for (p = 0; p < last_p; p++)
|
397 |
+
{
|
398 |
+
codes[val[p]] = huff_code[p];
|
399 |
+
code_sizes[val[p]] = huff_size[p];
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
// Quantization table generation.
|
404 |
+
void jpeg_encoder::compute_quant_table(int32 *pDst, int16 *pSrc)
|
405 |
+
{
|
406 |
+
int32 q;
|
407 |
+
if (m_params.m_quality < 50)
|
408 |
+
q = 5000 / m_params.m_quality;
|
409 |
+
else
|
410 |
+
q = 200 - m_params.m_quality * 2;
|
411 |
+
for (int i = 0; i < 64; i++)
|
412 |
+
{
|
413 |
+
int32 j = *pSrc++; j = (j * q + 50L) / 100L;
|
414 |
+
*pDst++ = JPGE_MIN(JPGE_MAX(j, 1), 255);
|
415 |
+
}
|
416 |
+
}
|
417 |
+
|
418 |
+
// Higher-level methods.
|
419 |
+
void jpeg_encoder::first_pass_init()
|
420 |
+
{
|
421 |
+
m_bit_buffer = 0; m_bits_in = 0;
|
422 |
+
memset(m_last_dc_val, 0, 3 * sizeof(m_last_dc_val[0]));
|
423 |
+
m_mcu_y_ofs = 0;
|
424 |
+
m_pass_num = 1;
|
425 |
+
}
|
426 |
+
|
427 |
+
bool jpeg_encoder::second_pass_init()
|
428 |
+
{
|
429 |
+
compute_huffman_table(&m_huff_codes[0+0][0], &m_huff_code_sizes[0+0][0], m_huff_bits[0+0], m_huff_val[0+0]);
|
430 |
+
compute_huffman_table(&m_huff_codes[2+0][0], &m_huff_code_sizes[2+0][0], m_huff_bits[2+0], m_huff_val[2+0]);
|
431 |
+
if (m_num_components > 1)
|
432 |
+
{
|
433 |
+
compute_huffman_table(&m_huff_codes[0+1][0], &m_huff_code_sizes[0+1][0], m_huff_bits[0+1], m_huff_val[0+1]);
|
434 |
+
compute_huffman_table(&m_huff_codes[2+1][0], &m_huff_code_sizes[2+1][0], m_huff_bits[2+1], m_huff_val[2+1]);
|
435 |
+
}
|
436 |
+
first_pass_init();
|
437 |
+
emit_markers();
|
438 |
+
m_pass_num = 2;
|
439 |
+
return true;
|
440 |
+
}
|
441 |
+
|
442 |
+
bool jpeg_encoder::jpg_open(int p_x_res, int p_y_res, int src_channels)
|
443 |
+
{
|
444 |
+
m_num_components = 3;
|
445 |
+
switch (m_params.m_subsampling)
|
446 |
+
{
|
447 |
+
case Y_ONLY:
|
448 |
+
{
|
449 |
+
m_num_components = 1;
|
450 |
+
m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1;
|
451 |
+
m_mcu_x = 8; m_mcu_y = 8;
|
452 |
+
break;
|
453 |
+
}
|
454 |
+
case H1V1:
|
455 |
+
{
|
456 |
+
m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1;
|
457 |
+
m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1;
|
458 |
+
m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1;
|
459 |
+
m_mcu_x = 8; m_mcu_y = 8;
|
460 |
+
break;
|
461 |
+
}
|
462 |
+
case H2V1:
|
463 |
+
{
|
464 |
+
m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 1;
|
465 |
+
m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1;
|
466 |
+
m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1;
|
467 |
+
m_mcu_x = 16; m_mcu_y = 8;
|
468 |
+
break;
|
469 |
+
}
|
470 |
+
case H2V2:
|
471 |
+
{
|
472 |
+
m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 2;
|
473 |
+
m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1;
|
474 |
+
m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1;
|
475 |
+
m_mcu_x = 16; m_mcu_y = 16;
|
476 |
+
}
|
477 |
+
}
|
478 |
+
|
479 |
+
m_image_x = p_x_res; m_image_y = p_y_res;
|
480 |
+
m_image_bpp = src_channels;
|
481 |
+
m_image_bpl = m_image_x * src_channels;
|
482 |
+
m_image_x_mcu = (m_image_x + m_mcu_x - 1) & (~(m_mcu_x - 1));
|
483 |
+
m_image_y_mcu = (m_image_y + m_mcu_y - 1) & (~(m_mcu_y - 1));
|
484 |
+
m_image_bpl_xlt = m_image_x * m_num_components;
|
485 |
+
m_image_bpl_mcu = m_image_x_mcu * m_num_components;
|
486 |
+
m_mcus_per_row = m_image_x_mcu / m_mcu_x;
|
487 |
+
|
488 |
+
if ((m_mcu_lines[0] = static_cast<uint8*>(jpge_malloc(m_image_bpl_mcu * m_mcu_y))) == NULL) return false;
|
489 |
+
for (int i = 1; i < m_mcu_y; i++)
|
490 |
+
m_mcu_lines[i] = m_mcu_lines[i-1] + m_image_bpl_mcu;
|
491 |
+
|
492 |
+
compute_quant_table(m_quantization_tables[0], s_std_lum_quant);
|
493 |
+
compute_quant_table(m_quantization_tables[1], m_params.m_no_chroma_discrim_flag ? s_std_lum_quant : s_std_croma_quant);
|
494 |
+
|
495 |
+
m_out_buf_left = JPGE_OUT_BUF_SIZE;
|
496 |
+
m_pOut_buf = m_out_buf;
|
497 |
+
|
498 |
+
if (m_params.m_two_pass_flag)
|
499 |
+
{
|
500 |
+
clear_obj(m_huff_count);
|
501 |
+
first_pass_init();
|
502 |
+
}
|
503 |
+
else
|
504 |
+
{
|
505 |
+
memcpy(m_huff_bits[0+0], s_dc_lum_bits, 17); memcpy(m_huff_val [0+0], s_dc_lum_val, DC_LUM_CODES);
|
506 |
+
memcpy(m_huff_bits[2+0], s_ac_lum_bits, 17); memcpy(m_huff_val [2+0], s_ac_lum_val, AC_LUM_CODES);
|
507 |
+
memcpy(m_huff_bits[0+1], s_dc_chroma_bits, 17); memcpy(m_huff_val [0+1], s_dc_chroma_val, DC_CHROMA_CODES);
|
508 |
+
memcpy(m_huff_bits[2+1], s_ac_chroma_bits, 17); memcpy(m_huff_val [2+1], s_ac_chroma_val, AC_CHROMA_CODES);
|
509 |
+
if (!second_pass_init()) return false; // in effect, skip over the first pass
|
510 |
+
}
|
511 |
+
return m_all_stream_writes_succeeded;
|
512 |
+
}
|
513 |
+
|
514 |
+
void jpeg_encoder::load_block_8_8_grey(int x)
|
515 |
+
{
|
516 |
+
uint8 *pSrc;
|
517 |
+
sample_array_t *pDst = m_sample_array;
|
518 |
+
x <<= 3;
|
519 |
+
for (int i = 0; i < 8; i++, pDst += 8)
|
520 |
+
{
|
521 |
+
pSrc = m_mcu_lines[i] + x;
|
522 |
+
pDst[0] = pSrc[0] - 128; pDst[1] = pSrc[1] - 128; pDst[2] = pSrc[2] - 128; pDst[3] = pSrc[3] - 128;
|
523 |
+
pDst[4] = pSrc[4] - 128; pDst[5] = pSrc[5] - 128; pDst[6] = pSrc[6] - 128; pDst[7] = pSrc[7] - 128;
|
524 |
+
}
|
525 |
+
}
|
526 |
+
|
527 |
+
void jpeg_encoder::load_block_8_8(int x, int y, int c)
|
528 |
+
{
|
529 |
+
uint8 *pSrc;
|
530 |
+
sample_array_t *pDst = m_sample_array;
|
531 |
+
x = (x * (8 * 3)) + c;
|
532 |
+
y <<= 3;
|
533 |
+
for (int i = 0; i < 8; i++, pDst += 8)
|
534 |
+
{
|
535 |
+
pSrc = m_mcu_lines[y + i] + x;
|
536 |
+
pDst[0] = pSrc[0 * 3] - 128; pDst[1] = pSrc[1 * 3] - 128; pDst[2] = pSrc[2 * 3] - 128; pDst[3] = pSrc[3 * 3] - 128;
|
537 |
+
pDst[4] = pSrc[4 * 3] - 128; pDst[5] = pSrc[5 * 3] - 128; pDst[6] = pSrc[6 * 3] - 128; pDst[7] = pSrc[7 * 3] - 128;
|
538 |
+
}
|
539 |
+
}
|
540 |
+
|
541 |
+
void jpeg_encoder::load_block_16_8(int x, int c)
|
542 |
+
{
|
543 |
+
uint8 *pSrc1, *pSrc2;
|
544 |
+
sample_array_t *pDst = m_sample_array;
|
545 |
+
x = (x * (16 * 3)) + c;
|
546 |
+
int a = 0, b = 2;
|
547 |
+
for (int i = 0; i < 16; i += 2, pDst += 8)
|
548 |
+
{
|
549 |
+
pSrc1 = m_mcu_lines[i + 0] + x;
|
550 |
+
pSrc2 = m_mcu_lines[i + 1] + x;
|
551 |
+
pDst[0] = ((pSrc1[ 0 * 3] + pSrc1[ 1 * 3] + pSrc2[ 0 * 3] + pSrc2[ 1 * 3] + a) >> 2) - 128; pDst[1] = ((pSrc1[ 2 * 3] + pSrc1[ 3 * 3] + pSrc2[ 2 * 3] + pSrc2[ 3 * 3] + b) >> 2) - 128;
|
552 |
+
pDst[2] = ((pSrc1[ 4 * 3] + pSrc1[ 5 * 3] + pSrc2[ 4 * 3] + pSrc2[ 5 * 3] + a) >> 2) - 128; pDst[3] = ((pSrc1[ 6 * 3] + pSrc1[ 7 * 3] + pSrc2[ 6 * 3] + pSrc2[ 7 * 3] + b) >> 2) - 128;
|
553 |
+
pDst[4] = ((pSrc1[ 8 * 3] + pSrc1[ 9 * 3] + pSrc2[ 8 * 3] + pSrc2[ 9 * 3] + a) >> 2) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3] + pSrc2[10 * 3] + pSrc2[11 * 3] + b) >> 2) - 128;
|
554 |
+
pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3] + pSrc2[12 * 3] + pSrc2[13 * 3] + a) >> 2) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3] + pSrc2[14 * 3] + pSrc2[15 * 3] + b) >> 2) - 128;
|
555 |
+
int temp = a; a = b; b = temp;
|
556 |
+
}
|
557 |
+
}
|
558 |
+
|
559 |
+
void jpeg_encoder::load_block_16_8_8(int x, int c)
|
560 |
+
{
|
561 |
+
uint8 *pSrc1;
|
562 |
+
sample_array_t *pDst = m_sample_array;
|
563 |
+
x = (x * (16 * 3)) + c;
|
564 |
+
for (int i = 0; i < 8; i++, pDst += 8)
|
565 |
+
{
|
566 |
+
pSrc1 = m_mcu_lines[i + 0] + x;
|
567 |
+
pDst[0] = ((pSrc1[ 0 * 3] + pSrc1[ 1 * 3]) >> 1) - 128; pDst[1] = ((pSrc1[ 2 * 3] + pSrc1[ 3 * 3]) >> 1) - 128;
|
568 |
+
pDst[2] = ((pSrc1[ 4 * 3] + pSrc1[ 5 * 3]) >> 1) - 128; pDst[3] = ((pSrc1[ 6 * 3] + pSrc1[ 7 * 3]) >> 1) - 128;
|
569 |
+
pDst[4] = ((pSrc1[ 8 * 3] + pSrc1[ 9 * 3]) >> 1) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3]) >> 1) - 128;
|
570 |
+
pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3]) >> 1) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3]) >> 1) - 128;
|
571 |
+
}
|
572 |
+
}
|
573 |
+
|
574 |
+
void jpeg_encoder::load_quantized_coefficients(int component_num)
|
575 |
+
{
|
576 |
+
int32 *q = m_quantization_tables[component_num > 0];
|
577 |
+
int16 *pDst = m_coefficient_array;
|
578 |
+
for (int i = 0; i < 64; i++)
|
579 |
+
{
|
580 |
+
sample_array_t j = m_sample_array[s_zag[i]];
|
581 |
+
if (j < 0)
|
582 |
+
{
|
583 |
+
if ((j = -j + (*q >> 1)) < *q)
|
584 |
+
*pDst++ = 0;
|
585 |
+
else
|
586 |
+
*pDst++ = static_cast<int16>(-(j / *q));
|
587 |
+
}
|
588 |
+
else
|
589 |
+
{
|
590 |
+
if ((j = j + (*q >> 1)) < *q)
|
591 |
+
*pDst++ = 0;
|
592 |
+
else
|
593 |
+
*pDst++ = static_cast<int16>((j / *q));
|
594 |
+
}
|
595 |
+
q++;
|
596 |
+
}
|
597 |
+
}
|
598 |
+
|
599 |
+
void jpeg_encoder::flush_output_buffer()
|
600 |
+
{
|
601 |
+
if (m_out_buf_left != JPGE_OUT_BUF_SIZE)
|
602 |
+
m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_buf(m_out_buf, JPGE_OUT_BUF_SIZE - m_out_buf_left);
|
603 |
+
m_pOut_buf = m_out_buf;
|
604 |
+
m_out_buf_left = JPGE_OUT_BUF_SIZE;
|
605 |
+
}
|
606 |
+
|
607 |
+
void jpeg_encoder::put_bits(uint bits, uint len)
|
608 |
+
{
|
609 |
+
m_bit_buffer |= ((uint32)bits << (24 - (m_bits_in += len)));
|
610 |
+
while (m_bits_in >= 8)
|
611 |
+
{
|
612 |
+
uint8 c;
|
613 |
+
#define JPGE_PUT_BYTE(c) { *m_pOut_buf++ = (c); if (--m_out_buf_left == 0) flush_output_buffer(); }
|
614 |
+
JPGE_PUT_BYTE(c = (uint8)((m_bit_buffer >> 16) & 0xFF));
|
615 |
+
if (c == 0xFF) JPGE_PUT_BYTE(0);
|
616 |
+
m_bit_buffer <<= 8;
|
617 |
+
m_bits_in -= 8;
|
618 |
+
}
|
619 |
+
}
|
620 |
+
|
621 |
+
void jpeg_encoder::code_coefficients_pass_one(int component_num)
|
622 |
+
{
|
623 |
+
if (component_num >= 3) return; // just to shut up static analysis
|
624 |
+
int i, run_len, nbits, temp1;
|
625 |
+
int16 *src = m_coefficient_array;
|
626 |
+
uint32 *dc_count = component_num ? m_huff_count[0 + 1] : m_huff_count[0 + 0], *ac_count = component_num ? m_huff_count[2 + 1] : m_huff_count[2 + 0];
|
627 |
+
|
628 |
+
temp1 = src[0] - m_last_dc_val[component_num];
|
629 |
+
m_last_dc_val[component_num] = src[0];
|
630 |
+
if (temp1 < 0) temp1 = -temp1;
|
631 |
+
|
632 |
+
nbits = 0;
|
633 |
+
while (temp1)
|
634 |
+
{
|
635 |
+
nbits++; temp1 >>= 1;
|
636 |
+
}
|
637 |
+
|
638 |
+
dc_count[nbits]++;
|
639 |
+
for (run_len = 0, i = 1; i < 64; i++)
|
640 |
+
{
|
641 |
+
if ((temp1 = m_coefficient_array[i]) == 0)
|
642 |
+
run_len++;
|
643 |
+
else
|
644 |
+
{
|
645 |
+
while (run_len >= 16)
|
646 |
+
{
|
647 |
+
ac_count[0xF0]++;
|
648 |
+
run_len -= 16;
|
649 |
+
}
|
650 |
+
if (temp1 < 0) temp1 = -temp1;
|
651 |
+
nbits = 1;
|
652 |
+
while (temp1 >>= 1) nbits++;
|
653 |
+
ac_count[(run_len << 4) + nbits]++;
|
654 |
+
run_len = 0;
|
655 |
+
}
|
656 |
+
}
|
657 |
+
if (run_len) ac_count[0]++;
|
658 |
+
}
|
659 |
+
|
660 |
+
void jpeg_encoder::code_coefficients_pass_two(int component_num)
|
661 |
+
{
|
662 |
+
int i, j, run_len, nbits, temp1, temp2;
|
663 |
+
int16 *pSrc = m_coefficient_array;
|
664 |
+
uint *codes[2];
|
665 |
+
uint8 *code_sizes[2];
|
666 |
+
|
667 |
+
if (component_num == 0)
|
668 |
+
{
|
669 |
+
codes[0] = m_huff_codes[0 + 0]; codes[1] = m_huff_codes[2 + 0];
|
670 |
+
code_sizes[0] = m_huff_code_sizes[0 + 0]; code_sizes[1] = m_huff_code_sizes[2 + 0];
|
671 |
+
}
|
672 |
+
else
|
673 |
+
{
|
674 |
+
codes[0] = m_huff_codes[0 + 1]; codes[1] = m_huff_codes[2 + 1];
|
675 |
+
code_sizes[0] = m_huff_code_sizes[0 + 1]; code_sizes[1] = m_huff_code_sizes[2 + 1];
|
676 |
+
}
|
677 |
+
|
678 |
+
temp1 = temp2 = pSrc[0] - m_last_dc_val[component_num];
|
679 |
+
m_last_dc_val[component_num] = pSrc[0];
|
680 |
+
|
681 |
+
if (temp1 < 0)
|
682 |
+
{
|
683 |
+
temp1 = -temp1; temp2--;
|
684 |
+
}
|
685 |
+
|
686 |
+
nbits = 0;
|
687 |
+
while (temp1)
|
688 |
+
{
|
689 |
+
nbits++; temp1 >>= 1;
|
690 |
+
}
|
691 |
+
|
692 |
+
put_bits(codes[0][nbits], code_sizes[0][nbits]);
|
693 |
+
if (nbits) put_bits(temp2 & ((1 << nbits) - 1), nbits);
|
694 |
+
|
695 |
+
for (run_len = 0, i = 1; i < 64; i++)
|
696 |
+
{
|
697 |
+
if ((temp1 = m_coefficient_array[i]) == 0)
|
698 |
+
run_len++;
|
699 |
+
else
|
700 |
+
{
|
701 |
+
while (run_len >= 16)
|
702 |
+
{
|
703 |
+
put_bits(codes[1][0xF0], code_sizes[1][0xF0]);
|
704 |
+
run_len -= 16;
|
705 |
+
}
|
706 |
+
if ((temp2 = temp1) < 0)
|
707 |
+
{
|
708 |
+
temp1 = -temp1;
|
709 |
+
temp2--;
|
710 |
+
}
|
711 |
+
nbits = 1;
|
712 |
+
while (temp1 >>= 1)
|
713 |
+
nbits++;
|
714 |
+
j = (run_len << 4) + nbits;
|
715 |
+
put_bits(codes[1][j], code_sizes[1][j]);
|
716 |
+
put_bits(temp2 & ((1 << nbits) - 1), nbits);
|
717 |
+
run_len = 0;
|
718 |
+
}
|
719 |
+
}
|
720 |
+
if (run_len)
|
721 |
+
put_bits(codes[1][0], code_sizes[1][0]);
|
722 |
+
}
|
723 |
+
|
724 |
+
void jpeg_encoder::code_block(int component_num)
|
725 |
+
{
|
726 |
+
DCT2D(m_sample_array);
|
727 |
+
load_quantized_coefficients(component_num);
|
728 |
+
if (m_pass_num == 1)
|
729 |
+
code_coefficients_pass_one(component_num);
|
730 |
+
else
|
731 |
+
code_coefficients_pass_two(component_num);
|
732 |
+
}
|
733 |
+
|
734 |
+
void jpeg_encoder::process_mcu_row()
|
735 |
+
{
|
736 |
+
if (m_num_components == 1)
|
737 |
+
{
|
738 |
+
for (int i = 0; i < m_mcus_per_row; i++)
|
739 |
+
{
|
740 |
+
load_block_8_8_grey(i); code_block(0);
|
741 |
+
}
|
742 |
+
}
|
743 |
+
else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1))
|
744 |
+
{
|
745 |
+
for (int i = 0; i < m_mcus_per_row; i++)
|
746 |
+
{
|
747 |
+
load_block_8_8(i, 0, 0); code_block(0); load_block_8_8(i, 0, 1); code_block(1); load_block_8_8(i, 0, 2); code_block(2);
|
748 |
+
}
|
749 |
+
}
|
750 |
+
else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1))
|
751 |
+
{
|
752 |
+
for (int i = 0; i < m_mcus_per_row; i++)
|
753 |
+
{
|
754 |
+
load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0);
|
755 |
+
load_block_16_8_8(i, 1); code_block(1); load_block_16_8_8(i, 2); code_block(2);
|
756 |
+
}
|
757 |
+
}
|
758 |
+
else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2))
|
759 |
+
{
|
760 |
+
for (int i = 0; i < m_mcus_per_row; i++)
|
761 |
+
{
|
762 |
+
load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0);
|
763 |
+
load_block_8_8(i * 2 + 0, 1, 0); code_block(0); load_block_8_8(i * 2 + 1, 1, 0); code_block(0);
|
764 |
+
load_block_16_8(i, 1); code_block(1); load_block_16_8(i, 2); code_block(2);
|
765 |
+
}
|
766 |
+
}
|
767 |
+
}
|
768 |
+
|
769 |
+
bool jpeg_encoder::terminate_pass_one()
|
770 |
+
{
|
771 |
+
optimize_huffman_table(0+0, DC_LUM_CODES); optimize_huffman_table(2+0, AC_LUM_CODES);
|
772 |
+
if (m_num_components > 1)
|
773 |
+
{
|
774 |
+
optimize_huffman_table(0+1, DC_CHROMA_CODES); optimize_huffman_table(2+1, AC_CHROMA_CODES);
|
775 |
+
}
|
776 |
+
return second_pass_init();
|
777 |
+
}
|
778 |
+
|
779 |
+
bool jpeg_encoder::terminate_pass_two()
|
780 |
+
{
|
781 |
+
put_bits(0x7F, 7);
|
782 |
+
flush_output_buffer();
|
783 |
+
emit_marker(M_EOI);
|
784 |
+
m_pass_num++; // purposely bump up m_pass_num, for debugging
|
785 |
+
return true;
|
786 |
+
}
|
787 |
+
|
788 |
+
bool jpeg_encoder::process_end_of_image()
|
789 |
+
{
|
790 |
+
if (m_mcu_y_ofs)
|
791 |
+
{
|
792 |
+
if (m_mcu_y_ofs < 16) // check here just to shut up static analysis
|
793 |
+
{
|
794 |
+
for (int i = m_mcu_y_ofs; i < m_mcu_y; i++)
|
795 |
+
memcpy(m_mcu_lines[i], m_mcu_lines[m_mcu_y_ofs - 1], m_image_bpl_mcu);
|
796 |
+
}
|
797 |
+
|
798 |
+
process_mcu_row();
|
799 |
+
}
|
800 |
+
|
801 |
+
if (m_pass_num == 1)
|
802 |
+
return terminate_pass_one();
|
803 |
+
else
|
804 |
+
return terminate_pass_two();
|
805 |
+
}
|
806 |
+
|
807 |
+
void jpeg_encoder::load_mcu(const void *pSrc)
|
808 |
+
{
|
809 |
+
const uint8* Psrc = reinterpret_cast<const uint8*>(pSrc);
|
810 |
+
|
811 |
+
uint8* pDst = m_mcu_lines[m_mcu_y_ofs]; // OK to write up to m_image_bpl_xlt bytes to pDst
|
812 |
+
|
813 |
+
if (m_num_components == 1)
|
814 |
+
{
|
815 |
+
if (m_image_bpp == 4)
|
816 |
+
RGBA_to_Y(pDst, Psrc, m_image_x);
|
817 |
+
else if (m_image_bpp == 3)
|
818 |
+
RGB_to_Y(pDst, Psrc, m_image_x);
|
819 |
+
else
|
820 |
+
memcpy(pDst, Psrc, m_image_x);
|
821 |
+
}
|
822 |
+
else
|
823 |
+
{
|
824 |
+
if (m_image_bpp == 4)
|
825 |
+
RGBA_to_YCC(pDst, Psrc, m_image_x);
|
826 |
+
else if (m_image_bpp == 3)
|
827 |
+
RGB_to_YCC(pDst, Psrc, m_image_x);
|
828 |
+
else
|
829 |
+
Y_to_YCC(pDst, Psrc, m_image_x);
|
830 |
+
}
|
831 |
+
|
832 |
+
// Possibly duplicate pixels at end of scanline if not a multiple of 8 or 16
|
833 |
+
if (m_num_components == 1)
|
834 |
+
memset(m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt, pDst[m_image_bpl_xlt - 1], m_image_x_mcu - m_image_x);
|
835 |
+
else
|
836 |
+
{
|
837 |
+
const uint8 y = pDst[m_image_bpl_xlt - 3 + 0], cb = pDst[m_image_bpl_xlt - 3 + 1], cr = pDst[m_image_bpl_xlt - 3 + 2];
|
838 |
+
uint8 *q = m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt;
|
839 |
+
for (int i = m_image_x; i < m_image_x_mcu; i++)
|
840 |
+
{
|
841 |
+
*q++ = y; *q++ = cb; *q++ = cr;
|
842 |
+
}
|
843 |
+
}
|
844 |
+
|
845 |
+
if (++m_mcu_y_ofs == m_mcu_y)
|
846 |
+
{
|
847 |
+
process_mcu_row();
|
848 |
+
m_mcu_y_ofs = 0;
|
849 |
+
}
|
850 |
+
}
|
851 |
+
|
852 |
+
void jpeg_encoder::clear()
|
853 |
+
{
|
854 |
+
m_mcu_lines[0] = NULL;
|
855 |
+
m_pass_num = 0;
|
856 |
+
m_all_stream_writes_succeeded = true;
|
857 |
+
}
|
858 |
+
|
859 |
+
jpeg_encoder::jpeg_encoder()
|
860 |
+
{
|
861 |
+
clear();
|
862 |
+
}
|
863 |
+
|
864 |
+
jpeg_encoder::~jpeg_encoder()
|
865 |
+
{
|
866 |
+
deinit();
|
867 |
+
}
|
868 |
+
|
869 |
+
bool jpeg_encoder::init(output_stream *pStream, int64_t width, int64_t height, int64_t src_channels, const params &comp_params)
|
870 |
+
{
|
871 |
+
deinit();
|
872 |
+
if (((!pStream) || (width < 1) || (height < 1)) || ((src_channels != 1) && (src_channels != 3) && (src_channels != 4)) || (!comp_params.check_valid())) return false;
|
873 |
+
m_pStream = pStream;
|
874 |
+
m_params = comp_params;
|
875 |
+
return jpg_open(width, height, src_channels);
|
876 |
+
}
|
877 |
+
|
878 |
+
void jpeg_encoder::deinit()
|
879 |
+
{
|
880 |
+
jpge_free(m_mcu_lines[0]);
|
881 |
+
clear();
|
882 |
+
}
|
883 |
+
|
884 |
+
bool jpeg_encoder::process_scanline(const void* pScanline)
|
885 |
+
{
|
886 |
+
if ((m_pass_num < 1) || (m_pass_num > 2)) return false;
|
887 |
+
if (m_all_stream_writes_succeeded)
|
888 |
+
{
|
889 |
+
if (!pScanline)
|
890 |
+
{
|
891 |
+
if (!process_end_of_image()) return false;
|
892 |
+
}
|
893 |
+
else
|
894 |
+
{
|
895 |
+
load_mcu(pScanline);
|
896 |
+
}
|
897 |
+
}
|
898 |
+
return m_all_stream_writes_succeeded;
|
899 |
+
}
|
900 |
+
|
901 |
+
// Higher level wrappers/examples (optional).
|
902 |
+
#include <stdio.h>
|
903 |
+
|
904 |
+
class cfile_stream : public output_stream
|
905 |
+
{
|
906 |
+
cfile_stream(const cfile_stream &);
|
907 |
+
cfile_stream &operator= (const cfile_stream &);
|
908 |
+
|
909 |
+
FILE* m_pFile;
|
910 |
+
bool m_bStatus;
|
911 |
+
|
912 |
+
public:
|
913 |
+
cfile_stream() : m_pFile(NULL), m_bStatus(false) { }
|
914 |
+
|
915 |
+
virtual ~cfile_stream()
|
916 |
+
{
|
917 |
+
close();
|
918 |
+
}
|
919 |
+
|
920 |
+
bool open(const char *pFilename)
|
921 |
+
{
|
922 |
+
close();
|
923 |
+
#if defined(_MSC_VER)
|
924 |
+
if (fopen_s(&m_pFile, pFilename, "wb") != 0)
|
925 |
+
{
|
926 |
+
return false;
|
927 |
+
}
|
928 |
+
#else
|
929 |
+
m_pFile = fopen(pFilename, "wb");
|
930 |
+
#endif
|
931 |
+
m_bStatus = (m_pFile != NULL);
|
932 |
+
return m_bStatus;
|
933 |
+
}
|
934 |
+
|
935 |
+
bool close()
|
936 |
+
{
|
937 |
+
if (m_pFile)
|
938 |
+
{
|
939 |
+
if (fclose(m_pFile) == EOF)
|
940 |
+
{
|
941 |
+
m_bStatus = false;
|
942 |
+
}
|
943 |
+
m_pFile = NULL;
|
944 |
+
}
|
945 |
+
return m_bStatus;
|
946 |
+
}
|
947 |
+
|
948 |
+
virtual bool put_buf(const void* pBuf, int64_t len)
|
949 |
+
{
|
950 |
+
m_bStatus = m_bStatus && (fwrite(pBuf, len, 1, m_pFile) == 1);
|
951 |
+
return m_bStatus;
|
952 |
+
}
|
953 |
+
|
954 |
+
uint get_size() const
|
955 |
+
{
|
956 |
+
return m_pFile ? ftell(m_pFile) : 0;
|
957 |
+
}
|
958 |
+
};
|
959 |
+
|
960 |
+
// Writes JPEG image to file.
|
961 |
+
bool compress_image_to_jpeg_file(const char *pFilename, int64_t width, int64_t height, int64_t num_channels, const uint8 *pImage_data, const params &comp_params)
|
962 |
+
{
|
963 |
+
cfile_stream dst_stream;
|
964 |
+
if (!dst_stream.open(pFilename))
|
965 |
+
return false;
|
966 |
+
|
967 |
+
jpge::jpeg_encoder dst_image;
|
968 |
+
if (!dst_image.init(&dst_stream, width, height, num_channels, comp_params))
|
969 |
+
return false;
|
970 |
+
|
971 |
+
for (uint pass_index = 0; pass_index < dst_image.get_total_passes(); pass_index++)
|
972 |
+
{
|
973 |
+
for (int64_t i = 0; i < height; i++)
|
974 |
+
{
|
975 |
+
// i, width, and num_channels are all 64bit
|
976 |
+
const uint8* pBuf = pImage_data + i * width * num_channels;
|
977 |
+
if (!dst_image.process_scanline(pBuf))
|
978 |
+
return false;
|
979 |
+
}
|
980 |
+
if (!dst_image.process_scanline(NULL))
|
981 |
+
return false;
|
982 |
+
}
|
983 |
+
|
984 |
+
dst_image.deinit();
|
985 |
+
|
986 |
+
return dst_stream.close();
|
987 |
+
}
|
988 |
+
|
989 |
+
class memory_stream : public output_stream
|
990 |
+
{
|
991 |
+
memory_stream(const memory_stream &);
|
992 |
+
memory_stream &operator= (const memory_stream &);
|
993 |
+
|
994 |
+
uint8 *m_pBuf;
|
995 |
+
uint64_t m_buf_size, m_buf_ofs;
|
996 |
+
|
997 |
+
public:
|
998 |
+
memory_stream(void *pBuf, uint64_t buf_size) : m_pBuf(static_cast<uint8*>(pBuf)), m_buf_size(buf_size), m_buf_ofs(0) { }
|
999 |
+
|
1000 |
+
virtual ~memory_stream() { }
|
1001 |
+
|
1002 |
+
virtual bool put_buf(const void* pBuf, int64_t len)
|
1003 |
+
{
|
1004 |
+
uint64_t buf_remaining = m_buf_size - m_buf_ofs;
|
1005 |
+
if ((uint64_t)len > buf_remaining)
|
1006 |
+
return false;
|
1007 |
+
memcpy(m_pBuf + m_buf_ofs, pBuf, len);
|
1008 |
+
m_buf_ofs += len;
|
1009 |
+
return true;
|
1010 |
+
}
|
1011 |
+
|
1012 |
+
uint64_t get_size() const
|
1013 |
+
{
|
1014 |
+
return m_buf_ofs;
|
1015 |
+
}
|
1016 |
+
};
|
1017 |
+
|
1018 |
+
bool compress_image_to_jpeg_file_in_memory(void *pDstBuf, int64_t &buf_size, int64_t width, int64_t height, int64_t num_channels, const uint8 *pImage_data, const params &comp_params)
|
1019 |
+
{
|
1020 |
+
if ((!pDstBuf) || (!buf_size))
|
1021 |
+
return false;
|
1022 |
+
|
1023 |
+
memory_stream dst_stream(pDstBuf, buf_size);
|
1024 |
+
|
1025 |
+
buf_size = 0;
|
1026 |
+
|
1027 |
+
jpge::jpeg_encoder dst_image;
|
1028 |
+
if (!dst_image.init(&dst_stream, width, height, num_channels, comp_params))
|
1029 |
+
return false;
|
1030 |
+
|
1031 |
+
for (uint pass_index = 0; pass_index < dst_image.get_total_passes(); pass_index++)
|
1032 |
+
{
|
1033 |
+
for (int64_t i = 0; i < height; i++)
|
1034 |
+
{
|
1035 |
+
const uint8* pScanline = pImage_data + i * width * num_channels;
|
1036 |
+
if (!dst_image.process_scanline(pScanline))
|
1037 |
+
return false;
|
1038 |
+
}
|
1039 |
+
if (!dst_image.process_scanline(NULL))
|
1040 |
+
return false;
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
dst_image.deinit();
|
1044 |
+
|
1045 |
+
buf_size = dst_stream.get_size();
|
1046 |
+
return true;
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
} // namespace jpge
|
crazy_functions/test_project/cpp/longcode/prod_cons.h
ADDED
@@ -0,0 +1,433 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#pragma once
|
2 |
+
|
3 |
+
#include <atomic>
|
4 |
+
#include <utility>
|
5 |
+
#include <cstring>
|
6 |
+
#include <type_traits>
|
7 |
+
#include <cstdint>
|
8 |
+
|
9 |
+
#include "libipc/def.h"
|
10 |
+
|
11 |
+
#include "libipc/platform/detail.h"
|
12 |
+
#include "libipc/circ/elem_def.h"
|
13 |
+
#include "libipc/utility/log.h"
|
14 |
+
#include "libipc/utility/utility.h"
|
15 |
+
|
16 |
+
namespace ipc {
|
17 |
+
|
18 |
+
////////////////////////////////////////////////////////////////
|
19 |
+
/// producer-consumer implementation
|
20 |
+
////////////////////////////////////////////////////////////////
|
21 |
+
|
22 |
+
template <typename Flag>
|
23 |
+
struct prod_cons_impl;
|
24 |
+
|
25 |
+
template <>
|
26 |
+
struct prod_cons_impl<wr<relat::single, relat::single, trans::unicast>> {
|
27 |
+
|
28 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
29 |
+
struct elem_t {
|
30 |
+
std::aligned_storage_t<DataSize, AlignSize> data_ {};
|
31 |
+
};
|
32 |
+
|
33 |
+
alignas(cache_line_size) std::atomic<circ::u2_t> rd_; // read index
|
34 |
+
alignas(cache_line_size) std::atomic<circ::u2_t> wt_; // write index
|
35 |
+
|
36 |
+
constexpr circ::u2_t cursor() const noexcept {
|
37 |
+
return 0;
|
38 |
+
}
|
39 |
+
|
40 |
+
template <typename W, typename F, typename E>
|
41 |
+
bool push(W* /*wrapper*/, F&& f, E* elems) {
|
42 |
+
auto cur_wt = circ::index_of(wt_.load(std::memory_order_relaxed));
|
43 |
+
if (cur_wt == circ::index_of(rd_.load(std::memory_order_acquire) - 1)) {
|
44 |
+
return false; // full
|
45 |
+
}
|
46 |
+
std::forward<F>(f)(&(elems[cur_wt].data_));
|
47 |
+
wt_.fetch_add(1, std::memory_order_release);
|
48 |
+
return true;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* In single-single-unicast, 'force_push' means 'no reader' or 'the only one reader is dead'.
|
53 |
+
* So we could just disconnect all connections of receiver, and return false.
|
54 |
+
*/
|
55 |
+
template <typename W, typename F, typename E>
|
56 |
+
bool force_push(W* wrapper, F&&, E*) {
|
57 |
+
wrapper->elems()->disconnect_receiver(~static_cast<circ::cc_t>(0u));
|
58 |
+
return false;
|
59 |
+
}
|
60 |
+
|
61 |
+
template <typename W, typename F, typename R, typename E>
|
62 |
+
bool pop(W* /*wrapper*/, circ::u2_t& /*cur*/, F&& f, R&& out, E* elems) {
|
63 |
+
auto cur_rd = circ::index_of(rd_.load(std::memory_order_relaxed));
|
64 |
+
if (cur_rd == circ::index_of(wt_.load(std::memory_order_acquire))) {
|
65 |
+
return false; // empty
|
66 |
+
}
|
67 |
+
std::forward<F>(f)(&(elems[cur_rd].data_));
|
68 |
+
std::forward<R>(out)(true);
|
69 |
+
rd_.fetch_add(1, std::memory_order_release);
|
70 |
+
return true;
|
71 |
+
}
|
72 |
+
};
|
73 |
+
|
74 |
+
template <>
|
75 |
+
struct prod_cons_impl<wr<relat::single, relat::multi , trans::unicast>>
|
76 |
+
: prod_cons_impl<wr<relat::single, relat::single, trans::unicast>> {
|
77 |
+
|
78 |
+
template <typename W, typename F, typename E>
|
79 |
+
bool force_push(W* wrapper, F&&, E*) {
|
80 |
+
wrapper->elems()->disconnect_receiver(1);
|
81 |
+
return false;
|
82 |
+
}
|
83 |
+
|
84 |
+
template <typename W, typename F, typename R,
|
85 |
+
template <std::size_t, std::size_t> class E, std::size_t DS, std::size_t AS>
|
86 |
+
bool pop(W* /*wrapper*/, circ::u2_t& /*cur*/, F&& f, R&& out, E<DS, AS>* elems) {
|
87 |
+
byte_t buff[DS];
|
88 |
+
for (unsigned k = 0;;) {
|
89 |
+
auto cur_rd = rd_.load(std::memory_order_relaxed);
|
90 |
+
if (circ::index_of(cur_rd) ==
|
91 |
+
circ::index_of(wt_.load(std::memory_order_acquire))) {
|
92 |
+
return false; // empty
|
93 |
+
}
|
94 |
+
std::memcpy(buff, &(elems[circ::index_of(cur_rd)].data_), sizeof(buff));
|
95 |
+
if (rd_.compare_exchange_weak(cur_rd, cur_rd + 1, std::memory_order_release)) {
|
96 |
+
std::forward<F>(f)(buff);
|
97 |
+
std::forward<R>(out)(true);
|
98 |
+
return true;
|
99 |
+
}
|
100 |
+
ipc::yield(k);
|
101 |
+
}
|
102 |
+
}
|
103 |
+
};
|
104 |
+
|
105 |
+
template <>
|
106 |
+
struct prod_cons_impl<wr<relat::multi , relat::multi, trans::unicast>>
|
107 |
+
: prod_cons_impl<wr<relat::single, relat::multi, trans::unicast>> {
|
108 |
+
|
109 |
+
using flag_t = std::uint64_t;
|
110 |
+
|
111 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
112 |
+
struct elem_t {
|
113 |
+
std::aligned_storage_t<DataSize, AlignSize> data_ {};
|
114 |
+
std::atomic<flag_t> f_ct_ { 0 }; // commit flag
|
115 |
+
};
|
116 |
+
|
117 |
+
alignas(cache_line_size) std::atomic<circ::u2_t> ct_; // commit index
|
118 |
+
|
119 |
+
template <typename W, typename F, typename E>
|
120 |
+
bool push(W* /*wrapper*/, F&& f, E* elems) {
|
121 |
+
circ::u2_t cur_ct, nxt_ct;
|
122 |
+
for (unsigned k = 0;;) {
|
123 |
+
cur_ct = ct_.load(std::memory_order_relaxed);
|
124 |
+
if (circ::index_of(nxt_ct = cur_ct + 1) ==
|
125 |
+
circ::index_of(rd_.load(std::memory_order_acquire))) {
|
126 |
+
return false; // full
|
127 |
+
}
|
128 |
+
if (ct_.compare_exchange_weak(cur_ct, nxt_ct, std::memory_order_acq_rel)) {
|
129 |
+
break;
|
130 |
+
}
|
131 |
+
ipc::yield(k);
|
132 |
+
}
|
133 |
+
auto* el = elems + circ::index_of(cur_ct);
|
134 |
+
std::forward<F>(f)(&(el->data_));
|
135 |
+
// set flag & try update wt
|
136 |
+
el->f_ct_.store(~static_cast<flag_t>(cur_ct), std::memory_order_release);
|
137 |
+
while (1) {
|
138 |
+
auto cac_ct = el->f_ct_.load(std::memory_order_acquire);
|
139 |
+
if (cur_ct != wt_.load(std::memory_order_relaxed)) {
|
140 |
+
return true;
|
141 |
+
}
|
142 |
+
if ((~cac_ct) != cur_ct) {
|
143 |
+
return true;
|
144 |
+
}
|
145 |
+
if (!el->f_ct_.compare_exchange_strong(cac_ct, 0, std::memory_order_relaxed)) {
|
146 |
+
return true;
|
147 |
+
}
|
148 |
+
wt_.store(nxt_ct, std::memory_order_release);
|
149 |
+
cur_ct = nxt_ct;
|
150 |
+
nxt_ct = cur_ct + 1;
|
151 |
+
el = elems + circ::index_of(cur_ct);
|
152 |
+
}
|
153 |
+
return true;
|
154 |
+
}
|
155 |
+
|
156 |
+
template <typename W, typename F, typename E>
|
157 |
+
bool force_push(W* wrapper, F&&, E*) {
|
158 |
+
wrapper->elems()->disconnect_receiver(1);
|
159 |
+
return false;
|
160 |
+
}
|
161 |
+
|
162 |
+
template <typename W, typename F, typename R,
|
163 |
+
template <std::size_t, std::size_t> class E, std::size_t DS, std::size_t AS>
|
164 |
+
bool pop(W* /*wrapper*/, circ::u2_t& /*cur*/, F&& f, R&& out, E<DS, AS>* elems) {
|
165 |
+
byte_t buff[DS];
|
166 |
+
for (unsigned k = 0;;) {
|
167 |
+
auto cur_rd = rd_.load(std::memory_order_relaxed);
|
168 |
+
auto cur_wt = wt_.load(std::memory_order_acquire);
|
169 |
+
auto id_rd = circ::index_of(cur_rd);
|
170 |
+
auto id_wt = circ::index_of(cur_wt);
|
171 |
+
if (id_rd == id_wt) {
|
172 |
+
auto* el = elems + id_wt;
|
173 |
+
auto cac_ct = el->f_ct_.load(std::memory_order_acquire);
|
174 |
+
if ((~cac_ct) != cur_wt) {
|
175 |
+
return false; // empty
|
176 |
+
}
|
177 |
+
if (el->f_ct_.compare_exchange_weak(cac_ct, 0, std::memory_order_relaxed)) {
|
178 |
+
wt_.store(cur_wt + 1, std::memory_order_release);
|
179 |
+
}
|
180 |
+
k = 0;
|
181 |
+
}
|
182 |
+
else {
|
183 |
+
std::memcpy(buff, &(elems[circ::index_of(cur_rd)].data_), sizeof(buff));
|
184 |
+
if (rd_.compare_exchange_weak(cur_rd, cur_rd + 1, std::memory_order_release)) {
|
185 |
+
std::forward<F>(f)(buff);
|
186 |
+
std::forward<R>(out)(true);
|
187 |
+
return true;
|
188 |
+
}
|
189 |
+
ipc::yield(k);
|
190 |
+
}
|
191 |
+
}
|
192 |
+
}
|
193 |
+
};
|
194 |
+
|
195 |
+
template <>
|
196 |
+
struct prod_cons_impl<wr<relat::single, relat::multi, trans::broadcast>> {
|
197 |
+
|
198 |
+
using rc_t = std::uint64_t;
|
199 |
+
|
200 |
+
enum : rc_t {
|
201 |
+
ep_mask = 0x00000000ffffffffull,
|
202 |
+
ep_incr = 0x0000000100000000ull
|
203 |
+
};
|
204 |
+
|
205 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
206 |
+
struct elem_t {
|
207 |
+
std::aligned_storage_t<DataSize, AlignSize> data_ {};
|
208 |
+
std::atomic<rc_t> rc_ { 0 }; // read-counter
|
209 |
+
};
|
210 |
+
|
211 |
+
alignas(cache_line_size) std::atomic<circ::u2_t> wt_; // write index
|
212 |
+
alignas(cache_line_size) rc_t epoch_ { 0 }; // only one writer
|
213 |
+
|
214 |
+
circ::u2_t cursor() const noexcept {
|
215 |
+
return wt_.load(std::memory_order_acquire);
|
216 |
+
}
|
217 |
+
|
218 |
+
template <typename W, typename F, typename E>
|
219 |
+
bool push(W* wrapper, F&& f, E* elems) {
|
220 |
+
E* el;
|
221 |
+
for (unsigned k = 0;;) {
|
222 |
+
circ::cc_t cc = wrapper->elems()->connections(std::memory_order_relaxed);
|
223 |
+
if (cc == 0) return false; // no reader
|
224 |
+
el = elems + circ::index_of(wt_.load(std::memory_order_relaxed));
|
225 |
+
// check all consumers have finished reading this element
|
226 |
+
auto cur_rc = el->rc_.load(std::memory_order_acquire);
|
227 |
+
circ::cc_t rem_cc = cur_rc & ep_mask;
|
228 |
+
if ((cc & rem_cc) && ((cur_rc & ~ep_mask) == epoch_)) {
|
229 |
+
return false; // has not finished yet
|
230 |
+
}
|
231 |
+
// consider rem_cc to be 0 here
|
232 |
+
if (el->rc_.compare_exchange_weak(
|
233 |
+
cur_rc, epoch_ | static_cast<rc_t>(cc), std::memory_order_release)) {
|
234 |
+
break;
|
235 |
+
}
|
236 |
+
ipc::yield(k);
|
237 |
+
}
|
238 |
+
std::forward<F>(f)(&(el->data_));
|
239 |
+
wt_.fetch_add(1, std::memory_order_release);
|
240 |
+
return true;
|
241 |
+
}
|
242 |
+
|
243 |
+
template <typename W, typename F, typename E>
|
244 |
+
bool force_push(W* wrapper, F&& f, E* elems) {
|
245 |
+
E* el;
|
246 |
+
epoch_ += ep_incr;
|
247 |
+
for (unsigned k = 0;;) {
|
248 |
+
circ::cc_t cc = wrapper->elems()->connections(std::memory_order_relaxed);
|
249 |
+
if (cc == 0) return false; // no reader
|
250 |
+
el = elems + circ::index_of(wt_.load(std::memory_order_relaxed));
|
251 |
+
// check all consumers have finished reading this element
|
252 |
+
auto cur_rc = el->rc_.load(std::memory_order_acquire);
|
253 |
+
circ::cc_t rem_cc = cur_rc & ep_mask;
|
254 |
+
if (cc & rem_cc) {
|
255 |
+
ipc::log("force_push: k = %u, cc = %u, rem_cc = %u\n", k, cc, rem_cc);
|
256 |
+
cc = wrapper->elems()->disconnect_receiver(rem_cc); // disconnect all invalid readers
|
257 |
+
if (cc == 0) return false; // no reader
|
258 |
+
}
|
259 |
+
// just compare & exchange
|
260 |
+
if (el->rc_.compare_exchange_weak(
|
261 |
+
cur_rc, epoch_ | static_cast<rc_t>(cc), std::memory_order_release)) {
|
262 |
+
break;
|
263 |
+
}
|
264 |
+
ipc::yield(k);
|
265 |
+
}
|
266 |
+
std::forward<F>(f)(&(el->data_));
|
267 |
+
wt_.fetch_add(1, std::memory_order_release);
|
268 |
+
return true;
|
269 |
+
}
|
270 |
+
|
271 |
+
template <typename W, typename F, typename R, typename E>
|
272 |
+
bool pop(W* wrapper, circ::u2_t& cur, F&& f, R&& out, E* elems) {
|
273 |
+
if (cur == cursor()) return false; // acquire
|
274 |
+
auto* el = elems + circ::index_of(cur++);
|
275 |
+
std::forward<F>(f)(&(el->data_));
|
276 |
+
for (unsigned k = 0;;) {
|
277 |
+
auto cur_rc = el->rc_.load(std::memory_order_acquire);
|
278 |
+
if ((cur_rc & ep_mask) == 0) {
|
279 |
+
std::forward<R>(out)(true);
|
280 |
+
return true;
|
281 |
+
}
|
282 |
+
auto nxt_rc = cur_rc & ~static_cast<rc_t>(wrapper->connected_id());
|
283 |
+
if (el->rc_.compare_exchange_weak(cur_rc, nxt_rc, std::memory_order_release)) {
|
284 |
+
std::forward<R>(out)((nxt_rc & ep_mask) == 0);
|
285 |
+
return true;
|
286 |
+
}
|
287 |
+
ipc::yield(k);
|
288 |
+
}
|
289 |
+
}
|
290 |
+
};
|
291 |
+
|
292 |
+
template <>
|
293 |
+
struct prod_cons_impl<wr<relat::multi, relat::multi, trans::broadcast>> {
|
294 |
+
|
295 |
+
using rc_t = std::uint64_t;
|
296 |
+
using flag_t = std::uint64_t;
|
297 |
+
|
298 |
+
enum : rc_t {
|
299 |
+
rc_mask = 0x00000000ffffffffull,
|
300 |
+
ep_mask = 0x00ffffffffffffffull,
|
301 |
+
ep_incr = 0x0100000000000000ull,
|
302 |
+
ic_mask = 0xff000000ffffffffull,
|
303 |
+
ic_incr = 0x0000000100000000ull
|
304 |
+
};
|
305 |
+
|
306 |
+
template <std::size_t DataSize, std::size_t AlignSize>
|
307 |
+
struct elem_t {
|
308 |
+
std::aligned_storage_t<DataSize, AlignSize> data_ {};
|
309 |
+
std::atomic<rc_t > rc_ { 0 }; // read-counter
|
310 |
+
std::atomic<flag_t> f_ct_ { 0 }; // commit flag
|
311 |
+
};
|
312 |
+
|
313 |
+
alignas(cache_line_size) std::atomic<circ::u2_t> ct_; // commit index
|
314 |
+
alignas(cache_line_size) std::atomic<rc_t> epoch_ { 0 };
|
315 |
+
|
316 |
+
circ::u2_t cursor() const noexcept {
|
317 |
+
return ct_.load(std::memory_order_acquire);
|
318 |
+
}
|
319 |
+
|
320 |
+
constexpr static rc_t inc_rc(rc_t rc) noexcept {
|
321 |
+
return (rc & ic_mask) | ((rc + ic_incr) & ~ic_mask);
|
322 |
+
}
|
323 |
+
|
324 |
+
constexpr static rc_t inc_mask(rc_t rc) noexcept {
|
325 |
+
return inc_rc(rc) & ~rc_mask;
|
326 |
+
}
|
327 |
+
|
328 |
+
template <typename W, typename F, typename E>
|
329 |
+
bool push(W* wrapper, F&& f, E* elems) {
|
330 |
+
E* el;
|
331 |
+
circ::u2_t cur_ct;
|
332 |
+
rc_t epoch = epoch_.load(std::memory_order_acquire);
|
333 |
+
for (unsigned k = 0;;) {
|
334 |
+
circ::cc_t cc = wrapper->elems()->connections(std::memory_order_relaxed);
|
335 |
+
if (cc == 0) return false; // no reader
|
336 |
+
el = elems + circ::index_of(cur_ct = ct_.load(std::memory_order_relaxed));
|
337 |
+
// check all consumers have finished reading this element
|
338 |
+
auto cur_rc = el->rc_.load(std::memory_order_relaxed);
|
339 |
+
circ::cc_t rem_cc = cur_rc & rc_mask;
|
340 |
+
if ((cc & rem_cc) && ((cur_rc & ~ep_mask) == epoch)) {
|
341 |
+
return false; // has not finished yet
|
342 |
+
}
|
343 |
+
else if (!rem_cc) {
|
344 |
+
auto cur_fl = el->f_ct_.load(std::memory_order_acquire);
|
345 |
+
if ((cur_fl != cur_ct) && cur_fl) {
|
346 |
+
return false; // full
|
347 |
+
}
|
348 |
+
}
|
349 |
+
// consider rem_cc to be 0 here
|
350 |
+
if (el->rc_.compare_exchange_weak(
|
351 |
+
cur_rc, inc_mask(epoch | (cur_rc & ep_mask)) | static_cast<rc_t>(cc), std::memory_order_relaxed) &&
|
352 |
+
epoch_.compare_exchange_weak(epoch, epoch, std::memory_order_acq_rel)) {
|
353 |
+
break;
|
354 |
+
}
|
355 |
+
ipc::yield(k);
|
356 |
+
}
|
357 |
+
// only one thread/process would touch here at one time
|
358 |
+
ct_.store(cur_ct + 1, std::memory_order_release);
|
359 |
+
std::forward<F>(f)(&(el->data_));
|
360 |
+
// set flag & try update wt
|
361 |
+
el->f_ct_.store(~static_cast<flag_t>(cur_ct), std::memory_order_release);
|
362 |
+
return true;
|
363 |
+
}
|
364 |
+
|
365 |
+
template <typename W, typename F, typename E>
|
366 |
+
bool force_push(W* wrapper, F&& f, E* elems) {
|
367 |
+
E* el;
|
368 |
+
circ::u2_t cur_ct;
|
369 |
+
rc_t epoch = epoch_.fetch_add(ep_incr, std::memory_order_release) + ep_incr;
|
370 |
+
for (unsigned k = 0;;) {
|
371 |
+
circ::cc_t cc = wrapper->elems()->connections(std::memory_order_relaxed);
|
372 |
+
if (cc == 0) return false; // no reader
|
373 |
+
el = elems + circ::index_of(cur_ct = ct_.load(std::memory_order_relaxed));
|
374 |
+
// check all consumers have finished reading this element
|
375 |
+
auto cur_rc = el->rc_.load(std::memory_order_acquire);
|
376 |
+
circ::cc_t rem_cc = cur_rc & rc_mask;
|
377 |
+
if (cc & rem_cc) {
|
378 |
+
ipc::log("force_push: k = %u, cc = %u, rem_cc = %u\n", k, cc, rem_cc);
|
379 |
+
cc = wrapper->elems()->disconnect_receiver(rem_cc); // disconnect all invalid readers
|
380 |
+
if (cc == 0) return false; // no reader
|
381 |
+
}
|
382 |
+
// just compare & exchange
|
383 |
+
if (el->rc_.compare_exchange_weak(
|
384 |
+
cur_rc, inc_mask(epoch | (cur_rc & ep_mask)) | static_cast<rc_t>(cc), std::memory_order_relaxed)) {
|
385 |
+
if (epoch == epoch_.load(std::memory_order_acquire)) {
|
386 |
+
break;
|
387 |
+
}
|
388 |
+
else if (push(wrapper, std::forward<F>(f), elems)) {
|
389 |
+
return true;
|
390 |
+
}
|
391 |
+
epoch = epoch_.fetch_add(ep_incr, std::memory_order_release) + ep_incr;
|
392 |
+
}
|
393 |
+
ipc::yield(k);
|
394 |
+
}
|
395 |
+
// only one thread/process would touch here at one time
|
396 |
+
ct_.store(cur_ct + 1, std::memory_order_release);
|
397 |
+
std::forward<F>(f)(&(el->data_));
|
398 |
+
// set flag & try update wt
|
399 |
+
el->f_ct_.store(~static_cast<flag_t>(cur_ct), std::memory_order_release);
|
400 |
+
return true;
|
401 |
+
}
|
402 |
+
|
403 |
+
template <typename W, typename F, typename R, typename E, std::size_t N>
|
404 |
+
bool pop(W* wrapper, circ::u2_t& cur, F&& f, R&& out, E(& elems)[N]) {
|
405 |
+
auto* el = elems + circ::index_of(cur);
|
406 |
+
auto cur_fl = el->f_ct_.load(std::memory_order_acquire);
|
407 |
+
if (cur_fl != ~static_cast<flag_t>(cur)) {
|
408 |
+
return false; // empty
|
409 |
+
}
|
410 |
+
++cur;
|
411 |
+
std::forward<F>(f)(&(el->data_));
|
412 |
+
for (unsigned k = 0;;) {
|
413 |
+
auto cur_rc = el->rc_.load(std::memory_order_acquire);
|
414 |
+
if ((cur_rc & rc_mask) == 0) {
|
415 |
+
std::forward<R>(out)(true);
|
416 |
+
el->f_ct_.store(cur + N - 1, std::memory_order_release);
|
417 |
+
return true;
|
418 |
+
}
|
419 |
+
auto nxt_rc = inc_rc(cur_rc) & ~static_cast<rc_t>(wrapper->connected_id());
|
420 |
+
bool last_one = false;
|
421 |
+
if ((last_one = (nxt_rc & rc_mask) == 0)) {
|
422 |
+
el->f_ct_.store(cur + N - 1, std::memory_order_release);
|
423 |
+
}
|
424 |
+
if (el->rc_.compare_exchange_weak(cur_rc, nxt_rc, std::memory_order_release)) {
|
425 |
+
std::forward<R>(out)(last_one);
|
426 |
+
return true;
|
427 |
+
}
|
428 |
+
ipc::yield(k);
|
429 |
+
}
|
430 |
+
}
|
431 |
+
};
|
432 |
+
|
433 |
+
} // namespace ipc
|
crazy_functions/高级功能函数模板.py
CHANGED
@@ -11,7 +11,7 @@ def 高阶功能模板函数(txt, top_p, temperature, chatbot, history, systemPr
|
|
11 |
for i in range(5):
|
12 |
currentMonth = (datetime.date.today() + datetime.timedelta(days=i)).month
|
13 |
currentDay = (datetime.date.today() + datetime.timedelta(days=i)).day
|
14 |
-
i_say = f'历史中哪些事件发生在{currentMonth}月{currentDay}日?列举两条并发送相关图片。发送图片时,请使用Markdown,将Unsplash API中的PUT_YOUR_QUERY_HERE
|
15 |
chatbot.append((i_say, "[Local Message] waiting gpt response."))
|
16 |
yield chatbot, history, '正常' # 由于请求gpt需要一段时间,我们先及时地做一次状态显示
|
17 |
|
|
|
11 |
for i in range(5):
|
12 |
currentMonth = (datetime.date.today() + datetime.timedelta(days=i)).month
|
13 |
currentDay = (datetime.date.today() + datetime.timedelta(days=i)).day
|
14 |
+
i_say = f'历史中哪些事件发生在{currentMonth}月{currentDay}日?列举两条并发送相关图片。发送图片时,请使用Markdown,将Unsplash API中的PUT_YOUR_QUERY_HERE替换成描述该事件的一个最重要的单词。'
|
15 |
chatbot.append((i_say, "[Local Message] waiting gpt response."))
|
16 |
yield chatbot, history, '正常' # 由于请求gpt需要一段时间,我们先及时地做一次状态显示
|
17 |
|
functional_crazy.py
CHANGED
@@ -19,10 +19,10 @@ def get_crazy_functionals():
|
|
19 |
|
20 |
function_plugins = {
|
21 |
"请解析并解构此项目本身": {
|
22 |
-
#
|
23 |
"Function": 解析项目本身
|
24 |
},
|
25 |
-
"解析整个
|
26 |
"Color": "stop", # 按钮颜色
|
27 |
"Function": 解析一个Python项目
|
28 |
},
|
@@ -32,9 +32,10 @@ def get_crazy_functionals():
|
|
32 |
},
|
33 |
"解析整个C++项目": {
|
34 |
"Color": "stop", # 按钮颜色
|
|
|
35 |
"Function": 解析一个C项目
|
36 |
},
|
37 |
-
"读
|
38 |
"Color": "stop", # 按钮颜色
|
39 |
"Function": 读文章写摘要
|
40 |
},
|
@@ -52,7 +53,7 @@ def get_crazy_functionals():
|
|
52 |
},
|
53 |
}
|
54 |
|
55 |
-
# VisibleLevel=1
|
56 |
if UserVisibleLevel >= 1:
|
57 |
from crazy_functions.批量总结PDF文档 import 批量总结PDF文档
|
58 |
from crazy_functions.批量总结PDF文档pdfminer import 批量总结PDF文档pdfminer
|
@@ -60,11 +61,11 @@ def get_crazy_functionals():
|
|
60 |
function_plugins.update({
|
61 |
"[仅供开发调试] 批量总结PDF文档": {
|
62 |
"Color": "stop",
|
63 |
-
# HotReload 的意思是热更新,修改函数插件代码后,不需要重启程序,代码直接生效
|
64 |
-
"Function": HotReload(批量总结PDF文档)
|
65 |
},
|
66 |
"[仅供开发调试] 批量总结PDF文档pdfminer": {
|
67 |
"Color": "stop",
|
|
|
68 |
"Function": HotReload(批量总结PDF文档pdfminer)
|
69 |
},
|
70 |
"[仅供开发调试] 批量总结Word文档": {
|
|
|
19 |
|
20 |
function_plugins = {
|
21 |
"请解析并解构此项目本身": {
|
22 |
+
"AsButton": False, # 加入下拉菜单中
|
23 |
"Function": 解析项目本身
|
24 |
},
|
25 |
+
"解析整个Py项目": {
|
26 |
"Color": "stop", # 按钮颜色
|
27 |
"Function": 解析一个Python项目
|
28 |
},
|
|
|
32 |
},
|
33 |
"解析整个C++项目": {
|
34 |
"Color": "stop", # 按钮颜色
|
35 |
+
"AsButton": False, # 加入下拉菜单中
|
36 |
"Function": 解析一个C项目
|
37 |
},
|
38 |
+
"读Tex论文写摘要": {
|
39 |
"Color": "stop", # 按钮颜色
|
40 |
"Function": 读文章写摘要
|
41 |
},
|
|
|
53 |
},
|
54 |
}
|
55 |
|
56 |
+
# VisibleLevel=1 经过测试,但功能上距离达到完美状态还差一点点
|
57 |
if UserVisibleLevel >= 1:
|
58 |
from crazy_functions.批量总结PDF文档 import 批量总结PDF文档
|
59 |
from crazy_functions.批量总结PDF文档pdfminer import 批量总结PDF文档pdfminer
|
|
|
61 |
function_plugins.update({
|
62 |
"[仅供开发调试] 批量总结PDF文档": {
|
63 |
"Color": "stop",
|
64 |
+
"Function": HotReload(批量总结PDF文档) # HotReload 的意思是热更新,修改函数插件代码后,不需要重启程序,代码直接生效
|
|
|
65 |
},
|
66 |
"[仅供开发调试] 批量总结PDF文档pdfminer": {
|
67 |
"Color": "stop",
|
68 |
+
"AsButton": False, # 加入下拉菜单中
|
69 |
"Function": HotReload(批量总结PDF文档pdfminer)
|
70 |
},
|
71 |
"[仅供开发调试] 批量总结Word文档": {
|
main.py
CHANGED
@@ -4,9 +4,8 @@ from predict import predict
|
|
4 |
from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf
|
5 |
|
6 |
# 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到
|
7 |
-
proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION = \
|
8 |
-
get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION')
|
9 |
-
|
10 |
|
11 |
# 如果WEB_PORT是-1, 则随机选取WEB端口
|
12 |
PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT
|
@@ -17,18 +16,18 @@ title_html = """<h1 align="center">ChatGPT 学术优化</h1>"""
|
|
17 |
|
18 |
# 问询记录, python 版本建议3.9+(越新越好)
|
19 |
import logging
|
20 |
-
os.makedirs(
|
21 |
-
try:logging.basicConfig(filename=
|
22 |
-
except:logging.basicConfig(filename=
|
23 |
-
print(
|
24 |
|
25 |
# 一些普通功能模块
|
26 |
from functional import get_functionals
|
27 |
functional = get_functionals()
|
28 |
|
29 |
-
#
|
30 |
from functional_crazy import get_crazy_functionals
|
31 |
-
|
32 |
|
33 |
# 处理markdown文本格式的转变
|
34 |
gr.Chatbot.postprocess = format_io
|
@@ -40,11 +39,10 @@ set_theme = adjust_theme()
|
|
40 |
cancel_handles = []
|
41 |
with gr.Blocks(theme=set_theme, analytics_enabled=False) as demo:
|
42 |
gr.HTML(title_html)
|
43 |
-
with gr.Row():
|
44 |
with gr.Column(scale=2):
|
45 |
chatbot = gr.Chatbot()
|
46 |
-
chatbot.style(height=
|
47 |
-
chatbot.style()
|
48 |
history = gr.State([])
|
49 |
with gr.Column(scale=1):
|
50 |
with gr.Row():
|
@@ -66,49 +64,70 @@ with gr.Blocks(theme=set_theme, analytics_enabled=False) as demo:
|
|
66 |
with gr.Row():
|
67 |
gr.Markdown("注意:以下“红颜色”标识的函数插件需从input区读取路径作为参数.")
|
68 |
with gr.Row():
|
69 |
-
for k in
|
70 |
-
|
71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
with gr.Row():
|
73 |
-
with gr.Accordion("
|
74 |
-
file_upload = gr.Files(label=
|
75 |
with gr.Accordion("展开SysPrompt & GPT参数 & 交互界面布局", open=False):
|
76 |
system_prompt = gr.Textbox(show_label=True, placeholder=f"System Prompt", label="System prompt", value=initial_prompt)
|
77 |
top_p = gr.Slider(minimum=-0, maximum=1.0, value=1.0, step=0.01,interactive=True, label="Top-p (nucleus sampling)",)
|
78 |
temperature = gr.Slider(minimum=-0, maximum=2.0, value=1.0, step=0.01, interactive=True, label="Temperature",)
|
79 |
-
checkboxes = gr.CheckboxGroup(["基础功能区", "函数插件区"],
|
80 |
-
value=["基础功能区", "函数插件区"], label="显示哪些功能区")
|
81 |
|
82 |
-
|
|
|
83 |
ret = {}
|
84 |
-
|
85 |
-
ret.update({
|
86 |
-
# if area_crazy_fn.visible != ("函数插件区" in a):
|
87 |
-
ret.update({area_crazy_fn: gr.update(visible=("函数插件区" in a))})
|
88 |
return ret
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
|
|
93 |
empty_txt_args = dict(fn=lambda: "", inputs=[], outputs=[txt]) # 用于在提交后清空输入栏
|
94 |
-
|
95 |
-
cancel_handles.append(txt.submit(**predict_args))
|
96 |
-
|
97 |
-
|
98 |
-
#
|
99 |
-
resetBtn.click(lambda: ([], [], "已重置"), None, [chatbot, history, statusDisplay])
|
100 |
for k in functional:
|
101 |
-
click_handle = functional[k]["Button"].click(predict,
|
102 |
-
[txt, top_p, temperature, chatbot, history, system_prompt, gr.State(True), gr.State(k)], [chatbot, history, statusDisplay], show_progress=True)
|
103 |
cancel_handles.append(click_handle)
|
|
|
104 |
file_upload.upload(on_file_uploaded, [file_upload, chatbot, txt], [chatbot, txt])
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
)
|
109 |
-
|
110 |
-
except: pass
|
111 |
cancel_handles.append(click_handle)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
stopBtn.click(fn=None, inputs=None, outputs=None, cancels=cancel_handles)
|
113 |
|
114 |
# gradio的inbrowser触发不太稳定,回滚代码到原始的浏览器打开函数
|
@@ -117,7 +136,7 @@ def auto_opentab_delay():
|
|
117 |
print(f"如果浏览器没有自动打开,请复制并转到以下URL: http://localhost:{PORT}")
|
118 |
def open():
|
119 |
time.sleep(2)
|
120 |
-
webbrowser.open_new_tab(f
|
121 |
threading.Thread(target=open, name="open-browser", daemon=True).start()
|
122 |
|
123 |
auto_opentab_delay()
|
|
|
4 |
from toolbox import format_io, find_free_port, on_file_uploaded, on_report_generated, get_conf
|
5 |
|
6 |
# 建议您复制一个config_private.py放自己的秘密, 如API和代理网址, 避免不小心传github被别人看到
|
7 |
+
proxies, WEB_PORT, LLM_MODEL, CONCURRENT_COUNT, AUTHENTICATION, CHATBOT_HEIGHT = \
|
8 |
+
get_conf('proxies', 'WEB_PORT', 'LLM_MODEL', 'CONCURRENT_COUNT', 'AUTHENTICATION', 'CHATBOT_HEIGHT')
|
|
|
9 |
|
10 |
# 如果WEB_PORT是-1, 则随机选取WEB端口
|
11 |
PORT = find_free_port() if WEB_PORT <= 0 else WEB_PORT
|
|
|
16 |
|
17 |
# 问询记录, python 版本建议3.9+(越新越好)
|
18 |
import logging
|
19 |
+
os.makedirs("gpt_log", exist_ok=True)
|
20 |
+
try:logging.basicConfig(filename="gpt_log/chat_secrets.log", level=logging.INFO, encoding="utf-8")
|
21 |
+
except:logging.basicConfig(filename="gpt_log/chat_secrets.log", level=logging.INFO)
|
22 |
+
print("所有问询记录将自动保存在本地目录./gpt_log/chat_secrets.log, 请注意自我隐私保护哦!")
|
23 |
|
24 |
# 一些普通功能模块
|
25 |
from functional import get_functionals
|
26 |
functional = get_functionals()
|
27 |
|
28 |
+
# 高级函数插件
|
29 |
from functional_crazy import get_crazy_functionals
|
30 |
+
crazy_fns = get_crazy_functionals()
|
31 |
|
32 |
# 处理markdown文本格式的转变
|
33 |
gr.Chatbot.postprocess = format_io
|
|
|
39 |
cancel_handles = []
|
40 |
with gr.Blocks(theme=set_theme, analytics_enabled=False) as demo:
|
41 |
gr.HTML(title_html)
|
42 |
+
with gr.Row().style(equal_height=True):
|
43 |
with gr.Column(scale=2):
|
44 |
chatbot = gr.Chatbot()
|
45 |
+
chatbot.style(height=CHATBOT_HEIGHT)
|
|
|
46 |
history = gr.State([])
|
47 |
with gr.Column(scale=1):
|
48 |
with gr.Row():
|
|
|
64 |
with gr.Row():
|
65 |
gr.Markdown("注意:以下“红颜色”标识的函数插件需从input区读取路径作为参数.")
|
66 |
with gr.Row():
|
67 |
+
for k in crazy_fns:
|
68 |
+
if not crazy_fns[k].get("AsButton", True): continue
|
69 |
+
variant = crazy_fns[k]["Color"] if "Color" in crazy_fns[k] else "secondary"
|
70 |
+
crazy_fns[k]["Button"] = gr.Button(k, variant=variant)
|
71 |
+
with gr.Row():
|
72 |
+
with gr.Accordion("更多函数插件", open=True):
|
73 |
+
dropdown_fn_list = [k for k in crazy_fns.keys() if not crazy_fns[k].get("AsButton", True)]
|
74 |
+
with gr.Column(scale=1):
|
75 |
+
dropdown = gr.Dropdown(dropdown_fn_list, value=r"打开插件列表", label="").style(container=False)
|
76 |
+
with gr.Column(scale=1):
|
77 |
+
switchy_bt = gr.Button(r"请先从插件列表中选择", variant="secondary")
|
78 |
with gr.Row():
|
79 |
+
with gr.Accordion("点击展开“文件上传区”。上传本地文件可供红色函数插件调用。", open=False) as area_file_up:
|
80 |
+
file_upload = gr.Files(label="任何文件, 但推荐上传压缩文件(zip, tar)", file_count="multiple")
|
81 |
with gr.Accordion("展开SysPrompt & GPT参数 & 交互界面布局", open=False):
|
82 |
system_prompt = gr.Textbox(show_label=True, placeholder=f"System Prompt", label="System prompt", value=initial_prompt)
|
83 |
top_p = gr.Slider(minimum=-0, maximum=1.0, value=1.0, step=0.01,interactive=True, label="Top-p (nucleus sampling)",)
|
84 |
temperature = gr.Slider(minimum=-0, maximum=2.0, value=1.0, step=0.01, interactive=True, label="Temperature",)
|
85 |
+
checkboxes = gr.CheckboxGroup(["基础功能区", "函数插件区"], value=["基础功能区", "函数插件区"], label="显示/隐藏功能区")
|
|
|
86 |
|
87 |
+
# 功能区显示开关与功能区的互动
|
88 |
+
def fn_area_visibility(a):
|
89 |
ret = {}
|
90 |
+
ret.update({area_basic_fn: gr.update(visible=("基础功能区" in a))})
|
91 |
+
ret.update({area_crazy_fn: gr.update(visible=("函数插件区" in a))})
|
|
|
|
|
92 |
return ret
|
93 |
+
checkboxes.select(fn_area_visibility, [checkboxes], [area_basic_fn, area_crazy_fn] )
|
94 |
+
# 整理反复出现的控件句柄组合
|
95 |
+
input_combo = [txt, top_p, temperature, chatbot, history, system_prompt]
|
96 |
+
output_combo = [chatbot, history, statusDisplay]
|
97 |
+
predict_args = dict(fn=predict, inputs=input_combo, outputs=output_combo, show_progress=True)
|
98 |
empty_txt_args = dict(fn=lambda: "", inputs=[], outputs=[txt]) # 用于在提交后清空输入栏
|
99 |
+
# 提交按钮、重置按钮
|
100 |
+
cancel_handles.append(txt.submit(**predict_args)) #; txt.submit(**empty_txt_args) 在提交后清空输入栏
|
101 |
+
cancel_handles.append(submitBtn.click(**predict_args)) #; submitBtn.click(**empty_txt_args) 在提交后清空输入栏
|
102 |
+
resetBtn.click(lambda: ([], [], "已重置"), None, output_combo)
|
103 |
+
# 基础功能区的回调函数注册
|
|
|
104 |
for k in functional:
|
105 |
+
click_handle = functional[k]["Button"].click(predict, [*input_combo, gr.State(True), gr.State(k)], output_combo, show_progress=True)
|
|
|
106 |
cancel_handles.append(click_handle)
|
107 |
+
# 文件上传区,接收文件后与chatbot的互动
|
108 |
file_upload.upload(on_file_uploaded, [file_upload, chatbot, txt], [chatbot, txt])
|
109 |
+
# 函数插件-固定按钮区
|
110 |
+
for k in crazy_fns:
|
111 |
+
if not crazy_fns[k].get("AsButton", True): continue
|
112 |
+
click_handle = crazy_fns[k]["Button"].click(crazy_fns[k]["Function"], [*input_combo, gr.State(PORT)], output_combo)
|
113 |
+
click_handle.then(on_report_generated, [file_upload, chatbot], [file_upload, chatbot])
|
|
|
114 |
cancel_handles.append(click_handle)
|
115 |
+
# 函数插件-下拉菜单与随变按钮的互动
|
116 |
+
def on_dropdown_changed(k):
|
117 |
+
variant = crazy_fns[k]["Color"] if "Color" in crazy_fns[k] else "secondary"
|
118 |
+
return {switchy_bt: gr.update(value=k, variant=variant)}
|
119 |
+
dropdown.select(on_dropdown_changed, [dropdown], [switchy_bt] )
|
120 |
+
# 随变按钮的回调函数注册
|
121 |
+
def route(k, *args, **kwargs):
|
122 |
+
if k in [r"打开插件列表", r"先从插件列表中选择"]: return
|
123 |
+
yield from crazy_fns[k]["Function"](*args, **kwargs)
|
124 |
+
click_handle = switchy_bt.click(route,[switchy_bt, *input_combo, gr.State(PORT)], output_combo)
|
125 |
+
click_handle.then(on_report_generated, [file_upload, chatbot], [file_upload, chatbot])
|
126 |
+
def expand_file_area(file_upload, area_file_up):
|
127 |
+
if len(file_upload)>0: return {area_file_up: gr.update(open=True)}
|
128 |
+
click_handle.then(expand_file_area, [file_upload, area_file_up], [area_file_up])
|
129 |
+
cancel_handles.append(click_handle)
|
130 |
+
# 终止按钮的回调函数注册
|
131 |
stopBtn.click(fn=None, inputs=None, outputs=None, cancels=cancel_handles)
|
132 |
|
133 |
# gradio的inbrowser触发不太稳定,回滚代码到原始的浏览器打开函数
|
|
|
136 |
print(f"如果浏览器没有自动打开,请复制并转到以下URL: http://localhost:{PORT}")
|
137 |
def open():
|
138 |
time.sleep(2)
|
139 |
+
webbrowser.open_new_tab(f"http://localhost:{PORT}")
|
140 |
threading.Thread(target=open, name="open-browser", daemon=True).start()
|
141 |
|
142 |
auto_opentab_delay()
|
predict.py
CHANGED
@@ -96,13 +96,19 @@ def predict_no_ui_long_connection(inputs, top_p, temperature, history=[], sys_pr
|
|
96 |
except StopIteration: break
|
97 |
if len(chunk)==0: continue
|
98 |
if not chunk.startswith('data:'):
|
99 |
-
|
100 |
-
|
101 |
-
|
|
|
|
|
|
|
|
|
102 |
if len(delta) == 0: break
|
103 |
if "role" in delta: continue
|
104 |
if "content" in delta: result += delta["content"]; print(delta["content"], end='')
|
105 |
else: raise RuntimeError("意外Json结构:"+delta)
|
|
|
|
|
106 |
return result
|
107 |
|
108 |
|
|
|
96 |
except StopIteration: break
|
97 |
if len(chunk)==0: continue
|
98 |
if not chunk.startswith('data:'):
|
99 |
+
error_msg = get_full_error(chunk.encode('utf8'), stream_response).decode()
|
100 |
+
if "reduce the length" in error_msg:
|
101 |
+
raise ConnectionAbortedError("OpenAI拒绝了请求:" + error_msg)
|
102 |
+
else:
|
103 |
+
raise RuntimeError("OpenAI拒绝了请求:" + error_msg)
|
104 |
+
json_data = json.loads(chunk.lstrip('data:'))['choices'][0]
|
105 |
+
delta = json_data["delta"]
|
106 |
if len(delta) == 0: break
|
107 |
if "role" in delta: continue
|
108 |
if "content" in delta: result += delta["content"]; print(delta["content"], end='')
|
109 |
else: raise RuntimeError("意外Json结构:"+delta)
|
110 |
+
if json_data['finish_reason'] == 'length':
|
111 |
+
raise ConnectionAbortedError("正常结束,但显示Token不足。")
|
112 |
return result
|
113 |
|
114 |
|
toolbox.py
CHANGED
@@ -2,21 +2,21 @@ import markdown, mdtex2html, threading, importlib, traceback, importlib, inspect
|
|
2 |
from show_math import convert as convert_math
|
3 |
from functools import wraps
|
4 |
|
5 |
-
def get_reduce_token_percent(
|
6 |
try:
|
7 |
# text = "maximum context length is 4097 tokens. However, your messages resulted in 4870 tokens"
|
8 |
pattern = r"(\d+)\s+tokens\b"
|
9 |
match = re.findall(pattern, text)
|
10 |
-
|
11 |
-
max_limit = float(match[0]) -
|
12 |
current_tokens = float(match[1])
|
13 |
ratio = max_limit/current_tokens
|
14 |
assert ratio > 0 and ratio < 1
|
15 |
-
return ratio
|
16 |
except:
|
17 |
-
return 0.5
|
18 |
|
19 |
-
def predict_no_ui_but_counting_down(i_say, i_say_show_user, chatbot, top_p, temperature, history=[], sys_prompt='', long_connection=
|
20 |
"""
|
21 |
调用简单的predict_no_ui接口,但是依然保留了些许界面心跳功能,当对话太长时,会自动采用二分法截断
|
22 |
i_say: 当前输入
|
@@ -45,19 +45,18 @@ def predict_no_ui_but_counting_down(i_say, i_say_show_user, chatbot, top_p, temp
|
|
45 |
break
|
46 |
except ConnectionAbortedError as token_exceeded_error:
|
47 |
# 尝试计算比例,尽可能多地保留文本
|
48 |
-
p_ratio = get_reduce_token_percent(str(token_exceeded_error))
|
49 |
if len(history) > 0:
|
50 |
history = [his[ int(len(his) *p_ratio): ] for his in history if his is not None]
|
51 |
-
mutable[1] = 'Warning! History conversation is too long, cut into half. '
|
52 |
else:
|
53 |
i_say = i_say[: int(len(i_say) *p_ratio) ]
|
54 |
-
|
55 |
except TimeoutError as e:
|
56 |
-
mutable[0] = '[Local Message]
|
57 |
raise TimeoutError
|
58 |
except Exception as e:
|
59 |
-
mutable[0] = f'[Local Message]
|
60 |
-
raise RuntimeError(f'[Local Message]
|
61 |
# 创建新线程发出http请求
|
62 |
thread_name = threading.Thread(target=mt, args=(i_say, history)); thread_name.start()
|
63 |
# 原来的线程则负责持续更新UI,实现一个超时倒计时,并等待新线程的任务完成
|
@@ -286,7 +285,7 @@ def on_report_generated(files, chatbot):
|
|
286 |
report_files = find_recent_files('gpt_log')
|
287 |
if len(report_files) == 0: return report_files, chatbot
|
288 |
# files.extend(report_files)
|
289 |
-
chatbot.append(['汇总报告如何远程获取?', '
|
290 |
return report_files, chatbot
|
291 |
|
292 |
def get_conf(*args):
|
|
|
2 |
from show_math import convert as convert_math
|
3 |
from functools import wraps
|
4 |
|
5 |
+
def get_reduce_token_percent(text):
|
6 |
try:
|
7 |
# text = "maximum context length is 4097 tokens. However, your messages resulted in 4870 tokens"
|
8 |
pattern = r"(\d+)\s+tokens\b"
|
9 |
match = re.findall(pattern, text)
|
10 |
+
EXCEED_ALLO = 500 # 稍微留一点余地,否则在回复时会因余量太少出问题
|
11 |
+
max_limit = float(match[0]) - EXCEED_ALLO
|
12 |
current_tokens = float(match[1])
|
13 |
ratio = max_limit/current_tokens
|
14 |
assert ratio > 0 and ratio < 1
|
15 |
+
return ratio, str(int(current_tokens-max_limit))
|
16 |
except:
|
17 |
+
return 0.5, '不详'
|
18 |
|
19 |
+
def predict_no_ui_but_counting_down(i_say, i_say_show_user, chatbot, top_p, temperature, history=[], sys_prompt='', long_connection=True):
|
20 |
"""
|
21 |
调用简单的predict_no_ui接口,但是依然保留了些许界面心跳功能,当对话太长时,会自动采用二分法截断
|
22 |
i_say: 当前输入
|
|
|
45 |
break
|
46 |
except ConnectionAbortedError as token_exceeded_error:
|
47 |
# 尝试计算比例,尽可能多地保留文本
|
48 |
+
p_ratio, n_exceed = get_reduce_token_percent(str(token_exceeded_error))
|
49 |
if len(history) > 0:
|
50 |
history = [his[ int(len(his) *p_ratio): ] for his in history if his is not None]
|
|
|
51 |
else:
|
52 |
i_say = i_say[: int(len(i_say) *p_ratio) ]
|
53 |
+
mutable[1] = f'警告,文本过长将进行截断,Token溢出数:{n_exceed},截断比例:{(1-p_ratio):.0%}。'
|
54 |
except TimeoutError as e:
|
55 |
+
mutable[0] = '[Local Message] 请求超时。'
|
56 |
raise TimeoutError
|
57 |
except Exception as e:
|
58 |
+
mutable[0] = f'[Local Message] 异常:{str(e)}.'
|
59 |
+
raise RuntimeError(f'[Local Message] 异常:{str(e)}.')
|
60 |
# 创建新线程发出http请求
|
61 |
thread_name = threading.Thread(target=mt, args=(i_say, history)); thread_name.start()
|
62 |
# 原来的线程则负责持续更新UI,实现一个超时倒计时,并等待新线程的任务完成
|
|
|
285 |
report_files = find_recent_files('gpt_log')
|
286 |
if len(report_files) == 0: return report_files, chatbot
|
287 |
# files.extend(report_files)
|
288 |
+
chatbot.append(['汇总报告如何远程获取?', '汇总报告已经添加到右侧“文件上传区”(可能处于折叠状态),请查收。'])
|
289 |
return report_files, chatbot
|
290 |
|
291 |
def get_conf(*args):
|