Hello Lee!
[quoted text, click to view] > I COULD use a single stream and seek to the beginning of each file
> when I need to, but it seems to me that it would make MUCH more sense
> to use one stream for each image (everything is reading only, so I
> don't have to worry about writing) with each stream's origin being
> the offset into the file of the associated image.
Of cause it is possible to do so. You may implement a special
System.IO.Stream which represents another stream starting from offset X.
e.g (untested).:
class OffsetStream : Stream {
Stream _s;
long _o, _l;
public OffsetStream(Stream stream, long offset, long length){
_s = stream;
_o = offset;
_l = length;
if(!_s.CanSeek)
throw new ArgumentException("not seekable...");
}
public override bool CanRead{
return _s.CanRead;
}
// do so with "CanWrite", "CanSeek", ...
public override long Length {
get{return _l;}
}
public override void SetLength(long value){
// would affect other parts of the stream
throw new NotSupportedException();
}
// seeking
public override long Seek(long offset, SeekOrgin orgin){
long p;
switch(orgin){
case SeekOrgin.Begin: p = _o+offset; break;
case SeekOrgin.Current: p = Position + offset;
case SeekOrgin.End: p = _o + _l - offset; break;
}
_s.Seek(SeekOrgin.Begin, p);
return p - _o;
}
public override long Position {
get{ return _s.Position - _o; }
set{Seek(value, SeekOrgin.Begin);}
}
// implement the other abstract members
}
This class may not be used to split up an Stream and to concurrenlty use the
parts individually (even in single-threaded environments). Because all
"OffsetStream" instances manipulate the Postion within the supplied Stream,
they would affect each other.
You have to know what operations are happening with your "OffsetStream" to
know if this is a problem or not. Image.FromStream() is a "Black-Box". It is
not documented when and how the Stream is used. So I would NOT recommend to
use the "OffsetStream" in this scenario.
You may implement the "OffsetStream" in a way that it loads all Data into
memory when it gets constructed. This would actually increase the
Memory-Footprint, but each Stream can operate individually.
e.g.
class OffsetStream : MemoryStream {
public OffsetStream(Stream stream, long offset, long length)
: base(GetData(stream, offset, length), false) {}
static byte[] GetData(Stream stream, long offset, long length){
byte[] buffer = new byte[(int)length];
stream.Read(buffer, (int)offset, buffer.Length);
return buffer;
// you should check the return-value of "stream.Read" to ensure that
// the data is read completly.
// you can also use a "BinaryReader" (which checks the Return-Value
by itself):
BinaryReader reader = new BinaryReader(stream);
// allthough this lock does NOT garanty that this code is
thread-safe in any case,
// it garanties that it is threadsafe when you create multiply
OffsetStream instances
// based on the the same Stream-Object.
lock(stream){
stream.Position = offset;
return reader.ReadBytes((int)length);
}
}
}
GP