/* * JPEG-LS encoder and decoder * Copyright (c) 2003 Michael Niedermayer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** * @file jpeg_ls.c * JPEG-LS encoder and decoder. */ #undef printf #undef fprintf static inline int quantize(MJpegDecodeContext *s, int v){ //FIXME optimize if(v==0) return 0; if(v < 0){ if (v >-s->t1) return -1; else if(v >-s->t2) return -2; else if(v >-s->t3) return -3; else return -4; }else{ if (v < s->t1) return 1; else if(v < s->t2) return 2; else if(v < s->t3) return 3; else return 4; } } static inline int predict8(uint8_t *src, uint8_t *last){ //FIXME perhaps its better to suppress these 2 const int LT= last[-1]; const int T= last[ 0]; const int L = src[-1]; return mid_pred(L, L + T - LT, T); } static inline int predict16(uint16_t *src, uint16_t *last){ const int LT= last[-1]; const int T= last[ 0]; const int L = src[-1]; return mid_pred(L, L + T - LT, T); } static int encode_picture_ls(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ return 0; } static int iso_clip(int v, int vmin, int vmax){ if(v > vmax || v < vmin) return vmin; else return v; } static void reset_ls_coding_parameters(MJpegDecodeContext *s, int reset_all){ const int basic_t1= 3; const int basic_t2= 7; const int basic_t3= 21; int factor; if(s->maxval==0 || reset_all) s->maxval= (1<<s->bits) - 1; if(s->maxval >=128){ factor= (FFMIN(s->maxval, 4096) + 128)>>8; if(s->t1==0 || reset_all) s->t1= iso_clip(factor*(basic_t1-2) + 2 + 3*s->near, s->near+1, s->maxval); if(s->t2==0 || reset_all) s->t2= iso_clip(factor*(basic_t2-3) + 3 + 5*s->near, s->t1, s->maxval); if(s->t3==0 || reset_all) s->t3= iso_clip(factor*(basic_t3-4) + 4 + 7*s->near, s->t2, s->maxval); }else{ factor= 256 / (s->maxval + 1); if(s->t1==0 || reset_all) s->t1= iso_clip(FFMAX(2, basic_t1/factor + 3*s->near), s->near+1, s->maxval); if(s->t2==0 || reset_all) s->t2= iso_clip(FFMAX(3, basic_t2/factor + 5*s->near), s->t1, s->maxval); if(s->t3==0 || reset_all) s->t3= iso_clip(FFMAX(4, basic_t3/factor + 6*s->near), s->t2, s->maxval); } if(s->reset==0 || reset_all) s->reset= 64; } static int decode_lse(MJpegDecodeContext *s) { int len, id; /* XXX: verify len field validity */ len = get_bits(&s->gb, 16); id = get_bits(&s->gb, 8); switch(id){ case 1: s->maxval= get_bits(&s->gb, 16); s->t1= get_bits(&s->gb, 16); s->t2= get_bits(&s->gb, 16); s->t3= get_bits(&s->gb, 16); s->reset= get_bits(&s->gb, 16); reset_ls_coding_parameters(s, 0); //FIXME quant table? break; case 2: case 3: printf("palette not supported\n"); return -1; case 4: printf("oversize image not supported\n"); return -1; default: printf("invalid id %d\n", id); return -1; } return 0; } #if 0 static inline void update_vlc_state(VlcState * const state, const int v, int half_count){ int drift= state->drift; int count= state->count; state->error_sum += ABS(v); drift += v; if(count == half_count){ count >>= 1; drift >>= 1; state->error_sum >>= 1; } count++; if(drift <= -count){ if(state->bias > -128) state->bias--; drift += count; if(drift <= -count) drift= -count + 1; }else if(drift > 0){ if(state->bias < 127) state->bias++; drift -= count; if(drift > 0) drift= 0; } state->drift= drift; state->count= count; } #define R(p, i) (is_uint8 ? (((uint8_t*)p)[i] : ((uint16_t*)p)[i]) static inline int ls_decode_line(MJpegDecodeContext *s, void *lastv, void *dstv, int last2, int w, int point_transform, int is_uint8){ int i, x, y; for(x=0; x < w; x++){ int l, t, lt, rt; t= R(last, 0); if(x){ l = t; lt= last2; }else{ l = R(dst, x-1); lt= R(last, x-1); } if(x<w-1) rt= R(last, x+1); else rt= t; hr_gradient= rt - t; hl_gradient= t - lt; v_gradient= lt - l; context= quantize(s, v_gradient) + 9*(quantize(s, hl_gradient) + 9*quantize(s, hr_gradient)); if(context){ int pred= mid_pred(l, l + t - lt, t); if(context < 0){ context= -context; sign= 1; pred= clip(0, pred - state->bias, maxval); }else{ sign= 0; pred= clip(0, pred + state->bias, maxval); } i= state->count; k=0; while(i < state->error_sum){ //FIXME optimize k++; i += i; } v= get_ur_golomb_jpegls(gb, k, LIMIT-qbpp, qbpp); #if 1 v++; if(v&1) v= (v>>1); else v= -(v>>1); if(k==0 && 2*state->drift <= - state->count) v ^= (-1); #else v ^= (k==0 && 2*state->drift <= - state->count); v++; if(v&1) v= (v>>1); else v= -(v>>1); #endif update_vlc_state(state, v, half_count); if(sign) v= -v; if(is_uint8) ((uint8_t *)dst)[x]= (pred + v) & maxval; else ((uint16_t*)dst)[x]= (pred + v) & maxval; }else{ int run_count; while(get_bits1(&s->gb)){ run_count = 1<<log2_run[run_index]; if(x + run_count > w) run_count= w - x; else run_index++; for(; run_count; run_count--){ if(is_uint8) ((uint8_t *)dst)[x++]= l; else ((uint16_t*)dst)[x++]= l; } if(x >= w) return 0; } run_count= get_bits(&s->gb, log2_run[run_index]); for(; run_count; run_count--){ if(is_uint8) ((uint8_t *)dst)[x++]= l; else ((uint16_t*)dst)[x++]= l; } if(run_index) run_index--; if(x >= w) return 0; t= R(last, 0); RItype= (l==t); if(l==t){ state= 366; temp= state->error_sum + (state->count>>1); }else{ state= 365; temp= state->error_sum; } pred= t; sign= l > t; i= state->count; k=0; while(i < temp){ //FIXME optimize k++; i += i; } assert(Errval != 0); map = (k==0 && 2*Nn < state->count) == (Errval>0); if(run_count==0 && run_mode==1){ if(get_bits1(&s->gb)){ run_count = 1<<log2_run[run_index]; if(x + run_count <= w) run_index++; }else{ if(log2_run[run_index]) run_count = get_bits(&s->gb, log2_run[run_index]); else run_count=0; if(run_index) run_index--; run_mode=2; } } run_count--; if(run_count < 0){ run_mode=0; run_count=0; diff= get_vlc_symbol(&s->gb, &p->vlc_state[context]); if(diff>=0) diff++; }else diff=0; } } /* if (s->restart_interval && !s->restart_count) s->restart_count = s->restart_interval;*/ if(mb_x==0 || mb_y==0 || s->interlaced){ for(i=0;i<nb_components;i++) { uint8_t *ptr; int n, h, v, x, y, c, j, linesize; n = s->nb_blocks[i]; c = s->comp_index[i]; h = s->h_scount[i]; v = s->v_scount[i]; x = 0; y = 0; linesize= s->linesize[c]; for(j=0; j<n; j++) { int pred; ptr = s->current_picture[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap if(y==0 && mb_y==0){ if(x==0 && mb_x==0){ pred= 128 << point_transform; }else{ pred= ptr[-1]; } }else{ if(x==0 && mb_x==0){ pred= ptr[-linesize]; }else{ PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); } } if (s->interlaced && s->bottom_field) ptr += linesize >> 1; *ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform); if (++x == h) { x = 0; y++; } } } }else{ for(i=0;i<nb_components;i++) { uint8_t *ptr; int n, h, v, x, y, c, j, linesize; n = s->nb_blocks[i]; c = s->comp_index[i]; h = s->h_scount[i]; v = s->v_scount[i]; x = 0; y = 0; linesize= s->linesize[c]; for(j=0; j<n; j++) { int pred; ptr = s->current_picture[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); *ptr= pred + (mjpeg_decode_dc(s, s->dc_index[i]) << point_transform); if (++x == h) { x = 0; y++; } } } } if (s->restart_interval && !--s->restart_count) { align_get_bits(&s->gb); skip_bits(&s->gb, 16); /* skip RSTn */ } return 0; } #endif #ifdef CONFIG_ENCODERS AVCodec jpegls_encoder = { //FIXME avoid MPV_* lossless jpeg shouldnt need them "jpegls", CODEC_TYPE_VIDEO, CODEC_ID_JPEGLS, sizeof(MpegEncContext), MPV_encode_init, encode_picture_ls, MPV_encode_end, }; #endif