मैंने स्वयं कुछ करने का फैसला किया। मैं एक सीधा जीडीआई + कोड के साथ आया, जो कि पहले से मिल चुके टाइल्स का उपयोग करता है। मैं सिर्फ उन हिस्सों को फ़िल्टर करता हूं जो वर्तमान क्लिपिंग क्षेत्र के लिए प्रासंगिक हैं। यह जादू की तरह काम करता है! कृपया नीचे अपना कोड पाएं। (फॉर्म सेटिंग्स अच्छे परिणाम के लिए डबल बफरिंग)
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics dc = e.Graphics;
dc.ScaleTransform(1.0F, 1.0F);
Size scrollOffset = new Size(AutoScrollPosition);
int start_x = Math.Min(matrix_x_size,
(e.ClipRectangle.Left - scrollOffset.Width)/256);
int start_y = Math.Min(matrix_y_size,
(e.ClipRectangle.Top - scrollOffset.Height)/256);
int end_x = Math.Min(matrix_x_size,
(e.ClipRectangle.Right - scrollOffset.Width + 255)/256);
int end_y = Math.Min(matrix_y_size,
(e.ClipRectangle.Bottom - scrollOffset.Height + 255)/256);
// start * contain the first and last tile x/y which are on screen
// and which need to be redrawn.
// now iterate trough all tiles which need an update
for (int y = start_y; y < end_y; y++)
for (int x = start_x; x < end_x; x++)
{ // draw bitmap with gdi+ at calculated position.
dc.DrawImage(BmpMatrix[y, x],
new Point(x * 256 + scrollOffset.Width,
y * 256 + scrollOffset.Height));
}
}
यह परीक्षण करने के लिए, मैं 256 के 80x80 टाइल (420 MPixel) के एक मैट्रिक्स बना लिया है। बेशक मुझे वास्तविक जीवन में कुछ स्थगित लोडिंग जोड़नी होगी। अगर वे अभी तक लोड नहीं हुए हैं तो मैं टाइल्स को छोड़ सकता हूं (खाली)। असल में, मैंने अपने क्लाइंट से अपनी मशीन में 8 जीबीटीटी चिपकने के लिए कहा है, इसलिए मुझे प्रदर्शन के बारे में परेशान करने की ज़रूरत नहीं है। एक बार लोड टाइल्स स्मृति में रह सकते हैं।
public partial class Form1 : Form
{
bool dragging = false;
float Zoom = 1.0F;
Point lastMouse;
PointF viewPortCenter;
private readonly Brush solidYellowBrush = new SolidBrush(Color.Yellow);
private readonly Brush solidBlueBrush = new SolidBrush(Color.LightBlue);
const int matrix_x_size = 80;
const int matrix_y_size = 80;
private Bitmap[,] BmpMatrix = new Bitmap[matrix_x_size, matrix_y_size];
public Form1()
{
InitializeComponent();
Font font = new Font("Times New Roman", 10, FontStyle.Regular);
StringFormat strFormat = new StringFormat();
strFormat.Alignment = StringAlignment.Center;
strFormat.LineAlignment = StringAlignment.Center;
for (int y = 0; y < matrix_y_size; y++)
for (int x = 0; x < matrix_x_size; x++)
{
BmpMatrix[y, x] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
// BmpMatrix[y, x].Palette.Entries[0] = (x+y)%1==0?Color.Blue:Color.White;
using (Graphics g = Graphics.FromImage(BmpMatrix[y, x]))
{
g.FillRectangle(((x + y) % 2 == 0) ? solidBlueBrush : solidYellowBrush, new Rectangle(new Point(0, 0), new Size(256, 256)));
g.DrawString("hello world\n[" + x.ToString() + "," + y.ToString() + "]", new Font("Tahoma", 8), Brushes.Black,
new RectangleF(0, 0, 256, 256), strFormat);
g.DrawImage(BmpMatrix[y, x], Point.Empty);
}
}
BackColor = Color.White;
Size = new Size(300, 300);
Text = "Scroll Shapes Correct";
AutoScrollMinSize = new Size(256 * matrix_x_size, 256 * matrix_y_size);
}
बाहर निकला यह आसान हिस्सा था।बैकग्राउंड में एसिंक मल्टीथ्रेड किए गए I/O को प्राप्त करना बहुत कठिन था। फिर भी, मैं इसे यहां वर्णित तरीके से काम कर रहा हूं। हल करने के लिए मुद्दे इस विषय से संबंधित .NET/Form multithreading थे।
छद्म कोड में यह इस तरह काम करता है:
after onPaint (and on Tick)
check if tiles on display need to be retrieved from disc
if so: post them to an async io queue
if not: check if tiles close to display area are already loaded
if not: post them to an async io/queue
check if bitmaps have arrived from io thread
if so: updat them on screen, and force repaint if visible
परिणाम: मैं अब जो मनमाने ढंग से आकार (टाइलों) TIFF फ़ाइलों के लिए बहुत तेजी से पहुँच के लिए लगभग 50 MByte का उपयोग करता है अपने खुद के कस्टम नियंत्रण है।
डीपज़ूम दृष्टिकोण की तरह दिखता है। आपको छवियों के कम-रिज़ॉल्यूशन संस्करणों को http://www.imagemagick.org/script/index.php जैसे कुछ बनाना होगा। मेरे पोकिंग से, ऐसा लगता है कि यह एक पेटेंट खानफील्ड है, इसलिए .... – kenny