//================================================================ // main function //================================================================ int #ifndef __ANSI__ __cdecl #endif // __ANSI__ main(int argc, char* argv[]) { if (argc != 5) { fprintf(stderr, "Required arguments:\n"); fprintf(stderr, "1. JPEG quality value, 0-100\n"); fprintf(stderr, "2. Image size (e.g. '512x512')\n"); fprintf(stderr, "3. Path to YUV input file\n"); fprintf(stderr, "4. Path to JXR output file\n"); return 1; } errno = 0; long quality = strtol(argv[1], NULL, 10); if (errno != 0 || quality < 0 || quality > 100) { fprintf(stderr, "Invalid JPEG quality value!\n"); return 1; } const char *size = argv[2]; const char *x = strchr(size, 'x'); if (!x && x != size && x != (x + strlen(x) - 1)) { fprintf(stderr, "Invalid image size input!\n"); return 1; } long width = strtol(size, NULL, 10); if (errno != 0) { fprintf(stderr, "Invalid image size input!\n"); return 1; } long height = strtol(x + 1, NULL, 10); if (errno != 0) { fprintf(stderr, "Invalid image size input!\n"); return 1; } /* Right now we only support dimensions that are multiples of 16. */ if ((width % 16) != 0 || (height % 16) != 0) { fprintf(stderr, "Image dimensions must be multiples of 16!\n"); return 1; } /* Will check these for validity when opening via 'fopen'. */ const char *yuv_path = argv[3]; const char *jxr_path = argv[4]; int yuv_size = width*height+2*(width>>1)*(height>>1); unsigned char *image_buffer = (unsigned char*)malloc(yuv_size); // set encoder parameters including quality { CWMIStrCodecParam params; init_encoder_params(¶ms, quality); // run encoder ERR err; PKFactory* pFactory = NULL; PKCodecFactory* pCodecFactory = NULL; struct WMPStream* pEncodeStream = NULL; PKImageEncode* pEncoder = NULL; const PKIID* pIID = NULL; struct WMPStream* pDecodeStream = NULL; PKImageDecode* pDecoder = NULL; Call( PKCreateFactory(&pFactory, PK_SDK_VERSION) ); Call( pFactory->CreateStreamFromFilename(&pEncodeStream, jxr_path, "wb") ); Call( pFactory->CreateStreamFromFilename(&pDecodeStream, yuv_path, "rb") ); // decode PKRect rc; rc.X = 0; rc.Y = 0; rc.Width = width; rc.Height = height; Call( GetTestDecodeIID(".iyuv", &pIID) ); Call( PKTestFactory_CreateCodec(pIID, (void **) &pDecoder) ); Call( pDecoder->Initialize(pDecoder, pDecodeStream) ); pDecoder->uWidth = width; pDecoder->uHeight = height; Call( pDecoder->Copy(pDecoder, &rc, (U8*)image_buffer, width) ); Call( PKCreateCodecFactory(&pCodecFactory, WMP_SDK_VERSION) ); Call( pCodecFactory->CreateCodec(&IID_PKImageWmpEncode, (void**)&pEncoder) ); Call( pEncoder->Initialize(pEncoder, pEncodeStream, ¶ms, sizeof(params)) ); Call( pEncoder->SetPixelFormat(pEncoder, GUID_PKPixelFormat12bppYCC420) ); Call( pEncoder->SetSize(pEncoder, width, height) ); Call( pEncoder->WritePixels(pEncoder, height, (U8*)image_buffer, width*3) ); Cleanup: if( pDecoder ) pDecoder->Release(&pDecoder); if( pEncoder ) pEncoder->Release(&pEncoder); if( pCodecFactory ) pCodecFactory->Release(&pCodecFactory); if( pFactory ) pFactory->Release(&pFactory); } free(image_buffer); return 0; }
static BOOL DLL_CALLCONV Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { BOOL bIsFlipped = FALSE; // FreeImage DIB are upside-down relative to usual graphic conventions PKPixelFormatGUID guid_format; // image format PKPixelInfo pixelInfo; // image specifications BOOL bHasAlpha = FALSE; // is alpha layer present ? PKImageEncode *pEncoder = NULL; // encoder interface ERR error_code = 0; // error code as returned by the interface // get the I/O stream wrapper WMPStream *pEncodeStream = (WMPStream*)data; if(!dib || !handle || !pEncodeStream) { return FALSE; } try { // get image dimensions unsigned width = FreeImage_GetWidth(dib); unsigned height = FreeImage_GetHeight(dib); // check JPEG-XR limits if((width < MB_WIDTH_PIXEL) || (height < MB_HEIGHT_PIXEL)) { FreeImage_OutputMessageProc(s_format_id, "Unsupported image size: width x height = %d x %d", width, height); throw (const char*)NULL; } // get output pixel format error_code = GetOutputPixelFormat(dib, &guid_format, &bHasAlpha); JXR_CHECK(error_code); pixelInfo.pGUIDPixFmt = &guid_format; error_code = PixelFormatLookup(&pixelInfo, LOOKUP_FORWARD); JXR_CHECK(error_code); // create a JXR encoder interface and initialize function pointers with *_WMP functions error_code = PKImageEncode_Create_WMP(&pEncoder); JXR_CHECK(error_code); // attach the stream to the encoder and set all encoder parameters to zero ... error_code = pEncoder->Initialize(pEncoder, pEncodeStream, &pEncoder->WMP.wmiSCP, sizeof(CWMIStrCodecParam)); JXR_CHECK(error_code); // ... then configure the encoder SetEncoderParameters(&pEncoder->WMP.wmiSCP, &pixelInfo, flags, bHasAlpha); // set pixel format pEncoder->SetPixelFormat(pEncoder, guid_format); // set image size pEncoder->SetSize(pEncoder, width, height); // set resolution (convert from universal units to English units) float resX = (float)(unsigned)(0.5F + 0.0254F * FreeImage_GetDotsPerMeterX(dib)); float resY = (float)(unsigned)(0.5F + 0.0254F * FreeImage_GetDotsPerMeterY(dib)); pEncoder->SetResolution(pEncoder, resX, resY); // set metadata WriteMetadata(pEncoder, dib); // write metadata & pixels // ----------------------- // dib coordinates are upside-down relative to usual conventions bIsFlipped = FreeImage_FlipVertical(dib); // 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); // write metadata + pixels on output error_code = pEncoder->WritePixels(pEncoder, height, dib_bits, cbStride); JXR_CHECK(error_code); // recover dib coordinates FreeImage_FlipVertical(dib); // free the encoder pEncoder->Release(&pEncoder); assert(pEncoder == NULL); return TRUE; } catch (const char *message) { if(bIsFlipped) { // recover dib coordinates FreeImage_FlipVertical(dib); } if(pEncoder) { // free the encoder pEncoder->Release(&pEncoder); assert(pEncoder == NULL); } if(NULL != message) { FreeImage_OutputMessageProc(s_format_id, message); } } return FALSE; }