// ezwconsole.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "ezwconsole.h"
#include "lib\codecy.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// The one and only application object
CWinApp theApp;
using namespace std;
//global data
CodecY gCodec;
void compress(int argc, TCHAR* argv[]);
void decompress(int argc, TCHAR* argv[]);
void help();
int get_encoder_clsid(const WCHAR* format, CLSID* pClsid);
void change_extension(wchar_t* path, const wchar_t* ext);
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
if (argc == 1+3 && wcscmp(argv[1], L"c") == 0)
compress(argc, argv);
else if (argc == 1+2 && wcscmp(argv[1], L"d") == 0)
decompress(argc, argv);
else
help();
}
Gdiplus::GdiplusShutdown(gdiplusToken);
return nRetCode;
}
void help()
{
wprintf(L"ezwconsole c image_file quality(0-100) - to compress the image\n"
L"ezwconsole d compressed_file.ezw - to decompress it to ezw.bmp and open it in image viewer\n");
}
void compress(int argc, TCHAR* argv[])
{
Gdiplus::Bitmap image(argv[2]);
if (image.GetLastStatus() == Gdiplus::Ok) {
wprintf(L"opened %s %dx%d\n", argv[2], image.GetWidth(), image.GetHeight());
unsigned int width = (image.GetWidth() % 8) ? image.GetWidth() - (image.GetWidth() % 8) : image.GetWidth();
unsigned int height = (image.GetHeight() % 8) ? image.GetHeight() - (image.GetHeight() % 8) : image.GetHeight();
Gdiplus::BitmapData bData;
Gdiplus::Status s = image.LockBits(&Gdiplus::Rect(0, 0, width, height), Gdiplus::ImageLockModeRead,
PixelFormat24bppRGB, &bData);
if (s == Gdiplus::Ok) {
unsigned char* gray = new unsigned char[width * height];
unsigned char* pgray = gray;
//rgb2gray
unsigned char* Pixels = (unsigned char *)bData.Scan0; //BGR triplet
for(unsigned int y = 0; y < height; y++) {
for(unsigned int x = 0; x < width; x++) {
*pgray++ = (unsigned char)(0.2989f * float(Pixels[3*x+2]) +
0.5870f * float(Pixels[3*x+1]) +
0.1140f * float(Pixels[3*x]));
}
Pixels += bData.Stride;
}
image.UnlockBits(&bData);
//compress gray
unsigned int size = 0;
unsigned int quality = _wtoi(argv[3]);
if (quality > 100) quality = 100;
quality = (unsigned int)(100.0f/log(100.0f) * log(float(quality))); //put quality to log scale
gCodec.initgray(width, height);
unsigned char* frame = gCodec.compressgray(gray, size, 100 - quality);
if (frame != 0) {
wchar_t name[_MAX_PATH];
wcscpy(name, argv[2]);
change_extension(name, L".ezw");
FILE* fp = _wfopen(name, L"wb");
if (fp != 0)
wprintf(L" compressed %s to %.2f Kb. 1:%.2f compression\n", argv[2],
(float)fwrite(frame, 1, size, fp) / 1000.0f, float(width * height) / float(size));
else
wprintf(L"failed to open %s for writing.\n", name);
fclose(fp);
}
else
wprintf(L"failed to compress image.\n");
delete[] gray;
}
else {
wprintf(L"failed to lock %s for data reading. err %d", argv[2], s);
return;
}
}
else {
wprintf(L"failed to open %s. err: %d", argv[2], image.GetLastStatus());
return;
}
}
void decompress(int argc, TCHAR* argv[])
{
FILE* fp = _wfopen(argv[2], L"rb");
if (fp != 0) {
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
rewind(fp);
if(size < 2 * sizeof(CODECHDR)) {
wprintf(L"the file %s is too small %d bytes.\n", argv[2], size);
fclose(fp);
return;
}
unsigned char* spec = new unsigned char[size];
fread(spec, 1, size, fp);
fclose(fp);
struct CODECHDR* phdr = (CODECHDR *)spec;
unsigned char* gray = new unsigned char[phdr->width * phdr->height];
gCodec.initgray(phdr->width, phdr->height);
int res = gCodec.decompressgray(gray, spec);
if (res < 0) {
wprintf(L"failed to decompress: %d\n", res);
delete[] gray;
delete[] spec;
return;
}
size = res;
unsigned int width = phdr->width;
unsigned int height = phdr->height;
delete[] spec;
unsigned char* bgr = new unsigned char[3 * size]; //arrange RGB buffer for saving image
for (unsigned int i = 0; i < size; i++) {
bgr[3*i] = gray[i];
bgr[3*i+1] = gray[i];
bgr[3*i+2] = gray[i];
}
delete[] gray;
Gdiplus::Bitmap image(width, height, 3 * width, PixelFormat24bppRGB, bgr);
CLSID encoder;
if (get_encoder_clsid(L"image/bmp", &encoder) >= 0) {
image.Save(L"ezw.bmp", &encoder);
ShellExecute(0, L"open", L"ezw.bmp", 0, 0, SW_SHOWNORMAL);
}
else
wprintf(L"failed to get encoder to save reconstructed image.\n");
delete[] bgr;
}
else
wprintf(L"failed to open %s", argv[2]);
}
void change_extension(wchar_t* path, const wchar_t* ext)
{
for (int i = (int)wcslen(path) - 1; i > 0; i--) {
if (path[i] == '.') {
path[i] = 0;
wcscat(path, ext);
return;
}
}
wcscat(path, ext);
}
int get_encoder_clsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;
Gdiplus::GetImageEncodersSize(&num, &size);
if (size == 0)
return -1; // Failure
pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL)
return -1; // Failure
Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);
for (UINT j = 0; j < num; ++j) {
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}