/* updates cimg state when header dimensions are know. Only allowed to be called * in state 8 and 10. * Allocates right amount of memory into buffer, formats it (with background or * zeroes, depens on buffer_bytes_per_pixel). Updates dimensions (xww and yww) * according to newly known header dimensions. Fills in gamma_stamp, bmp.user * (NULL because we not bother with generating bitmap here) * and rows_added. * Resets strip_optimized if image will be scaled or * Allocates dregs if on exit strip_optimized is nonzero. * Allocates and computes gamma_table, otherwise * sets gamma_table to NULL. Also doesn't make gamma table if image contains less * than 1024 pixels (it would be probably a waste of time). * Output state is always 12 (from input state 8) or 14 (from input state 10). * * The caller must have set the following elements of cimg: * width * height * buffer_bytes_per_pixel * red_gamma * green_gamma * blue_gamma * strip_optimized */ void header_dimensions_known(struct cached_image *cimg) { unsigned short red, green, blue; #ifdef DEBUG if ((cimg->state^8)&13){ fprintf(stderr,"cimg->state=%d\n",cimg->state); internal("Invalid state in header_dimensions_known"); } if (cimg->width<1||cimg->height<1){ fprintf(stderr,"width=%d height=%d\n",cimg->width, cimg->height); internal("Zero dimensions in header_dimensions_known"); } #endif /* #ifdef DEBUG */ if (cimg->wanted_xw<0){ /* Unspecified width */ if (cimg->wanted_yw<0){ /* Unspecified width and height */ cimg->xww=img_scale_h(cimg->scale, cimg->width); cimg->yww=img_scale_v(cimg->scale, cimg->height); }else{ /* Unspecified width specified height */ cimg->xww=(cimg->yww *cimg->width+(cimg->height>>1)) /cimg->height; if (cimg->xww<=0) cimg->xww=1; } }else{ if (cimg->wanted_yw<0){
/* updates cimg state when header dimensions are know. Only allowed to be called * in state 8 and 10. * Allocates right amount of memory into buffer, formats it (with background or * zeroes, depens on buffer_bytes_per_pixel). Updates dimensions (xww and yww) * according to newly known header dimensions. Fills in gamma_stamp, bmp.user * (NULL because we not bother with generating bitmap here) * and rows_added. * Resets strip_optimized if image will be scaled or * Allocates dregs if on exit strip_optimized is nonzero. * Allocates and computes gamma_table, otherwise * sets gamma_table to NULL. Also doesn't make gamma table if image contains less * than 1024 pixels (it would be probably a waste of time). * Output state is always 12 (from input state 8) or 14 (from input state 10). * * The caller must have set the following elements of cimg: * width * height * buffer_bytes_per_pixel * red_gamma * green_gamma * blue_gamma * strip_optimized */ int header_dimensions_known(struct cached_image *cimg) { unsigned short red, green, blue; #ifdef DEBUG if ((cimg->state^8)&13){ fprintf(stderr,"cimg->state=%d\n",cimg->state); internal("Invalid state in header_dimensions_known"); } #endif /* #ifdef DEBUG */ if (cimg->width<1||cimg->height<1){ /*fprintf(stderr,"width=%d height=%d\n",cimg->width, cimg->height);*/ return 1; } if (!is_image_size_sane(cimg->width, cimg->height)) { return 1; } if (cimg->wanted_xw<0){ /* Unspecified width */ if (cimg->wanted_yw<0){ /* Unspecified neither width nor height */ cimg->xww=img_scale_h(cimg->scale, cimg->width); cimg->yww=img_scale_v(cimg->scale, cimg->height); }else{ /* Unspecified width specified height */ cimg->xww=height2width(cimg->yww, cimg->width, cimg->height); if (cimg->xww<=0) cimg->xww=1; } }else{ /* Specified width */ if (cimg->wanted_yw<0){ /* Unspecified height, specified width */ cimg->yww=width2height(cimg->xww, cimg->width, cimg->height); if (cimg->yww<=0) cimg->yww=1; }else if (cimg->wanted_xyw_meaning==MEANING_AUTOSCALE){ /* Specified height and width and autoscale meant */ /* Try first to nail the height */ cimg->yww=cimg->wanted_yw; cimg->xww=height2width(cimg->yww, cimg->width, cimg->height); if (cimg->xww>cimg->wanted_xw) { /* Width too much, we nail the width */ cimg->xww=cimg->wanted_xw; cimg->yww=width2height(cimg->xww, cimg->width, cimg->height); } /* Some sanity checks */ if (cimg->xww<=0) cimg->xww=1; if (cimg->yww<=0) cimg->yww=1; } } if (!is_image_size_sane(cimg->xww, cimg->yww)) { cimg->xww = cimg->width; cimg->yww = cimg->height; } if (cimg->width!=cimg->xww||cimg->height!=cimg->yww) cimg->strip_optimized=0; cimg->gamma_stamp=gamma_stamp; if (cimg->strip_optimized){ struct bitmap tmpbmp; unsigned short *buf_16; int i; tmpbmp.x=cimg->width; tmpbmp.y=1; /* No buffer, bitmap is valid from the very beginning */ cimg->bmp.x=cimg->width; cimg->bmp.y=cimg->height; if (drv->get_empty_bitmap(&(cimg->bmp))) { cimg->dregs = NULL; goto skip_img; } if ((unsigned)cimg->width > MAXINT / sizeof(*buf_16) / 3) overalloc(); buf_16=mem_alloc(sizeof(*buf_16)*3*cimg->width); round_color_sRGB_to_48(&red, &green, &blue , cimg->background_color); mix_one_color_48(buf_16,cimg->width, red, green, blue); #ifdef DEBUG if (cimg->height<=0){ fprintf(stderr,"cimg->height=%d\n",cimg->height); internal("Invalid cimg->height in strip_optimized section of\ header_dimensions_known"); } #endif /* #ifdef DEBUG */ /* The skip is uninitialized here and is read by dither_start * but is not used in any malicious way so it doesn't matter */ tmpbmp.data=cimg->bmp.data; cimg->dregs=dither_images?dither_start(buf_16,&tmpbmp):NULL; tmpbmp.data=(unsigned char *)tmpbmp.data+cimg->bmp.skip; if (cimg->dregs) for (i=cimg->height-1;i;i--){ dither_restart(buf_16,&tmpbmp,cimg->dregs); tmpbmp.data=(unsigned char *)tmpbmp.data+cimg->bmp.skip; } else for (i=cimg->height-1;i;i--){ (*round_fn)(buf_16,&tmpbmp); tmpbmp.data=(unsigned char *)tmpbmp.data+cimg->bmp.skip; } mem_free(buf_16); skip_img: drv->register_bitmap(&(cimg->bmp)); if(cimg->dregs) memset(cimg->dregs,0,cimg->width*sizeof(*cimg->dregs)*3); cimg->bmp.user=(void *)&end_callback_hit; /* Nonzero value */ /* This ensures the dregs are none and because strip * optimization is unusable in interlaced pictures, * this saves the zeroing out at the beginning of the * decoder itself. */ }else {