BaseJpegDeocde exampe program

Dependencies:   BaseJpegDecode Terminal BaseUsbHost mbed mbed-rtos

Fork of BaseJpegDecode by Norimasa Okamoto

Files at this revision

API Documentation at this revision

Comitter:
va009039
Date:
Thu Nov 15 10:20:38 2012 +0000
Parent:
4:7d88de31c55a
Child:
6:95be1cd2bc14
Commit message:
bug fix SimpleJpegDecode.cpp

Changed in this revision

BaseJpegDecode.lib Show annotated file Show diff for this revision Revisions of this file
SimpleJpegDecode.cpp Show annotated file Show diff for this revision Revisions of this file
SimpleJpegDecode.h Show annotated file Show diff for this revision Revisions of this file
bmp24.h Show annotated file Show diff for this revision Revisions of this file
example1_c270.cpp Show annotated file Show diff for this revision Revisions of this file
example_SimpleJpegDecode.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/BaseJpegDecode.lib	Tue Oct 30 15:35:36 2012 +0000
+++ b/BaseJpegDecode.lib	Thu Nov 15 10:20:38 2012 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/va009039/code/BaseJpegDecode/#5b1dd4e34857
+http://mbed.org/users/va009039/code/BaseJpegDecode/#a7547692071d
--- a/SimpleJpegDecode.cpp	Tue Oct 30 15:35:36 2012 +0000
+++ b/SimpleJpegDecode.cpp	Thu Nov 15 10:20:38 2012 +0000
@@ -3,18 +3,42 @@
 #define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0);
 #define ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
 
-SimpleJpegDecode::SimpleJpegDecode()
+
+#define _1_4020 45
+#define _0_3441 11
+#define _0_7139 23
+#define _1_7718 57
+#define _0_0012 0
+
+int adjust(int r) {
+    if (r >= 0) {
+        if (r <= 255) {
+            return r;
+        } else {
+            return 255;
+        }
+    } else {
+        return 0;
+    }
+}
+    
+void convYUVtoRGB(uint8_t rgb[], int y, int u, int v)
 {
-    for(int i = 0; i < 6; i++) {
-        m_block_data[i] = new uint8_t[64];
-        ASSERT(m_block_data[i]);
-    }
+    rgb[0] = adjust((y*32             + v*_1_4020)/32 + 128);
+    rgb[1] = adjust((y*32 - u*_0_3441 - v*_0_7139)/32 + 128);
+    rgb[2] = adjust((y*32 + u*_1_7718 - v*_0_0012)/32 + 128);
+}
+
+SimpleJpegDecode::SimpleJpegDecode(uint8_t output_mode)
+{
+    m_output_mode = output_mode;
     clearOnResult();
 }
 
+
 void SimpleJpegDecode::output(int mcu, int block, int scan, int value)
 {
-    int sc = (block < m_yblocks) ? 0 : 1;
+    int sc = (block < yblock) ? 0 : 1;
     inputBLOCK(mcu, block, scan, value * qt[sc][scan]);
 }
 
@@ -34,38 +58,83 @@
 {
 }
 
-void SimpleJpegDecode::outputBLOCK(int mcu, int block, uint8_t* values)
+void SimpleJpegDecode::format_YUV(int mcu, int block, int8_t* values)
 {
-    BLOCK_count++;
-
-    memcpy(m_block_data[block], values, 64);
-    if (block < m_yblocks+1) {
+    if (block < yblock+1) {
+        memcpy(m_block_data[block], values, 64);
         return;
     }
-    int mcu_x = mcu % (width/16);
-    int mcu_y = mcu / (width/16);
+    int mcu_x_count = (width+15)/16;
+    int mcu_x = mcu % mcu_x_count;
+    int mcu_y = mcu / mcu_x_count;
     uint8_t yuv[3];
-    if (m_yblocks == 2) {
+    if (yblock == 2) {
         for(int y = 0; y < 8; y++) {
             for(int x = 0; x < 16; x++) {
-                yuv[0] = m_block_data[x/8][y*8+x%8];
-                yuv[1] = m_block_data[2][y*8+x/2];
-                yuv[2] = m_block_data[3][y*8+x/2];
+                yuv[0] = m_block_data[x/8][y*8+x%8] + 128;
+                yuv[1] = m_block_data[2][y*8+x/2] + 128;
+                yuv[2] = values[y*8+x/2] + 128;
                 onResult(mcu_x * 16 + x, mcu_y * 8 + y, yuv);
             }
         }
-    } else if (m_yblocks == 4) {
+    } else if (yblock == 4) {
         for(int y = 0; y < 16; y++) {
             for(int x = 0; x < 16; x++) {
-                int block = (y/8)*2+x/8;
-                yuv[0] = m_block_data[block][(y%8)*8+x%8];
-                yuv[1] = m_block_data[4][(y/2)*8+x/2];
-                yuv[2] = m_block_data[5][(y/2)*8+x/2];
+                yuv[0] = m_block_data[(y/8)*2+x/8][(y%8)*8+x%8] + 128;
+                yuv[1] = m_block_data[4][(y/2)*8+x/2] + 128;
+                yuv[2] = values[(y/2)*8+x/2] + 128;
                 onResult(mcu_x * 16 + x, mcu_y * 16 + y, yuv);
             }
         }
     } else {
-        ASSERT(m_yblocks == 2 || m_yblocks == 4);
+        ASSERT(yblock == 2 || yblock == 4);
+    }    
+}
+
+void SimpleJpegDecode::format_RGB24(int mcu, int block, int8_t* values)
+{
+    if (block < yblock+1) {
+        memcpy(m_block_data[block], values, 64);
+        return;
+    }
+    int mcu_x_count = (width+15)/16;
+    int mcu_x = mcu % mcu_x_count;
+    int mcu_y = mcu / mcu_x_count;
+    uint8_t rgb[3];
+    if (yblock == 2) {
+        for(int y = 0; y < 8; y++) {
+            for(int x = 0; x < 16; x++) {
+                int8_t yuv_y = m_block_data[x/8][y*8+x%8];
+                int8_t yuv_u = m_block_data[2][y*8+x/2];
+                int8_t yuv_v = values[y*8+x/2];
+                convYUVtoRGB(rgb, yuv_y, yuv_u, yuv_v);
+                onResult(mcu_x * 16 + x, mcu_y * 8 + y, rgb);
+            }
+        }
+    } else if (yblock == 4) {
+        for(int y = 0; y < 16; y++) {
+            for(int x = 0; x < 16; x++) {
+                int8_t yuv_y = m_block_data[(y/8)*2+x/8][(y%8)*8+x%8];
+                int8_t yuv_u = m_block_data[4][(y/2)*8+x/2];
+                int8_t yuv_v = values[(y/2)*8+x/2];
+                convYUVtoRGB(rgb, yuv_y, yuv_u, yuv_v);
+                onResult(mcu_x * 16 + x, mcu_y * 16 + y, rgb);
+            }
+        }
+    } else {
+        ASSERT(yblock == 2 || yblock == 4);
+    }    
+}
+
+void SimpleJpegDecode::outputBLOCK(int mcu, int block, int8_t* values)
+{
+    BLOCK_count++;
+    if (m_output_mode == YUV) {
+        format_YUV(mcu, block, values);
+    } else if (m_output_mode == RGB24) {
+        format_RGB24(mcu, block, values);
+    } else {
+        ASSERT(m_output_mode == YUV || m_output_mode == RGB24);
     }    
 }
 
--- a/SimpleJpegDecode.h	Tue Oct 30 15:35:36 2012 +0000
+++ b/SimpleJpegDecode.h	Thu Nov 15 10:20:38 2012 +0000
@@ -4,16 +4,23 @@
 #include "BaseJpegDecode.h"
 #include "inverseDCT.h"
 
+#define YUV   0
+#define RGB24 1
+
 class SimpleJpegDecode : public BaseJpegDecode, public inverseDCT {
 public:
-    SimpleJpegDecode();
+    SimpleJpegDecode(uint8_t output_mode=RGB24);
+
+    void format_YUV(int mcu, int block, int8_t* values);
+    void format_RGB24(int mcu, int block, int8_t* values);
+
     void output(int mcu, int block, int scan, int value);
     virtual void outputDC(int mcu, int block, int value);
     virtual void outputAC(int mcu, int block, int scan, int value);
     virtual void outputMARK(uint8_t c);
-    virtual void outputBLOCK(int muc, int block, uint8_t* values); // iDCT
+    virtual void outputBLOCK(int muc, int block, int8_t* values); // iDCT
 
-    uint8_t* m_block_data[6];
+    int8_t m_block_data[5][64];
     int DC_count;
     int AC_count;
     int BLOCK_count;
@@ -43,6 +50,7 @@
     CDummy* m_pCbItem;
     void (CDummy::*m_pCbMeth)(int, int, uint8_t*);
     void (*m_pCb)(int, int, uint8_t*);
+    uint8_t m_output_mode;
 };
 
 #endif // SIMPLE_JPEG_DECODE_H
\ No newline at end of file
--- a/bmp24.h	Tue Oct 30 15:35:36 2012 +0000
+++ b/bmp24.h	Thu Nov 15 10:20:38 2012 +0000
@@ -6,9 +6,12 @@
 
 class bmp24 {
 public:
+    int width;
+    int height;
+
     bmp24() {
-        m_width = BMP24_WIDTH;
-        m_height = BMP24_HEIGHT;
+        width = BMP24_WIDTH;
+        height = BMP24_HEIGHT;
     }
     
     void clear() {
@@ -16,8 +19,8 @@
     }
     
     void point(int x, int y, uint8_t* rgb) {
-        if (x >= 0 && x < m_width && y >= 0 && y < m_height) {
-            int pos = y*m_width*3+x*3;
+        if (x >= 0 && x < width && y >= 0 && y < height) {
+            int pos = y*width*3+x*3;
             m_bitmap[pos++] = rgb[0];
             m_bitmap[pos++] = rgb[1];
             m_bitmap[pos]   = rgb[2];
@@ -43,21 +46,20 @@
 0x00,0x00,0x00,0x00,0x00,0x00};
         int file_size = sizeof(header) + sizeof(m_bitmap);
         LE32write(header+2, file_size);
-        LE32write(header+18, m_width);
-        LE32write(header+22, m_height);
+        LE32write(header+18, width);
+        LE32write(header+22, height);
         
         fwrite(header, 1, sizeof(header), fp);
-        for(int y = m_height-1; y >=0; y--) {
-            for(int x = 0; x < m_width; x++) {
-                fputc(m_bitmap[y*m_width*3+x*3+2], fp);
-                fputc(m_bitmap[y*m_width*3+x*3+1], fp);
-                fputc(m_bitmap[y*m_width*3+x*3+0], fp);
+        for(int y = height-1; y >=0; y--) {
+            for(int x = 0; x < width; x++) {
+                fputc(m_bitmap[y*width*3+x*3+2], fp);
+                fputc(m_bitmap[y*width*3+x*3+1], fp);
+                fputc(m_bitmap[y*width*3+x*3+0], fp);
             }
         }    
         fclose(fp);
     }
-    int m_width;
-    int m_height;
+    
     uint8_t m_bitmap[BMP24_WIDTH*BMP24_HEIGHT*3];
 };
 
--- a/example1_c270.cpp	Tue Oct 30 15:35:36 2012 +0000
+++ b/example1_c270.cpp	Thu Nov 15 10:20:38 2012 +0000
@@ -1,4 +1,4 @@
-#if 0
+#if 1
 //
 // simple color tracking
 //
@@ -9,7 +9,10 @@
 
 // Logitech C270
 #define WIDTH  320
-#define HEIGHT 176
+//#define HEIGHT 176
+
+// LifeCam
+#define HEIGHT 240
 
 #define THRESHOLD 100
 
--- a/example_SimpleJpegDecode.cpp	Tue Oct 30 15:35:36 2012 +0000
+++ b/example_SimpleJpegDecode.cpp	Thu Nov 15 10:20:38 2012 +0000
@@ -1,4 +1,4 @@
-#if 1
+#if 0
 //
 // split jpeg to bmp files
 //
@@ -18,32 +18,11 @@
 
 int offset_x = 0;
 int offset_y = 0;
-void callback(int x, int y, uint8_t* yuv)
+
+void callbackRGB(int x, int y, uint8_t* rgb)
 {
     led1 = !led1;
     if (bmp) {
-        uint8_t rgb[3];
-        int r = yuv[0] + (yuv[2]-128) * 1.4020;
-        if (r < 0) {
-            r = 0;
-        } else if (r > 255) {
-            r = 255;
-        }
-        rgb[0] = r;
-        int g = yuv[0] - (yuv[1]-128) * 0.3441 - (yuv[2]-128) * 0.7139;
-        if (g < 0) {
-            g = 0;
-        } else if (g > 255) {
-            g = 255;
-        }
-        rgb[1] = g;
-        int b = yuv[0] + (yuv[1]-128) * 1.7718 - (yuv[2]-128) * 0.0012;
-        if (b < 0) {
-            b = 0;
-        } else if (b > 255) {
-            b = 255;
-        }
-        rgb[2] = b;
         bmp->point(x - offset_x, y - offset_y, rgb);
     }
 }
@@ -59,34 +38,67 @@
     bmp = new bmp24;
     ASSERT(bmp);
 
-    decode = new SimpleJpegDecode;
+    decode = new SimpleJpegDecode();
     ASSERT(decode);
-    decode->setOnResult(callback);
 
     const char* input_file = "/usb/input.jpg";
-    printf("input: %s\n", input_file);
+
+    FILE *fp = fopen(input_file, "rb");
+    ASSERT(fp != NULL);
+    Timer benchmark_t;
+    benchmark_t.reset();
+    benchmark_t.start();
+    while(!feof(fp)) {
+        int c = fgetc(fp);
+        led2 = !led2;
+    }
+    benchmark_t.stop();
+    fclose(fp);
+    printf("input: %s, %d ms\n", input_file, benchmark_t.read_ms());
+    
+    decode->clear();
+    fp = fopen(input_file, "rb");
+    ASSERT(fp != NULL);
+    benchmark_t.reset();
+    benchmark_t.start();
+    while(!feof(fp)) {
+        int c = fgetc(fp);
+        decode->input(c);
+        led2 = !led2;
+    }
+    benchmark_t.stop();
+    fclose(fp);
+    printf("width: %d, height: %d, yblock: %d, %d ms\n", decode->width, decode->height, 
+                                                         decode->yblock, benchmark_t.read_ms());
+
+    decode->setOnResult(callbackRGB);
     int n = 0;
-    for(offset_y = 0; offset_y < 240; offset_y += 48) {
-        for(offset_x = 0; offset_x < 320; offset_x += 64) {
+    for(offset_y = 0; offset_y < decode->height; offset_y += bmp->height) {
+        for(offset_x = 0; offset_x < decode->width; offset_x += bmp->width) {
             bmp->clear();
             decode->clear();
-            FILE *fp = fopen(input_file, "rb");
+            fp = fopen(input_file, "rb");
             ASSERT(fp != NULL);
+            benchmark_t.reset();
+            benchmark_t.start();
             while(!feof(fp)) {
                 int c = fgetc(fp);
                 decode->input(c);
                 led2 = !led2;
             }
+            benchmark_t.stop();
             fclose(fp);
             char path[32];
             sprintf(path, "/usb/output%02d.bmp", n++);
-            printf("offset: (%3d,%3d) %s\n", offset_x, offset_y, path);
+            printf("offset: (%3d,%3d), size:(%3d,%3d), %s %d ms\n", 
+                offset_x, offset_y, bmp->width, bmp->height, 
+                path, benchmark_t.read_ms());
             bmp->writeFile(path);
             led3 = !led3;
         }
         led4 = !led4;
     }
-    printf("width: %d, height: %d, yblock: %d\n", decode->width, decode->height, decode->m_yblocks);
+    printf("done\n");
     exit(1);     
 }
 #endif