#include "WindowsImageService.h"
#include "../GDI/WinGDI.h"
#include <Shlwapi.h>
#pragma comment(lib,
"WindowsCodecs.lib"
)
namespace
{
namespace
{
namespace
{
using
namespace
collections
;
void
::
(
*
)
{
*
=
();
<
>
;
{
*
=
0
;
=
factory
->
(&
formatConverter
);
{
converter
formatConverter
;
converter
(
,
GUID_WICPixelFormat32bppPBGRA
,
,
0.0f
,
WICBitmapPaletteTypeCustom
);
}
}
*
=
0
;
*
=
0
;
if
(
converter
)
{
convertedBitmapSource
=
converter
.
();
}
else
{
convertedBitmapSource
=
;
}
=
factory
->
(
convertedBitmapSource
,
, &
bitmap
);
{
bitmap
;
}
}
::
(
*
,
*
)
:image(
)
{
(
);
}
::
(
*
,
*
)
:image(
)
{
(
);
}
::
()
{
for
(
=
0
;
i
<
.
();
i
++)
{
.
().
(
i
)
(
this
);
}
}
*
::
()
{
return
;
}
::
()
{
=
0
;
=
0
;
(&
width
, &
height
);
return
(
width
,
height
);
}
bool
::
(
void
*
,
<
>
)
{
=
.
().
(
);
if
(
index
!=-
1
)
{
return
false
;
}
.
(
,
);
(
this
);
return
true
;
}
<
>
::
(
void
*
)
{
=
.
().
(
);
return
index
==-
1
?
nullptr
:
.
().
(
index
);
}
<
>
::
(
void
*
)
{
=
.
().
(
);
if
(
index
==-
1
)
{
return
0
;
}
<
>
=
.
().
(
index
);
cache
(
this
);
.
(
);
return
cache
;
}
*
::
()
{
return
.
();
}
void
::
(
stream
::
&
)
{
=
0
;
=
0
;
(&
width
, &
height
);
auto
=
<
>((
)
width
, (
)
height
,
::
,
true
);
;
rect
.
=
0
;
rect
.
=
0
;
rect
.
= (
)
width
;
rect
.
= (
)
height
;
(&
rect
, (
)
bitmap
(), (
)(
bitmap
()*
height
), (
*)
bitmap
()[
0
]);
bitmap
(
,
false
);
}
::
(
*
,
*
)
:imageService(
)
,bitmapDecoder(
)
{
=
0
;
(&
count
);
.
(
count
);
}
::
()
{
}
*
::
()
{
return
;
}
::
::
()
{
;
=
(&
formatGUID
);
{
if
(
formatGUID
==
GUID_ContainerFormatBmp
)
{
return
::
;
}
else
if
(
formatGUID
==
GUID_ContainerFormatPng
)
{
return
::
;
}
else
if
(
formatGUID
==
GUID_ContainerFormatGif
)
{
return
::
;
}
else
if
(
formatGUID
==
GUID_ContainerFormatJpeg
)
{
return
::
;
}
else
if
(
formatGUID
==
GUID_ContainerFormatIco
)
{
return
::
;
}
else
if
(
formatGUID
==
GUID_ContainerFormatTiff
)
{
return
::
;
}
else
if
(
formatGUID
==
GUID_ContainerFormatWmp
)
{
return
::
;
}
}
return
::
;
}
::
()
{
return
.
();
}
*
::
(
)
{
if
(
0
<=
&&
<
())
{
<
>&
=
];
if
(!
frame
)
{
*
=
0
;
=
((
int
)
, &
frameDecode
);
{
frame
new
(
this
,
frameDecode
);
frameDecode
->
();
}
}
return
frame
.
();
}
else
{
return
0
;
}
}
void
(
*
,
*
,
const
&
)
{
*
=
nullptr
;
=
->
(&
enumString
);
if
(
enumString
)
{
while
(
true
)
{
=
nullptr
;
=
0
;
hr
=
enumString
->
(
1
, &
metadataName
, &
fetched
);
if
(
fetched
==
0
)
break
;
;
(&
metadataValue
);
hr
=
->
(
metadataName
, &
metadataValue
);
{
if
(
metadataValue
.
==
&&
metadataValue
.
)
{
*
=
nullptr
;
hr
=
metadataValue
.
->
<
>(&
embeddedReader
);
if
(
embeddedReader
)
{
(
embeddedReader
,
,
+
metadataName
);
embeddedReader
->
();
}
}
else
{
hr
=
->
((
+
metadataName
).Buffer(), &
metadataValue
);
}
hr
=
(&
metadataValue
);
}
(
metadataName
);
}
enumString
->
();
}
}
template
<
typename
,
typename
>
void
(
*
,
*
)
{
*
=
nullptr
;
*
=
nullptr
;
=
->GetMetadataQueryReader(&
reader
);
hr
=
->GetMetadataQueryWriter(&
writer
);
if
(
reader
&&
writer
)
{
(
reader
,
writer
,
::
);
}
if
(
reader
)
reader
->
();
if
(
writer
)
writer
->
();
}
(
::
)
{
switch
(
)
{
case
::
:
return
GUID_ContainerFormatBmp
;
case
::
:
return
GUID_ContainerFormatGif
;
case
::
:
return
GUID_ContainerFormatIco
;
case
::
:
return
GUID_ContainerFormatJpeg
;
case
::
:
return
GUID_ContainerFormatPng
;
case
::
:
return
GUID_ContainerFormatTiff
;
case
::
:
return
GUID_ContainerFormatWmp
;
default: CHECK_FAIL(L"GetGuidFromFormat(INativeImage::FormatType)#Unexpected format type.");
default
:
do
{
throw
(
L"GetGuidFromFormat(INativeImage::FormatType)#Unexpected format type."
);}
while
(
0
);
}
}
void
(
*
,
stream
::
&
)
{
;
dlibMove
.
=
0
;
HRESULT hr = pIStream->Seek(dlibMove, STREAM_SEEK_SET, NULL);
<
char
>
(
65536
);
while
(
true
)
{
= (
)
buffer
.
();
=
0
;
hr
=
->
(&
buffer
0
],
count
, &
read
);
if
(
read
>
0
)
{
.
(&
buffer
0
], (
)
read
);
}
if
(
read
!=
count
)
{
break
;
}
}
}
void
::
(
stream
::
&
,
)
{
auto
=
();
;
;
bool
=
==
::
||
==
();
if
(
==
::
)
{
hr
=
(&
formatGUID
);
if (hr != S_OK) goto FAILED;
if
(
hr
!= ((
)
0L
))
goto
FAILED;
}
else
{
formatGUID
(
);
}
{
*
=
nullptr
;
hr = factory->CreateEncoder(formatGUID, NULL, &bitmapEncoder);
hr
=
factory
->
(
formatGUID
,
0
, &
bitmapEncoder
);
if
(!
bitmapEncoder
)
goto
FAILED;
*
=
nullptr
;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pIStream);
if
(!
pIStream
)
{
bitmapEncoder
->
();
goto
FAILED;
}
hr
=
bitmapEncoder
->
(
pIStream
,
);
{
pIStream
->
();
bitmapEncoder
->
();
goto
FAILED;
}
{
=
0
;
<
*>
(
16
);
hr
=
((
)
colorContexts
.
(), &
colorContexts
0
], &
actualCount
);
{
if
((
)
actualCount
>
colorContexts
.
())
{
for
(
=
0
;
i
<
colorContexts
.
();
i
++)
colorContexts
i
]->
();
colorContexts
.
((
)
actualCount
);
(
actualCount
, &
colorContexts
0
], &
actualCount
);
}
if
(
actualCount
>
0
)
{
bitmapEncoder
->
(
actualCount
, &
colorContexts
0
]);
for
(
=
0
;
i
< (
)
actualCount
;
i
++)
colorContexts
i
]->
();
}
}
}
{
*
=
nullptr
;
hr
=
factory
->
(&
palette
);
if
(
palette
)
{
hr
=
(
palette
);
{
bitmapEncoder
->
(
palette
);
}
palette
->
();
}
}
{
*
=
nullptr
;
hr
=
(&
source
);
if
(
source
)
{
bitmapEncoder
->
(
source
);
source
->
();
}
}
{
*
=
nullptr
;
hr
=
(&
source
);
if
(
source
)
{
bitmapEncoder
->
(
source
);
source
->
();
}
}
if
(
sameFormat
)
{
(
.
(),
bitmapEncoder
);
}
=
0
;
(&
frameCount
);
for
(
=
0
;
i
<
frameCount
;
i
++)
{
*
=
nullptr
;
*
=
nullptr
;
hr
=
(
i
, &
frameDecode
);
hr = bitmapEncoder->CreateNewFrame(&frameEncode, NULL);
hr
=
bitmapEncoder
->
(&
frameEncode
,
0
);
if
(
frameDecode
&&
frameEncode
)
{
hr = frameEncode->Initialize(NULL);
if
(
sameFormat
)
{
(
frameDecode
,
frameEncode
);
}
hr = frameEncode->WriteSource(frameDecode, NULL);
hr
=
frameEncode
->
(
frameDecode
,
0
);
hr
=
frameEncode
->
();
}
if
(
frameDecode
)
frameDecode
->
();
if
(
frameEncode
)
frameEncode
->
();
}
hr
=
bitmapEncoder
->
();
bitmapEncoder
->
();
(
pIStream
,
);
pIStream
->
();
}
FAILED:;
}
::
(
*
,
*
,
)
:imageService(
)
,formatType(
)
{
new
(
this
,
);
}
::
()
{
}
*
::
()
{
return
;
}
::
::
()
{
return
;
}
::
()
{
return
1
;
}
*
::
(
)
{
return
==
0
?
.
():
0
;
}
void
::
(
stream
::
&
,
)
{
auto
=
();
if
(
==
::
)
{
=
::
;
}
=
(
);
*
=
nullptr
;
HRESULT hr = factory->CreateEncoder(formatGUID, NULL, &bitmapEncoder);
=
factory
->
(
formatGUID
,
0
, &
bitmapEncoder
);
if
(!
bitmapEncoder
)
goto
FAILED;
{
*
=
nullptr
;
hr = CreateStreamOnHGlobal(NULL, TRUE, &pIStream);
if
(!
pIStream
)
{
bitmapEncoder
->
();
goto
FAILED;
}
hr
=
bitmapEncoder
->
(
pIStream
,
);
{
pIStream
->
();
bitmapEncoder
->
();
goto
FAILED;
}
{
*
=
nullptr
;
hr = bitmapEncoder->CreateNewFrame(&frameEncode, NULL);
hr
=
bitmapEncoder
->
(&
frameEncode
,
0
);
if
(
frameEncode
)
{
hr = frameEncode->Initialize(NULL);
hr = frameEncode->WriteSource(frame->GetFrameBitmap(), NULL);
hr
=
frameEncode
->
(
(),
0
);
hr
=
frameEncode
->
();
frameEncode
->
();
}
}
hr
=
bitmapEncoder
->
();
bitmapEncoder
->
();
(
pIStream
,
);
pIStream
->
();
}
FAILED:;
}
::
()
{
*
=
0
;
=
(
#if defined(WINCODEC_SDK_VERSION2)
CLSID_WICImagingFactory1
,
#else
CLSID_WICImagingFactory,
#endif
,
IID_IWICImagingFactory
,
(
*)&
factory
);
{
factory
;
}
}
::
()
{
}
<
>
::
(
const
&
)
{
*
=
0
;
=
CreateDecoderFromFilename
(
.
(),
WICDecodeMetadataCacheOnDemand
,
&
bitmapDecoder
);
{
return
new
(
this
,
bitmapDecoder
);
}
else
{
return
0
;
}
}
<
>
::
(
void
*
,
)
{
<
>
;
::
*
=
((
const
*)
, (
int
)
);
if
(
stream
)
{
*
=
0
;
HRESULT hr=imagingFactory->CreateDecoderFromStream(stream, NULL, WICDecodeMetadataCacheOnDemand, &bitmapDecoder);
=
(
stream
,
0
,
WICDecodeMetadataCacheOnDemand
, &
bitmapDecoder
);
{
result
new
(
this
,
bitmapDecoder
);
}
stream
->
();
}
return
result
;
}
<
>
::
(
stream
::
&
)
{
stream
::
;
char
[
65536
];
while
(
true
)
{
=
.
(
buffer
,
sizeof
(
buffer
));
memoryStream
.
(
buffer
,
length
);
if
(
length
!=
sizeof
(
buffer
))
{
break
;
}
}
return
(
memoryStream
.
(), (
)
memoryStream
.
());
}
<
>
::
(
)
{
*
=
0
;
HRESULT hr=imagingFactory->CreateBitmapFromHBITMAP(handle, NULL, WICBitmapUseAlpha, &bitmap);
{
<
>
=
new
(
this
,
bitmap
,
::
);
bitmap
->
();
return
image
;
}
else
{
return
0
;
}
}
<
>
::
(
)
{
*
=
0
;
=
(
, &
bitmap
);
{
<
>
=
new
(
this
,
bitmap
,
::
);
bitmap
->
();
return
image
;
}
else
{
return
0
;
}
}
*
::
()
{
return
.
();
}
*
()
{
return
dynamic_cast
<
*>(
()->
())->
();
}
*
(
*
)
{
return
dynamic_cast
<
*>(
)->
();
}
<
>
(
)
{
return
dynamic_cast
<
*>(
()->
())->
(
);
}
<
>
(
)
{
return
dynamic_cast
<
*>(
()->
())->
(
);
}
}
}
}