Assuming the source and destination images are packed 24-bit RGB, and you have two open file handles to these images, and the headers are properly formed, try this:
This crops the source image of dimension (sw x sh) starting at pixel (cropX, cropY) to the destination image of dimension (dw x dh).
void cropRGB( FILE *srcImg, unsigned int srcDataOffset, unsigned int sw, unsigned int sh,
FILE *dstImg, unsigned int dstDataOffset, unsigned int dw, unsigned int dh,
unsigned int cropX, unsigned int cropY )
unsigned int row;
unsigned char *rowBuffer = malloc( 3 * dw );
if( dstDataOffset > 0 )
fseek( dstImg, dstDataOffset, SEEK_SET );
for( row = cropY; row < cropY + dh; ++row )
fseek( srcImg, srcDataOffset + 3 * ( row * sw + cropX ), SEEK_SET );
fread ( rowBuffer, 1, 3 * dw, srcImg );
fwrite( rowBuffer, 1, 3 * dw, dstImg );
free( rowBuffer );
srcDataOffset and dstDataOffset point past the image headers to the first byte of where the image data starts for both the input and output images.
if the destination is not seekable (for instance, it's a pipe or stdout) then you can pass 0 for the dstDataOffset and the data will be written where the file pointer is positioned.