jxrlib: Add library sources

This commit is contained in:
Rémi Bernon 2020-09-11 20:56:27 +02:00 committed by Andrew Eikum
parent 9a746c257e
commit d9d777072a
63 changed files with 37177 additions and 0 deletions

315
jxrlib/jxrtestlib/JXRTest.c Normal file
View file

@ -0,0 +1,315 @@
//*@@@+++@@@@******************************************************************
//
// Copyright © Microsoft Corp.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// • Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// • Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//*@@@---@@@@******************************************************************
#include <JXRTest.h>
//================================================================
const PKIID IID_PKImagePnmEncode = 102;
const PKIID IID_PKImageBmpEncode = 103;
const PKIID IID_PKImageTifEncode = 104;
const PKIID IID_PKImageHdrEncode = 105;
const PKIID IID_PKImageIyuvEncode = 106;
const PKIID IID_PKImageYuv422Encode = 107;
const PKIID IID_PKImageYuv444Encode = 108;
const PKIID IID_PKImageBmpDecode = 202;
const PKIID IID_PKImagePnmDecode = 203;
const PKIID IID_PKImageTifDecode = 204;
const PKIID IID_PKImageHdrDecode = 205;
const PKIID IID_PKImageIyuvDecode = 206;
const PKIID IID_PKImageYuv422Decode = 207;
const PKIID IID_PKImageYuv444Decode = 208;
//================================================================
// Misc supporting functions
//================================================================
extern int PKStrnicmp(const char* s1, const char* s2, size_t c);
//----------------------------------------------------------------
typedef struct tagPKIIDInfo
{
const char* szExt;
const PKIID* pIIDEnc;
const PKIID* pIIDDec;
} PKIIDInfo;
static ERR GetTestInfo(const char* szExt, const PKIIDInfo** ppInfo)
{
ERR err = WMP_errSuccess;
static PKIIDInfo iidInfo[] = {
{".bmp", &IID_PKImageBmpEncode, &IID_PKImageBmpDecode},
{".ppm", &IID_PKImagePnmEncode, &IID_PKImagePnmDecode},
{".pgm", &IID_PKImagePnmEncode, &IID_PKImagePnmDecode},
{".pnm", &IID_PKImagePnmEncode, &IID_PKImagePnmDecode},
{".pfm", &IID_PKImagePnmEncode, &IID_PKImagePnmDecode},
{".tif", &IID_PKImageTifEncode, &IID_PKImageTifDecode},
{".hdr", &IID_PKImageHdrEncode, &IID_PKImageHdrDecode},
{".iyuv", &IID_PKImageIyuvEncode, &IID_PKImageIyuvDecode},
{".yuv422", &IID_PKImageYuv422Encode, &IID_PKImageYuv422Decode},
{".yuv444", &IID_PKImageYuv444Encode, &IID_PKImageYuv444Decode},
};
size_t i = 0;
*ppInfo = NULL;
for (i = 0; i < sizeof2(iidInfo); ++i)
{
if (0 == PKStrnicmp(szExt, iidInfo[i].szExt, strlen(iidInfo[i].szExt)))
{
*ppInfo = &iidInfo[i];
goto Cleanup;
}
}
Call(WMP_errUnsupportedFormat);
Cleanup:
return err;
}
ERR GetTestEncodeIID(const char* szExt, const PKIID** ppIID)
{
ERR err = WMP_errSuccess;
const PKIIDInfo* pInfo = NULL;
Call(GetTestInfo(szExt, &pInfo));
*ppIID = pInfo->pIIDEnc;
Cleanup:
return err;
}
ERR GetTestDecodeIID(const char* szExt, const PKIID** ppIID)
{
ERR err = WMP_errSuccess;
const PKIIDInfo* pInfo = NULL;
Call(GetTestInfo(szExt, &pInfo));
*ppIID = pInfo->pIIDDec;
Cleanup:
return err;
}
//================================================================
// PKTestFactory
//================================================================
ERR PKTestFactory_CreateCodec(const PKIID* iid, void** ppv)
{
ERR err = WMP_errSuccess;
if (IID_PKImageBmpEncode == *iid)
{
Call(PKImageEncode_Create_BMP((PKImageEncode**)ppv));
}
else if (IID_PKImagePnmEncode == *iid)
{
Call(PKImageEncode_Create_PNM((PKImageEncode**)ppv));
}
else if (IID_PKImageTifEncode == *iid)
{
Call(PKImageEncode_Create_TIF((PKImageEncode**)ppv));
}
else if (IID_PKImageHdrEncode == *iid)
{
Call(PKImageEncode_Create_HDR((PKImageEncode**)ppv));
}
else if (IID_PKImageIyuvEncode == *iid)
{
Call(PKImageEncode_Create_IYUV((PKImageEncode**)ppv));
}
else if (IID_PKImageYuv422Encode == *iid)
{
Call(PKImageEncode_Create_YUV422((PKImageEncode**)ppv));
}
else if (IID_PKImageYuv444Encode == *iid)
{
Call(PKImageEncode_Create_YUV444((PKImageEncode**)ppv));
}
else if (IID_PKImageBmpDecode == *iid)
{
Call(PKImageDecode_Create_BMP((PKTestDecode**)ppv));
}
else if (IID_PKImagePnmDecode == *iid)
{
Call(PKImageDecode_Create_PNM((PKTestDecode**)ppv));
}
else if (IID_PKImageTifDecode == *iid)
{
Call(PKImageDecode_Create_TIF((PKTestDecode**)ppv));
}
else if (IID_PKImageHdrDecode == *iid)
{
Call(PKImageDecode_Create_HDR((PKTestDecode**)ppv));
}
else if (IID_PKImageIyuvDecode == *iid)
{
Call(PKImageDecode_Create_IYUV((PKTestDecode**)ppv));
}
else if (IID_PKImageYuv422Decode == *iid)
{
Call(PKImageDecode_Create_YUV422((PKTestDecode**)ppv));
}
else if (IID_PKImageYuv444Decode == *iid)
{
Call(PKImageDecode_Create_YUV444((PKTestDecode**)ppv));
}
else
{
Call(WMP_errUnsupportedFormat);
}
Cleanup:
return err;
}
ERR PKTestFactory_CreateDecoderFromFile(const char* szFilename, PKImageDecode** ppDecoder)
{
ERR err = WMP_errSuccess;
char *pExt = NULL;
PKIID* pIID = NULL;
struct WMPStream* pStream = NULL;
PKImageDecode* pDecoder = NULL;
// get file extension
pExt = strrchr(szFilename, '.');
FailIf(NULL == pExt, WMP_errUnsupportedFormat);
// get decode PKIID
Call(GetTestDecodeIID(pExt, &pIID));
// create stream
Call(CreateWS_File(&pStream, szFilename, "rb"));
// Create decoder
Call(PKTestFactory_CreateCodec(pIID, ppDecoder));
pDecoder = *ppDecoder;
// attach stream to decoder
Call(pDecoder->Initialize(pDecoder, pStream));
pDecoder->fStreamOwner = !0;
Cleanup:
return err;
}
ERR PKCreateTestFactory(PKCodecFactory** ppCFactory, U32 uVersion)
{
ERR err = WMP_errSuccess;
PKCodecFactory* pCFactory = NULL;
UNREFERENCED_PARAMETER( uVersion );
Call(PKAlloc(ppCFactory, sizeof(**ppCFactory)));
pCFactory = *ppCFactory;
pCFactory->CreateCodec = PKTestFactory_CreateCodec;
pCFactory->CreateDecoderFromFile = PKTestFactory_CreateDecoderFromFile;
pCFactory->CreateFormatConverter = PKCodecFactory_CreateFormatConverter;
pCFactory->Release = PKCreateCodecFactory_Release;
Cleanup:
return err;
}
//================================================================
// PKTestDecode
//================================================================
ERR PKTestDecode_Initialize(
PKTestDecode* pID,
struct WMPStream* pStream)
{
ERR err = WMP_errSuccess;
pID->pStream = pStream;
pID->guidPixFormat = GUID_PKPixelFormatDontCare;
pID->fResX = 96;
pID->fResY = 96;
pID->cFrame = 1;
Call(pID->pStream->GetPos(pID->pStream, &pID->offStart));
Cleanup:
return WMP_errSuccess;
}
ERR PKTestDecode_Copy(
PKTestDecode* pID,
const PKRect* pRect,
U8* pb,
U32 cbStride)
{
UNREFERENCED_PARAMETER( pID );
UNREFERENCED_PARAMETER( pRect );
UNREFERENCED_PARAMETER( pb );
UNREFERENCED_PARAMETER( cbStride );
return WMP_errAbstractMethod;
}
ERR PKTestDecode_Release(
PKTestDecode** ppID)
{
PKTestDecode* pID = *ppID;
pID->fStreamOwner && pID->pStream->Close(&pID->pStream);
return PKFree(ppID);
}
ERR PKTestDecode_Create(
PKTestDecode** ppID)
{
ERR err = WMP_errSuccess;
PKTestDecode* pID = NULL;
Call(PKAlloc(ppID, sizeof(**ppID)));
pID = *ppID;
pID->Initialize = PKTestDecode_Initialize;
pID->GetPixelFormat = PKImageDecode_GetPixelFormat;
pID->GetSize = PKImageDecode_GetSize;
pID->GetResolution = PKImageDecode_GetResolution;
pID->GetColorContext = PKImageDecode_GetColorContext;
pID->GetDescriptiveMetadata = PKImageDecode_GetDescriptiveMetadata;
pID->Copy = PKTestDecode_Copy;
pID->GetFrameCount = PKImageDecode_GetFrameCount;
pID->SelectFrame = PKImageDecode_SelectFrame;
pID->Release = PKTestDecode_Release;
Cleanup:
return err;
}

164
jxrlib/jxrtestlib/JXRTest.h Normal file
View file

@ -0,0 +1,164 @@
//*@@@+++@@@@******************************************************************
//
// Copyright © Microsoft Corp.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// • Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// • Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//*@@@---@@@@******************************************************************
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <JXRGlue.h>
EXTERN_C const PKIID IID_PKImageBmpEncode;
EXTERN_C const PKIID IID_PKImagePnmEncode;
EXTERN_C const PKIID IID_PKImageTifEncode;
EXTERN_C const PKIID IID_PKImageBmpDecode;
EXTERN_C const PKIID IID_PKImagePnmDecode;
EXTERN_C const PKIID IID_PKImageTifDecode;
//----------------------------------------------------------------
ERR GetTestEncodeIID(const char* szExt, const PKIID** ppIID);
ERR GetTestDecodeIID(const char* szExt, const PKIID** ppIID);
//================================================================
#ifdef __ANSI__
#define PKTestDecode struct tagPKTestDecode
#else // __ANSI__
typedef struct tagPKTestDecode PKTestDecode;
#endif // __ANSI__
//================================================================
//----------------------------------------------------------------
ERR PKTestFactory_CreateCodec(const PKIID* iid, void** ppv);
EXTERN_C ERR PKCreateTestFactory(PKCodecFactory**, U32);
//----------------------------------------------------------------
ERR PKImageEncode_Create_BMP(PKImageEncode** ppIE);
ERR PKImageEncode_Create_PNM(PKImageEncode** ppIE);
ERR PKImageEncode_Create_TIF(PKImageEncode** ppIE);
ERR PKImageEncode_Create_HDR(PKImageEncode** ppIE);
ERR PKImageEncode_Create_IYUV(PKImageEncode** ppIE);
ERR PKImageEncode_Create_YUV422(PKImageEncode** ppIE);
ERR PKImageEncode_Create_YUV444(PKImageEncode** ppIE);
//================================================================
typedef struct tagPKTestDecode
{
ERR (*Initialize)(PKTestDecode*, struct WMPStream* pStream);
ERR (*GetPixelFormat)(PKImageDecode*, PKPixelFormatGUID*);
ERR (*GetSize)(PKImageDecode*, I32*, I32*);
ERR (*GetResolution)(PKImageDecode*, Float*, Float*);
ERR (*GetColorContext)(PKImageDecode *pID, U8 *pbColorContext,
U32 *pcbColorContext);
ERR (*GetDescriptiveMetadata)(PKImageDecode *pIE,
DESCRIPTIVEMETADATA *pDescMetadata);
ERR (*GetRawStream)(PKImageDecode*, struct WMPStream**);
ERR (*Copy)(PKTestDecode*, const PKRect*, U8*, U32);
ERR (*GetFrameCount)(PKImageDecode*, U32*);
ERR (*SelectFrame)(PKImageDecode*, U32);
ERR (*Release)(PKTestDecode**);
struct WMPStream* pStream;
Bool fStreamOwner;
size_t offStart;
PKPixelFormatGUID guidPixFormat;
U32 uWidth;
U32 uHeight;
U32 idxCurrentLine;
Float fResX;
Float fResY;
U32 cFrame;
union
{
struct
{
size_t offPixel;
size_t cbPixel;
} BMP;
struct
{
size_t offPixel;
size_t cbPixel;
} HDR;
struct
{
size_t offPixel;
} PNM;
struct
{
U32 uRowsPerStrip;
U32* uStripOffsets;
U32* uStripByteCounts;
U32 uInterpretation;
U32 uSamplePerPixel;
U32 uBitsPerSample;
U32 uSampleFormat;
U32 uExtraSamples;
U16 uResolutionUnit;
Float fResX;
Float fResY;
Bool fLittleEndian;
} TIF;
} EXT;
#ifdef __ANSI__
#undef PKTestDecode
#endif // __ANSI__
} PKTestDecode;
//----------------------------------------------------------------
ERR PKImageDecode_Create_BMP(PKTestDecode** ppID);
ERR PKImageDecode_Create_PNM(PKTestDecode** ppID);
ERR PKImageDecode_Create_TIF(PKTestDecode** ppID);
ERR PKImageDecode_Create_HDR(PKTestDecode** ppID);
ERR PKImageDecode_Create_IYUV(PKTestDecode** ppID);
ERR PKImageDecode_Create_YUV422(PKTestDecode** ppID);
ERR PKImageDecode_Create_YUV444(PKTestDecode** ppID);
ERR PKTestDecode_Initialize(PKTestDecode* pID, struct WMPStream* pStream);
ERR PKTestDecode_Copy(PKTestDecode* pID, const PKRect* pRect, U8* pb, U32 cbStride);
ERR PKTestDecode_Release(PKTestDecode** ppID);
ERR PKTestDecode_Create(PKTestDecode** ppID);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -0,0 +1,401 @@
//*@@@+++@@@@******************************************************************
//
// Copyright © Microsoft Corp.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// • Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// • Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//*@@@---@@@@******************************************************************
#include <stdlib.h>
#include <string.h>
#include <JXRTest.h>
#pragma pack(push, 1)
#define BI_RGB 0
#define BI_BITFIELDS 3
#define BI_RGB555_MASK_B 0x001F
#define BI_RGB555_MASK_G 0x03E0
#define BI_RGB555_MASK_R 0x7C00
#define BI_RGB565_MASK_B 0x001F
#define BI_RGB565_MASK_G 0x07E0
#define BI_RGB565_MASK_R 0xF800
#define BI_RGB101010_MASK_B 0x000003FF
#define BI_RGB101010_MASK_G 0x000FFC00
#define BI_RGB101010_MASK_R 0x3FF00000
typedef struct tagBITMAPFILEHEADER {
U8 szBM[2];
U32 uSize;
U16 reserved1;
U16 reserved2;
U32 uOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{
U32 uSize;
I32 iWidth;
I32 iHeight;
I16 iPlanes;
I16 iBitCount;
U32 uCompression;
U32 uImageSize;
I32 iPelsPerMeterX;
I32 iPelsPerMeterY;
U32 uColorUsed;
U32 uColorImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
typedef struct tagBITMAPINFOHEADEREXT{
U32 uA;
U32 uB;
U32 uC;
U32 uD;
} BITMAPINFOHEADEREXT, *PBITMAPINFOHEADEREXT;
#pragma pack(pop)
//================================================================
// PKImageEncode_BMP
//================================================================
ERR WriteBMPHeader(
PKImageEncode* pIE)
{
ERR err = WMP_errSuccess;
static U32 rguColorTable[256] = {0};
size_t cbColorTable = 0;
size_t cbLineS = 0;
U32 i = 0;
struct WMPStream* pS = pIE->pStream;
BITMAPFILEHEADER bmpFH = { 0, };
BITMAPINFOHEADER bmpIH = {sizeof(bmpIH), 0, };
bmpFH.szBM[0] = 'B';
bmpFH.szBM[1] = 'M';
if (IsEqualGUID(&GUID_PKPixelFormat24bppRGB, &pIE->guidPixFormat) || IsEqualGUID(&GUID_PKPixelFormat24bppBGR, &pIE->guidPixFormat))
{
pIE->cbPixel = 3;
cbColorTable = 0;
}
else if (IsEqualGUID(&GUID_PKPixelFormat32bppBGRA, &pIE->guidPixFormat)
|| IsEqualGUID(&GUID_PKPixelFormat32bppBGR, &pIE->guidPixFormat)
|| IsEqualGUID(&GUID_PKPixelFormat32bppPBGRA, &pIE->guidPixFormat))
{
pIE->cbPixel = 4;
cbColorTable = 0;
}
else if (IsEqualGUID(&GUID_PKPixelFormat8bppGray, &pIE->guidPixFormat))
{
pIE->cbPixel = 1;
cbColorTable = sizeof(rguColorTable);
for (i = 0; i < sizeof2(rguColorTable); ++i)
{
rguColorTable[i] = i | (i << 8) | (i << 16);
}
}
else if (IsEqualGUID(&GUID_PKPixelFormat16bppRGB555, &pIE->guidPixFormat))
{
pIE->cbPixel = 2;
bmpIH.uCompression = BI_BITFIELDS;
cbColorTable = sizeof(rguColorTable[0]) * 3;
rguColorTable[0] = BI_RGB555_MASK_R;
rguColorTable[1] = BI_RGB555_MASK_G;
rguColorTable[2] = BI_RGB555_MASK_B;
}
else if (IsEqualGUID(&GUID_PKPixelFormat16bppRGB565, &pIE->guidPixFormat))
{
pIE->cbPixel = 2;
bmpIH.uCompression = BI_BITFIELDS;
cbColorTable = sizeof(rguColorTable[0]) * 3;
rguColorTable[0] = BI_RGB565_MASK_R;
rguColorTable[1] = BI_RGB565_MASK_G;
rguColorTable[2] = BI_RGB565_MASK_B;
}
else if (IsEqualGUID(&GUID_PKPixelFormat32bppRGB101010, &pIE->guidPixFormat))
{
pIE->cbPixel = 4;
bmpIH.uCompression = BI_BITFIELDS;
cbColorTable = sizeof(rguColorTable[0]) * 3;
rguColorTable[0] = BI_RGB101010_MASK_R;
rguColorTable[1] = BI_RGB101010_MASK_G;
rguColorTable[2] = BI_RGB101010_MASK_B;
}
else
Call(WMP_errUnsupportedFormat);
cbLineS = (pIE->cbPixel * pIE->uWidth + 3) / 4 * 4;
bmpFH.uOffBits = (U32)(sizeof(bmpFH) + sizeof(bmpIH) + cbColorTable);
bmpFH.uSize = (U32)(bmpFH.uOffBits + cbLineS * pIE->uHeight);
bmpIH.iWidth = pIE->uWidth;
bmpIH.iHeight = pIE->uHeight;
bmpIH.iPlanes = 1;
bmpIH.iBitCount = (I16)(8 * pIE->cbPixel);
bmpIH.uImageSize = (U32)(cbLineS * pIE->uHeight);
bmpIH.iPelsPerMeterX = (I32)(pIE->fResX * 39.37);
bmpIH.iPelsPerMeterY = (I32)(pIE->fResY * 39.37);
Call(pS->Write(pS, &bmpFH, sizeof(bmpFH)));
Call(pS->Write(pS, &bmpIH, sizeof(bmpIH)));
Call(pS->Write(pS, rguColorTable, cbColorTable));
pIE->offPixel = pIE->offStart + bmpFH.uOffBits;
pIE->fHeaderDone = !FALSE;
Cleanup:
return err;
}
ERR PKImageEncode_WritePixels_BMP(
PKImageEncode* pIE,
U32 cLine,
U8* pbPixel,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pIE->pStream;
size_t cbLineM = 0, cbLineS = 0;
I32 i = 0;
static U8 pPadding[4] = {0};
// header
if (!pIE->fHeaderDone)
{
// WriteBMPHeader() also inits this object
Call(WriteBMPHeader(pIE));
}
// body
// calculate line size in memory and in stream
cbLineM = pIE->cbPixel * pIE->uWidth;
cbLineS = (cbLineM + 3) / 4 * 4;
//FailIf(pRect->X < 0 || pID->uWidth <= pRect->X, WMP_errInvalidParameter);
//FailIf(pRect->Y < 0 || pID->uHeight <= pRect->Y, WMP_errInvalidParameter);
//FailIf(pRect->Width < 0 || pID->uWidth < pRect->X + pRect->Width, WMP_errInvalidParameter);
//FailIf(pRect->Height < 0 || pID->uHeight < pRect->Y + pRect->Height, WMP_errInvalidParameter);
FailIf(cbStride < cbLineM, WMP_errInvalidParameter);
for (i = cLine - 1; 0 <= i; --i)
{
size_t offM = cbStride * i;
size_t offS = cbLineS * (pIE->uHeight - (pIE->idxCurrentLine + i + 1));
Call(pS->SetPos(pS, pIE->offPixel + offS));
Call(pS->Write(pS, pbPixel + offM, cbLineM));
}
Call(pS->Write(pS, pPadding, (cbLineS - cbLineM)));
pIE->idxCurrentLine += cLine;
Cleanup:
return err;
}
ERR PKImageEncode_Create_BMP(
PKImageEncode** ppIE)
{
ERR err = WMP_errSuccess;
PKImageEncode* pIE = NULL;
Call(PKImageEncode_Create(ppIE));
pIE = *ppIE;
pIE->WritePixels = PKImageEncode_WritePixels_BMP;
Cleanup:
return err;
}
//================================================================
// PKImageDecode_BMP
//================================================================
ERR ParseBMPHeader(
PKTestDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
BITMAPFILEHEADER bmpFH = {0};
BITMAPINFOHEADER bmpIH = {0};
static U32 bmpIHE[32] = {0}; // should be >= sizeof(BITMAPV5HEADER) - sizeof(BITMAPINFOHEADER)
static U32 rguColorTable[256] = {0};
U32 i = 0;
Call(pWS->Read(pWS, &bmpFH, sizeof(bmpFH)));
FailIf(bmpFH.szBM != (U8 *) strstr((char *) bmpFH.szBM, "BM"), WMP_errUnsupportedFormat);
Call(pWS->Read(pWS, &bmpIH, sizeof(bmpIH)));
FailIf(((sizeof(bmpIH) > bmpIH.uSize) || ((sizeof(bmpIH) + sizeof(bmpIHE)) < bmpIH.uSize)), WMP_errUnsupportedFormat);
if (sizeof(bmpIH) < bmpIH.uSize)
Call(pWS->Read(pWS, &bmpIHE, bmpIH.uSize - sizeof(bmpIH)));
switch (bmpIH.iBitCount)
{
case 8:
// check the color table to verify the image is actually gray scale
Call(pWS->Read(pWS, rguColorTable, sizeof(rguColorTable)));
for (i = 0; i < sizeof2(rguColorTable); ++i)
{
U32 c = i | (i << 8) | (i << 16);
FailIf(c != rguColorTable[i], WMP_errUnsupportedFormat);
}
pID->guidPixFormat = GUID_PKPixelFormat8bppGray;
pID->EXT.BMP.cbPixel = 1;
break;
case 16:
// Call(pWS->Read(pWS, rguColorTable, sizeof(rguColorTable[0] * 3)));
/* if (BI_RGB555_MASK_B == rguColorTable[0] && BI_RGB555_MASK_G == rguColorTable[1] && BI_RGB555_MASK_R == rguColorTable[2])
{
pID->guidPixFormat = GUID_PKPixelFormat16bppRGB555;
}
if (BI_RGB565_MASK_B == rguColorTable[0] && BI_RGB565_MASK_G == rguColorTable[1] && BI_RGB565_MASK_R == rguColorTable[2])
{
pID->guidPixFormat = GUID_PKPixelFormat16bppRGB565;
}
else
{
Call(WMP_errUnsupportedFormat);
}
*/
pID->EXT.BMP.cbPixel = 2;
break;
case 24:
pID->guidPixFormat = GUID_PKPixelFormat24bppBGR;
pID->EXT.BMP.cbPixel = 3;
break;
case 32:
/* Call(pWS->Read(pWS, rguColorTable, sizeof(rguColorTable[0] * 3)));
if (BI_RGB101010_MASK_B == rguColorTable[0] && BI_RGB101010_MASK_G == rguColorTable[1] && BI_RGB101010_MASK_R == rguColorTable[2])
{
pID->guidPixFormat = GUID_PKPixelFormat32bppRGB101010;
}
else
{
Call(WMP_errUnsupportedFormat);
}
*/
// pID->guidPixFormat = GUID_PKPixelFormat32bppBGRA;
pID->EXT.BMP.cbPixel = 4;
break;
default:
Call(WMP_errUnsupportedFormat);
break;
}
pID->uWidth = (U32)bmpIH.iWidth;
pID->uHeight = (U32)bmpIH.iHeight;
pID->fResX = (0 == bmpIH.iPelsPerMeterX ? 96 : (Float)(bmpIH.iPelsPerMeterX * .0254));
pID->fResY = (0 == bmpIH.iPelsPerMeterY ? 96 : (Float)(bmpIH.iPelsPerMeterY * .0254));
pID->EXT.BMP.offPixel = pID->offStart + bmpFH.uOffBits;
Cleanup:
return err;
}
ERR PKImageDecode_Initialize_BMP(
PKTestDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
Call(PKTestDecode_Initialize(pID, pWS));
Call(ParseBMPHeader(pID, pWS));
Cleanup:
return err;
}
ERR PKImageDecode_Copy_BMP(
PKTestDecode* pID,
const PKRect* pRect,
U8* pb,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pID->pStream;
size_t cbLineS = (pID->EXT.BMP.cbPixel * pID->uWidth + 3) / 4 * 4;
size_t cbLineM = pID->EXT.BMP.cbPixel * pRect->Width;
I32 i = 0;
//FailIf(pRect->X < 0 || pID->uWidth <= pRect->X, WMP_errInvalidParameter);
//FailIf(pRect->Y < 0 || pID->uHeight <= pRect->Y, WMP_errInvalidParameter);
//FailIf(pRect->Width < 0 || pID->uWidth < pRect->X + pRect->Width, WMP_errInvalidParameter);
//FailIf(pRect->Height < 0 || pID->uHeight < pRect->Y + pRect->Height, WMP_errInvalidParameter);
FailIf(cbStride < cbLineM, WMP_errInvalidParameter);
for (i = pRect->Y + pRect->Height - 1; pRect->Y <= i; --i)
{
size_t offLine = pID->EXT.BMP.cbPixel * pRect->X;
size_t offS = cbLineS * (pID->uHeight - i - 1) + offLine;
size_t offM = cbStride * (i - pRect->Y) + offLine;
Call(pS->SetPos(pS, pID->EXT.BMP.offPixel + offS));
Call(pS->Read(pS, pb + offM, cbLineM));
}
Cleanup:
return err;
}
ERR PKImageDecode_Create_BMP(
PKTestDecode** ppID)
{
ERR err = WMP_errSuccess;
PKTestDecode* pID = NULL;
Call(PKTestDecode_Create(ppID));
pID = *ppID;
pID->Initialize = PKImageDecode_Initialize_BMP;
pID->Copy = PKImageDecode_Copy_BMP;
Cleanup:
return err;
}

View file

@ -0,0 +1,242 @@
//*@@@+++@@@@******************************************************************
//
// Copyright © Microsoft Corp.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// • Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// • Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//*@@@---@@@@******************************************************************
#ifndef ANSI
#define _CRT_SECURE_NO_WARNINGS
#endif ANSI
#include <stdlib.h>
#include <string.h>
#include <JXRTest.h>
#pragma pack(push, 1)
#pragma pack(pop)
//================================================================
// PKImageEncode_HDR
//================================================================
ERR WriteHDRHeader(
PKImageEncode* pIE)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pIE->pStream;
char txtbuff[100];
strcpy(txtbuff, "#?RADIANCE\nFORMAT=32-bit_rle_rgbe\n\n");
Call(pS->Write(pS, txtbuff, strlen(txtbuff)));
pIE->offPixel = strlen(txtbuff);
sprintf(txtbuff, "-Y %d +X %d\n", pIE->uHeight, pIE->uWidth);
Call(pS->Write(pS, txtbuff, strlen(txtbuff)));
pIE->offPixel += strlen(txtbuff);
pIE->cbPixel = 4;
pIE->fHeaderDone = !FALSE;
Cleanup:
return err;
}
ERR PKImageEncode_WritePixels_HDR(
PKImageEncode* pIE,
U32 cLine,
U8* pbPixel,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pIE->pStream;
size_t cbLineM = 0, cbLineS = 0;
size_t i = 0;
// header
if (!pIE->fHeaderDone)
{
// WriteHDRHeader() also inits this object
Call(WriteHDRHeader(pIE));
}
// body
// calculate line size in memory and in stream
cbLineM = pIE->cbPixel * pIE->uWidth;
cbLineS = (cbLineM + 3) / 4 * 4;
//FailIf(pRect->X < 0 || pID->uWidth <= pRect->X, WMP_errInvalidParameter);
//FailIf(pRect->Y < 0 || pID->uHeight <= pRect->Y, WMP_errInvalidParameter);
//FailIf(pRect->Width < 0 || pID->uWidth < pRect->X + pRect->Width, WMP_errInvalidParameter);
//FailIf(pRect->Height < 0 || pID->uHeight < pRect->Y + pRect->Height, WMP_errInvalidParameter);
FailIf(cbStride < cbLineM, WMP_errInvalidParameter);
for (i = 0; i <= cLine - 1; i++)
{
size_t offM = cbStride * i;
size_t offS = cbLineS * (pIE->idxCurrentLine + i);
Call(pS->SetPos(pS, pIE->offPixel + offS));
Call(pS->Write(pS, pbPixel + offM, cbLineM));
}
pIE->idxCurrentLine += cLine;
Cleanup:
return err;
}
ERR PKImageEncode_Create_HDR(
PKImageEncode** ppIE)
{
ERR err = WMP_errSuccess;
PKImageEncode* pIE = NULL;
Call(PKImageEncode_Create(ppIE));
pIE = *ppIE;
pIE->WritePixels = PKImageEncode_WritePixels_HDR;
Cleanup:
return err;
}
//================================================================
// PKImageDecode_HDR
//================================================================
ERR ParseHDRHeader(
PKTestDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
char txtbuff[512];
Bool done = FALSE;
FailIf(NULL == fgets(txtbuff, 12, pWS->state.file.pFile), WMP_errUnsupportedFormat);
FailIf(0 != strcmp(txtbuff, "#?RADIANCE\n"), WMP_errUnsupportedFormat);
// Read lines to image size
while (!done) {
FailIf(NULL == fgets(txtbuff, 512, pWS->state.file.pFile), WMP_errUnsupportedFormat);
if (0 == strncmp(txtbuff, "FORMAT", 6)) {
FailIf(0 != strcmp(txtbuff, "FORMAT=32-bit_rle_rgbe\n"), WMP_errUnsupportedFormat);
}
if (0 == strncmp(txtbuff, "-Y", 2)) {
sscanf(txtbuff, "-Y %d +X %d\n", &pID->uHeight, &pID->uWidth);
done = TRUE;
}
}
Call(pWS->Read(pWS, txtbuff, 3));
if(((2 == txtbuff[0]) && (2 == txtbuff[1]) && (0 == (txtbuff[2] & 0x80))) ||
((1 == txtbuff[0]) && (1 == txtbuff[1]) && (1 == txtbuff[2])))
{
printf("Doesn't support compressed HDR files.\n");
err = WMP_errUnsupportedFormat;
goto Cleanup;
}
// Set header other header parameters
pID->guidPixFormat = GUID_PKPixelFormat32bppRGBE;
pID->EXT.HDR.cbPixel = 4;
// Set pointer to first pixel
Call(pWS->GetPos(pWS, &pID->EXT.HDR.offPixel));
pID->EXT.HDR.offPixel -= 3;
Call(pWS->SetPos(pWS, pID->EXT.HDR.offPixel));
// We don't need: pID->fResX and pID->fResY
Cleanup:
return err;
}
ERR PKImageDecode_Initialize_HDR(
PKTestDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
Call(PKTestDecode_Initialize(pID, pWS));
Call(ParseHDRHeader(pID, pWS));
Cleanup:
return err;
}
ERR PKImageDecode_Copy_HDR(
PKTestDecode* pID,
const PKRect* pRect,
U8* pb,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pID->pStream;
size_t cbLineS = (pID->EXT.HDR.cbPixel * pID->uWidth + 3) / 4 * 4;
size_t cbLineM = pID->EXT.HDR.cbPixel * pRect->Width;
I32 i = 0;
//FailIf(pRect->X < 0 || pID->uWidth <= pRect->X, WMP_errInvalidParameter);
//FailIf(pRect->Y < 0 || pID->uHeight <= pRect->Y, WMP_errInvalidParameter);
//FailIf(pRect->Width < 0 || pID->uWidth < pRect->X + pRect->Width, WMP_errInvalidParameter);
//FailIf(pRect->Height < 0 || pID->uHeight < pRect->Y + pRect->Height, WMP_errInvalidParameter);
FailIf(cbStride < cbLineM, WMP_errInvalidParameter);
for (i = pRect->Y ; i < pRect->Y + pRect->Height ; i++)
{
size_t offLine = pID->EXT.HDR.cbPixel * pRect->X;
size_t offS = cbLineS * i + offLine;
size_t offM = cbStride * (i - pRect->Y) + offLine;
Call(pS->SetPos(pS, pID->EXT.HDR.offPixel + offS));
Call(pS->Read(pS, pb + offM, cbLineM));
}
Cleanup:
return err;
}
ERR PKImageDecode_Create_HDR(
PKTestDecode** ppID)
{
ERR err = WMP_errSuccess;
PKTestDecode* pID = NULL;
Call(PKTestDecode_Create(ppID));
pID = *ppID;
pID->Initialize = PKImageDecode_Initialize_HDR;
pID->Copy = PKImageDecode_Copy_HDR;
Cleanup:
return err;
}

View file

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>JXRTestLib</ProjectName>
<ProjectGuid>{A69603CC-65E8-443F-8E31-737DBD6BB0DC}</ProjectGuid>
<RootNamespace>JXRTestLib</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)/$(ProjectName)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(OutDir)</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Configuration)\$(ProjectName)\$(Platform)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)/$(ProjectName)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(OutDir)</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Configuration)\$(ProjectName)\$(Platform)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)</IntDir>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\image\sys;..\image\x86;..\JXRTestLib;..\JXRGlueLib;..\common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(ProjectName).lib</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\image\sys;..\image\x86;..\JXRTestLib;..\JXRGlueLib;..\common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(ProjectName).lib</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<WholeProgramOptimization>true</WholeProgramOptimization>
<AdditionalIncludeDirectories>..\image\sys;..\image\x86;..\JXRTestLib;..\JXRGlueLib;..\common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;ENABLE_OPTIMIZATIONS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Lib>
<AdditionalOptions>/LTCG %(AdditionalOptions)</AdditionalOptions>
<OutputFile>$(OutDir)$(ProjectName).lib</OutputFile>
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>..\image\sys;..\image\x86;..\JXRTestLib;..\JXRGlueLib;..\common\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<WholeProgramOptimization>true</WholeProgramOptimization>
</ClCompile>
<Lib>
<OutputFile>$(OutDir)$(ProjectName).lib</OutputFile>
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="JXRTest.c" />
<ClCompile Include="JXRTestBmp.c" />
<ClCompile Include="JXRTestHdr.c" />
<ClCompile Include="JXRTestPnm.c" />
<ClCompile Include="JXRTestTif.c" />
<ClCompile Include="JXRTestYUV.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="JXRTest.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,331 @@
//*@@@+++@@@@******************************************************************
//
// Copyright © Microsoft Corp.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// • Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// • Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//*@@@---@@@@******************************************************************
#ifndef ANSI
#define _CRT_SECURE_NO_WARNINGS
#endif ANSI
#include <stdlib.h>
#include <JXRTest.h>
//================================================================
// PKImageEncode_PNM helpers
//================================================================
ERR WritePNMHeader(PKImageEncode* pIE)
{
ERR err = WMP_errSuccess;
PKPixelInfo PI;
struct WMPStream* pS = pIE->pStream;
U8 buf[64] = {0};
int cb = 0;
char szSig[2];
U32 uMaxVal = 0;
PI.pGUIDPixFmt = &pIE->guidPixFormat;
PixelFormatLookup(&PI, LOOKUP_FORWARD);
if (IsEqualGUID(&GUID_PKPixelFormatBlackWhite, PI.pGUIDPixFmt))
{
szSig[0] = 'P', szSig[1] = '5';
uMaxVal = 1;
}
else if (IsEqualGUID(&GUID_PKPixelFormat8bppGray, PI.pGUIDPixFmt))
{
szSig[0] = 'P', szSig[1] = '5';
uMaxVal = 255;
}
else if (IsEqualGUID(&GUID_PKPixelFormat24bppRGB, PI.pGUIDPixFmt))
{
szSig[0] = 'P', szSig[1] = '6';
uMaxVal = 255;
}
else if (IsEqualGUID(&GUID_PKPixelFormat48bppRGB, PI.pGUIDPixFmt))
{
szSig[0] = 'P', szSig[1] = '6';
uMaxVal = 65535;
}
else if (IsEqualGUID(&GUID_PKPixelFormat16bppGray, PI.pGUIDPixFmt))
{
szSig[0] = 'P', szSig[1] = '6';
uMaxVal = 65535;
}
else if (IsEqualGUID(&GUID_PKPixelFormat96bppRGBFloat, PI.pGUIDPixFmt))
{
szSig[0] = 'P', szSig[1] = 'F';
}
else
Call(WMP_errUnsupportedFormat);
if('P' == szSig[0] && 'F' == szSig[1])
cb = sprintf((char *) buf, "%c%c\n%u\n%u\n%s\n",
szSig[0], szSig[1], (int)pIE->uWidth, (int)pIE->uHeight, "-1.0000");
else
cb = sprintf((char *) buf, "%c%c\n%u %u\n%u\n",
szSig[0], szSig[1], (int)pIE->uWidth, (int)pIE->uHeight, (int)uMaxVal);
assert(cb < sizeof2(buf));
Call(pS->Write(pS, buf, cb));
Call(pS->GetPos(pS, &pIE->offPixel));
pIE->cbPixel = ((PI.cbitUnit + 7) >> 3);// ->cbPixel / pPI->cbPixelDenom;
pIE->fHeaderDone = !FALSE;
Cleanup:
return err;
}
//================================================================
// PKImageEncode_PNM
//================================================================
ERR PKImageEncode_WritePixels_PNM(
PKImageEncode* pIE,
U32 cLine,
U8* pbPixel,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pIE->pStream;
size_t cbLine = 0;
size_t offPos = 0;
size_t i = 0;
// header
if (!pIE->fHeaderDone)
{
Call(WritePNMHeader(pIE));
}
// body
cbLine = pIE->cbPixel * pIE->uWidth;
FailIf(cbStride < cbLine, WMP_errInvalidParameter);
offPos = pIE->offPixel + cbLine * pIE->idxCurrentLine;
Call(pS->SetPos(pS, offPos));
for (i = 0; i < cLine; ++i)
{
Call(pS->Write(pS, pbPixel + cbStride * i, cbLine));
}
pIE->idxCurrentLine += cLine;
Cleanup:
return err;
}
ERR PKImageEncode_Create_PNM(
PKImageEncode** ppIE)
{
ERR err = WMP_errSuccess;
PKImageEncode* pIE = NULL;
Call(PKImageEncode_Create(ppIE));
pIE = *ppIE;
pIE->WritePixels = PKImageEncode_WritePixels_PNM;
Cleanup:
return err;
}
//================================================================
// PKImageDecode_PNM helpers
//================================================================
ERR GetLineSkipPound(struct WMPStream* pWS, U8* pb, size_t cb)
{
ERR err = WMP_errSuccess;
U8 *pb1;
size_t cb1;
do
{
pb1 = pb;
cb1 = cb;
do {
Call(pWS->Read(pWS, pb1, 1));
cb1--;
pb1++;
}
while (cb1 > 0 && pb1[-1] != '\n');
//Call(pWS->GetLine(pWS, pb, cb));
} while('#' == pb[0]);
Cleanup:
return err;
}
ERR ParsePNMHeader(
PKTestDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
U8 line[128] = {0};
size_t idxChannel = 0, idxBitDepth = 0;
unsigned int width = 0, height = 0, maxval = 0;
static const PKPixelFormatGUID* pixFormat[2][2] =
{
{&GUID_PKPixelFormat8bppGray, &GUID_PKPixelFormat16bppGray,},
{&GUID_PKPixelFormat24bppRGB, &GUID_PKPixelFormat48bppRGB,},
};
//================================
Call(GetLineSkipPound(pWS, line, sizeof2(line)));
if (line == (U8 *) strstr((char *) line, "P5"))
{
idxChannel = 0;
Call(GetLineSkipPound(pWS, line, sizeof2(line)));
FailIf(2 != sscanf((char *) line, "%u %u", &width, &height), WMP_errUnsupportedFormat);
}
else if(line == (U8 *) strstr((char *) line, "P6"))
{
idxChannel = 1;
Call(GetLineSkipPound(pWS, line, sizeof2(line)));
FailIf(2 != sscanf((char *) line, "%u %u", &width, &height), WMP_errUnsupportedFormat);
}
else if(line == (U8 *) strstr((char *) line, "PF"))
{
idxChannel = 2;
Call(GetLineSkipPound(pWS, line, sizeof2(line)));
FailIf(1 != sscanf((char *) line, "%u", &width), WMP_errUnsupportedFormat);
Call(GetLineSkipPound(pWS, line, sizeof2(line)));
FailIf(1 != sscanf((char *) line, "%u", &height), WMP_errUnsupportedFormat);
}
else
{
Call(WMP_errUnsupportedFormat);
}
//================================
// Call(GetLineSkipPound(pWS, line, sizeof2(line)));
// FailIf(2 != sscanf(line, "%u %u", &width, &height), WMP_errUnsupportedFormat);
FailIf(0 == width || 0 == height, WMP_errUnsupportedFormat);
pID->uWidth = (U32)width;
pID->uHeight = (U32)height;
//================================
Call(GetLineSkipPound(pWS, line, sizeof2(line)));
FailIf(1 != sscanf((char *) line, "%u", &maxval), WMP_errUnsupportedFormat);
if (2==idxChannel)
{
FailIf(maxval != -1, WMP_errUnsupportedFormat);
pID->guidPixFormat = GUID_PKPixelFormat96bppRGBFloat;
}
else
{
FailIf(maxval < 1 || 65535 < maxval, WMP_errUnsupportedFormat);
idxBitDepth = 255 < maxval;
pID->guidPixFormat = *pixFormat[idxChannel][idxBitDepth];
}
Call(pWS->GetPos(pWS, &pID->EXT.PNM.offPixel));
Cleanup:
return err;
}
//================================================================
// PKImageDecode_PNM
//================================================================
ERR PKImageDecode_Initialize_PNM(
PKTestDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
Call(PKTestDecode_Initialize(pID, pWS));
Call(ParsePNMHeader(pID, pWS));
Cleanup:
return err;
}
ERR PKImageDecode_Copy_PNM(
PKTestDecode* pID,
const PKRect* pRect,
U8* pb,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pID->pStream;
PKPixelInfo PI;
size_t cbLineS = 0;
size_t cbLineM = 0;
I32 i = 0;
PI.pGUIDPixFmt = &pID->guidPixFormat;
PixelFormatLookup(&PI, LOOKUP_FORWARD);
cbLineS = (BD_1 == PI.bdBitDepth ? ((PI.cbitUnit * pID->uWidth + 7) >> 3) : (((PI.cbitUnit + 7) >> 3) * pID->uWidth));
cbLineM = (BD_1 == PI.bdBitDepth ? ((PI.cbitUnit * pRect->Width + 7) >> 3) : (((PI.cbitUnit + 7) >> 3) * pRect->Width));
FailIf(cbStride < cbLineM, WMP_errInvalidParameter);
for (i = 0; i < pRect->Height; ++i)
{
size_t offLine = (BD_1 == PI.bdBitDepth ? ((PI.cbitUnit * pRect->X + 7) >> 3) : (((PI.cbitUnit + 7) >> 3) * pRect->X));
size_t offS = cbLineS * (pRect->Y + i) + offLine;
size_t offM = cbStride * i + offLine;
Call(pS->SetPos(pS, pID->EXT.PNM.offPixel + offS));
Call(pS->Read(pS, pb + offM, cbLineM));
}
Cleanup:
return err;
}
ERR PKImageDecode_Create_PNM(
PKTestDecode** ppID)
{
ERR err = WMP_errSuccess;
PKTestDecode* pID = NULL;
Call(PKTestDecode_Create(ppID));
pID = *ppID;
pID->Initialize = PKImageDecode_Initialize_PNM;
pID->Copy = PKImageDecode_Copy_PNM;
Cleanup:
return err;
}

View file

@ -0,0 +1,936 @@
//*@@@+++@@@@******************************************************************
//
// Copyright © Microsoft Corp.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// • Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// • Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//*@@@---@@@@******************************************************************
#include <stdlib.h>
#include <string.h>
#include <strcodec.h>
#include <JXRTest.h>
//================================================================
#define TIF_tagNull 0
#define TIF_tagSubfileType 0xff
#define TIF_tagNewSubfileType 0xfe
#define TIF_tagImageWidth 0x100
#define TIF_tagImageLength 0x101
#define TIF_tagBitsPerSample 0x102
#define TIF_tagCompression 0x103
#define TIF_tagPhotometricInterpretation 0x106
#define TIF_tagStripOffsets 0x111
#define TIF_tagOrientation 0x112
#define TIF_tagSamplesPerPixel 0x115
#define TIF_tagRowsPerStrip 0x116
#define TIF_tagStripByteCounts 0x117
#define TIF_tagXResolution 0x11a
#define TIF_tagYResolution 0x11b
#define TIF_tagPlanarConfiguration 0x11c
#define TIF_tagResolutionUnit 0x128
#define TIF_tagSoftware 0x131
#define TIF_tagColorMap 0x140
#define TIF_tagPredictor 0x13d
#define TIF_tagInkSet 0x14c
#define TIF_tagExtraSamples 0x152
#define TIF_tagSampleFormat 0x153
#define TIF_typBYTE 1
#define TIF_typASCII 2
#define TIF_typSHORT 3
#define TIF_typLONG 4
#define TIF_typRATIOAL 5
#define TIF_typSBYTE 6
#define TIF_typUNDEFINED 7
#define TIF_typSSHORT 8
#define TIF_typSLONG 9
#define TIF_typSRATIONAL 10
#define TIF_typFLOAT 11
#define TIF_typDOUBLE 12
//================================================================
typedef float FLOAT;
typedef double DOUBLE;
//================================================================
// PKImageEncode_TIF helpers
//================================================================
typedef struct tagTifDE
{
U16 uTag;
U16 uType;
U32 uCount;
U32 uValueOrOffset;
} TifDE;
typedef struct tagTifDEMisc
{
U32 offBitsPerSample;
U32 offSampleFormat;
U32 bps, spp, sf;
U32 iPhotometricInterpretation;
U32 offXResolution;
U32 resXF, resXD;
U32 offYResolution;
U32 resYF, resYD;
} TifDEMisc;
ERR PutTifUShort(
struct WMPStream* pS,
size_t offPos,
U16 uValue)
{
ERR err = WMP_errSuccess;
Call(pS->SetPos(pS, offPos));
Call(pS->Write(pS, &uValue, sizeof(uValue)));
Cleanup:
return err;
}
ERR PutTifULong(
struct WMPStream* pS,
size_t offPos,
U32 uValue)
{
ERR err = WMP_errSuccess;
Call(pS->SetPos(pS, offPos));
Call(pS->Write(pS, &uValue, sizeof(uValue)));
Cleanup:
return err;
}
ERR WriteTifDE(
struct WMPStream* pS,
size_t offPos,
TifDE* pDE)
{
ERR err = WMP_errSuccess;
assert(-1 != pDE->uCount);
assert(-1 != pDE->uValueOrOffset);
Call(PutTifUShort(pS, offPos, pDE->uTag)); offPos += 2;
Call(PutTifUShort(pS, offPos, pDE->uType)); offPos += 2;
Call(PutTifULong(pS, offPos, pDE->uCount)); offPos += 4;
switch (pDE->uType)
{
case TIF_typSHORT:
if (1 == pDE->uCount)
{
Call(PutTifUShort(pS, offPos, (U16)pDE->uValueOrOffset)); offPos += 2;
Call(PutTifUShort(pS, offPos, 0)); offPos += 2;
break;
}
case TIF_typLONG:
case TIF_typRATIOAL:
Call(PutTifULong(pS, offPos, pDE->uValueOrOffset)); offPos += 4;
break;
default:
Call(WMP_errInvalidParameter);
break;
}
Cleanup:
return err;
}
ERR WriteTifHeader(
PKImageEncode* pIE)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pIE->pStream;
size_t offPos = 0;
#ifdef _BIG__ENDIAN_
U8 IIMM[3] = "MM";
#else // _BIG__ENDIAN_
U8 IIMM[3] = "II";
#endif // _BIG__ENDIAN_
TifDEMisc tifDEMisc = {
(U32) -1, (U32) -1, (U32) -1, (U32) -1, (U32) -1,
2, // photometric interpretation
(U32) -1, 10000, 10000,
(U32) -1, 10000, 10000,
};
// const U32 cbTifDEMisc = sizeof(U16) * 10 + sizeof(U32) * 2 * 2;
const static TifDE tifDEs[] =
{
{0x100, 4, 1, (U32) -1}, // TIF_tagImageWidth
{0x101, 4, 1, (U32) -1}, // TIF_tagImageLength
{0x102, 3, (U32) -1, (U32) -1}, // TIF_tagBitsPerSample
{0x103, 3, 1, 1}, // TIF_tagCompression
{0x106, 3, 1, (U32) -1}, // TIF_tagPhotometricInterpretation
{0x111, 4, 1, (U32) -1}, // TIF_tagStripOffsets
{0x112, 3, 1, 1}, // TIF_tagOrientation
{0x115, 3, 1, (U32) -1}, // TIF_tagSamplesPerPixel
{0x116, 4, 1, (U32) -1}, // TIF_tagRowsPerStrip
{0x117, 4, 1, (U32) -1}, // TIF_tagStripByteCounts
{0x11a, 5, 1, (U32) -1}, // TIF_tagXResolution
{0x11b, 5, 1, (U32) -1}, // TIF_tagYResolution
{0x11c, 3, 1, 1}, // TIF_tagPlanarConfiguration
{0x128, 3, 1, 2}, // TIF_tagResolutionUnit
{0x153, 3, (U32) -1, (U32) -1}, // TIF_tagSampleFormat
// {0x131, 2, -1, -1}, // TIF_tagSoftware
// {0x140, 3, -1, -1}, // TIF_tagColorMap
};
U16 cTifDEs = sizeof2(tifDEs);
TifDE tifDE = {0};
PKPixelInfo PI;
size_t cbLine = 0;
size_t i = 0;
size_t j;
tifDEMisc.resXF = (U32)(pIE->fResX * 10000);
tifDEMisc.resYF = (U32)(pIE->fResY * 10000);
Call(pS->GetPos(pS, &offPos));
FailIf(0 != offPos, WMP_errUnsupportedFormat);
//================
// TifHeader
Call(pS->Write(pS, IIMM, 2)); offPos += 2;
Call(PutTifUShort(pS, offPos, 42)); offPos += 2;
Call(PutTifULong(pS, offPos, (U32)(offPos + 4))); offPos += 4;
//================
// TifDEMisc
PI.pGUIDPixFmt = &pIE->guidPixFormat;
PixelFormatLookup(&PI, LOOKUP_FORWARD);
tifDEMisc.iPhotometricInterpretation =
//the N channel TIF by PS has PhotometricInterpretation of PK_PI_RGB
PI.uInterpretation == PK_PI_NCH || PI.uInterpretation == PK_PI_RGBE ? PK_PI_RGB :
(PI.uInterpretation == PK_PI_B0 && pIE->WMP.wmiSCP.bBlackWhite ? PK_PI_W0 : PI.uInterpretation);
tifDEMisc.spp = PI.uSamplePerPixel;
tifDEMisc.bps = PI.uBitsPerSample;
tifDEMisc.sf = PI.uSampleFormat;
if (tifDEMisc.iPhotometricInterpretation == PK_PI_CMYK)
cTifDEs++;
if (PI.grBit & PK_pixfmtHasAlpha)
cTifDEs++;
tifDEMisc.offBitsPerSample = (U32)offPos + sizeof(U16) + 12 * cTifDEs + sizeof(U32);
tifDEMisc.offSampleFormat = tifDEMisc.offBitsPerSample + (tifDEMisc.spp == 1 ? 0 : tifDEMisc.spp * 2);
tifDEMisc.offXResolution = tifDEMisc.offSampleFormat + (tifDEMisc.spp == 1 ? 0 : tifDEMisc.spp * 2);
tifDEMisc.offYResolution = tifDEMisc.offXResolution + 8;
//================
// TifIFD
pIE->offPixel = tifDEMisc.offYResolution + 8;
Call(PutTifUShort(pS, offPos, cTifDEs)); offPos += 2;
//================
tifDE = tifDEs[i++];
assert(TIF_tagImageWidth == tifDE.uTag);
tifDE.uValueOrOffset = pIE->uWidth;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagImageLength == tifDE.uTag);
tifDE.uValueOrOffset = pIE->uHeight;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagBitsPerSample == tifDE.uTag);
tifDE.uCount = tifDEMisc.spp;
tifDE.uValueOrOffset = 1 == tifDE.uCount ? tifDEMisc.bps : tifDEMisc.offBitsPerSample;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagCompression == tifDE.uTag);
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagPhotometricInterpretation == tifDE.uTag);
tifDE.uValueOrOffset = tifDEMisc.iPhotometricInterpretation;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagStripOffsets == tifDE.uTag);
tifDE.uValueOrOffset = (U32)pIE->offPixel;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagOrientation == tifDE.uTag);
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagSamplesPerPixel == tifDE.uTag);
tifDE.uValueOrOffset = tifDEMisc.spp;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagRowsPerStrip == tifDE.uTag);
tifDE.uValueOrOffset = pIE->uHeight;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagStripByteCounts == tifDE.uTag);
cbLine = (BD_1 == PI.bdBitDepth ? ((PI.cbitUnit * pIE->uWidth + 7) >> 3) : (((PI.cbitUnit + 7) >> 3) * pIE->uWidth));
tifDE.uValueOrOffset = (U32)(cbLine * pIE->uHeight);
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagXResolution == tifDE.uTag);
tifDE.uValueOrOffset = tifDEMisc.offXResolution;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagYResolution == tifDE.uTag);
tifDE.uValueOrOffset = tifDEMisc.offYResolution;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagPlanarConfiguration == tifDE.uTag);
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
tifDE = tifDEs[i++];
assert(TIF_tagResolutionUnit == tifDE.uTag);
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
if (tifDEMisc.iPhotometricInterpretation == PK_PI_CMYK)
{
TifDE tifDE = {TIF_tagInkSet, 3, 1, 1};
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
}
if (PI.grBit & PK_pixfmtHasAlpha)
{
TifDE tifDE = {TIF_tagExtraSamples, 3, 1, 1};
if (!(PI.grBit & PK_pixfmtPreMul))
tifDE.uValueOrOffset++;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
}
tifDE = tifDEs[i++];
assert(TIF_tagSampleFormat == tifDE.uTag);
tifDE.uCount = tifDEMisc.spp;
tifDE.uValueOrOffset = 1 == tifDE.uCount ? tifDEMisc.sf : tifDEMisc.offSampleFormat;
Call(WriteTifDE(pS, offPos, &tifDE)); offPos += 12;
//================
Call(PutTifULong(pS, offPos, 0)); offPos += 4;
//================
// TifDEMisc
if (tifDE.uCount > 1)
{
assert(tifDEMisc.offBitsPerSample == offPos);
if (PI.bdBitDepth == BD_565)
{
Call(PutTifUShort(pS, offPos, 5)); offPos += 2;
Call(PutTifUShort(pS, offPos, 6)); offPos += 2;
Call(PutTifUShort(pS, offPos, 5)); offPos += 2;
}
else
{
for (j = 0; j < tifDE.uCount; j++)
{
Call(PutTifUShort(pS, offPos, (U16)tifDEMisc.bps)); offPos += 2;
}
}
assert(tifDEMisc.offSampleFormat == offPos);
for (j = 0; j < tifDE.uCount; j++)
{
Call(PutTifUShort(pS, offPos, (U16)tifDEMisc.sf)); offPos += 2;
}
}
assert(tifDEMisc.offXResolution == offPos);
Call(PutTifULong(pS, offPos, tifDEMisc.resXF)); offPos += 4;
Call(PutTifULong(pS, offPos, tifDEMisc.resXD)); offPos += 4;
assert(tifDEMisc.offYResolution == offPos);
Call(PutTifULong(pS, offPos, tifDEMisc.resYF)); offPos += 4;
Call(PutTifULong(pS, offPos, tifDEMisc.resYD)); offPos += 4;
assert(pIE->offPixel == offPos);
pIE->fHeaderDone = !FALSE;
Cleanup:
return err;
}
//================================================================
// PKImageEncode_TIF
//================================================================
ERR PKImageEncode_WritePixels_TIF(
PKImageEncode* pIE,
U32 cLine,
U8* pbPixel,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pIE->pStream;
PKPixelInfo PI;
size_t cbLine = 0;
size_t offPos = 0;
size_t i = 0;
// header
if (!pIE->fHeaderDone)
{
Call(WriteTifHeader(pIE));
}
// body
PI.pGUIDPixFmt = &pIE->guidPixFormat;
PixelFormatLookup(&PI, LOOKUP_FORWARD);
cbLine = (BD_1 == PI.bdBitDepth ? ((PI.cbitUnit * pIE->uWidth + 7) >> 3) : (((PI.cbitUnit + 7) >> 3) * pIE->uWidth));
FailIf(cbStride < cbLine, WMP_errInvalidParameter);
offPos = pIE->offPixel + cbLine * pIE->idxCurrentLine;
Call(pS->SetPos(pS, offPos));
for (i = 0; i < cLine; ++i)
{
Call(pS->Write(pS, pbPixel + cbStride * i, cbLine));
}
pIE->idxCurrentLine += cLine;
Cleanup:
return err;
}
ERR PKImageEncode_Create_TIF(PKImageEncode** ppIE)
{
ERR err = WMP_errSuccess;
PKImageEncode* pIE = NULL;
Call(PKImageEncode_Create(ppIE));
pIE = *ppIE;
pIE->WritePixels = PKImageEncode_WritePixels_TIF;
Cleanup:
return err;
}
//================================================================
// PKImageDecode_TIF helpers
//================================================================
ERR GetTifUShort(
struct WMPStream* pWS,
size_t offPos,
Bool fLittleEndian,
U16* puValue)
{
ERR err = WMP_errSuccess;
U8 buf[2];
Call(pWS->SetPos(pWS, offPos));
Call(pWS->Read(pWS, buf, sizeof2(buf)));
if (fLittleEndian)
{
*puValue = buf[0] + ((U16)buf[1] << 8);
}
else
{
*puValue = ((U16)buf[0] << 8) + buf[1];
}
Cleanup:
return err;
}
ERR GetTifULong(
struct WMPStream* pWS,
size_t offPos,
Bool fLittleEndian,
U32* puValue)
{
ERR err = WMP_errSuccess;
U8 buf[4];
Call(pWS->SetPos(pWS, offPos));
Call(pWS->Read(pWS, buf, sizeof2(buf)));
if (fLittleEndian)
{
*puValue = buf[0] + ((U32)buf[1] << 8) + ((U32)buf[2] << 16) + ((U32)buf[3] << 24);
}
else
{
*puValue = ((U32)buf[0] << 24) + ((U32)buf[1] << 16) + ((U32)buf[2] << 8) + buf[3];
}
Cleanup:
return err;
}
ERR GetTifULongArray(
struct WMPStream* pWS,
size_t offPos,
size_t cElements,
Bool fLittleEndian,
U32* puValue)
{
ERR err = WMP_errSuccess;
if (1 == cElements)
{
puValue[0] = (U32)offPos;
}
else
{
size_t i = 0;
for (i = 0; i < cElements; ++i)
{
Call(GetTifULong(pWS, offPos, fLittleEndian, &puValue[i]));
offPos += sizeof(*puValue);
}
}
Cleanup:
return err;
}
ERR ParseTifDEValue(
PKTestDecode* pID,
U16 uTag,
U16 uType,
U32 uCount)
{
ERR err = WMP_errSuccess;
struct WMPStream* pWS = pID->pStream;
U16 bpc[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
U16 sf[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
U32 uPos = 0;
U16 usValue = 0;
U32 uValue0 = 0;
U32 uValue1 = 0;
size_t i, offPos = 0;
//================================
Call(pWS->GetPos(pWS, &offPos));
//================================
switch (uType)
{
case TIF_typSHORT:
Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &usValue));
uValue0 = usValue;
break;
case TIF_typLONG:
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uValue0));
break;
}
//================================
switch (uTag)
{
case TIF_tagNewSubfileType:
FailIf(0 != uValue0, WMP_errUnsupportedFormat);
break;
case TIF_tagSubfileType:
case TIF_tagPredictor:
FailIf(1 != uValue0, WMP_errUnsupportedFormat);
break;
case TIF_tagImageWidth:
pID->uWidth = uValue0;
break;
case TIF_tagImageLength:
pID->uHeight = uValue0;
break;
case TIF_tagBitsPerSample:
if (1 == uCount)
{
pID->EXT.TIF.uBitsPerSample = uValue0;
}
else
{
Bool bpcAnd = 1;
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uPos));
offPos = uPos;
Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &bpc[0]));
for (i = 1; i < uCount; i++)
{
Call(GetTifUShort(pWS, offPos + (i << 1) , pID->EXT.TIF.fLittleEndian, &bpc[i]));
bpcAnd = (bpcAnd && (bpc[0] == bpc[i]));
}
if (bpcAnd)
pID->EXT.TIF.uBitsPerSample = bpc[0];
else
Call(WMP_errUnsupportedFormat);
}
break;
case TIF_tagExtraSamples:
FailIf(0 != uValue0 && 1 != uValue0 && 2 != uValue0, WMP_errUnsupportedFormat);
pID->EXT.TIF.uExtraSamples = uValue0;
break;
case TIF_tagSampleFormat:
if (1 == uCount)
{
pID->EXT.TIF.uSampleFormat = uValue0;
}
else
{
Bool sfAnd = 1;
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uPos));
offPos = uPos;
Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &sf[0]));
for (i = 1; i < uCount; i++)
{
Call(GetTifUShort(pWS, offPos + (i << 1) , pID->EXT.TIF.fLittleEndian, &sf[i]));
sfAnd = (sfAnd && (sf[0] == sf[i]));
}
if (sfAnd)
pID->EXT.TIF.uSampleFormat = sf[0];
else
Call(WMP_errUnsupportedFormat);
}
break;
case TIF_tagCompression:
FailIf(1 != uValue0, WMP_errUnsupportedFormat);
break;
case TIF_tagPhotometricInterpretation:
Test(PK_PI_W0 == uValue0 || PK_PI_B0 == uValue0 || PK_PI_RGB == uValue0
|| PK_PI_RGBPalette == uValue0 || PK_PI_TransparencyMask == uValue0
|| PK_PI_CMYK == uValue0 || PK_PI_YCbCr == uValue0
|| PK_PI_CIELab == uValue0, WMP_errUnsupportedFormat);
pID->EXT.TIF.uInterpretation = uValue0;
break;
case TIF_tagStripOffsets:
Call(WMPAlloc((void **) &pID->EXT.TIF.uStripOffsets, sizeof(*pID->EXT.TIF.uStripOffsets) * uCount));
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uValue0));
Call(GetTifULongArray(pWS, uValue0, uCount, pID->EXT.TIF.fLittleEndian, pID->EXT.TIF.uStripOffsets));
break;
case TIF_tagOrientation:
case TIF_tagSamplesPerPixel:
pID->EXT.TIF.uSamplePerPixel = uValue0;
break;
case TIF_tagRowsPerStrip:
pID->EXT.TIF.uRowsPerStrip = uValue0;
break;
case TIF_tagStripByteCounts:
Call(WMPAlloc((void **) &pID->EXT.TIF.uStripByteCounts, sizeof(*pID->EXT.TIF.uStripByteCounts) * uCount));
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uValue0));
Call(GetTifULongArray(pWS, uValue0, uCount, pID->EXT.TIF.fLittleEndian, pID->EXT.TIF.uStripByteCounts));
break;
case TIF_tagXResolution:
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uPos));
offPos = uPos;
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uValue0));//numerator
Call(GetTifULong(pWS, offPos + 4, pID->EXT.TIF.fLittleEndian, &uValue1));//denominator
pID->EXT.TIF.fResX = (Float)uValue0/(Float)uValue1;
break;
case TIF_tagYResolution:
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uPos));
offPos = uPos;
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uValue0));//numerator
Call(GetTifULong(pWS, offPos + 4, pID->EXT.TIF.fLittleEndian, &uValue1));//denominator
pID->EXT.TIF.fResY = (Float)uValue0/(Float)uValue1;
break;
case TIF_tagResolutionUnit:
pID->EXT.TIF.uResolutionUnit = usValue;
break;
case TIF_tagPlanarConfiguration:
case TIF_tagSoftware:
case TIF_tagColorMap:
break;
default:
printf("Unrecognized TIFTag: %d(%#x), %d, %d" CRLF, (int)uTag, (int)uTag, (int)uType, (int)uCount);
break;
}
Cleanup:
return err;
}
ERR ParseTifDEArray(
PKTestDecode* pID,
size_t offPos)
{
ERR err = WMP_errSuccess;
struct WMPStream* pWS = pID->pStream;
U16 uTag = 0;
U16 uType = 0;
U32 uCount = 0;
Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uTag));
offPos += 2;
Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uType));
offPos += 2;
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uCount));
offPos += 4;
Call(ParseTifDEValue(pID, uTag, uType, uCount));
Cleanup:
return err;
}
ERR ParseTifHeader(
PKTestDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
PKPixelInfo PI;
size_t offPosBase = 0;
size_t offPos = 0;
U8 szSig[3] = {0, 0, '\0'};
U16 uTiffId = 0;
U32 uOffNextIFD = 0;
U16 uCountDE = 0, i = 0;
//default
pID->EXT.TIF.uRowsPerStrip = (U32) -1;
pID->EXT.TIF.uInterpretation = (U32) -1;
pID->EXT.TIF.uSamplePerPixel = (U32) -1;
pID->EXT.TIF.uBitsPerSample = (U32) -1;
pID->EXT.TIF.uSampleFormat = 1;
pID->EXT.TIF.uResolutionUnit = 2;
pID->EXT.TIF.fResX = 96;
pID->EXT.TIF.fResY = 96;
//================================
Call(pWS->GetPos(pWS, &offPosBase));
FailIf(0 != offPosBase, WMP_errUnsupportedFormat);
//================================
// Header
Call(pWS->Read(pWS, szSig, 2));
offPos += 2;
if (szSig == (U8 *) strstr((char *) szSig, "II"))
{
pID->EXT.TIF.fLittleEndian = !FALSE;
}
else if (szSig == (U8 *) strstr((char *) szSig, "MM"))
{
pID->EXT.TIF.fLittleEndian = FALSE;
}
else
{
Call(WMP_errUnsupportedFormat);
}
Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uTiffId));
offPos += 2;
FailIf(42 != uTiffId, WMP_errUnsupportedFormat);
Call(GetTifULong(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uOffNextIFD));
offPos += 4;
//================================
// IFD
offPos = (size_t)uOffNextIFD;
Call(GetTifUShort(pWS, offPos, pID->EXT.TIF.fLittleEndian, &uCountDE));
offPos += 2;
for (i = 0; i < uCountDE; ++i)
{
Call(ParseTifDEArray(pID, offPos));
offPos += 12;
}
if(pID->EXT.TIF.uRowsPerStrip == -1)
pID->EXT.TIF.uRowsPerStrip = pID->uHeight;//default
FailIf((-1 == pID->EXT.TIF.uInterpretation
|| -1 == pID->EXT.TIF.uSamplePerPixel
|| -1 == pID->EXT.TIF.uBitsPerSample), WMP_errUnsupportedFormat);
PI.uInterpretation = pID->EXT.TIF.uInterpretation;
PI.uSamplePerPixel = pID->EXT.TIF.uSamplePerPixel;
PI.uBitsPerSample = pID->EXT.TIF.uBitsPerSample;
PI.uSampleFormat = pID->EXT.TIF.uSampleFormat;
PI.grBit = pID->EXT.TIF.uExtraSamples == 1 || pID->EXT.TIF.uExtraSamples == 2 ||
/* Workaround for some images without correct info about alpha channel */
(pID->EXT.TIF.uExtraSamples == 0 && pID->EXT.TIF.uSamplePerPixel > 3) ? PK_pixfmtHasAlpha : 0x0;
PI.grBit |= pID->EXT.TIF.uExtraSamples == 1 ? PK_pixfmtPreMul : 0x0;
pID->fResX = (3 == pID->EXT.TIF.uResolutionUnit ? (Float)(pID->EXT.TIF.fResX * 2.54) : pID->EXT.TIF.fResX);//cm -> inch
pID->fResY = (3 == pID->EXT.TIF.uResolutionUnit ? (Float)(pID->EXT.TIF.fResY * 2.54) : pID->EXT.TIF.fResY);//cm -> inch
Call(PixelFormatLookup(&PI, LOOKUP_BACKWARD_TIF));
pID->guidPixFormat = *(PI.pGUIDPixFmt);
Cleanup:
return err;
}
//================================================================
// PKImageDecode_TIF
//================================================================
ERR PKImageDecode_Initialize_TIF(
PKTestDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
Call(PKTestDecode_Initialize(pID, pWS));
Call(ParseTifHeader(pID, pWS));
Cleanup:
return err;
}
ERR GetScanLineOffset(
PKTestDecode* pID,
I32 iLine,
U32 cbLine,
U32 *offLine)
{
*offLine = pID->EXT.TIF.uRowsPerStrip ?
(pID->EXT.TIF.uStripOffsets[iLine / pID->EXT.TIF.uRowsPerStrip] +
cbLine * (iLine % pID->EXT.TIF.uRowsPerStrip)) :
0;
return WMP_errSuccess;
}
ERR PKImageDecode_Copy_TIF(
PKTestDecode* pID,
const PKRect* pRect,
U8* pb,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pID->pStream;
PKPixelInfo PI;
U32 cbLine = 0;
I32 i = 0;
PI.pGUIDPixFmt = &pID->guidPixFormat;
PixelFormatLookup(&PI, LOOKUP_FORWARD);
cbLine = (BD_1 == PI.bdBitDepth ? ((PI.cbitUnit * pRect->Width + 7) >> 3) : (((PI.cbitUnit + 7) >> 3) * pRect->Width));
assert(0 == pRect->X && pID->uWidth == (U32)pRect->Width);
assert(cbLine <= cbStride);
for (i = 0; i < pRect->Height; ++i)
{
U32 offPixels = 0;
Call(GetScanLineOffset(pID, pRect->Y + i, cbLine, &offPixels));
Call(pS->SetPos(pS, offPixels));
Call(pS->Read(pS, pb + cbStride * i, cbLine));
if (PK_PI_W0 == pID->EXT.TIF.uInterpretation)
{
U32 j, begin = cbStride * (U32)i, end = begin + cbLine;
for (j = begin; j < end; ++j)
{
pb[j] = ~pb[j];
}
}
}
Cleanup:
return err;
}
ERR PKImageDecode_Release_TIF(PKTestDecode** ppID)
{
ERR err = WMP_errSuccess;
PKTestDecode *pID = *ppID;
Call(WMPFree(&pID->EXT.TIF.uStripOffsets));
Call(WMPFree(&pID->EXT.TIF.uStripByteCounts));
Call(PKTestDecode_Release(ppID));
Cleanup:
return err;
}
ERR PKImageDecode_Create_TIF(PKTestDecode** ppID)
{
ERR err = WMP_errSuccess;
PKTestDecode* pID = NULL;
Call(PKTestDecode_Create(ppID));
pID = *ppID;
pID->Initialize = PKImageDecode_Initialize_TIF;
pID->Copy = PKImageDecode_Copy_TIF;
pID->Release = PKImageDecode_Release_TIF;
Cleanup:
return err;
}

View file

@ -0,0 +1,723 @@
//*@@@+++@@@@******************************************************************
//
// Copyright © Microsoft Corp.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// • Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// • Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//*@@@---@@@@******************************************************************
#include <stdlib.h>
#include <string.h>
#include <JXRGlue.h>
#pragma pack(push, 1)
#pragma pack(pop)
//================================================================
// PKImageEncode_Iyuv
//================================================================
ERR WriteIYUVHeader(
PKImageEncode* pIE)
{
ERR err = WMP_errSuccess;
// struct WMPStream* pS = pIE->pStream;
pIE->offPixel = 0;
pIE->cbPixel = 3;
pIE->fHeaderDone = !FALSE;
return err;
}
//================================================================
// PKImageEncode_Yuv422
//================================================================
ERR WriteYUV422Header(
PKImageEncode* pIE)
{
ERR err = WMP_errSuccess;
// struct WMPStream* pS = pIE->pStream;
pIE->offPixel = 0;
pIE->cbPixel = 3;
pIE->fHeaderDone = !FALSE;
return err;
}
//================================================================
// PKImageEncode_Yuv444
//================================================================
ERR WriteYUV444Header(
PKImageEncode* pIE)
{
ERR err = WMP_errSuccess;
// struct WMPStream* pS = pIE->pStream;
pIE->offPixel = 0;
pIE->cbPixel = 3;
pIE->fHeaderDone = !FALSE;
return err;
}
ERR PKImageEncode_WritePixels_IYUV(
PKImageEncode* pIE,
U32 cLine,
U8* pbPixel,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pIE->pStream;
size_t iRow, iCol;
U32 uYSize, uUVSize;
U8 *pY;
U8 *pU;
U8 *pV;
UNREFERENCED_PARAMETER( cbStride );
// header
if (!pIE->fHeaderDone)
{
Call(WriteIYUVHeader(pIE));
}
//from packed to planar:
uYSize = cLine * pIE->uWidth;
uUVSize = (uYSize >> 2);
pY = (U8 *)malloc(uYSize);
pU = (U8 *)malloc(uUVSize);
pV = (U8 *)malloc(uUVSize);
if(pY == NULL || pU == NULL || pV == NULL)
{
return ICERR_ERROR;
}
for (iRow = 0; iRow < pIE->uHeight; iRow += 2, pY += pIE->uWidth)
{
for (iCol = 0; iCol < pIE->uWidth; iCol += 2, pY += 2)
{
*pY = *pbPixel;
pbPixel++;
*(pY + 1)= *pbPixel;
pbPixel++;
*(pY + pIE->uWidth) = *pbPixel;
pbPixel++;
*(pY + pIE->uWidth + 1) = *pbPixel;
pbPixel++;
*pU = *pbPixel;
pbPixel++; pU++;
*pV = *pbPixel;
pbPixel++; pV++;
}
}
pY-=uYSize;
pU-=uUVSize;
pV-=uUVSize;
Call(pS->Write(pS, pY, uYSize));
Call(pS->Write(pS, pU, uUVSize));
Call(pS->Write(pS, pV, uUVSize));
if(pY!=NULL)
free(pY);
if(pU!=NULL)
free(pU);
if(pV!=NULL)
free(pV);
pIE->idxCurrentLine += cLine;
Cleanup:
return err;
}
ERR PKImageEncode_WritePixels_YUV422(
PKImageEncode* pIE,
U32 cLine,
U8* pbPixel,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pIE->pStream;
size_t iRow, iCol;
U32 uYSize, uUVSize;
U8 *pY;
U8 *pU;
U8 *pV;
UNREFERENCED_PARAMETER( cbStride );
// header
if (!pIE->fHeaderDone)
{
Call(WriteIYUVHeader(pIE));
}
//from packed to planar:
uYSize = cLine * pIE->uWidth;
uUVSize = (uYSize >> 1);
pY = (U8 *)malloc(uYSize);
pU = (U8 *)malloc(uUVSize);
pV = (U8 *)malloc(uUVSize);
if(pY == NULL || pU == NULL || pV == NULL)
{
return ICERR_ERROR;
}
//YYUV
for (iRow = 0; iRow < pIE->uHeight; iRow += 1)
{
for (iCol = 0; iCol < pIE->uWidth; iCol += 2)
{
*pU = *pbPixel;
pbPixel++; pU++;
*pY = *pbPixel;
pbPixel++; pY++;
*pV = *pbPixel;
pbPixel++; pV++;
*pY = *pbPixel;
pbPixel++; pY++;
}
}
pY-=uYSize;
pU-=uUVSize;
pV-=uUVSize;
Call(pS->Write(pS, pY, uYSize));
Call(pS->Write(pS, pU, uUVSize));
Call(pS->Write(pS, pV, uUVSize));
if(pY!=NULL)
free(pY);
if(pU!=NULL)
free(pU);
if(pV!=NULL)
free(pV);
pIE->idxCurrentLine += cLine;
Cleanup:
return err;
}
ERR PKImageEncode_WritePixels_YUV444(
PKImageEncode* pIE,
U32 cLine,
U8* pbPixel,
U32 cbStride)
{
ERR err = WMP_errSuccess;
struct WMPStream* pS = pIE->pStream;
size_t iRow, iCol;
U32 uYSize, uUVSize;
U8 *pY;
U8 *pU;
U8 *pV;
UNREFERENCED_PARAMETER( cbStride );
// header
if (!pIE->fHeaderDone)
{
Call(WriteIYUVHeader(pIE));
}
//from packed to planar:
uYSize = cLine * pIE->uWidth;
uUVSize = uYSize;
pY = (U8 *)malloc(uYSize);
pU = (U8 *)malloc(uUVSize);
pV = (U8 *)malloc(uUVSize);
if(pY == NULL || pU == NULL || pV == NULL)
{
return ICERR_ERROR;
}
for (iRow = 0; iRow < pIE->uHeight; iRow += 1)
{
for (iCol = 0; iCol < pIE->uWidth; iCol += 1)
{
*pY = *pbPixel;
pbPixel++; pY++;
*pU = *pbPixel;
pbPixel++; pU++;
*pV = *pbPixel;
pbPixel++; pV++;
}
}
pY-=uYSize;
pU-=uUVSize;
pV-=uUVSize;
Call(pS->Write(pS, pY, uYSize));
Call(pS->Write(pS, pU, uUVSize));
Call(pS->Write(pS, pV, uUVSize));
if(pY!=NULL)
free(pY);
if(pU!=NULL)
free(pU);
if(pV!=NULL)
free(pV);
pIE->idxCurrentLine += cLine;
Cleanup:
return err;
}
ERR PKImageEncode_Create_IYUV(
PKImageEncode** ppIE)
{
ERR err = WMP_errSuccess;
PKImageEncode* pIE = NULL;
Call(PKImageEncode_Create(ppIE));
pIE = *ppIE;
pIE->WritePixels = PKImageEncode_WritePixels_IYUV;
Cleanup:
return err;
}
ERR PKImageEncode_Create_YUV422(
PKImageEncode** ppIE)
{
ERR err = WMP_errSuccess;
PKImageEncode* pIE = NULL;
Call(PKImageEncode_Create(ppIE));
pIE = *ppIE;
pIE->WritePixels = PKImageEncode_WritePixels_YUV422;
Cleanup:
return err;
}
ERR PKImageEncode_Create_YUV444(
PKImageEncode** ppIE)
{
ERR err = WMP_errSuccess;
PKImageEncode* pIE = NULL;
Call(PKImageEncode_Create(ppIE));
pIE = *ppIE;
pIE->WritePixels = PKImageEncode_WritePixels_YUV444;
Cleanup:
return err;
}
//================================================================
// PKImageDecode_IYUV
//================================================================
ERR ParseIYUVHeader(
PKImageDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
UNREFERENCED_PARAMETER( pWS );
// Set header other header parameters
pID->guidPixFormat = GUID_PKPixelFormat12bppYUV420;
pID->uHeight = 144;
pID->uWidth = 176;
//I don't need offpixel for raw data! Call(pWS->GetPos(pWS, &pID->YUV420.offPixel));
return err;
}
//================================================================
// PKImageDecode_YUV422
//================================================================
ERR ParseYUV422Header(
PKImageDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
UNREFERENCED_PARAMETER( pWS );
// Set header other header parameters
pID->guidPixFormat = GUID_PKPixelFormat16bppYUV422;
pID->uHeight = 144;
pID->uWidth = 176;
return err;
}
//================================================================
// PKImageDecode_YUV422
//================================================================
ERR ParseYUV444Header(
PKImageDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
UNREFERENCED_PARAMETER( pWS );
// Set header other header parameters
pID->guidPixFormat = GUID_PKPixelFormat24bppYUV444;
pID->uHeight = 144;
pID->uWidth = 176;
return err;
}
ERR PKImageDecode_Initialize_IYUV(
PKImageDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
Call(PKImageDecode_Initialize(pID, pWS));
Call(ParseIYUVHeader(pID, pWS));
Cleanup:
return err;
}
ERR PKImageDecode_Initialize_YUV422(
PKImageDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
Call(PKImageDecode_Initialize(pID, pWS));
Call(ParseYUV422Header(pID, pWS));
Cleanup:
return err;
}
ERR PKImageDecode_Initialize_YUV444(
PKImageDecode* pID,
struct WMPStream* pWS)
{
ERR err = WMP_errSuccess;
Call(PKImageDecode_Initialize(pID, pWS));
Call(ParseYUV444Header(pID, pWS));
Cleanup:
return err;
}
ERR PKImageDecode_Copy_IYUV(
PKImageDecode* pID,
const PKRect* pRect,
U8* pb,
U32 cbStride)
{
ERR err = WMP_errSuccess;
U32 uYSize, uUVSize;
U8 *pY;
U8 *pU;
U8 *pV;
struct WMPStream* pS = pID->pStream;
size_t iRow, iCol;
UNREFERENCED_PARAMETER( pRect );
UNREFERENCED_PARAMETER( cbStride );
//from planar to packed! YYYYUV YYYYUV
uYSize = pID->uWidth * pID->uHeight;
uUVSize = (uYSize >> 2);
pY = (U8 *)malloc(uYSize);
pU = (U8 *)malloc(uUVSize);
pV = (U8 *)malloc(uUVSize);
if(pY == NULL || pU == NULL || pV == NULL)
{
return ICERR_ERROR;
}
Call(pS->Read(pS, pY, uYSize));
Call(pS->Read(pS, pU, uUVSize));
Call(pS->Read(pS, pV, uUVSize));
//re-organize it to Y0 Y1
// Y2 Y3 U V
for (iRow = 0; iRow < pID->uHeight; iRow += 2, pY += pID->uWidth)
{
for (iCol = 0; iCol < pID->uWidth; iCol += 2, pY += 2)
{
*pb = *pY;
pb++;
*pb = *(pY + 1);
pb++;
*pb = *(pY + pID->uWidth);
pb++;
*pb = *(pY + pID->uWidth + 1);
pb++;
*pb = *pU;
pb++; pU++;
*pb = *pV;
pb++; pV++;
}
}
pY-=uYSize;
pU-=uUVSize;
pV-=uUVSize;
if(pY!=NULL)
free(pY);
if(pU!=NULL)
free(pU);
if(pV!=NULL)
free(pV);
Cleanup:
return err;
}
ERR PKImageDecode_Copy_YUV422(
PKImageDecode* pID,
const PKRect* pRect,
U8* pb,
U32 cbStride)
{
ERR err = WMP_errSuccess;
U32 uYSize, uUVSize;
U8 *pY;
U8 *pU;
U8 *pV;
struct WMPStream* pS = pID->pStream;
size_t iRow, iCol;
UNREFERENCED_PARAMETER( pRect );
UNREFERENCED_PARAMETER( cbStride );
uYSize = pID->uWidth * pID->uHeight;
uUVSize = (uYSize >> 1);
pY = (U8 *)malloc(uYSize);
pU = (U8 *)malloc(uUVSize);
pV = (U8 *)malloc(uUVSize);
if(pY == NULL || pU == NULL || pV == NULL)
{
return ICERR_ERROR;
}
Call(pS->Read(pS, pY, uYSize));
Call(pS->Read(pS, pU, uUVSize));
Call(pS->Read(pS, pV, uUVSize));
//re-organize to iMode 0 : YYUV
for (iRow = 0; iRow < pID->uHeight; iRow += 1)
{
for (iCol = 0; iCol < pID->uWidth; iCol += 2)
{
*pb = *pU;
pb++; pU++;
*pb = *pY;
pb++; pY++;
*pb = *pV;
pb++; pV++;
*pb = *pY;
pb++; pY++;
}
}
pY-=uYSize;
pU-=uUVSize;
pV-=uUVSize;
if(pY!=NULL)
free(pY);
if(pU!=NULL)
free(pU);
if(pV!=NULL)
free(pV);
Cleanup:
return err;
}
ERR PKImageDecode_Copy_YUV444(
PKImageDecode* pID,
const PKRect* pRect,
U8* pb,
U32 cbStride)
{
ERR err = WMP_errSuccess;
U32 uYSize, uUVSize;
U8 *pY;
U8 *pU;
U8 *pV;
struct WMPStream* pS = pID->pStream;
size_t iRow, iCol;
UNREFERENCED_PARAMETER( pRect );
UNREFERENCED_PARAMETER( cbStride );
//from planar to packed! YYYYUV YYYYUV
uYSize = pID->uWidth * pID->uHeight;
uUVSize = uYSize;
pY = (U8 *)malloc(uYSize);
pU = (U8 *)malloc(uUVSize);
pV = (U8 *)malloc(uUVSize);
if(pY == NULL || pU == NULL || pV == NULL)
{
return ICERR_ERROR;
}
Call(pS->Read(pS, pY, uYSize));
Call(pS->Read(pS, pU, uUVSize));
Call(pS->Read(pS, pV, uUVSize));
//Organize it as YUVYUVYUV...
for (iRow = 0; iRow < pID->uHeight; iRow += 1)
{
for (iCol = 0; iCol < pID->uWidth; iCol += 1)
{
*pb = *pY;
pb++; pY++;
*pb = *pU;
pb++; pU++;
*pb = *pV;
pb++; pV++;
}
}
pY-=uYSize;
pU-=uUVSize;
pV-=uUVSize;
if(pY!=NULL)
free(pY);
if(pU!=NULL)
free(pU);
if(pV!=NULL)
free(pV);
Cleanup:
return err;
}
ERR PKImageDecode_Create_IYUV(
PKImageDecode** ppID)
{
ERR err = WMP_errSuccess;
PKImageDecode* pID = NULL;
Call(PKImageDecode_Create(ppID));
pID = *ppID;
pID->Initialize = PKImageDecode_Initialize_IYUV;
pID->Copy = PKImageDecode_Copy_IYUV;
Cleanup:
return err;
}
ERR PKImageDecode_Create_YUV422(
PKImageDecode** ppID)
{
ERR err = WMP_errSuccess;
PKImageDecode* pID = NULL;
Call(PKImageDecode_Create(ppID));
pID = *ppID;
pID->Initialize = PKImageDecode_Initialize_YUV422;
pID->Copy = PKImageDecode_Copy_YUV422;
Cleanup:
return err;
}
ERR PKImageDecode_Create_YUV444(
PKImageDecode** ppID)
{
ERR err = WMP_errSuccess;
PKImageDecode* pID = NULL;
Call(PKImageDecode_Create(ppID));
pID = *ppID;
pID->Initialize = PKImageDecode_Initialize_YUV444;
pID->Copy = PKImageDecode_Copy_YUV444;
Cleanup:
return err;
}