|
Blender
V2.59
|
00001 /* 00002 * tiff.c 00003 * 00004 * $Id: tiff.c 36669 2011-05-13 14:27:12Z campbellbarton $ 00005 * 00006 * ***** BEGIN GPL LICENSE BLOCK ***** 00007 * 00008 * This program is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU General Public License 00010 * as published by the Free Software Foundation; either version 2 00011 * of the License, or (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software Foundation, 00020 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00021 * 00022 * Contributor(s): Jonathan Merritt. 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00048 #ifdef WITH_TIFF 00049 00050 #include <string.h> 00051 00052 #include "imbuf.h" 00053 00054 #include "BLI_math.h" 00055 #include "BLI_string.h" 00056 #include "BLI_utildefines.h" 00057 00058 #include "BKE_global.h" 00059 00060 00061 #include "IMB_imbuf_types.h" 00062 #include "IMB_imbuf.h" 00063 00064 #include "IMB_allocimbuf.h" 00065 #include "IMB_filetype.h" 00066 #include "IMB_filter.h" 00067 00068 #include "tiffio.h" 00069 00070 00071 00072 /*********************** 00073 * Local declarations. * 00074 ***********************/ 00075 /* Reading and writing of an in-memory TIFF file. */ 00076 static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n); 00077 static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n); 00078 static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence); 00079 static int imb_tiff_CloseProc(thandle_t handle); 00080 static toff_t imb_tiff_SizeProc(thandle_t handle); 00081 static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize); 00082 static void imb_tiff_DummyUnmapProc(thandle_t fd, tdata_t base, toff_t size); 00083 00084 00085 /* Structure for in-memory TIFF file. */ 00086 typedef struct ImbTIFFMemFile { 00087 unsigned char *mem; /* Location of first byte of TIFF file. */ 00088 toff_t offset; /* Current offset within the file. */ 00089 tsize_t size; /* Size of the TIFF file. */ 00090 } ImbTIFFMemFile; 00091 #define IMB_TIFF_GET_MEMFILE(x) ((ImbTIFFMemFile*)(x)); 00092 00093 00094 00095 /***************************** 00096 * Function implementations. * 00097 *****************************/ 00098 00099 00100 static void imb_tiff_DummyUnmapProc(thandle_t fd, tdata_t base, toff_t size) 00101 { 00102 (void)fd; 00103 (void)base; 00104 (void)size; 00105 } 00106 00107 static int imb_tiff_DummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) 00108 { 00109 (void)fd; 00110 (void)pbase; 00111 (void)psize; 00112 00113 return (0); 00114 } 00115 00126 static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n) 00127 { 00128 tsize_t nRemaining, nCopy; 00129 ImbTIFFMemFile* mfile; 00130 void *srcAddr; 00131 00132 /* get the pointer to the in-memory file */ 00133 mfile = IMB_TIFF_GET_MEMFILE(handle); 00134 if(!mfile || !mfile->mem) { 00135 fprintf(stderr, "imb_tiff_ReadProc: !mfile || !mfile->mem!\n"); 00136 return 0; 00137 } 00138 00139 /* find the actual number of bytes to read (copy) */ 00140 nCopy = n; 00141 if((tsize_t)mfile->offset >= mfile->size) 00142 nRemaining = 0; 00143 else 00144 nRemaining = mfile->size - mfile->offset; 00145 00146 if(nCopy > nRemaining) 00147 nCopy = nRemaining; 00148 00149 /* on EOF, return immediately and read (copy) nothing */ 00150 if(nCopy <= 0) 00151 return (0); 00152 00153 /* all set -> do the read (copy) */ 00154 srcAddr = (void*)(&(mfile->mem[mfile->offset])); 00155 memcpy((void*)data, srcAddr, nCopy); 00156 mfile->offset += nCopy; /* advance file ptr by copied bytes */ 00157 return nCopy; 00158 } 00159 00160 00161 00168 static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n) 00169 { 00170 (void)handle; 00171 (void)data; 00172 (void)n; 00173 00174 printf("imb_tiff_WriteProc: this function should not be called.\n"); 00175 return (-1); 00176 } 00177 00178 00179 00194 static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence) 00195 { 00196 ImbTIFFMemFile *mfile; 00197 toff_t new_offset; 00198 00199 /* get the pointer to the in-memory file */ 00200 mfile = IMB_TIFF_GET_MEMFILE(handle); 00201 if(!mfile || !mfile->mem) { 00202 fprintf(stderr, "imb_tiff_SeekProc: !mfile || !mfile->mem!\n"); 00203 return (-1); 00204 } 00205 00206 /* find the location we plan to seek to */ 00207 switch (whence) { 00208 case SEEK_SET: 00209 new_offset = ofs; 00210 break; 00211 case SEEK_CUR: 00212 new_offset = mfile->offset + ofs; 00213 break; 00214 default: 00215 /* no other types are supported - return an error */ 00216 fprintf(stderr, 00217 "imb_tiff_SeekProc: " 00218 "Unsupported TIFF SEEK type.\n"); 00219 return (-1); 00220 } 00221 00222 /* set the new location */ 00223 mfile->offset = new_offset; 00224 return mfile->offset; 00225 } 00226 00227 00228 00241 static int imb_tiff_CloseProc(thandle_t handle) 00242 { 00243 ImbTIFFMemFile *mfile; 00244 00245 /* get the pointer to the in-memory file */ 00246 mfile = IMB_TIFF_GET_MEMFILE(handle); 00247 if(!mfile || !mfile->mem) { 00248 fprintf(stderr,"imb_tiff_CloseProc: !mfile || !mfile->mem!\n"); 00249 return (0); 00250 } 00251 00252 /* virtually close the file */ 00253 mfile->mem = NULL; 00254 mfile->offset = 0; 00255 mfile->size = 0; 00256 00257 return (0); 00258 } 00259 00260 00261 00267 static toff_t imb_tiff_SizeProc(thandle_t handle) 00268 { 00269 ImbTIFFMemFile* mfile; 00270 00271 /* get the pointer to the in-memory file */ 00272 mfile = IMB_TIFF_GET_MEMFILE(handle); 00273 if(!mfile || !mfile->mem) { 00274 fprintf(stderr,"imb_tiff_SizeProc: !mfile || !mfile->mem!\n"); 00275 return (0); 00276 } 00277 00278 /* return the size */ 00279 return (toff_t)(mfile->size); 00280 } 00281 00282 static TIFF *imb_tiff_client_open(ImbTIFFMemFile *memFile, unsigned char *mem, size_t size) 00283 { 00284 /* open the TIFF client layer interface to the in-memory file */ 00285 memFile->mem = mem; 00286 memFile->offset = 0; 00287 memFile->size = size; 00288 00289 return TIFFClientOpen("(Blender TIFF Interface Layer)", 00290 "r", (thandle_t)(memFile), 00291 imb_tiff_ReadProc, imb_tiff_WriteProc, 00292 imb_tiff_SeekProc, imb_tiff_CloseProc, 00293 imb_tiff_SizeProc, imb_tiff_DummyMapProc, imb_tiff_DummyUnmapProc); 00294 } 00295 00311 #define IMB_TIFF_NCB 4 /* number of comparison bytes used */ 00312 int imb_is_a_tiff(unsigned char *mem) 00313 { 00314 char big_endian[IMB_TIFF_NCB] = { 0x4d, 0x4d, 0x00, 0x2a }; 00315 char lil_endian[IMB_TIFF_NCB] = { 0x49, 0x49, 0x2a, 0x00 }; 00316 00317 return ( (memcmp(big_endian, mem, IMB_TIFF_NCB) == 0) || 00318 (memcmp(lil_endian, mem, IMB_TIFF_NCB) == 0) ); 00319 } 00320 00321 static void scanline_contig_16bit(float *rectf, unsigned short *sbuf, int scanline_w, int spp) 00322 { 00323 int i; 00324 for (i=0; i < scanline_w; i++) { 00325 rectf[i*4 + 0] = sbuf[i*spp + 0] / 65535.0; 00326 rectf[i*4 + 1] = sbuf[i*spp + 1] / 65535.0; 00327 rectf[i*4 + 2] = sbuf[i*spp + 2] / 65535.0; 00328 rectf[i*4 + 3] = (spp==4)?(sbuf[i*spp + 3] / 65535.0):1.0; 00329 } 00330 } 00331 00332 static void scanline_contig_32bit(float *rectf, float *fbuf, int scanline_w, int spp) 00333 { 00334 int i; 00335 for (i=0; i < scanline_w; i++) { 00336 rectf[i*4 + 0] = fbuf[i*spp + 0]; 00337 rectf[i*4 + 1] = fbuf[i*spp + 1]; 00338 rectf[i*4 + 2] = fbuf[i*spp + 2]; 00339 rectf[i*4 + 3] = (spp==4)?fbuf[i*spp + 3]:1.0f; 00340 } 00341 } 00342 00343 static void scanline_separate_16bit(float *rectf, unsigned short *sbuf, int scanline_w, int chan) 00344 { 00345 int i; 00346 for (i=0; i < scanline_w; i++) 00347 rectf[i*4 + chan] = sbuf[i] / 65535.0; 00348 } 00349 00350 static void scanline_separate_32bit(float *rectf, float *fbuf, int scanline_w, int chan) 00351 { 00352 int i; 00353 for (i=0; i < scanline_w; i++) 00354 rectf[i*4 + chan] = fbuf[i]; 00355 } 00356 00357 static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image) 00358 { 00359 uint16 unit; 00360 float xres; 00361 float yres; 00362 00363 TIFFGetFieldDefaulted(image, TIFFTAG_RESOLUTIONUNIT, &unit); 00364 TIFFGetFieldDefaulted(image, TIFFTAG_XRESOLUTION, &xres); 00365 TIFFGetFieldDefaulted(image, TIFFTAG_YRESOLUTION, &yres); 00366 00367 if(unit == RESUNIT_CENTIMETER) { 00368 ibuf->ppm[0]= (double)xres * 100.0; 00369 ibuf->ppm[1]= (double)yres * 100.0; 00370 } 00371 else { 00372 ibuf->ppm[0]= (double)xres / 0.0254; 00373 ibuf->ppm[1]= (double)yres / 0.0254; 00374 } 00375 } 00376 00377 /* 00378 * Use the libTIFF scanline API to read a TIFF image. 00379 * This method is most flexible and can handle multiple different bit depths 00380 * and RGB channel orderings. 00381 */ 00382 static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul) 00383 { 00384 ImBuf *tmpibuf; 00385 int success= 0; 00386 short bitspersample, spp, config; 00387 size_t scanline; 00388 int ib_flag=0, row, chan; 00389 float *fbuf=NULL; 00390 unsigned short *sbuf=NULL; 00391 00392 TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample); 00393 TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); /* number of 'channels' */ 00394 TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config); 00395 00396 imb_read_tiff_resolution(ibuf, image); 00397 00398 scanline = TIFFScanlineSize(image); 00399 00400 if (bitspersample == 32) { 00401 ib_flag = IB_rectfloat; 00402 fbuf = (float *)_TIFFmalloc(scanline); 00403 } else if (bitspersample == 16) { 00404 ib_flag = IB_rectfloat; 00405 sbuf = (unsigned short *)_TIFFmalloc(scanline); 00406 } else { 00407 ib_flag = IB_rect; 00408 } 00409 00410 tmpibuf= IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->depth, ib_flag); 00411 00412 /* simple RGBA image */ 00413 if (!(bitspersample == 32 || bitspersample == 16)) { 00414 success |= TIFFReadRGBAImage(image, ibuf->x, ibuf->y, tmpibuf->rect, 0); 00415 } 00416 /* contiguous channels: RGBRGBRGB */ 00417 else if (config == PLANARCONFIG_CONTIG) { 00418 for (row = 0; row < ibuf->y; row++) { 00419 int ib_offset = ibuf->x*ibuf->y*4 - ibuf->x*4 * (row+1); 00420 00421 if (bitspersample == 32) { 00422 success |= TIFFReadScanline(image, fbuf, row, 0); 00423 scanline_contig_32bit(tmpibuf->rect_float+ib_offset, fbuf, ibuf->x, spp); 00424 00425 } else if (bitspersample == 16) { 00426 success |= TIFFReadScanline(image, sbuf, row, 0); 00427 scanline_contig_16bit(tmpibuf->rect_float+ib_offset, sbuf, ibuf->x, spp); 00428 } 00429 } 00430 /* separate channels: RRRGGGBBB */ 00431 } else if (config == PLANARCONFIG_SEPARATE) { 00432 00433 /* imbufs always have 4 channels of data, so we iterate over all of them 00434 * but only fill in from the TIFF scanline where necessary. */ 00435 for (chan = 0; chan < 4; chan++) { 00436 for (row = 0; row < ibuf->y; row++) { 00437 int ib_offset = ibuf->x*ibuf->y*4 - ibuf->x*4 * (row+1); 00438 00439 if (bitspersample == 32) { 00440 if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ 00441 memset(fbuf, 1.0, sizeof(fbuf)); 00442 else 00443 success |= TIFFReadScanline(image, fbuf, row, chan); 00444 scanline_separate_32bit(tmpibuf->rect_float+ib_offset, fbuf, ibuf->x, chan); 00445 00446 } else if (bitspersample == 16) { 00447 if (chan == 3 && spp == 3) /* fill alpha if only RGB TIFF */ 00448 memset(sbuf, 65535, sizeof(sbuf)); 00449 else 00450 success |= TIFFReadScanline(image, sbuf, row, chan); 00451 scanline_separate_16bit(tmpibuf->rect_float+ib_offset, sbuf, ibuf->x, chan); 00452 00453 } 00454 } 00455 } 00456 } 00457 00458 if (bitspersample == 32) 00459 _TIFFfree(fbuf); 00460 else if (bitspersample == 16) 00461 _TIFFfree(sbuf); 00462 00463 if(success) { 00464 ibuf->profile = (bitspersample==32)?IB_PROFILE_LINEAR_RGB:IB_PROFILE_SRGB; 00465 00466 // Code seems to be not needed for 16 bits tif, on PPC G5 OSX (ton) 00467 if(bitspersample < 16) 00468 if(ENDIAN_ORDER == B_ENDIAN) 00469 IMB_convert_rgba_to_abgr(tmpibuf); 00470 if(premul) { 00471 IMB_premultiply_alpha(tmpibuf); 00472 ibuf->flags |= IB_premul; 00473 } 00474 00475 /* assign rect last */ 00476 if (tmpibuf->rect_float) 00477 ibuf->rect_float= tmpibuf->rect_float; 00478 else 00479 ibuf->rect= tmpibuf->rect; 00480 ibuf->mall |= ib_flag; 00481 ibuf->flags |= ib_flag; 00482 00483 tmpibuf->mall &= ~ib_flag; 00484 } 00485 00486 IMB_freeImBuf(tmpibuf); 00487 00488 return success; 00489 } 00490 00491 void imb_inittiff(void) 00492 { 00493 if (!(G.f & G_DEBUG)) 00494 TIFFSetErrorHandler(NULL); 00495 } 00496 00508 ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags) 00509 { 00510 TIFF *image = NULL; 00511 ImBuf *ibuf = NULL, *hbuf; 00512 ImbTIFFMemFile memFile; 00513 uint32 width, height; 00514 char *format = NULL; 00515 int level; 00516 short spp; 00517 int ib_depth; 00518 00519 /* check whether or not we have a TIFF file */ 00520 if(size < IMB_TIFF_NCB) { 00521 fprintf(stderr, "imb_loadtiff: size < IMB_TIFF_NCB\n"); 00522 return NULL; 00523 } 00524 if(imb_is_a_tiff(mem) == 0) 00525 return NULL; 00526 00527 image = imb_tiff_client_open(&memFile, mem, size); 00528 00529 if(image == NULL) { 00530 printf("imb_loadtiff: could not open TIFF IO layer.\n"); 00531 return NULL; 00532 } 00533 00534 /* allocate the image buffer */ 00535 TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width); 00536 TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height); 00537 TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); 00538 00539 ib_depth = (spp==3)?24:32; 00540 00541 ibuf = IMB_allocImBuf(width, height, ib_depth, 0); 00542 if(ibuf) { 00543 ibuf->ftype = TIF; 00544 } 00545 else { 00546 fprintf(stderr, 00547 "imb_loadtiff: could not allocate memory for TIFF " \ 00548 "image.\n"); 00549 TIFFClose(image); 00550 return NULL; 00551 } 00552 00553 /* if testing, we're done */ 00554 if(flags & IB_test) { 00555 TIFFClose(image); 00556 return ibuf; 00557 } 00558 00559 /* detect if we are reading a tiled/mipmapped texture, in that case 00560 we don't read pixels but leave it to the cache to load tiles */ 00561 if(flags & IB_tilecache) { 00562 format= NULL; 00563 TIFFGetField(image, TIFFTAG_PIXAR_TEXTUREFORMAT, &format); 00564 00565 if(format && strcmp(format, "Plain Texture")==0 && TIFFIsTiled(image)) { 00566 int numlevel = TIFFNumberOfDirectories(image); 00567 00568 /* create empty mipmap levels in advance */ 00569 for(level=0; level<numlevel; level++) { 00570 if(!TIFFSetDirectory(image, level)) 00571 break; 00572 00573 if(level > 0) { 00574 width= (width > 1)? width/2: 1; 00575 height= (height > 1)? height/2: 1; 00576 00577 hbuf= IMB_allocImBuf(width, height, 32, 0); 00578 hbuf->miplevel= level; 00579 hbuf->ftype= ibuf->ftype; 00580 ibuf->mipmap[level-1] = hbuf; 00581 00582 if(flags & IB_premul) 00583 hbuf->flags |= IB_premul; 00584 } 00585 else 00586 hbuf= ibuf; 00587 00588 hbuf->flags |= IB_tilecache; 00589 00590 TIFFGetField(image, TIFFTAG_TILEWIDTH, &hbuf->tilex); 00591 TIFFGetField(image, TIFFTAG_TILELENGTH, &hbuf->tiley); 00592 00593 hbuf->xtiles= ceil(hbuf->x/(float)hbuf->tilex); 00594 hbuf->ytiles= ceil(hbuf->y/(float)hbuf->tiley); 00595 00596 imb_addtilesImBuf(hbuf); 00597 00598 ibuf->miptot++; 00599 } 00600 } 00601 } 00602 00603 /* read pixels */ 00604 if(!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image, 0)) { 00605 fprintf(stderr, "imb_loadtiff: Failed to read tiff image.\n"); 00606 TIFFClose(image); 00607 return NULL; 00608 } 00609 00610 /* close the client layer interface to the in-memory file */ 00611 TIFFClose(image); 00612 00613 /* return successfully */ 00614 return ibuf; 00615 } 00616 00617 void imb_loadtiletiff(ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect) 00618 { 00619 TIFF *image = NULL; 00620 uint32 width, height; 00621 ImbTIFFMemFile memFile; 00622 00623 image = imb_tiff_client_open(&memFile, mem, size); 00624 00625 if(image == NULL) { 00626 printf("imb_loadtiff: could not open TIFF IO layer for loading mipmap level.\n"); 00627 return; 00628 } 00629 00630 if(TIFFSetDirectory(image, ibuf->miplevel)) { /* allocate the image buffer */ 00631 TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width); 00632 TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height); 00633 00634 if(width == ibuf->x && height == ibuf->y) { 00635 if(rect) { 00636 /* tiff pixels are bottom to top, tiles are top to bottom */ 00637 if(TIFFReadRGBATile(image, tx*ibuf->tilex, (ibuf->ytiles - 1 - ty)*ibuf->tiley, rect) == 1) { 00638 if(ibuf->tiley > ibuf->y) 00639 memmove(rect, rect+ibuf->tilex*(ibuf->tiley - ibuf->y), sizeof(int)*ibuf->tilex*ibuf->y); 00640 00641 if(ibuf->flags & IB_premul) 00642 IMB_premultiply_rect(rect, 32, ibuf->tilex, ibuf->tiley); 00643 } 00644 else 00645 printf("imb_loadtiff: failed to read tiff tile at mipmap level %d\n", ibuf->miplevel); 00646 } 00647 } 00648 else 00649 printf("imb_loadtiff: mipmap level %d has unexpected size %dx%d instead of %dx%d\n", ibuf->miplevel, width, height, ibuf->x, ibuf->y); 00650 } 00651 else 00652 printf("imb_loadtiff: could not find mipmap level %d\n", ibuf->miplevel); 00653 00654 /* close the client layer interface to the in-memory file */ 00655 TIFFClose(image); 00656 } 00657 00674 int imb_savetiff(ImBuf *ibuf, const char *name, int flags) 00675 { 00676 TIFF *image = NULL; 00677 uint16 samplesperpixel, bitspersample; 00678 size_t npixels; 00679 unsigned char *pixels = NULL; 00680 unsigned char *from = NULL, *to = NULL; 00681 unsigned short *pixels16 = NULL, *to16 = NULL; 00682 float *fromf = NULL; 00683 float xres, yres; 00684 int x, y, from_i, to_i, i; 00685 int extraSampleTypes[1] = { EXTRASAMPLE_ASSOCALPHA }; 00686 00687 00688 /* check for a valid number of bytes per pixel. Like the PNG writer, 00689 * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding 00690 * to gray, RGB, RGBA respectively. */ 00691 samplesperpixel = (uint16)((ibuf->depth + 7) >> 3); 00692 if((samplesperpixel > 4) || (samplesperpixel == 2)) { 00693 fprintf(stderr, 00694 "imb_savetiff: unsupported number of bytes per " 00695 "pixel: %d\n", samplesperpixel); 00696 return (0); 00697 } 00698 00699 if((ibuf->ftype & TIF_16BIT) && ibuf->rect_float) 00700 bitspersample = 16; 00701 else 00702 bitspersample = 8; 00703 00704 /* open TIFF file for writing */ 00705 if(flags & IB_mem) { 00706 /* bork at the creation of a TIFF in memory */ 00707 fprintf(stderr, 00708 "imb_savetiff: creation of in-memory TIFF files is " 00709 "not yet supported.\n"); 00710 return (0); 00711 } 00712 else { 00713 /* create image as a file */ 00714 image = TIFFOpen(name, "w"); 00715 } 00716 if(image == NULL) { 00717 fprintf(stderr, 00718 "imb_savetiff: could not open TIFF for writing.\n"); 00719 return (0); 00720 } 00721 00722 /* allocate array for pixel data */ 00723 npixels = ibuf->x * ibuf->y; 00724 if(bitspersample == 16) 00725 pixels16 = (unsigned short*)_TIFFmalloc(npixels * 00726 samplesperpixel * sizeof(unsigned short)); 00727 else 00728 pixels = (unsigned char*)_TIFFmalloc(npixels * 00729 samplesperpixel * sizeof(unsigned char)); 00730 00731 if(pixels == NULL && pixels16 == NULL) { 00732 fprintf(stderr, 00733 "imb_savetiff: could not allocate pixels array.\n"); 00734 TIFFClose(image); 00735 return (0); 00736 } 00737 00738 /* setup pointers */ 00739 if(bitspersample == 16) { 00740 fromf = ibuf->rect_float; 00741 to16 = pixels16; 00742 } 00743 else { 00744 from = (unsigned char*)ibuf->rect; 00745 to = pixels; 00746 } 00747 00748 /* setup samples per pixel */ 00749 TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample); 00750 TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); 00751 00752 if(samplesperpixel == 4) { 00753 /* RGBA images */ 00754 TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, 00755 extraSampleTypes); 00756 TIFFSetField(image, TIFFTAG_PHOTOMETRIC, 00757 PHOTOMETRIC_RGB); 00758 } 00759 else if(samplesperpixel == 3) { 00760 /* RGB images */ 00761 TIFFSetField(image, TIFFTAG_PHOTOMETRIC, 00762 PHOTOMETRIC_RGB); 00763 } 00764 else if(samplesperpixel == 1) { 00765 /* greyscale images, 1 channel */ 00766 TIFFSetField(image, TIFFTAG_PHOTOMETRIC, 00767 PHOTOMETRIC_MINISBLACK); 00768 } 00769 00770 /* copy pixel data. While copying, we flip the image vertically. */ 00771 for(x = 0; x < ibuf->x; x++) { 00772 for(y = 0; y < ibuf->y; y++) { 00773 from_i = 4*(y*ibuf->x+x); 00774 to_i = samplesperpixel*((ibuf->y-y-1)*ibuf->x+x); 00775 00776 if(pixels16) { 00777 /* convert from float source */ 00778 float rgb[3]; 00779 00780 if (ibuf->profile == IB_PROFILE_LINEAR_RGB) 00781 linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]); 00782 else 00783 copy_v3_v3(rgb, &fromf[from_i]); 00784 00785 to16[to_i+0] = FTOUSHORT(rgb[0]); 00786 to16[to_i+1] = FTOUSHORT(rgb[1]); 00787 to16[to_i+2] = FTOUSHORT(rgb[2]); 00788 to_i += 3; from_i+=3; 00789 00790 if (samplesperpixel == 4) { 00791 to16[to_i+3] = FTOUSHORT(fromf[from_i+3]); 00792 /*to_i++; from_i++;*/ /*unused, set on each loop */ 00793 } 00794 } 00795 else { 00796 for(i = 0; i < samplesperpixel; i++, to_i++, from_i++) 00797 to[to_i] = from[from_i]; 00798 } 00799 } 00800 } 00801 00802 /* write the actual TIFF file */ 00803 TIFFSetField(image, TIFFTAG_IMAGEWIDTH, ibuf->x); 00804 TIFFSetField(image, TIFFTAG_IMAGELENGTH, ibuf->y); 00805 TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, ibuf->y); 00806 TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); 00807 TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); 00808 TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); 00809 00810 00811 if(ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) { 00812 xres= (float)(ibuf->ppm[0] * 0.0254); 00813 yres= (float)(ibuf->ppm[1] * 0.0254); 00814 } 00815 else { 00816 xres= yres= 150.0f; 00817 } 00818 00819 TIFFSetField(image, TIFFTAG_XRESOLUTION, xres); 00820 TIFFSetField(image, TIFFTAG_YRESOLUTION, yres); 00821 TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); 00822 if(TIFFWriteEncodedStrip(image, 0, 00823 (bitspersample == 16)? (unsigned char*)pixels16: pixels, 00824 ibuf->x*ibuf->y*samplesperpixel*bitspersample/8) == -1) { 00825 fprintf(stderr, 00826 "imb_savetiff: Could not write encoded TIFF.\n"); 00827 TIFFClose(image); 00828 if(pixels) _TIFFfree(pixels); 00829 if(pixels16) _TIFFfree(pixels16); 00830 return (1); 00831 } 00832 00833 /* close the TIFF file */ 00834 TIFFClose(image); 00835 if(pixels) _TIFFfree(pixels); 00836 if(pixels16) _TIFFfree(pixels16); 00837 return (1); 00838 } 00839 00840 #endif /* WITH_TIFF */