Skip to content

Instantly share code, notes, and snippets.

@madewokherd
Created September 5, 2012 03:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save madewokherd/3629620 to your computer and use it in GitHub Desktop.
Save madewokherd/3629620 to your computer and use it in GitHub Desktop.
/*
* WIC image conversion test program
*
* Copyright (c) 2012 Vincent Povirk for CodeWeavers
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
i586-mingw32msvc-gcc convert.c -Wall -I/usr/local/include/wine/windows -lole32 -o convert.exe
*/
#define COBJMACROS
#include "windows.h"
#include "stdio.h"
#include "initguid.h"
#include "wincodec.h"
static inline WCHAR *strchrnulW( const WCHAR *str, WCHAR ch )
{
while (1) { if (*str == ch || !*str) return (WCHAR *)(ULONG_PTR)str; str++; }
}
static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
{
if (n <= 0) return 0;
while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
return *str1 - *str2;
}
IWICImagingFactory *factory;
#define check_hr() do { \
if (FAILED(hr)) { \
printf("Failure, code 0x%x, line %i\n", hr, __LINE__); \
exit(1); \
} \
} while (0)
LPWSTR atow(const char *string)
{
int len;
LPWSTR result;
len = MultiByteToWideChar(CP_ACP, 0, string, -1, NULL, 0);
result = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * len);
MultiByteToWideChar(CP_ACP, 0, string, -1, result, len);
return result;
}
int find_encoder_for_mimetype(LPWSTR mimetype, CLSID *result)
{
IEnumUnknown *enum_encoders;
IUnknown *item;
IWICBitmapEncoderInfo *encoder_info;
HRESULT hr;
ULONG count;
BOOL matches=FALSE;
int mimetype_len = lstrlenW(mimetype);
WCHAR mimetypes[256];
int start, end;
hr = IWICImagingFactory_CreateComponentEnumerator(factory, WICEncoder,
WICComponentEnumerateDefault, &enum_encoders);
check_hr();
while (!matches && SUCCEEDED(IEnumUnknown_Next(enum_encoders, 1, &item, &count)) && count == 1)
{
hr = IUnknown_QueryInterface(item, &IID_IWICBitmapEncoderInfo, (void**)&encoder_info);
check_hr();
#if 0
/* Unimplemented on windows */
hr = IWICBitmapEncoderInfo_MatchesMimeType(encoder_info, mimetype, &matches);
check_hr();
#endif
hr = IWICBitmapCodecInfo_GetMimeTypes(encoder_info, sizeof(mimetypes)/sizeof(mimetypes[0]), mimetypes, &count);
check_hr();
start = 0;
do {
end = strchrnulW(mimetypes+start, ',') - mimetypes;
if (end - start == mimetype_len && strncmpW(mimetypes+start, mimetype, end-start) == 0)
{
matches = TRUE;
break;
}
start = end+1;
} while (mimetypes[end] != 0);
if (matches)
IWICBitmapEncoderInfo_GetCLSID(encoder_info, result);
IWICBitmapEncoderInfo_Release(encoder_info);
IUnknown_Release(item);
}
IEnumUnknown_Release(enum_encoders);
return matches;
}
void copy_image_data(IWICBitmapEncoder *encoder, IWICBitmapDecoder *decoder)
{
UINT frame_count, i;
IWICBitmapFrameDecode *frame_decode;
IWICBitmapFrameEncode *frame_encode;
HRESULT hr;
IPropertyBag2 *propertybag;
UINT width, height;
hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
check_hr();
for (i=0; i<frame_count; i++)
{
hr = IWICBitmapDecoder_GetFrame(decoder, i, &frame_decode);
check_hr();
hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frame_encode, &propertybag);
check_hr();
hr = IWICBitmapFrameEncode_Initialize(frame_encode, propertybag);
check_hr();
IPropertyBag2_Release(propertybag);
hr = IWICBitmapFrameDecode_GetSize(frame_decode, &width, &height);
check_hr();
hr = IWICBitmapFrameEncode_SetSize(frame_encode, width, height);
check_hr();
hr = IWICBitmapFrameEncode_WriteSource(frame_encode, (IWICBitmapSource*)frame_decode, NULL);
check_hr();
hr = IWICBitmapFrameEncode_Commit(frame_encode);
check_hr();
IWICBitmapFrameDecode_Release(frame_decode);
IWICBitmapFrameEncode_Release(frame_encode);
}
hr = IWICBitmapEncoder_Commit(encoder);
check_hr();
}
int main(int argc, char* argv[])
{
LPWSTR src_file, dst_file, mimetype;
IWICBitmapDecoder *decoder;
IWICBitmapEncoder *encoder;
IWICStream *stream;
CLSID encoder_clsid;
HRESULT hr;
if (argc < 4)
{
printf("Usage: convert.exe source dest mimetype\n");
return 2;
}
src_file = atow(argv[1]);
dst_file = atow(argv[2]);
mimetype = atow(argv[3]);
hr = CoInitialize(NULL);
check_hr();
hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICImagingFactory, (void**)&factory);
check_hr();
hr = IWICImagingFactory_CreateDecoderFromFilename(factory, src_file, NULL,
GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder);
check_hr();
if (!find_encoder_for_mimetype(mimetype, &encoder_clsid))
{
printf("No encoder found for %s\n", argv[3]);
exit(1);
}
hr = CoCreateInstance(&encoder_clsid, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICBitmapEncoder, (void**)&encoder);
check_hr();
hr = IWICImagingFactory_CreateStream(factory, &stream);
check_hr();
hr = IWICStream_InitializeFromFilename(stream, dst_file, GENERIC_READ|GENERIC_WRITE);
check_hr();
hr = IWICBitmapEncoder_Initialize(encoder, (IStream*)stream, WICBitmapEncoderNoCache);
check_hr();
copy_image_data(encoder, decoder);
IWICBitmapDecoder_Release(decoder);
IWICBitmapEncoder_Release(encoder);
IWICStream_Release(stream);
IWICImagingFactory_Release(factory);
CoUninitialize();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment