242 lines
7 KiB
C
242 lines
7 KiB
C
//*@@@+++@@@@******************************************************************
|
|
//
|
|
// 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;
|
|
}
|
|
|