📄 npwebwko.c
字号:
* 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 + -