/* * File: tiff_utils.c * * Purpose: C functions to interface to MEX and the TIFF libraries * MUST be compiled using the MEX compiler * * $Date: 2004/12/18 07:49:04 $ * $Id: tiff_utils.c,v 1.1.6.2 2004/12/18 07:49:04 batserve Exp $ * * */ #include "tiff_utils.h" void writeImageFromMxArray(TIFF *tif, int inClass, int imType, const mxArray *inputArray, int w, int h, int rowsPerStrip) { if(imType == RGB_IMG || imType == PACKED_RGB_IMG ) { /** * Write an RGB image */ if ( imType == PACKED_RGB_IMG ) { writeRGBFromUint32(tif, inputArray, w, h, rowsPerStrip); } else if ( inClass == mxUINT8_CLASS ) { writeRGBFromUint8(tif, inputArray, w, h, rowsPerStrip); } else if ( inClass == mxUINT16_CLASS ) { writeRGBFromUint16(tif, inputArray, w, h, rowsPerStrip); } } else { /** * Write an Indexed, Gray or Binary image */ if ( inClass == mxLOGICAL_CLASS ) { writeBitsFromLogical(tif, inputArray, w, h, rowsPerStrip); } else if ( inClass == mxUINT8_CLASS ) { writeBytesFromUint8(tif, inputArray, w, h, rowsPerStrip); } else if ( inClass == mxUINT16_CLASS ) { writeBytesFromUint16(tif, inputArray, w, h, rowsPerStrip); } } } void writeImageFromMxArrayNew(TIFF *tif, int photo, const mxArray *inputArray, int w, int h, int spp, int rowsPerStrip) { if (photo == PHOTOMETRIC_MINISWHITE) { writeBitsFromLogical(tif, inputArray, w, h, rowsPerStrip); } else if ((photo == PHOTOMETRIC_RGB) && (mxIsUint32(inputArray))) { writeRGBFromUint32(tif, inputArray, w, h, rowsPerStrip); } else { writeMultisample(tif, mxGetData(inputArray), w, h, spp, mxGetElementSize(inputArray), rowsPerStrip); } } void writeMultisample(TIFF *tif, void *data, int w, int h, int spp, int bytesPerSample, int rps) { uint8_T *buf; int i,j,p,s; int numStrips; int strip; int col, row; /* Allocate buffer for image write */ buf = (uint8_T *) mxCalloc(w*rps*spp, bytesPerSample); numStrips = (h + rps - 1) / rps; for (strip = 0, row = 0; strip < numStrips; strip++) { /* Fill the strip buffer */ for (p = 0; (p < rps) && (row < h); p++, row++) { for (col = 0; col < w; col++) { j = (col + (p*w)) * bytesPerSample * spp; /* index into buf */ i = ((col*h) + row) * bytesPerSample; /* index into data */ for (s = 0; s < spp; s++) { memcpy(buf + j + s*bytesPerSample, (uint8_T *) data + i + s*w*h*bytesPerSample, bytesPerSample); } } } /* Write the strip buffer */ TIFFWriteEncodedStrip(tif, strip, buf, w*p*spp*bytesPerSample); } mxFree((void *) buf); } void writeBytesFromUint8(TIFF *tif, const mxArray *inputArray, int w, int h, int rps) { uint8_T *buf; int i,j,p; int numStrips; int strip; int col, row; uint8_T *data; /* Allocate buffer for image write */ data = (uint8_T *) mxGetData(inputArray); buf = (uint8_T *) mxCalloc(w*rps, sizeof(uint8_T)); numStrips = (h + rps - 1) / rps; for (strip = 0, row = 0; strip < numStrips; strip++) { /* Fill the strip buffer */ for (p = 0; (p < rps) && (row < h); p++, row++) { for (col = 0; col < w; col++) { j = col + (p*w); /* index into buf */ i = (col*h) + row; /* index into data */ buf[j] = data[i]; } } /* Write the strip buffer */ TIFFWriteEncodedStrip(tif, strip, buf, w*p*sizeof(uint8)); } mxFree(buf); } void writeBytesFromUint16(TIFF *tif, const mxArray *inputArray, int w, int h, int rps) { uint16_T *buf; int i,j,p; int numStrips; int strip; int col, row; uint16_T *data; /* Allocate buffer for image write */ data = (uint16_T *) mxGetData(inputArray); buf = (uint16_T *) mxCalloc(w*rps, sizeof(uint16_T)); numStrips = (h + rps - 1) / rps; for (strip = 0, row = 0; strip < numStrips; strip++) { /* Fill the strip buffer */ for (p = 0; (p < rps) && (row < h); p++, row++) { for (col = 0; col < w; col++) { j = col + (p*w); /* index into buf */ i = (col*h) + row; /* index into data */ buf[j] = data[i]; } } /* write the strip buffer */ TIFFWriteEncodedStrip(tif, strip, buf, w*p*sizeof(uint16_T)); } mxFree(buf); } /* * WriteBitsFromLogical * Write from a binary image stored in mxLogicals. * * Write the image data with White-is-Zero (PHOTOMETRIX_MINISWHITE). This * is non-intuitive, but it is the norm for binary TIFFS. Many (supposed) * Tiff readers will not read the data correctly if it is written with * PHOTOMETRIC_MINISBLACK . */ void writeBitsFromLogical(TIFF *tif, const mxArray *inputArray, int w, int h, int rps) { uint8_T *buf; int i,j,k,p; int numStrips; int strip; uint8_T pixel, byte; int col, row; int stripBytes; mxLogical *data; /* Allocate buffer for image write */ data = mxGetLogicals(inputArray); stripBytes = ((w+7)/8) * rps; buf = (uint8_T *) mxCalloc(stripBytes, sizeof(uint8_T)); numStrips = (h + rps - 1) / rps; for (strip = 0, row = 0; strip < numStrips; strip++) { j = 0; /* index into buf */ k = 0; /* bit within a byte */ byte = 0; /* Fill the strip buffer */ for (p = 0; (p < rps) && (row < h); p++, row++) { for (col = 0; col < w; col++) { i = (col*h) + row; /* index into data */ pixel = (data[i]==0) ? 1 : 0; /* 0 is white */ byte |= (pixel << (7-k)); k++; if ((k == 8) || (col == (w-1))) { /* either we've filled a byte or we've */ /* reached the end of a row. Stuff the */ /* byte into the buffer. */ buf[j] = byte; j++; k = 0; byte = 0; } } } TIFFWriteEncodedStrip(tif, strip, buf, j); } mxFree((void *) buf); } void writeRGBFromUint8(TIFF *tif, const mxArray *inputArray, int w, int h, int rps) { uint8_T *buf; int i,j,p; int numStrips; int strip; int col, row; uint8_T *data; /* Allocate buffer for image write */ data = (uint8_T *) mxGetData(inputArray); buf = (uint8_T *) mxCalloc(w*rps*3, sizeof(uint8_T)); numStrips = (h + rps - 1) / rps; for (strip = 0, row = 0; strip < numStrips; strip++) { /* Fill the strip buffer */ for (p = 0; (p < rps) && (row < h); p++, row++) { for (col = 0; col < w; col++) { j = col + (p*w); /* index into buf */ i = (col*h) + row; /* index into data */ buf[j*3] = data[i]; /* Red Pixel */ buf[j*3+1] = data[i+(w*h)]; /* Green Pixel */ buf[j*3+2] = data[i+(2*w*h)]; /* Blue Pixel */ } } /* Write the strip buffer */ TIFFWriteEncodedStrip(tif, strip, buf, w*p*3*sizeof(uint8)); } mxFree((void *) buf); } void writeRGBFromUint16(TIFF *tif, const mxArray *inputArray, int w, int h, int rps) { uint16_T *buf; int i,j,p; int numStrips; int strip; int col, row; uint16_T *data; /* Allocate buffer for image write */ data = (uint16_T *) mxGetData(inputArray); buf = (uint16_T *) mxCalloc(w*rps*3, sizeof(uint16_T)); numStrips = (h + rps - 1) / rps; for (strip = 0, row = 0; strip < numStrips; strip++) { /* Fill the strip buffer */ for (p = 0; (p < rps) && (row < h); p++, row++) { for (col = 0; col < w; col++) { j = col + (p*w); /* index into buf */ i = (col*h) + row; /* index into data */ buf[j*3] = data[i]; /* Red Pixel */ buf[j*3+1] = data[i+(w*h)]; /* Green Pixel */ buf[j*3+2] = data[i+(2*w*h)]; /* Blue Pixel */ } } /* Write the strip buffer */ TIFFWriteEncodedStrip(tif, strip, buf, w*p*3*sizeof(uint16_T)); } mxFree((void *) buf); } void writeRGBFromUint32(TIFF *tif, const mxArray *inputArray, int w, int h, int rps) { uint8_T *buf, *data8; int j,p; int numStrips; int strip; int col, row; uint32_T *data; /* Index each byte of the 4 byte uint32 as packed [ Alpha(garbage) R G B ] */ data8 = (uint8_T *)data; /* Allocate buffer for image write */ data = (uint32_T *) mxGetData(inputArray); buf = (uint8_T *) mxCalloc(w*rps*3, sizeof(uint8_T)); numStrips = (h + rps - 1) / rps; for (strip = 0, row = 0; strip < numStrips; strip++) { /* Fill the strip buffer */ for (p = 0; (p < rps) && (row < h); p++, row++) { for (col = 0; col < w; col++) { j = col + (p*w); /* index into buf (why not just buf++?) */ /* Shifts are hardcoded TCPI offsets of IMSAVE driver */ buf[j*3] = (*data >> 16) & (uint32_T)255; /* Red Pixel */ buf[j*3+1] = (*data >> 8) & (uint32_T)255; /* Green Pixel */ buf[j*3+2] = *data & (uint32_T)255; /* Blue Pixel */ data++; } } /* Write the strip buffer */ TIFFWriteEncodedStrip(tif, strip, buf, w*p*3); } mxFree((void *) buf); } /* * Put the colormap into the TIFF structure for the write operation. */ void writeTIFFColormap(TIFF *tif, int imType, const mxArray *cmap, int dataClass) { uint16_T *red,*green,*blue; int i; const int *size; int rows, cols, ndims; mxClassID mapClass; uint8_T *u8_data; uint16_T *u16_data; red = (uint16_T *) mxCalloc(65536, sizeof(*red)); green = (uint16_T *) mxCalloc(65536, sizeof(*green)); blue = (uint16_T *) mxCalloc(65536, sizeof(*blue)); if (imType != INDEX_IMG) return; for(i=0; i<256; i++) /* Clear colormap */ { red[i] = 0; green[i] = 0; blue[i] = 0; } mapClass = mxGetClassID(cmap); ndims = mxGetNumberOfDimensions(cmap); if(ndims != 2) mexErrMsgTxt("Invalid colormap, must be 2-D."); size = mxGetDimensions(cmap); rows = size[0]; cols = size[1]; if(cols!=3) mexErrMsgTxt("Invalid colormap, must be n X 3."); if( dataClass==mxUINT8_CLASS && rows>256) mexErrMsgTxt("Invalid colormap for 8-bit image, must be n X 3 (n<=256)."); if( dataClass==mxUINT16_CLASS && rows>65536) mexErrMsgTxt("Invalid colormap for 16-bit image, must be n X 3 (n<=65536)."); if (mapClass==mxUINT8_CLASS) { /* Multiply data by 65535/255 = 257 */ u8_data = (uint8_T *) mxGetData(cmap); for(i=0; i256) mexErrMsgTxt("Invalid colormap for 8-bit image, must be n X 3 (n<=256)."); if( dataClass==mxUINT16_CLASS && rows>65536) mexErrMsgTxt("Invalid colormap for 16-bit image, must be n X 3 (n<=65536)."); if (mapClass==mxUINT8_CLASS) { /* Multiply data by 65535/255 = 257 */ u8_data = (uint8_T *) mxGetData(cmap); for(i=0; i