/* *--------------------------------------------------------------------------- * * PictureToTif -- * * Writes a TIFF format image to the provided data buffer. * * Results: * A standard TCL result. If an error occured, TCL_ERROR is * returned and an error message will be place in the interpreter * result. Otherwise, the data sink will contain the binary * output of the image. * * Side Effects: * Memory is allocated for the data sink. * *--------------------------------------------------------------------------- */ static int PictureToTif(Tcl_Interp *interp, Blt_Picture picture, Blt_DBuffer dbuffer, TifExportSwitches *switchesPtr) { TIFF *tifPtr; TIFFErrorHandler oldErrorHandler, oldWarningHandler; TifMessage message; int photometric, samplesPerPixel; int compress, result, nColors; Picture *srcPtr; compress = tifCompressionSchemes[switchesPtr->compress]; if (compress == COMPRESSION_NONE) { fprintf(stderr, "not compressing TIFF output\n"); } #ifdef notdef if (!TIFFIsCODECConfigured((unsigned short int)compress)) { compress = COMPRESSION_NONE; } #endif srcPtr = picture; Tcl_DStringInit(&message.errors); Tcl_DStringInit(&message.warnings); Tcl_DStringAppend(&message.errors, "error writing TIF output: ", -1); tifMessagePtr = &message; message.nErrors = message.nWarnings = 0; oldErrorHandler = TIFFSetErrorHandler(TifError); oldWarningHandler = TIFFSetWarningHandler(TifWarning); tifPtr = TIFFClientOpen("data buffer", "w", (thandle_t)dbuffer, TifRead, /* TIFFReadWriteProc */ TifWrite, /* TIFFReadWriteProc */ TifSeek, /* TIFFSeekProc */ TifClose, /* TIFFCloseProc */ TifSize, /* TIFFSizeProc */ TifMapFile, /* TIFFMapFileProc */ TifUnmapFile); /* TIFFUnmapFileProc */ if (tifPtr == NULL) { Tcl_AppendResult(interp, "can't register TIF procs: ", (char *)NULL); return TCL_ERROR; } nColors = Blt_QueryColors(srcPtr, (Blt_HashTable *)NULL); if (Blt_PictureIsColor(srcPtr)) { samplesPerPixel = (Blt_PictureIsOpaque(srcPtr)) ? 3 : 4; photometric = PHOTOMETRIC_RGB; } else { if (!Blt_PictureIsOpaque(srcPtr)) { Blt_Picture background; Blt_Pixel white; /* Blend picture with solid color background. */ background = Blt_CreatePicture(srcPtr->width, srcPtr->height); white.u32 = 0xFFFFFFFF; Blt_BlankPicture(background, &white); /* White background. */ Blt_BlendPictures(background, srcPtr, 0, 0, srcPtr->width, srcPtr->height, 0, 0); srcPtr = background; } samplesPerPixel = 1; photometric = PHOTOMETRIC_MINISBLACK; } TIFFSetField(tifPtr, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(tifPtr, TIFFTAG_COMPRESSION, (unsigned short int)compress); TIFFSetField(tifPtr, TIFFTAG_IMAGELENGTH, srcPtr->height); TIFFSetField(tifPtr, TIFFTAG_IMAGEWIDTH, srcPtr->width); TIFFSetField(tifPtr, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(tifPtr, TIFFTAG_PHOTOMETRIC, photometric); TIFFSetField(tifPtr, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tifPtr, TIFFTAG_RESOLUTIONUNIT, 2); TIFFSetField(tifPtr, TIFFTAG_ROWSPERSTRIP, srcPtr->height); TIFFSetField(tifPtr, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel); TIFFSetField(tifPtr, TIFFTAG_SOFTWARE, TIFFGetVersion()); TIFFSetField(tifPtr, TIFFTAG_XRESOLUTION, 300.0f); TIFFSetField(tifPtr, TIFFTAG_YRESOLUTION, 300.0f); #ifdef WORD_BIGENDIAN TIFFSetField(tifPtr, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); #else TIFFSetField(tifPtr, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); #endif result = -1; { Blt_Pixel *srcRowPtr; int destBitsSize; int y; unsigned char *destBits; unsigned char *dp; destBitsSize = srcPtr->width * srcPtr->height * sizeof(uint32); destBits = (unsigned char *)_TIFFmalloc(destBitsSize); if (destBits == NULL) { TIFFError("tiff", "can't allocate space for TIF buffer"); TIFFClose(tifPtr); return TCL_ERROR; } dp = destBits; srcRowPtr = srcPtr->bits; switch (samplesPerPixel) { case 4: for (y = 0; y < srcPtr->height; y++) { Blt_Pixel *sp; int x; sp = srcRowPtr; for (x = 0; x < srcPtr->width; x++) { dp[0] = sp->Red; dp[1] = sp->Green; dp[2] = sp->Blue; dp[3] = sp->Alpha; dp += 4, sp++; } srcRowPtr += srcPtr->pixelsPerRow; } break; case 3: /* RGB, 100% opaque image. */ for (y = 0; y < srcPtr->height; y++) { Blt_Pixel *sp; int x; sp = srcRowPtr; for (x = 0; x < srcPtr->width; x++) { dp[0] = sp->Red; dp[1] = sp->Green; dp[2] = sp->Blue; dp += 3, sp++; } srcRowPtr += srcPtr->pixelsPerRow; } break; case 1: for (y = 0; y < srcPtr->height; y++) { Blt_Pixel *sp; int x; sp = srcRowPtr; for (x = 0; x < srcPtr->width; x++) { *dp++ = sp->Red; sp++; } srcRowPtr += srcPtr->pixelsPerRow; } break; } result = TIFFWriteEncodedStrip(tifPtr, 0, destBits, destBitsSize); if (result < 0) { Tcl_AppendResult(interp, "error writing TIFF encoded strip", (char *)NULL); } _TIFFfree(destBits); } TIFFClose(tifPtr); if (result == -1) { Blt_DBuffer_Free(dbuffer); } TIFFSetErrorHandler(oldErrorHandler); TIFFSetWarningHandler(oldWarningHandler); if (message.nWarnings > 0) { Tcl_SetErrorCode(interp, "PICTURE", "TIF_WRITE_WARNINGS", Tcl_DStringValue(&message.warnings), (char *)NULL); } else { Tcl_SetErrorCode(interp, "NONE", (char *)NULL); } Tcl_DStringFree(&message.warnings); if (message.nErrors > 0) { Tcl_DStringResult(interp, &message.errors); } Tcl_DStringFree(&message.errors); if (srcPtr != picture) { Blt_FreePicture(srcPtr); } return (result == -1) ? TCL_ERROR : TCL_OK; }
int main(int argc, char *argv[]){ // Define an image -- this is 32 pixels by 9 pixels char buffer[25 * 144] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; TIFF *image; // Open the TIFF file if((image = TIFFOpen("output.tif", "w")) == NULL){ printf("Could not open output.tif for writing\n"); exit(42); } // We need to set some values for basic tags before we can add any data TIFFSetField(image, TIFFTAG_IMAGEWIDTH, 25 * 8); TIFFSetField(image, TIFFTAG_IMAGELENGTH, 144); TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 1); TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, 144); TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(image, TIFFTAG_XRESOLUTION, 150.0); TIFFSetField(image, TIFFTAG_YRESOLUTION, 150.0); TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); // Write the information to the file TIFFWriteEncodedStrip(image, 0, buffer, 25 * 144); // Close the file TIFFClose(image); }
__declspec(dllexport) int AppendPage(int*& FileRef, double* DataArray, uint32 ImageHeight, uint32 ImageWidth, char* ImageType) { uint16 SamplesPerPixel, BitsPerSample; uint8* DataArray_uint8 = (uint8*) DataArray; uint16* DataArray_uint16 = (uint16*)DataArray; int16* DataArray_int16 = (int16*)DataArray; uint32* DataArray_RGBA32 = (uint32*)DataArray; uint64* DataArray_RGBA64 = (uint64*)DataArray; float* DataArray_float32 = (float*)DataArray; tsize_t StripSize; uint32 rows; int nPixels = ImageWidth * ImageHeight; tstrip_t nStrips; if (!strcmp(ImageType, "uint8")) { BitsPerSample = 8; SamplesPerPixel = 1; DataArray_uint8 = new uint8[nPixels]; for (int i = 0; i < nPixels; i++) DataArray_uint8[i] = (uint8)DataArray[i]; } else if (!strcmp(ImageType, "uint16")) { BitsPerSample = 16; SamplesPerPixel = 1; DataArray_uint16 = new uint16[nPixels]; for (int i = 0; i < nPixels; i++) DataArray_uint16[i] = (uint16)DataArray[i]; } else if (!strcmp(ImageType, "int16")) { BitsPerSample = 16; SamplesPerPixel = 1; DataArray_int16 = new int16[nPixels]; for (int i = 0; i < nPixels; i++) DataArray_int16[i] = (int16)DataArray[i]; } else if (!strcmp(ImageType, "RGBA32")) { BitsPerSample = 8; SamplesPerPixel = 4; DataArray_RGBA32 = new uint32[nPixels]; for (int i = 0; i < nPixels; i++) DataArray_RGBA32[i] = (uint32)DataArray[i]; } else if (!strcmp(ImageType, "RGBA64")) { BitsPerSample = 16; SamplesPerPixel = 4; DataArray_RGBA64 = new uint64[nPixels]; for (int i = 0; i < nPixels; i++) DataArray_RGBA64[i] = (uint64)DataArray[i]; } else if (!strcmp(ImageType, "float32")) { BitsPerSample = 32; SamplesPerPixel = 1; DataArray_float32 = new float[nPixels]; for (int i = 0; i < nPixels; i++) DataArray_float32[i] = (float)DataArray[i]; } TIFF *tif = (TIFF*)FileRef; TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, ImageWidth); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, ImageHeight); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, SamplesPerPixel); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, BitsPerSample); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, 1); // black is zero TIFFSetField(tif, TIFFTAG_COMPRESSION, 5); // LZW compression rows = TIFFDefaultStripSize(tif, 0); TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rows); nStrips = TIFFNumberOfStrips(tif); StripSize = TIFFStripSize(tif); // the code works fine for even number of rows. A proper handling of remainders should be introduced. // currently, the remainders are just not used. int striprows = (int)rows * (int)nStrips; if (striprows > (int)ImageHeight) { nStrips = nStrips - 1; TIFFSetField(tif, TIFFTAG_IMAGELENGTH, ImageHeight-1); } for (tstrip_t StripCount = 0; StripCount < nStrips; StripCount++) { if (!strcmp(ImageType, "uint8")) TIFFWriteEncodedStrip(tif, StripCount, &DataArray_uint8[StripCount * StripSize], StripSize); else if (!strcmp(ImageType, "uint16")) TIFFWriteEncodedStrip(tif, StripCount, &DataArray_uint16[(StripCount * StripSize)/2], StripSize); else if (!strcmp(ImageType, "int16")) TIFFWriteEncodedStrip(tif, StripCount, &DataArray_int16[(StripCount * StripSize)/2], StripSize); else if (!strcmp(ImageType, "RGBA32")) TIFFWriteEncodedStrip(tif, StripCount, &DataArray_RGBA32[(StripCount * StripSize)/4], StripSize); else if (!strcmp(ImageType, "RGBA64")) TIFFWriteEncodedStrip(tif, StripCount, &DataArray_RGBA64[(StripCount * StripSize)/4], StripSize); else if (!strcmp(ImageType, "float32")) TIFFWriteEncodedStrip(tif, StripCount, &DataArray_float32[(StripCount * StripSize)/4], StripSize); } TIFFRewriteDirectory(tif); if (!strcmp(ImageType, "uint8")) { delete[] DataArray_uint8; } else if (!strcmp(ImageType, "uint16")) { delete[] DataArray_uint16; } else if (!strcmp(ImageType, "int16")) { delete[] DataArray_int16; } else if (!strcmp(ImageType, "RGBA32")) { delete[] DataArray_RGBA32; } else if (!strcmp(ImageType, "RGBA64")) { delete[] DataArray_RGBA64; } else if (!strcmp(ImageType, "float32")) { delete [] DataArray_float32; } return 0; }
bool AcquireImages(CamInfo* cams, int numCams) { int i; PvResult result; // Initialize Camera System PvSystem system; system.SetDetectionTimeout(2000); result = system.Find(); if(!result.IsOK()){ printf("PvSystem::Find Error: %s", result.GetCodeString().GetAscii()); return false; } PvDevice lDevice[numCams]; PvGenParameterArray *lDeviceParams[numCams]; PvStream lStream[numCams]; PvPipeline *lPipeline[numCams]; for(i=0; i < numCams; i++){ PvDeviceInfo* lDeviceInfo = NULL; PvDeviceInfo* tempInfo; // Get the number of GEV Interfaces that were found using GetInterfaceCount. PvUInt32 lInterfaceCount = system.GetInterfaceCount(); // For each interface, check MAC Address against passed address for( PvUInt32 x = 0; x < lInterfaceCount; x++ ) { // get pointer to each of interface PvInterface * lInterface = system.GetInterface( x ); // Get the number of GEV devices that were found using GetDeviceCount. PvUInt32 lDeviceCount = lInterface->GetDeviceCount(); for( PvUInt32 y = 0; y < lDeviceCount ; y++ ) { tempInfo = lInterface->GetDeviceInfo( y ); if(strlen(cams[i].MACAddress) == strlen(tempInfo->GetMACAddress().GetAscii()) && strncmp(cams[i].MACAddress,tempInfo->GetMACAddress().GetAscii(),strlen(cams[i].MACAddress)) == 0){ lDeviceInfo = tempInfo; break; } } } // If no device is selected, abort if( lDeviceInfo == NULL ) { printf( "No device selected.\n" ); return false; } // Connect to the GEV Device printf( "Connecting to %s\n", lDeviceInfo->GetMACAddress().GetAscii() ); if ( !lDevice[i].Connect( lDeviceInfo ).IsOK() ) { printf( "Unable to connect to %s\n", lDeviceInfo->GetMACAddress().GetAscii() ); return false; } printf( "Successfully connected to %s\n", lDeviceInfo->GetMACAddress().GetAscii() ); printf( "\n" ); // Get device parameters need to control streaming lDeviceParams[i] = lDevice[i].GetGenParameters(); // Negotiate streaming packet size lDevice[i].NegotiatePacketSize(); // Open stream - have the PvDevice do it for us printf( "Opening stream to device\n" ); lStream[i].Open( lDeviceInfo->GetIPAddress() ); // Create the PvPipeline object lPipeline[i] = new PvPipeline( &lStream[i] ); // Reading payload size from device PvInt64 lSize = 0; lDeviceParams[i]->GetIntegerValue( "PayloadSize", lSize ); // Set the Buffer size and the Buffer count lPipeline[i]->SetBufferSize( static_cast<PvUInt32>( lSize ) ); lPipeline[i]->SetBufferCount( 16 ); // Increase for high frame rate without missing block IDs // Have to set the Device IP destination to the Stream lDevice[i].SetStreamDestination( lStream[i].GetLocalIPAddress(), lStream[i].GetLocalPort() ); } PvGenParameterArray *lStreamParams[numCams]; for(i=0; i < numCams; i++){ // IMPORTANT: the pipeline needs to be "armed", or started before // we instruct the device to send us images printf( "Starting pipeline %d\n",i); lPipeline[i]->Start(); // Get stream parameters/stats lStreamParams[i] = lStream[i].GetParameters(); // TLParamsLocked is optional but when present, it MUST be set to 1 // before sending the AcquisitionStart command lDeviceParams[i]->SetIntegerValue( "TLParamsLocked", 1 ); printf( "Resetting timestamp counter...\n" ); lDeviceParams[i]->ExecuteCommand( "GevTimestampControlReset" ); // The pipeline is already "armed", we just have to tell the device // to start sending us images printf( "Sending StartAcquisition command to device\n" ); lDeviceParams[i]->ExecuteCommand( "AcquisitionStart" ); } char lDoodle[] = "|\\-|-/"; int lDoodleIndex = 0; PvInt64 lImageCountVal = 0; double lFrameRateVal = 0.0; double lBandwidthVal = 0.0; PvInt64 lPipelineBlocksDropped = 0; // Acquire images until the user instructs us to stop printf( "\n<press the enter key to stop streaming>\n" ); //PvBufferWriter writer; char filePath[MAXFILEPATH]; PvUInt32 lWidth = 4096, lHeight = 9250; while ( running ) { for(i=0; i < numCams; i++){ // Retrieve next buffer PvBuffer *lBuffer = NULL; PvResult lOperationResult; PvResult lResult = lPipeline[i]->RetrieveNextBuffer( &lBuffer, 1000, &lOperationResult ); if ( lResult.IsOK() ) { if ( lOperationResult.IsOK() ) { lStreamParams[i]->GetIntegerValue( "ImagesCount", lImageCountVal ); lStreamParams[i]->GetFloatValue( "AcquisitionRateAverage", lFrameRateVal ); lStreamParams[i]->GetFloatValue( "BandwidthAverage", lBandwidthVal ); lStreamParams[i]->GetIntegerValue("PipelineBlocksDropped", lPipelineBlocksDropped); filePath[0] = '\0'; sprintf(filePath,"%s/%s%04X.tif",cams[i].filename,cams[i].prefix,lBuffer->GetBlockID()); TIFF *out = TIFFOpen(filePath,"w"); TIFFSetField(out, TIFFTAG_IMAGEWIDTH, lWidth); TIFFSetField(out, TIFFTAG_IMAGELENGTH, lHeight); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE); TIFFWriteEncodedStrip(out,0,lBuffer->GetDataPointer(),lWidth*lHeight); TIFFClose(out); printf( "%d:%s%c Timestamp: %016llX BlockID: %04X %.01f FPS %d DROP %.01f Mb/s\r\n",i, cams[i].prefix, lDoodle[ lDoodleIndex ], lBuffer->GetTimestamp(), lBuffer->GetBlockID(), lFrameRateVal, lPipelineBlocksDropped, lBandwidthVal / 1000000.0 ); } else { printf("%d: ERROR Code: %s, Description: %s\r\n",i,lOperationResult.GetCodeString().GetAscii(),lOperationResult.GetDescription().GetAscii()); } // We have an image - do some processing (...) // VERY IMPORTANT: // release the buffer back to the pipeline lPipeline[i]->ReleaseBuffer( lBuffer ); usleep(200); } else { // Timeout printf( "%d:%s%c Timeout\r\n",i, cams[i].prefix,lDoodle[ lDoodleIndex ]); } } ++lDoodleIndex %= 6; } //_getch(); // Flush key buffer for next stop printf( "\n\n" ); for(i=0; i < numCams; i++){ // Tell the device to stop sending images printf( "Sending AcquisitionStop command to the device\n" ); lDeviceParams[i]->ExecuteCommand( "AcquisitionStop" ); // If present reset TLParamsLocked to 0. Must be done AFTER the // streaming has been stopped lDeviceParams[i]->SetIntegerValue( "TLParamsLocked", 0 ); // We stop the pipeline - letting the object lapse out of // scope would have had the destructor do the same, but we do it anyway printf( "Stop pipeline\n" ); lPipeline[i]->Stop(); delete lPipeline[i]; // Now close the stream. Also optionnal but nice to have printf( "Closing stream\n" ); lStream[i].Close(); // Finally disconnect the device. Optional, still nice to have printf( "Disconnecting device\n" ); lDevice[i].Disconnect(); } return true; }
int write_image (dt_imageio_module_data_t *d_tmp, const char *filename, const void *in_void, void *exif, int exif_len, int imgid) { dt_imageio_tiff_t *d=(dt_imageio_tiff_t*)d_tmp; uint8_t* profile = NULL; uint32_t profile_len = 0; TIFF* tif = NULL; void* rowdata = NULL; uint32_t rowsize = 0; uint32_t stripesize = 0; uint32_t stripe = 0; int rc = 1; // default to error if(imgid > 0) { cmsHPROFILE out_profile = dt_colorspaces_create_output_profile(imgid); cmsSaveProfileToMem(out_profile, 0, &profile_len); if (profile_len > 0) { profile = malloc(profile_len); if (!profile) { rc = 1; goto exit; } cmsSaveProfileToMem(out_profile, profile, &profile_len); } dt_colorspaces_cleanup_profile(out_profile); } // Create little endian tiff image tif = TIFFOpen(filename,"wl"); if (!tif) { rc = 1; goto exit; } // http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf (dated 2002) // "A proprietary ZIP/Flate compression code (0x80b2) has been used by some" // "software vendors. This code should be considered obsolete. We recommend" // "that TIFF implentations recognize and read the obsolete code but only" // "write the official compression code (0x0008)." // http://www.awaresystems.be/imaging/tiff/tifftags/compression.html // http://www.awaresystems.be/imaging/tiff/tifftags/predictor.html if (d->compress == 1) { TIFFSetField(tif, TIFFTAG_COMPRESSION, (uint16_t)COMPRESSION_ADOBE_DEFLATE); TIFFSetField(tif, TIFFTAG_PREDICTOR, (uint16_t)1); TIFFSetField(tif, TIFFTAG_ZIPQUALITY, (uint16_t)9); } else if (d->compress == 2) { TIFFSetField(tif, TIFFTAG_COMPRESSION, (uint16_t)COMPRESSION_ADOBE_DEFLATE); TIFFSetField(tif, TIFFTAG_PREDICTOR, (uint16_t)2); TIFFSetField(tif, TIFFTAG_ZIPQUALITY, (uint16_t)9); } else if (d->compress == 3) { TIFFSetField(tif, TIFFTAG_COMPRESSION, (uint16_t)COMPRESSION_ADOBE_DEFLATE); if (d->bpp == 32) TIFFSetField(tif, TIFFTAG_PREDICTOR, (uint16_t)3); else TIFFSetField(tif, TIFFTAG_PREDICTOR, (uint16_t)2); TIFFSetField(tif, TIFFTAG_ZIPQUALITY, (uint16_t)9); } else // (d->compress == 0) { TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); } TIFFSetField(tif, TIFFTAG_FILLORDER, (uint16_t)FILLORDER_MSB2LSB); if (profile != NULL) { TIFFSetField(tif, TIFFTAG_ICCPROFILE, (uint32_t)profile_len, profile); } TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (uint16_t)3); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, (uint16_t)d->bpp); TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, (uint16_t)(d->bpp == 32 ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT)); TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32_t)d->width); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32_t)d->height); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, (uint16_t)PHOTOMETRIC_RGB); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, (uint16_t)PLANARCONFIG_CONTIG); TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, (uint32_t)DT_TIFFIO_STRIPE); TIFFSetField(tif, TIFFTAG_ORIENTATION, (uint16_t)ORIENTATION_TOPLEFT); int resolution = dt_conf_get_int("metadata/resolution"); if (resolution > 0) { TIFFSetField(tif, TIFFTAG_XRESOLUTION, (float)resolution); TIFFSetField(tif, TIFFTAG_YRESOLUTION, (float)resolution); TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, (uint16_t)RESUNIT_INCH); } rowsize = (d->width*3) * d->bpp / 8; stripesize = rowsize * DT_TIFFIO_STRIPE; stripe = 0; rowdata = malloc(stripesize); if (!rowdata) { rc = 1; goto exit; } if (d->bpp == 32) { float* wdata = rowdata; for (int y = 0; y < d->height; y++) { float* in = (float*)in_void + (size_t)4*y*d->width; for (int x = 0; x < d->width; x++, in+=4, wdata+=3) { memcpy(wdata, in, 3*sizeof(float)); } if ((uintptr_t)wdata - (uintptr_t)rowdata == (uintptr_t)stripesize) { TIFFWriteEncodedStrip(tif, stripe++, rowdata, (size_t)(rowsize * DT_TIFFIO_STRIPE)); wdata = rowdata; } } if ((uintptr_t)wdata - (uintptr_t)rowdata != (uintptr_t)stripesize) { TIFFWriteEncodedStrip(tif, stripe++, rowdata, (size_t)((uintptr_t)wdata - (uintptr_t)rowdata)); } } else if (d->bpp == 16) { uint16_t* wdata = rowdata; for (int y = 0; y < d->height; y++) { uint16_t* in = (uint16_t*)in_void + (size_t)4*y*d->width; for(int x = 0; x < d->width; x++, in+=4, wdata+=3) { memcpy(wdata, in, 3*sizeof(uint16_t)); } if((uintptr_t)wdata - (uintptr_t)rowdata == (uintptr_t)stripesize) { TIFFWriteEncodedStrip(tif, stripe++, rowdata, (size_t)(rowsize * DT_TIFFIO_STRIPE)); wdata = rowdata; } } if ((uintptr_t)wdata - (uintptr_t)rowdata != (uintptr_t)stripesize) { TIFFWriteEncodedStrip(tif, stripe, rowdata, (size_t)((uintptr_t)wdata - (uintptr_t)rowdata)); } } else { uint8_t* wdata = rowdata; for (int y = 0; y < d->height; y++) { uint8_t* in = (uint8_t*)in_void + (size_t)4*y*d->width; for(int x = 0; x < d->width; x++, in+=4, wdata+=3) { memcpy(wdata, in, 3*sizeof(uint8_t)); } if((uintptr_t)wdata - (uintptr_t)rowdata == (uintptr_t)stripesize) { TIFFWriteEncodedStrip(tif, stripe++, rowdata, (size_t)(rowsize * DT_TIFFIO_STRIPE)); wdata = rowdata; } } if((uintptr_t)wdata - (uintptr_t)rowdata != (uintptr_t)stripesize) { TIFFWriteEncodedStrip(tif, stripe, rowdata, (size_t)((uintptr_t)wdata - (uintptr_t)rowdata)); } } // success rc = 0; exit: // close the file before adding exif data if (tif) { TIFFClose(tif); tif = NULL; } if(!rc && exif) { rc = dt_exif_write_blob(exif,exif_len,filename); // Until we get symbolic error status codes, if rc is 1, return 0 rc = (rc == 1) ? 0 : 1; } free(profile); profile = NULL; free(rowdata); rowdata = NULL; return rc; }
void rasterize(int interleaved, char* mode) { register unsigned long row; unsigned char *newras; unsigned char *ras; TIFF *tif; tstrip_t strip; tsize_t stripsize; if ((newras = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) { fprintf(stderr, "not enough memory for image\n"); return; } #define DRAWSEGMENT(offset, step) { \ for (row = offset; row < height; row += step) { \ _TIFFmemcpy(newras + row*width, ras, width);\ ras += width; \ } \ } ras = raster; if (interleaved) { DRAWSEGMENT(0, 8); DRAWSEGMENT(4, 8); DRAWSEGMENT(2, 4); DRAWSEGMENT(1, 2); } else DRAWSEGMENT(0, 1); #undef DRAWSEGMENT tif = TIFFOpen(imagename, mode); if (!tif) { TIFFError(imagename,"Can not open output image"); exit(-1); } TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32) width); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32) height); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip = TIFFDefaultStripSize(tif, rowsperstrip)); TIFFSetField(tif, TIFFTAG_COMPRESSION, compression); switch (compression) { case COMPRESSION_LZW: case COMPRESSION_DEFLATE: if (predictor != 0) TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor); break; } TIFFSetField(tif, TIFFTAG_COLORMAP, red, green, blue); TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); strip = 0; stripsize = TIFFStripSize(tif); for (row=0; row<height; row += rowsperstrip) { if (rowsperstrip > height-row) { rowsperstrip = height-row; stripsize = TIFFVStripSize(tif, rowsperstrip); } if (TIFFWriteEncodedStrip(tif, strip, newras+row*width, stripsize) < 0) break; strip++; } TIFFClose(tif); _TIFFfree(newras); }
static int cvt_whole_image( TIFF *in, TIFF *out ) { uint32* raster; /* retrieve RGBA image */ uint32 width, height; /* image width & height */ uint32 row; size_t pixel_count; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); pixel_count = width * height; /* XXX: Check the integer overflow. */ if (!width || !height || pixel_count / width != height) { TIFFError(TIFFFileName(in), "Malformed input file; can't allocate buffer for raster of %lux%lu size", (unsigned long)width, (unsigned long)height); return 0; } rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); raster = (uint32*)_TIFFCheckMalloc(in, pixel_count, sizeof(uint32), "raster buffer"); if (raster == 0) { TIFFError(TIFFFileName(in), "Requested buffer size is %lu elements %lu each", (unsigned long)pixel_count, (unsigned long)sizeof(uint32)); return (0); } /* Read the image in one chunk into an RGBA array */ if (!TIFFReadRGBAImageOriented(in, width, height, raster, ORIENTATION_TOPLEFT, 0)) { _TIFFfree(raster); return (0); } /* * XXX: raster array has 4-byte unsigned integer type, that is why * we should rearrange it here. */ #if HOST_BIGENDIAN TIFFSwabArrayOfLong(raster, width * height); #endif /* * Do we want to strip away alpha components? */ if (no_alpha) { size_t count = pixel_count; unsigned char *src, *dst; src = dst = (unsigned char *) raster; while (count > 0) { *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); src++; count--; } } /* * Write out the result in strips */ for (row = 0; row < height; row += rowsperstrip) { unsigned char * raster_strip; int rows_to_write; int bytes_per_pixel; if (no_alpha) { raster_strip = ((unsigned char *) raster) + 3 * row * width; bytes_per_pixel = 3; } else { raster_strip = (unsigned char *) (raster + row * width); bytes_per_pixel = 4; } if( row + rowsperstrip > height ) rows_to_write = height - row; else rows_to_write = rowsperstrip; if( TIFFWriteEncodedStrip( out, row / rowsperstrip, raster_strip, bytes_per_pixel * rows_to_write * width ) == -1 ) { _TIFFfree( raster ); return 0; } } _TIFFfree( raster ); return 1; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int TiffUtilities::writePalettedImage(TiffImage* data, char* imageDescription, char* outputFileName) { int err; unsigned char* raster; // size_t i; TIFF *out; char* dateTime; char software[1024]; tsize_t area; size_t totalPixels = 0; uint16 *r, *g, *b; int bitsPerSample = 8; uint16 nColors = 1<<bitsPerSample; totalPixels = data->width * data->height; if (NULL == data->imageData) { return -1; } out = TIFFOpen(outputFileName, "w"); if (out == NULL) { printf("Could not open output file '%s' for writing.\n", outputFileName); return -1; } err = 0; // set the basic values err = TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (int)data->width); err = TIFFSetField(out, TIFFTAG_IMAGELENGTH, (int)data->height); err = TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bitsPerSample); err = TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1); err = TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, (int)data->height); // 1 strip dateTime = EIMTOMO_TiffDateTime(); err = TIFFSetField(out, TIFFTAG_DATETIME, dateTime); // String based tags if (NULL != outputFileName) { err = TIFFSetField(out, TIFFTAG_DOCUMENTNAME, outputFileName); } if (NULL != imageDescription) { err = TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, imageDescription); } err = TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); err = TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE); // err = TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // single image plane r = (uint16 *) _TIFFmalloc(sizeof(uint16) * nColors); g = (uint16 *) _TIFFmalloc(sizeof(uint16) * nColors); b = (uint16 *) _TIFFmalloc(sizeof(uint16) * nColors); // Set the entire color table to Zeros memset(r,0, sizeof(uint16) * nColors); memset(g,0, sizeof(uint16) * nColors); memset(b,0, sizeof(uint16) * nColors); // Copy in the Gray_Table for the segmentation for (int32_t i = 0; i < 1; i++) { r[i] = UINT16_MAX * ( (float)data->grayTable[i]/(float)UINT8_MAX); g[i] = UINT16_MAX * ( (float)data->grayTable[i]/(float)UINT8_MAX); b[i] = UINT16_MAX * ( (float)data->grayTable[i]/(float)UINT8_MAX); } TIFFSetField(out, TIFFTAG_COLORMAP, r, g, b); #if USE_LZW_COMPRESSION err = TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_LZW); err = TIFFSetField(image, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL); #else err = TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE); #endif // Insert Resolution Units here if possible memset(software, 0, 1024); snprintf(software, 1024, "%s using libTIFF", TomoEngine_PACKAGE_COMPLETE); err = TIFFSetField(out, TIFFTAG_SOFTWARE, software); { err = TIFFSetField(out, TIFFTAG_XRESOLUTION, data->xResolution); err = TIFFSetField(out, TIFFTAG_YRESOLUTION, data->yResolution); err = TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, data->resolutionUnits); } // Write the information to the file area = (tsize_t)( data->width * data->height); err = TIFFWriteEncodedStrip(out, 0, raster, area); if (err != area) { err = -1; } else { err = 1; } (void)TIFFClose(out); // Release the color table _TIFFfree(r); _TIFFfree(g); _TIFFfree(b); return 1; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int writeOutputAsTiff(unsigned char* segData, int width, int height, const std::string &outputFile, const std::string &imageDescription) { std::stringstream ss; ss.setf(std::ios::fixed); ss.fill('0'); ss.width(4); std::string fileName = outputFile; TIFF *image; image = TIFFOpen(fileName.c_str(), "w"); if (image == NULL) { std::cout << "Could not open output tiff for writing" << std::endl; return -1; } int err = 0; int imageDims[2] = {width, height}; // set the basic values err = TIFFSetField(image, TIFFTAG_IMAGEWIDTH, (int) imageDims[0]); err = TIFFSetField(image, TIFFTAG_IMAGELENGTH, (int) imageDims[1]); err = TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 8); err = TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, 3); err = TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, (int) imageDims[1]); // 1 strip #if USE_LZW_COMPRESSION err = TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_LZW); err = TIFFSetField(image, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL); #else err = TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_NONE); #endif // std::string datetime = tifDateTime(); // err = TIFFSetField(image, TIFFTAG_DATETIME, datetime.c_str()); // String based tags if (fileName.length() > 0) { err = TIFFSetField(image, TIFFTAG_DOCUMENTNAME, fileName.c_str()); } if (imageDescription.length() > 0) { err = TIFFSetField(image, TIFFTAG_IMAGEDESCRIPTION, imageDescription.c_str()); } err = TIFFSetField(image, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT); err = TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); err = TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // Insert Resolution Units here if possible std::string software("LibTiff"); err = TIFFSetField(image, TIFFTAG_SOFTWARE, software.c_str()); // err = TIFFSetField(image, TIFFTAG_HOSTCOMPUTER, MXADATAMODEL_SYSTEM); // Write the information to the file tsize_t area = static_cast<tsize_t>(imageDims[0]* imageDims[1] * RGB_NUM_COMP); err = TIFFWriteEncodedStrip(image, 0, segData, area); (void) TIFFClose(image); return err; }
/* tiffWriter * ---------- * Write the gd image as a tiff file (called by gdImageTiffCtx) * Parameters are: * image: gd image structure; * out: the stream where to write * bitDepth: depth in bits of each pixel */ void tiffWriter(gdImagePtr image, gdIOCtx *out, int bitDepth) { int x, y; int i; int r, g, b, a; TIFF *tiff; int width, height; int color; char *scan; int samplesPerPixel = 3; int bitsPerSample; int transparentColorR = -1; int transparentColorG = -1; int transparentColorB = -1; uint16 extraSamples[1]; uint16 *colorMapRed = NULL; uint16 *colorMapGreen = NULL; uint16 *colorMapBlue = NULL; tiff_handle *th; th = new_tiff_handle(out); if (!th) { return; } extraSamples[0] = EXTRASAMPLE_ASSOCALPHA; /* read in the width/height of gd image */ width = gdImageSX(image); height = gdImageSY(image); /* reset clip region to whole image */ gdImageSetClip(image, 0, 0, width, height); /* handle old-style single-colour mapping to 100% transparency */ if(image->transparent != -1) { /* set our 100% transparent colour value */ transparentColorR = gdImageRed(image, image->transparent); transparentColorG = gdImageGreen(image, image->transparent); transparentColorB = gdImageBlue(image, image->transparent); } /* Open tiff file writing routines, but use special read/write/seek * functions so that tiff lib writes correct bits of tiff content to * correct areas of file opened and modifieable by the gdIOCtx functions */ tiff = TIFFClientOpen("", "w", th, tiff_readproc, tiff_writeproc, tiff_seekproc, tiff_closeproc, tiff_sizeproc, tiff_mapproc, tiff_unmapproc); TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height); TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, (bitDepth == 24) ? PHOTOMETRIC_RGB : PHOTOMETRIC_PALETTE); bitsPerSample = (bitDepth == 24 || bitDepth == 8) ? 8 : 1; TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, bitsPerSample); /* build the color map for 8 bit images */ if(bitDepth != 24) { colorMapRed = (uint16 *) gdMalloc(3 * (1 << bitsPerSample)); if (!colorMapRed) { gdFree(th); return; } colorMapGreen = (uint16 *) gdMalloc(3 * (1 << bitsPerSample)); if (!colorMapGreen) { gdFree(colorMapRed); gdFree(th); return; } colorMapBlue = (uint16 *) gdMalloc(3 * (1 << bitsPerSample)); if (!colorMapBlue) { gdFree(colorMapRed); gdFree(colorMapGreen); gdFree(th); return; } for(i = 0; i < image->colorsTotal; i++) { colorMapRed[i] = gdImageRed(image,i) + (gdImageRed(image,i) * 256); colorMapGreen[i] = gdImageGreen(image,i)+(gdImageGreen(image,i)*256); colorMapBlue[i] = gdImageBlue(image,i) + (gdImageBlue(image,i)*256); } TIFFSetField(tiff, TIFFTAG_COLORMAP, colorMapRed, colorMapGreen, colorMapBlue); samplesPerPixel = 1; } /* here, we check if the 'save alpha' flag is set on the source gd image */ if ((bitDepth == 24) && (image->saveAlphaFlag || image->transparent != -1)) { /* so, we need to store the alpha values too! * Also, tell TIFF what the extra sample means (associated alpha) */ samplesPerPixel = 4; TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel); TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, extraSamples); } else { TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel); } TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, 1); if(overflow2(width, samplesPerPixel)) { if (colorMapRed) gdFree(colorMapRed); if (colorMapGreen) gdFree(colorMapGreen); if (colorMapBlue) gdFree(colorMapBlue); gdFree(th); return; } if(!(scan = (char *)gdMalloc(width * samplesPerPixel))) { if (colorMapRed) gdFree(colorMapRed); if (colorMapGreen) gdFree(colorMapGreen); if (colorMapBlue) gdFree(colorMapBlue); gdFree(th); return; } /* loop through y-coords, and x-coords */ for(y = 0; y < height; y++) { for(x = 0; x < width; x++) { /* generate scan line for writing to tiff */ color = gdImageGetPixel(image, x, y); a = (127 - gdImageAlpha(image, color)) * 2; a = (a == 0xfe) ? 0xff : a & 0xff; b = gdImageBlue(image, color); g = gdImageGreen(image, color); r = gdImageRed(image, color); /* if this pixel has the same RGB as the transparent colour, * then set alpha fully transparent */ if (transparentColorR == r && transparentColorG == g && transparentColorB == b) { a = 0x00; } if(bitDepth != 24) { /* write out 1 or 8 bit value in 1 byte * (currently treats 1bit as 8bit) */ scan[(x * samplesPerPixel) + 0] = color; } else { /* write out 24 bit value in 3 (or 4 if transparent) bytes */ if(image->saveAlphaFlag || image->transparent != -1) { scan[(x * samplesPerPixel) + 3] = a; } scan[(x * samplesPerPixel) + 2] = b; scan[(x * samplesPerPixel) + 1] = g; scan[(x * samplesPerPixel) + 0] = r; } } /* Write the scan line to the tiff */ if(TIFFWriteEncodedStrip(tiff, y, scan, width * samplesPerPixel) == -1) { if (colorMapRed) gdFree(colorMapRed); if (colorMapGreen) gdFree(colorMapGreen); if (colorMapBlue) gdFree(colorMapBlue); gdFree(th); /* error handler here */ gd_error("Could not create TIFF\n"); return; } } /* now cloase and free up resources */ TIFFClose(tiff); gdFree(scan); gdFree(th); if(bitDepth != 24) { gdFree(colorMapRed); gdFree(colorMapGreen); gdFree(colorMapBlue); } }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- int TiffUtilities::writeGrayScaleImage(const char* filename, int rows, int columns, const char* imageDescription, unsigned char* image) { int err; TIFF *out; char software[1024]; tsize_t area; if (NULL == image) { return -1; } out = TIFFOpen(filename, "w"); if (out == NULL) { printf("Could not open output file '%s' for writing.\n", filename); return -1; } err = 0; // set the basic values err = TIFFSetField(out, TIFFTAG_IMAGEWIDTH, (int)columns); err = TIFFSetField(out, TIFFTAG_IMAGELENGTH, (int)rows); err = TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); err = TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1); err = TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, (int)rows); // 1 strip std::string dateTime = tifDateTime(); err = TIFFSetField(out, TIFFTAG_DATETIME, dateTime.c_str()); // String based tags if (NULL != filename) { err = TIFFSetField(out, TIFFTAG_DOCUMENTNAME, filename); } if (NULL != imageDescription) { err = TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, imageDescription); } err = TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT); err = TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); #if 0 err = TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_LZW); err = TIFFSetField(image, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL); #else err = TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE); #endif // Insert Resolution Units here if possible ::memset(software, 0, 1024); snprintf(software, 1024, "%s using libTif", MXA::Version::Complete().c_str() ); err = TIFFSetField(out, TIFFTAG_SOFTWARE, software); // err = TIFFSetField(out, TIFFTAG_HOSTCOMPUTER, EMMPM_SYSTEM); // Write the information to the file area = (tsize_t)( columns * rows); err = TIFFWriteEncodedStrip(out, 0, image, area); if (err != area) { err = -1; } else { err = 1; } (void)TIFFClose(out); return err; }
void ImageCodecTiff::save(const Image& image, const std::string& filename) { // create a new TIFF file Tiff::File file(TIFFOpen(filename.c_str(), "w")); if (!file) AURORA_THROW(EInOut, "File could not be created: " + filename); const int64_t cols = image.cols(); const int64_t rows = image.rows(); uint16_t samplesPerPixel; // some standard tags that must be set Tiff::setField(file, TIFFTAG_IMAGEWIDTH , cols); Tiff::setField(file, TIFFTAG_IMAGELENGTH , rows); Tiff::setField(file, TIFFTAG_BITSPERSAMPLE, 8); Tiff::setField(file, TIFFTAG_PLANARCONFIG , PLANARCONFIG_CONTIG); Tiff::setField(file, TIFFTAG_ROWSPERSTRIP , rows); if (Image::PixelFormat::Gray8 == image.pixelFormat()) { samplesPerPixel = 1; Tiff::setField(file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); } else if (Image::PixelFormat::RGBA8 == image.pixelFormat()) { samplesPerPixel = 3; Tiff::setField(file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); } else if (Image::PixelFormat::Float == image.pixelFormat()) { AURORA_THROW(ENotSupported, "Float images cannot be saved."); } else { AURORA_UNREACHABLE; } Tiff::setField(file, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel); // convert the internal format into the TIFF format std::vector<uint8_t> tempBuffer(cols * rows * samplesPerPixel); if (Image::PixelFormat::Gray8 == image.pixelFormat()) { #pragma omp parallel for for (int64_t y = 0; y < rows; ++y) for (int64_t x = 0; x < cols; ++x) tempBuffer[y * cols + x] = image.pixel<Gray8>(x, y); } else if (Image::PixelFormat::RGBA8 == image.pixelFormat()) { #pragma omp parallel for for (int64_t y = 0; y < rows; ++y) { for (int64_t x = 0; x < cols; ++x) { tempBuffer[(y * cols + x) * 3 + 0] = image.pixel<Rgba8>(x, y).r; tempBuffer[(y * cols + x) * 3 + 1] = image.pixel<Rgba8>(x, y).g; tempBuffer[(y * cols + x) * 3 + 2] = image.pixel<Rgba8>(x, y).b; } } } else { AURORA_UNREACHABLE; } // write all the image data at once const int64_t numBytes = cols * rows * samplesPerPixel; if (-1 == TIFFWriteEncodedStrip(file, 0, tempBuffer.data(), numBytes)) AURORA_THROW(EInOut, "Writing image data to TIFF file failed."); }
void writeTIFF(const char *pszFile, HDC hdc) { precondition_throw(pszFile != NULL, "Path to TIFF file cannot be null."); precondition_throw(hdc != NULL, "Source device context cannot be null."); HBITMAP hbm = (HBITMAP) ::GetCurrentObject(hdc, OBJ_BITMAP); DIBSECTION ds = {255}; memset(&ds,255,sizeof(ds)); ::GetObject(hbm, sizeof(DIBSECTION), &ds); LONG buffWidth = ds.dsBmih.biWidth; LONG buffHeight = (ds.dsBmih.biHeight < 0) ? ds.dsBmih.biHeight * -1 : ds.dsBmih.biHeight; WORD planes = ds.dsBmih.biPlanes; WORD bitsPerPixel = ds.dsBmih.biBitCount; if (planes != 1) throw std::runtime_error("Unsupported image format."); long padding = 0; while ((buffWidth * 3 + padding) % sizeof(DWORD) != 0) ++padding; long pitchBytes = buffWidth * 3 + padding; long neededBytes = pitchBytes * buffHeight; ScopedArray<BYTE> spBuffer(new BYTE[neededBytes]); memset(spBuffer.get(), 0, neededBytes); BITMAPINFO bmi = {0}; bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 24; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biWidth = buffWidth; bmi.bmiHeader.biHeight = buffHeight * -1; ::GetDIBits(hdc, hbm, 0, buffHeight, spBuffer.get(), &bmi, DIB_RGB_COLORS); TIFF *pTIFF = TIFFOpen(pszFile, "w"); if (!pTIFF) throw std::runtime_error("Couldn't create specified TIFF file."); ScopeGuard guardTIFF = MakeGuard(TIFFClose, pTIFF); TIFFSetField(pTIFF, TIFFTAG_IMAGEWIDTH, buffWidth); TIFFSetField(pTIFF, TIFFTAG_IMAGELENGTH, buffHeight); TIFFSetField(pTIFF, TIFFTAG_SAMPLESPERPIXEL, 3); TIFFSetField(pTIFF, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(pTIFF, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(pTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(pTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); long packedSize = buffWidth * buffHeight * 3; ScopedArray<BYTE> spPackedBuffer(new BYTE[packedSize]); BYTE *pDest = spPackedBuffer.get(); BYTE *pSrc = spBuffer.get(); for (long y = 0; y < buffHeight; ++y) { for (long x = 0; x < buffWidth; ++x) { // Swapping bytes so the byte order is as we expect pDest[0] = pSrc[2]; pDest[1] = pSrc[1]; pDest[2] = pSrc[0]; pDest += 3; pSrc += 3; } pSrc += padding; } if (TIFFWriteEncodedStrip(pTIFF, 0, spPackedBuffer.get(), buffWidth * buffHeight * 3) == 0) throw std::runtime_error("Couldn't write image."); }
int writeColorTiff(const std::string filename, DataArray<uint8_t>::Pointer image, int width, int height, const std::string imageDescription, int orientation) { int err; TIFF *out; std::string dateTime; char software[1024]; tsize_t area; if (NULL == image) { return -1; } out = TIFFOpen(filename.c_str(), "w"); if (out == NULL) { printf("Could not open output file '%s' for writing.\n", filename.c_str()); return -1; } err = 0; // set the basic values err = TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width); err = TIFFSetField(out, TIFFTAG_IMAGELENGTH, height); err = TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); err = TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 3); err = TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, height); // 1 strip err = TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // single image plane dateTime = tifDateTime(); err = TIFFSetField(out, TIFFTAG_DATETIME, dateTime.c_str()); // String based tags if (filename.empty() == false) { err = TIFFSetField(out, TIFFTAG_DOCUMENTNAME, filename.c_str()); } if (imageDescription.empty() == false) { err = TIFFSetField(out, TIFFTAG_IMAGEDESCRIPTION, imageDescription.c_str()); } err = TIFFSetField(out, TIFFTAG_ORIENTATION, orientation); err = TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); #if USE_LZW_COMPRESSION err = TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_LZW); err = TIFFSetField(image, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL); #else err = TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE); #endif // Insert Resolution Units here if possible memset(software, 0, 1024); snprintf(software, 1024, "%s using libTif", EbsdLib::Version::Complete().c_str()); err = TIFFSetField(out, TIFFTAG_SOFTWARE, software); err = TIFFSetField(out, TIFFTAG_HOSTCOMPUTER, MXADATAMODEL_SYSTEM); // Write the information to the file area = (tsize_t)( width * height * 3); err = TIFFWriteEncodedStrip(out, 0, image->GetVoidPointer(0), area); if (err != area) { err = -1; } else { err = 1; } (void)TIFFClose(out); return err; }
int imb_savetiff(ImBuf *ibuf, const char *name, int flags) { TIFF *image = NULL; uint16 samplesperpixel, bitspersample; size_t npixels; unsigned char *pixels = NULL; unsigned char *from = NULL, *to = NULL; unsigned short *pixels16 = NULL, *to16 = NULL; float *fromf = NULL; float xres, yres; int x, y, from_i, to_i, i; /* check for a valid number of bytes per pixel. Like the PNG writer, * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding * to gray, RGB, RGBA respectively. */ samplesperpixel = (uint16)((ibuf->planes + 7) >> 3); if ((samplesperpixel > 4) || (samplesperpixel == 2)) { fprintf(stderr, "imb_savetiff: unsupported number of bytes per " "pixel: %d\n", samplesperpixel); return (0); } if ((ibuf->ftype & TIF_16BIT) && ibuf->rect_float) bitspersample = 16; else bitspersample = 8; /* open TIFF file for writing */ if (flags & IB_mem) { /* bork at the creation of a TIFF in memory */ fprintf(stderr, "imb_savetiff: creation of in-memory TIFF files is " "not yet supported.\n"); return (0); } else { /* create image as a file */ #ifdef WIN32 wchar_t *wname = alloc_utf16_from_8(name, 0); image = TIFFOpenW(wname, "w"); free(wname); #else image = TIFFOpen(name, "w"); #endif } if (image == NULL) { fprintf(stderr, "imb_savetiff: could not open TIFF for writing.\n"); return (0); } /* allocate array for pixel data */ npixels = ibuf->x * ibuf->y; if (bitspersample == 16) pixels16 = (unsigned short *)_TIFFmalloc(npixels * samplesperpixel * sizeof(unsigned short)); else pixels = (unsigned char *)_TIFFmalloc(npixels * samplesperpixel * sizeof(unsigned char)); if (pixels == NULL && pixels16 == NULL) { fprintf(stderr, "imb_savetiff: could not allocate pixels array.\n"); TIFFClose(image); return (0); } /* setup pointers */ if (bitspersample == 16) { fromf = ibuf->rect_float; to16 = pixels16; } else { from = (unsigned char *)ibuf->rect; to = pixels; } /* setup samples per pixel */ TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample); TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); if (samplesperpixel == 4) { unsigned short extraSampleTypes[1]; if (bitspersample == 16) extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA; else extraSampleTypes[0] = EXTRASAMPLE_UNASSALPHA; /* RGBA images */ TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes); TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); } else if (samplesperpixel == 3) { /* RGB images */ TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); } else if (samplesperpixel == 1) { /* grayscale images, 1 channel */ TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); } /* copy pixel data. While copying, we flip the image vertically. */ for (x = 0; x < ibuf->x; x++) { for (y = 0; y < ibuf->y; y++) { from_i = 4 * (y * ibuf->x + x); to_i = samplesperpixel * ((ibuf->y - y - 1) * ibuf->x + x); if (pixels16) { /* convert from float source */ float rgb[4]; if (ibuf->float_colorspace) { /* float buffer was managed already, no need in color space conversion */ copy_v3_v3(rgb, &fromf[from_i]); } else { /* standard linear-to-srgb conversion if float buffer wasn't managed */ linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]); } rgb[3] = fromf[from_i + 3]; for (i = 0; i < samplesperpixel; i++, to_i++) to16[to_i] = FTOUSHORT(rgb[i]); } else { for (i = 0; i < samplesperpixel; i++, to_i++, from_i++) to[to_i] = from[from_i]; } } } /* write the actual TIFF file */ TIFFSetField(image, TIFFTAG_IMAGEWIDTH, ibuf->x); TIFFSetField(image, TIFFTAG_IMAGELENGTH, ibuf->y); TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, ibuf->y); TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) { xres = (float)(ibuf->ppm[0] * 0.0254); yres = (float)(ibuf->ppm[1] * 0.0254); } else { xres = yres = IMB_DPI_DEFAULT; } TIFFSetField(image, TIFFTAG_XRESOLUTION, xres); TIFFSetField(image, TIFFTAG_YRESOLUTION, yres); TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); if (TIFFWriteEncodedStrip(image, 0, (bitspersample == 16) ? (unsigned char *)pixels16 : pixels, ibuf->x * ibuf->y * samplesperpixel * bitspersample / 8) == -1) { fprintf(stderr, "imb_savetiff: Could not write encoded TIFF.\n"); TIFFClose(image); if (pixels) _TIFFfree(pixels); if (pixels16) _TIFFfree(pixels16); return (1); } /* close the TIFF file */ TIFFClose(image); if (pixels) _TIFFfree(pixels); if (pixels16) _TIFFfree(pixels16); return (1); }
char *initTiff3DFile ( char *filename, unsigned int sz0, unsigned int sz1, unsigned int sz2, unsigned int sz3, int datatype ) { //int initTiff3DFile ( char *filename, uint32 XSIZE, uint32 YSIZE, uint16 spp, uint16 Npages, int datatype){ // 2015-01-30. Alessandro. @ADDED performance (time) measurement in all most time-consuming methods. #ifdef _VAA3D_TERAFLY_PLUGIN_MODE TERAFLY_TIME_START(TiffInitData) #endif uint32 XSIZE = sz0; uint32 YSIZE = sz1; uint16 Npages = sz2; uint16 spp = sz3; uint16 bpp=8 * datatype; unsigned char *fakeData=new unsigned char[XSIZE * YSIZE * spp * (bpp/8)]; int check; if ( sz3 == 1 ) spp = sz3; else if ( sz3 < 4 ) spp = 3; else return ((char *) "More than 3 channels in Tiff files."); char *completeFilename = (char *) 0; int fname_len = (int) strlen(filename); char *suffix = strstr(filename,".tif"); while ( suffix && (fname_len - (suffix-filename) > 5) ) suffix = strstr(suffix+4,".tif"); //if ( (suffix != 0) && (fname_len - (suffix-filename) <= 5) ) { // a substring ".tif is already at the end of the filename if ( suffix ) { // a substring ".tif is already at the very end of the filename completeFilename = new char[fname_len+1]; strcpy(completeFilename,filename); } else { completeFilename = new char[fname_len+4+1]; strcpy(completeFilename,filename); strcat(completeFilename,"."); strcat(completeFilename,TIFF3D_SUFFIX); } // 2015-01-30. Alessandro. @ADDED performance (time) measurement in all most time-consuming methods. #ifdef _VAA3D_TERAFLY_PLUGIN_MODE TERAFLY_TIME_STOP(TiffInitData, tf::CPU, tf::strprintf("generated fake data for 3D tiff \"%s\"", completeFilename)) TERAFLY_TIME_RESTART(TiffInitData) #endif //disable warning and error handlers to avoid messages on unrecognized tags TIFFSetWarningHandler(0); TIFFSetErrorHandler(0); TIFF *output; output = TIFFOpen(completeFilename,"w"); if (!output) { return ((char *) "Cannot open the file."); } check = TIFFSetField(output, TIFFTAG_IMAGEWIDTH, XSIZE); if (!check) { return ((char *) "Cannot set the image width."); } check = TIFFSetField(output, TIFFTAG_IMAGELENGTH, YSIZE); if (!check) { return ((char *) "Cannot set the image height."); } check = TIFFSetField(output, TIFFTAG_BITSPERSAMPLE, bpp); if (!check) { return ((char *) "Cannot set the image bit per sample."); } check = TIFFSetField(output, TIFFTAG_SAMPLESPERPIXEL, spp); if (!check) { return ((char *) "Cannot set the image sample per pixel."); } check = TIFFSetField(output, TIFFTAG_ROWSPERSTRIP, (rowsPerStrip == -1) ? YSIZE : rowsPerStrip); if (!check) { return ((char *) "Cannot set the image rows per strip."); } check = TIFFSetField(output, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); if (!check) { return ((char *) "Cannot set the image orientation."); } check = TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_LZW); if (!check) { return ((char *) "Cannot set the compression tag."); } check = TIFFSetField(output, TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); if (!check) { return ((char *) "Cannot set the planarconfig tag."); } if ( spp == 1 ) check = TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); else // spp == 3 check = TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); if (!check) { return ((char *) "Cannot set the photometric tag."); } /* We are writing single page of the multipage file */ check = TIFFSetField(output, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); if (!check) { return ((char *) "Cannot set the subfiletype tag."); } check = TIFFSetField(output, TIFFTAG_PAGENUMBER, 0, Npages); if (!check) { return ((char *) "Cannot set the page number."); } check = (int)TIFFWriteEncodedStrip(output, 0, fakeData, XSIZE * YSIZE); if (!check) { return ((char *) "Cannot write encoded strip to file."); } if ( rowsPerStrip == -1 ) TIFFWriteEncodedStrip(output, 0, fakeData, XSIZE * YSIZE * spp * (bpp/8)); else { int check,StripsPerImage,LastStripSize; uint32 rps = rowsPerStrip; unsigned char *buf = fakeData; StripsPerImage = (YSIZE + rps - 1) / rps; LastStripSize = YSIZE % rps; if (LastStripSize==0) LastStripSize=rps; for (int i=0; i < StripsPerImage-1; i++){ //if (comp==1) { // TIFFReadRawStrip(input, i, buf, spp * rps * img_width * (bpp/8)); // buf = buf + spp * rps * img_width * (bpp/8); //} //else{ TIFFWriteEncodedStrip(output, i, buf, spp * rps * XSIZE * (bpp/8)); buf = buf + spp * rps * XSIZE * (bpp/8); //} } //if (comp==1) { // TIFFReadRawStrip(input, StripsPerImage-1, buf, spp * LastStripSize * img_width * (bpp/8)); //} //else{ TIFFWriteEncodedStrip(output, StripsPerImage-1, buf, spp * LastStripSize * XSIZE * (bpp/8)); //} buf = buf + spp * LastStripSize * XSIZE * (bpp/8); } delete[] fakeData; delete []completeFilename; check = TIFFWriteDirectory(output); if (!check) { return ((char *) "Cannot write a new directory."); } TIFFClose(output); // 2015-01-30. Alessandro. @ADDED performance (time) measurement in all most time-consuming methods. #ifdef _VAA3D_TERAFLY_PLUGIN_MODE TERAFLY_TIME_STOP(TiffInitData, tf::IO, tf::strprintf("written initialized 3D tiff \"%s\"", completeFilename)) #endif return (char *) 0; }
static int write_tiff_image(t4_rx_state_t *s) { t4_rx_tiff_state_t *t; #if defined(SPANDSP_SUPPORT_TIFF_FX) && TIFFLIB_VERSION >= 20120922 && defined(HAVE_TIF_DIR_H) toff_t diroff; #endif t = &s->tiff; if (s->decoder.no_decoder.buf_ptr <= 0 && (t->image_buffer == NULL || t->image_size <= 0)) return -1; /* Set up the TIFF directory info... */ set_tiff_directory_info(s); /* ...Put the directory in the file before the image data, to get them in the order specified for TIFF/F files... */ //if (!TIFFCheckpointDirectory(t->tiff_file)) // span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to checkpoint directory for page %d.\n", t->file, s->current_page); /* ...and write out the image... */ if (s->current_decoder == 0) { if (TIFFWriteRawStrip(s->tiff.tiff_file, 0, s->decoder.no_decoder.buf, s->decoder.no_decoder.buf_ptr) < 0) span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", s->tiff.file); } else { switch (t->compression) { case T4_COMPRESSION_T85: case T4_COMPRESSION_T85_L0: /* We need to perform this compression here, as libtiff does not understand it. */ if (write_tiff_t85_image(s) < 0) return -1; break; #if defined(SPANDSP_SUPPORT_T88) case T4_COMPRESSION_T88: /* We need to perform this compression here, as libtiff does not understand it. */ if (write_tiff_t88_image(s) < 0) return -1; break; #endif case T4_COMPRESSION_T43: /* We need to perform this compression here, as libtiff does not understand it. */ if (write_tiff_t43_image(s) < 0) return -1; break; #if defined(SPANDSP_SUPPORT_T45) case T4_COMPRESSION_T45: /* We need to perform this compression here, as libtiff does not understand it. */ if (write_tiff_t45_image(s) < 0) return -1; break; #endif default: /* Let libtiff do the compression */ if (TIFFWriteEncodedStrip(t->tiff_file, 0, t->image_buffer, t->image_size) < 0) span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", t->file); break; } } /* ...then finalise the directory entry, and libtiff is happy. */ if (!TIFFWriteDirectory(t->tiff_file)) span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to write directory for page %d.\n", t->file, s->current_page); #if defined(SPANDSP_SUPPORT_TIFF_FX) /* According to the TIFF/FX spec, a global parameters IFD should only be inserted into the first page in the file */ if (s->current_page == 0) { #if TIFFLIB_VERSION >= 20120922 && defined(HAVE_TIF_DIR_H) if (!TIFFCreateCustomDirectory(t->tiff_file, &tiff_fx_field_array)) { TIFFSetField(t->tiff_file, TIFFTAG_FAXPROFILE, PROFILETYPE_G3_FAX); TIFFSetField(t->tiff_file, TIFFTAG_PROFILETYPE, FAXPROFILE_F); TIFFSetField(t->tiff_file, TIFFTAG_CODINGMETHODS, CODINGMETHODS_T4_1D | CODINGMETHODS_T4_2D | CODINGMETHODS_T6); TIFFSetField(t->tiff_file, TIFFTAG_VERSIONYEAR, "1998"); TIFFSetField(t->tiff_file, TIFFTAG_MODENUMBER, 3); diroff = 0; if (!TIFFWriteCustomDirectory(t->tiff_file, &diroff)) span_log(&s->logging, SPAN_LOG_WARNING, "Failed to write custom directory.\n"); /* Now go back and patch in the pointer to the new IFD */ if (!TIFFSetDirectory(t->tiff_file, s->current_page)) span_log(&s->logging, SPAN_LOG_WARNING, "Failed to set directory.\n"); if (!TIFFSetField(t->tiff_file, TIFFTAG_GLOBALPARAMETERSIFD, diroff)) span_log(&s->logging, SPAN_LOG_WARNING, "Failed to set field.\n"); if (!TIFFWriteDirectory(t->tiff_file)) span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to write directory for page %d.\n", t->file, s->current_page); } #endif } #endif return 0; }
char *appendSlice2Tiff3DFile ( char *filename, int slice, unsigned char *img, unsigned int img_width, unsigned int img_height ) { // 2015-01-30. Alessandro. @ADDED performance (time) measurement in all most time-consuming methods. #ifdef _VAA3D_TERAFLY_PLUGIN_MODE TERAFLY_TIME_START(TiffAppendData) #endif TIFF *output; uint16 spp, bpp, NPages, pg0; //disable warning and error handlers to avoid messages on unrecognized tags TIFFSetWarningHandler(0); TIFFSetErrorHandler(0); output=TIFFOpen(filename,"r"); TIFFGetField(output, TIFFTAG_BITSPERSAMPLE, &bpp); TIFFGetField(output, TIFFTAG_SAMPLESPERPIXEL, &spp); TIFFGetField(output, TIFFTAG_PAGENUMBER, &pg0, &NPages); TIFFClose(output); // since we are output = (slice==0)? TIFFOpen(filename,"w") : TIFFOpen(filename,"a"); TIFFSetDirectory(output,slice); // WARNING: slice must be the first page after the last, otherwise the file can be corrupted TIFFSetField(output, TIFFTAG_IMAGEWIDTH, img_width); TIFFSetField(output, TIFFTAG_IMAGELENGTH, img_height); TIFFSetField(output, TIFFTAG_BITSPERSAMPLE, bpp); TIFFSetField(output, TIFFTAG_SAMPLESPERPIXEL, spp); TIFFSetField(output, TIFFTAG_ROWSPERSTRIP, (rowsPerStrip == -1) ? img_height : rowsPerStrip); TIFFSetField(output, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_LZW); //TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_NONE); TIFFSetField(output, TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); //TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); // We are writing single page of the multipage file TIFFSetField(output, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); TIFFSetField(output, TIFFTAG_PAGENUMBER, (uint16)slice, NPages); if ( rowsPerStrip == -1 ) TIFFWriteEncodedStrip(output, 0, img, img_width * img_height * spp * (bpp/8)); else { int check,StripsPerImage,LastStripSize; uint32 rps = rowsPerStrip; unsigned char *buf = img; StripsPerImage = (img_height + rps - 1) / rps; LastStripSize = img_height % rps; if (LastStripSize==0) LastStripSize=rps; for (int i=0; i < StripsPerImage-1; i++){ //if (comp==1) { // TIFFReadRawStrip(input, i, buf, spp * rps * img_width * (bpp/8)); // buf = buf + spp * rps * img_width * (bpp/8); //} //else{ TIFFWriteEncodedStrip(output, i, buf, spp * rps * img_width * (bpp/8)); buf = buf + spp * rps * img_width * (bpp/8); //} } //if (comp==1) { // TIFFReadRawStrip(input, StripsPerImage-1, buf, spp * LastStripSize * img_width * (bpp/8)); //} //else{ TIFFWriteEncodedStrip(output, StripsPerImage-1, buf, spp * LastStripSize * img_width * (bpp/8)); //} buf = buf + spp * LastStripSize * img_width * (bpp/8); } //img += img_width * img_height; TIFFWriteDirectory(output); TIFFClose(output); // 2015-01-30. Alessandro. @ADDED performance (time) measurement in all most time-consuming methods. #ifdef _VAA3D_TERAFLY_PLUGIN_MODE TERAFLY_TIME_STOP(TiffAppendData, tf::IO, tf::strprintf("appended slice %d x %d to 3D tiff \"%s\"", img_width, img_height, filename)) #endif return (char *) 0; }
void HeightMipmap::buildResiduals(int level) { int nTiles = max(1, (baseLevelSize / this->tileSize) >> (maxLevel - level)); int nTilesPerFile = min(nTiles, 16); int tileSize = min(topLevelSize << level, this->tileSize); printf("Build residuals level %d...\n", level); currentLevel = level; reset(baseLevelSize >> (maxLevel - currentLevel), baseLevelSize >> (maxLevel - currentLevel), min(topLevelSize << currentLevel, this->tileSize)); float *parentTile = new float[(this->tileSize + 5) * (this->tileSize + 5)]; float *currentTile = new float[(this->tileSize + 5) * (this->tileSize + 5)]; float *residualTile = new float[(this->tileSize + 5) * (this->tileSize + 5)]; unsigned char *encodedResidual = new unsigned char[(this->tileSize + 5) * (this->tileSize + 5) * 2]; float maxRR = 0.0; float maxEE = 0.0; for (int dy = 0; dy < nTiles / nTilesPerFile; ++dy) { for (int dx = 0; dx < nTiles / nTilesPerFile; ++dx) { char buf[256]; sprintf(buf, "%s/residual-%.2d-%.4d-%.4d.tiff", cache.c_str(), level, dx, dy); if (flog(buf)) { TIFF* f = TIFFOpen(buf, "wb"); for (int ny = 0; ny < nTilesPerFile; ++ny) { for (int nx = 0; nx < nTilesPerFile; ++nx) { int tx = nx + dx * nTilesPerFile; int ty = ny + dy * nTilesPerFile; float maxR, meanR, maxErr; getApproxTile(level - 1, tx / 2, ty / 2, parentTile); getTile(level, tx, ty, currentTile); computeResidual(parentTile, currentTile, level, tx, ty, residualTile, maxR, meanR); encodeResidual(level, residualTile, encodedResidual); computeApproxTile(parentTile, residualTile, level, tx, ty, currentTile, maxErr); if (level < maxLevel) { saveApproxTile(level, tx, ty, currentTile); } TIFFSetField(f, TIFFTAG_IMAGEWIDTH, tileSize + 5); TIFFSetField(f, TIFFTAG_IMAGELENGTH, tileSize + 5); TIFFSetField(f, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); TIFFSetField(f, TIFFTAG_ORIENTATION, ORIENTATION_BOTLEFT); TIFFSetField(f, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(f, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); /*TIFFSetField(f, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(f, TIFFTAG_BITSPERSAMPLE, 16);*/ TIFFSetField(f, TIFFTAG_SAMPLESPERPIXEL, 2); TIFFSetField(f, TIFFTAG_BITSPERSAMPLE, 8); TIFFWriteEncodedStrip(f, 0, encodedResidual, (tileSize + 5) * (tileSize + 5) * 2); TIFFWriteDirectory(f); maxRR = max(maxR, maxRR); maxEE = max(maxErr, maxEE); } } TIFFClose(f); printf("%f max residual, %f max err\n", maxRR, maxEE); } } } delete[] parentTile; delete[] currentTile; delete[] residualTile; delete[] encodedResidual; }
int imb_savetiff(ImBuf *ibuf, const char *name, int flags) { TIFF *image = NULL; uint16 samplesperpixel, bitspersample; size_t npixels; unsigned char *pixels = NULL; unsigned char *from = NULL, *to = NULL; unsigned short *pixels16 = NULL, *to16 = NULL; float *fromf = NULL; int x, y, from_i, to_i, i; int extraSampleTypes[1] = { EXTRASAMPLE_ASSOCALPHA }; /* check for a valid number of bytes per pixel. Like the PNG writer, * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding * to gray, RGB, RGBA respectively. */ samplesperpixel = (uint16)((ibuf->depth + 7) >> 3); if((samplesperpixel > 4) || (samplesperpixel == 2)) { fprintf(stderr, "imb_savetiff: unsupported number of bytes per " "pixel: %d\n", samplesperpixel); return (0); } if((ibuf->ftype & TIF_16BIT) && ibuf->rect_float) bitspersample = 16; else bitspersample = 8; /* open TIFF file for writing */ if(flags & IB_mem) { /* bork at the creation of a TIFF in memory */ fprintf(stderr, "imb_savetiff: creation of in-memory TIFF files is " "not yet supported.\n"); return (0); } else { /* create image as a file */ image = TIFFOpen(name, "w"); } if(image == NULL) { fprintf(stderr, "imb_savetiff: could not open TIFF for writing.\n"); return (0); } /* allocate array for pixel data */ npixels = ibuf->x * ibuf->y; if(bitspersample == 16) pixels16 = (unsigned short*)_TIFFmalloc(npixels * samplesperpixel * sizeof(unsigned short)); else pixels = (unsigned char*)_TIFFmalloc(npixels * samplesperpixel * sizeof(unsigned char)); if(pixels == NULL && pixels16 == NULL) { fprintf(stderr, "imb_savetiff: could not allocate pixels array.\n"); TIFFClose(image); return (0); } /* setup pointers */ if(bitspersample == 16) { fromf = ibuf->rect_float; to16 = pixels16; } else { from = (unsigned char*)ibuf->rect; to = pixels; } /* setup samples per pixel */ TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample); TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); if(samplesperpixel == 4) { /* RGBA images */ TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes); TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); } else if(samplesperpixel == 3) { /* RGB images */ TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); } else if(samplesperpixel == 1) { /* greyscale images, 1 channel */ TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); } /* copy pixel data. While copying, we flip the image vertically. */ for(x = 0; x < ibuf->x; x++) { for(y = 0; y < ibuf->y; y++) { from_i = 4*(y*ibuf->x+x); to_i = samplesperpixel*((ibuf->y-y-1)*ibuf->x+x); if(pixels16) { /* convert from float source */ float rgb[3]; if (ibuf->profile == IB_PROFILE_LINEAR_RGB) linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]); else copy_v3_v3(rgb, &fromf[from_i]); to16[to_i+0] = FTOUSHORT(rgb[0]); to16[to_i+1] = FTOUSHORT(rgb[1]); to16[to_i+2] = FTOUSHORT(rgb[2]); to_i += 3; from_i+=3; if (samplesperpixel == 4) { to16[to_i+3] = FTOUSHORT(fromf[from_i+3]); /*to_i++; from_i++;*/ /*unused, set on each loop */ } } else { for(i = 0; i < samplesperpixel; i++, to_i++, from_i++) to[to_i] = from[from_i]; } } } /* write the actual TIFF file */ TIFFSetField(image, TIFFTAG_IMAGEWIDTH, ibuf->x); TIFFSetField(image, TIFFTAG_IMAGELENGTH, ibuf->y); TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, ibuf->y); TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(image, TIFFTAG_XRESOLUTION, 150.0); TIFFSetField(image, TIFFTAG_YRESOLUTION, 150.0); TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); if(TIFFWriteEncodedStrip(image, 0, (bitspersample == 16)? (unsigned char*)pixels16: pixels, ibuf->x*ibuf->y*samplesperpixel*bitspersample/8) == -1) { fprintf(stderr, "imb_savetiff: Could not write encoded TIFF.\n"); TIFFClose(image); if(pixels) _TIFFfree(pixels); if(pixels16) _TIFFfree(pixels16); return (1); } /* close the TIFF file */ TIFFClose(image); if(pixels) _TIFFfree(pixels); if(pixels16) _TIFFfree(pixels16); return (1); }
static int SaveTIFF( ClientData cl,Tcl_Interp *interp,int argc,char **argv ) { unsigned char *buffer; char fname[256]; int nx, ny, ox, oy, viewp[4]; TIFF *image; int y, stride; // Determine file name: //--------------------- if( argc < 2 ) { strcpy( fname, "elmerpost.tif" ); } else { strncpy( fname,argv[1], 256 ); } image = TIFFOpen( fname, "w" ); if( image==NULL ) { #if defined(WIN32) || defined(win32) sprintf( interp->result, "savetiff: can't open [%s] for writing!\n",fname ); #else sprintf( interp->result, "savetiff: can't open [%s] for writing:\n%s\n", fname, strerror(errno) ); #endif return TCL_ERROR; } // Determine picture size: //------------------------ glGetIntegerv( GL_VIEWPORT, viewp ); ox = viewp[0]; oy = viewp[1]; nx = viewp[2]+1; ny = viewp[3]+1; // Allocate buffer: //------------------ buffer = (unsigned char *) malloc( nx*ny*3 ); if ( buffer==NULL ) { TIFFClose( image ); #if defined(WIN32) || defined(win32) sprintf( interp->result, "savetiff: can't allocate memory!\n" ); #else sprintf( interp->result, "savetiff: can't allocate memory:\n%s\n", strerror(errno) ); #endif return TCL_ERROR; } fprintf( stdout, "Saving %s ... ", fname ); fflush( stdout ); // Copy RGB-data into buffer: //---------------------------- glReadBuffer( GL_FRONT ); glReadPixels( ox, oy, nx, ny, GL_RGB, GL_UNSIGNED_BYTE, buffer ); // Flip the picture: //------------------ stride = 3*nx; for( y=0; y<ny/2; y++ ) { unsigned char *r1 = buffer + stride*y; unsigned char *r2 = buffer + stride*(ny-1-y); memcpy( buffer, r1, stride ); memcpy( r1, r2, stride ); memcpy( r2, buffer, stride ); } TIFFSetField( image, TIFFTAG_IMAGEWIDTH, nx ); TIFFSetField( image, TIFFTAG_IMAGELENGTH, ny ); TIFFSetField( image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE ); TIFFSetField( image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG ); TIFFSetField( image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB ); TIFFSetField( image, TIFFTAG_BITSPERSAMPLE, 8 ); TIFFSetField( image, TIFFTAG_SAMPLESPERPIXEL, 3 ); if( TIFFWriteEncodedStrip( image, 0, buffer, nx*ny*3) == 0 ) { TIFFClose( image ); #if defined(WIN32) || defined(win32) sprintf( interp->result, "savetiff: unable to encode picture\n" ); #else sprintf( interp->result, "savetiff: unable to encode picture\n%s\n", strerror(errno) ); #endif free( buffer ); return TCL_ERROR; } TIFFClose( image ); free( buffer ); fprintf( stdout, "done\n"); fflush( stdout ); return TCL_OK; }
static int cvt_by_strip( TIFF *in, TIFF *out ) { uint32* raster; /* retrieve RGBA image */ uint32 width, height; /* image width & height */ uint32 row; uint32 *wrk_line; tsize_t raster_size; int ok = 1; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); if( !TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip) ) { TIFFError(TIFFFileName(in), "Source image not in strips"); return (0); } TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); /* * Allocate strip buffer */ raster_size = multiply(multiply(width, rowsperstrip), sizeof (uint32)); if (!raster_size) { TIFFError(TIFFFileName(in), "Can't allocate buffer for raster of size %lux%lu", (unsigned long) width, (unsigned long) rowsperstrip); return (0); } raster = (uint32*)_TIFFmalloc(raster_size); if (raster == 0) { TIFFError(TIFFFileName(in), "No space for raster buffer"); return (0); } /* * Allocate a scanline buffer for swapping during the vertical * mirroring pass. (Request can't overflow given prior checks.) */ wrk_line = (uint32*)_TIFFmalloc(width * sizeof (uint32)); if (!wrk_line) { TIFFError(TIFFFileName(in), "No space for raster scanline buffer"); ok = 0; } /* * Loop over the strips. */ for( row = 0; ok && row < height; row += rowsperstrip ) { int rows_to_write, i_row; /* Read the strip into an RGBA array */ if (!TIFFReadRGBAStrip(in, row, raster)) { ok = 0; break; } /* * XXX: raster array has 4-byte unsigned integer type, that is why * we should rearrange it here. */ #if HOST_BIGENDIAN TIFFSwabArrayOfLong(raster, width * rowsperstrip); #endif /* * Figure out the number of scanlines actually in this strip. */ if( row + rowsperstrip > height ) rows_to_write = height - row; else rows_to_write = rowsperstrip; /* * For some reason the TIFFReadRGBAStrip() function chooses the * lower left corner as the origin. Vertically mirror scanlines. */ for( i_row = 0; i_row < rows_to_write / 2; i_row++ ) { uint32 *top_line, *bottom_line; top_line = raster + width * i_row; bottom_line = raster + width * (rows_to_write-i_row-1); _TIFFmemcpy(wrk_line, top_line, 4*width); _TIFFmemcpy(top_line, bottom_line, 4*width); _TIFFmemcpy(bottom_line, wrk_line, 4*width); } /* * Write out the result in a strip */ if( TIFFWriteEncodedStrip( out, row / rowsperstrip, raster, 4 * rows_to_write * width ) == -1 ) { ok = 0; break; } } _TIFFfree( raster ); _TIFFfree( wrk_line ); return ok; }
UINT ImaqThreadProc(LPVOID hWnd) { //Variables for image/file saving char index[4], direction; TIFF *image; CString strFramesFilePath ; int FileIndex=0; int TmpAvgNum=1; int ImaqBuffOffset, CaliBuffOffset, tmpAxialLine_i; bool bScan; //initialize CImgAcq class for Image acquisition CImgAcq * pImgAcq=new CImgAcq(); if (pImgAcq->Initialize()){ delete pImgAcq; theApp.m_hImaqThread=NULL; return 0; } while(bImaq) { if ( pImgAcq->GetImg()) { delete pImgAcq; theApp.m_hImaqThread=NULL; return 0; } bScan = (bScanDirection==FORWARD) || bScanBackward; //frame shift by resetting the scanning voltage to enable complex 3d / arbitrary direction imaging. if (bScan) { if ( TmpAvgNum==AvgNum ) { if (bStepX) { ScanVMinX=ScanVMinX+FrameThickness*FRAME2VOLTAGESHIFT; ScanVMaxX=ScanVMaxX+FrameThickness*FRAME2VOLTAGESHIFT; } if (bStepY){ ScanVMinY=ScanVMinY+FrameThickness*FRAME2VOLTAGESHIFT; ScanVMaxY=ScanVMaxY+FrameThickness*FRAME2VOLTAGESHIFT; } ////move the translation stage //if ( bEnableStage ) { // if (MotorStepsize>0) // pMainDlg->m_TStage.MoveJog(0,1); // else // pMainDlg->m_TStage.MoveJog(0,2); //} } //get reference if (bGetRef){ for (int j=0;j< SPECTRUMWIDTH;j++) { for (int i=0;i< ALineNum * IterationNum ;i++) { AveragedReference[j] = AveragedReference[j] + *((UINT16 *)(pImgAcq->ImaqBuff)+i*SPECTRUMWIDTH+j) ; } AveragedReference[j] = AveragedReference[j] / (ALineNum * IterationNum); } bGetRef=FALSE; } //if the DrawCurveThread is running, and RawSpectrum is checked for display, copy AxialLine Spectrum for the thread. if (bDrawCurve && bRawSpectrum ) { tmpAxialLine_i=bScanDirection? (ALineNum -1- AxialLine_i) : AxialLine_i; memcpy(RawSpectrumCurveData,(UINT16 *)(pImgAcq->ImaqBuff)+ (tmpAxialLine_i* IterationNum)*SPECTRUMWIDTH, SPECTRUMWIDTH*2); } if (bDrawCurve && bPower ) { for (int i=0;i<ALineNum;i++) { PowerData[i] = 0; for (int j=0;j<SPECTRUMWIDTH;j++) PowerData[i]= PowerData[i]+ abs(* ((INT16 *) (pImgAcq->ImaqBuff)+ (i* IterationNum)*SPECTRUMWIDTH +j)-2048.0); } } //if bReconstructImage checked, bCali ==1, thus reconstruct the images, otherwise, do not reconstruct the images to save time/speed up. if ( bCali ) { WaitForSingleObject(CaliBuffEmpty, INFINITE); TmpAvgNum++; for (int i=0;i< ALineNum * IterationNum ;i++) { ImaqBuffOffset = i*SPECTRUMWIDTH; CaliBuffOffset =bScanDirection? ((ALineNum*IterationNum-i-1)*SPECTRUMWIDTH) : (i*SPECTRUMWIDTH); for (int j=0;j< SPECTRUMWIDTH;j++) //*(CaliBuff+CaliBuffOffset+j) = *((INT16 *)(pImgAcq->ImaqBuff)+ImaqBuffOffset+j) - *(AveragedReference+j); *(CaliBuff+CaliBuffOffset+j) = *((INT16 *)(pImgAcq->ImaqBuff)+ImaqBuffOffset+j); } SetEvent(CaliBuffNew); } //continuous acquisition, if (bImqFrames) { //check if the file path is ready for continuous acquisition if (strFramesFilePath.CompareNoCase(DefaultFilePath)){ strFramesFilePath=DefaultFilePath; FileIndex=0; } //separate forward and backward scanning. FileIndex++; itoa(FileIndex,index,10); //save data as TIFF if continuous acquisition direction= bScanDirection? 'B' : 'F'; image = TIFFOpen(strFramesFilePath+index+direction+".RAW", "w"); TIFFSetField(image, TIFFTAG_IMAGEWIDTH, SPECTRUMWIDTH); TIFFSetField(image, TIFFTAG_IMAGELENGTH, ALineNum*IterationNum); TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 16); TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, IterationNum); TIFFSetField(image, TIFFTAG_COMPRESSION, 1); TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); //write the images int imageOffset = 0; int stripSize = IterationNum * SPECTRUMWIDTH*2; for ( int stripCount = 0; stripCount < ALineNum; stripCount++ ) imageOffset+=TIFFWriteEncodedStrip(image, stripCount, CaliBuff + imageOffset, stripSize)/2; // '/2' is because bits per sample is 16 = 2 bytes. TIFFClose(image); //when FramNum Images saved, stop continuous acquisition and return if ( FileIndex>=FrameNum ) { FileIndex=0; bImqFrames=FALSE; pMainDlg->GetDlgItem(IDC_IMAQ_FRAMES_STOP)->EnableWindow(FALSE); pMainDlg->GetDlgItem(IDC_IMAQ_FRAMES_STOP)->ShowWindow(FALSE); pMainDlg->GetDlgItem(IDC_IMAQ_FRAMES_START)->ShowWindow(TRUE); pMainDlg->GetDlgItem(IDC_IMAQ_FRAMES_START)->EnableWindow(TRUE); break; } } else FileIndex=0; if (TmpAvgNum>AvgNum) TmpAvgNum=1; //if (FrameInterval) Sleep(FrameInterval); } bScanDirection=!bScanDirection; //switching between backward and forward. } //exit this thread by deleting the ImgAcq classes.and set the handle of thread to Null; delete pImgAcq; theApp.m_hImaqThread=NULL; return 0; }
int write_image (dt_imageio_module_data_t *d_tmp, const char *filename, const void *in_void, void *exif, int exif_len, int imgid) { dt_imageio_tiff_t *d=(dt_imageio_tiff_t*)d_tmp; // Fetch colorprofile into buffer if wanted uint8_t *profile = NULL; uint32_t profile_len = 0; int rc = 0; if(imgid > 0) { cmsHPROFILE out_profile = dt_colorspaces_create_output_profile(imgid); cmsSaveProfileToMem(out_profile, 0, &profile_len); if (profile_len > 0) { profile=malloc(profile_len); cmsSaveProfileToMem(out_profile, profile, &profile_len); } dt_colorspaces_cleanup_profile(out_profile); } // Create tiff image TIFF *tif=TIFFOpen(filename,"wb"); if(d->bpp == 8) TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); else TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); if(profile!=NULL) TIFFSetField(tif, TIFFTAG_ICCPROFILE, profile_len, profile); TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, d->width); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, d->height); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tif, TIFFTAG_PREDICTOR, 1); // Reference www.awaresystems.be/imaging/tiff/tifftags/predictor.html TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, DT_TIFFIO_STRIPE); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3); TIFFSetField(tif, TIFFTAG_XRESOLUTION, 300.0); TIFFSetField(tif, TIFFTAG_YRESOLUTION, 300.0); TIFFSetField(tif, TIFFTAG_ZIPQUALITY, 9); const uint8_t *in8 =(const uint8_t *)in_void; const uint16_t *in16=(const uint16_t *)in_void; if(d->bpp == 16) { uint32_t rowsize=(d->width*3)*sizeof(uint16_t); uint32_t stripesize=rowsize*DT_TIFFIO_STRIPE; uint16_t *rowdata = (uint16_t *)malloc(stripesize); uint16_t *wdata = rowdata; uint32_t stripe=0; // uint32_t insize=((d->width*d->height)*3)*sizeof(uint16_t); // while(stripedata<(in8+insize)-(stripesize)) { // TIFFWriteEncodedStrip(tif,stripe++,stripedata,stripesize); // stripedata+=stripesize; // } for (int y = 0; y < d->height; y++) { for(int x=0; x<d->width; x++) for(int k=0; k<3; k++) { (wdata)[0] = in16[4*d->width*y + 4*x + k]; wdata++; } if((wdata-stripesize/sizeof(uint16_t))==rowdata) { TIFFWriteEncodedStrip(tif,stripe++,rowdata,rowsize*DT_TIFFIO_STRIPE); wdata=rowdata; } } if((wdata-stripesize/sizeof(uint16_t))!=rowdata) TIFFWriteEncodedStrip(tif,stripe,rowdata,(wdata-rowdata)*sizeof(uint16_t)); TIFFClose(tif); free(rowdata); } else { uint32_t rowsize=(d->width*3)*sizeof(uint8_t); uint32_t stripesize=rowsize*DT_TIFFIO_STRIPE; uint8_t *rowdata = (uint8_t *)malloc(stripesize); uint8_t *wdata = rowdata; uint32_t stripe=0; for (int y = 0; y < d->height; y++) { for(int x=0; x<d->width; x++) for(int k=0; k<3; k++) { (wdata)[0] = in8[4*d->width*y + 4*x + k]; wdata++; } if((wdata-stripesize)==rowdata) { TIFFWriteEncodedStrip(tif,stripe++,rowdata,rowsize*DT_TIFFIO_STRIPE); wdata=rowdata; } } if((wdata-stripesize)!=rowdata) TIFFWriteEncodedStrip(tif,stripe,rowdata,wdata-rowdata); TIFFClose(tif); free(rowdata); } if(exif) rc = dt_exif_write_blob(exif,exif_len,filename); free(profile); /* * Until we get symbolic error status codes, if rc is 1, return 0. */ return ((rc == 1) ? 0 : 1); }
static void TIFFWriteOvrRow( TIFFOvrCache * psCache ) { int nRet, iTileX, iTileY = psCache->nBlockOffset; unsigned char *pabyData; uint32 nBaseDirOffset; uint32 RowsInStrip; /* -------------------------------------------------------------------- */ /* If the output cache is multi-byte per sample, and the file */ /* being written to is of a different byte order than the current */ /* platform, we will need to byte swap the data. */ /* -------------------------------------------------------------------- */ if( TIFFIsByteSwapped(psCache->hTIFF) ) { if( psCache->nBitsPerPixel == 16 ) TIFFSwabArrayOfShort( (uint16 *) psCache->pabyRow1Blocks, (psCache->nBytesPerBlock * psCache->nSamples) / 2 ); else if( psCache->nBitsPerPixel == 32 ) TIFFSwabArrayOfLong( (uint32 *) psCache->pabyRow1Blocks, (psCache->nBytesPerBlock * psCache->nSamples) / 4 ); else if( psCache->nBitsPerPixel == 64 ) TIFFSwabArrayOfDouble( (double *) psCache->pabyRow1Blocks, (psCache->nBytesPerBlock * psCache->nSamples) / 8 ); } /* -------------------------------------------------------------------- */ /* Record original directory position, so we can restore it at */ /* end. */ /* -------------------------------------------------------------------- */ nBaseDirOffset = TIFFCurrentDirOffset( psCache->hTIFF ); nRet = TIFFSetSubDirectory( psCache->hTIFF, psCache->nDirOffset ); assert( nRet == 1 ); /* -------------------------------------------------------------------- */ /* Write blocks to TIFF file. */ /* -------------------------------------------------------------------- */ for( iTileX = 0; iTileX < psCache->nBlocksPerRow; iTileX++ ) { int nTileID; if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE) { int iSample; for( iSample = 0; iSample < psCache->nSamples; iSample++ ) { pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, iSample ); if( psCache->bTiled ) { nTileID = TIFFComputeTile( psCache->hTIFF, iTileX * psCache->nBlockXSize, iTileY * psCache->nBlockYSize, 0, (tsample_t) iSample ); TIFFWriteEncodedTile( psCache->hTIFF, nTileID, pabyData, TIFFTileSize(psCache->hTIFF) ); } else { nTileID = TIFFComputeStrip( psCache->hTIFF, iTileY * psCache->nBlockYSize, (tsample_t) iSample ); RowsInStrip=psCache->nBlockYSize; if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize) RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize; TIFFWriteEncodedStrip( psCache->hTIFF, nTileID, pabyData, TIFFVStripSize(psCache->hTIFF,RowsInStrip) ); } } } else { pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, 0 ); if( psCache->bTiled ) { nTileID = TIFFComputeTile( psCache->hTIFF, iTileX * psCache->nBlockXSize, iTileY * psCache->nBlockYSize, 0, 0 ); TIFFWriteEncodedTile( psCache->hTIFF, nTileID, pabyData, TIFFTileSize(psCache->hTIFF) ); } else { nTileID = TIFFComputeStrip( psCache->hTIFF, iTileY * psCache->nBlockYSize, 0 ); RowsInStrip=psCache->nBlockYSize; if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize) RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize; TIFFWriteEncodedStrip( psCache->hTIFF, nTileID, pabyData, TIFFVStripSize(psCache->hTIFF,RowsInStrip) ); } } } /* TODO: add checks on error status return of TIFFWriteEncodedTile and TIFFWriteEncodedStrip */ /* -------------------------------------------------------------------- */ /* Rotate buffers. */ /* -------------------------------------------------------------------- */ pabyData = psCache->pabyRow1Blocks; psCache->pabyRow1Blocks = psCache->pabyRow2Blocks; psCache->pabyRow2Blocks = pabyData; _TIFFmemset( pabyData, 0, psCache->nBytesPerRow ); psCache->nBlockOffset++; /* -------------------------------------------------------------------- */ /* Restore access to original directory. */ /* -------------------------------------------------------------------- */ TIFFFlush( psCache->hTIFF ); /* TODO: add checks on error status return of TIFFFlush */ TIFFSetSubDirectory( psCache->hTIFF, nBaseDirOffset ); /* TODO: add checks on error status return of TIFFSetSubDirectory */ }
static int cvt_whole_image( TIFF *in, TIFF *out ) { uint32* raster; /* retrieve RGBA image */ uint32 width, height; /* image width & height */ uint32 row; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip); TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32)); if (raster == 0) { TIFFError(TIFFFileName(in), "No space for raster buffer"); return (0); } /* Read the image in one chunk into an RGBA array */ if (!TIFFReadRGBAImageOriented(in, width, height, raster, ORIENTATION_TOPLEFT, 0)) { _TIFFfree(raster); return (0); } /* ** Do we want to strip away alpha components? */ if( no_alpha ) { int pixel_count = width * height; unsigned char *src, *dst; src = (unsigned char *) raster; dst = (unsigned char *) raster; while( pixel_count > 0 ) { *(dst++) = *(src++); *(dst++) = *(src++); *(dst++) = *(src++); src++; pixel_count--; } } /* Write out the result in strips */ for( row = 0; row < height; row += rowsperstrip ) { unsigned char * raster_strip; int rows_to_write; int bytes_per_pixel; if( no_alpha ) { raster_strip = ((unsigned char *) raster) + 3 * row * width; bytes_per_pixel = 3; } else { raster_strip = (unsigned char *) (raster + row * width); bytes_per_pixel = 4; } if( row + rowsperstrip > height ) rows_to_write = height - row; else rows_to_write = rowsperstrip; if( TIFFWriteEncodedStrip( out, row / rowsperstrip, raster_strip, bytes_per_pixel * rows_to_write * width ) == -1 ) { _TIFFfree( raster ); return 0; } } _TIFFfree( raster ); return 1; }
char *initTiff3DFile ( char *filename, unsigned int sz0, unsigned int sz1, unsigned int sz2, unsigned int sz3, int datatype ) { //int initTiff3DFile ( char *filename, uint32 XSIZE, uint32 YSIZE, uint16 spp, uint16 Npages, int datatype){ // 2015-01-30. Alessandro. @ADDED performance (time) measurement in all most time-consuming methods. #ifdef _VAA3D_TERAFLY_PLUGIN_MODE TERAFLY_TIME_START(TiffInitData) #endif uint32 XSIZE = sz0; uint32 YSIZE = sz1; uint16 Npages = sz2; uint16 spp = sz3; uint16 bpp=8 * datatype; unsigned char *fakeData=new unsigned char[XSIZE * YSIZE]; int check; if ( sz3 == 1 ) spp = sz3; else if ( sz3 < 4 ) spp = 3; else return ((char *) "More than 3 channels in Tiff files."); char *completeFilename = (char *) 0; int fname_len = (int) strlen(filename); char *suffix = strstr(filename,".tif"); while ( suffix && (fname_len - (suffix-filename) > 5) ) suffix = strstr(suffix+4,".tif"); //if ( (suffix != 0) && (fname_len - (suffix-filename) <= 5) ) { // a substring ".tif is already at the end of the filename if ( suffix ) { // a substring ".tif is already at the very end of the filename completeFilename = new char[fname_len+1]; strcpy(completeFilename,filename); } else { completeFilename = new char[fname_len+4+1]; strcpy(completeFilename,filename); strcat(completeFilename,"."); strcat(completeFilename,TIFF3D_SUFFIX); } // 2015-01-30. Alessandro. @ADDED performance (time) measurement in all most time-consuming methods. #ifdef _VAA3D_TERAFLY_PLUGIN_MODE TERAFLY_TIME_STOP(TiffInitData, itm::CPU, itm::strprintf("generated fake data for 3D tiff \"%s\"", completeFilename)) TERAFLY_TIME_RESTART(TiffInitData) #endif TIFF *output; output = TIFFOpen(completeFilename,"w"); if (!output) { return ((char *) "Cannot open the file."); } check = TIFFSetField(output, TIFFTAG_IMAGEWIDTH, XSIZE); if (!check) { return ((char *) "Cannot set the image width."); } check = TIFFSetField(output, TIFFTAG_IMAGELENGTH, YSIZE); if (!check) { return ((char *) "Cannot set the image width."); } check = TIFFSetField(output, TIFFTAG_BITSPERSAMPLE, bpp); if (!check) { return ((char *) "Cannot set the image width."); } check = TIFFSetField(output, TIFFTAG_SAMPLESPERPIXEL, spp); if (!check) { return ((char *) "Cannot set the image width."); } check = TIFFSetField(output, TIFFTAG_ROWSPERSTRIP, YSIZE); // one page per strip if (!check) { return ((char *) "Cannot set the image height."); } check = TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_LZW); if (!check) { return ((char *) "Cannot set the compression tag."); } check = TIFFSetField(output, TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); if (!check) { return ((char *) "Cannot set the planarconfig tag."); } if ( spp == 1 ) check = TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); else // spp == 3 check = TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); if (!check) { return ((char *) "Cannot set the photometric tag."); } /* We are writing single page of the multipage file */ check = TIFFSetField(output, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE); if (!check) { return ((char *) "Cannot set the subfiletype tag."); } check = TIFFSetField(output, TIFFTAG_PAGENUMBER, 0, Npages); if (!check) { return ((char *) "Cannot set the page number."); } check = (int)TIFFWriteEncodedStrip(output, 0, fakeData, XSIZE * YSIZE); if (!check) { return ((char *) "Cannot write encoded strip to file."); } delete[] fakeData; delete []completeFilename; check = TIFFWriteDirectory(output); if (!check) { return ((char *) "Cannot write a new directory."); } TIFFClose(output); // 2015-01-30. Alessandro. @ADDED performance (time) measurement in all most time-consuming methods. #ifdef _VAA3D_TERAFLY_PLUGIN_MODE TERAFLY_TIME_STOP(TiffInitData, itm::IO, itm::strprintf("written initialized 3D tiff \"%s\"", completeFilename)) #endif return (char *) 0; }
void tiff_out() { int i,j; int m; int mincount; int* maskcount=(int*)malloc(g_numimages*sizeof(int)); int* masklimit=(int*)malloc(g_numimages*sizeof(int)); int* mask=(int*)malloc(g_numimages*sizeof(int)); int rowsperstrip=64; int p=0; int strips; int remaining; int strip_p; int x,y=0,s; int stripy; int rows; uint16 out[1]; uint32 temp; int mul; mul=3; if (!g_nomask) mul=4; if (g_workbpp==16) mul=mul<<1; mul=mul*g_workwidth; for (i=0; i<g_numimages; i++) g_images[i].binary_mask.pointer=g_images[i].binary_mask.data; void* strip=malloc((rowsperstrip*g_workwidth)<<(g_workbpp>>2)); TIFFSetField(g_tiff, TIFFTAG_IMAGEWIDTH, g_workwidth); TIFFSetField(g_tiff, TIFFTAG_IMAGELENGTH, g_workheight); TIFFSetField(g_tiff, TIFFTAG_COMPRESSION, g_compression); TIFFSetField(g_tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(g_tiff, TIFFTAG_ROWSPERSTRIP, rowsperstrip); TIFFSetField(g_tiff, TIFFTAG_BITSPERSAMPLE, g_workbpp); if (g_nomask) { TIFFSetField(g_tiff, TIFFTAG_SAMPLESPERPIXEL, 3); } else { TIFFSetField(g_tiff, TIFFTAG_SAMPLESPERPIXEL, 4); out[0] = EXTRASAMPLE_UNASSALPHA; TIFFSetField(g_tiff, TIFFTAG_EXTRASAMPLES, 1, &out); } TIFFSetField(g_tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); if (g_xres!=-1) { TIFFSetField(g_tiff, TIFFTAG_XRESOLUTION, g_xres); TIFFSetField(g_tiff, TIFFTAG_XPOSITION, (float)(g_min_left/g_xres)); } if (g_yres!=-1) { TIFFSetField(g_tiff, TIFFTAG_YRESOLUTION, g_yres); TIFFSetField(g_tiff, TIFFTAG_YPOSITION, (float)(g_min_top/g_yres)); } if (g_images[0].geotiff.set) { // if we got a georeferenced input, store the geotags in the output GeoTIFFInfo info(g_images[0].geotiff); info.XGeoRef = g_min_left * g_images[0].geotiff.XCellRes; info.YGeoRef = -g_min_top * g_images[0].geotiff.YCellRes; output(1,"Output georef: UL: %f %f, pixel size: %f %f\n",info.XGeoRef, info.YGeoRef, info.XCellRes, info.YCellRes); geotiff_write(g_tiff, &info); } strips=(int)((g_workheight+rowsperstrip-1)/rowsperstrip); remaining=g_workheight; for (s=0; s<strips; s++) { rows=min(remaining,rowsperstrip); strip_p=0; for (stripy=0; stripy<rows; stripy++) { if (g_nomask) { if (g_workbpp==8) { for (x=0; x<g_workwidth; x++) { ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[0])[p]; ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[1])[p]; ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[2])[p]; p++; } } else { for (x=0; x<g_workwidth; x++) { ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[0])[p]; ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[1])[p]; ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[2])[p]; p++; } } } else { for (i=0; i<g_numimages; i++) { mask[i]=MASKOFF; if (y>=g_images[i].ypos && y<g_images[i].ypos+g_images[i].height) { maskcount[i]=g_images[i].xpos; masklimit[i]=g_images[i].xpos+g_images[i].width; g_images[i].binary_mask.pointer=&g_images[i].binary_mask.data[g_images[i].binary_mask.rows[y-g_images[i].ypos]]; } else { maskcount[i]=g_workwidth; masklimit[i]=g_workwidth; } } x=0; while (x<g_workwidth) { m=MASKOFF; mincount=g_workwidth-x; for (i=0; i<g_numimages; i++) { if (maskcount[i]==0) { if (x<masklimit[i]) { NEXTiMASK(i); } else { mask[i]=MASKOFF; maskcount[i]=mincount; } } if (maskcount[i]<mincount) mincount=maskcount[i]; if (mask[i]!=MASKOFF) m=MASKON; } if (m==MASKON) { if (g_workbpp==8) { for (j=0; j<mincount; j++) { ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[0])[p]; ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[1])[p]; ((uint8*)strip)[strip_p++]=((uint8*)g_out_channels[2])[p]; ((uint8*)strip)[strip_p++]=0xff; p++; } } else { for (j=0; j<mincount; j++) { ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[0])[p]; ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[1])[p]; ((uint16*)strip)[strip_p++]=((uint16*)g_out_channels[2])[p]; if (!g_nomask) ((uint16*)strip)[strip_p++]=0xffff; p++; } } } else { if (g_workbpp==8) { memset(&((uint8*)strip)[strip_p],0,mincount<<2); } else { memset(&((uint16*)strip)[strip_p],0,mincount<<3); } strip_p+=mincount<<2; p+=mincount; } /* if (m==MASKON || g_nomask) { if (g_workbpp==8) { for (j=0; j<mincount; j++) { ((uint8*)strip)[strip_p++]=((uint8**)g_out_channels)[0][p]; ((uint8*)strip)[strip_p++]=((uint8**)g_out_channels)[1][p]; ((uint8*)strip)[strip_p++]=((uint8**)g_out_channels)[2][p]; if (!g_nomask) ((uint8*)strip)[strip_p++]=0xff; p++; } } else { for (j=0; j<mincount; j++) { ((uint16*)strip)[strip_p++]=((uint16**)g_out_channels)[0][p]; ((uint16*)strip)[strip_p++]=((uint16**)g_out_channels)[1][p]; ((uint16*)strip)[strip_p++]=((uint16**)g_out_channels)[2][p]; if (!g_nomask) ((uint16*)strip)[strip_p++]=0xffff; p++; } } } else { if (g_workbpp==8) { if (g_nomask) blank=mincount*3; else blank=mincount<<2; memset(&((uint8*)strip)[strip_p],0,blank); strip_p+=mincount<<2; } else { if (g_nomask) blank=mincount*6; else blank=mincount<<3; memset(&((uint16*)strip)[strip_p],0,blank); strip_p+=mincount<<2; } p+=mincount; } */ for (i=0; i<g_numimages; i++) maskcount[i]-=mincount; x+=mincount; } } y++; } TIFFWriteEncodedStrip(g_tiff,s,strip,rows*mul); remaining-=rows; } TIFFClose(g_tiff); }
static int cvt_by_strip( TIFF *in, TIFF *out ) { uint32* raster; /* retrieve RGBA image */ uint32 width, height; /* image width & height */ uint32 row; uint32 *wrk_line; int ok = 1; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); if( !TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip) ) { TIFFError(TIFFFileName(in), "Source image not in strips"); return (0); } TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip); /* * Allocate strip buffer */ raster = (uint32*)_TIFFmalloc(width * rowsperstrip * sizeof (uint32)); if (raster == 0) { TIFFError(TIFFFileName(in), "No space for raster buffer"); return (0); } /* * Allocate a scanline buffer for swapping during the vertical * mirroring pass. */ wrk_line = (uint32*)_TIFFmalloc(width * sizeof (uint32)); if (wrk_line == 0) { TIFFError(TIFFFileName(in), "No space for raster scanline buffer"); ok = 0; } /* * Loop over the strips. */ for( row = 0; ok && row < height; row += rowsperstrip ) { int rows_to_write, i_row; /* Read the strip into an RGBA array */ if (!TIFFReadRGBAStrip(in, row, raster)) { ok = 0; break; } /* * Figure out the number of scanlines actually in this strip. */ if( row + rowsperstrip > height ) rows_to_write = height - row; else rows_to_write = rowsperstrip; /* * For some reason the TIFFReadRGBAStrip() function chooses the * lower left corner as the origin. Vertically mirror scanlines. */ for( i_row = 0; i_row < rows_to_write / 2; i_row++ ) { uint32 *top_line, *bottom_line; top_line = raster + width * i_row; bottom_line = raster + width * (rows_to_write-i_row-1); _TIFFmemcpy(wrk_line, top_line, 4*width); _TIFFmemcpy(top_line, bottom_line, 4*width); _TIFFmemcpy(bottom_line, wrk_line, 4*width); } /* * Write out the result in a strip */ if( TIFFWriteEncodedStrip( out, row / rowsperstrip, raster, 4 * rows_to_write * width ) == -1 ) { ok = 0; break; } } _TIFFfree( raster ); _TIFFfree( wrk_line ); return ok; }
static void TIFF_WriteOverview( TIFF *hTIFF, int nSamples, RawBlockedImage **papoRBI, int bTiled, int nCompressFlag, int nPhotometric, unsigned short *panRed, unsigned short *panGreen, unsigned short *panBlue, int bUseSubIFDs ) { int iSample; RawBlockedImage *poRBI = papoRBI[0]; /* -------------------------------------------------------------------- */ /* Setup TIFF fields. */ /* -------------------------------------------------------------------- */ TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, poRBI->GetXSize() ); TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, poRBI->GetYSize() ); TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_SEPARATE ); TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, poRBI->GetBitsPerPixel() ); TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples ); TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag ); TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric ); if( bTiled ) { TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, poRBI->GetBlockXSize() ); TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, poRBI->GetBlockYSize() ); } else TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, poRBI->GetBlockYSize() ); TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE ); /* -------------------------------------------------------------------- */ /* Write color table if one is present. */ /* -------------------------------------------------------------------- */ if( panRed != NULL ) { TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue ); } /* -------------------------------------------------------------------- */ /* Write blocks to TIFF file. */ /* -------------------------------------------------------------------- */ for( iSample = 0; iSample < nSamples; iSample++ ) { int iTileX, iTileY; poRBI = papoRBI[iSample]; for( iTileY = 0; iTileY*poRBI->GetBlockYSize() < poRBI->GetYSize(); iTileY++ ) { for( iTileX = 0; iTileX*poRBI->GetBlockXSize() < poRBI->GetXSize(); iTileX++ ) { unsigned char *pabyData = poRBI->GetTile( iTileX, iTileY ); int nTileID; if( bTiled ) { nTileID = TIFFComputeTile(hTIFF, iTileX * poRBI->GetBlockXSize(), iTileY * poRBI->GetBlockYSize(), 0, iSample ); TIFFWriteEncodedTile( hTIFF, nTileID, pabyData, TIFFTileSize(hTIFF) ); } else { nTileID = TIFFComputeStrip(hTIFF, iTileY*poRBI->GetBlockYSize(), iSample); TIFFWriteEncodedStrip( hTIFF, nTileID, pabyData, TIFFStripSize( hTIFF ) ); } } } } TIFFWriteDirectory( hTIFF ); }