Spaces:
				
			
			
	
			
			
		Sleeping
		
	
	
	
			
			
	
	
	
	
		
		
		Sleeping
		
	优化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):
         |