ILboolean iLoadWdpInternal(/*ILconst_string FileName*/) { ERR err = WMP_errSuccess; PKFactory* pFactory = NULL; PKCodecFactory* pCodecFactory = NULL; PKImageDecode* pDecoder = NULL; PKPixelInfo PI; PKPixelFormatGUID guidPixFormat; PKFormatConverter* pConverter = NULL; U32 cFrame = 0, i = 0; PKRect Rect; struct WMPStream* pEncodeStream = NULL; PKImageEncode* pEncoder = NULL; //Call(PKCreateFactory(&pFactory, PK_SDK_VERSION)); //Call(PKCreateCodecFactory(&pCodecFactory, WMP_SDK_VERSION)); //Call(pCodecFactory->CreateDecoderFromFile(FileName, &pDecoder)); Call(ilPKCreateFactory(&pFactory, PK_SDK_VERSION)); Call(PKCreateCodecFactory(&pCodecFactory, WMP_SDK_VERSION)); Call(ilPKCodecFactory_CreateDecoderFromFile(&pDecoder)); //guidPixFormat = GUID_PKPixelFormat24bppRGB; guidPixFormat = GUID_PKPixelFormat32bppBGRA; //guidPixFormat = GUID_PKPixelFormat8bppGray; //guidPixFormat = GUID_PKPixelFormat16bppGray; // Color transcoding if (IsEqualGUID(&guidPixFormat, &GUID_PKPixelFormat8bppGray) || IsEqualGUID(&guidPixFormat, &GUID_PKPixelFormat16bppGray)){ // ** => Y transcoding pDecoder->guidPixFormat = guidPixFormat; pDecoder->WMP.wmiI.cfColorFormat = Y_ONLY; } else if(IsEqualGUID(&guidPixFormat, &GUID_PKPixelFormat24bppRGB) && pDecoder->WMP.wmiI.cfColorFormat == CMYK){ // CMYK = > RGB pDecoder->WMP.wmiI.cfColorFormat = CF_RGB; pDecoder->guidPixFormat = guidPixFormat; pDecoder->WMP.wmiI.bRGB = 1; //RGB } PI.pGUIDPixFmt = &guidPixFormat; PixelFormatLookup(&PI, LOOKUP_FORWARD); pDecoder->WMP.wmiSCP.bfBitstreamFormat = 0; pDecoder->WMP.wmiSCP.uAlphaMode = 0; pDecoder->WMP.wmiSCP.sbSubband = SB_ALL; pDecoder->WMP.bIgnoreOverlap = FALSE; pDecoder->WMP.wmiI.cfColorFormat = PI.cfColorFormat; pDecoder->WMP.wmiI.bdBitDepth = PI.bdBitDepth; pDecoder->WMP.wmiI.cBitsPerUnit = PI.cbitUnit; //==== Validate thumbnail decode parameters ===== pDecoder->WMP.wmiI.cThumbnailWidth = pDecoder->WMP.wmiI.cWidth; pDecoder->WMP.wmiI.cThumbnailHeight = pDecoder->WMP.wmiI.cHeight; pDecoder->WMP.wmiI.bSkipFlexbits = FALSE; pCodecFactory->CreateFormatConverter(&pConverter); pConverter->Initialize(pConverter, pDecoder, NULL, guidPixFormat); // Right now, we are just assuming one frame. // @TODO: Deal with multiple frames. //pDecoder->GetFrameCount(pDecoder, &cFrame); //pDecoder->SelectFrame(pDecoder, 1); if (!ilTexImage(pDecoder->uWidth, pDecoder->uHeight, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) goto Cleanup; //ilTexImage(pDecoder->uWidth, pDecoder->uHeight, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, Data); pFactory->CreateStreamFromMemory(&pEncodeStream, iCurImage->Data, iCurImage->SizeOfData); iWmpDecAppCreateEncoderFromExt(pCodecFactory, ".wdp", &pEncoder); pEncoder->Initialize(pEncoder, pEncodeStream, ".wdp", 0); pEncoder->pStream->GetPos(pEncoder->pStream, &pEncoder->offStart); // Set the region that we want to be the whole image. Rect.X = 0; Rect.Y = 0; Rect.Height = pDecoder->uHeight; Rect.Width = pDecoder->uWidth; pEncoder->SetPixelFormat(pEncoder, guidPixFormat); pEncoder->SetSize(pEncoder, Rect.Width, Rect.Height); pEncoder->WriteSource = PKImageEncode_Transcode; pEncoder->WriteSource(pEncoder, pConverter, &Rect); Cleanup: // Release everything all at the end. PKImageDecode_Release(&pDecoder); if (pEncoder) PKImageEncode_Release(&pEncoder); PKCreateCodecFactory_Release(&pCodecFactory); PKCreateFactory_Release(&pFactory); PKFormatConverter_Release(&pConverter); if (err != WMP_errSuccess) return IL_FALSE; return IL_TRUE; }
/** Copy or convert & copy decoded pixels into the dib @param pDecoder Decoder handle @param out_guid_format Target guid format @param dib Output dib @param width Image width @param height Image height @return Returns 0 if successful, returns ERR otherwise */ static ERR CopyPixels(PKImageDecode *pDecoder, PKPixelFormatGUID out_guid_format, FIBITMAP *dib, int width, int height) { PKFormatConverter *pConverter = NULL; // pixel format converter ERR error_code = 0; // error code as returned by the interface BYTE *pb = NULL; // local buffer used for pixel format conversion // image dimensions const PKRect rect = {0, 0, width, height}; try { // get input file pixel format ... PKPixelFormatGUID in_guid_format; error_code = pDecoder->GetPixelFormat(pDecoder, &in_guid_format); JXR_CHECK(error_code); // is a format conversion needed ? if(IsEqualGUID(out_guid_format, in_guid_format)) { // no conversion, load bytes "as is" ... // get a pointer to dst pixel data BYTE *dib_bits = FreeImage_GetBits(dib); // get dst pitch (count of BYTE for stride) const unsigned cbStride = FreeImage_GetPitch(dib); // decode and copy bits to dst array error_code = pDecoder->Copy(pDecoder, &rect, dib_bits, cbStride); JXR_CHECK(error_code); } else { // we need to use the conversion API ... // allocate the pixel format converter error_code = PKCodecFactory_CreateFormatConverter(&pConverter); JXR_CHECK(error_code); // set the conversion function error_code = pConverter->Initialize(pConverter, pDecoder, NULL, out_guid_format); JXR_CHECK(error_code); // get the maximum stride unsigned cbStride = 0; { PKPixelInfo pPIFrom; PKPixelInfo pPITo; pPIFrom.pGUIDPixFmt = &in_guid_format; error_code = PixelFormatLookup(&pPIFrom, LOOKUP_FORWARD); JXR_CHECK(error_code); pPITo.pGUIDPixFmt = &out_guid_format; error_code = PixelFormatLookup(&pPITo, LOOKUP_FORWARD); JXR_CHECK(error_code); unsigned cbStrideFrom = ((pPIFrom.cbitUnit + 7) >> 3) * width; unsigned cbStrideTo = ((pPITo.cbitUnit + 7) >> 3) * width; cbStride = MAX(cbStrideFrom, cbStrideTo); } // allocate a local decoder / encoder buffer error_code = PKAllocAligned((void **) &pb, cbStride * height, 128); JXR_CHECK(error_code); // copy / convert pixels error_code = pConverter->Copy(pConverter, &rect, pb, cbStride); JXR_CHECK(error_code); // now copy pixels into the dib const size_t line_size = FreeImage_GetLine(dib); for(int y = 0; y < height; y++) { BYTE *src_bits = (BYTE*)(pb + y * cbStride); BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, y); memcpy(dst_bits, src_bits, line_size); } // free the local buffer PKFreeAligned((void **) &pb); // free the pixel format converter PKFormatConverter_Release(&pConverter); } // FreeImage DIB are upside-down relative to usual graphic conventions FreeImage_FlipVertical(dib); // post-processing ... // ------------------- // swap RGB as needed #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR if(IsEqualGUID(out_guid_format, GUID_PKPixelFormat24bppRGB) || IsEqualGUID(out_guid_format, GUID_PKPixelFormat32bppRGB)) { SwapRedBlue32(dib); } #elif FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB if(IsEqualGUID(out_guid_format, GUID_PKPixelFormat24bppBGR) || IsEqualGUID(out_guid_format, GUID_PKPixelFormat32bppBGR)) { SwapRedBlue32(dib); } #endif return WMP_errSuccess; } catch(...) { // free the local buffer PKFreeAligned((void **) &pb); // free the pixel format converter PKFormatConverter_Release(&pConverter); return error_code; } }