ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

tiffformat.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.