/** ** $Header: /roq/libim/imvfbchan.c 1 11/02/99 4:38p Zaphod $ ** Copyright (c) 1989-1995 San Diego Supercomputer Center (SDSC) ** a division of General Atomics, San Diego, California, USA ** ** Users and possessors of this source code are hereby granted a ** nonexclusive, royalty-free copyright and design patent license to ** use this code in individual software. License is not granted for ** commercial resale, in whole or in part, without prior written ** permission from SDSC. This source is provided "AS IS" without express ** or implied warranty of any kind. ** ** For further information contact: ** E-Mail: info@sds.sdsc.edu ** ** Surface Mail: Information Center ** San Diego Supercomputer Center ** P.O. Box 85608 ** San Diego, CA 92138-5608 ** (619) 534-5000 **/ #define HEADER " $Header: /roq/libim/imvfbchan.c 1 11/02/99 4:38p Zaphod $" /** ** FILE ** imvfbchan.c - Image Library VFB channel interchanging ** ** PROJECT ** libim - SDSC image manipulation library ** ** DESCRIPTION ** These functions permute / copy channels between VFBs. ** ** PUBLIC CONTENTS ** d =defined constant ** f =function ** m =defined macro ** t =typedef/struct/union ** v =variable ** ? =other ** ** ImVfbCopyChannel f copy one channel of one vfb to ** another channel of a another vfb ** ImVfbProcessMapRequests f Permute the channels of a vfb ** ** PRIVATE CONTENTS ** none ** ** HISTORY ** $Log: /roq/libim/imvfbchan.c $ * * 1 11/02/99 4:38p Zaphod * Revision 1.6 1995/09/28 05:11:40 bduggan * fixed -inmap, -outmap bug * (default is to copy rgb channels * now when the alpha is copied.) * / * * Revision 1.5 1995/06/30 22:11:26 bduggan * removed strings.h * * Revision 1.4 1995/06/29 00:28:04 bduggan * updated copyright year * * Revision 1.3 1995/06/16 08:51:54 bduggan * added some casts. took out some unused vars * * Revision 1.2 1995/05/17 23:49:12 bduggan * Added copying for a few more channels (PROT, Z, DATA) * * Revision 1.1 1995/02/16 21:43:00 bduggan * Initial revision * **/ /** ** CODE CREDITS ** Custom development, Brian Duggan, San Diego Supercomputer Center, 1995 **/ #include "iminternal.h" #include #ifdef __STDC__ static int imGetOutChannel(char* expression); static int imGetInChannel(char* expression); static ImVfb* imAllocateNewVfb(TagTable* flagsTable, ImVfb* inVfb); static int imCheckChannelMapEntries(TagTable* flagsTable, ImVfb* inVfb); static int imGiveInfoAboutChannel(TagTable* flagsTable, char* chanName); #else static int imGetOutChannel(); static int imGetInChannel(); static ImVfb* imAllocateNewVfb(); static int imCheckChannelMapEntries(); static int imGiveInfoAboutChannel(); #endif /* * MACRO * ImVfbQChannel (value, vfb, vfbptr, channel) * * DESCRIPTION * Query a channel of the vfb into value * */ #define ImVfbQChannel(value, vfb, vfbptr, channel) \ switch (channel & IMVFBOTHERMASK) \ { \ case IMVFBGREY : /* same as INDEX8 */ \ value = ImVfbQGrey (vfb, vfbptr); \ break; \ case IMVFBRED : \ value = ImVfbQRed (vfb, vfbptr); \ break; \ case IMVFBGREEN : \ value = ImVfbQGreen(vfb, vfbptr); \ break; \ case IMVFBBLUE : \ value = ImVfbQBlue (vfb, vfbptr); \ break; \ case IMVFBALPHA : \ value = ImVfbQAlpha (vfb, vfbptr); \ break; \ case IMVFBWPROT : \ value = ImVfbQWProt (vfb, vfbptr); \ break; \ case IMVFBZ : \ value = ImVfbQZ(vfb, vfbptr ); \ break; \ case IMVFBFDATA : \ /* value = ImVfbQFData(vfb, vfbptr ); */ \ break; \ case IMVFBIDATA : \ value = ImVfbQIData(vfb, vfbptr ); \ break; \ default : \ if (channel & IMVFBINDEX8) \ value = ImVfbQGrey (vfb, vfbptr); \ else if (channel & IMVFBINDEX16) \ value = ImVfbQIndex16 (vfb, vfbptr); \ else \ value = 0; \ break; \ } /* * MACRO * ImVfbSChannel (value, vfb, vfbptr, channel) * * DESCRIPTION * Put value into this channel of the vfb * */ #define ImVfbSChannel(value, vfb, vfbptr, channel) \ switch (channel & IMVFBOTHERMASK) \ { \ case IMVFBRED : \ ImVfbSRed (vfb, vfbptr, value); \ break; \ case IMVFBGREEN : \ ImVfbSGreen(vfb, vfbptr, value); \ break; \ case IMVFBBLUE : \ ImVfbSBlue (vfb, vfbptr, value); \ break; \ case IMVFBALPHA : \ ImVfbSAlpha (vfb, vfbptr, value); \ break; \ case IMVFBWPROT : \ ImVfbSWProt (vfb, vfbptr, value); \ break; \ case IMVFBZ : \ ImVfbSZ(vfb, vfbptr, value); \ break; \ case IMVFBFDATA : \ /* ImVfbSFData(vfb, vfbptr, value); */ \ break; \ case IMVFBIDATA : \ ImVfbSIData(vfb, vfbptr, value); \ break; \ default : \ if (channel & IMVFBGREY) \ ImVfbSGrey (vfb, vfbptr, value); \ else \ if (channel & IMVFBINDEX16) \ ImVfbSIndex16 (vfb, vfbptr, value); \ break; \ } /* * FUNCTION * ImVfbCopyChannel * * DESCRIPTION * Copy a specified channel from one vfb to * a specified channel of another vfb * * The channels which can be specifed are as follows: * IMVFBRED red * IMVFBBLUE blue * IMVFBGREEN green * IMVFBALPHA alpha * IMVFBINDEX8 index8 / gray * IMVFBINDEX16 index16 * NULL none * * Copying "none" to a channel is equivalent to filling the outgoing * channel with zeros. * * (It does not make the channel dissappear from the vfb. If this is * desired, then the -outnoalpha option, for instance, should be used.) * */ ImVfb * /* Returns the destination vfb */ #ifdef __STDC__ ImVfbCopyChannel( ImVfb* inVfb, int inFieldMask, ImVfb* outVfb, int outFieldMask) #else ImVfbCopyChannel( inVfb, inFieldMask, outVfb, outFieldMask) ImVfb* inVfb; int inFieldMask; ImVfb* outVfb; int outFieldMask; #endif { int width, height; /* Dimensions of incoming vfb */ int w, h; /* Loop indices */ ImVfbPtr inVfbPtr; /* pointer into a vfb */ ImVfbPtr outVfbPtr; /* pointer into a vfb */ unsigned int chanData; /* temporary variable for data */ unsigned int tempMask; /* holds masks during error checking */ int inOK, outOK; /* flags indicating that masks are ok*/ int inFields, outFields; /* Fields in the vfbs */ char message[300]; /* Buffer for messages */ if (inVfb==IMVFBNULL) { ImErrNo = IMENOVFB; return IMVFBNULL; } /* Get width and height of incoming vfb */ width = ImVfbQWidth (inVfb); height = ImVfbQHeight (inVfb); /* Allocate a new Vfb if necessary */ if (outVfb==IMVFBNEW) { int allocFields; /* Make it the same type as the incoming vfb */ allocFields = ImVfbQFields (inVfb) & IMVFBIMAGEMASK; outVfb = ImVfbAlloc(width, height, allocFields | outFieldMask); if (outVfb == IMVFBNULL) { ImErrNo = IMEMALLOC; return IMVFBNULL; } } /* Discern the fields that are present */ inFields = ImVfbQFields(inVfb); outFields = ImVfbQFields(outVfb); if (inFields & IMVFBRGB) { inFields |= IMVFBRED; inFields |= IMVFBGREEN; inFields |= IMVFBBLUE; } if (outFields & IMVFBRGB) { outFields |= IMVFBRED; outFields |= IMVFBGREEN; outFields |= IMVFBBLUE; } /* Confirm that inVfb has the specified field * (if it's not NULL) */ if ((inFieldMask!=NULL) && !(inFields & inFieldMask)) { sprintf(message,"The incoming vfb does not have the requested channel"); ImErrorFatal( message, IMVFBNULL, IMEBADCHANNEL ); } /* * Confirm that outVfb has the specified field */ if (!(outFields & outFieldMask)) { sprintf(message,"The requested channel is not supported by the outgoing vfb"); ImErrorFatal( message, IMVFBNULL, IMEFIELD ); } /* Confirm that the vfbs are the same size */ if ( width!=ImVfbQWidth(outVfb) || height!=ImVfbQHeight(outVfb)) { ImErrNo = IMEDIFFSIZE; return IMVFBNULL; } /* Verify that the field masks are okay */ /* i.e. only one field can be copied */ inOK = (inFieldMask==NULL); /* Okay to copy from "none" */ outOK = 0; /* Can't copy to "none" */ for (tempMask = (((unsigned int)1)<<31); (tempMask!=0) ; tempMask >>= 1) { if (tempMask==inFieldMask) inOK = 1; if (tempMask==outFieldMask) outOK = 1; } if (!inOK || !outOK) { ImErrNo = IMEFIELD; return IMVFBNULL; } /* Copy the data (finally)! */ /* Note that a 16-bit value will automatically be truncated by the cast in the ImVfbSChannel macro, if index16 is copied to another channel */ inVfbPtr = ImVfbQPtr(inVfb, 0, 0); outVfbPtr = ImVfbQPtr(outVfb, 0, 0); for (w=0;w0 means okay, <=0 means not okay. */ #ifdef __STDC__ imCheckChannelMapEntries(TagTable* flagsTable, ImVfb* inVfb) #else imCheckChannelMapEntries(flagsTable, inVfb) TagTable * flagsTable; ImVfb* inVfb; #endif { int fieldsToTest; /* fields we are checking for */ int numMappings; /* number of mappings for this channel */ char* newString; /* new string to add to the table */ int inFields; /* fields in inVfb */ /* Discern the fields that are present */ inFields = ImVfbQFields(inVfb); if (inFields & IMVFBRGB) { inFields |= IMVFBRED; inFields |= IMVFBGREEN; inFields |= IMVFBBLUE; } fieldsToTest = inFields; /* * For each channel, ensure that there is precisely * ONE channel mapped to it. * * If there are more than one, report an error and quit. * If there are none * if this field exists in the inVfb, add channel=channel * if this field doesn't exist in inVfb, add channel=none */ /* * Red */ if (fieldsToTest & IMVFBRED) { numMappings = numOfMappingsToChannel(flagsTable, IMVFBRED); if (numMappings>1) { ImErrorFatal("Too many mappings to red", -1, IMEBADCHANNELS); } if (numMappings==0) { /* Add a mapping to red to the flags table */ if (inFields & IMVFBRED) { /* Add "red=red" to the flagsTable */ ImMalloc(newString, char *, 10 * sizeof(char)); strcpy(newString, "red=red"); } else { /* Add "red=none" to the flagsTable */ ImMalloc(newString, char *, 10 * sizeof(char)); strcpy(newString, "red=none"); } TagTableAppend(flagsTable, TagEntryAlloc("channel map request",POINTER, &newString)); } /* Give an imInfo message */ imGiveInfoAboutChannel(flagsTable,"red"); } /* * Green */ if (fieldsToTest & IMVFBGREEN) { numMappings = numOfMappingsToChannel(flagsTable, IMVFBGREEN); if (numMappings>1) { ImErrorFatal("Too many mappings to green", -1, IMEBADCHANNELS); } if (numMappings==0) { /* Add a mapping to red to the flags table */ if (inFields & IMVFBGREEN) { /* Add "green=green" to the flagsTable */ ImMalloc(newString, char *, 15 * sizeof(char)); strcpy(newString, "green=green"); } else { /* Add "green=none" to the flagsTable */ ImMalloc(newString, char *, 15 * sizeof(char)); strcpy(newString, "green=none"); } TagTableAppend(flagsTable, TagEntryAlloc("channel map request",POINTER, &newString)); } /* Give an imInfo message */ imGiveInfoAboutChannel(flagsTable,"green"); } /* * Blue */ if (fieldsToTest & IMVFBBLUE) { numMappings = numOfMappingsToChannel(flagsTable, IMVFBBLUE); if (numMappings>1) { ImErrorFatal("Too many mappings to blue", -1, IMEBADCHANNELS); } if (numMappings==0) { /* Add a mapping to red to the flags table */ if (inFields & IMVFBBLUE) { /* Add "blue=blue" to the flagsTable */ ImMalloc(newString, char *, 15 * sizeof(char)); strcpy(newString, "blue=blue"); } else { /* Add "blue=none" to the flagsTable */ ImMalloc(newString, char *, 15 * sizeof(char)); strcpy(newString, "blue=none"); } TagTableAppend(flagsTable, TagEntryAlloc("channel map request",POINTER, &newString)); } /* Give an imInfo message */ imGiveInfoAboutChannel(flagsTable,"blue"); } /* * Grey/Index8 */ if (fieldsToTest & IMVFBGREY) { numMappings = numOfMappingsToChannel(flagsTable, IMVFBGREY); if (numMappings>1) { ImErrorFatal("Too many mappings to grey", -1, IMEBADCHANNELS); } if (numMappings==0) { /* Add a mapping to grey to the flags table */ if (inFields & IMVFBGREY) { /* Add "grey=grey" to the flagsTable */ ImMalloc(newString, char *, 10 * sizeof(char)); strcpy(newString, "grey=grey"); } else { /* Add "grey=none" to the flagsTable */ ImMalloc(newString, char *, 10 * sizeof(char)); strcpy(newString, "grey=none"); } TagTableAppend(flagsTable, TagEntryAlloc("channel map request",POINTER, &newString)); } /* Give an imInfo message */ imGiveInfoAboutChannel(flagsTable,"grey"); } /* * Alpha */ if (fieldsToTest & IMVFBALPHA) { numMappings = numOfMappingsToChannel(flagsTable, IMVFBALPHA); if (numMappings>1) { ImErrorFatal("Too many mappings to alpha", -1, IMEBADCHANNELS); } if (numMappings==0) { /* Add a mapping to alpha to the flags table */ if (inFields & IMVFBALPHA) { /* Add "alpha=alpha" to the flagsTable */ ImMalloc(newString, char *, 10 * sizeof(char)); strcpy(newString, "alpha=alpha"); } else { /* Add "alpha=none" to the flagsTable */ ImMalloc(newString, char *, 10 * sizeof(char)); strcpy(newString, "alpha=none"); } TagTableAppend(flagsTable, TagEntryAlloc("channel map request",POINTER, &newString)); } /* Give an imInfo message */ imGiveInfoAboutChannel(flagsTable,"alpha"); } /* * Index16 */ if (fieldsToTest & IMVFBINDEX16) { numMappings = numOfMappingsToChannel(flagsTable, IMVFBINDEX16); if (numMappings>1) { ImErrorFatal("Too many mappings to index16", -1, IMEBADCHANNELS); } if (numMappings==0) { /* Add a mapping to red to the flags table */ if (inFields & IMVFBINDEX16) { /* Add "index16=index16" to the flagsTable */ ImMalloc(newString, char *, 20 * sizeof(char)); strcpy(newString, "index16=index16"); } else { /* Add "index16=none" to the flagsTable */ ImMalloc(newString, char *, 20 * sizeof(char)); strcpy(newString, "index16=none"); } TagTableAppend(flagsTable, TagEntryAlloc("channel map request",POINTER, &newString)); } /* Give an imInfo message */ imGiveInfoAboutChannel(flagsTable,"index16"); } return (1); } /* * FUNCTION * imGiveInfoAboutChannel * * DESCRIPTION * Spit out an ImInfo message describing what * is being mapped to this channel, according to * the flags table * * e.g. passing "red" will search the flags * table for something like red=blue, then * print "red = blue" */ static int /* returns status */ #ifdef __STDC__ imGiveInfoAboutChannel(TagTable* flagsTable, char* chanName) #else imGiveInfoAboutChannel(flagsTable,chanName) TagTable* flagsTable; char* chanName; #endif { TagEntry* tmpEntry; /* temporary tag table entry */ char* request; /* Request from entry */ int numChannelEntries; /* # of 'channel map request's */ int i; /* Loop index */ char tmpRequest[50]; /* Holds the request */ char* ptr; /* temp char* pointer */ char message[300]; /* Buffer for messages */ numChannelEntries = TagTableQNEntry(flagsTable, "channel map request"); for (i=0; i