ReactOS  0.4.14-dev-384-g5b37caa
tgaformat.c
Go to the documentation of this file.
1 /*
2  * Copyright 2010 Vincent Povirk for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "config.h"
20 #include "wine/port.h"
21 
22 #include <stdarg.h>
23 
24 #define COBJMACROS
25 
26 #include "windef.h"
27 #include "winbase.h"
28 #include "objbase.h"
29 
30 #include "wincodecs_private.h"
31 
32 #include "wine/debug.h"
33 #include "wine/library.h"
34 
36 
37 #include "pshpack1.h"
38 
39 typedef struct {
43  /* Colormap Specification */
47  /* Image Specification */
54 } tga_header;
55 
56 #define IMAGETYPE_COLORMAPPED 1
57 #define IMAGETYPE_TRUECOLOR 2
58 #define IMAGETYPE_GRAYSCALE 3
59 #define IMAGETYPE_RLE 8
60 
61 #define IMAGE_ATTRIBUTE_BITCOUNT_MASK 0xf
62 #define IMAGE_RIGHTTOLEFT 0x10
63 #define IMAGE_TOPTOBOTTOM 0x20
64 
65 typedef struct {
68  char magic[18];
69 } tga_footer;
70 
71 static const BYTE tga_footer_magic[18] = "TRUEVISION-XFILE.";
72 
73 typedef struct {
75  char author_name[41];
76  char author_comments[324];
78  char job_name[41];
79  WORD job_timestamp[6];
80  char software_id[41];
93 
94 #define ATTRIBUTE_NO_ALPHA 0
95 #define ATTRIBUTE_UNDEFINED 1
96 #define ATTRIBUTE_UNDEFINED_PRESERVE 2
97 #define ATTRIBUTE_ALPHA 3
98 #define ATTRIBUTE_PALPHA 4
99 
100 #include "poppack.h"
101 
102 typedef struct {
112  int stride;
120 } TgaDecoder;
121 
123 {
124  return CONTAINING_RECORD(iface, TgaDecoder, IWICBitmapDecoder_iface);
125 }
126 
128 {
129  return CONTAINING_RECORD(iface, TgaDecoder, IWICBitmapFrameDecode_iface);
130 }
131 
133  void **ppv)
134 {
136  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
137 
138  if (!ppv) return E_INVALIDARG;
139 
140  if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
141  {
142  *ppv = &This->IWICBitmapDecoder_iface;
143  }
144  else
145  {
146  *ppv = NULL;
147  return E_NOINTERFACE;
148  }
149 
150  IUnknown_AddRef((IUnknown*)*ppv);
151  return S_OK;
152 }
153 
155 {
158 
159  TRACE("(%p) refcount=%u\n", iface, ref);
160 
161  return ref;
162 }
163 
165 {
168 
169  TRACE("(%p) refcount=%u\n", iface, ref);
170 
171  if (ref == 0)
172  {
173  This->lock.DebugInfo->Spare[0] = 0;
174  DeleteCriticalSection(&This->lock);
175  if (This->stream)
176  IStream_Release(This->stream);
177  HeapFree(GetProcessHeap(), 0, This->imagebits);
179  }
180 
181  return ref;
182 }
183 
185  DWORD *capability)
186 {
187  HRESULT hr;
188 
189  TRACE("(%p,%p,%p)\n", iface, stream, capability);
190 
191  if (!stream || !capability) return E_INVALIDARG;
192 
193  hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
194  if (hr != S_OK) return hr;
195 
198  return S_OK;
199 }
200 
202  WICDecodeOptions cacheOptions)
203 {
205  HRESULT hr=S_OK;
206  DWORD bytesread;
208  tga_footer footer;
209  int attribute_bitcount;
210  int mapped_depth=0;
211 
212  TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions);
213 
214  EnterCriticalSection(&This->lock);
215 
216  if (This->initialized)
217  {
219  goto end;
220  }
221 
222  seek.QuadPart = 0;
223  hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
224  if (FAILED(hr)) goto end;
225 
226  hr = IStream_Read(pIStream, &This->header, sizeof(tga_header), &bytesread);
227  if (SUCCEEDED(hr) && bytesread != sizeof(tga_header))
228  {
229  TRACE("got only %u bytes\n", bytesread);
230  hr = E_FAIL;
231  }
232  if (FAILED(hr)) goto end;
233 
234  TRACE("imagetype=%u, colormap type=%u, depth=%u, image descriptor=0x%x\n",
235  This->header.image_type, This->header.colormap_type,
236  This->header.depth, This->header.image_descriptor);
237 
238  /* Sanity checking. Since TGA has no clear identifying markers, we need
239  * to be careful to not load a non-TGA image. */
240  switch (This->header.image_type)
241  {
244  if (This->header.colormap_type != 1)
245  hr = E_FAIL;
246  mapped_depth = This->header.colormap_entrysize;
247  break;
248  case IMAGETYPE_TRUECOLOR:
250  if (This->header.colormap_type != 0 && This->header.colormap_type != 1)
251  hr = E_FAIL;
252  mapped_depth = This->header.depth;
253  break;
254  case IMAGETYPE_GRAYSCALE:
256  if (This->header.colormap_type != 0)
257  hr = E_FAIL;
258  mapped_depth = 0;
259  break;
260  default:
261  hr = E_FAIL;
262  }
263 
264  if (This->header.depth != 8 && This->header.depth != 16 &&
265  This->header.depth != 24 && This->header.depth != 32)
266  hr = E_FAIL;
267 
268  if ((This->header.image_descriptor & 0xc0) != 0)
269  hr = E_FAIL;
270 
271  attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;
272 
273  if (attribute_bitcount &&
274  !((mapped_depth == 32 && attribute_bitcount == 8) ||
275  (mapped_depth == 16 && attribute_bitcount == 1)))
276  hr = E_FAIL;
277 
278  if (FAILED(hr))
279  {
280  WARN("bad tga header\n");
281  goto end;
282  }
283 
284  /* Locate data in the file based on the header. */
285  This->id_offset = sizeof(tga_header);
286  This->colormap_offset = This->id_offset + This->header.id_length;
287  if (This->header.colormap_type == 1)
288  This->colormap_length = ((This->header.colormap_entrysize+7)/8) * This->header.colormap_length;
289  else
290  This->colormap_length = 0;
291  This->image_offset = This->colormap_offset + This->colormap_length;
292 
293  /* Read footer if there is one */
294  seek.QuadPart = -(LONGLONG)sizeof(tga_footer);
295  hr = IStream_Seek(pIStream, seek, STREAM_SEEK_END, NULL);
296 
297  if (SUCCEEDED(hr)) {
298  hr = IStream_Read(pIStream, &footer, sizeof(tga_footer), &bytesread);
299  if (SUCCEEDED(hr) && bytesread != sizeof(tga_footer))
300  {
301  TRACE("got only %u footer bytes\n", bytesread);
302  hr = E_FAIL;
303  }
304 
305  if (memcmp(footer.magic, tga_footer_magic, sizeof(tga_footer_magic)) == 0)
306  {
307  This->extension_area_offset = footer.extension_area_offset;
308  This->developer_directory_offset = footer.developer_directory_offset;
309  }
310  else
311  {
312  This->extension_area_offset = 0;
313  This->developer_directory_offset = 0;
314  }
315  }
316  else
317  {
318  /* File is too small to have a footer. */
319  This->extension_area_offset = 0;
320  This->developer_directory_offset = 0;
321  hr = S_OK;
322  }
323 
324  if (This->extension_area_offset)
325  {
326  seek.QuadPart = This->extension_area_offset;
327  hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
328  if (FAILED(hr)) goto end;
329 
330  hr = IStream_Read(pIStream, &This->extension_area, sizeof(tga_extension_area), &bytesread);
331  if (SUCCEEDED(hr) && bytesread != sizeof(tga_extension_area))
332  {
333  TRACE("got only %u extension area bytes\n", bytesread);
334  hr = E_FAIL;
335  }
336  if (SUCCEEDED(hr) && This->extension_area.size < 495)
337  {
338  TRACE("extension area is only %u bytes long\n", This->extension_area.size);
339  hr = E_FAIL;
340  }
341  if (FAILED(hr)) goto end;
342  }
343 
344  IStream_AddRef(pIStream);
345  This->stream = pIStream;
346  This->initialized = TRUE;
347 
348 end:
349  LeaveCriticalSection(&This->lock);
350  return hr;
351 }
352 
354  GUID *pguidContainerFormat)
355 {
356  memcpy(pguidContainerFormat, &GUID_WineContainerFormatTga, sizeof(GUID));
357  return S_OK;
358 }
359 
361  IWICBitmapDecoderInfo **ppIDecoderInfo)
362 {
363  TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
364 
365  return get_decoder_info(&CLSID_WineTgaDecoder, ppIDecoderInfo);
366 }
367 
369  IWICPalette *pIPalette)
370 {
371  FIXME("(%p,%p): stub\n", iface, pIPalette);
372  return E_NOTIMPL;
373 }
374 
376  IWICMetadataQueryReader **ppIMetadataQueryReader)
377 {
378  FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
379  return E_NOTIMPL;
380 }
381 
383  IWICBitmapSource **ppIBitmapSource)
384 {
385  FIXME("(%p,%p): stub\n", iface, ppIBitmapSource);
387 }
388 
390  UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
391 {
392  FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
394 }
395 
397  IWICBitmapSource **ppIThumbnail)
398 {
399  FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
401 }
402 
404  UINT *pCount)
405 {
406  if (!pCount) return E_INVALIDARG;
407 
408  *pCount = 1;
409  return S_OK;
410 }
411 
413  UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
414 {
416  TRACE("(%p,%p)\n", iface, ppIBitmapFrame);
417 
418  if (!This->initialized) return WINCODEC_ERR_FRAMEMISSING;
419 
420  if (index != 0) return E_INVALIDARG;
421 
422  IWICBitmapDecoder_AddRef(iface);
423  *ppIBitmapFrame = &This->IWICBitmapFrameDecode_iface;
424 
425  return S_OK;
426 }
427 
428 static const IWICBitmapDecoderVtbl TgaDecoder_Vtbl = {
443 };
444 
446  void **ppv)
447 {
448  TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
449 
450  if (!ppv) return E_INVALIDARG;
451 
452  if (IsEqualIID(&IID_IUnknown, iid) ||
453  IsEqualIID(&IID_IWICBitmapSource, iid) ||
454  IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
455  {
456  *ppv = iface;
457  }
458  else
459  {
460  *ppv = NULL;
461  return E_NOINTERFACE;
462  }
463 
464  IUnknown_AddRef((IUnknown*)*ppv);
465  return S_OK;
466 }
467 
469 {
471  return IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface);
472 }
473 
475 {
477  return IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
478 }
479 
481  UINT *puiWidth, UINT *puiHeight)
482 {
484 
485  *puiWidth = This->header.width;
486  *puiHeight = This->header.height;
487 
488  TRACE("(%p)->(%u,%u)\n", iface, *puiWidth, *puiHeight);
489 
490  return S_OK;
491 }
492 
494  WICPixelFormatGUID *pPixelFormat)
495 {
497  int attribute_bitcount;
498  byte attribute_type;
499 
500  TRACE("(%p,%p)\n", iface, pPixelFormat);
501 
502  attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;
503 
504  if (attribute_bitcount && This->extension_area_offset)
505  attribute_type = This->extension_area.attributes_type;
506  else if (attribute_bitcount)
507  attribute_type = ATTRIBUTE_ALPHA;
508  else
509  attribute_type = ATTRIBUTE_NO_ALPHA;
510 
511  switch (This->header.image_type & ~IMAGETYPE_RLE)
512  {
514  switch (This->header.depth)
515  {
516  case 8:
517  memcpy(pPixelFormat, &GUID_WICPixelFormat8bppIndexed, sizeof(GUID));
518  break;
519  default:
520  FIXME("Unhandled indexed color depth %u\n", This->header.depth);
521  return E_NOTIMPL;
522  }
523  break;
524  case IMAGETYPE_TRUECOLOR:
525  switch (This->header.depth)
526  {
527  case 16:
528  switch (attribute_type)
529  {
530  case ATTRIBUTE_NO_ALPHA:
531  case ATTRIBUTE_UNDEFINED:
533  memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGR555, sizeof(GUID));
534  break;
535  case ATTRIBUTE_ALPHA:
536  case ATTRIBUTE_PALPHA:
537  memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGRA5551, sizeof(GUID));
538  break;
539  default:
540  FIXME("Unhandled 16-bit attribute type %u\n", attribute_type);
541  return E_NOTIMPL;
542  }
543  break;
544  case 24:
545  memcpy(pPixelFormat, &GUID_WICPixelFormat24bppBGR, sizeof(GUID));
546  break;
547  case 32:
548  switch (attribute_type)
549  {
550  case ATTRIBUTE_NO_ALPHA:
551  case ATTRIBUTE_UNDEFINED:
553  memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGR, sizeof(GUID));
554  break;
555  case ATTRIBUTE_ALPHA:
556  memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID));
557  break;
558  case ATTRIBUTE_PALPHA:
559  memcpy(pPixelFormat, &GUID_WICPixelFormat32bppPBGRA, sizeof(GUID));
560  break;
561  default:
562  FIXME("Unhandled 32-bit attribute type %u\n", attribute_type);
563  return E_NOTIMPL;
564  }
565  break;
566  default:
567  FIXME("Unhandled truecolor depth %u\n", This->header.depth);
568  return E_NOTIMPL;
569  }
570  break;
571  case IMAGETYPE_GRAYSCALE:
572  switch (This->header.depth)
573  {
574  case 8:
575  memcpy(pPixelFormat, &GUID_WICPixelFormat8bppGray, sizeof(GUID));
576  break;
577  case 16:
578  memcpy(pPixelFormat, &GUID_WICPixelFormat16bppGray, sizeof(GUID));
579  break;
580  default:
581  FIXME("Unhandled grayscale depth %u\n", This->header.depth);
582  return E_NOTIMPL;
583  }
584  break;
585  default:
586  ERR("Unknown image type %u\n", This->header.image_type);
587  return E_FAIL;
588  }
589 
590  return S_OK;
591 }
592 
594  double *pDpiX, double *pDpiY)
595 {
596  FIXME("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
597  return E_NOTIMPL;
598 }
599 
601  IWICPalette *pIPalette)
602 {
604  HRESULT hr=S_OK;
605  WICColor colors[256], *color;
606  BYTE *colormap_data;
607  WORD *wcolormap_data;
608  DWORD *dwcolormap_data;
610  ULONG bytesread;
611  int depth, attribute_bitcount, attribute_type;
612  int i;
613 
614  TRACE("(%p,%p)\n", iface, pIPalette);
615 
616  if (!This->colormap_length)
617  {
618  WARN("no colormap present in this file\n");
620  }
621 
622  if (This->header.colormap_firstentry + This->header.colormap_length > 256)
623  {
624  FIXME("cannot read colormap with %i entries starting at %i\n",
625  This->header.colormap_firstentry + This->header.colormap_length,
626  This->header.colormap_firstentry);
627  return E_FAIL;
628  }
629 
630  colormap_data = HeapAlloc(GetProcessHeap(), 0, This->colormap_length);
631  if (!colormap_data) return E_OUTOFMEMORY;
632 
633  wcolormap_data = (WORD*)colormap_data;
634  dwcolormap_data = (DWORD*)colormap_data;
635 
636  EnterCriticalSection(&This->lock);
637 
638  seek.QuadPart = This->colormap_offset;
639  hr = IStream_Seek(This->stream, seek, STREAM_SEEK_SET, NULL);
640 
641  if (SUCCEEDED(hr))
642  {
643  hr = IStream_Read(This->stream, colormap_data, This->colormap_length, &bytesread);
644  if (SUCCEEDED(hr) && bytesread != This->colormap_length)
645  {
646  WARN("expected %i bytes in colormap, got %i\n", This->colormap_length, bytesread);
647  hr = E_FAIL;
648  }
649  }
650 
651  LeaveCriticalSection(&This->lock);
652 
653  if (SUCCEEDED(hr))
654  {
655  attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;
656 
657  if (attribute_bitcount && This->extension_area_offset)
658  attribute_type = This->extension_area.attributes_type;
659  else if (attribute_bitcount)
660  attribute_type = ATTRIBUTE_ALPHA;
661  else
662  attribute_type = ATTRIBUTE_NO_ALPHA;
663 
664  depth = This->header.colormap_entrysize;
665  if (depth == 15)
666  {
667  depth = 16;
668  attribute_type = ATTRIBUTE_NO_ALPHA;
669  }
670 
671  memset(colors, 0, sizeof(colors));
672 
673  color = &colors[This->header.colormap_firstentry];
674 
675  /* Colormap entries can be in any truecolor format, and we have to convert them. */
676  switch (depth)
677  {
678  case 16:
679  switch (attribute_type)
680  {
681  case ATTRIBUTE_NO_ALPHA:
682  case ATTRIBUTE_UNDEFINED:
684  for (i=0; i<This->header.colormap_length; i++)
685  {
686  WORD srcval = wcolormap_data[i];
687  *color++=0xff000000 | /* constant 255 alpha */
688  ((srcval << 9) & 0xf80000) | /* r */
689  ((srcval << 4) & 0x070000) | /* r - 3 bits */
690  ((srcval << 6) & 0x00f800) | /* g */
691  ((srcval << 1) & 0x000700) | /* g - 3 bits */
692  ((srcval << 3) & 0x0000f8) | /* b */
693  ((srcval >> 2) & 0x000007); /* b - 3 bits */
694  }
695  break;
696  case ATTRIBUTE_ALPHA:
697  case ATTRIBUTE_PALPHA:
698  for (i=0; i<This->header.colormap_length; i++)
699  {
700  WORD srcval = wcolormap_data[i];
701  *color++=((srcval & 0x8000) ? 0xff000000 : 0) | /* alpha */
702  ((srcval << 9) & 0xf80000) | /* r */
703  ((srcval << 4) & 0x070000) | /* r - 3 bits */
704  ((srcval << 6) & 0x00f800) | /* g */
705  ((srcval << 1) & 0x000700) | /* g - 3 bits */
706  ((srcval << 3) & 0x0000f8) | /* b */
707  ((srcval >> 2) & 0x000007); /* b - 3 bits */
708  }
709  break;
710  default:
711  FIXME("Unhandled 16-bit attribute type %u\n", attribute_type);
712  hr = E_NOTIMPL;
713  }
714  break;
715  case 24:
716  for (i=0; i<This->header.colormap_length; i++)
717  {
718  *color++=0xff000000 | /* alpha */
719  colormap_data[i*3+2] | /* red */
720  colormap_data[i*3+1] | /* green */
721  colormap_data[i*3]; /* blue */
722  }
723  break;
724  case 32:
725  switch (attribute_type)
726  {
727  case ATTRIBUTE_NO_ALPHA:
728  case ATTRIBUTE_UNDEFINED:
730  for (i=0; i<This->header.colormap_length; i++)
731  *color++=dwcolormap_data[i]|0xff000000;
732  break;
733  case ATTRIBUTE_ALPHA:
734  for (i=0; i<This->header.colormap_length; i++)
735  *color++=dwcolormap_data[i];
736  break;
737  case ATTRIBUTE_PALPHA:
738  /* FIXME: Unpremultiply alpha */
739  default:
740  FIXME("Unhandled 16-bit attribute type %u\n", attribute_type);
741  hr = E_NOTIMPL;
742  }
743  break;
744  default:
745  FIXME("Unhandled truecolor depth %u\n", This->header.depth);
746  hr = E_NOTIMPL;
747  }
748  }
749 
750  HeapFree(GetProcessHeap(), 0, colormap_data);
751 
752  if (SUCCEEDED(hr))
753  hr = IWICPalette_InitializeCustom(pIPalette, colors, 256);
754 
755  return hr;
756 }
757 
759 {
760  int i=0, j, bytesperpixel;
761  ULONG bytesread;
762  HRESULT hr=S_OK;
763 
764  bytesperpixel = This->header.depth / 8;
765 
766  while (i<datasize)
767  {
768  BYTE rc;
769  int count, size;
770  BYTE pixeldata[4];
771 
772  hr = IStream_Read(This->stream, &rc, 1, &bytesread);
773  if (bytesread != 1) hr = E_FAIL;
774  if (FAILED(hr)) break;
775 
776  count = (rc&0x7f)+1;
777  size = count * bytesperpixel;
778 
779  if (size + i > datasize)
780  {
781  WARN("RLE packet too large\n");
782  hr = E_FAIL;
783  break;
784  }
785 
786  if (rc&0x80)
787  {
788  /* Run-length packet */
789  hr = IStream_Read(This->stream, pixeldata, bytesperpixel, &bytesread);
790  if (bytesread != bytesperpixel) hr = E_FAIL;
791  if (FAILED(hr)) break;
792 
793  if (bytesperpixel == 1)
794  memset(&imagebits[i], pixeldata[0], count);
795  else
796  {
797  for (j=0; j<count; j++)
798  memcpy(&imagebits[i+j*bytesperpixel], pixeldata, bytesperpixel);
799  }
800  }
801  else
802  {
803  /* Raw packet */
804  hr = IStream_Read(This->stream, &imagebits[i], size, &bytesread);
805  if (bytesread != size) hr = E_FAIL;
806  if (FAILED(hr)) break;
807  }
808 
809  i += size;
810  }
811 
812  return hr;
813 }
814 
816 {
817  HRESULT hr=S_OK;
818  int datasize;
820  ULONG bytesread;
821 
822  if (This->imagebits)
823  return S_OK;
824 
825  EnterCriticalSection(&This->lock);
826 
827  if (!This->imagebits)
828  {
829  if (This->header.image_descriptor & IMAGE_RIGHTTOLEFT)
830  {
831  FIXME("Right to left image reading not implemented\n");
832  hr = E_NOTIMPL;
833  }
834 
835  if (SUCCEEDED(hr))
836  {
837  datasize = This->header.width * This->header.height * (This->header.depth / 8);
838  This->imagebits = HeapAlloc(GetProcessHeap(), 0, datasize);
839  if (!This->imagebits) hr = E_OUTOFMEMORY;
840  }
841 
842  if (SUCCEEDED(hr))
843  {
844  seek.QuadPart = This->image_offset;
845  hr = IStream_Seek(This->stream, seek, STREAM_SEEK_SET, NULL);
846  }
847 
848  if (SUCCEEDED(hr))
849  {
850  if (This->header.image_type & IMAGETYPE_RLE)
851  {
852  hr = TgaDecoder_ReadRLE(This, This->imagebits, datasize);
853  }
854  else
855  {
856  hr = IStream_Read(This->stream, This->imagebits, datasize, &bytesread);
857  if (SUCCEEDED(hr) && bytesread != datasize)
858  hr = E_FAIL;
859  }
860  }
861 
862  if (SUCCEEDED(hr))
863  {
864  if (This->header.image_descriptor & IMAGE_TOPTOBOTTOM)
865  {
866  This->origin = This->imagebits;
867  This->stride = This->header.width * (This->header.depth / 8);
868  }
869  else
870  {
871  This->stride = -This->header.width * (This->header.depth / 8);
872  This->origin = This->imagebits + This->header.width * (This->header.height - 1) * (This->header.depth / 8);
873  }
874  }
875  else
876  {
877  HeapFree(GetProcessHeap(), 0, This->imagebits);
878  This->imagebits = NULL;
879  }
880  }
881 
882  LeaveCriticalSection(&This->lock);
883 
884  return hr;
885 }
886 
888  const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
889 {
891  HRESULT hr;
892 
893  TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
894 
896 
897  if (SUCCEEDED(hr))
898  {
899  hr = copy_pixels(This->header.depth, This->origin,
900  This->header.width, This->header.height, This->stride,
901  prc, cbStride, cbBufferSize, pbBuffer);
902  }
903 
904  return hr;
905 }
906 
908  IWICMetadataQueryReader **ppIMetadataQueryReader)
909 {
910  FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
912 }
913 
915  UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
916 {
917  FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
919 }
920 
922  IWICBitmapSource **ppIThumbnail)
923 {
924  FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
926 }
927 
928 static const IWICBitmapFrameDecodeVtbl TgaDecoder_Frame_Vtbl = {
940 };
941 
943 {
944  TgaDecoder *This;
945  HRESULT ret;
946 
947  TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
948 
949  *ppv = NULL;
950 
951  This = HeapAlloc(GetProcessHeap(), 0, sizeof(TgaDecoder));
952  if (!This) return E_OUTOFMEMORY;
953 
954  This->IWICBitmapDecoder_iface.lpVtbl = &TgaDecoder_Vtbl;
955  This->IWICBitmapFrameDecode_iface.lpVtbl = &TgaDecoder_Frame_Vtbl;
956  This->ref = 1;
957  This->initialized = FALSE;
958  This->stream = NULL;
959  This->imagebits = NULL;
961  This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TgaDecoder.lock");
962 
963  ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
964  IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
965 
966  return ret;
967 }
static HRESULT WINAPI TgaDecoder_GetColorContexts(IWICBitmapDecoder *iface, UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
Definition: tgaformat.c:389
#define ATTRIBUTE_UNDEFINED_PRESERVE
Definition: tgaformat.c:96
#define IMAGETYPE_RLE
Definition: tgaformat.c:59
static ULONG WINAPI TgaDecoder_Frame_Release(IWICBitmapFrameDecode *iface)
Definition: tgaformat.c:474
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
WORD xorigin
Definition: tgaformat.c:48
#define E_NOINTERFACE
Definition: winerror.h:2364
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static HRESULT WINAPI TgaDecoder_GetContainerFormat(IWICBitmapDecoder *iface, GUID *pguidContainerFormat)
Definition: tgaformat.c:353
static SIZE_T datasize
Definition: asm.c:30
#define ATTRIBUTE_ALPHA
Definition: tgaformat.c:97
#define DWORD_PTR
Definition: treelist.c:76
static HRESULT WINAPI TgaDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface, IWICPalette *pIPalette)
Definition: tgaformat.c:600
HRESULT hr
Definition: shlfolder.c:183
static HRESULT WINAPI TgaDecoder_Frame_GetThumbnail(IWICBitmapFrameDecode *iface, IWICBitmapSource **ppIThumbnail)
Definition: tgaformat.c:921
static HRESULT WINAPI TgaDecoder_Frame_GetPixelFormat(IWICBitmapFrameDecode *iface, WICPixelFormatGUID *pPixelFormat)
Definition: tgaformat.c:493
static HRESULT WINAPI TgaDecoder_Frame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid, void **ppv)
Definition: tgaformat.c:445
ULONG colormap_length
Definition: tgaformat.c:114
static HRESULT TgaDecoder_ReadImage(TgaDecoder *This)
Definition: tgaformat.c:815
ULONG developer_directory_offset
Definition: tgaformat.c:118
BYTE * origin
Definition: tgaformat.c:111
GLuint GLuint GLsizei count
Definition: gl.h:1545
static const IWICBitmapDecoderVtbl TgaDecoder_Vtbl
Definition: tgaformat.c:428
#define WARN(fmt,...)
Definition: debug.h:111
DWORD thumbnail_offset
Definition: tgaformat.c:89
static HRESULT WINAPI TgaDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface, IWICMetadataQueryReader **ppIMetadataQueryReader)
Definition: tgaformat.c:375
REFIID LPVOID * ppv
Definition: atlbase.h:39
u32_t magic(void)
static HRESULT WINAPI TgaDecoder_GetFrameCount(IWICBitmapDecoder *iface, UINT *pCount)
Definition: tgaformat.c:403
WORD colormap_firstentry
Definition: tgaformat.c:44
ULONG id_offset
Definition: tgaformat.c:113
GLuint GLuint end
Definition: gl.h:1545
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
static ULONG WINAPI TgaDecoder_Frame_AddRef(IWICBitmapFrameDecode *iface)
Definition: tgaformat.c:468
#define E_FAIL
Definition: ddrawi.h:102
Definition: send.c:47
char software_version_letter
Definition: tgaformat.c:82
DWORD scanline_offset
Definition: tgaformat.c:90
DWORD color_correction_offset
Definition: tgaformat.c:88
BYTE colormap_type
Definition: tgaformat.c:41
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
GLuint color
Definition: glext.h:6243
static HRESULT WINAPI TgaDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream, WICDecodeOptions cacheOptions)
Definition: tgaformat.c:201
ULONG extension_area_offset
Definition: tgaformat.c:117
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:110
#define E_INVALIDARG
Definition: ddrawi.h:101
#define WINCODEC_ERR_PALETTEUNAVAILABLE
Definition: winerror.h:3284
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
smooth NULL
Definition: ftsmooth.c:416
static TgaDecoder * impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
Definition: tgaformat.c:127
GLuint index
Definition: glext.h:6031
static HRESULT WINAPI TgaDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid, void **ppv)
Definition: tgaformat.c:132
#define debugstr_guid
Definition: kernel32.h:35
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
int64_t LONGLONG
Definition: typedefs.h:66
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static HRESULT WINAPI TgaDecoder_GetThumbnail(IWICBitmapDecoder *iface, IWICBitmapSource **ppIThumbnail)
Definition: tgaformat.c:396
static HRESULT WINAPI TgaDecoder_Frame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, IWICMetadataQueryReader **ppIMetadataQueryReader)
Definition: tgaformat.c:907
static TgaDecoder * impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
Definition: tgaformat.c:122
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
LONG HRESULT
Definition: typedefs.h:77
const GUID IID_IUnknown
BYTE image_descriptor
Definition: tgaformat.c:53
#define ATTRIBUTE_UNDEFINED
Definition: tgaformat.c:95
#define WINAPI
Definition: msvc.h:8
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs)
#define IMAGETYPE_COLORMAPPED
Definition: tgaformat.c:56
WORD height
Definition: tgaformat.c:51
static ULONG WINAPI TgaDecoder_Release(IWICBitmapDecoder *iface)
Definition: tgaformat.c:164
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
#define IMAGE_ATTRIBUTE_BITCOUNT_MASK
Definition: tgaformat.c:61
#define WINCODEC_ERR_CODECNOTHUMBNAIL
Definition: winerror.h:3283
static HRESULT TgaDecoder_ReadRLE(TgaDecoder *This, BYTE *imagebits, int datasize)
Definition: tgaformat.c:758
static HRESULT WINAPI TgaDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *iface, UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
Definition: tgaformat.c:914
int seek(void *fd, ulong off, int mode)
Definition: pe.c:51
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
int ret
#define WINCODEC_ERR_FRAMEMISSING
Definition: winerror.h:3293
IWICBitmapFrameDecode IWICBitmapFrameDecode_iface
Definition: tgaformat.c:104
WORD yorigin
Definition: tgaformat.c:49
BYTE image_type
Definition: tgaformat.c:42
#define InterlockedDecrement
Definition: armddk.h:52
Definition: parse.h:22
static const char * debug_wic_rect(const WICRect *rect)
#define ATTRIBUTE_NO_ALPHA
Definition: tgaformat.c:94
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned char BYTE
Definition: mem.h:68
#define IMAGE_TOPTOBOTTOM
Definition: tgaformat.c:63
#define WINCODEC_ERR_UNSUPPORTEDOPERATION
Definition: winerror.h:3300
void copy_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pitch, BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *size, const struct pixel_format_desc *format) DECLSPEC_HIDDEN
Definition: surface.c:1601
#define IMAGETYPE_TRUECOLOR
Definition: tgaformat.c:57
#define IMAGETYPE_GRAYSCALE
Definition: tgaformat.c:58
#define ERR(fmt,...)
Definition: debug.h:109
WICDecodeOptions
Definition: wincodec.idl:27
tga_extension_area extension_area
Definition: tgaformat.c:109
tga_header header
Definition: tgaformat.c:108
static HRESULT WINAPI TgaDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, IWICBitmapDecoderInfo **ppIDecoderInfo)
Definition: tgaformat.c:360
#define WINCODEC_ERR_WRONGSTATE
Definition: winerror.h:3273
#define S_OK
Definition: intsafe.h:59
WORD width
Definition: tgaformat.c:50
static GpStatus get_decoder_info(IStream *stream, const struct image_codec **result)
Definition: image.c:4237
BOOL initialized
Definition: tgaformat.c:106
int stride
Definition: tgaformat.c:112
#define InterlockedIncrement
Definition: armddk.h:53
static const IWICBitmapFrameDecodeVtbl TgaDecoder_Frame_Vtbl
Definition: tgaformat.c:928
static HRESULT WINAPI TgaDecoder_Frame_GetSize(IWICBitmapFrameDecode *iface, UINT *puiWidth, UINT *puiHeight)
Definition: tgaformat.c:480
#define E_NOTIMPL
Definition: ddrawi.h:99
static HRESULT WINAPI TgaDecoder_GetPreview(IWICBitmapDecoder *iface, IWICBitmapSource **ppIBitmapSource)
Definition: tgaformat.c:382
HRESULT TgaDecoder_CreateInstance(REFIID iid, void **ppv)
Definition: tgaformat.c:942
WORD colormap_length
Definition: tgaformat.c:45
static ULONG WINAPI TgaDecoder_AddRef(IWICBitmapDecoder *iface)
Definition: tgaformat.c:154
unsigned int UINT
Definition: ndis.h:50
#define ATTRIBUTE_PALPHA
Definition: tgaformat.c:98
ULONG image_offset
Definition: tgaformat.c:116
static const BYTE tga_footer_magic[18]
Definition: tgaformat.c:71
IStream * stream
Definition: tgaformat.c:107
BYTE id_length
Definition: tgaformat.c:40
WORD gamma_denominator
Definition: tgaformat.c:87
static HRESULT WINAPI TgaDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
Definition: tgaformat.c:887
ULONG colormap_offset
Definition: tgaformat.c:115
IWICBitmapDecoder IWICBitmapDecoder_iface
Definition: tgaformat.c:103
unsigned int ULONG
Definition: retypes.h:1
LONG ref
Definition: tgaformat.c:105
CRITICAL_SECTION lock
Definition: tgaformat.c:119
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
BYTE depth
Definition: tgaformat.c:52
_Out_ LPRECT prc
Definition: ntgdi.h:1658
#define memset(x, y, z)
Definition: compat.h:39
UINT32 WICColor
Definition: wincodec.idl:250
static HRESULT WINAPI TgaDecoder_Frame_GetResolution(IWICBitmapFrameDecode *iface, double *pDpiX, double *pDpiY)
Definition: tgaformat.c:593
#define IMAGE_RIGHTTOLEFT
Definition: tgaformat.c:62
#define HeapFree(x, y, z)
Definition: compat.h:402
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
static HRESULT WINAPI TgaDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream, DWORD *capability)
Definition: tgaformat.c:184
BYTE colormap_entrysize
Definition: tgaformat.c:46
#define SUCCEEDED(hr)
Definition: intsafe.h:57
static HRESULT WINAPI TgaDecoder_GetFrame(IWICBitmapDecoder *iface, UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
Definition: tgaformat.c:412
BYTE * imagebits
Definition: tgaformat.c:110
static HRESULT WINAPI TgaDecoder_CopyPalette(IWICBitmapDecoder *iface, IWICPalette *pIPalette)
Definition: tgaformat.c:368