#include #include #define true 1 #define false 0 #define RST0 0xd0 /* Restart 0 */ #define SOI 0xd8 /* Start of Image */ #define APP0 0xe0 /* application segments */ #define DQT 0xdb /* quantization table */ #define SOF0 0xc0 /* Start of Frame */ #define DHT 0xc4 /* Huffman table */ #define SOS 0xda /* Start of Scan */ #define EOI 0xd9 /* End of Image */ #define EOB 0 /* End of Block */ #define ZRL 240 /* Zero Run Length */ #define SECTION_MARKER 0xff #define NO_OF_HUF_TBLS 4 #define MAX_NODES 256 #define MAX_COMPONENTS 3 #define WORD_LEN 8 #define ic1 251 #define is1 50 #define ic3 213 #define is3 142 #define ir2c6 277 #define ir2s6 669 #define ir2 181 typedef struct { short app0_len; char identifier[5]; short version; unsigned char units; short x_density; short y_density; short x_thumbnail; short y_thumbnail; } JPGHEADER; typedef struct { unsigned char id; unsigned char samp_factor; unsigned char v_samp_factor; unsigned char h_samp_factor; unsigned char quant_tbl_no; } COMPONENT; typedef struct { unsigned char precision; short height; short width; unsigned char components; COMPONENT component[3]; } SOFINFO; typedef struct { unsigned char id; unsigned char tbl_no; unsigned char ac_tbl_no; unsigned char dc_tbl_no; } SCANCOMPONENT; typedef struct { unsigned char components; SCANCOMPONENT component[3]; } SOSINFO; typedef struct { unsigned char bits[16]; unsigned char val[256]; } HUFTBL; typedef struct { unsigned short code; short size; short value; unsigned long tree_index; } huf_node; //unsigned short videobuf[38016]; //QCIF: 176*144*3=76032 bytes //static unsigned short videobuf[4]; //QCIF: 176*144*3=76032 bytes static unsigned char* videobuf; static short reset_mcu; static short image_started=false; static JPGHEADER jpg_header; static SOFINFO sof_info; static short image_height; static short image_width; static SOSINFO sos_info; static HUFTBL ac_huf_tbl[NO_OF_HUF_TBLS]; static HUFTBL dc_huf_tbl[NO_OF_HUF_TBLS]; static short quant_tbl[2][64]; static char identifier_mark[5]; static short thumbnail_size; static short jfif_found; static huf_node ac_node[MAX_COMPONENTS][MAX_NODES]; static huf_node dc_node[MAX_COMPONENTS][MAX_NODES]; static short h_div[MAX_COMPONENTS]; static short v_div[MAX_COMPONENTS]; static short total_nodes; static short dc_total_nodes[MAX_COMPONENTS]; static short ac_total_nodes[MAX_COMPONENTS]; static short size,amplitude,symbol,run; static short prev_dc_amplitude[MAX_COMPONENTS]; static short component[4][4][MAX_COMPONENTS][8][8]; static short transform[8][8]; static short block[64]; static short coefficient[64]; static short zigzag_array[64]; static unsigned char max_v_samp_factor; static unsigned char max_h_samp_factor; static short mcu_ctr; static short mcu_x; static short mcu_y; static short mcu_width; static short mcu_height; static unsigned char current_word; static short current_bit; static unsigned short word_var; static unsigned char byte_var; static unsigned char three_byte_var[3]; static short done; static int iter = 0; static unsigned char* in_stream; static long x0, x1, x2, x3, x4, x5, x6, x7, x8; static unsigned int bg_width; static unsigned int bg_height; static unsigned int offset_x; static unsigned int offset_y; static unsigned int out_format =0; void jpeg_dec(unsigned char* inbuf, unsigned char* outbuf); static unsigned char stream_getc() { unsigned char r = in_stream[iter]; iter++; return r; } static void stream_read(unsigned char* buf, short len) { short i; for(i=0; i> 6; x4 = (x6 + (- ic3 + is3) * x4) >> 6; x6 = ic1 * (x1 + x8); x1 = (x6 + (- ic1 - is1) * x1) >> 6; x8 = (x6 + (- ic1 + is1) * x8) >> 6; x7 += 512; x2 += 512; x0 += 512; x3 += 512; component[l][m][k][i][0] = (short) ((x3 + x4) >> 10); component[l][m][k][i][1] = (short) ((x2 + x8) >> 10); component[l][m][k][i][2] = (short) ((x0 + x1) >> 10); component[l][m][k][i][3] = (short) ((x7 + x5) >> 10); component[l][m][k][i][4] = (short) ((x7 - x5) >> 10); component[l][m][k][i][5] = (short) ((x0 - x1) >> 10); component[l][m][k][i][6] = (short) ((x2 - x8) >> 10); component[l][m][k][i][7] = (short) ((x3 - x4) >> 10); } for (i = 0; i < 8; i ++) { x0 = (long) component[l][m][k][0][i]<< 9; x1 = (long) component[l][m][k][1][i] << 7; x2 = (long) component[l][m][k][2][i]; x3 = (long) component[l][m][k][3][i] * ir2; x4 = (long) component[l][m][k][4][i] << 9; x5 = (long) component[l][m][k][5][i] * ir2; x6 = (long) component[l][m][k][6][i]; x7 = (long) component[l][m][k][7][i] << 7; x8 = x7 + x1; x1 -= x7; x7 = x0 + x4; x0 -= x4; x4 = x1 + x5; x1 -= x5; x5 = x3 + x8; x8 -= x3; x3 = ir2c6 * (x2 + x6); x6 = x3 + (- ir2c6 - ir2s6) * x6; x2 = x3 + (- ir2c6 + ir2s6) * x2; x3 = x7 + x2; x7 -= x2; x2 = x0 + x6; x0 -= x6; x4 >>= 6; x5 >>= 6; x1 >>= 6; x8 >>= 6; x6 = ic3 * (x4 + x5); x5 = (x6 + (- ic3 - is3) * x5); x4 = (x6 + (- ic3 + is3) * x4); x6 = ic1 * (x1 + x8); x1 = (x6 + (- ic1 - is1) * x1); x8 = (x6 + (- ic1 + is1) * x8); x7 += 1024; x2 += 1024; x0 += 1024; x3 += 1024; component[l][m][k][0][i] = (short) ((x3 + x4) >> 11); component[l][m][k][1][i] = (short) ((x2 + x8) >> 11); component[l][m][k][2][i] = (short) ((x0 + x1) >> 11); component[l][m][k][3][i] = (short) ((x7 + x5) >> 11); component[l][m][k][4][i] = (short) ((x7 - x5) >> 11); component[l][m][k][5][i] = (short) ((x0 - x1) >> 11); component[l][m][k][6][i] = (short) ((x2 - x8) >> 11); component[l][m][k][7][i] = (short) ((x3 - x4) >> 11); } } static void set_pixel_yuv422(unsigned x, unsigned y, unsigned char y1, unsigned char u, unsigned char v) { long idx; unsigned char* videobuf2= videobuf+ sof_info.width*sof_info.height; idx = (long)y; idx *= sof_info.width; idx += x; //YUV422 pack if(x & 1){ videobuf[idx] = y1; videobuf2[idx] = v; } else{ videobuf[idx] = y1; videobuf2[idx] = u; } } static void set_pixel_vyuy(unsigned x, unsigned y, unsigned char y1, unsigned char u, unsigned char v) { long idx; #if 0 idx = (long)y; idx *= sof_info.width; idx += x; idx *= 2; #else idx = (long)(y+offset_y); idx *= bg_width; idx += x+offset_x; idx *= 2; #endif if(x & 1){ videobuf[idx] = v; videobuf[idx+1] = y1; } else{ videobuf[idx] = u; videobuf[idx+1] = y1; } } static void set_pixel(unsigned x,unsigned y, unsigned char red,unsigned char green,unsigned char blue) { long idx; //idx = (y * sof_info.width + x) * 3; idx = (long)y; idx *= sof_info.width; idx += x; idx *= 3; #if 0 if(idx % 2) { idx /= 2; videobuf[idx] += red; videobuf[idx+1] = (green<<8) + blue; } else { idx /= 2; videobuf[idx] = (red<<8) + green; videobuf[idx+1] = (blue<<8); } #else videobuf[idx] = red; videobuf[idx+1] = green; videobuf[idx+2] = blue; #endif } static void check_for_reset_marker(unsigned char buf) { short i; for (i=0;i<8;i++) { if (buf==(RST0+i)) { reset_mcu=true; break; } } if (reset_mcu) { /* zero out the previous dc values */ for (i=0;i bg_width/bg_height!!\n"); offset_x = 0; offset_y = 0; bg_width = image_width; bg_height = image_height; } else{ offset_x = (bg_width - image_width)/2; offset_y = (bg_height - image_height)/2; } } stream_read(&byte_var,1); sof_info.components=byte_var; if (sof_info.components!=3) { done=true; return; } max_v_samp_factor=0; max_h_samp_factor=0; for (i=0;i>4; if (sof_info.component[i].v_samp_factor>max_v_samp_factor) max_v_samp_factor=sof_info.component[i].v_samp_factor; if (sof_info.component[i].h_samp_factor>max_h_samp_factor) max_h_samp_factor=sof_info.component[i].h_samp_factor; stream_read(&byte_var,1); sof_info.component[i].quant_tbl_no=byte_var; } /* Get divisors used for upsampling the chrominance components */ for (i=0;i0) { stream_read(&byte_var,1); type=byte_var>>4; /* Hi Nibble */ ndx=byte_var&0x0f; /* Lo Nibble */ /* Choose Huffman Table for AC or DC components */ if (type==1) huf_tbl_ptr=&ac_huf_tbl[ndx]; else huf_tbl_ptr=&dc_huf_tbl[ndx]; count=0; for (i=0;i<16;i++) { stream_read(&byte_var,1); huf_tbl_ptr->bits[i]=byte_var; count+=byte_var; } if (count>256) { done=true; return; } for (i=0;ival[i]=byte_var; } len-=(1+16+count); /* subtract for type, index, bits & values */ } } } static void dec_mcu(void); static void build_huf_nodes(); static void dec_image_data() { short i; if (!image_started) done=true; else { build_huf_nodes(); /* Initialize previous DC amplitudes to zero for each component */ for (i=0;i>4; len-=2; } /* Skip over the rest of the start of scan */ for (i=0;i0) { while (node[k].size==si) { node[k].code=code; node[k].value=hufval[k]; code++; k++; } if (node[k].size>0) { while (node[k].size!=si) { code<<=1; si++; } } } } static void generate_code_size(unsigned char *bits,huf_node *node) { short i,j,k; i=0;j=1;k=0; while (i<16) { while (j<=bits[i]) { node[k].size=i+1; k++; j++; } i++; j=1; } node[k].size=0; total_nodes=k; } static void build_huf_nodes() { short k; for (k=0;k=first && !found) { middle=(first+last)>>1; if (indexnode[middle].tree_index) first=middle+1; else { found=true; *value=node[middle].value; } } return found; } static short get_huf_code(huf_node *node,short total_nodes) { char bit; short found=false; unsigned long index=0; short value,ctr=0; while (!found && ctr<16) { bit=getbit(); if (reset_mcu) return 0; if (bit==0) index=(index<<1)+1; /* take left branch */ else index=(index<<1)+2; /* take right branch */ found=find_node_index(index,&value,node,total_nodes); if (found) return value; ctr++; } return 0; } static unsigned short get_binary_number(short length) { short i; char bit; unsigned short mask,number; number=0; mask=1<<(length-1); for (i=0;i>=1; } if (number<1<<(length-1)) /* negative */ return number+((-1)<>4; /* Hi Nibble */ size=symbol & 0x0f; /* Lo Nibble */ if (symbol==ZRL) run++; for (i=0;i0) { amplitude=get_binary_number(size); coefficient[index]=amplitude; index++; } if (index==64) done_with_dat_unit=true; } } de_zigzag(k); build_transform(); new_idct(k,l,m); shift_block(k,l,m); } static void dec_dat_unit(short k) { short i,j; for (j=0;j255) red=255; green=y-0.34414*(u-128)-0.71414*(v-128); if (green<0) green=0; if (green>255) green=255; blue=y+1.772*(u-128); if (blue<0) blue=0; if (blue>255) blue=255; *r=(unsigned char)red; *g=(unsigned char)green; *b=(unsigned char)blue; } static void display_data_block(short i,short j) { short x,y; short y_comp,u_comp,v_comp; unsigned char r,g,b; unsigned x_pos,y_pos; short v_data_index,h_data_index; for (y=0;y<8;y++) for (x=0;x<8;x++) { y_comp=component[i][j][0][x][y]; /* Up Sample the blue chrominance */ if (i>=sof_info.component[1].h_samp_factor) h_data_index=sof_info.component[1].h_samp_factor-1; else h_data_index=i; if (j>=sof_info.component[1].v_samp_factor) v_data_index=sof_info.component[1].v_samp_factor-1; else v_data_index=j; u_comp=component[h_data_index][v_data_index][1][(x+i*8)/h_div[1]][(y+j*8)/v_div[1]]; /* Up Sample the red chrominance */ if (i>=sof_info.component[2].h_samp_factor) h_data_index=sof_info.component[2].h_samp_factor-1; else h_data_index=i; if (j>=sof_info.component[2].v_samp_factor) v_data_index=sof_info.component[2].v_samp_factor-1; else v_data_index=j; v_comp=component[h_data_index][v_data_index][2][(x+i*8)/h_div[1]][(y+j*8)/v_div[1]]; /* //???, it should be //v_comp=component[h_data_index][v_data_index][2][(x+i*8)/h_div[2]][(y+j*8)/v_div[2]]; */ #if 1 //YUV422 #else //RGB888 convert_yuv_to_rgb(y_comp,u_comp,v_comp,&r,&g,&b); #endif mcu_x=mcu_ctr % mcu_width; mcu_y=mcu_ctr/mcu_width; x_pos=mcu_x*max_h_samp_factor*8+i*8+x; y_pos=mcu_y*max_v_samp_factor*8+j*8+y; if (x_pos 0xFF) y_comp = 0xFF; if(u_comp > 0xFF) u_comp = 0xFF; if(v_comp > 0xFF) v_comp = 0xFF; if(out_format==1) { set_pixel_yuv422(x_pos, y_pos, (unsigned char)y_comp, (unsigned char)u_comp, (unsigned char)v_comp); } else { set_pixel_vyuy(x_pos, y_pos, (unsigned char)y_comp, (unsigned char)u_comp, (unsigned char)v_comp); } } #else //RGB888 set_pixel(x_pos, y_pos, r, g, b); #endif } } static void dec_mcu(void) { short i,j,k; reset_mcu=false; for (k=0;k