⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fractalsqueeze.c

📁 分形图像压缩源代码
💻 C
字号:
/*******************************************************************/
/*                                                                 */
/*      Fractal Squeeze 1.0                                        */
/*                                                                 */
/*      Alexander Davidson                                         */
/*      96107642                                                   */
/*      December 2000                                              */
/*                                                                 */
/*******************************************************************/

#include "FractalSqueeze.h"

#include <commdlg.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <png.h>

#include "resource.h"

#define MAXFILELENGTH 256
#define IDS_TITLE "FractalSqueeze"
#define IDS_CLASSNAME "FRACTALSQUEEZE"

#define LOAD_IMAGE_FILE 0
#define SAVE_IMAGE_FILE 1
#define LOAD_FSQ_FILE 2
#define SAVE_FSQ_FILE 3

// Global Variables:
HINSTANCE hInst;	// current instance
HWND hwndMain;		// main window handle
png_infop image_data; // data for currently loaded file

// Prototypes:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
BOOL PNGLoad(char *file_name);
BOOL PNGWrite(char *file_name);
void fractal_encode(png_infop image_data, char* outputfilename);
void fractal_decode(png_infop image_data, char* inputfilename);

//
//  FUNCTION: WinMain()
//
//  PURPOSE: Program entry function
//
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	MSG msg;
	HACCEL hAccelTable;

	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow)) 
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_FRACTALSQUEEZE);

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return msg.wParam;
}

//
//  FUNCTION: CleanUp()
//
//  PURPOSE: Cleans up any leftover memory.
//
void CleanUp()
{
	if (image_data) {
		png_free_data(NULL, image_data, PNG_FREE_ALL, -1);
	}
}

//
//  FUNCTION: DoFileIO()
//
//  PURPOSE: Loads or saves data to files.
//
void DoFileIO(int iotype)
{
	OPENFILENAME ofn;
	CHAR szFilter[MAXFILELENGTH];
	CHAR szDefExt[4];
	CHAR szFile[MAXFILELENGTH] = "";
	HCURSOR hcur;

	if (iotype == SAVE_IMAGE_FILE || iotype == LOAD_IMAGE_FILE)	{
		lstrcpy(szFilter, "Portable Network Graphics (*.png)|*.png|All Files (*.*)|*.*|");
		lstrcpy(szDefExt, "png");
	}
	else if (iotype == SAVE_FSQ_FILE || iotype == LOAD_FSQ_FILE) {
		lstrcpy(szFilter, "FractalSqueeze (*.fsq)|*.fsq|All Files (*.*)|*.*|");
		lstrcpy(szDefExt, "fsq");
	}
	
	{ // fix filter string to conform to required format (double null-terminated)
		char* p = szFilter;
		while (*p != '\0') {
			if (*p == '|') *p = '\0';
			++p;
		}
	}

	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hwndMain;
	ofn.lpstrFilter = szFilter;
	ofn.lpstrCustomFilter = (LPTSTR)NULL;
	ofn.nMaxCustFilter = 0L;
	ofn.nFilterIndex = 1L;
	ofn.lpstrFile = szFile;
	ofn.nMaxFile = sizeof(szFile);
	ofn.lpstrFileTitle = (LPTSTR)NULL;
	ofn.nMaxFileTitle = 0L;
	ofn.lpstrInitialDir = (LPTSTR) NULL;
	ofn.lpstrTitle = (LPTSTR)NULL;
	if (iotype == LOAD_FSQ_FILE || iotype == LOAD_IMAGE_FILE)	
		ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
	else if (iotype == SAVE_FSQ_FILE || iotype == SAVE_IMAGE_FILE)
		ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;

	ofn.nFileOffset = 0;
	ofn.nFileExtension = 0;
	ofn.lpstrDefExt = szDefExt;

	switch (iotype) {
	case LOAD_IMAGE_FILE:
		if (GetOpenFileName(&ofn)) {
			PNGLoad(szFile);
		}
		break;
	case SAVE_IMAGE_FILE:
		if (GetSaveFileName(&ofn)) {
			PNGWrite(szFile);
		}
		break;
	case LOAD_FSQ_FILE:
		if (GetOpenFileName(&ofn)) {
			hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
			fractal_decode(image_data, szFile);
			SetCursor(hcur); // restore cursor
		}
		break;
	case SAVE_FSQ_FILE:
		if (GetSaveFileName(&ofn)) {
			hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
			fractal_encode(image_data, szFile);
			SetCursor(hcur); // restore cursor
		}
		break;
	}
}

//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_FRACTALSQUEEZE);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCSTR)IDC_FRACTALSQUEEZE;
	wcex.lpszClassName	= IDS_CLASSNAME;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_FRACTALSQUEEZE);

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HANDLE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handle in our global variable

   hwndMain = CreateWindow(IDS_CLASSNAME, IDS_TITLE, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hwndMain)
   {
      return FALSE;
   }

   ShowWindow(hwndMain, nCmdShow);
   UpdateWindow(hwndMain);

   return TRUE;
}

//
//  FUNCTION: PNGWrite()
//
//  PURPOSE: Writes currently loaded image_data to a PNG file
//
BOOL PNGWrite(char* file_name)
{
   FILE *fp;
   png_structp png_ptr;

   /* open the file */
   fp = fopen(file_name, "wb");
   if (fp == NULL)
      return FALSE;

   /* Create and initialize the png_struct with the desired error handler
    * functions.  If you want to use the default stderr and longjump method,
    * you can supply NULL for the last three parameters.  We also check that
    * the library version is compatible with the one used at compile time,
    * in case we are using dynamically linked libraries.  REQUIRED.
    */
   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,	0, 0, 0);

   if (png_ptr == NULL)
   {
      fclose(fp);
      return FALSE;
   }

   /* Set error handling.  REQUIRED if you aren't supplying your own
    * error handling functions in the png_create_write_struct() call.
    */
   if (setjmp(png_jmpbuf(png_ptr)))
   {
      /* If we get here, we had a problem reading the file */
      fclose(fp);
      png_destroy_write_struct(&png_ptr, &image_data);
      return FALSE;
   }

   /* set up the output control if you are using standard C streams */
   png_init_io(png_ptr, fp);

   /* This is the easy way.  Use it if you already have all the
    * image info living info in the structure.  You could "|" many
    * PNG_TRANSFORM flags into the png_transforms integer here.
    */
   png_write_png(png_ptr, image_data, PNG_TRANSFORM_IDENTITY, NULL);

   /* Similarly, if you png_malloced any data that you passed in with
      png_set_something(), such as a hist or trans array, free it here,
      when you can be sure that libpng is through with it. */
   //png_free(png_ptr, trans);
   //trans=NULL;

   /* clean up after the write, and free any memory allocated */
   png_destroy_write_struct(&png_ptr, /*&image_data*/0);

   /* close the file */
   fclose(fp);

   /* that's it */
   return TRUE;
}

//
//  FUNCTION: PNGLoad()
//
//  PURPOSE: Loads png file into global image_data
//
BOOL PNGLoad(char* file_name)
{
   png_structp png_ptr;
   unsigned int sig_read = 0;
   FILE *fp;

   if ((fp = fopen(file_name, "rb")) == NULL)
      return FALSE;

   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);

   if (png_ptr == NULL)
   {
      fclose(fp);
      return FALSE;
   }

   if (image_data) {
   		png_free_data(NULL, image_data, PNG_FREE_ALL, -1);
   }

   /* Allocate/initialize the memory for image information.  REQUIRED. */
   image_data = png_create_info_struct(png_ptr);
   if (image_data == NULL)
   {
      fclose(fp);
      png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
      return FALSE;
   }

   /* Set error handling if you are using the setjmp/longjmp method (this is
    * the normal method of doing things with libpng).  REQUIRED unless you
    * set up your own error handlers in the png_create_read_struct() earlier.
    */

   if (setjmp(png_jmpbuf(png_ptr)))
   {
      /* Free all of the memory associated with the png_ptr and image_data */
      png_destroy_read_struct(&png_ptr, &image_data, (png_infopp)NULL);
      fclose(fp);
      /* If we get here, we had a problem reading the file */
      return FALSE;
   }
   /* Set up the input control if you are using standard C streams */
   png_init_io(png_ptr, fp);

   png_read_png(png_ptr, image_data, PNG_TRANSFORM_IDENTITY, NULL);

   /* At this point you have read the entire image */

   /* clean up after the read, and free any memory allocated - REQUIRED */
   //png_destroy_read_struct(&png_ptr, &image_data, (png_infopp)NULL);
	png_destroy_read_struct(&png_ptr, NULL, (png_infopp)NULL);

   /* close the file */
   fclose(fp);

   /* that's it */
   return TRUE;
}

//
//  FUNCTION: WndProc()
//
//  PURPOSE:  Processes messages for the main window.
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message) {
	case WM_COMMAND:
		wmId    = LOWORD(wParam); 
		wmEvent = HIWORD(wParam); 
		// Parse the menu selections:
		switch (wmId) {
		case ID_LOAD_IMAGE:
			DoFileIO(LOAD_IMAGE_FILE);
			if (image_data) {
				SetWindowPos(hwndMain, NULL, 0, 0, 8+ image_data->width, 46+image_data->height, SWP_NOMOVE);
				InvalidateRect(hWnd, NULL, TRUE);
			}
			break;
		case ID_SAVE_IMAGE:
			if (image_data) {
				DoFileIO(SAVE_IMAGE_FILE);
			}
			else {
				ERROROUT("No image loaded");
			}
			break;
		case ID_SAVE_FSQ:
			if (image_data)
				DoFileIO(SAVE_FSQ_FILE);
			break;
		case ID_LOAD_FSQ:
			if (image_data) {
				DoFileIO(LOAD_FSQ_FILE);
			}
			else ERROROUT("load an image first"); // fix this later
			InvalidateRect(hWnd, NULL, TRUE);
			break;
		case IDM_ABOUT:
			DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		
		if (image_data) {
			UINT i,j;
			BYTE b;

			for (i = 0; i < image_data->width; ++i) {
				for (j = 0; j < image_data->height; ++j) {
					b = image_data->row_pointers[i][j];
					SetPixel(hdc, j, i, RGB(b, b, b));
				}
			}
		}

		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		CleanUp();
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_INITDIALOG:
				return TRUE;
		case WM_COMMAND:
			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
			{
				EndDialog(hDlg, LOWORD(wParam));
				return TRUE;
			}
			break;
	}
    return FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -