/* ** Title: MMXImage ** SCCSid: %W% %E% %U% ** CCid: %W% %E% %U% ** Author: Informix Software, Inc. ** Created: 06/11/1998 14:48 ** Description: This is the generated 'C' file for the MMXImage DataBlade. ** Comments: Generated for project MMXImage.3.6 */ /* ** The following is placed here to insure ** that name "mangling" does not occur. */ #ifdef __cplusplus extern "C" { #endif /* Standard library includes. */ #include #include #include #include #include #define IMAGEBUFSIZE 128*128 /* Function prototypes. */ void MMXImage2x( byte * lpBackbufferMemory, int x_res, int y_res ); void CImage2x( byte * lpBackbufferMemory, int x_res, int y_res ); void MMXpick1of4( byte * lpSource, byte * lpDest, int width, int height ); void Cpick1of4( byte * lpSource, byte * lpDest, int width, int height ); /* Used by Informix GLS routines. */ #include /* Include when accessing the Informix API. */ #include /* This is the project include file. */ #include "MMXImage.h" /* {{FUNCTION(5dde0fd0-e34d-11d0-8874-00a0c9255cf3) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** ZoomImageXN ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine ZoomImageXN (Image,integer) returns Image. ** ** Parameters: ** ** Return value: ** ** Image ** ** History: ** ** 06/30/1998 - Generated by BladeSmith Version 3.60.630 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT Image * ZoomImageXN ( Image * MyImage, mi_integer ZoomCount, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { Image* Gen_RetVal; /* The return value. */ MI_CONNECTION * Gen_Con; /* The connection handle. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ MI_LODESC Gen_LoDesc; /* The LO descriptor. */ MI_LO_HANDLE * ImageHandle; /* The image's LO handle. */ char * ScaledImageBuf; /* A buffer for the image pixels. */ char * ColorMap; /* The image's color map. */ int ColorsUsed; /* The number of colors used. */ mi_integer ColorSize; /* Size of the color map. */ BITMAPFILEHEADER bf; /* BMP file header info. */ BITMAPINFO bi; /* BMP image info. */ char * tempptr; /* Used to copy the description. */ char * lp; /* Temporary copy ptr. */ int index; /* Index over the image's rows. */ int ZoomIndex; /* Count the number of zooms. */ /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ /* ** Write to the trace file indicating ** that ZoomImageXN has been called. */ DBDK_TRACE_ENTER( "ZoomImageXN" ); /* Validate the zoom count. */ if( ZoomCount < 1 ) { /* ** An invalid value of zoom was specified. */ DBDK_TRACE_ERROR( "ZoomImageXN", "MMX07", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Open the large object's handle and read it. */ Gen_LoDesc = mi_large_object_open( Gen_Con, &MyImage->ImageHandle, MI_LO_RDONLY ); if( Gen_LoDesc == MI_ERROR ) { /* ** An error has occurred while reading the large object. */ DBDK_TRACE_ERROR( "ZoomImageXN", "MMX06", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Read the LO BMP file. */ if( mi_large_object_read( Gen_Con, Gen_LoDesc, (char *)&bf, sizeof(BITMAPFILEHEADER) ) == MI_ERROR || mi_large_object_read( Gen_Con, Gen_LoDesc, (char *)&bi, sizeof(BITMAPINFOHEADER) ) == MI_ERROR ) { /* ** An error has occurred while reading the large object. */ DBDK_TRACE_ERROR( "ZoomImageXN", "MMX06", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* ** Create a buffer for the data bits with ** a buffer of this size. We can 2x ** enlarge an 8-bit image of dimensions ** up to 128x128. */ ScaledImageBuf = (char *)mi_alloc( 4*bi.bmiHeader.biWidth*bi.bmiHeader.biHeight ); /* Allocate room for the color map. */ ColorsUsed = bi.bmiHeader.biClrUsed == 0 ? 256 : bi.bmiHeader.biClrUsed; ColorMap = (char *)mi_alloc( 4 * ColorsUsed ); ColorSize = bf.bfOffBits-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER); /* Read the color table that preceeds the image bits array. */ if( mi_large_object_read( Gen_Con, Gen_LoDesc, ColorMap, ColorSize ) == MI_ERROR) { /* ** An error has occurred while reading the large object. */ DBDK_TRACE_ERROR( "ZoomImageXN", "MMX06", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* ** ... and read the image pixel values. Space is ** inserted in preparation for the scaling. */ lp = ScaledImageBuf; for( index = 0; index < bi.bmiHeader.biHeight; index++ ) { if( mi_large_object_read( Gen_Con, Gen_LoDesc, lp, bi.bmiHeader.biWidth ) == MI_ERROR ) { /* ** An error has occurred while reading the large object. */ DBDK_TRACE_ERROR( "ZoomImageXN", "MMX06", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } lp += 2 * bi.bmiHeader.biWidth; } mi_large_object_close( Gen_Con, Gen_LoDesc ); /* ** Piece the new image together. */ bf.bfSize += 3 * bi.bmiHeader.biHeight * bi.bmiHeader.biWidth; bi.bmiHeader.biWidth *= 2; bi.bmiHeader.biHeight *= 2; bi.bmiHeader.biSizeImage *= 4; /* ** Call MMXImage2x to perform a N-zoom of the image. ** Note the semantics of the following for-loops: ** a zoom of 1 is the same as a call to EnlargeImageX2. */ if( Gen_IsMMXMachine() ) { for( ZoomIndex = 0; ZoomIndex < ZoomCount; ++ZoomIndex ) { MMXImage2x( ScaledImageBuf, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight ); } } else { for( ZoomIndex = 0; ZoomIndex < ZoomCount; ++ZoomIndex ) { CImage2x( ScaledImageBuf, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight ); } } /* Compute and store your value into Gen_RetVal. */ Gen_RetVal = (Image *)mi_alloc( sizeof( Image ) ); if( Gen_RetVal == 0) { /* ** Memory allocation has failed so issue ** the following message and quit. ** ** "Memory allocation has failed in ZoomImageXN." */ DBDK_TRACE_ERROR( "ZoomImageXN", ERRORMESG2, 10 ); /* not reached */ } /* ** Create a new LO from the scaled bitmap and place ** it in the return result. The process is, create ** an empty LO, open it, write the BMP image to it, ** and, finally, close it. */ ImageHandle = mi_large_object_create_opts ( Gen_Con, NULL, MI_LO_INTERNAL_LO, NULL, MI_LO_DEFAULT_SMGR, NULL, NULL, NULL ); if( ImageHandle == NULL ) { /* ** An error has occurred while creating the large object. */ DBDK_TRACE_ERROR( "ZoomImageXN", "MMX04", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Open the newly created large object for appending. */ Gen_LoDesc = mi_large_object_open( Gen_Con, ImageHandle, MI_LO_WRONLY | MI_LO_APPEND ); if( Gen_LoDesc == MI_ERROR ) { /* ** An error has occurred while creating the large object. */ DBDK_TRACE_ERROR( "ZoomImageXN", "MMX04", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Save the LO handle. */ Gen_RetVal->ImageHandle = *ImageHandle; /* Write the image to the large object. */ if( mi_large_object_write( Gen_Con, Gen_LoDesc, (char *)&bf, sizeof(BITMAPFILEHEADER) ) == MI_ERROR || mi_large_object_write( Gen_Con, Gen_LoDesc, (char *)&bi, sizeof(BITMAPINFOHEADER) ) == MI_ERROR || mi_large_object_write( Gen_Con, Gen_LoDesc, ColorMap, 4 * ColorsUsed ) == MI_ERROR || mi_large_object_write( Gen_Con, Gen_LoDesc, ScaledImageBuf, bi.bmiHeader.biWidth * bi.bmiHeader.biHeight ) == MI_ERROR || mi_large_object_close( Gen_Con, Gen_LoDesc ) == MI_ERROR ) { /* ** An error has occurred while writing the large object. */ DBDK_TRACE_ERROR( "ZoomImageXN", "MMX04", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Get the data value for Gen_OutData->ImageWidth. */ Gen_RetVal->ImageWidth = 2 * MyImage->ImageWidth; /* Get the data value for Gen_OutData->ImageHeight. */ Gen_RetVal->ImageHeight = 2 * MyImage->ImageHeight; /* ** Build a new description. This is the description ** of the unscaled image prepended with "(Zoomed xN)". ** We must be careful not to exceed the alloted size ** for ImageDescription. */ strcpy( (char *)&Gen_RetVal->ImageDescription, "(Zoomed xN)" ); tempptr = (char *)Gen_RetVal->ImageDescription; memcpy( tempptr + strlen("(Zoomed xN)"), &MyImage->ImageDescription, sizeof(Gen_RetVal->ImageDescription) - strlen("(Zoomed xN)") -1 ); /* Free allocated memory. */ mi_free( ScaledImageBuf ); mi_free( ColorMap ); /* ** Write to the trace file indicating ** that ZoomImageXN has successfully exited. */ DBDK_TRACE_EXIT( "ZoomImageXN" ); /* ------ }}Your_Code (#8QNQ) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#BSEPAA92) */ /* {{FUNCTION(7d39abf1-dd12-11d0-8874-00a0c9255cf3) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** ReduceImageX2 ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine ReduceImageX2 (Image) returns Image. ** ** Parameters: ** ** Return value: ** ** Image ** ** History: ** ** 06/30/1998 - Generated by BladeSmith Version 3.60.630 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT Image * ReduceImageX2 ( Image * MyImage, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { Image* Gen_RetVal; /* The return value. */ MI_CONNECTION * Gen_Con; /* The connection handle. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ MI_LODESC Gen_LoDesc; /* The LO descriptor. */ MI_LO_HANDLE * ImageHandle; /* The image's LO handle. */ char * ScaledImageBuf; /* A buffer for the image pixels. */ char * ShrunkImageBuf; /* A buffer for the image pixels. */ char * ColorMap; /* The image's color map. */ int ColorsUsed; /* The number of colors used. */ mi_integer ColorSize; /* Size of the color table. */ BITMAPFILEHEADER bf; /* BMP file header info. */ BITMAPINFO bi; /* BMP image info. */ char * tempptr; /* Used to copy the description. */ /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ /* ** Write to the trace file indicating ** that ReduceImageX2 has been called. */ DBDK_TRACE_ENTER( "ReduceImageX2" ); /* Open the large object's handle and read it. */ Gen_LoDesc = mi_large_object_open( Gen_Con, &MyImage->ImageHandle, MI_LO_RDONLY ); if( Gen_LoDesc == MI_ERROR ) { /* ** An error has occurred while creating the large object. */ DBDK_TRACE_ERROR( "ReduceImageX2", "MMX04", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Read the LO BMP file. */ if( mi_large_object_read( Gen_Con, Gen_LoDesc, (char *)&bf, sizeof(BITMAPFILEHEADER) ) == MI_ERROR || mi_large_object_read( Gen_Con, Gen_LoDesc, (char *)&bi, sizeof(BITMAPINFOHEADER) ) == MI_ERROR ) { /* ** An error has occurred while reading the large object. */ DBDK_TRACE_ERROR( "ReduceImageX2", "MMX06", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* ** Create a buffer for the data bits with ** a buffer of this size. We can 2x ** reduce an 8-bit image of dimensions ** up to 128x128. */ ScaledImageBuf = (char *)mi_alloc( bi.bmiHeader.biWidth*bi.bmiHeader.biHeight+1000 ); ShrunkImageBuf = (char *)mi_alloc( bi.bmiHeader.biWidth*bi.bmiHeader.biHeight+1000 ); /* Allocate room for the color map. */ ColorsUsed = bi.bmiHeader.biClrUsed == 0 ? 256 : bi.bmiHeader.biClrUsed; ColorMap = (char *)mi_alloc( 4 * ColorsUsed ); ColorSize = bf.bfOffBits-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER); /* Read the color table that preceeds the image bits array. */ if( mi_large_object_read( Gen_Con, Gen_LoDesc, ColorMap, ColorSize) == MI_ERROR || /* ... and read the image pixel values. */ mi_large_object_read( Gen_Con, Gen_LoDesc, ScaledImageBuf, bi.bmiHeader.biWidth*bi.bmiHeader.biHeight ) == MI_ERROR || mi_large_object_close( Gen_Con, Gen_LoDesc ) == MI_ERROR ) { /* ** An error has occurred while reading the large object. */ DBDK_TRACE_ERROR( "ReduceImageX2", "MMX06", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* ** Call MMXpick1of4 to perform the 2X down scaling of the image. */ if( Gen_IsMMXMachine() ) { MMXpick1of4( ScaledImageBuf, ShrunkImageBuf, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight ); } else { Cpick1of4( ScaledImageBuf, ShrunkImageBuf, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight ); } /* ** Adjust the image info for the scaled image. ** Note that in the case when width and height are ** odd, the resultant has a height and width which ** is the integral value of the division by two. */ bf.bfSize -= 3 * bi.bmiHeader.biHeight * bi.bmiHeader.biWidth; bi.bmiHeader.biWidth /= 2; bi.bmiHeader.biHeight /= 2; bi.bmiHeader.biSizeImage /= 4; /* Compute and store your value into Gen_RetVal. */ Gen_RetVal = (Image *)mi_alloc( sizeof( Image ) ); if( Gen_RetVal == 0) { /* ** Memory allocation has failed so issue ** the following message and quit. ** ** "Memory allocation has failed in ReduceImageX2." */ DBDK_TRACE_ERROR( "ReduceImageX2", ERRORMESG2, 10 ); /* not reached */ } /* ** Create a new LO from the scaled bitmap and place ** it in the return result. The process is, create ** an empty LO, open it, write the BMP image to it, ** and, finally, close it. */ ImageHandle = mi_large_object_create_opts ( Gen_Con, NULL, MI_LO_INTERNAL_LO, NULL, MI_LO_DEFAULT_SMGR, NULL, NULL, NULL ); if( ImageHandle == NULL ) { /* ** An error has occurred while creating the large object. */ DBDK_TRACE_ERROR( "ReduceImageX2", "MMX04", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Open the newly created large object for appending. */ Gen_LoDesc = mi_large_object_open( Gen_Con, ImageHandle, MI_LO_WRONLY | MI_LO_APPEND ); if( Gen_LoDesc == MI_ERROR ) { /* ** An error has occurred while creating the large object. */ DBDK_TRACE_ERROR( "ReduceImageX2", "MMX04", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Save the LO handle. */ Gen_RetVal->ImageHandle = *ImageHandle; /* Write the image to the large object. */ if( mi_large_object_write( Gen_Con, Gen_LoDesc, (char *)&bf, sizeof(BITMAPFILEHEADER) ) == MI_ERROR || mi_large_object_write( Gen_Con, Gen_LoDesc, (char *)&bi, sizeof(BITMAPINFOHEADER) ) == MI_ERROR || mi_large_object_write( Gen_Con, Gen_LoDesc, ColorMap, 4 * ColorsUsed ) == MI_ERROR || mi_large_object_write( Gen_Con, Gen_LoDesc, ShrunkImageBuf, bi.bmiHeader.biWidth * bi.bmiHeader.biHeight ) == MI_ERROR || mi_large_object_close( Gen_Con, Gen_LoDesc ) == MI_ERROR ) { /* ** An error has occurred while writing the large object. */ DBDK_TRACE_ERROR( "ReduceImageX2", "MMX04", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* ** Piece the new Image together. */ /* Get the data value for Gen_OutData->ImageWidth. */ Gen_RetVal->ImageWidth = MyImage->ImageWidth/2; /* Get the data value for Gen_OutData->ImageHeight. */ Gen_RetVal->ImageHeight = MyImage->ImageHeight/2; /* ** Build a new description. This is the description ** of the unscaled image prepended with "(Reduced x2)". ** We must be careful not to exceed the alloted size ** for ImageDescription. */ strcpy( (char *)&Gen_RetVal->ImageDescription, "(Reduced x2)" ); tempptr = (char *)Gen_RetVal->ImageDescription; memcpy( tempptr + strlen("(Reduced x2)"), &MyImage->ImageDescription, sizeof(Gen_RetVal->ImageDescription) - strlen("(Reduced x2)") -1 ); /* Free allocated memory. */ mi_free( ScaledImageBuf ); mi_free( ShrunkImageBuf ); mi_free( ColorMap ); /* ** Write to the trace file indicating ** that ReduceImageX2 has successfully exited. */ DBDK_TRACE_EXIT( "ReduceImageX2" ); /* ------ }}Your_Code (#QUJS) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#19SB55FG) */ __int64 MASK = 0x00ff00ff00ff00ff; void MMXpick1of4( byte * lpSource, byte * lpDest, int width, int height ) { int w; /* Counter for unprocessed pixels in a row. */ int h; /* Counter for unprocessed rows of pixels. */ w = width; h = height; __asm { mov esi, lpSource mov edi, lpDest mov eax, width mov ebx, height mov ecx, eax ; ecx = BREADTH COUNTER movq mm7, MASK ; MAKE A MASK = 00ff00ff00ff00ffh RowLoop: cmp ebx, 1 jng Done cmp ecx, 15 jng GotoNewRow mov edx, eax ; COPY BREADTH IN edx PixelLoop: movq mm0, [esi] ; p07 p06 p05 p04 p03 p02 p01 p00 movq mm1, [esi + 8] ; p15 p14 p13 p12 p11 p10 p09 p08 pand mm0, mm7 ; 0 p06 0 p04 0 p02 0 p00 pand mm1, mm7 ; 0 p14 0 p12 0 p10 0 p08 packuswb mm0, mm1 ; p14 p12 p10 p08 p06 p04 p02 p00 movq [edi], mm0 ; WRITEBACK TO DESTINATION ARRAY sub ecx, 16 add esi, 16 ; GO TO NEXT SET OF PIXELS add edi, 8 cmp ecx, 16 jge PixelLoop GotoNewRow: add esi, edx ; GENERATE ADDRESS OF NEW ROW mov ecx, eax ; ecx = RELOAD WIDTH COUNTER WITH WIDTH sub ebx, 2 ; UPDATE # OF ROWS REMAINING jmp RowLoop Done: emms ; EMPTY THE MMX STATE } } void Cpick1of4( byte * lpSource, byte * lpDest, int width, int height ) { int w; /* Counter for unprocessed pixels in a row. */ int h; /* Counter for unprocessed rows of pixels. */ int readPtr = 0; /* Advances pointer to average next 4 pixels. */ int writePtr = 0; /* Advances pointer to write a pixel. */ w = width; h = height; while( h > 1 ) { while( w > 1 ) { // PICKING ONE FROM A SQUARE BLOCK OF 4 PIXELS // readPtr/writePtr ARE THE BASE AND i ADDS THE BYTE-OFFSET lpDest[writePtr] = lpSource[readPtr]; writePtr++; readPtr += 2; w -= 2; // 2 PIXELS OF A ROW DONE } /* Begin a new row. */ if( w == 1 ) // ODD PIXEL - INCREMENT ODD PIXEL + NEXT ROW { readPtr += 1 + width; // SKIP A ROW } else // EVEN PIXEL - INCREMENT TO NEXT ROW { readPtr += width; } w = width; // RESET 'w' h -= 2; // MOVE POINTER TO NEXT PAIR OF ROWS // SKIP A ROW } } /* {{FUNCTION(19b7386a-d6b0-11d0-8874-00a0c9255cf3) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** EnlargeImageX2 ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine EnlargeImageX2 (Image) returns Image. ** ** Parameters: ** ** Return value: ** ** Image ** ** History: ** ** 06/30/1998 - Generated by BladeSmith Version 3.60.630 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT Image * EnlargeImageX2 ( Image * MyImage, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { Image* Gen_RetVal; /* The return value. */ MI_CONNECTION * Gen_Con; /* The connection handle. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ MI_LODESC Gen_LoDesc; /* The LO descriptor. */ MI_LO_HANDLE * ImageHandle; /* The image's LO handle. */ char * ScaledImageBuf; /* A buffer for the image pixels. */ char * ColorMap; /* The image's color map. */ int ColorsUsed; /* The number of colors used. */ mi_integer ColorSize; /* Size of the color map. */ BITMAPFILEHEADER bf; /* BMP file header info. */ BITMAPINFO bi; /* BMP image info. */ char * tempptr; /* Used to copy the description. */ char * lp; /* Temporary copy ptr. */ int index; /* Index over the image's rows. */ /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ /* ** Write to the trace file indicating ** that EnlargeImageX2 has been called. */ DBDK_TRACE_ENTER( "EnlargeImageX2" ); /* Open the large object's handle and read it. */ Gen_LoDesc = mi_large_object_open( Gen_Con, &MyImage->ImageHandle, MI_LO_RDONLY ); if( Gen_LoDesc == MI_ERROR ) { /* ** An error has occurred while reading the large object. */ DBDK_TRACE_ERROR( "EnlargeImageX2", "MMX06", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Read the LO BMP file. */ if( mi_large_object_read( Gen_Con, Gen_LoDesc, (char *)&bf, sizeof(BITMAPFILEHEADER) ) == MI_ERROR || mi_large_object_read( Gen_Con, Gen_LoDesc, (char *)&bi, sizeof(BITMAPINFOHEADER) ) == MI_ERROR ) { /* ** An error has occurred while reading the large object. */ DBDK_TRACE_ERROR( "EnlargeImageX2", "MMX06", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* ** Create a buffer for the data bits with ** a buffer of this size. We can 2x ** enlarge an 8-bit image of dimensions ** up to 128x128. */ ScaledImageBuf = (char *)mi_alloc( 4*bi.bmiHeader.biWidth*bi.bmiHeader.biHeight ); /* Allocate room for the color map. */ ColorsUsed = bi.bmiHeader.biClrUsed == 0 ? 256 : bi.bmiHeader.biClrUsed; ColorMap = (char *)mi_alloc( 4 * ColorsUsed ); ColorSize = bf.bfOffBits-sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER); /* Read the color table that preceeds the image bits array. */ if( mi_large_object_read( Gen_Con, Gen_LoDesc, ColorMap, ColorSize ) == MI_ERROR) { /* ** An error has occurred while reading the large object. */ DBDK_TRACE_ERROR( "EnlargeImageX2", "MMX06", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* ** ... and read the image pixel values. Space is ** inserted in preparation for the scaling. */ lp = ScaledImageBuf; for( index = 0; index < bi.bmiHeader.biHeight; index++ ) { if( mi_large_object_read( Gen_Con, Gen_LoDesc, lp, bi.bmiHeader.biWidth ) == MI_ERROR ) { /* ** An error has occurred while reading the large object. */ DBDK_TRACE_ERROR( "EnlargeImageX2", "MMX06", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } lp += 2 * bi.bmiHeader.biWidth; } mi_large_object_close( Gen_Con, Gen_LoDesc ); /* ** Piece the new image together. */ bf.bfSize += 3 * bi.bmiHeader.biHeight * bi.bmiHeader.biWidth; bi.bmiHeader.biWidth *= 2; bi.bmiHeader.biHeight *= 2; bi.bmiHeader.biSizeImage *= 4; /* ** Call MMXImage2x to perform the 2X scaling of the image. */ if( Gen_IsMMXMachine() ) { MMXImage2x( ScaledImageBuf, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight ); } else { CImage2x( ScaledImageBuf, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight ); } /* Compute and store your value into Gen_RetVal. */ Gen_RetVal = (Image *)mi_alloc( sizeof( Image ) ); if( Gen_RetVal == 0) { /* ** Memory allocation has failed so issue ** the following message and quit. ** ** "Memory allocation has failed in EnlargeImageX2." */ DBDK_TRACE_ERROR( "EnlargeImageX2", ERRORMESG2, 10 ); /* not reached */ } /* ** Create a new LO from the scaled bitmap and place ** it in the return result. The process is, create ** an empty LO, open it, write the BMP image to it, ** and, finally, close it. */ ImageHandle = mi_large_object_create_opts ( Gen_Con, NULL, MI_LO_INTERNAL_LO, NULL, MI_LO_DEFAULT_SMGR, NULL, NULL, NULL ); if( ImageHandle == NULL ) { /* ** An error has occurred while creating the large object. */ DBDK_TRACE_ERROR( "EnlargeImageX2", "MMX04", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Open the newly created large object for appending. */ Gen_LoDesc = mi_large_object_open( Gen_Con, ImageHandle, MI_LO_WRONLY | MI_LO_APPEND ); if( Gen_LoDesc == MI_ERROR ) { /* ** An error has occurred while creating the large object. */ DBDK_TRACE_ERROR( "EnlargeImageX2", "MMX04", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Save the LO handle. */ Gen_RetVal->ImageHandle = *ImageHandle; /* Write the image to the large object. */ if( mi_large_object_write( Gen_Con, Gen_LoDesc, (char *)&bf, sizeof(BITMAPFILEHEADER) ) == MI_ERROR || mi_large_object_write( Gen_Con, Gen_LoDesc, (char *)&bi, sizeof(BITMAPINFOHEADER) ) == MI_ERROR || mi_large_object_write( Gen_Con, Gen_LoDesc, ColorMap, 4 * ColorsUsed ) == MI_ERROR || mi_large_object_write( Gen_Con, Gen_LoDesc, ScaledImageBuf, bi.bmiHeader.biWidth * bi.bmiHeader.biHeight ) == MI_ERROR || mi_large_object_close( Gen_Con, Gen_LoDesc ) == MI_ERROR ) { /* ** An error has occurred while writing the large object. */ DBDK_TRACE_ERROR( "EnlargeImageX2", "MMX04", 0 ); mi_fp_setreturnisnull( Gen_fparam, 0, MI_TRUE ); return (0); } /* Get the data value for Gen_OutData->ImageWidth. */ Gen_RetVal->ImageWidth = 2 * MyImage->ImageWidth; /* Get the data value for Gen_OutData->ImageHeight. */ Gen_RetVal->ImageHeight = 2 * MyImage->ImageHeight; /* ** Build a new description. This is the description ** of the unscaled image prepended with "(Enlarged x2)". ** We must be careful not to exceed the alloted size ** for ImageDescription. */ strcpy( (char *)&Gen_RetVal->ImageDescription, "(Enlarged x2)" ); tempptr = (char *)Gen_RetVal->ImageDescription; memcpy( tempptr + strlen("(Enlarged x2)"), &MyImage->ImageDescription, sizeof(Gen_RetVal->ImageDescription) - strlen("(Enlarged x2)") -1 ); /* Free allocated memory. */ mi_free( ScaledImageBuf ); mi_free( ColorMap ); /* ** Write to the trace file indicating ** that EnlargeImageX2 has successfully exited. */ DBDK_TRACE_EXIT( "EnlargeImageX2" ); /* ------ }}Your_Code (#9TH8) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#HPH58UG3) */ /**************************************************************** ** ** Function name: ** ** CImage2x ** ** Description: ** ** This is the C equivalent of the MMX routine MMXImage2x. ** ** Special Comments: ** ** Support routine for opaque type Image returns image. ** ** Parameters: ** ** byte * lpBackbufferMemory Points to the beginning of the image ** int x_res Width ** int y_res Height ** ** NOTE: This program assumes image height to be equal to the image width. ** ** Return value: ** ** Image * The constructed UDT value. ** ** History: ** ** May 30, 1997 - Generated by BladeSmith Version 3.30.TM2. ** ***************************************************************** */ void CImage2x(byte *lpBackbufferMemory, int x_res, int y_res ) { register byte * srcptr; register byte * destptr; int i; int j; /* srcptr points to the end of the source rectangle to be expanded. */ srcptr = ((y_res/2) * x_res) - (x_res/2) + lpBackbufferMemory; /* desptr points to the end of the surface memory. */ destptr = (y_res * x_res) + lpBackbufferMemory; /* ** In the loop below, pixels are processed starting from the ** high memory locations and moving to lower memory locations. */ for (j = y_res/2; j > 0; j-- ) { for ( i = 0; i < x_res/2; i++ ) { destptr = destptr - 2; srcptr = srcptr - 1; *destptr = *srcptr; *(destptr + 1) = *srcptr; *(destptr-x_res) = *srcptr; *(destptr+1-x_res) = *srcptr; } srcptr = srcptr - (x_res/2); destptr = destptr - x_res; } } /**************************************************************** ** ** Function name: ** ** MMXImage2x ** ** Description: ** ** MMX enabled function which uses massive array arithmetic ** to do rapid integer unpacking to double scale an image. ** ** Special Comments: ** ** Support routine for opaque type Image returns image. ** ** Parameters: ** ** byte * lpBackbufferMemory Points to the beginning of the image ** int x_res Width ** int y_res Height ** ** NOTE: This program assumes image height to be equal to the image width. ** ** Return value: ** ** Image * The constructed UDT value. ** ** History: ** ** May 30, 1997 - Generated by BladeSmith Version 3.30.TM2. ** ***************************************************************** */ void MMXImage2x ( byte * lpBackbufferMemory, int x_res, int y_res ) { int x_half; _asm { mov edi, x_res ; edi = x_res mov edx, x_res mov eax, edi shr edx, 1 ; edx = x_res /2 mov esi, edi imul eax, y_res ; edx:eax = x_res * y_res ; But since x_res * y_res does not exceed 65536 ; (individual) the results in edx are ignored. mov ebx, eax add eax, lpBackbufferMemory shr ebx, 1 ; ebx = (y_res/2) * x_res sub eax, edi ; eax = end destination - x_res mov x_half, edx add ebx, lpBackbufferMemory ; ebx = source end + x_half mov ecx, eax sub ebx, x_half ; ebx = source end shl esi, 1 ; esi = 2*x_res sub ecx, edi ; ecx = end destination - 2*x_res ; Pointer initialization is completed here. ; The main loop starts here. loopstart: movq mm0, [ebx - 32] movq mm1, mm0 mov edx, [eax - 64] ; Cache read -- better performance sub ebx, 32 mov edx, [eax - 32] ; Cache read -- better performance sub eax, 64 punpcklbw mm0, mm0 movq mm2, [ebx + 8] ; 2nd read punpckhbw mm1, mm1 movq [eax + edi], mm0 ; 2a write -- row no. 2 movq [eax + edi + 8], mm1 ; 2b write -- row no. 2 movq mm3, mm2 movq [eax], mm0 ; 1a write -- row no. 1 punpcklbw mm2, mm2 movq [eax + 8], mm1 ; 1b write movq [eax + 16], mm2 ; 1c write punpckhbw mm3, mm3 movq mm4, [ebx + 16] ; 3rd read movq [eax + 24], mm3 ; 1d write movq mm5, mm4 movq [eax + edi + 16], mm2 ; 2c write punpcklbw mm4, mm4 movq [eax + edi + 24], mm3 ; 2d write punpckhbw mm5, mm5 movq [eax + 32], mm4 ; 1e write movq mm6, [ebx + 24] ; 4th read movq [eax + 40], mm5 ; 1f write movq mm7, mm6 movq [eax + edi + 32], mm4 ; 2e write punpcklbw mm6, mm6 movq [eax + edi + 40], mm5 ; 2f write punpckhbw mm7, mm7 movq [eax + 48], mm6 ; 1g write movq [eax + 56], mm7 ; 1h write movq [eax + edi + 48], mm6 ; 2g write movq [eax + edi + 56], mm7 ; 2h write cmp ecx, eax jne loopstart sub ecx, esi sub eax, edi sub ebx, x_half cmp eax, lpBackbufferMemory ja loopstart emms } /* _asm */ } #ifdef __cplusplus } #endif