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

📄 npwebwko.c

📁 c++ Builder中网络图象渐进传输实例
💻 C
📖 第 1 页 / 共 2 页
字号:
		 * Instead of the following line, you will probably need to implement
		 * printing yourself.  You also might as well set pluginPrinted to TRUE,
		 * though every browser I've tested ignores it. */
		printInfo->print.fullPrint.pluginPrinted = FALSE;
		/*  or */
		/*  PrintFullPage();
		 *  printInfo->print.fullPrint.pluginPrinted = TRUE;  */
	}
	else {	/* If not fullscreen, we must be embedded */
		HDC pdc;
		int prevstretchmode;
		NPWindow* printWindow;
		
		if (This->status != ST_LOADED)
			return;

		printWindow= &(printInfo->print.embedPrint.window);

		/* embedPrint.platformPrint is a Windows device context in disguise */

		/* The definition of NPWindow changed between API verion 0.9 and 0.11,
		 * increasing in size from 28 to 32 bytes. This normally makes it
		 * impossible for version 0.9 browsers to print version 0.11 plugins
		 * (because the platformPrint field ends up at the wrong offset) --
		 * unless the plugin takes special care to detect this situation.
		 * To work around it, if we are compiled with API 0.11 or higher,
		 * and the browser is version 0.9 or earlier, we look for the HDC
		 * 4 bytes earlier, at offset 28 instead of 32 (of the embedPrint
		 * sub-structure).
		 */

		if(sizeof(NPWindow)>28 &&     /* i.e. is plugin API >= 0.11? */
			     HIBYTE(g_pNavigatorFuncs->version)==0 &&
		         LOBYTE(g_pNavigatorFuncs->version)<=9) {
			char *tmpc;
			HDC  *tmph;

			tmpc= (char*)&(printInfo->print.embedPrint);
			tmph= (HDC*)&tmpc[28];
			pdc=  *tmph;  /* I know this could be all be done in 1 line, */
			              /* it would look too messy for my taste. */
		}
		else {
			pdc= (HDC) (printInfo->print.embedPrint.platformPrint);
		}

		if (!This->dib)
			return;

		prevstretchmode = SetStretchBltMode(pdc, HALFTONE);
		StretchDIBits(pdc,
			printWindow->x, printWindow->y, printWindow->width, printWindow->height,
			0, 0, This->wvh.owidth, This->wvh.oheight,
			This->dib_bits, &This->bi, DIB_RGB_COLORS, SRCCOPY);
		if (prevstretchmode)
			SetStretchBltMode(pdc, prevstretchmode);
	}
}

void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
{
	return;
}

int16 NPP_HandleEvent(NPP instance, void* event)
{
	return 0;
}

/**********************************************************************/

DWORD WINAPI DecodeFunc(PluginInstance *This)
{
	//如果网路数据I/O返回值均为有效值,开始解码
	if (This && This->valid && This->bits_read - This->last_bits_drawn > 0 && This->dib)
	{
		t_bit_file *bf;

		This->last_time_drawn = time(NULL);
		This->update_bits *= 3;
		EnterCriticalSection(&This->lpbits_lock);
		This->last_bits_drawn = This->bits_read;
		//以数据流格式打开插件中的压缩文件
		bf = bit_open(This->lpbits, "rm", This->bits_read);	
		//如果文件打开有效
		if (bf)
		{
			//新建一个低频带(即最低SNR水平条件下)的解码信道
			t_wv_dchannels* dc;
			int ycbcr;
			//低频带的解码
			ycbcr = bit_read(1, bf);
			dc = wv_init_decode_channels(0, bf);
			bit_close(bf, NULL);
			LeaveCriticalSection(&This->lpbits_lock);
			//开始图象细节部分的解码
			if (dc)
			{
				wv_pel *r, *g, *b;
				int y, x;
				//如果低频带完成解码,细化图象
				if (ycbcr && dc->hdr.num_channels >= 3)
				{
					for (y = 0; y < dc->hdr.oheight; y++)
						wv_ycbcr_to_rgb(dc->hdr.width, dc->channels[0] + y * dc->hdr.width, dc->channels[1] + y * dc->hdr.width,
							dc->channels[2] + y * dc->hdr.width);
				}
				//解码图象的r、g、b值
				r = dc->channels[0];
				g = dc->hdr.num_channels > 1 ? dc->channels[1] : dc->channels[dc->hdr.num_channels - 1];
				b = dc->hdr.num_channels > 2 ? dc->channels[2] : dc->channels[dc->hdr.num_channels - 1];
				EnterCriticalSection(&This->bitmap_lock);
				GdiFlush();
				for (y = 0; y < This->wvh.oheight; y++)
				{
					unsigned int ofs = y * This->wvh.width;
					unsigned int* dst = This->dib_bits + (This->bi.bmiHeader.biHeight - y - 1) * This->bi.bmiHeader.biWidth;

					for (x = 0; x < This->wvh.owidth; x++)
					{
						*dst++ = RGB(min(255, max(0, b[ofs])), min(255, max(0, g[ofs])), min(255, max(0, r[ofs])));
						ofs++;
					}
				}
				LeaveCriticalSection(&This->bitmap_lock);
				wv_done_decode_channels(dc);
			}
		}
		else
			LeaveCriticalSection(&This->lpbits_lock);
		//BMP图象在IE的矩形框
		InvalidateRect(This->fhWnd, NULL, FALSE);
	}
	This->decode_thread = INVALID_THREAD;
	return 0;
}


void UpdateBitmap(PluginInstance *This)
{
	if (This && This->valid && This->decode_thread == INVALID_THREAD && (This->bits_read - This->last_bits_drawn > 0 || !This->dib))
	{
		if (!This->dib)
			This->dib = CreateDIBSection(NULL, &This->bi, DIB_RGB_COLORS, &This->dib_bits, NULL, 0);
		if (This->dib && This->dib_bits)
		{
			DWORD tid;

			if (This->last_thread != INVALID_THREAD)
			{
				WaitForSingleObject(This->last_thread, INFINITE);
				CloseHandle(This->last_thread);
				This->last_thread = INVALID_THREAD;
			}
			This->decode_thread = This->last_thread = CreateThread(NULL, 0, DecodeFunc, This, 0, &tid);
//			This->decode_thread = _beginthread(DecodeFunc, 0, This);
//			DecodeFunc(This);
		}
	}
}

void PaintBitmap(PluginInstance *This, HDC hdc, RECT *rect1) 
{
	int prevstretchmode;
	RECT rect;

	//函数假设完整的解码BMP以装载,并且得到了有效的BMP头
	if (!This->valid || !This->dib)
		return;
	
	//备份显示区域的坐标值
	rect.left = rect1->left;    rect.top=rect1->top;
	rect.right = rect1->right;  rect.bottom=rect1->bottom;
	//如果BMP图象尺寸同IE窗口尺寸不匹配,那么将按图象的实际尺寸全局显示
	//实现方法其实可以调用Windows的API,在IE窗口加上一个浏览条即可
	if (This->fMode == NP_FULL)
	{
		int w,h,x,y;
		HPEN oldpen;
		HBRUSH oldbrush;

		w = This->wvh.owidth;
		h = This->wvh.oheight;

		//如果需要,可以减小图象的尺寸
		if (w > rect.right)
		{
			h = (int)(((double)h * (double)rect.right)/(double)w);
			w = rect.right;
		}
		if (h > rect.bottom)
		{
			w = (int)(((double)w * (double)rect.bottom)/(double)h);
			h = rect.bottom;
		}

		//图象居中,如果窗口大于图象
		if (w < rect.right) 
			x = (rect.right - w) / 2;
		else
			x = 0;
		if (h < rect.bottom)
			y = (rect.bottom - h) / 2;
		else
			y = 0;

		rect.left = x;
		rect.right = w;
		rect.top = y;
		rect.bottom = h;

		oldpen = SelectObject(hdc, GetStockObject(NULL_PEN));
		oldbrush = SelectObject(hdc, GetStockObject(WHITE_BRUSH));

		Rectangle(hdc,rect1->left,rect1->top, rect1->left+rect1->right+1,rect1->top+rect1->bottom+1);

		if (oldpen)
			SelectObject(hdc, oldpen);
		if (oldbrush)
			SelectObject(hdc, oldbrush);
	}

	prevstretchmode = SetStretchBltMode(hdc, HALFTONE);
	EnterCriticalSection(&This->bitmap_lock);
	StretchDIBits(hdc,
		rect.left, rect.top, rect.right, rect.bottom,
		0, 0, This->wvh.owidth, This->wvh.oheight,
		This->dib_bits, &This->bi, DIB_RGB_COLORS, SRCCOPY);
	LeaveCriticalSection(&This->bitmap_lock);
	if (prevstretchmode)
		SetStretchBltMode(hdc, prevstretchmode);
}


void CopyToClipboard(PluginInstance *This, unsigned char *mem, int size, UINT format)
{
	HGLOBAL hClip;
	LPVOID lpClip;

	if (!mem)
		return;

	if (!OpenClipboard(NULL))
	{
		warn(This,"Can't open the clipboard");
		return;
	}

	if (EmptyClipboard())
	{
		hClip = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,size);
		lpClip = GlobalLock(hClip);
		if (lpClip)
		{
			CopyMemory(lpClip, mem, size);
			GlobalUnlock(hClip);
			if(!SetClipboardData(format,hClip))
				warn(This, "Can't set clipboard data");
		}
		else
			warn(This, "Can't allocate memory for clipboard");
	}
	else
		warn(This, "Can't clear the clipboard");
	CloseClipboard();
}


int SaveToBMPFile(PluginInstance *This, char *filename)
{
	HANDLE hFile;
	BITMAPFILEHEADER hdr;
	DWORD written;

	if (!This->dib)
		return 0;

	hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		warn(This, "Could not save file '%s'", filename);
		return 0;
	}

	hdr.bfType = 0x4d42; // BM
    hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + This->bi.bmiHeader.biSize + This->bi.bmiHeader.biSizeImage); 
    hdr.bfReserved1 = 0; 
    hdr.bfReserved2 = 0; 
    // Compute the offset to the array of color indices. 
    hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + This->bi.bmiHeader.biSize; 
	WriteFile(hFile, (LPVOID)&hdr, sizeof hdr, &written, NULL);
	WriteFile(hFile, (LPVOID)&This->bi.bmiHeader, This->bi.bmiHeader.biSize, &written, NULL);
	WriteFile(hFile, (LPVOID)This->dib_bits, This->bi.bmiHeader.biSizeImage, &written, NULL);

	CloseHandle(hFile);
	return 1;
}

/* 本函数从url地址中提取有效的文件名,得到的文件名存放在fn[256]字符数组中。
这个函数可以从url地址中抽取有效的BMP文件名和WKO文件名,
如果url地址不存在有效的文件名,数组fn[256]为空。 */
void url2filename(char *fn, char *url)
{
	int title,ext,i;

	strcpy(fn,"");
	ext=0;   	//文件的后缀名 
	title=0; 	//文件名 
	for(i=0;url[i];i++) {
		if(url[i]=='.') ext=i+1;
		if(url[i]=='/') title=i+1;
		if(url[i]==':') title=i+1;
		if(url[i]=='=') title=i+1;
	}

	if(!_stricmp(&url[ext],"wko")) {
		strncpy(fn,&url[title],MAX_PATH);
		fn[MAX_PATH-1]='\0';
	}
}


/* Write the image to a local file; see SaveToBMPFile() */
void SaveImage(PluginInstance *This)
{
	OPENFILENAME ofn;
	char fn[MAX_PATH];

	if(This->status != ST_LOADED) {
		warn(This,"Image not loaded -- can't save");
		return;
	}

	if(strlen(This->url)) {
		url2filename(fn,This->url);
	}
	else {
		strcpy(fn,"");
	}

	ZeroMemory(&ofn,sizeof(OPENFILENAME));
	ofn.lStructSize=sizeof(OPENFILENAME);
	ofn.hwndOwner=This->fhWnd;
	ofn.lpstrFilter="Wavelet Kompressed (*.wko)\0*.wko\0Bitmaps (*.bmp)\0*.bmp\0\0";
	ofn.nFilterIndex=1;
	ofn.lpstrTitle="Save Image As...";
	ofn.lpstrFile=fn;
	ofn.nMaxFile=MAX_PATH;
	ofn.Flags=OFN_PATHMUSTEXIST|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;
	ofn.lpstrDefExt="wko";

	if(GetSaveFileName(&ofn))
	{
		if (strcmpi(&ofn.lpstrFile[ofn.nFileExtension], "bmp") == 0)
			SaveToBMPFile(This,ofn.lpstrFile);
		else
		{
			FILE *f = fopen(ofn.lpstrFile, "wb");

			if (f)
			{
				fwrite(This->lpbits, This->bits_read / 8, 1, f);
				fclose(f);
			}
			else
				warn(This, "Could not save file '%s'", ofn.lpstrFile);
		}
	}
}

void AboutDialog(PluginInstance *This)
{
	DialogBoxParam(hInst,"ABOUTDLG",This->fhWnd,(DLGPROC)DlgProcAbout,(LPARAM)This);
}

void ContextMenu(PluginInstance *This, int x, int y, HWND hwnd)
{
	HMENU sub;
	int cmd;
	POINT pt;

	pt.x=pt.y=0;
	GetCursorPos(&pt);
	x=pt.x; y=pt.y;

	sub=GetSubMenu(hmenuContext,0);

	cmd=TrackPopupMenuEx(sub, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_NONOTIFY|TPM_RETURNCMD|
		TPM_RIGHTBUTTON,x,y,hwnd,NULL);

	switch(cmd)
	{
		case ID_SAVEAS:
			SaveImage(This);
		break;
		case ID_COPYIMAGE:
			if (This->status==ST_LOADED && This->dib)
			{
				HBITMAP bmp;

				bmp = CreateBitmap(This->bi.bmiHeader.biWidth, abs(This->bi.bmiHeader.biHeight), 1, 32, This->dib_bits); 
				
				if (!OpenClipboard(NULL))
				{
					warn(This,"Can't open the clipboard");
					return;
				}

				if (EmptyClipboard())
				{
					if(!SetClipboardData(CF_BITMAP, bmp))
						warn(This, "Can't set clipboard data");
				}
				else
					warn(This, "Can't clear the clipboard");
				CloseClipboard();
				DeleteObject(bmp);
			}
			else
				warn(This,"No image to copy");
		break;
		case ID_COPYURL:
			if (strlen(This->url))
				CopyToClipboard(This,This->url,strlen(This->url)+1,CF_TEXT);
			else
				warn(This,"No link to copy");
		break;
		case ID_VIEWIMAGE:
			if (strlen(This->url)) 
				NPN_GetURL(This->instance,This->url, "_self");
			break;
		case ID_ABOUT:
			AboutDialog(This);
		break;
	}
}

/*+++++++++++++++++++++++++++++++++++++++++++++++++
 * PluginWindowProc
 * Handle the Windows window-event loop.
 +++++++++++++++++++++++++++++++++++++++++++++++++*/
LRESULT CALLBACK PluginWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	PluginInstance* This = (PluginInstance*) GetProp(hWnd, gInstanceLookupString);
	if(!This) return DefWindowProc( hWnd, Msg, wParam, lParam);

	switch(Msg) {
	case WM_ERASEBKGND:
			//禁用IE背景,可以通过WM_PAINT手工重画
		return 1;

	case WM_CONTEXTMENU: case WM_RBUTTONDOWN:
		ContextMenu(This,LOWORD(lParam),HIWORD(lParam), hWnd);
		return 0;

	case WM_PAINT:
		if (This->dib)
		{
			PAINTSTRUCT paintStruct;
			HDC hdc;
			RECT rect;
			
			hdc = BeginPaint(hWnd, &paintStruct);
			GetClientRect(hWnd, &rect);
			PaintBitmap(This, hdc, &rect);
			EndPaint(hWnd, &paintStruct);

			return 0;
		}
		else
			return This->fDefaultWindowProc(hWnd, Msg, wParam, lParam);
	}
	return This->fDefaultWindowProc(hWnd, Msg, wParam, lParam);
}


LRESULT CALLBACK DlgProcAbout(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
	switch(Msg) {
	case WM_INITDIALOG:
		{
			char buf[4096];
			char info[1024];
			DWORD tabs[1];

			PluginInstance *This=(PluginInstance*)lParam;

			tabs[0]= 60;
			SendDlgItemMessage(hWnd,IDC_IMGINFO,EM_SETTABSTOPS,(WPARAM)1,(LPARAM)tabs);

			sprintf(buf,"WebWKO Plug-in, Version %s\r\n%s"
#ifdef _DEBUG
				" DEBUG BUILD"
#endif
				"\r\nBy Daniel Vollmer (maven@maven.de),\r\nbased on WebBMP by Jason Summers."
				,VERS,__DATE__);
			SetDlgItemText(hWnd,IDC_PRGINFO,buf);

			sprintf(buf,"URL:\t%s\r\n",This->url);
				
			if (!This->valid)
				GetImageInfo(This);
			if (This->status == ST_LOADED)
			{
				sprintf(info,"Size:\t%d bytes\r\n", This->bits_read / 8);
				strcat(buf, info);
#ifdef _DEBUG
				sprintf(info, "Reported size:\t%d bytes\r\n", This->streamend);
				strcat(buf, info);
				sprintf(info, "Memory alloc:\t%d bytes\r\n", This->bytes_alloc);
				strcat(buf, info);
				sprintf(info, "Num blocks:\t%d\r\n", This->wvh.num_blocks);
				strcat(buf, info);
#endif
				sprintf(info, "Dimensions:\t%d x %d pixels\r\n", This->wvh.owidth, This->wvh.oheight);
				strcat(buf, info);

				sprintf(info, "# of channels:\t%d\r\n", This->wvh.num_channels);
				strcat(buf,info);
				
				sprintf(info, "YCbCr:\t%d\r\n", This->wvh_is_yuv);
				strcat(buf, info);
			}

			sprintf(info,"Browser:\t%s\r\n",NPN_UserAgent(This->instance));
			strcat(buf,info);

			sprintf(info,"Browser API:\t%d.%d\r\n",HIBYTE(g_pNavigatorFuncs->version),
				LOBYTE(g_pNavigatorFuncs->version));
			strcat(buf,info);

			sprintf(info,"Plug-in API:\t%d.%d\r\n",NP_VERSION_MAJOR,NP_VERSION_MINOR);
			strcat(buf,info);

			SetDlgItemText(hWnd,IDC_IMGINFO,buf);
		}
		return(TRUE);
	case WM_CLOSE:
		EndDialog(hWnd,0);
		return(TRUE);
	case WM_COMMAND:
		switch(wParam) {
		case IDOK:
		case IDCANCEL:
			EndDialog(hWnd,0);
			return(TRUE);
		}
	}
	return(FALSE);
}

⌨️ 快捷键说明

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