/************************************************************************** * * * This code is developed by Adam Li. This software is an * * implementation of a part of one or more MPEG-4 Video tools as * * specified in ISO/IEC 14496-2 standard. Those intending to use this * * software module in hardware or software products are advised that its * * use may infringe existing patents or copyrights, and any such use * * would be at such party's own risk. The original developer of this * * software module and his/her company, and subsequent editors and their * * companies (including Project Mayo), will have no liability for use of * * this software or modifications or derivatives thereof. * * * * Project Mayo gives users of the Codec a license to this software * * module or modifications thereof for use in hardware or software * * products claiming conformance to the MPEG-4 Video Standard as * * described in the Open DivX license. * * * * The complete Open DivX license can be found at * * http://www.projectmayo.com/opendivx/license.php . * * * **************************************************************************/ /************************************************************************** * * mom_util.c * * Copyright (C) 2001 Project Mayo * * Adam Li * * DivX Advance Research Center * **************************************************************************/ /* This file contains some utility functions to manipulate Image data */ /* structures. */ /* Some codes of this project come from MoMuSys MPEG-4 implementation. */ /* Please see seperate acknowledgement file for a list of contributors. */ #include "mom_util.h" /* private prototypes */ Char *emalloc(Int n); Char *ecalloc(Int n, Int s); Char *erealloc(Char *p, Int n); Void CopyImageI(ImageI *image_in, ImageI *image_out); Void CopyImageF(ImageF *image_in, ImageF *image_out); Void SetConstantImageI(ImageI *image, SInt val); Void SetConstantImageF(ImageF *image, Float val); Void SubImageI(ImageI *image_in1, ImageI *image_in2, ImageI *image_out); Void SubImageF(ImageF *image_in1, ImageF *image_in2, ImageF *image_out); /* The following is the Image maintance functions. */ /***********************************************************CommentBegin****** * * -- AllocImage -- Allocates memory for an Image structure * * Purpose : * Allocates memory for an Image structure, including memory * for the actual image pixels. The image pixels can be of type * UChar, SInt or Float depending on the parameter type. * * Return values : * A pointer to the allocated Image structure. * * Description : * Allocates memory for the Image if possible, otherwise a * memory allocation error is signalled and the program will * exit. * ***********************************************************CommentEnd********/ Image * AllocImage(UInt size_x, UInt size_y, ImageType type) { Image *image; image = (Image *) emalloc(sizeof(Image)); image->version = VERSION; image->x = size_x; image->y = size_y; image->upperodd = 0; image->grid = 's'; image->type = type; image->data = (ImageData *) emalloc(sizeof(ImageData)); switch(type) { case SHORT_TYPE: image->data->s = (SInt *) ecalloc(size_x*size_y,sizeof(SInt)); break; case FLOAT_TYPE: image->data->f = (Float *) ecalloc(size_x*size_y,sizeof(Float)); break; case UCHAR_TYPE: image->data->u = (UChar *) ecalloc(size_x*size_y,sizeof(UChar)); break; } image->f = image->data->s; /* For compatibility with KHOROS */ return(image); } /***********************************************************CommentBegin****** * * -- FreeImage -- Frees up all the memory associated with an Image structure * * Purpose : * Frees up all the memory associated with an Image structure * ***********************************************************CommentEnd********/ Void FreeImage(Image *image) { SInt *ps; Float *pf; UChar *pu; if (image == NULL) return; switch(image->type) { case SHORT_TYPE: ps = (SInt *)GetImageData(image); if(ps != NULL) free((Char *)ps); free((Char *) image->data); free((Char *)image); break; case FLOAT_TYPE: pf = (Float *)GetImageData(image); if(pf != NULL) free((Char *)pf); free((Char *) image->data); free((Char *)image); break; case UCHAR_TYPE: pu = (UChar *)GetImageData(image); if(pu != NULL) free((Char *)pu); free((Char *) image->data); free((Char *)image); break; } } /***********************************************************CommentBegin****** * * -- CopyImage -- Copies the pixel values of one image to another image * * Purpose : * Copies the pixel values of one image to another image. * * Description : * Currently, the function exits with an error if * the source and destination images are not of the same allocated * size and type. * * Also, the images of type UChar are not yet supported. * ***********************************************************CommentEnd********/ Void CopyImage(Image *image_in, Image *image_out) { switch(image_out->type) { case SHORT_TYPE: CopyImageI(image_in,image_out); break; case FLOAT_TYPE: CopyImageF(image_in,image_out); break; } } /***********************************************************CommentBegin****** * * -- CopyImageI -- * ***********************************************************CommentEnd********/ Void CopyImageI(ImageI *image_in, ImageI *image_out) { SInt *p_in = image_in->data->s, *p_out = image_out->data->s, *p_end; UInt sx_in = image_in->x, sx_out = image_out->x, sy_in = image_in->y, sy_out = image_out->y, sxy_in = sx_in * sy_in; p_end = p_in + sxy_in; while (p_in != p_end) { *p_out = *p_in; p_in++; p_out++; } } /***********************************************************CommentBegin****** * * -- CopyImageF -- Copies image_in to image_out * ***********************************************************CommentEnd********/ Void CopyImageF(ImageF *image_in, ImageF *image_out) { Float *p_in = image_in->data->f, *p_out = image_out->data->f, *p_end; UInt sx_in = image_in->x, sx_out = image_out->x, sy_in = image_in->y, sy_out = image_out->y, sxy_in = sx_in * sy_in; p_end = p_in + sxy_in; while (p_in != p_end) { *p_out = *p_in; p_in++; p_out++; } } /***********************************************************CommentBegin****** * * -- SetConstantImage -- Sets each pixel in the Image to val * * Purpose : * Sets each pixel in the Image to val. * * Side effects : * Note val is a Float. If image is not a Float image then * val is cast to the appropriate type i.e. SInt, unsigned * Char. * * Description : * Images of type UChar are not yet supported. * ***********************************************************CommentEnd********/ Void SetConstantImage(Image *image, Float val) { switch(image->type) { case SHORT_TYPE: SetConstantImageI(image,(SInt)val); break; case FLOAT_TYPE: SetConstantImageF(image,val); break; } } /***********************************************************CommentBegin****** * * -- SetConstantImageI -- * ***********************************************************CommentEnd********/ Void SetConstantImageI(ImageI *image, SInt val) { SInt *p = image->data->s, *p_end; UInt sxy = image->x * image->y; if (val == 0) memset (p, 0, sxy * 2); else { p_end = p + sxy; while (p != p_end) { *p = val; p++; } } } /***********************************************************CommentBegin****** * * -- SetConstantImageF -- * ***********************************************************CommentEnd********/ Void SetConstantImageF(ImageF *image, Float val) { Float *p = image->data->f, *p_end; UInt sxy = image->x * image->y; p_end = p + sxy; while (p != p_end) { *p = val; p++; } } /***********************************************************CommentBegin****** * * -- SubImage -- Subtracts two images * * Purpose : * Subtracts two images and stores the result in the third * i.e. image_out = image_in1 - image_in2 * * Description : * Currently, the function exits with an error if * the source and destination images are not of the same allocated * size and type. * * Also, the images of type UChar are not yet supported. * ***********************************************************CommentEnd********/ Void SubImage(Image *image_in1, Image *image_in2, Image *image_out) { switch(image_in1->type) { case SHORT_TYPE: SubImageI(image_in1,image_in2,image_out); break; case FLOAT_TYPE: SubImageF(image_in1,image_in2,image_out); break; } } /***********************************************************CommentBegin****** * * -- SubImageI -- * ***********************************************************CommentEnd********/ Void SubImageI(ImageI *image_in1, ImageI *image_in2, ImageI *image_out) { SInt *p = image_out->data->s, *p1 = image_in1->data->s, *p2 = image_in2->data->s, *p_end; UInt sx_in1 = image_in1->x, sx_in2 = image_in2->x, sx_out = image_out->x, sy_in1 = image_in1->y, sy_in2 = image_in2->y, sy_out = image_out->y, sxy = sx_out * sy_out; p_end = p + sxy; while (p != p_end) { *p = *p1 - *p2; p++; p1++; p2++; } } /***********************************************************CommentBegin****** * * -- SubImageF -- * ***********************************************************CommentEnd********/ Void SubImageF(ImageF *image_in1, ImageF *image_in2, ImageF *image_out) { Float *p = image_out->data->f, *p1 = image_in1->data->f, *p2 = image_in2->data->f, *p_end; UInt sx_in1 = image_in1->x, sx_in2 = image_in2->x, sx_out = image_out->x, sy_in1 = image_in1->y, sy_in2 = image_in2->y, sy_out = image_out->y, sxy = sx_out * sy_out; p_end = p + sxy; while (p != p_end) { *p = *p1 - *p2; p++; p1++; p2++; } } /* The following is Vop maintance functions. */ Vop * SallocVop() { Vop *vop; vop = (Vop *)ecalloc(1,sizeof(Vop)); return(vop); } Vop * AllocVop(UInt x, UInt y) { Vop *vop; Image *y_chan, *u_chan, *v_chan; /* first allocate memory for the data structure */ vop = SallocVop(); vop->width = x; vop->height = y; /* Allocate image fields */ y_chan = AllocImage(x,y,SHORT_TYPE); u_chan = AllocImage(x/2,y/2,SHORT_TYPE); v_chan = AllocImage(x/2,y/2,SHORT_TYPE); /* Include image fields in structure */ FreeImage(vop->y_chan); vop->y_chan = y_chan; FreeImage(vop->u_chan); vop->u_chan = u_chan; FreeImage(vop->v_chan); vop->v_chan = v_chan; return(vop); } Void SfreeVop (Vop *vop) { free ((Char*)vop); /* vop = NULL; */ return; } Void FreeVop(Vop *vop) { Image *data=NULL; /*SpSc: added the initialization */ if(vop != NULL) { /* Deallocate memory for image fields */ data = vop->y_chan; FreeImage(data); data = vop->u_chan; FreeImage(data); data = vop->v_chan; FreeImage(data); SfreeVop(vop); } return; } Void CopyVopNonImageField(Vop *in,Vop *out) { out->quant_precision = in->quant_precision; out->bits_per_pixel = in->bits_per_pixel; out->mod_time_base = in->mod_time_base; out->time_inc = in->time_inc; out->prediction_type = in->prediction_type; out->rounding_type = in->rounding_type; out->width = in->width; out->height = in->height; out->hor_spat_ref = in->hor_spat_ref; out->ver_spat_ref = in->ver_spat_ref; out->quantizer = in->quantizer; out->intra_quantizer = in->intra_quantizer; out->time_increment_resolution = in->time_increment_resolution; out->intra_acdc_pred_disable = in->intra_acdc_pred_disable; out->fcode_for = in->fcode_for; out->sr_for = in->sr_for; out->intra_dc_vlc_thr = in->intra_dc_vlc_thr; } /* The following is Memory allocation functions. */ /***********************************************************CommentBegin****** * * -- emalloc -- Memory allocation with error handling * * Purpose : * Memory allocation with error handling. * * Description : * WARNING: There is a problem when you want to allocate more memory * than size can handle. Malloc gets as argument an unsigned. It poses * a problem when sizeof(unsigned) < sizeof(Char *)... * ***********************************************************CommentEnd********/ Char * emalloc(Int n) { Char *p; p = (Char *) malloc((UInt)n); return p; } /***********************************************************CommentBegin****** * * -- ecalloc -- Memory allocation with error handling * * Purpose : * Memory allocation with error handling. * * Description : * WARNING: There is a problem when you want to allocate more memory * than size can handle. Malloc gets as argument an unsigned. It poses * a problem when sizeof(unsigned) < sizeof(Char *)... * ***********************************************************CommentEnd********/ Char * ecalloc(Int n, Int s) { Char *p; p = (Char *) calloc((UInt)n,(UInt)s); return p; } /***********************************************************CommentBegin****** * * -- erealloc -- Memory re-allocation with error handling. * * Purpose : * Memory re-allocation with error handling * * Description : * WARNING: There is a problem when you want to allocate more memory * than size can handle. Malloc gets as argument an unsigned. It poses * a problem when sizeof(unsigned) < sizeof(Char *)... * ***********************************************************CommentEnd********/ Char * erealloc(Char *p, Int n) { p = (Char *) realloc(p,(UInt)n); return p; }