Merge "wicdec: add ICC profile extraction"
This commit is contained in:
commit
7381254e9a
@ -79,7 +79,6 @@ static int ReadYUV(FILE* in_file, WebPPicture* const pic) {
|
||||
static int ReadPicture(const char* const filename, WebPPicture* const pic,
|
||||
int keep_alpha, Metadata* const metadata) {
|
||||
int ok;
|
||||
(void)metadata; // TODO(jzern): add metadata extraction using WIC
|
||||
if (pic->width != 0 && pic->height != 0) {
|
||||
// If image size is specified, infer it as YUV format.
|
||||
FILE* in_file = fopen(filename, "rb");
|
||||
@ -91,7 +90,7 @@ static int ReadPicture(const char* const filename, WebPPicture* const pic,
|
||||
fclose(in_file);
|
||||
} else {
|
||||
// If no size specified, try to decode it using WIC.
|
||||
ok = ReadPictureWithWIC(filename, pic, keep_alpha);
|
||||
ok = ReadPictureWithWIC(filename, pic, keep_alpha, metadata);
|
||||
}
|
||||
if (!ok) {
|
||||
fprintf(stderr, "Error! Could not process file %s\n", filename);
|
||||
@ -827,10 +826,10 @@ int main(int argc, const char *argv[]) {
|
||||
start = token + 1;
|
||||
}
|
||||
#ifdef HAVE_WINCODEC_H
|
||||
if (keep_metadata != 0) {
|
||||
if (keep_metadata != 0 && keep_metadata != METADATA_ICCP) {
|
||||
// TODO(jzern): remove when -metadata is supported on all platforms.
|
||||
fprintf(stderr, "Warning: -metadata is currently unsupported on this"
|
||||
" platform. Ignoring this option!\n");
|
||||
fprintf(stderr, "Warning: only ICC profile extraction is currently"
|
||||
" supported on this platform!\n");
|
||||
}
|
||||
#endif
|
||||
} else if (!strcmp(argv[c], "-v")) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <wincodec.h>
|
||||
|
||||
#include "webp/encode.h"
|
||||
#include "./metadata.h"
|
||||
|
||||
#define IFS(fn) \
|
||||
do { \
|
||||
@ -61,8 +62,76 @@ static HRESULT OpenInputStream(const char* filename, IStream** ppStream) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Stores the first non-zero sized color profile from 'pFrame' to 'iccp'.
|
||||
// Returns an HRESULT to indicate success or failure. The caller is responsible
|
||||
// for freeing 'iccp->bytes' in either case.
|
||||
static HRESULT ExtractICCP(IWICImagingFactory* const pFactory,
|
||||
IWICBitmapFrameDecode* const pFrame,
|
||||
MetadataPayload* const iccp) {
|
||||
HRESULT hr = S_OK;
|
||||
UINT i, count;
|
||||
IWICColorContext** ppColorContext;
|
||||
|
||||
IFS(IWICBitmapFrameDecode_GetColorContexts(pFrame, 0, NULL, &count));
|
||||
if (FAILED(hr) || count == 0) return hr;
|
||||
|
||||
ppColorContext = (IWICColorContext**)calloc(count, sizeof(*ppColorContext));
|
||||
if (ppColorContext == NULL) return E_OUTOFMEMORY;
|
||||
for (i = 0; SUCCEEDED(hr) && i < count; ++i) {
|
||||
IFS(IWICImagingFactory_CreateColorContext(pFactory, &ppColorContext[i]));
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
UINT num_color_contexts;
|
||||
IFS(IWICBitmapFrameDecode_GetColorContexts(pFrame,
|
||||
count, ppColorContext,
|
||||
&num_color_contexts));
|
||||
for (i = 0; SUCCEEDED(hr) && i < num_color_contexts; ++i) {
|
||||
WICColorContextType type;
|
||||
IFS(IWICColorContext_GetType(ppColorContext[i], &type));
|
||||
if (SUCCEEDED(hr) && type == WICColorContextProfile) {
|
||||
UINT size;
|
||||
IFS(IWICColorContext_GetProfileBytes(ppColorContext[i],
|
||||
0, NULL, &size));
|
||||
if (size > 0) {
|
||||
iccp->bytes = (uint8_t*)malloc(size);
|
||||
if (iccp->bytes == NULL) {
|
||||
hr = E_OUTOFMEMORY;
|
||||
break;
|
||||
}
|
||||
iccp->size = size;
|
||||
IFS(IWICColorContext_GetProfileBytes(ppColorContext[i],
|
||||
(UINT)iccp->size, iccp->bytes,
|
||||
&size));
|
||||
if (SUCCEEDED(hr) && size != iccp->size) {
|
||||
fprintf(stderr, "Warning! ICC profile size (%u) != expected (%u)\n",
|
||||
size, iccp->size);
|
||||
iccp->size = size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (ppColorContext[i] != NULL) IUnknown_Release(ppColorContext[i]);
|
||||
}
|
||||
free(ppColorContext);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT ExtractMetadata(IWICImagingFactory* const pFactory,
|
||||
IWICBitmapFrameDecode* const pFrame,
|
||||
Metadata* const metadata) {
|
||||
// TODO(jzern): add XMP/EXIF extraction.
|
||||
const HRESULT hr = ExtractICCP(pFactory, pFrame, &metadata->iccp);
|
||||
if (FAILED(hr)) MetadataFree(metadata);
|
||||
return hr;
|
||||
}
|
||||
|
||||
int ReadPictureWithWIC(const char* const filename,
|
||||
WebPPicture* const pic, int keep_alpha) {
|
||||
WebPPicture* const pic, int keep_alpha,
|
||||
Metadata* const metadata) {
|
||||
// From Microsoft SDK 7.0a -- wincodec.h
|
||||
// Create local copies for compatibility when building against earlier
|
||||
// versions of the SDK.
|
||||
@ -191,6 +260,12 @@ int ReadPictureWithWIC(const char* const filename,
|
||||
if (has_alpha && keep_alpha == 2) {
|
||||
WebPCleanupTransparentArea(pic);
|
||||
}
|
||||
if (metadata != NULL) {
|
||||
hr = ExtractMetadata(pFactory, pFrame, metadata);
|
||||
if (FAILED(hr)) {
|
||||
fprintf(stderr, "Error extracting image metadata using WIC!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup.
|
||||
@ -204,10 +279,12 @@ int ReadPictureWithWIC(const char* const filename,
|
||||
}
|
||||
#else // !HAVE_WINCODEC_H
|
||||
int ReadPictureWithWIC(const char* const filename,
|
||||
struct WebPPicture* const pic, int keep_alpha) {
|
||||
struct WebPPicture* const pic, int keep_alpha,
|
||||
struct Metadata* const metadata) {
|
||||
(void)filename;
|
||||
(void)pic;
|
||||
(void)keep_alpha;
|
||||
(void)metadata;
|
||||
fprintf(stderr, "Windows Imaging Component (WIC) support not compiled. "
|
||||
"Visual Studio and mingw-w64 builds support WIC. Make sure "
|
||||
"wincodec.h detection is working correctly if using autoconf "
|
||||
|
@ -14,6 +14,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct Metadata;
|
||||
struct WebPPicture;
|
||||
|
||||
// Reads an image from 'filename', returning the decoded output in 'pic'.
|
||||
@ -21,7 +22,8 @@ struct WebPPicture;
|
||||
// RGBA otherwise it will be RGB.
|
||||
// Returns true on success.
|
||||
int ReadPictureWithWIC(const char* const filename,
|
||||
struct WebPPicture* const pic, int keep_alpha);
|
||||
struct WebPPicture* const pic, int keep_alpha,
|
||||
struct Metadata* const metadata);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
} // extern "C"
|
||||
|
Loading…
Reference in New Issue
Block a user