huffmancode to decode in real-time for motion-jpeg

Dependents:   BaseJpegDecode_example SimpleJpegDecode_example Dumb_box_rev2

example code:

Import programBaseJpegDecode_example

BaseJpegDeocde exampe program

Import programSimpleJpegDecode_example

convert JPEG stream data to bitmap, BaseJpegDecode example program

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Tue Oct 30 13:22:08 2012 +0000
Parent:
1:bfbc18000cca
Child:
3:a7547692071d
Commit message:
add inverseDCT

Changed in this revision

BaseJpegDecode.cpp Show annotated file Show diff for this revision Revisions of this file
BaseJpegDecode.h Show annotated file Show diff for this revision Revisions of this file
inverseDCT.cpp Show annotated file Show diff for this revision Revisions of this file
inverseDCT.h Show annotated file Show diff for this revision Revisions of this file
--- a/BaseJpegDecode.cpp	Thu Oct 25 11:00:05 2012 +0000
+++ b/BaseJpegDecode.cpp	Tue Oct 30 13:22:08 2012 +0000
@@ -71,8 +71,9 @@
 {
     m_block = 0;
     m_scan = 0;
-    m_old_DC_value[0] = 0;
-    m_old_DC_value[1] = 0;
+    m_pre_DC_value[0] = 0;
+    m_pre_DC_value[1] = 0;
+    m_pre_DC_value[2] = 0;
     m_bitpat.clear();
     m_huff = NULL;
 }
@@ -95,10 +96,10 @@
             m_param1 = c<<8;
             break;
         case 2:
-            width = m_param1 | c;
+            height = m_param1 | c;
             break;
         case 4:
-            height = m_param1 | c;
+            width = m_param1 | c;
             break;
         case 7:
             if (c == 0x22) {
@@ -202,18 +203,25 @@
         DBG("%d %d %d %02x\n", m_huff->run, m_huff->value_size, m_huff->code_size, m_huff->code);
         int value = pHD->getValue(m_huff, &m_bitpat);
         if (tc == HT_DC) {
-            value += m_old_DC_value[th];
+            int sc = 0; // Y
+            if (m_block == m_yblocks) {
+                sc = 1; // Cb
+            } else if (m_block == (m_yblocks+1)) {
+                sc = 2; // Cr
+            }
+            value += m_pre_DC_value[sc];
             outputDC(m_mcu, m_block, value);
-            m_old_DC_value[th] = value;
+            m_pre_DC_value[sc] = value;
             m_scan++;
             REPORT_CODE(report_scan_dc_count++);
         } else { // AC
             if (m_huff->value_size == 0 && m_huff->run == 0) { // EOB
                 DBG("AC EOB\n");
+                outputAC(m_mcu, m_block, 63, 0);
                 m_scan = 64;
             } else {
                 for(int i = 0; i < m_huff->run; i++) {
-                    outputAC(m_mcu, m_block, m_scan, 0);
+                    //outputAC(m_mcu, m_block, m_scan, 0);
                     m_scan++;
                 }
                 outputAC(m_mcu, m_block, m_scan, value);
--- a/BaseJpegDecode.h	Thu Oct 25 11:00:05 2012 +0000
+++ b/BaseJpegDecode.h	Tue Oct 30 13:22:08 2012 +0000
@@ -33,7 +33,7 @@
     int m_block;
     int m_scan;
     Huff* m_huff;
-    int m_old_DC_value[2];
+    int m_pre_DC_value[3];
     BitPattern m_bitpat;
     uint8_t m_mark;
     HuffmanDecode* pHD;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inverseDCT.cpp	Tue Oct 30 13:22:08 2012 +0000
@@ -0,0 +1,130 @@
+#include "mbed.h"
+#include <math.h>
+#include "inverseDCT.h"
+
+#define PI 3.14159265
+
+const int zigzag[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};
+
+int adjust(int value) {
+    value += 128;
+    if (value < 0) {
+        return 0;
+    } else if (value > 255) {
+        return 255;
+    }
+    return value;
+}
+
+#if DCT_USE_INT
+inverseDCT::inverseDCT()
+{
+    for(int x = 0; x < 8; x++) {
+        for(int u = 0; u < 8; u++) {
+            float value = cos((x*2+1)*u*PI/16);
+            m_cosxu[x*8+u] = value * 32;
+        }
+    }
+    
+    for(int v = 0; v < 8; v++) {
+        for(int u = 0; u < 8; u++) {
+            float value = 1.0 / 4.0;
+            if (v == 0 && u == 0) {
+                value /= 2.0;
+            } else if (v == 0 || u == 0) {
+                value /= sqrt(2.0);
+            }
+            m_cucv[v*8+u] = value * 32;
+        }
+    }
+}
+
+void inverseDCT::inputBLOCK(int mcu, int block, int scan, int value)
+{
+    if (scan == 0) {
+        for(int i = 0; i < 64; i++) {
+            m_sum[i] = 0;
+        }
+    }
+
+    if (value != 0) {
+        int uv = zigzag[scan];
+        int u = uv % 8;
+        int v = uv / 8;
+        for(int y = 0; y < 8; y++) {
+            for(int x = 0; x < 8; x++) {
+                int t = m_cucv[uv] * value * m_cosxu[x*8+u] * m_cosxu[y*8+v] / 32 / 32;
+                m_sum[y*8+x] += t;
+            }
+        }
+    }
+    
+    if (scan == 63) {
+        uint8_t result[64];
+        for(int i = 0; i < 64; i++) {
+            int value = m_sum[i] / 32;
+            result[i] = adjust(value);
+        }
+        outputBLOCK(mcu, block, result);
+    }
+}
+
+#else
+
+inverseDCT::inverseDCT()
+{
+}
+
+void inverseDCT::input(int mcu, int block, int scan, int value) {
+    if (scan == 0) {
+        for(int i = 0; i < 64; i++) {
+            m_s[i] = 0;
+        }
+    }
+    m_s[zigzag[scan]] = value;
+    if (scan == 63) {
+        calc(mcu, block, m_s);
+    }
+}
+
+void inverseDCT::calc(int mcu, int block, int s[]) {
+    for(int y = 0; y < 8; y++) {
+        for(int x = 0; x < 8; x++) {
+            float sum = 0.0;
+            for(int v = 0; v < 8; v++) {
+                float cv = 1.0;
+                if (v == 0) {
+                    cv /= sqrt(2.0);
+                }
+                for(int u = 0; u < 8; u++) {
+                    float cu = 1.0;
+                    if (u == 0) {
+                        cu /= sqrt(2.0);
+                    }
+                    int vu = v * 8 + u;
+                    float cosxu = cos((x*2+1) * u * PI / 16);
+                    float cosyv = cos((y*2+1) * v * PI / 16);
+                    sum += cu * cv * s[vu] * cosxu * cosyv;
+                }
+            }    
+            sum /= 4;
+            m_result[y*8+x] = adjust(sum);
+        }
+    }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inverseDCT.h	Tue Oct 30 13:22:08 2012 +0000
@@ -0,0 +1,35 @@
+#ifndef INVERSE_DCT_H
+#define INVERSE_DCT_H
+
+#define DCT_USE_INT 1
+
+#ifdef DCT_USE_INT
+
+class inverseDCT {
+public:
+    inverseDCT();
+    void inputBLOCK(int mcu, int block, int scan, int value);
+    virtual void outputBLOCK(int mcu, int block, unsigned char* values) = 0;
+private:
+    int16_t m_sum[64];
+    int8_t m_cosxu[64];
+    int8_t m_cucv[64];
+};
+
+#else
+
+class inverseDCT {
+public:
+    inverseDCT();
+    void input(int mcu, int block, int scan, int value);
+    int m_result[64];
+private:
+    int m_sum[64];
+    void calc(int mcu, int block, int s[]);
+    int m_s[64];
+    void outputDot(int mcu, int block, int x, int y, int value);
+};
+
+#endif
+
+#endif // INVERSE_DCT_H
\ No newline at end of file