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