📄 fractalsqueeze.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 + -