Commit 5f22fdb8 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

windowscodecs: Add support for…

windowscodecs: Add support for WICPersistOptionsLittleEndian/WICPersistOptionsBigEndian in the IFD metadata reader.
parent ec437888
/* /*
* Copyright 2012 Vincent Povirk for CodeWeavers * Copyright 2012 Vincent Povirk for CodeWeavers
* Copyright 2012 Dmitry Timoshkov
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -26,6 +27,7 @@ ...@@ -26,6 +27,7 @@
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winternl.h"
#include "objbase.h" #include "objbase.h"
#include "wincodec.h" #include "wincodec.h"
#include "wincodecsdk.h" #include "wincodecsdk.h"
...@@ -599,12 +601,16 @@ HRESULT UnknownMetadataReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, vo ...@@ -599,12 +601,16 @@ HRESULT UnknownMetadataReader_CreateInstance(IUnknown *pUnkOuter, REFIID iid, vo
return MetadataReader_Create(&UnknownMetadataReader_Vtbl, pUnkOuter, iid, ppv); return MetadataReader_Create(&UnknownMetadataReader_Vtbl, pUnkOuter, iid, ppv);
} }
#define SWAP_USHORT(x) do { if (!native_byte_order) (x) = RtlUshortByteSwap(x); } while(0)
#define SWAP_ULONG(x) do { if (!native_byte_order) (x) = RtlUlongByteSwap(x); } while(0)
#define SWAP_ULONGLONG(x) do { if (!native_byte_order) (x) = RtlUlonglongByteSwap(x); } while(0)
#include "pshpack2.h" #include "pshpack2.h"
struct IFD_entry struct IFD_entry
{ {
SHORT id; SHORT id;
SHORT type; SHORT type;
ULONG length; ULONG count;
LONG value; LONG value;
}; };
...@@ -629,47 +635,60 @@ struct IFD_rational ...@@ -629,47 +635,60 @@ struct IFD_rational
#define IFD_DOUBLE 12 #define IFD_DOUBLE 12
#define IFD_IFD 13 #define IFD_IFD 13
static HRESULT load_IFD_entry(IStream *input, struct IFD_entry *entry, MetadataItem *item) static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry,
MetadataItem *item, BOOL native_byte_order)
{ {
ULONG count, value;
SHORT type;
item->schema.vt = VT_EMPTY; item->schema.vt = VT_EMPTY;
item->id.vt = VT_UI2; item->id.vt = VT_UI2;
item->id.u.uiVal = entry->id; item->id.u.uiVal = entry->id;
SWAP_USHORT(item->id.u.uiVal);
switch (entry->type) count = entry->count;
SWAP_ULONG(count);
type = entry->type;
SWAP_USHORT(type);
value = entry->value;
SWAP_ULONG(value);
switch (type)
{ {
case IFD_SHORT: case IFD_SHORT:
if (entry->length == 1) if (count == 1)
{ {
item->value.vt = VT_UI2; item->value.vt = VT_UI2;
item->value.u.uiVal = entry->value; item->value.u.uiVal = value;
break; break;
} }
FIXME("loading multiple short fields is not implemented\n"); FIXME("loading multiple short fields is not implemented\n");
break; break;
case IFD_LONG: case IFD_LONG:
if (entry->length == 1) if (count == 1)
{ {
item->value.vt = VT_UI4; item->value.vt = VT_UI4;
item->value.u.ulVal = entry->value; item->value.u.ulVal = value;
break; break;
} }
FIXME("loading multiple long fields is not implemented\n"); FIXME("loading multiple long fields is not implemented\n");
break; break;
case IFD_RATIONAL: case IFD_RATIONAL:
if (entry->length == 1) if (count == 1)
{ {
HRESULT hr; HRESULT hr;
LARGE_INTEGER pos; LARGE_INTEGER pos;
struct IFD_rational rational; struct IFD_rational rational;
pos.QuadPart = entry->value; pos.QuadPart = value;
hr = IStream_Seek(input, pos, SEEK_SET, NULL); hr = IStream_Seek(input, pos, SEEK_SET, NULL);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
item->value.vt = VT_UI8; item->value.vt = VT_UI8;
hr = IStream_Read(input, &rational , sizeof(rational), NULL); hr = IStream_Read(input, &rational, sizeof(rational), NULL);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
item->value.u.uhVal.QuadPart = ((LONGLONG)rational.denominator << 32) | rational.numerator; item->value.u.uhVal.QuadPart = ((LONGLONG)rational.denominator << 32) | rational.numerator;
SWAP_ULONGLONG(item->value.u.uhVal.QuadPart);
break; break;
} }
FIXME("loading multiple rational fields is not implemented\n"); FIXME("loading multiple rational fields is not implemented\n");
...@@ -688,12 +707,22 @@ static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor, ...@@ -688,12 +707,22 @@ static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor,
MetadataItem *result; MetadataItem *result;
USHORT count, i; USHORT count, i;
struct IFD_entry *entry; struct IFD_entry *entry;
BOOL native_byte_order = TRUE;
TRACE("\n"); TRACE("\n");
#ifdef WORDS_BIGENDIAN
if (persist_options & WICPersistOptionsLittleEndian)
#else
if (persist_options & WICPersistOptionsBigEndian)
#endif
native_byte_order = FALSE;
hr = IStream_Read(input, &count, sizeof(count), NULL); hr = IStream_Read(input, &count, sizeof(count), NULL);
if (FAILED(hr)) return hr; if (FAILED(hr)) return hr;
SWAP_USHORT(count);
entry = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*entry)); entry = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*entry));
if (!entry) return E_OUTOFMEMORY; if (!entry) return E_OUTOFMEMORY;
...@@ -713,7 +742,7 @@ static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor, ...@@ -713,7 +742,7 @@ static HRESULT LoadIfdMetadata(IStream *input, const GUID *preferred_vendor,
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
hr = load_IFD_entry(input, &entry[i], &result[i]); hr = load_IFD_entry(input, &entry[i], &result[i], native_byte_order);
if (FAILED(hr)) if (FAILED(hr))
{ {
HeapFree(GetProcessHeap(), 0, entry); HeapFree(GetProcessHeap(), 0, entry);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment