📄 kdu_show.cpp
字号:
/******************************************************************************//* CKdu_showApp::paint_region *//******************************************************************************/void CKdu_showApp::paint_region(CDC *dc, kdu_dims region){ kdu_dims region_on_buffer = region; region_on_buffer.pos += view_dims.pos; // Convert to absolute region region_on_buffer &= buffer_dims; // Intersect with buffer region region_on_buffer.pos -= buffer_dims.pos; // Make relative to buffer region if (region_on_buffer.size != region.size) { /* Need to erase the region first and then modify it to reflect the region we are about to actually paint. */ dc->BitBlt(region.pos.x,region.pos.y,region.size.x,region.size.y, NULL,0,0,WHITENESS); region = region_on_buffer; region.pos += buffer_dims.pos; // Convert to absolute region region.pos -= view_dims.pos; // Make relative to client region. } if (!region_on_buffer) return; assert(region.size == region_on_buffer.size); BITMAPINFO info; memset(&info,0,sizeof(info)); info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); info.bmiHeader.biWidth = buffer_extent.x; info.bmiHeader.biHeight = -region.size.y; info.bmiHeader.biPlanes = 1; info.bmiHeader.biBitCount = 24; info.bmiHeader.biCompression = BI_RGB; kdu_byte *start = buffer + (region_on_buffer.pos.y*buffer_extent.x + region_on_buffer.pos.x)*3; int success = SetDIBitsToDevice(dc->GetSafeHdc(),region.pos.x,region.pos.y, region.size.x,region.size.y,0,0,0,region.size.y, start,&info,DIB_RGB_COLORS); if (!success) { // This should not be necessary, except that there appears to be a nasty // bug in the Windows OS or MFC. After a window has been automatically // resized (required sometimes after rotation or zooming operations to // make sure the image fits inside the window), the framework sometimes // gets itself into an inexplicable (and certainly undocumented) funk, // where attempts to paint to a region which includes the last line of // the window sometimes cause the entire paint operation to fail. I // have tried just about every version of the painting functions, // defering painting operations thru the windows message loop and all // sorts of things. To create the problem yourself (let me know if you // are able to fix it) try viewing an image which is wider than it is // tall. Rotate the image thru 360 degrees so that the window is forced // to shrink in the horizontal direction. Then try scrolling to the // right (scrolling to the left seems not to be so problematic). My // only conclusion at this point is that it is a Microsoft bug which I // can do nothing about. The current work-around, simply does not update // the last line of the viewing window, which is not ideal. Manually // resizing the window horizontally can get the framework out of this // difficulty. Windows NT has also been observed to be a lot more // robust to this problem than Windows 95. success = SetDIBitsToDevice(dc->GetSafeHdc(),region.pos.x,region.pos.y, region.size.x,region.size.y-1,0,0,0,region.size.y-1, start,&info,DIB_RGB_COLORS); }}/******************************************************************************//* CKdu_showApp::display_quality_layer_status *//******************************************************************************/void CKdu_showApp::display_quality_layer_status(){ if (!codestream) return; char string[128]; if (max_display_layers >= codestream.get_max_tile_layers()) sprintf(string,"All quality layers in use."); else sprintf(string,"Using %d of %d quality layers.", max_display_layers,codestream.get_max_tile_layers()); frame->SetMessageText(string);}/******************************************************************************//* CKdu_showApp::OnIdle *//******************************************************************************/BOOL CKdu_showApp::OnIdle(LONG lCount) /* Note: this function implements a very simple heuristic for scheduling regions for processing. It is intended primarily to demonstrate capabilities of the underlying framework -- in particular the `kd_region_decompressor' object and the rest of the Kakadu JPEG2000 platform on which it is built. */{ if (in_idle || !codestream) return FALSE; // Don't need to be called from recursive loop again. in_idle = true; if (!processing) { // Decide on a region to process. if (valid_dims.area() < (buffer_dims.area()>>2)) region_in_process = buffer_dims; // No point skirting round `valid_dims' else { /* The new region should share a boundary with `valid_dims' so that they can be added together to form a new rectangular valid region. Of the four possible regions of this form, pick the one whose intersection with the current view is largest. */ kdu_coords valid_min = valid_dims.pos; kdu_coords valid_lim = valid_min + valid_dims.size; kdu_coords buffer_min = buffer_dims.pos; kdu_coords buffer_lim = buffer_min + buffer_dims.size; int needed_left = valid_min.x - buffer_min.x; int needed_right = buffer_lim.x - valid_lim.x; int needed_above = valid_min.y - buffer_min.y; int needed_below = buffer_lim.y - valid_lim.y; assert((needed_left >= 0) && (needed_right >= 0) && (needed_above >= 0) && (needed_below >= 0)); kdu_dims region_left = valid_dims; region_left.pos.x = buffer_min.x; region_left.size.x = needed_left; kdu_dims region_right = valid_dims; region_right.pos.x = valid_lim.x; region_right.size.x = needed_right; kdu_dims region_above = valid_dims; region_above.pos.y = buffer_min.y; region_above.size.y = needed_above; kdu_dims region_below = valid_dims; region_below.pos.y = valid_lim.y; region_below.size.y = needed_below; region_in_process = region_left; if (((region_in_process & view_dims).area() < (region_right & view_dims).area()) || !region_in_process) region_in_process = region_right; if (((region_in_process & view_dims).area() < (region_above & view_dims).area()) || !region_in_process) region_in_process = region_above; if (((region_in_process & view_dims).area() < (region_below & view_dims).area()) || !region_in_process) region_in_process = region_below; } if (!(!region_in_process)) { decompressor.start(codestream,(single_component<0)?(&channels):NULL, single_component,discard_levels,max_display_layers, region_in_process,expansion); incomplete_region = region_in_process; processing = true; } } if (processing) { // Process some more data. kdu_dims new_region; if ((!decompressor.process(buffer,buffer_extent.x,buffer_dims, incomplete_region,8192,new_region)) || !incomplete_region) { processing = false; if (!decompressor.finish()) { // Code-stream failure. Must destroy it. close_file(); } else valid_dims = combine_regions(valid_dims,region_in_process); } // In any event, paint any newly decompressed region right away. new_region &= view_dims; // No point in painting invisible regions. if (!(!new_region)) { new_region.pos -= view_dims.pos; // Make relative to view region. CDC *dc = child->GetDC(); paint_region(dc,new_region); child->ReleaseDC(dc); } } in_idle = false; if (valid_dims != buffer_dims) return TRUE; display_quality_layer_status(); // All processing done, keep status up to date return CWinApp::OnIdle(lCount); // Give low-level idle processing a go.}/******************************************************************************//* CKdu_showApp::OnAppAbout *//******************************************************************************/void CKdu_showApp::OnAppAbout(){ CAboutDlg aboutDlg; aboutDlg.DoModal();}/******************************************************************************//* CKdu_showApp::OnFileClose *//******************************************************************************/void CKdu_showApp::OnFileClose() { if (codestream.exists()) close_file(); }/******************************************************************************//* CKdu_showApp::OnUpdateFileClose *//******************************************************************************/void CKdu_showApp::OnUpdateFileClose(CCmdUI* pCmdUI) { pCmdUI->Enable(codestream.exists());}/******************************************************************************//* CKdu_showApp::OnFileOpen *//******************************************************************************/void CKdu_showApp::OnFileOpen() { char filename[1024]; OPENFILENAME ofn; memset(&ofn,0,sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = m_pMainWnd->GetSafeHwnd(); ofn.lpstrFilter = "JP2 compatible file (*.jp2, *.jpx)\0*.jp2;*.jpx\0" "JPEG2000 unwrapped code-stream (*.j2c)\0*.j2c\0" "Arbitrary name (*.*)\0*.*\0\0"; ofn.nFilterIndex = 3; ofn.lpstrFile = filename; filename[0] = '\0'; ofn.nMaxFile = 1023; ofn.lpstrTitle = "Open JPEG2000 Compressed Image"; ofn.Flags = OFN_FILEMUSTEXIST; if (!GetOpenFileName(&ofn)) return; open_file(filename);}/******************************************************************************//* CKdu_showApp::OnFileProperties *//******************************************************************************/void CKdu_showApp::OnFileProperties() { if (!codestream) return; if (processing) { processing = false; if (!decompressor.finish()) { close_file(); return; } } // Make sure we have all tile information. if (!tiles_loaded) { try { // We may be parsing the code-stream for the first time max_discard_levels = -1; codestream.apply_input_restrictions(0,total_components,0,0,NULL); kdu_dims valid_tiles; codestream.get_valid_tiles(valid_tiles); kdu_coords idx; for (idx.y=0; idx.y < valid_tiles.size.y; idx.y++) for (idx.x=0; idx.x < valid_tiles.size.x; idx.x++) { kdu_tile tile = codestream.open_tile(valid_tiles.pos+idx); tile.close(); } tiles_loaded = true; } catch (int) { close_file(); return; } } // Textualize the properties into an `ostrstream' object. std::ostrstream string_buf; kdu_params *root = codestream.access_siz(); string_buf << "<<<<< Main Header >>>>>\n"; root->textualize_attributes(string_buf,-1,-1); codestream.apply_input_restrictions(0,total_components,0,0,NULL); codestream.change_appearance(false,false,false); kdu_dims valid_tiles; codestream.get_valid_tiles(valid_tiles); kdu_coords idx; for (idx.y=0; idx.y < valid_tiles.size.y; idx.y++) for (idx.x=0; idx.x < valid_tiles.size.x; idx.x++) { kdu_dims tile_dims; codestream.get_tile_dims(valid_tiles.pos+idx,-1,tile_dims); int tnum = idx.x + idx.y*valid_tiles.size.x; string_buf << "<<<<< Tile " << tnum << " >>>>>" << " Canvas coordinates: " << "y = " << tile_dims.pos.y << "; x = " << tile_dims.pos.x << "; height = " << tile_dims.size.y << "; width = " << tile_dims.size.x << "\n"; root->textualize_attributes(string_buf,tnum,tnum); } // Display the properties. CPropertiesDlg properties(codestream,&string_buf); properties.DoModal();}/******************************************************************************//* CKdu_showApp::OnUpdateFileProperties *//******************************************************************************/void CKdu_showApp::OnUpdateFileProperties(CCmdUI* pCmdUI){ pCmdUI->Enable(codestream.exists());}/******************************************************************************//* CKdu_showApp::OnViewHflip *//******************************************************************************/void CKdu_showApp::OnViewHflip(){ if (!codestream) return; hflip = !hflip; calculate_view_centre(); view_centre_x = 1.0F - view_centre_x; initialize_regions();}/******************************************************************************//* CKdu_showApp::OnUpdateViewHflip *//******************************************************************************/void CKdu_showApp::OnUpdateViewHflip(CCmdUI* pCmdUI) { pCmdUI->Enable(codestream.exists());}/******************************************************************************//* CKdu_showApp::OnViewVflip *//******************************************************************************/void CKdu_showApp::OnViewVflip() { if (!codestream) return; vflip = !vflip; calculate_view_centre(); view_centre_y = 1.0F - view_centre_y; initialize_regions();}/******************************************************************************//* CKdu_showApp::OnUpdateViewVflip *//****
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -