www.pudn.com > spca5xx-.rar > spcadecoder.c
/******************************************************************************* # spcadecoder: Generic decoder for various input stream yyuv # # yuyv yuvy jpeg411 jpeg422 bayer rggb with gamma correct # # and various output palette rgb16 rgb24 rgb32 yuv420p # # various output size with crop feature # # Copyright (C) 2003 2004 2005 Michel Xhaard # # mxhaard@magic.fr # # Sonix Decompressor by B.S. (C) 2004 # # Spca561decoder (C) 2005 Andrzej Szombierski [qq@kuku.eu.org] # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the Free Software # # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # ********************************************************************************/ #ifndef __KERNEL__ #include#include #include #else /* __KERNEL__ */ #include #endif /* __KERNEL__ */ #include "spcadecoder.h" #include "jpeg_header.h" #include "spcagamma.h" #define ISHIFT 11 #define IFIX(a) ((long)((a) * (1 << ISHIFT) + .5)) #define IMULT(a, b) (((a) * (b)) >> ISHIFT) #define ITOINT(a) ((a) >> ISHIFT) /* special markers */ #define M_BADHUFF -1 /* Sonix decompressor struct B.S.(2004) */ typedef struct { int is_abs; int len; int val; } code_table_t; static code_table_t table[256]; #define ERR_NO_SOI 1 #define ERR_NOT_8BIT 2 #define ERR_HEIGHT_MISMATCH 3 #define ERR_WIDTH_MISMATCH 4 #define ERR_BAD_WIDTH_OR_HEIGHT 5 #define ERR_TOO_MANY_COMPPS 6 #define ERR_ILLEGAL_HV 7 #define ERR_QUANT_TABLE_SELECTOR 8 #define ERR_NOT_YCBCR_221111 9 #define ERR_UNKNOWN_CID_IN_SCAN 10 #define ERR_NOT_SEQUENTIAL_DCT 11 #define ERR_WRONG_MARKER 12 #define ERR_NO_EOI 13 #define ERR_BAD_TABLES 14 #define ERR_DEPTH_MISMATCH 15 #define ERR_CORRUPTFRAME 16 #define JPEGHEADER_LENGTH 589 const unsigned char JPEGHeader[JPEGHEADER_LENGTH] = { 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05, 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06, 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e, 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16, 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16, 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29, 0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29, 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a, 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, 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, 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, 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, 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, 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, 0xf9, 0xfa, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 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, 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, 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, 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, 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, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11, 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 }; int spca50x_outpicture ( struct spca50x_frame *myframe ); static int jpeg_decode411(struct spca50x_frame *myframe, int force_rgb); static int jpeg_decode422(struct spca50x_frame *myframe, int force_rgb); static int yuv_decode(struct spca50x_frame *myframe, int force_rgb); static int bayer_decode(struct spca50x_frame *myframe, int force_rgb); static int make_jpeg ( struct spca50x_frame *myframe ); static int make_jpeg_conexant (struct spca50x_frame *myframe); #define CLIP(color) (unsigned char)(((color)>0xFF)?0xff:(((color)<0)?0:(color))) /****************************************************************/ /************** Sonix huffman decoder ****************/ /****************************************************************/ void init_sonix_decoder(void) { int i; int is_abs, val, len; for (i = 0; i < 256; i++) { is_abs = 0; val = 0; len = 0; if ((i & 0x80) == 0) { /* code 0 */ val = 0; len = 1; } else if ((i & 0xE0) == 0x80) { /* code 100 */ val = +4; len = 3; } else if ((i & 0xE0) == 0xA0) { /* code 101 */ val = -4; len = 3; } else if ((i & 0xF0) == 0xD0) { /* code 1101 */ val = +11; len = 4; } else if ((i & 0xF0) == 0xF0) { /* code 1111 */ val = -11; len = 4; } else if ((i & 0xF8) == 0xC8) { /* code 11001 */ val = +20; len = 5; } else if ((i & 0xFC) == 0xC0) { /* code 110000 */ val = -20; len = 6; } else if ((i & 0xFC) == 0xC4) { /* code 110001xx: unknown */ val = -1; len = 8; } else if ((i & 0xF0) == 0xE0) { /* code 1110xxxx */ is_abs = 1; val = (i & 0x0F) << 4; len = 8; } table[i].is_abs = is_abs; table[i].val = val; table[i].len = len; } } static void sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp) { int row, col; int val; int bitpos; unsigned char code; unsigned char *addr; bitpos = 0; for (row = 0; row < height; row++) { col = 0; /* first two pixels in first two rows are stored as raw 8-bit */ if (row < 2) { addr = inp + (bitpos >> 3); code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); bitpos += 8; *outp++ = code; addr = inp + (bitpos >> 3); code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); bitpos += 8; *outp++ = code; col += 2; } while (col < width) { /* get bitcode from bitstream */ addr = inp + (bitpos >> 3); code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); /* update bit position */ bitpos += table[code].len; /* calculate pixel value */ val = table[code].val; /* unknowcode output nothing BS update 23:10:2005*/ if(val == -1) continue; if (!table[code].is_abs) { /* value is relative to top and left pixel */ if (col < 2) { /* left column: relative to top pixel */ val += outp[-2*width]; } else if (row < 2) { /* top row: relative to left pixel */ val += outp[-2]; } else { /* main area: average of left pixel and top pixel */ val += (outp[-2] + outp[-2*width]) / 2; //val += (outp[-2] + outp[-2*width] - outp[-2*width -2]); } } /* store pixel */ *outp++ = CLIP(val); col++; } } } static void tv8532_preprocess(struct spca50x_frame *myframe) { /* we should received a whole frame with header and EOL marker in myframe->data and return a GBRG pattern in frame->tmpbuffer sequence 2bytes header the Alternate pixels bayer GB 4 bytes Alternate pixels bayer RG 4 bytes EOL */ int width = myframe->hdrwidth; int height =myframe->hdrheight; int src = 0; unsigned char *dst = myframe->tmpbuffer; unsigned char *data = myframe->data; int i; int seq1,seq2; /* precompute where is the good bayer line */ if((((data[src+3]+ data[src+width+7]) >>1 )+(data[src+4]>>2)+(data[src+width+6]>>1)) >= (((data[src+2]+data[src+width+6]) >>1)+(data[src+3]>>2)+(data[src+width+5]>>1))){ seq1 = 3; seq2 = 4; } else { seq1 = 2; seq2 = 5; } for(i=0; i < height/2; i++){ src += seq1; memcpy(dst,&myframe->data[src],width); src += (width + 3); dst += width; memcpy(dst,&myframe->data[src],width); src += (width + seq2); dst += width; } } static int pixart_preprocess(struct spca50x_frame *myframe) { /* we should received a whole frame with header and EOL marker in myframe->data and return a GBRG pattern in frame->tmpbuffer remove the header then copy line by line EOL is set with 0x0f 0xf0 marker*/ int width = myframe->hdrwidth; int height =myframe->hdrheight; int length = 0; unsigned char *dst = myframe->tmpbuffer; unsigned char *data = myframe->data; int j = 0; int k = 0; while (data[j] != 0x0f && data[j+1] != 0xf0){ j++; } j +=2; //skip 0x0f 0xf0 marker while(height){ if ((data[j] == 0x0f) && (data[j+1] == 0xf0)){ height--; if (length > width) return -1; j +=2; length =0; } else { dst[k] = data[j]; k++; j++; length++; } } return 0; } /* # Decoder for compressed spca561 images # # It was developed for "Labtec WebCam Elch 2(SPCA561A)" (046d:0929) # # but it might work with other spca561 cameras # */ static unsigned int bit_bucket; static unsigned char *input_ptr; static inline void refill(int *bitfill) { if(*bitfill < 8){ bit_bucket = (bit_bucket << 8) | *(input_ptr++); *bitfill += 8; } } static inline int nbits(int *bitfill, int n) { bit_bucket = (bit_bucket << 8) | *(input_ptr++); *bitfill -= n; return (bit_bucket >> (*bitfill & 0xff)) & ((1< > (*bitfill & 0xff)) & ((1< 47) return 0xff; return tab[tab1[tmp]]; } static int fun_C(int *bitfill, int gkw) { static int tab1[]={0,1,2,3,4,5,6,7,8,9,10,11,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,12,13,14,15,16,17,18,19,20,21,22}; static int tab[] = { 8,9,10,11,12,13,14,15,16,17,18,19,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18,-19}; unsigned int tmp; if(gkw == 0xfe){ if(nbits(bitfill,1) == 0) return 7; else return -8; } if(gkw != 0xff) return 0xff; tmp = nbits(bitfill,7) - 72; if(tmp > 43) return 0xff; refill(bitfill); return tab[tab1[tmp]]; } static int fun_D(int *bitfill, int gkw) { if(gkw == 0xfd){ if(nbits(bitfill,1) == 0) return 12; else return -13; } if(gkw == 0xfc){ if(nbits(bitfill,1) == 0) return 13; else return -14; } if(gkw == 0xfe){ switch(nbits(bitfill, 2)){ case 0: return 14; case 1: return -15; case 2: return 15; case 3: return -16; } } if(gkw == 0xff){ switch(nbits(bitfill,3)){ case 4: return 16; case 5: return -17; case 6: return 17; case 7: return -18; case 2: return _nbits(bitfill, 1)?0xed:0x12; case 3: *bitfill--; return 18; } return 0xff; } return gkw; } static int fun_E(int cur_byte, int *bitfill) { static int tab0[] = { 0, -1, 1, -2, 2, -3, 3, -4 }; static int tab1[] = { 4, -5, 5, -6, 6, -7, 7, -8 }; static int tab2[] = { 8, -9, 9, -10, 10, -11, 11, -12 }; static int tab3[] = { 12, -13, 13, -14, 14, -15, 15, -16 }; static int tab4[] = { 16, -17, 17, -18, 18, -19, 19, -19 }; if((cur_byte & 0xf0) >= 0x80){ *bitfill -= 4; return tab0[(cur_byte >> 4) & 7]; }else if((cur_byte & 0xc0) == 0x40){ *bitfill -= 5; return tab1[(cur_byte >> 3) & 7]; }else if((cur_byte & 0xe0) == 0x20){ *bitfill -= 6; return tab2[(cur_byte >> 2) & 7]; }else if((cur_byte & 0xf0) == 0x10){ *bitfill -= 7; return tab3[(cur_byte >> 1) & 7]; }else if((cur_byte & 0xf8) == 8){ *bitfill -= 8; return tab4[cur_byte & 7]; } return 0xff; } static int fun_F(int cur_byte, int *bitfill) { *bitfill -= 5; switch(cur_byte & 0xf8){ case 0x80: return 0; case 0x88: return -1; case 0x90: return 1; case 0x98: return -2; case 0xa0: return 2; case 0xa8: return -3; case 0xb0: return 3; case 0xb8: return -4; case 0xc0: return 4; case 0xc8: return -5; case 0xd0: return 5; case 0xd8: return -6; case 0xe0: return 6; case 0xe8: return -7; case 0xf0: return 7; case 0xf8: return -8; } *bitfill -= 1; switch(cur_byte & 0xfc){ case 0x40: return 8; case 0x44: return -9; case 0x48: return 9; case 0x4c: return -10; case 0x50: return 10; case 0x54: return -11; case 0x58: return 11; case 0x5c: return -12; case 0x60: return 12; case 0x64: return -13; case 0x68: return 13; case 0x6c: return -14; case 0x70: return 14; case 0x74: return -15; case 0x78: return 15; case 0x7c: return -16; } *bitfill -= 1; switch(cur_byte & 0xfe){ case 0x20: return 16; case 0x22: return -17; case 0x24: return 17; case 0x26: return -18; case 0x28: return 18; case 0x2a: return -19; case 0x2c: return 19; } *bitfill += 7; return 0xff; } int internal_spca561_decode(int width, int height, unsigned char *inbuf, unsigned char *outbuf) // {{{ { // buffers static int accum[8*8*8]; static int i_hits[8*8*8]; const static int nbits_A[] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, }; const static int tab_A[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,-11,4,4,5,5,6,6,7,7,8,8,9,9,10,10,255,254,-4,-4,-5,-5,-6,-6,-7,-7,-8,-8,-9,-9,-10,-10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,-2,-2,-2,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3,-3,-3,-3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 }; const static int nbits_B[] = { 0,8,7,7,6,6,6,6,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, }; const static int tab_B[] = { 0xff,-4,3,3,-3,-3,-3,-3,2,2,2,2,2,2,2,2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; const static int nbits_C[] = { 0,0,8,8,7,7,7,7,6,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, }; const static int tab_C[] = { 0xff,0xfe,6,-7,5,5,-6,-6,4,4,4,4,-5,-5,-5,-5,3,3,3,3,3,3,3,3,-4,-4,-4,-4,-4,-4,-4,-4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; const static int nbits_D[] = { 0,0,0,0,8,8,8,8,7,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 }; const static int tab_D[] = { 0xff,0xfe,0xfd,0xfc,10,-11,11,-12,8,8,-9,-9,9,9,-10,-10,6,6,6,6,-7,-7,-7,-7,7,7,7,7,-8,-8,-8,-8,4,4,4,4,4,4,4,4,-5,-5,-5,-5,-5,-5,-5,-5,5,5,5,5,5,5,5,5,-6,-6,-6,-6,-6,-6,-6,-6,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,-3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2 }; // a_curve[19 + i] = ... [-19..19] => [-160..160] const static int a_curve[] = { -160,-144,-128,-112,-98,-88,-80,-72,-64,-56,-48,-40,-32,-24,-18,-12,-8,-5,-2,0,2,5,8,12,18,24,32,40,48,56,64,72,80,88,98,112,128,144,160}; // clamp0_255[256 + i] = min(max(i,255),0) const static unsigned char clamp0_255[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}; // abs_clamp15[19 + i] = min(abs(i), 15) const static int abs_clamp15[] = { 15,15,15,15,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,15,15 }; // diff_encoding[256 + i] = ... const static int diff_encoding[] = { 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,3,3,3,3,1,1,0,2,2,4,4,4,4,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 }; int block; int bitfill = 0; int xwidth = width+6; int off_up_right = 2 - 2*xwidth; int off_up_left = -2 - 2*xwidth; int pixel_U = 0, saved_pixel_UR = 0; int pixel_x = 0, pixel_y = 2; unsigned char *output_ptr = outbuf; memset(i_hits, 0, sizeof(i_hits)); memset(accum, 0, sizeof(accum)); memcpy(outbuf + xwidth*2 + 3, inbuf + 0x14, width); memcpy(outbuf + xwidth*3 + 3, inbuf + 0x14 + width, width); input_ptr = inbuf + 0x14 + width * 2; output_ptr = outbuf + (xwidth)*4 + 3; bit_bucket = 0; for(block=0;block < ((height - 2) * width) / 32;++block){ int b_it, var_7=0; int cur_byte; refill(&bitfill); cur_byte = (bit_bucket >> (bitfill & 7)) & 0xff; if((cur_byte & 0x80) == 0){ var_7 = 0; bitfill--; }else if((cur_byte & 0xC0) == 0x80){ var_7 = 1; bitfill-=2; }else if((cur_byte & 0xc0) == 0xc0){ var_7 = 2; bitfill-=2; } for(b_it=0;b_it<32;b_it++){ int index; int pixel_L, pixel_UR, pixel_UL; int multiplier; int dL, dC, dR; int gkw; // God knows what refill(&bitfill); cur_byte = bit_bucket >> (bitfill & 7) & 0xff; pixel_L = output_ptr[-2]; pixel_UR = output_ptr[off_up_right]; pixel_UL = output_ptr[off_up_left]; dL = diff_encoding[0x100+pixel_UL - pixel_L]; dC = diff_encoding[0x100+pixel_U - pixel_UL]; dR = diff_encoding[0x100+pixel_UR - pixel_U]; if(pixel_x < 2){ pixel_L = pixel_UL = pixel_U = output_ptr[-xwidth*2]; pixel_UR = output_ptr[off_up_right]; dL = dC = 0; dR = diff_encoding[0x100+pixel_UR - pixel_U]; }else if(pixel_x > width - 3) dR = 0; multiplier = 4; index = dR+dC*8+dL*64; if(pixel_L + pixel_U * 2 <= 144 && (pixel_y & 1) == 0 && (b_it & 3) == 0 && (dR < 5) && (dC < 5) && (dL < 5)){ multiplier = 1; }else if(pixel_L <= 48 && dL <= 4 && dC <= 4 && dL >= 1 && dC >= 1){ multiplier = 2; }else if(var_7 == 1){ multiplier = 2; }else if(dC + dL >= 11 || var_7 == 2){ multiplier = 8; } if(i_hits[index] < 7){ bitfill -= nbits_A[cur_byte]; gkw = tab_A[cur_byte]; if(gkw == 0xfe) gkw = fun_A(&bitfill); }else if(i_hits[index] >= accum[index]){ bitfill -= nbits_B[cur_byte]; gkw = tab_B[cur_byte]; if(cur_byte == 0) gkw = fun_B(&bitfill); }else if(i_hits[index]*2 >= accum[index]){ bitfill -= nbits_C[cur_byte]; gkw = tab_C[cur_byte]; if(cur_byte < 2) gkw = fun_C(&bitfill, gkw); }else if(i_hits[index]*4 >= accum[index]){ bitfill -= nbits_D[cur_byte]; gkw = tab_D[cur_byte]; if(cur_byte < 4) gkw = fun_D(&bitfill, gkw); }else if(i_hits[index]*8 >= accum[index]){ gkw = fun_E(cur_byte, &bitfill); }else{ gkw = fun_F(cur_byte, &bitfill); } if(gkw == 0xff) return -3; { int tmp1, tmp2; tmp1 = (pixel_U + pixel_L)*3 - pixel_UL*2; tmp1 += (tmp1 < 0)?3:0; tmp2 = a_curve[19 + gkw] * multiplier; tmp2 += (tmp2 < 0)?1:0; *(output_ptr++) = clamp0_255[0x100 + (tmp1 >> 2) - (tmp2 >> 1)]; } pixel_U = saved_pixel_UR; saved_pixel_UR = pixel_UR; if(++pixel_x == width){ output_ptr += 6; pixel_x = 0; pixel_y++; } accum[index] += abs_clamp15[19 + gkw]; if(i_hits[index]++ == 15){ i_hits[index] = 8; accum[index] /= 2; } } } return 0; } void decode_spca561(unsigned char * inbuf, char * outbuf, int width, int height) { int i; static char tmpbuf[650*490]; if(internal_spca561_decode(width, height, inbuf, tmpbuf) == 0){ for(i=0;i marker) { if (le <= 16) in->bits = bi << 16, le += 16; return le; } while (le <= 24) { b = *in->p++; if(in->omitescape){ if (b == 0xff && (m = *in->p++) != 0) { in->marker = m; if (le <= 16) bi = bi << 16, le += 16; break; } } bi = bi << 8 | b; le += 8; } in->bits = bi; /* tmp... 2 return values needed */ return le; } #define LEBI_GET(in) (le = in->left, bi = in->bits) #define LEBI_PUT(in) (in->left = le, in->bits = bi) #define GETBITS(in, n) ( \ (le < (n) ? le = fillbits(in, le, bi), bi = in->bits : 0), \ (le -= (n)), \ bi >> le & ((1 << (n)) - 1) \ ) #define UNGETBITS(in, n) ( \ le += (n) \ ) static void dec_initscans(struct dec_data * decode) { struct jpginfo *info = &decode->info; struct scan *dscans = decode->dscans; int i; info->ns = 3; // HARDCODED here info->nm = info->dri + 1; // macroblock count info->rm = M_RST0; for (i = 0; i < info->ns; i++) dscans[i].dc = 0; } static int dec_readmarker(struct in *in) { int m; in->left = fillbits(in, in->left, in->bits); if ((m = in->marker) == 0) return 0; in->left = 0; in->marker = 0; return m; } static int dec_checkmarker(struct dec_data * decode) { struct jpginfo *info = &decode->info; struct scan *dscans = decode->dscans; struct in *in = &decode->in; int i; if (dec_readmarker(in) != info->rm) return -1; info->nm = info->dri; info->rm = (info->rm + 1) & ~0x08; for (i = 0; i < info->ns; i++) dscans[i].dc = 0; return 0; } void jpeg_reset_input_context (struct dec_data *decode, unsigned char *buf,int oescap) { /* set input context */ struct in *in = &decode->in; in->p = buf; in->omitescape = oescap; in->left = 0; in->bits = 0; in->marker = 0; } static int dec_rec2 (struct in *in, struct dec_hufftbl *hu, int *runp, int c, int i) { int le, bi; le = in->left; bi = in->bits; if (i) { UNGETBITS (in, i & 127); *runp = i >> 8 & 15; i >>= 16; } else { for (i = DECBITS; (c = ((c << 1) | GETBITS (in, 1))) >= (hu->maxcode[i]); i++) ; if (i >= 16) { in->marker = M_BADHUFF; return 0; } i = hu->vals[hu->valptr[i] + c - hu->maxcode[i - 1] * 2]; *runp = i >> 4; i &= 15; } if (i == 0) { /* sigh, 0xf0 is 11 bit */ LEBI_PUT (in); return 0; } /* receive part */ c = GETBITS (in, i); if (c < (1 << (i - 1))) c += (-1 << i) + 1; LEBI_PUT (in); return c; } #define DEC_REC(in, hu, r, i) ( \ r = GETBITS(in, DECBITS), \ i = hu->llvals[r], \ i & 128 ? \ ( \ UNGETBITS(in, i & 127), \ r = i >> 8 & 15, \ i >> 16 \ ) \ : \ ( \ LEBI_PUT(in), \ i = dec_rec2(in, hu, &r, r, i), \ LEBI_GET(in), \ i \ ) \ ) inline static void decode_mcus (struct in *in, int *dct, int n, struct scan *sc, int *maxp) { struct dec_hufftbl *hu; int i, r, t; int le, bi; memset (dct, 0, n * 64 * sizeof (*dct)); le = in->left; bi = in->bits; while (n-- > 0) { hu = sc->hudc.dhuff; *dct++ = (sc->dc += DEC_REC (in, hu, r, t)); hu = sc->huac.dhuff; i = 63; while (i > 0) { t = DEC_REC (in, hu, r, t); if (t == 0 && r == 0) { dct += i; break; } dct += r; *dct++ = t; i -= r + 1; } *maxp++ = 64 - i; if (n == sc->next) sc++; } LEBI_PUT (in); } static void dec_makehuff (struct dec_hufftbl *hu, int *hufflen, unsigned char *huffvals) { int code, k, i, j, d, x, c, v; for (i = 0; i < (1 << DECBITS); i++) hu->llvals[i] = 0; /* * llvals layout: * * value v already known, run r, backup u bits: * vvvvvvvvvvvvvvvv 0000 rrrr 1 uuuuuuu * value unknown, size b bits, run r, backup u bits: * 000000000000bbbb 0000 rrrr 0 uuuuuuu * value and size unknown: * 0000000000000000 0000 0000 0 0000000 */ code = 0; k = 0; for (i = 0; i < 16; i++, code <<= 1) { /* sizes */ hu->valptr[i] = k; for (j = 0; j < hufflen[i]; j++) { hu->vals[k] = *huffvals++; if (i < DECBITS) { c = code << (DECBITS - 1 - i); v = hu->vals[k] & 0x0f; /* size */ for (d = 1 << (DECBITS - 1 - i); --d >= 0;) { if (v + i < DECBITS) { /* both fit in table */ x = d >> (DECBITS - 1 - v - i); if (v && x < (1 << (v - 1))) x += (-1 << v) + 1; x = x << 16 | (hu-> vals[k] & 0xf0) << 4 | (DECBITS - (i + 1 + v)) | 128; } else x = v << 16 | (hu-> vals[k] & 0xf0) << 4 | (DECBITS - (i + 1)); hu->llvals[c | d] = x; } } code++; k++; } hu->maxcode[i] = code; } hu->maxcode[16] = 0x20000; /* always terminate decode */ } /****************************************************************/ /************** idct ***************/ /****************************************************************/ #define S22 ((long)IFIX(2 * 0.382683432)) #define C22 ((long)IFIX(2 * 0.923879532)) #define IC4 ((long)IFIX(1 / 0.707106781)) static unsigned char zig2[64] = { 0, 2, 3, 9, 10, 20, 21, 35, 14, 16, 25, 31, 39, 46, 50, 57, 5, 7, 12, 18, 23, 33, 37, 48, 27, 29, 41, 44, 52, 55, 59, 62, 15, 26, 30, 40, 45, 51, 56, 58, 1, 4, 8, 11, 19, 22, 34, 36, 28, 42, 43, 53, 54, 60, 61, 63, 6, 13, 17, 24, 32, 38, 47, 49 }; inline static void idct (int *in, int *out, int *quant, long off, int max) { long t0, t1, t2, t3, t4, t5, t6, t7; // t ; long tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; long tmp[64], *tmpp; int i, j, te; unsigned char *zig2p; t0 = off; if (max == 1) { t0 += in[0] * quant[0]; for (i = 0; i < 64; i++) out[i] = ITOINT (t0); return; } zig2p = zig2; tmpp = tmp; for (i = 0; i < 8; i++) { j = *zig2p++; t0 += in[j] * (long) quant[j]; j = *zig2p++; t5 = in[j] * (long) quant[j]; j = *zig2p++; t2 = in[j] * (long) quant[j]; j = *zig2p++; t7 = in[j] * (long) quant[j]; j = *zig2p++; t1 = in[j] * (long) quant[j]; j = *zig2p++; t4 = in[j] * (long) quant[j]; j = *zig2p++; t3 = in[j] * (long) quant[j]; j = *zig2p++; t6 = in[j] * (long) quant[j]; if ((t1 | t2 | t3 | t4 | t5 | t6 | t7) == 0) { tmpp[0 * 8] = t0; tmpp[1 * 8] = t0; tmpp[2 * 8] = t0; tmpp[3 * 8] = t0; tmpp[4 * 8] = t0; tmpp[5 * 8] = t0; tmpp[6 * 8] = t0; tmpp[7 * 8] = t0; tmpp++; t0 = 0; continue; } //IDCT; tmp0 = t0 + t1; t1 = t0 - t1; tmp2 = t2 - t3; t3 = t2 + t3; tmp2 = IMULT (tmp2, IC4) - t3; tmp3 = tmp0 + t3; t3 = tmp0 - t3; tmp1 = t1 + tmp2; tmp2 = t1 - tmp2; tmp4 = t4 - t7; t7 = t4 + t7; tmp5 = t5 + t6; t6 = t5 - t6; tmp6 = tmp5 - t7; t7 = tmp5 + t7; tmp5 = IMULT (tmp6, IC4); tmp6 = IMULT ((tmp4 + t6), S22); tmp4 = IMULT (tmp4, (C22 - S22)) + tmp6; t6 = IMULT (t6, (C22 + S22)) - tmp6; t6 = t6 - t7; t5 = tmp5 - t6; t4 = tmp4 - t5; tmpp[0 * 8] = tmp3 + t7; //t0; tmpp[1 * 8] = tmp1 + t6; //t1; tmpp[2 * 8] = tmp2 + t5; //t2; tmpp[3 * 8] = t3 + t4; //t3; tmpp[4 * 8] = t3 - t4; //t4; tmpp[5 * 8] = tmp2 - t5; //t5; tmpp[6 * 8] = tmp1 - t6; //t6; tmpp[7 * 8] = tmp3 - t7; //t7; tmpp++; t0 = 0; } for (i = 0, j = 0; i < 8; i++) { t0 = tmp[j + 0]; t1 = tmp[j + 1]; t2 = tmp[j + 2]; t3 = tmp[j + 3]; t4 = tmp[j + 4]; t5 = tmp[j + 5]; t6 = tmp[j + 6]; t7 = tmp[j + 7]; if ((t1 | t2 | t3 | t4 | t5 | t6 | t7) == 0) { te = ITOINT (t0); out[j + 0] = te; out[j + 1] = te; out[j + 2] = te; out[j + 3] = te; out[j + 4] = te; out[j + 5] = te; out[j + 6] = te; out[j + 7] = te; j += 8; continue; } //IDCT; tmp0 = t0 + t1; t1 = t0 - t1; tmp2 = t2 - t3; t3 = t2 + t3; tmp2 = IMULT (tmp2, IC4) - t3; tmp3 = tmp0 + t3; t3 = tmp0 - t3; tmp1 = t1 + tmp2; tmp2 = t1 - tmp2; tmp4 = t4 - t7; t7 = t4 + t7; tmp5 = t5 + t6; t6 = t5 - t6; tmp6 = tmp5 - t7; t7 = tmp5 + t7; tmp5 = IMULT (tmp6, IC4); tmp6 = IMULT ((tmp4 + t6), S22); tmp4 = IMULT (tmp4, (C22 - S22)) + tmp6; t6 = IMULT (t6, (C22 + S22)) - tmp6; t6 = t6 - t7; t5 = tmp5 - t6; t4 = tmp4 - t5; out[j + 0] = ITOINT (tmp3 + t7); out[j + 1] = ITOINT (tmp1 + t6); out[j + 2] = ITOINT (tmp2 + t5); out[j + 3] = ITOINT (t3 + t4); out[j + 4] = ITOINT (t3 - t4); out[j + 5] = ITOINT (tmp2 - t5); out[j + 6] = ITOINT (tmp1 - t6); out[j + 7] = ITOINT (tmp3 - t7); j += 8; } } static unsigned char zig[64] = { 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63 }; static int aaidct[8] = { IFIX (0.3535533906), IFIX (0.4903926402), IFIX (0.4619397663), IFIX (0.4157348062), IFIX (0.3535533906), IFIX (0.2777851165), IFIX (0.1913417162), IFIX (0.0975451610) }; inline static void idctqtab (unsigned char *qin, int *qout) { int i, j; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) qout[zig[i * 8 + j]] = qin[zig[i * 8 + j]] * IMULT (aaidct[i], aaidct[j]); } inline static void scaleidctqtab (int *q, int sc) { int i; for (i = 0; i < 64; i++) q[i] = IMULT (q[i], sc); } /* Reduce to the necessary minimum. FIXME */ void init_jpeg_decoder (struct usb_spca50x *spca50x, unsigned int qIndex) { unsigned int i, j, k, l; //unsigned int qIndex = 1; // 2; int tc, th, tt, tac, tdc; unsigned char *ptr; memcpy(spca50x->maindecode.comps,comp_template, MAXCOMP*sizeof(struct comp)); /* set up the huffman table */ ptr = (unsigned char *) GsmartJPEGHuffmanTable; l = GSMART_JPG_HUFFMAN_TABLE_LENGTH; while (l > 0) { int hufflen[16]; unsigned char huffvals[256]; tc = *ptr++; th = tc & 15; tc >>= 4; tt = tc * 2 + th; if (tc > 1 || th > 1) { //printf("died whilst setting up huffman table.\n"); //abort(); } for (i = 0; i < 16; i++) hufflen[i] = *ptr++; l -= 1 + 16; k = 0; for (i = 0; i < 16; i++) { for (j = 0; j < (unsigned int) hufflen[i]; j++) huffvals[k++] = *ptr++; l -= hufflen[i]; } dec_makehuff (dhuff + tt, hufflen, huffvals); } /* set up the scan table */ ptr = (unsigned char *) GsmartJPEGScanTable; for (i = 0; i < 3; i++) { spca50x->maindecode.dscans[i].cid = *ptr++; tdc = *ptr++; tac = tdc & 15; tdc >>= 4; if (tdc > 1 || tac > 1) { //printf("died whilst setting up scan table.\n"); //abort(); } /* for each component */ for (j = 0; j < 3; j++) if (spca50x->maindecode.comps[j].cid == spca50x->maindecode.dscans[i].cid) break; spca50x->maindecode.dscans[i].hv = spca50x->maindecode.comps[j].hv; spca50x->maindecode.dscans[i].tq = spca50x->maindecode.comps[j].tq; spca50x->maindecode.dscans[i].hudc.dhuff = dec_huffdc + tdc; spca50x->maindecode.dscans[i].huac.dhuff = dec_huffac + tac; } if (spca50x->maindecode.dscans[0].cid != 1 || spca50x->maindecode.dscans[1].cid != 2 || spca50x->maindecode.dscans[2].cid != 3) { //printf("invalid cid found.\n"); //abort(); } if (spca50x->maindecode.dscans[0].hv != 0x22 || spca50x->maindecode.dscans[1].hv != 0x11 || spca50x->maindecode.dscans[2].hv != 0x11) { //printf("invalid hv found.\n"); //abort(); } spca50x->maindecode.dscans[0].next = 6 - 4; spca50x->maindecode.dscans[1].next = 6 - 4 - 1; spca50x->maindecode.dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */ /* set up a quantization table */ for (i = 0; i < 2; i++) { for (j = 0; j < 64; j++) { spca50x->maindecode.quant[i][j] = GsmartQTable[qIndex * 2 + i][j]; } } idctqtab (spca50x->maindecode.quant[spca50x->maindecode.dscans[0].tq], spca50x->maindecode.dquant[0]); idctqtab (spca50x->maindecode.quant[spca50x->maindecode.dscans[1].tq], spca50x->maindecode.dquant[1]); idctqtab (spca50x->maindecode.quant[spca50x->maindecode.dscans[2].tq], spca50x->maindecode.dquant[2]); /* rescale qtab */ scaleidctqtab (spca50x->maindecode.dquant[0], IFIX (0.7)); scaleidctqtab (spca50x->maindecode.dquant[1], IFIX (0.7)); scaleidctqtab (spca50x->maindecode.dquant[2], IFIX (0.7)); } static int bgr = 0; /* Gamma correction setting */ /* Gtable[0][n] -> 2.2 * Gtable[1][n] -> 1.7 * Gtable[2][n] -> 1.45 * Gtable[3][n] -> 1 * Gtable[4][n] -> 0.6896 * Gtable[5][n] -> 0.5882 * Gtable[6][n] -> 0.4545 * gCor coeff 0..6 */ int spca50x_outpicture ( struct spca50x_frame *myframe ) { /* general idea keep a frame in the temporary buffer from the tasklet*/ /* decode with native format at input and asked format at output */ /* myframe->cameratype is the native input format */ /* myframe->format is the asked format */ struct pictparam *gCorrect = &myframe->pictsetting; unsigned char *red = myframe->decoder->Red; unsigned char *green = myframe->decoder->Green; unsigned char * blue = myframe->decoder->Blue; int width = 0; int height = 0; int done = 0; int i; if (gCorrect->change) { if ( gCorrect->change == 0x01) { /* Gamma setting change compute all case */ memcpy (red,>able[gCorrect->gamma],256); memcpy (green,>able[gCorrect->gamma],256); memcpy (blue,>able[gCorrect->gamma],256); for (i =0; i < 256 ; i++){ red[i] = CLIP(((red[i] + gCorrect->OffRed) * gCorrect->GRed) >> 8); green[i] = CLIP(((green[i] + gCorrect->OffGreen) * gCorrect->GGreen) >> 8); blue[i] = CLIP(((blue[i] + gCorrect->OffBlue) * gCorrect->GBlue) >> 8); } bgr = gCorrect->force_rgb; gCorrect->change = 0x00; } if ( gCorrect->change == 0x02) { /* Red setting change compute Red Value */ memcpy (red,>able[gCorrect->gamma],256); for (i =0; i < 256 ; i++){ red[i] = CLIP(((red[i] + gCorrect->OffRed) * gCorrect->GRed) >> 8); } gCorrect->change &= ~0x02; } if ( gCorrect->change == 0x04) { /* Green setting change compute Green Value */ memcpy (green,>able[gCorrect->gamma],256); for (i =0; i < 256 ; i++){ green[i] = CLIP(((green[i] + gCorrect->OffGreen) * gCorrect->GGreen) >> 8); } gCorrect->change &= ~0x04; } if ( gCorrect->change == 0x08) { /* Blue setting change compute Blue Value */ memcpy (blue,>able[gCorrect->gamma],256); for (i =0; i < 256 ; i++){ blue[i] = CLIP(((blue[i] + gCorrect->OffBlue) * gCorrect->GBlue) >> 8); } gCorrect->change &= ~0x08; } if ( gCorrect->change == 0x10) { /* force_rgb setting change */ bgr = gCorrect->force_rgb; gCorrect->change &= ~0x10; } } switch(myframe->cameratype){ case JPGC: height = (myframe->data[11] << 8) | myframe->data[12]; width = (myframe->data[13] << 8) | myframe->data[14]; if (myframe->hdrheight != height || myframe->hdrwidth != width){ done = ERR_CORRUPTFRAME; } else { //set info.dri struct should be kmalloc with the // instance camera myframe->decoder->info.dri = myframe->data[5]; if (myframe->format == VIDEO_PALETTE_JPEG){ memcpy(myframe->tmpbuffer,myframe->data,myframe->scanlength); done = make_jpeg_conexant ( myframe ); } else { memcpy(myframe->tmpbuffer,myframe->data + 39,myframe->scanlength - 39); done = jpeg_decode422( myframe, bgr); } } break; case JPGH: width = (myframe->data[10] << 8) | myframe->data[11]; height = (myframe->data[12] << 8) | myframe->data[13]; /* some camera did not respond with the good height ie:Labtec Pro 240 -> 232 */ if (myframe->hdrwidth != width){ done = ERR_CORRUPTFRAME; } else { // reset info.dri myframe->decoder->info.dri = 0; memcpy(myframe->tmpbuffer,myframe->data+16,myframe->scanlength - 16); if (myframe->format == VIDEO_PALETTE_JPEG){ done = make_jpeg ( myframe ); } else { done = jpeg_decode422( myframe, bgr); } } break; case JPGM: case JPGS: // reset info.dri myframe->decoder->info.dri = 0; memcpy(myframe->tmpbuffer,myframe->data,myframe->scanlength ); if (myframe->format == VIDEO_PALETTE_JPEG){ done = make_jpeg ( myframe ); } else { done = jpeg_decode422( myframe, bgr); } break; case JPEG: memcpy(myframe->tmpbuffer,myframe->data,myframe->scanlength); if (myframe->format == VIDEO_PALETTE_JPEG){ done = make_jpeg ( myframe ); } else { done = jpeg_decode411( myframe, bgr); } break; case YUVY: case YUYV: case YYUV: memcpy(myframe->tmpbuffer,myframe->data,myframe->scanlength); done = yuv_decode( myframe, bgr); break; case PGBRG: done = pixart_preprocess(myframe); if (done < 0) break; done = bayer_decode( myframe,bgr); break; case GBGR: /* translate the tv8532 stream into GBRG stream */ tv8532_preprocess(myframe); done = bayer_decode( myframe, bgr); break; case GBRG: memcpy(myframe->tmpbuffer,myframe->data,myframe->scanlength); done = bayer_decode( myframe, bgr); break; case S561: if(myframe->data[1] & 0x10){ decode_spca561(myframe->data, myframe->tmpbuffer, myframe->width, myframe->height); }else{ memcpy(myframe->tmpbuffer,myframe->data+20,myframe->scanlength); } done = bayer_decode( myframe, bgr); break; case SN9C: sonix_decompress(myframe->hdrwidth,myframe->hdrheight,myframe->data,myframe->tmpbuffer); done = bayer_decode( myframe, bgr); break; default : done = -1; break; } return done; } static int yuv_decode(struct spca50x_frame *myframe, int force_rgb ) { int r_offset, g_offset, b_offset; int my , mx; /* scan input surface */ unsigned char *pic1; /* output surface */ __u16 *pix1,*pix2; /* same for 16 bits output */ unsigned char *U, *V; /* chroma output pointer */ int inuv, inv, pocx; /* offset chroma input */ int iny,iny1; /* offset luma input */ int nextinline, nextoutline; int u1,v1,rg; unsigned char y,y1; char u,v; unsigned char *pic = myframe->data; /* output surface */ unsigned char *buf = myframe->tmpbuffer; /* input surface */ int width = myframe->hdrwidth; int height = myframe->hdrheight; int softwidth = myframe->width; int softheight = myframe->height; //int method = myframe->method; int format = myframe->format; int cropx1 = myframe->cropx1; int cropx2 = myframe->cropx2; int cropy1 = myframe->cropy1; int cropy2 = myframe->cropy2; unsigned char *red = myframe->decoder->Red; unsigned char *green = myframe->decoder->Green; unsigned char * blue = myframe->decoder->Blue; int bpp; int framesize, frameUsize; framesize = softwidth * softheight; frameUsize = framesize >> 2; /* rgb or bgr like U or V that's the question */ if (force_rgb) { U = pic + framesize; V = U + frameUsize; r_offset = 2; g_offset = 1; b_offset = 0; } else { V = pic + framesize; U = V + frameUsize; r_offset = 0; g_offset = 1; b_offset = 2; } switch (myframe->cameratype) { case YUVY: { iny = 0; /********* iny **********/ inuv = width; /*** inuv **** inv ******/ nextinline = 3 * width; inv = ( nextinline >> 1); iny1 = width << 1; /********* iny1 *********/ } break; case YUYV: { iny = 0; /********* iny **********/ inuv = width; /*** inuv **** iny1 *****/ nextinline = 3 * width; iny1 = ( nextinline >> 1); inv = iny1 + width ;/*** iny1 **** inv ******/ } break; case YYUV: { iny = 0; /********* iny **********/ iny1 = width; /********* iny1 *********/ inuv = width << 1; /*** inuv **** inv ******/ inv = inuv +(width >>1); nextinline = 3 * width; } break; default: { iny = 0 ; /* make compiler happy */ iny1 = 0; inuv = 0; inv = 0 ; nextinline = 0; } break; } /* Decode to the correct format. */ switch (format) { case VIDEO_PALETTE_RGB565: { bpp = 2; /* initialize */ pix1 = (__u16*) pic; pix2 = pix1 + softwidth; for ( my =0; my < height; my += 2){ for ( mx = 0, pocx = 0; mx < width ; mx += 2, pocx++){ /* test if we need to decode */ if ((my >= cropy1) && (my < height - cropy2) && (mx >= cropx1) && (mx < width - cropx2)) { /* yes decode */ if ( force_rgb ){ u = buf [inuv + pocx] ; v = buf [inv + pocx] ; } else { v = buf [inuv + pocx] ; u = buf [inv + pocx] ; } v1 = ((v << 10) + (v << 9)) >> 10; rg = ((u << 8) + (u << 7) + (v << 9) + (v << 4)) >> 10; u1 = ((u << 11) + (u << 4)) >> 10; /* top pixel Right */ y1 = 128 +buf [iny + mx]; *pix1++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3 | ((green[CLIP((y1 - rg))] & 0xFC) << 3) | ((blue[CLIP((y1 + u1))] & 0xF8) << 8)) ; /* top pixel Left */ y1 = 128 +buf [iny + mx +1]; *pix1++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3 | ((green[CLIP((y1 - rg))] & 0xFC) << 3) | ((blue[CLIP((y1 + u1))] & 0xF8) << 8)) ; /* bottom pixel Right */ y1 = 128 + buf [iny1 + mx]; *pix2++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3 | ((green[CLIP((y1 - rg))] & 0xFC) << 3) | ((blue[CLIP((y1 + u1))] & 0xF8) << 8)) ; /* bottom pixel Left */ y1 = 128 + buf [iny1 + mx + 1]; *pix2++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3 | ((green[CLIP((y1 - rg))] & 0xFC) << 3) | ((blue[CLIP((y1 + u1))] & 0xF8) << 8)) ; } // end test decode } // end mx loop iny += nextinline; inuv += nextinline ; inv += nextinline ; iny1 += nextinline; if (my >= cropy1){ /* are we in a decode surface move the output pointer */ pix1 += softwidth ; pix2 += softwidth ; } } // end my loop } myframe->scanlength = (long)(softwidth*softheight*bpp); break; case VIDEO_PALETTE_RGB32: case VIDEO_PALETTE_RGB24: { bpp = (format == VIDEO_PALETTE_RGB32) ? 4 : 3; /* initialize */ nextoutline = bpp * softwidth; pic1 = pic + nextoutline; for ( my =0; my < height; my += 2){ for ( mx = 0, pocx = 0; mx < width ; mx += 2, pocx++){ /* test if we need to decode */ if ((my >= cropy1) && (my < height - cropy2) && (mx >= cropx1) && (mx < width - cropx2)) { /* yes decode */ v = buf [inuv + pocx] ; u = buf [inv + pocx] ; v1 = ((v << 10) + (v << 9)) >> 10; rg = ((u << 8) + (u << 7) + (v << 9) + (v << 4)) >> 10; u1 = ((u << 11) + (u << 4)) >> 10; y = 128 +buf [iny + mx]; /* top pixel Right */ pic[r_offset] = red[CLIP ((y + v1))]; pic[g_offset] = green[CLIP ((y - rg))]; pic[b_offset] = blue[CLIP ((y + u1))]; pic += bpp; /* top pixel Left */ y = 128 +buf [iny + mx +1]; pic[r_offset] = red[CLIP ((y + v1))]; pic[g_offset] = green[CLIP ((y - rg))]; pic[b_offset] = blue[CLIP ((y + u1))]; pic += bpp; /* bottom pixel Right */ y1 = 128 + buf [iny1 + mx]; pic1[r_offset] = red[CLIP ((y1 + v1))]; pic1[g_offset] = green[CLIP ((y1 - rg))]; pic1[b_offset] = blue[CLIP ((y1 + u1))]; pic1 += bpp; /* bottom pixel Left */ y1 = 128 + buf [iny1 + mx + 1]; pic1[r_offset] = red[CLIP ((y1 + v1))]; pic1[g_offset] = green[CLIP ((y1 - rg))]; pic1[b_offset] = blue[CLIP ((y1 + u1))]; pic1 += bpp; } // end test decode } // end mx loop iny += nextinline; inuv += nextinline ; inv += nextinline ; iny1 += nextinline; if (my >= cropy1){ /* are we in a decode surface move the output pointer */ pic += nextoutline; pic1 += nextoutline; } } // end my loop } myframe->scanlength = (long)(softwidth*softheight*bpp); break; case VIDEO_PALETTE_YUV420P: { /* initialize */ pic1 = pic + softwidth; for ( my =0; my < height; my += 2){ for ( mx = 0, pocx=0; mx < width ; mx +=2, pocx++){ /* test if we need to decode */ if ((my >= cropy1) && (my < height - cropy2) && (mx >= cropx1) && (mx < width - cropx2)) { /* yes decode */ *V++ = 128 + buf [inuv + pocx]; *U++ = 128 + buf [inv + pocx] ; *pic++ = 128 +buf [iny + mx]; *pic++ = 128 +buf [iny + mx+1]; *pic1++ = 128 + buf [iny1 + mx]; *pic1++ = 128 + buf [iny1 + mx +1]; } // end test decode } // end mx loop iny += nextinline; inuv += nextinline; inv += nextinline; iny1 += nextinline; if (my >= cropy1){ /* are we in a decode surface move the output pointer */ pic += softwidth; pic1 += softwidth; } } // end my loop } myframe->scanlength = (long)(softwidth*softheight*3)>>1; break; default: break; }// end case return 0; } /* * linux/drivers/video/fbcon-jpegdec.c - a tiny jpeg decoder. * * (w) August 2001 by Michael Schroeder, * * I severly gutted this beast and hardcoded it to the palette and subset * of jpeg needed for the spca50x driver. Also converted it from K&R style * C to a more modern form ;). Michael can't be blamed for what is left. * All nice features are his, all bugs are mine. - till * * Change color space converter for YUVP and RGB - * Rework the IDCT implementation for best speed, cut test in the loop but instead * more copy and paste code :) * For more details about idct look at : * http://rnvs.informatik.tu-chemnitz.de/~jan/MPEG/HTML/IDCT.html * 12/12/2003 mxhaard@magic.fr * add make jpeg from header (mxhaard 20/09/2004) * add jpeg_decode for 422 stream (mxhaard 01/10/2004) */ static int jpeg_decode411 (struct spca50x_frame *myframe, int force_rgb) { int mcusx, mcusy, mx, my; int *dcts = myframe->dcts; int *out =myframe->out; int *max=myframe->max; // int i; int bpp; int framesize, frameUsize; int k, j; int nextline, nextuv, nextblk, nextnewline; unsigned char *pic0, *pic1, *outv, *outu; __u16 *pix1,*pix2; int picy, picx, pocx, pocy; unsigned char *U, *V; int *outy, *inv, *inu; int outy1, outy2; int v, u, y1, v1, u1, u2; int r_offset, g_offset, b_offset; unsigned char *pic = myframe->data; /* output surface */ unsigned char *buf = myframe->tmpbuffer; /* input surface */ int width = myframe->hdrwidth; int height = myframe->hdrheight; int softwidth = myframe->width; int softheight = myframe->height; //int method = myframe->method; int format = myframe->format; int cropx1 = myframe->cropx1; int cropx2 = myframe->cropx2; int cropy1 = myframe->cropy1; int cropy2 = myframe->cropy2; unsigned char *red = myframe->decoder->Red; unsigned char *green = myframe->decoder->Green; unsigned char * blue = myframe->decoder->Blue; struct dec_data *decode= myframe->decoder; if ((height & 15) || (width & 15)) return 1; if (width < softwidth || height < softheight) return 1; mcusx = width >> 4; mcusy = height >> 4; framesize = softwidth * softheight; frameUsize = framesize >> 2; jpeg_reset_input_context (decode,buf,0); /* for each component. Reset dc values. */ //for (i = 0; i < 3; i++) //dscans[i].dc = 0; dec_initscans(decode); /* rgb or bgr like U or V that's the question */ if (force_rgb) { U = pic + framesize; V = U + frameUsize; r_offset = 2; g_offset = 1; b_offset = 0; } else { V = pic + framesize; U = V + frameUsize; r_offset = 0; g_offset = 1; b_offset = 2; } /* Decode to the correct format. */ switch (format) { case VIDEO_PALETTE_RGB565: { bpp = 2; nextline = ((softwidth << 1) - 16);// *bpp; nextblk = bpp * (softwidth << 4); nextnewline = softwidth ; // *bpp; for (my = 0, picy = 0; my < mcusy; my++) { for (mx = 0, picx = 0; mx < mcusx; mx++) { decode_mcus (&decode->in, dcts, 6, decode->dscans, max); if ((my >= cropy1) && (my < mcusy - cropy2) && (mx >= cropx1) && (mx < mcusx - cropx2)) { idct (dcts, out, decode->dquant[0], IFIX (128.5), max[0]); idct (dcts + 64, out + 64, decode->dquant[0], IFIX (128.5), max[1]); idct (dcts + 128, out + 128, decode->dquant[0], IFIX (128.5), max[2]); idct (dcts + 192, out + 192, decode->dquant[0], IFIX (128.5), max[3]); idct (dcts + 256, out + 256, decode->dquant[1], IFIX (0.5), max[4]); idct (dcts + 320, out + 320, decode->dquant[2], IFIX (0.5), max[5]); pix1 = (__u16 *)(pic + picx + picy); pix2 = pix1 + nextnewline; outy = out; outy1 = 0; outy2 = 8; inv = out + 64 * 4; inu = out + 64 * 5; for (j = 0; j < 8; j++) { for (k = 0; k < 8; k++) { if (k == 4) { outy1 += 56; outy2 += 56; } /* outup 4 pixels */ /* get the UV colors need to change UV order for force rgb? */ if ( force_rgb){ u = *inv++; v = *inu++; } else { v = *inv++; u = *inu++; } /* MX color space why not? */ v1 = ((v << 10) + (v << 9)) >> 10; u1 = ((u << 8) + (u << 7) + (v << 9) + (v << 4)) >> 10; u2 = ((u << 11) + (u << 4)) >> 10; /* top pixel Right */ y1 = outy[outy1++]; *pix1++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3 | ((green[CLIP((y1 - u1))] & 0xFC) << 3) | ((blue[CLIP((y1 + u2))] & 0xF8) << 8)) ; /* top pixel Left */ y1 = outy[outy1++]; *pix1++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3 | ((green[CLIP((y1 - u1))] & 0xFC) << 3) | ((blue[CLIP((y1 + u2))] & 0xF8) << 8)) ; /* bottom pixel Right */ y1 = outy[outy2++]; *pix2++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3 | ((green[CLIP((y1 - u1))] & 0xFC) << 3) | ((blue[CLIP((y1 + u2))] & 0xF8) << 8)) ; /* bottom pixel Left */ y1 = outy[outy2++]; *pix2++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3| ((green[CLIP((y1 - u1))] & 0xFC) << 3) | ((blue[CLIP((y1 + u2))] & 0xF8) << 8)) ; } if (j == 3) { outy = out + 128; } else { outy += 16; } outy1 = 0; outy2 = 8; pix1 += nextline; pix2 += nextline; } picx += 16 * bpp; } } if (my >= cropy1) picy += nextblk; } } myframe->scanlength = (long)(softwidth*softheight*bpp); break; case VIDEO_PALETTE_RGB32: case VIDEO_PALETTE_RGB24: { bpp = (format == VIDEO_PALETTE_RGB32) ? 4 : 3; nextline = bpp * ((softwidth << 1) - 16); nextblk = bpp * (softwidth << 4); nextnewline = bpp * softwidth; for (my = 0, picy = 0; my < mcusy; my++) { for (mx = 0, picx = 0; mx < mcusx; mx++) { decode_mcus (&decode->in, dcts, 6, decode->dscans, max); if ((my >= cropy1) && (my < mcusy - cropy2) && (mx >= cropx1) && (mx < mcusx - cropx2)) { idct (dcts, out, decode->dquant[0], IFIX (128.5), max[0]); idct (dcts + 64, out + 64, decode->dquant[0], IFIX (128.5), max[1]); idct (dcts + 128, out + 128, decode->dquant[0], IFIX (128.5), max[2]); idct (dcts + 192, out + 192, decode->dquant[0], IFIX (128.5), max[3]); idct (dcts + 256, out + 256, decode->dquant[1], IFIX (0.5), max[4]); idct (dcts + 320, out + 320, decode->dquant[2], IFIX (0.5), max[5]); pic0 = pic + picx + picy; pic1 = pic0 + nextnewline; outy = out; outy1 = 0; outy2 = 8; inv = out + 64 * 4; inu = out + 64 * 5; for (j = 0; j < 8; j++) { for (k = 0; k < 8; k++) { if (k == 4) { outy1 += 56; outy2 += 56; } /* outup 4 pixels */ /* get the UV colors need to change UV order for force rgb? */ v = *inv++; u = *inu++; /* MX color space why not? */ v1 = ((v << 10) + (v << 9)) >> 10; u1 = ((u << 8) + (u << 7) + (v << 9) + (v << 4)) >> 10; u2 = ((u << 11) + (u << 4)) >> 10; /* top pixel Right */ y1 = outy[outy1++]; pic0[r_offset] = red[CLIP ((y1 + v1))]; pic0[g_offset] = green[CLIP ((y1 - u1))]; pic0[b_offset] = blue[CLIP ((y1 + u2))]; pic0 += bpp; /* top pixel Left */ y1 = outy[outy1++]; pic0[r_offset] = red[CLIP ((y1 + v1))]; pic0[g_offset] = green[CLIP ((y1 - u1))]; pic0[b_offset] = blue[CLIP ((y1 + u2))]; pic0 += bpp; /* bottom pixel Right */ y1 = outy[outy2++]; pic1[r_offset] = red[CLIP ((y1 + v1))]; pic1[g_offset] = green[CLIP ((y1 - u1))]; pic1[b_offset] = blue[CLIP ((y1 + u2))]; pic1 += bpp; /* bottom pixel Left */ y1 = outy[outy2++]; pic1[r_offset] = red[CLIP ((y1 + v1))]; pic1[g_offset] = green[CLIP ((y1 - u1))]; pic1[b_offset] = blue[CLIP ((y1 + u2))]; pic1 += bpp; } if (j == 3) { outy = out + 128; } else { outy += 16; } outy1 = 0; outy2 = 8; pic0 += nextline; pic1 += nextline; } picx += 16 * bpp; } } if (my >= cropy1) picy += nextblk; } } myframe->scanlength = (long)(softwidth*softheight*bpp); break; case VIDEO_PALETTE_YUV420P: { nextline = (softwidth << 1) - 16; nextuv = (softwidth >> 1) - 8; nextblk = softwidth << 4; nextnewline = softwidth << 2; for (my = 0, picy = 0, pocy = 0; my < mcusy; my++) { for (mx = 0, picx = 0, pocx = 0; mx < mcusx; mx++) { decode_mcus (&decode->in, dcts, 6, decode->dscans, max); if ((my >= cropy1) && (my < mcusy - cropy2) && (mx >= cropx1) && (mx < mcusx - cropx2)) { idct (dcts, out, decode->dquant[0], IFIX (128.5), max[0]); idct (dcts + 64, out + 64, decode->dquant[0], IFIX (128.5), max[1]); idct (dcts + 128, out + 128, decode->dquant[0], IFIX (128.5), max[2]); idct (dcts + 192, out + 192, decode->dquant[0], IFIX (128.5), max[3]); idct (dcts + 256, out + 256, decode->dquant[1], IFIX (0.5), max[4]); idct (dcts + 320, out + 320, decode->dquant[2], IFIX (0.5), max[5]); pic0 = pic + picx + picy; pic1 = pic0 + softwidth; outv = V + (pocx + pocy); outu = U + (pocx + pocy); outy = out; outy1 = 0; outy2 = 8; inv = out + 64 * 4; inu = out + 64 * 5; for (j = 0; j < 8; j++) { for (k = 0; k < 8; k++) { if (k == 4) { outy1 += 56; outy2 += 56; } /* outup 4 pixels */ *pic0++ = outy[outy1++]; *pic0++ = outy[outy1++]; *pic1++ = outy[outy2++]; *pic1++ = outy[outy2++]; *outv++ = 128 + *inv++; *outu++ = 128 + *inu++; } if (j == 3) { outy = out + 128; } else { outy += 16; } outy1 = 0; outy2 = 8; pic0 += nextline; pic1 += nextline; outv += nextuv; outu += nextuv; } picx += 16; pocx += 8; } } if (my >= cropy1) { picy += nextblk; pocy += nextnewline; } } } myframe->scanlength = (long)((softwidth*softheight*3)>>1); break; default: break; } // end case return 0; } static int jpeg_decode422 (struct spca50x_frame *myframe, int force_rgb) { int mcusx, mcusy, mx, my; int *dcts = myframe->dcts; int *out =myframe->out; int *max=myframe->max; int bpp; int framesize, frameUsize; int k, j; int nextline, nextuv, nextblk, nextnewline; unsigned char *pic0, *pic1, *outv, *outu; __u16 *pix1,*pix2; int picy, picx, pocx, pocy; unsigned char *U, *V; int *outy, *inv, *inu; int outy1, outy2; int v, u, y1, v1, u1, u2; int r_offset, g_offset, b_offset; unsigned char *pic = myframe->data; /* output surface */ unsigned char *buf = myframe->tmpbuffer; /* input surface */ int width = myframe->hdrwidth; int height = myframe->hdrheight; int softwidth = myframe->width; int softheight = myframe->height; //int method = myframe->method; int format = myframe->format; int cropx1 = myframe->cropx1; int cropx2 = myframe->cropx2; int cropy1 = myframe->cropy1; int cropy2 = myframe->cropy2; unsigned char *red = myframe->decoder->Red; unsigned char *green = myframe->decoder->Green; unsigned char * blue = myframe->decoder->Blue; struct dec_data *decode= myframe->decoder; if ((height & 15) || (width & 7)) return 1; if (width < softwidth || height < softheight) return 1; mcusx = width >> 4; mcusy = height >> 3; framesize = softwidth * softheight; frameUsize = framesize >> 2; jpeg_reset_input_context (decode,buf,1); /* for each component. Reset dc values. */ dec_initscans(decode); /* rgb or bgr like U or V that's the question */ if (force_rgb) { U = pic + framesize; V = U + frameUsize; r_offset = 2; g_offset = 1; b_offset = 0; } else { V = pic + framesize; U = V + frameUsize; r_offset = 0; g_offset = 1; b_offset = 2; } /* Decode to the correct format. */ switch (format) { case VIDEO_PALETTE_RGB565: { bpp = 2; nextline = ((softwidth << 1) - 16);// *bpp; nextblk = bpp * (softwidth << 3); nextnewline = softwidth ; // *bpp; for (my = 0, picy = 0; my < mcusy; my++) { for (mx = 0, picx = 0; mx < mcusx; mx++) { if (decode->info.dri && !--decode->info.nm) if (dec_checkmarker(decode)) return ERR_WRONG_MARKER; decode_mcus (&decode->in, dcts, 4, decode->dscans, max); if ((my >= cropy1) && (my < mcusy - cropy2) && (mx >= cropx1) && (mx < mcusx - cropx2)) { idct (dcts, out, decode->dquant[0], IFIX (128.5), max[0]); idct (dcts + 64, out + 64, decode->dquant[0], IFIX (128.5), max[1]); idct (dcts + 128, out + 256, decode->dquant[1], IFIX (0.5), max[2]); idct (dcts + 192, out + 320, decode->dquant[2], IFIX (0.5), max[3]); pix1 = (__u16 *)(pic + picx + picy); pix2 = pix1 + nextnewline; outy = out; outy1 = 0; outy2 = 8; inv = out + 64 * 4; inu = out + 64 * 5; for (j = 0; j < 4; j++) { for (k = 0; k < 8; k++) { if (k == 4) { outy1 += 56; outy2 += 56; } /* outup 4 pixels Colors are treated as 411 */ /* get the UV colors need to change UV order for force rgb? */ if ( force_rgb){ u = *inv++; v = *inu++; } else { v = *inv++; u = *inu++; } /* MX color space why not? */ v1 = ((v << 10) + (v << 9)) >> 10; u1 = ((u << 8) + (u << 7) + (v << 9) + (v << 4)) >> 10; u2 = ((u << 11) + (u << 4)) >> 10; /* top pixel Right */ y1 = outy[outy1++]; *pix1++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3 | ((green[CLIP((y1 - u1))] & 0xFC) << 3) | ((blue[CLIP((y1 + u2))] & 0xF8) << 8)) ; /* top pixel Left */ y1 = outy[outy1++]; *pix1++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3 | ((green[CLIP((y1 - u1))] & 0xFC) << 3) | ((blue[CLIP((y1 + u2))] & 0xF8) << 8)) ; /* bottom pixel Right */ y1 = outy[outy2++]; *pix2++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3 | ((green[CLIP((y1 - u1))] & 0xFC) << 3) | ((blue[CLIP((y1 + u2))] & 0xF8) << 8)) ; /* bottom pixel Left */ y1 = outy[outy2++]; *pix2++ = ((red[CLIP((y1 + v1))] & 0xF8) >> 3| ((green[CLIP((y1 - u1))] & 0xFC) << 3) | ((blue[CLIP((y1 + u2))] & 0xF8) << 8)) ; } outy += 16; outy1 = 0; outy2 = 8; pix1 += nextline; pix2 += nextline; } picx += 16 * bpp; } } if (my >= cropy1) picy += nextblk; } } myframe->scanlength = (long)(softwidth*softheight*bpp); break; case VIDEO_PALETTE_RGB32: case VIDEO_PALETTE_RGB24: { bpp = (format == VIDEO_PALETTE_RGB32) ? 4 : 3; nextline = bpp * ((softwidth << 1) - 16); nextblk = bpp * (softwidth << 3); nextnewline = bpp * softwidth; for (my = 0, picy = 0; my < mcusy; my++) { for (mx = 0, picx = 0; mx < mcusx; mx++) { if (decode->info.dri && !--decode->info.nm) if (dec_checkmarker(decode)) return ERR_WRONG_MARKER; decode_mcus (&decode->in, dcts, 4, decode->dscans, max); if ((my >= cropy1) && (my < mcusy - cropy2) && (mx >= cropx1) && (mx < mcusx - cropx2)) { idct (dcts, out, decode->dquant[0], IFIX (128.5), max[0]); idct (dcts + 64, out + 64, decode->dquant[0], IFIX (128.5), max[1]); idct (dcts + 128, out + 256, decode->dquant[1], IFIX (0.5), max[2]); idct (dcts + 192, out + 320, decode->dquant[2], IFIX (0.5), max[3]); pic0 = pic + picx + picy; pic1 = pic0 + nextnewline; outy = out; outy1 = 0; outy2 = 8; inv = out + 64 * 4; inu = out + 64 * 5; for (j = 0; j < 4; j++) { for (k = 0; k < 8; k++) { if (k == 4) { outy1 += 56; outy2 += 56; } /* outup 4 pixels Colors are treated as 411 */ v = *inv++; u = *inu++; /* MX color space why not? */ v1 = ((v << 10) + (v << 9)) >> 10; u1 = ((u << 8) + (u << 7) + (v << 9) + (v << 4)) >> 10; u2 = ((u << 11) + (u << 4)) >> 10; /* top pixel Right */ y1 = outy[outy1++]; pic0[r_offset] = red[CLIP ((y1 + v1))]; pic0[g_offset] = green[CLIP ((y1 - u1))]; pic0[b_offset] = blue[CLIP ((y1 + u2))]; pic0 += bpp; /* top pixel Left */ y1 = outy[outy1++]; pic0[r_offset] = red[CLIP ((y1 + v1))]; pic0[g_offset] = green[CLIP ((y1 - u1))]; pic0[b_offset] = blue[CLIP ((y1 + u2))]; pic0 += bpp; /* bottom pixel Right */ y1 = outy[outy2++]; pic1[r_offset] = red[CLIP ((y1 + v1))]; pic1[g_offset] = green[CLIP ((y1 - u1))]; pic1[b_offset] = blue[CLIP ((y1 + u2))]; pic1 += bpp; /* bottom pixel Left */ y1 = outy[outy2++]; pic1[r_offset] = red[CLIP ((y1 + v1))]; pic1[g_offset] = green[CLIP ((y1 - u1))]; pic1[b_offset] = blue[CLIP ((y1 + u2))]; pic1 += bpp; } outy += 16; outy1 = 0; outy2 = 8; pic0 += nextline; pic1 += nextline; } picx += 16 * bpp; } } if (my >= cropy1) picy += nextblk; } } myframe->scanlength = (long)(softwidth*softheight*bpp); break; case VIDEO_PALETTE_YUV420P: { nextline = (softwidth << 1) - 16; nextuv = (softwidth >> 1) - 8; nextblk = softwidth << 3; nextnewline = softwidth << 1;//2 for (my = 0, picy = 0, pocy = 0; my < mcusy; my++) { for (mx = 0, picx = 0, pocx = 0; mx < mcusx; mx++) { if (decode->info.dri && !--decode->info.nm) if (dec_checkmarker(decode)) return ERR_WRONG_MARKER; decode_mcus (&decode->in, dcts, 4, decode->dscans, max); if ((my >= cropy1) && (my < mcusy - cropy2) && (mx >= cropx1) && (mx < mcusx - cropx2)) { idct (dcts, out, decode->dquant[0], IFIX (128.5), max[0]); idct (dcts + 64, out + 64, decode->dquant[0], IFIX (128.5), max[1]); idct (dcts + 128, out + 256, decode->dquant[1], IFIX (0.5), max[2]); idct (dcts + 192, out + 320, decode->dquant[2], IFIX (0.5), max[3]); pic0 = pic + picx + picy; pic1 = pic0 + softwidth; outv = V + (pocx + pocy); outu = U + (pocx + pocy); outy = out; outy1 = 0; outy2 = 8; inv = out + 64 * 4; inu = out + 64 * 5; for (j = 0; j < 4; j++) { for (k = 0; k < 8; k++) { if (k == 4) { outy1 += 56; outy2 += 56; } /* outup 4 pixels */ *pic0++ = CLIP(outy[outy1]);outy1++; *pic0++ = CLIP(outy[outy1]);outy1++; *pic1++ = CLIP(outy[outy2]);outy2++; *pic1++ = CLIP(outy[outy2]);outy2++; /* maybe one day yuv422P */ *outv++ = CLIP(128 + *inv);inv++; *outu++ = CLIP(128 + *inu);inu++; } outy += 16; outy1 = 0; outy2 = 8; pic0 += nextline; pic1 += nextline; outv += nextuv; outu += nextuv; } picx += 16; pocx += 8; } } if (my >= cropy1) { picy += nextblk; pocy += nextnewline; } } } myframe->scanlength = (long)((softwidth*softheight*3)>>1); break; default: break; } // end case return 0; } // y=0.656g+0.125b+0.226r #define RGB24_TO_Y(r,g,b) (CLIP(\ (((g) <<9)+((g)<<7)+((g)<<5)+((b)<<7)+((r)<<8)-((r)<<4)-((r)<<3))>>10)) // v=(r-y)0.656 #define YR_TO_V(r,y) (128 + \ (((((r)-(y)) << 9 )+(((r)-(y)) << 7 )+(((r)-(y)) << 5 )) >> 10)) // u=(b-y)0.5 #define YB_TO_U(b,y) (128 + \ (((b)-(y)) >> 1)) #define PACKRGB16(r,g,b) (__u16) ((((b) & 0xF8) << 8 ) | (((g) & 0xFC) << 3 ) | (((r) & 0xF8) >> 3 )) static int bayer_decode(struct spca50x_frame *myframe, int force_rgb ) { int r_offset, g_offset, b_offset; int my , mx; /* scan input surface */ unsigned char *pic1; /* output surface */ __u16 *pix1,*pix2; /* same for 16 bits output */ unsigned char *U, *V; /* chroma output pointer */ unsigned char inr, ing1, ing2, inb, ing; /* srgb input */ int inl,inl1; /* offset line input */ int nextinline, nextoutline; unsigned char r,b,y1,y2,y3,y4; /*kernel matrix 4x4 */ unsigned char G00, R10, G20, R30, B01, G02, B03, G31, R32, G13, B23, G33; unsigned char r1, g1, b1, r2, g2, b2, r3, g3, b3, r4, g4, b4; int bpp; unsigned char *pic = myframe->data; /* output surface */ unsigned char *buf = myframe->tmpbuffer; /* input surface */ int width = myframe->hdrwidth; int height = myframe->hdrheight; int softwidth = myframe->width; int softheight = myframe->height; //int method = myframe->method; int format = myframe->format; int cropx1 = myframe->cropx1; int cropx2 = myframe->cropx2; int cropy1 = myframe->cropy1; int cropy2 = myframe->cropy2; unsigned char *red = myframe->decoder->Red; unsigned char *green = myframe->decoder->Green; unsigned char * blue = myframe->decoder->Blue; int framesize, frameUsize; inr=ing1=ing2=ing=inb=r=b=0; //compiler maybe happy !! framesize = softwidth * softheight; frameUsize = framesize >> 2; /* rgb or bgr like U or V that's the question */ if (force_rgb) { V = pic + framesize; U = V + frameUsize; r_offset = 0; g_offset = 1; b_offset = 2; } else { U = pic + framesize; V = U + frameUsize; r_offset = 2; g_offset = 1; b_offset = 0; } /* initialize input pointer */ inl = 0; inl1 = width ; nextinline = width << 1; /* Decode to the correct format. */ switch (format) { case VIDEO_PALETTE_RGB565: { bpp = 2; /* initialize */ pix1 = (__u16*) pic; pix2 = pix1 + softwidth; for ( my =0; my < height; my += 2){ for ( mx = 0 ; mx < width ; mx += 2 ){ /* test if we need to decode */ if ((my >= cropy1) && (my < height - cropy2) && (mx >= cropx1) && (mx < width - cropx2)) { /* yes decode GBRG */ g1 = green[buf [inl + mx]] ; b2 = blue[buf [inl+ 1 + mx]] ; r3 = red[buf [inl1 + mx]]; g4 = green[buf [inl1 +1 + mx]]; if ((mx == 0) || (my == 0) || (mx == (width - 2)) || (my == (height - 2))) { ing = (g1 + g4) >> 1; if (force_rgb) { *pix1++=PACKRGB16(r3,g1,b2); *pix1++=PACKRGB16(r3,ing,b2); *pix2++=PACKRGB16(r3,ing,b2); *pix2++=PACKRGB16(r3,g4,b2); } else { *pix1++=PACKRGB16(b2,g1,r3); *pix1++=PACKRGB16(b2,ing,r3); *pix2++=PACKRGB16(b2,ing,r3); *pix2++=PACKRGB16(b2,g4,r3); } } else { G00 = buf[inl + mx - width - 1]; R10 = buf[inl + mx - width]; G20 = buf[inl + mx - width + 1]; R30 = buf[inl + mx - width + 2]; B01 = buf[inl + mx - 1]; G31 = buf[inl + mx + 2]; G02 = buf[inl1 + mx - 1]; R32 = buf[inl1 + mx + 2]; B03 = buf[inl1 + mx + width - 1]; G13 = buf[inl1 + mx + width]; B23 = buf[inl1 + mx + width + 1]; G33 = buf[inl1 + mx + width + 2]; b1 = blue[((B01 + b2) >> 1)]; r1 = red[((R10 + r3) >> 1)]; r4 = red[((r3 + R32) >> 1)]; b4 = blue[((b2 + B23) >> 1)]; g2 = green[((g1 + g4 + G31 + G20) >> 2)]; r2 = red[((R10 + R30 + r3 + R32) >> 2)]; g3 = green[((g1 + g4 + G13 + G02) >> 2)]; b3 = blue[((B01 + b2 + B23 + B03) >> 2)]; if(force_rgb){ *pix1++=PACKRGB16(r1,g1,b1); *pix1++=PACKRGB16(r2,g2,b2); *pix2++=PACKRGB16(r3,g3,b3); *pix2++=PACKRGB16(r4,g4,b4); } else { *pix1++=PACKRGB16(b1,g1,r1); *pix1++=PACKRGB16(b2,g2,r2); *pix2++=PACKRGB16(b3,g3,r3); *pix2++=PACKRGB16(b4,g4,r4); } } } // end test decode } // end mx loop inl += nextinline; inl1 += nextinline ; if (my >= cropy1){ /* are we in a decode surface move the output pointer */ pix1 += (softwidth); pix2 += (softwidth); } } // end my loop } myframe->scanlength = (long)(softwidth*softheight*bpp); break; case VIDEO_PALETTE_RGB32: case VIDEO_PALETTE_RGB24: { bpp = (format == VIDEO_PALETTE_RGB32) ? 4 : 3; /* initialize */ nextoutline = bpp * softwidth; pic1 = pic + nextoutline; for ( my =0; my < height; my += 2){ for ( mx = 0 ; mx < width ; mx += 2 ){ /* test if we need to decode */ if ((my >= cropy1) && (my < height - cropy2) && (mx >= cropx1) && (mx < width - cropx2)) { /* yes decode GBRG */ g1 = green[buf [inl + mx]] ; b2 = blue[buf [inl+ 1 + mx]] ; r3 = red[buf [inl1 + mx]]; g4 = green[buf [inl1 +1 + mx]]; if ((mx == 0) || (my == 0) || (mx == (width - 2)) || (my == (height - 2))) { ing = (g1 + g4) >> 1; /* top pixel Right */ pic[r_offset] = r3; pic[g_offset] = g1; pic[b_offset] = b2; pic += bpp; /* top pixel Left */ pic[r_offset] = r3; pic[g_offset] = ing; pic[b_offset] = b2; pic += bpp; /* bottom pixel Right */ pic1[r_offset] = r3; pic1[g_offset] = ing; pic1[b_offset] = b2; pic1 += bpp; /* bottom pixel Left */ pic1[r_offset] = r3; pic1[g_offset] = g4; pic1[b_offset] = b2; pic1 += bpp; } else { G00 = buf[inl + mx - width - 1]; R10 = buf[inl + mx - width]; G20 = buf[inl + mx - width + 1]; R30 = buf[inl + mx - width + 2]; B01 = buf[inl + mx - 1]; G31 = buf[inl + mx + 2]; G02 = buf[inl1 + mx - 1]; R32 = buf[inl1 + mx + 2]; B03 = buf[inl1 + mx + width - 1]; G13 = buf[inl1 + mx + width]; B23 = buf[inl1 + mx + width + 1]; G33 = buf[inl1 + mx + width + 2]; b1 = blue[((B01 + b2) >> 1)]; r1 = red[((R10 + r3) >> 1)]; r4 = red[((r3 + R32) >> 1)]; b4 = blue[((b2 + B23) >> 1)]; g2 = green[((g1 + g4 + G31 + G20) >> 2)]; r2 = red[((R10 + R30 + r3 + R32) >> 2)]; g3 = green[((g1 + g4 + G13 + G02) >> 2)]; b3 = blue[((B01 + b2 + B23 + B03) >> 2)]; /* top pixel Right */ pic[r_offset] = r1; pic[g_offset] = g1; pic[b_offset] = b1; pic += bpp; /* top pixel Left */ pic[r_offset] = r2; pic[g_offset] = g2; pic[b_offset] = b2; pic += bpp; /* bottom pixel Right */ pic1[r_offset] = r3; pic1[g_offset] = g3; pic1[b_offset] = b3; pic1 += bpp; /* bottom pixel Left */ pic1[r_offset] = r4; pic1[g_offset] = g4; pic1[b_offset] = b4; pic1 += bpp; } } // end test decode } // end mx loop inl += nextinline; inl1 += nextinline ; if (my >= cropy1){ /* are we in a decode surface move the output pointer */ pic += (nextoutline); pic1 += (nextoutline); } } // end my loop } myframe->scanlength = (long)(softwidth*softheight*bpp); break; case VIDEO_PALETTE_YUV420P: { /* Not yet implemented */ nextoutline = softwidth; pic1 = pic + nextoutline; for ( my =0; my < height; my += 2){ for ( mx = 0; mx < width ; mx +=2 ){ /* test if we need to decode */ if ((my >= cropy1) && (my < height - cropy2) && (mx >= cropx1) && (mx < width - cropx2)) { g1 = green[buf [inl + mx]] ; b2 = blue[buf [inl+ 1 + mx]] ; r3 = red[buf [inl1 + mx]]; g4 = green[buf [inl1 +1 + mx]]; if ((mx == 0) || (my == 0) || (mx == (width - 2)) || (my == (height - 2))) { ing = (g1 + g4) >> 1; /* top pixel Right */ y1=RGB24_TO_Y(r3,g1,b2); *pic++ = y1; /* top pixel Left */ y2=RGB24_TO_Y(r3,ing,b2); *pic++ = y2; /* bottom pixel Right */ y3=RGB24_TO_Y(r3,ing,b2); *pic1++ = y3; /* bottom pixel Left */ y4=RGB24_TO_Y(r3,g4,b2); *pic1++ = y4; /* U V plane */ *U++ = YB_TO_U(b2,((y1+y4) >> 1)); *V++ = YR_TO_V(r3,((y1+y4) >> 1)); } else { G00 = buf[inl + mx - width - 1]; R10 = buf[inl + mx - width]; G20 = buf[inl + mx - width + 1]; R30 = buf[inl + mx - width + 2]; B01 = buf[inl + mx - 1]; G31 = buf[inl + mx + 2]; G02 = buf[inl1 + mx - 1]; R32 = buf[inl1 + mx + 2]; B03 = buf[inl1 + mx + width - 1]; G13 = buf[inl1 + mx + width]; B23 = buf[inl1 + mx + width + 1]; G33 = buf[inl1 + mx + width + 2]; b1 = blue[((B01 + b2) >> 1)]; r1 = red[((R10 + r3) >> 1)]; r4 = red[((r3 + R32) >> 1)]; b4 = blue[((b2 + B23) >> 1)]; g2 = green[((g1 + g4 + G31 + G20) >> 2)]; r2 = red[((R10 + R30 + r3 + R32) >> 2)]; g3 = green[((g1 + g4 + G13 + G02) >> 2)]; b3 = blue[((B01 + b2 + B23 + B03) >> 2)]; /* top pixel Right */ y1=RGB24_TO_Y(r1,g1,b1); *pic++ = y1; /* top pixel Left */ y2=RGB24_TO_Y(r2,g2,b2); *pic++ = y2; /* bottom pixel Right */ y3=RGB24_TO_Y(r3,g3,b3); *pic1++ = y3; /* bottom pixel Left */ y4=RGB24_TO_Y(r4,g4,b4); *pic1++ = y4; /* U V plane */ *U++ = YB_TO_U(((b1+b2+b3+b4)>>2),((y1+y2+y3+y4)>>2)); *V++ = YR_TO_V(((r1+r2+r3+r4)>>2),((y1+y2+y3+y4)>>2)); } } // end test decode } // end mx loop inl += nextinline; inl1 += nextinline ; if (my >= cropy1){ /* are we in a decode surface move the output pointer */ pic += softwidth ; pic1 += softwidth ; } } // end my loop } myframe->scanlength = (long)((softwidth*softheight*3)>>1); break; default: break; }// end case return 0; } // end bayer_decode /* this function restore the missing header for the jpeg camera */ /* adapted from Till Adam create_jpeg_from_data() */ static int make_jpeg (struct spca50x_frame *myframe) { int width; int height; int inputsize; int i; __u8 value; __u8 *buf; __u8 *dst; __u8 *start; dst = myframe->data; start = dst; buf = myframe->tmpbuffer; width = myframe->hdrwidth; height = myframe->hdrheight; inputsize = width*height; /* set up the default header */ memcpy(dst,JPEGHeader,JPEGHEADER_LENGTH); /* setup quantization table */ *(dst+6) = 0; memcpy(dst+7,myframe->decoder->quant[0],64); *(dst+7+64) = 1; memcpy(dst+8+64,myframe->decoder->quant[1],64); *(dst + 564) = width & 0xFF; //Image width low byte *(dst + 563) = width >> 8 & 0xFF; //Image width high byte *(dst + 562) = height & 0xFF; //Image height low byte *(dst + 561) = height >> 8 & 0xFF; //Image height high byte /* set the format */ if(myframe->cameratype == JPEG){ *(dst + 567) = 0x22; dst += JPEGHEADER_LENGTH; for (i=0 ; i < inputsize; i++){ value = *(buf + i) & 0xFF; *dst = value; dst++; if ((*(buf+i)+*(buf+i+1)+ *(buf+i+2)+*(buf+i+3)) == 0) break; if (value == 0xFF){ *dst = 0; dst++; } } /* Add end of image marker */ *(dst++) = 0xFF; *(dst++) = 0xD9; } else { *(dst + 567) = 0x21; dst += JPEGHEADER_LENGTH; for (i=0 ; i < inputsize; i++){ value = *(buf + i) & 0xFF; *dst = value; dst++; if((value == 0XFF) && (*(buf+i+1) == 0xD9)){ *dst = *(buf+i+1); dst++; break; } } } myframe->scanlength = (long)(dst - start); return 0; } static int make_jpeg_conexant (struct spca50x_frame *myframe) { __u8 *buf; __u8 *dst; dst = myframe->data; buf = myframe->tmpbuffer; memcpy(dst,JPEGHeader,JPEGHEADER_LENGTH-33); *(dst+6) = 0; memcpy(dst+7,myframe->decoder->quant[0],64); *(dst+7+64) = 1; memcpy(dst+8+64,myframe->decoder->quant[1],64); dst += (JPEGHEADER_LENGTH-33); memcpy(dst,buf,myframe->scanlength); myframe->scanlength +=(JPEGHEADER_LENGTH-33); return 0; }