Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentiffformat.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2010 Vincent Povirk for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include "config.h" 00020 #include "wine/port.h" 00021 00022 #include <stdarg.h> 00023 #ifdef HAVE_UNISTD_H 00024 #include <unistd.h> 00025 #endif 00026 #ifdef HAVE_TIFFIO_H 00027 #include <tiffio.h> 00028 #endif 00029 00030 #define COBJMACROS 00031 00032 #include "windef.h" 00033 #include "winbase.h" 00034 #include "objbase.h" 00035 #include "wincodec.h" 00036 00037 #include "wincodecs_private.h" 00038 00039 #include "wine/debug.h" 00040 #include "wine/library.h" 00041 00042 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 00043 00044 #ifdef SONAME_LIBTIFF 00045 00046 static CRITICAL_SECTION init_tiff_cs; 00047 static CRITICAL_SECTION_DEBUG init_tiff_cs_debug = 00048 { 00049 0, 0, &init_tiff_cs, 00050 { &init_tiff_cs_debug.ProcessLocksList, 00051 &init_tiff_cs_debug.ProcessLocksList }, 00052 0, 0, { (DWORD_PTR)(__FILE__ ": init_tiff_cs") } 00053 }; 00054 static CRITICAL_SECTION init_tiff_cs = { &init_tiff_cs_debug, -1, 0, 0, 0, 0 }; 00055 00056 static void *libtiff_handle; 00057 #define MAKE_FUNCPTR(f) static typeof(f) * p##f 00058 MAKE_FUNCPTR(TIFFClientOpen); 00059 MAKE_FUNCPTR(TIFFClose); 00060 MAKE_FUNCPTR(TIFFCurrentDirectory); 00061 MAKE_FUNCPTR(TIFFGetField); 00062 MAKE_FUNCPTR(TIFFReadDirectory); 00063 MAKE_FUNCPTR(TIFFReadEncodedStrip); 00064 MAKE_FUNCPTR(TIFFSetDirectory); 00065 #undef MAKE_FUNCPTR 00066 00067 static void *load_libtiff(void) 00068 { 00069 void *result; 00070 00071 EnterCriticalSection(&init_tiff_cs); 00072 00073 if (!libtiff_handle && 00074 (libtiff_handle = wine_dlopen(SONAME_LIBTIFF, RTLD_NOW, NULL, 0)) != NULL) 00075 { 00076 00077 #define LOAD_FUNCPTR(f) \ 00078 if((p##f = wine_dlsym(libtiff_handle, #f, NULL, 0)) == NULL) { \ 00079 ERR("failed to load symbol %s\n", #f); \ 00080 libtiff_handle = NULL; \ 00081 LeaveCriticalSection(&init_tiff_cs); \ 00082 return NULL; \ 00083 } 00084 LOAD_FUNCPTR(TIFFClientOpen); 00085 LOAD_FUNCPTR(TIFFClose); 00086 LOAD_FUNCPTR(TIFFCurrentDirectory); 00087 LOAD_FUNCPTR(TIFFGetField); 00088 LOAD_FUNCPTR(TIFFReadDirectory); 00089 LOAD_FUNCPTR(TIFFReadEncodedStrip); 00090 LOAD_FUNCPTR(TIFFSetDirectory); 00091 #undef LOAD_FUNCPTR 00092 00093 } 00094 00095 result = libtiff_handle; 00096 00097 LeaveCriticalSection(&init_tiff_cs); 00098 return result; 00099 } 00100 00101 static tsize_t tiff_stream_read(thandle_t client_data, tdata_t data, tsize_t size) 00102 { 00103 IStream *stream = (IStream*)client_data; 00104 ULONG bytes_read; 00105 HRESULT hr; 00106 00107 hr = IStream_Read(stream, data, size, &bytes_read); 00108 if (FAILED(hr)) bytes_read = 0; 00109 return bytes_read; 00110 } 00111 00112 static tsize_t tiff_stream_write(thandle_t client_data, tdata_t data, tsize_t size) 00113 { 00114 IStream *stream = (IStream*)client_data; 00115 ULONG bytes_written; 00116 HRESULT hr; 00117 00118 hr = IStream_Write(stream, data, size, &bytes_written); 00119 if (FAILED(hr)) bytes_written = 0; 00120 return bytes_written; 00121 } 00122 00123 static toff_t tiff_stream_seek(thandle_t client_data, toff_t offset, int whence) 00124 { 00125 IStream *stream = (IStream*)client_data; 00126 LARGE_INTEGER move; 00127 DWORD origin; 00128 ULARGE_INTEGER new_position; 00129 HRESULT hr; 00130 00131 move.QuadPart = offset; 00132 switch (whence) 00133 { 00134 case SEEK_SET: 00135 origin = STREAM_SEEK_SET; 00136 break; 00137 case SEEK_CUR: 00138 origin = STREAM_SEEK_CUR; 00139 break; 00140 case SEEK_END: 00141 origin = STREAM_SEEK_END; 00142 break; 00143 default: 00144 ERR("unknown whence value %i\n", whence); 00145 return -1; 00146 } 00147 00148 hr = IStream_Seek(stream, move, origin, &new_position); 00149 if (SUCCEEDED(hr)) return new_position.QuadPart; 00150 else return -1; 00151 } 00152 00153 static int tiff_stream_close(thandle_t client_data) 00154 { 00155 /* Caller is responsible for releasing the stream object. */ 00156 return 0; 00157 } 00158 00159 static toff_t tiff_stream_size(thandle_t client_data) 00160 { 00161 IStream *stream = (IStream*)client_data; 00162 STATSTG statstg; 00163 HRESULT hr; 00164 00165 hr = IStream_Stat(stream, &statstg, STATFLAG_NONAME); 00166 00167 if (SUCCEEDED(hr)) return statstg.cbSize.QuadPart; 00168 else return -1; 00169 } 00170 00171 static int tiff_stream_map(thandle_t client_data, tdata_t *addr, toff_t *size) 00172 { 00173 /* Cannot mmap streams */ 00174 return 0; 00175 } 00176 00177 static void tiff_stream_unmap(thandle_t client_data, tdata_t addr, toff_t size) 00178 { 00179 /* No need to ever do this, since we can't map things. */ 00180 } 00181 00182 static TIFF* tiff_open_stream(IStream *stream, const char *mode) 00183 { 00184 return pTIFFClientOpen("<IStream object>", mode, stream, tiff_stream_read, 00185 tiff_stream_write, tiff_stream_seek, tiff_stream_close, 00186 tiff_stream_size, tiff_stream_map, tiff_stream_unmap); 00187 } 00188 00189 typedef struct { 00190 const IWICBitmapDecoderVtbl *lpVtbl; 00191 LONG ref; 00192 IStream *stream; 00193 CRITICAL_SECTION lock; /* Must be held when tiff is used or initiailzed is set */ 00194 TIFF *tiff; 00195 BOOL initialized; 00196 } TiffDecoder; 00197 00198 typedef struct { 00199 const WICPixelFormatGUID *format; 00200 int bpp; 00201 int indexed; 00202 int reverse_bgr; 00203 UINT width, height; 00204 UINT tile_width, tile_height; 00205 UINT tile_stride; 00206 UINT tile_size; 00207 } tiff_decode_info; 00208 00209 typedef struct { 00210 const IWICBitmapFrameDecodeVtbl *lpVtbl; 00211 LONG ref; 00212 TiffDecoder *parent; 00213 UINT index; 00214 tiff_decode_info decode_info; 00215 INT cached_tile_x, cached_tile_y; 00216 BYTE *cached_tile; 00217 } TiffFrameDecode; 00218 00219 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl; 00220 00221 static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info) 00222 { 00223 uint16 photometric, bps, samples, planar; 00224 int ret; 00225 00226 decode_info->indexed = 0; 00227 decode_info->reverse_bgr = 0; 00228 00229 ret = pTIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric); 00230 if (!ret) 00231 { 00232 WARN("missing PhotometricInterpretation tag\n"); 00233 return E_FAIL; 00234 } 00235 00236 ret = pTIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bps); 00237 if (!ret) bps = 1; 00238 00239 switch(photometric) 00240 { 00241 case 1: /* BlackIsZero */ 00242 decode_info->bpp = bps; 00243 switch (bps) 00244 { 00245 case 1: 00246 decode_info->format = &GUID_WICPixelFormatBlackWhite; 00247 break; 00248 case 4: 00249 decode_info->format = &GUID_WICPixelFormat4bppGray; 00250 break; 00251 case 8: 00252 decode_info->format = &GUID_WICPixelFormat8bppGray; 00253 break; 00254 default: 00255 FIXME("unhandled greyscale bit count %u\n", bps); 00256 return E_FAIL; 00257 } 00258 break; 00259 case 2: /* RGB */ 00260 if (bps != 8) 00261 { 00262 FIXME("unhandled RGB bit count %u\n", bps); 00263 return E_FAIL; 00264 } 00265 ret = pTIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples); 00266 if (samples != 3) 00267 { 00268 FIXME("unhandled RGB sample count %u\n", samples); 00269 return E_FAIL; 00270 } 00271 ret = pTIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &planar); 00272 if (!ret) planar = 1; 00273 if (planar != 1) 00274 { 00275 FIXME("unhandled planar configuration %u\n", planar); 00276 return E_FAIL; 00277 } 00278 decode_info->bpp = bps * samples; 00279 decode_info->reverse_bgr = 1; 00280 decode_info->format = &GUID_WICPixelFormat24bppBGR; 00281 break; 00282 case 3: /* RGB Palette */ 00283 decode_info->indexed = 1; 00284 decode_info->bpp = bps; 00285 switch (bps) 00286 { 00287 case 4: 00288 decode_info->format = &GUID_WICPixelFormat4bppIndexed; 00289 break; 00290 case 8: 00291 decode_info->format = &GUID_WICPixelFormat8bppIndexed; 00292 break; 00293 default: 00294 FIXME("unhandled indexed bit count %u\n", bps); 00295 return E_FAIL; 00296 } 00297 break; 00298 case 0: /* WhiteIsZero */ 00299 case 4: /* Transparency mask */ 00300 case 5: /* CMYK */ 00301 case 6: /* YCbCr */ 00302 case 8: /* CIELab */ 00303 default: 00304 FIXME("unhandled PhotometricInterpretation %u\n", photometric); 00305 return E_FAIL; 00306 } 00307 00308 ret = pTIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &decode_info->width); 00309 if (!ret) 00310 { 00311 WARN("missing image width\n"); 00312 return E_FAIL; 00313 } 00314 00315 ret = pTIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &decode_info->height); 00316 if (!ret) 00317 { 00318 WARN("missing image length\n"); 00319 return E_FAIL; 00320 } 00321 00322 ret = pTIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &decode_info->tile_height); 00323 if (ret) 00324 { 00325 decode_info->tile_width = decode_info->width; 00326 decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8); 00327 decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride; 00328 } 00329 else 00330 { 00331 /* Probably a tiled image */ 00332 FIXME("missing RowsPerStrip value\n"); 00333 return E_FAIL; 00334 } 00335 00336 return S_OK; 00337 } 00338 00339 static HRESULT WINAPI TiffDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid, 00340 void **ppv) 00341 { 00342 TiffDecoder *This = (TiffDecoder*)iface; 00343 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 00344 00345 if (!ppv) return E_INVALIDARG; 00346 00347 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid)) 00348 { 00349 *ppv = This; 00350 } 00351 else 00352 { 00353 *ppv = NULL; 00354 return E_NOINTERFACE; 00355 } 00356 00357 IUnknown_AddRef((IUnknown*)*ppv); 00358 return S_OK; 00359 } 00360 00361 static ULONG WINAPI TiffDecoder_AddRef(IWICBitmapDecoder *iface) 00362 { 00363 TiffDecoder *This = (TiffDecoder*)iface; 00364 ULONG ref = InterlockedIncrement(&This->ref); 00365 00366 TRACE("(%p) refcount=%u\n", iface, ref); 00367 00368 return ref; 00369 } 00370 00371 static ULONG WINAPI TiffDecoder_Release(IWICBitmapDecoder *iface) 00372 { 00373 TiffDecoder *This = (TiffDecoder*)iface; 00374 ULONG ref = InterlockedDecrement(&This->ref); 00375 00376 TRACE("(%p) refcount=%u\n", iface, ref); 00377 00378 if (ref == 0) 00379 { 00380 if (This->tiff) pTIFFClose(This->tiff); 00381 if (This->stream) IStream_Release(This->stream); 00382 This->lock.DebugInfo->Spare[0] = 0; 00383 DeleteCriticalSection(&This->lock); 00384 HeapFree(GetProcessHeap(), 0, This); 00385 } 00386 00387 return ref; 00388 } 00389 00390 static HRESULT WINAPI TiffDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream, 00391 DWORD *pdwCapability) 00392 { 00393 FIXME("(%p,%p,%p): stub\n", iface, pIStream, pdwCapability); 00394 return E_NOTIMPL; 00395 } 00396 00397 static HRESULT WINAPI TiffDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream, 00398 WICDecodeOptions cacheOptions) 00399 { 00400 TiffDecoder *This = (TiffDecoder*)iface; 00401 TIFF *tiff; 00402 HRESULT hr=S_OK; 00403 00404 TRACE("(%p,%p,%x): stub\n", iface, pIStream, cacheOptions); 00405 00406 EnterCriticalSection(&This->lock); 00407 00408 if (This->initialized) 00409 { 00410 hr = WINCODEC_ERR_WRONGSTATE; 00411 goto exit; 00412 } 00413 00414 tiff = tiff_open_stream(pIStream, "r"); 00415 00416 if (!tiff) 00417 { 00418 hr = E_FAIL; 00419 goto exit; 00420 } 00421 00422 This->tiff = tiff; 00423 This->stream = pIStream; 00424 IStream_AddRef(pIStream); 00425 This->initialized = TRUE; 00426 00427 exit: 00428 LeaveCriticalSection(&This->lock); 00429 return hr; 00430 } 00431 00432 static HRESULT WINAPI TiffDecoder_GetContainerFormat(IWICBitmapDecoder *iface, 00433 GUID *pguidContainerFormat) 00434 { 00435 memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID)); 00436 return S_OK; 00437 } 00438 00439 static HRESULT WINAPI TiffDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, 00440 IWICBitmapDecoderInfo **ppIDecoderInfo) 00441 { 00442 FIXME("(%p,%p): stub\n", iface, ppIDecoderInfo); 00443 return E_NOTIMPL; 00444 } 00445 00446 static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface, 00447 IWICPalette *pIPalette) 00448 { 00449 FIXME("(%p,%p): stub\n", iface, pIPalette); 00450 return E_NOTIMPL; 00451 } 00452 00453 static HRESULT WINAPI TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface, 00454 IWICMetadataQueryReader **ppIMetadataQueryReader) 00455 { 00456 FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader); 00457 return E_NOTIMPL; 00458 } 00459 00460 static HRESULT WINAPI TiffDecoder_GetPreview(IWICBitmapDecoder *iface, 00461 IWICBitmapSource **ppIBitmapSource) 00462 { 00463 FIXME("(%p,%p): stub\n", iface, ppIBitmapSource); 00464 return E_NOTIMPL; 00465 } 00466 00467 static HRESULT WINAPI TiffDecoder_GetColorContexts(IWICBitmapDecoder *iface, 00468 UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount) 00469 { 00470 FIXME("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount); 00471 return E_NOTIMPL; 00472 } 00473 00474 static HRESULT WINAPI TiffDecoder_GetThumbnail(IWICBitmapDecoder *iface, 00475 IWICBitmapSource **ppIThumbnail) 00476 { 00477 TRACE("(%p,%p)\n", iface, ppIThumbnail); 00478 return WINCODEC_ERR_CODECNOTHUMBNAIL; 00479 } 00480 00481 static HRESULT WINAPI TiffDecoder_GetFrameCount(IWICBitmapDecoder *iface, 00482 UINT *pCount) 00483 { 00484 TiffDecoder *This = (TiffDecoder*)iface; 00485 00486 if (!This->tiff) 00487 { 00488 WARN("(%p) <-- WINCODEC_ERR_WRONGSTATE\n", iface); 00489 return WINCODEC_ERR_WRONGSTATE; 00490 } 00491 00492 EnterCriticalSection(&This->lock); 00493 while (pTIFFReadDirectory(This->tiff)) { } 00494 *pCount = pTIFFCurrentDirectory(This->tiff)+1; 00495 LeaveCriticalSection(&This->lock); 00496 00497 TRACE("(%p) <-- %i\n", iface, *pCount); 00498 00499 return S_OK; 00500 } 00501 00502 static HRESULT WINAPI TiffDecoder_GetFrame(IWICBitmapDecoder *iface, 00503 UINT index, IWICBitmapFrameDecode **ppIBitmapFrame) 00504 { 00505 TiffDecoder *This = (TiffDecoder*)iface; 00506 TiffFrameDecode *result; 00507 int res; 00508 tiff_decode_info decode_info; 00509 HRESULT hr; 00510 00511 TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame); 00512 00513 if (!This->tiff) 00514 return WINCODEC_ERR_WRONGSTATE; 00515 00516 EnterCriticalSection(&This->lock); 00517 res = pTIFFSetDirectory(This->tiff, index); 00518 if (!res) hr = E_INVALIDARG; 00519 else hr = tiff_get_decode_info(This->tiff, &decode_info); 00520 LeaveCriticalSection(&This->lock); 00521 00522 if (SUCCEEDED(hr)) 00523 { 00524 result = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffFrameDecode)); 00525 00526 if (result) 00527 { 00528 result->lpVtbl = &TiffFrameDecode_Vtbl; 00529 result->ref = 1; 00530 result->parent = This; 00531 result->index = index; 00532 result->decode_info = decode_info; 00533 result->cached_tile_x = -1; 00534 result->cached_tile = HeapAlloc(GetProcessHeap(), 0, decode_info.tile_size); 00535 00536 if (result->cached_tile) 00537 *ppIBitmapFrame = (IWICBitmapFrameDecode*)result; 00538 else 00539 { 00540 hr = E_OUTOFMEMORY; 00541 HeapFree(GetProcessHeap(), 0, result); 00542 } 00543 } 00544 else hr = E_OUTOFMEMORY; 00545 } 00546 00547 if (FAILED(hr)) *ppIBitmapFrame = NULL; 00548 00549 return hr; 00550 } 00551 00552 static const IWICBitmapDecoderVtbl TiffDecoder_Vtbl = { 00553 TiffDecoder_QueryInterface, 00554 TiffDecoder_AddRef, 00555 TiffDecoder_Release, 00556 TiffDecoder_QueryCapability, 00557 TiffDecoder_Initialize, 00558 TiffDecoder_GetContainerFormat, 00559 TiffDecoder_GetDecoderInfo, 00560 TiffDecoder_CopyPalette, 00561 TiffDecoder_GetMetadataQueryReader, 00562 TiffDecoder_GetPreview, 00563 TiffDecoder_GetColorContexts, 00564 TiffDecoder_GetThumbnail, 00565 TiffDecoder_GetFrameCount, 00566 TiffDecoder_GetFrame 00567 }; 00568 00569 static HRESULT WINAPI TiffFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid, 00570 void **ppv) 00571 { 00572 TiffFrameDecode *This = (TiffFrameDecode*)iface; 00573 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 00574 00575 if (!ppv) return E_INVALIDARG; 00576 00577 if (IsEqualIID(&IID_IUnknown, iid) || 00578 IsEqualIID(&IID_IWICBitmapSource, iid) || 00579 IsEqualIID(&IID_IWICBitmapFrameDecode, iid)) 00580 { 00581 *ppv = This; 00582 } 00583 else 00584 { 00585 *ppv = NULL; 00586 return E_NOINTERFACE; 00587 } 00588 00589 IUnknown_AddRef((IUnknown*)*ppv); 00590 return S_OK; 00591 } 00592 00593 static ULONG WINAPI TiffFrameDecode_AddRef(IWICBitmapFrameDecode *iface) 00594 { 00595 TiffFrameDecode *This = (TiffFrameDecode*)iface; 00596 ULONG ref = InterlockedIncrement(&This->ref); 00597 00598 TRACE("(%p) refcount=%u\n", iface, ref); 00599 00600 return ref; 00601 } 00602 00603 static ULONG WINAPI TiffFrameDecode_Release(IWICBitmapFrameDecode *iface) 00604 { 00605 TiffFrameDecode *This = (TiffFrameDecode*)iface; 00606 ULONG ref = InterlockedDecrement(&This->ref); 00607 00608 TRACE("(%p) refcount=%u\n", iface, ref); 00609 00610 if (ref == 0) 00611 { 00612 HeapFree(GetProcessHeap(), 0, This->cached_tile); 00613 HeapFree(GetProcessHeap(), 0, This); 00614 } 00615 00616 return ref; 00617 } 00618 00619 static HRESULT WINAPI TiffFrameDecode_GetSize(IWICBitmapFrameDecode *iface, 00620 UINT *puiWidth, UINT *puiHeight) 00621 { 00622 TiffFrameDecode *This = (TiffFrameDecode*)iface; 00623 00624 *puiWidth = This->decode_info.width; 00625 *puiHeight = This->decode_info.height; 00626 00627 TRACE("(%p) <-- %ux%u\n", iface, *puiWidth, *puiHeight); 00628 00629 return S_OK; 00630 } 00631 00632 static HRESULT WINAPI TiffFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface, 00633 WICPixelFormatGUID *pPixelFormat) 00634 { 00635 TiffFrameDecode *This = (TiffFrameDecode*)iface; 00636 00637 memcpy(pPixelFormat, This->decode_info.format, sizeof(GUID)); 00638 00639 TRACE("(%p) <-- %s\n", This, debugstr_guid(This->decode_info.format)); 00640 00641 return S_OK; 00642 } 00643 00644 static HRESULT WINAPI TiffFrameDecode_GetResolution(IWICBitmapFrameDecode *iface, 00645 double *pDpiX, double *pDpiY) 00646 { 00647 FIXME("(%p,%p,%p)\n", iface, pDpiX, pDpiY); 00648 return E_NOTIMPL; 00649 } 00650 00651 static HRESULT WINAPI TiffFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, 00652 IWICPalette *pIPalette) 00653 { 00654 FIXME("(%p,%p)\n", iface, pIPalette); 00655 return E_NOTIMPL; 00656 } 00657 00658 static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT tile_y) 00659 { 00660 HRESULT hr=S_OK; 00661 tsize_t ret; 00662 00663 ret = pTIFFSetDirectory(This->parent->tiff, This->index); 00664 00665 if (ret == -1) 00666 hr = E_FAIL; 00667 00668 if (hr == S_OK) 00669 { 00670 ret = pTIFFReadEncodedStrip(This->parent->tiff, tile_y, This->cached_tile, This->decode_info.tile_size); 00671 00672 if (ret == -1) 00673 hr = E_FAIL; 00674 } 00675 00676 if (hr == S_OK && This->decode_info.reverse_bgr) 00677 { 00678 if (This->decode_info.format == &GUID_WICPixelFormat24bppBGR) 00679 { 00680 UINT i, total_pixels; 00681 BYTE *pixel, temp; 00682 00683 total_pixels = This->decode_info.tile_width * This->decode_info.tile_height; 00684 pixel = This->cached_tile; 00685 for (i=0; i<total_pixels; i++) 00686 { 00687 temp = pixel[2]; 00688 pixel[2] = pixel[0]; 00689 pixel[0] = temp; 00690 pixel += 3; 00691 } 00692 } 00693 } 00694 00695 if (hr == S_OK) 00696 { 00697 This->cached_tile_x = tile_x; 00698 This->cached_tile_y = tile_y; 00699 } 00700 00701 return hr; 00702 } 00703 00704 static HRESULT WINAPI TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface, 00705 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) 00706 { 00707 TiffFrameDecode *This = (TiffFrameDecode*)iface; 00708 UINT min_tile_x, max_tile_x, min_tile_y, max_tile_y; 00709 UINT tile_x, tile_y; 00710 WICRect rc; 00711 HRESULT hr=S_OK; 00712 BYTE *dst_tilepos; 00713 UINT bytesperrow; 00714 00715 TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer); 00716 00717 if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->decode_info.width || 00718 prc->Y+prc->Height > This->decode_info.height) 00719 return E_INVALIDARG; 00720 00721 bytesperrow = ((This->decode_info.bpp * prc->Width)+7)/8; 00722 00723 if (cbStride < bytesperrow) 00724 return E_INVALIDARG; 00725 00726 if ((cbStride * prc->Height) > cbBufferSize) 00727 return E_INVALIDARG; 00728 00729 min_tile_x = prc->X / This->decode_info.tile_width; 00730 min_tile_y = prc->Y / This->decode_info.tile_height; 00731 max_tile_x = (prc->X+prc->Width-1) / This->decode_info.tile_width; 00732 max_tile_y = (prc->Y+prc->Height-1) / This->decode_info.tile_height; 00733 00734 EnterCriticalSection(&This->parent->lock); 00735 00736 for (tile_x=min_tile_x; tile_x <= max_tile_x; tile_x++) 00737 { 00738 for (tile_y=min_tile_y; tile_y <= max_tile_y; tile_y++) 00739 { 00740 if (tile_x != This->cached_tile_x || tile_y != This->cached_tile_y) 00741 { 00742 hr = TiffFrameDecode_ReadTile(This, tile_x, tile_y); 00743 } 00744 00745 if (SUCCEEDED(hr)) 00746 { 00747 if (prc->X < tile_x * This->decode_info.tile_width) 00748 rc.X = 0; 00749 else 00750 rc.X = prc->X - tile_x * This->decode_info.tile_width; 00751 00752 if (prc->Y < tile_y * This->decode_info.tile_height) 00753 rc.Y = 0; 00754 else 00755 rc.Y = prc->Y - tile_y * This->decode_info.tile_height; 00756 00757 if (prc->X+prc->Width > (tile_x+1) * This->decode_info.tile_width) 00758 rc.Width = This->decode_info.tile_width - rc.X; 00759 else if (prc->X < tile_x * This->decode_info.tile_width) 00760 rc.Width = prc->Width + prc->X - tile_x * This->decode_info.tile_width; 00761 else 00762 rc.Width = prc->Width; 00763 00764 if (prc->Y+prc->Height > (tile_y+1) * This->decode_info.tile_height) 00765 rc.Height = This->decode_info.tile_height - rc.Y; 00766 else if (prc->Y < tile_y * This->decode_info.tile_height) 00767 rc.Height = prc->Height + prc->Y - tile_y * This->decode_info.tile_height; 00768 else 00769 rc.Height = prc->Height; 00770 00771 dst_tilepos = pbBuffer + (cbStride * ((rc.Y + tile_y * This->decode_info.tile_height) - prc->Y)) + 00772 ((This->decode_info.bpp * ((rc.X + tile_x * This->decode_info.tile_width) - prc->X) + 7) / 8); 00773 00774 hr = copy_pixels(This->decode_info.bpp, This->cached_tile, 00775 This->decode_info.tile_width, This->decode_info.tile_height, This->decode_info.tile_stride, 00776 &rc, cbStride, cbBufferSize, dst_tilepos); 00777 } 00778 00779 if (FAILED(hr)) 00780 { 00781 LeaveCriticalSection(&This->parent->lock); 00782 TRACE("<-- 0x%x\n", hr); 00783 return hr; 00784 } 00785 } 00786 } 00787 00788 LeaveCriticalSection(&This->parent->lock); 00789 00790 return S_OK; 00791 } 00792 00793 static HRESULT WINAPI TiffFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, 00794 IWICMetadataQueryReader **ppIMetadataQueryReader) 00795 { 00796 FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader); 00797 return E_NOTIMPL; 00798 } 00799 00800 static HRESULT WINAPI TiffFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface, 00801 UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount) 00802 { 00803 FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount); 00804 return E_NOTIMPL; 00805 } 00806 00807 static HRESULT WINAPI TiffFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface, 00808 IWICBitmapSource **ppIThumbnail) 00809 { 00810 FIXME("(%p,%p): stub\n", iface, ppIThumbnail); 00811 return E_NOTIMPL; 00812 } 00813 00814 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl = { 00815 TiffFrameDecode_QueryInterface, 00816 TiffFrameDecode_AddRef, 00817 TiffFrameDecode_Release, 00818 TiffFrameDecode_GetSize, 00819 TiffFrameDecode_GetPixelFormat, 00820 TiffFrameDecode_GetResolution, 00821 TiffFrameDecode_CopyPalette, 00822 TiffFrameDecode_CopyPixels, 00823 TiffFrameDecode_GetMetadataQueryReader, 00824 TiffFrameDecode_GetColorContexts, 00825 TiffFrameDecode_GetThumbnail 00826 }; 00827 00828 HRESULT TiffDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) 00829 { 00830 HRESULT ret; 00831 TiffDecoder *This; 00832 00833 TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv); 00834 00835 *ppv = NULL; 00836 00837 if (pUnkOuter) return CLASS_E_NOAGGREGATION; 00838 00839 if (!load_libtiff()) 00840 { 00841 ERR("Failed reading TIFF because unable to load %s\n",SONAME_LIBTIFF); 00842 return E_FAIL; 00843 } 00844 00845 This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffDecoder)); 00846 if (!This) return E_OUTOFMEMORY; 00847 00848 This->lpVtbl = &TiffDecoder_Vtbl; 00849 This->ref = 1; 00850 This->stream = NULL; 00851 InitializeCriticalSection(&This->lock); 00852 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffDecoder.lock"); 00853 This->tiff = NULL; 00854 This->initialized = FALSE; 00855 00856 ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv); 00857 IUnknown_Release((IUnknown*)This); 00858 00859 return ret; 00860 } 00861 00862 #else /* !SONAME_LIBTIFF */ 00863 00864 HRESULT TiffDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv) 00865 { 00866 ERR("Trying to load TIFF picture, but Wine was compiled without TIFF support.\n"); 00867 return E_FAIL; 00868 } 00869 00870 #endif Generated on Sat May 26 2012 04:25:25 for ReactOS by
1.7.6.1
|