Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.09;
Скачать: CL | DM;

Вниз

Вывод большого изображения (Gb)   Найти похожие ветки 

 
hgd   (2005-12-16 20:59) [0]

Подскажите, мне надо выводить большое изображение (bmp весит 1 Gb) и выводить надо со 100% размером. Тоесть если картинка 10000 на 10000, то на экране 800 на 600 надо вывести кусок. Как это сделать и можно ли предусмотреть скроллинг изображения?


 
TUser ©   (2005-12-16 21:10) [1]

TScrollBox


 
Kolan ©   (2005-12-16 21:11) [2]

ScrollBox не подойдет?


 
Джо ©   (2005-12-16 21:11) [3]

Боюсь, что стандартными средствами изображение такого размера не вывести. Я имею все, что построено на TCanvas и TBitmap. Впрочем, практика - критерий истины.


 
Джо ©   (2005-12-16 21:12) [4]


>  Я имею все

Я имею в виду все


 
Eraser ©   (2005-12-16 21:30) [5]


> Джо ©   (16.12.05 21:11) [3]


>  Я имею все, что построено на TCanvas и TBitmap.

Ну TCanvas в любом случае использовать прийдётся, ну или по крайней мере HDC )

> hgd   (16.12.05 20:59)

На torry.net по-моему есть компоненты для работы с большими граф. файлами.


 
Andy BitOff ©   (2005-12-16 21:39) [6]

На основании своей практики могу посоветовать GDIPlus для вывода. Я выводил jpg 19 метров, 13500 по ширине и 8500 по высоте - доли секуды.
http://msdn.microsoft.com/library/en-us/gdicpp/GDIPlus/GDIPlus.asp


 
Джо ©   (2005-12-16 21:43) [7]

Присоединяюсь к совету попробовать GDI+.


>  [5] Eraser ©   (16.12.05 21:30)

У меня тут уже в голове после сегодняшней запарки перепуталось все. Конечно, я имел в виду TBitmap, собственно из-за его "out of resources" ^)


 
GuAV ©   (2005-12-16 21:54) [8]

Если загрузится в TBitmap, то
ScrollBox + PaintBox, у PaintBox в OnDraw юзать ClipRect, делая туда BrushCopy(R, FBitmap, SrcRect, clNone);, или не туда а во временный Bitmap по размерам ClipRect, если "кэширование" нужно.
Я так делал, хотя мои картинки много меньше.


 
Германн ©   (2005-12-17 01:27) [9]

Не специалист, но имхо, смахивает на задачу ГИС. Так может покопать именно в эту сторону?


 
Separator ©   (2005-12-17 04:57) [10]

Выводи почастям, а при прокрутке подгружай нужные части


 
hgd   (2005-12-17 10:36) [11]

да это действительно задача ГИС, может есть какие-нибудь компоненты?


 
Германн ©   (2005-12-18 02:26) [12]


> hgd   (17.12.05 10:36) [11]
>
> да это действительно задача ГИС, может есть какие-нибудь
> компоненты?


Был бы тут ShaggiDoc он бы ответил.
Вроде бы, "просто компонента" нет.
Но ведь есть Яндекс, Гугль и т.п. Да пребудет с ними... Ищи там.


 
PAVIA ©   (2005-12-18 14:03) [13]

Сам напиши.


 
wicked ©   (2005-12-18 20:47) [14]

вставлю свои 3 коп.....
учитывая, что это bmp, могу посоветовать MMF + StretchDIBits...
с помощью 1-го - отображаем файлик в память (думаю, 1 Гб отобразит), с помощью 2-го - рисуем нужный кусок на экране....
такие вот домыслы, я бы с этого начинал...


 
miek ©   (2005-12-19 09:24) [15]

MMF безусловно сработает - создать дибсекцию на отображении и вперед, хоть BitBlt, хоть StretchBlt..


 
WondeRu ©   (2005-12-19 11:54) [16]

wicked ©   (18.12.05 20:47) [14]
с помощью 1-го - отображаем файлик в память (думаю, 1 Гб отобразит),

фига се....

Автору советую читать напрямую из файла по кусочкам, формат файла .bmp очень простой.


 
wicked ©   (2005-12-19 12:38) [17]

> WondeRu ©   (19.12.05 11:54) [16]

> фига се....

когда я экспериментировал с MMF, то файлы по 700 Мб (фильм, 1 шт) отлично отображались в память, коей было всего 256 Мб.....


 
wicked ©   (2005-12-19 12:40) [18]


> MMF безусловно сработает - создать дибсекцию на отображении
> и вперед, хоть BitBlt, хоть StretchBlt..

можно без дибсекции - см. StretchDIBits....


 
Ryan Dickinson   (2006-01-19 16:49) [19]

Удалено модератором


 
имя   (2006-01-19 16:51) [20]

Удалено модератором


 
0bsid ©   (2006-01-25 15:30) [21]

я пользуюсь компонентой Graphics32. изображение 500 мб отображается на ура.


 
имя   (2006-01-25 17:11) [22]

Удалено модератором


 
Universe ©   (2006-01-28 16:04) [23]

По подробнее пример использования MMF + StretchDIBits можно посмотреть?


 
wicked ©   (2006-01-29 22:39) [24]


> По подробнее пример использования MMF + StretchDIBits можно
> посмотреть?

1) класс, создающий MMF... наследник TCustomMemoryStream...
unit MMapStream;

interface
uses Windows, SysUtils, Classes;
const
def_Granularity = (512 * 1024);

type
TMemoryMapStream = class(TCustomMemoryStream)
protected
 fRealSize: integer;
 fGranularity: integer;
 fFile: THandle;
 fMemMap: THandle;
 fReadOnly: boolean;

 procedure SetSize(const NewSize: int64); overload; override;
 procedure SetGranularity(value: integer); virtual;

 procedure OpenMMap; virtual;
 procedure CloseMMap; virtual;
 procedure Map; virtual;
 procedure UnMap; virtual;
 procedure doPack(reopen: boolean); virtual;
 procedure SetEOF(pos: integer); virtual;

public
 constructor Create(const AFileName: string; RequestReadOnly: boolean = false; AGranularity: integer = def_Granularity);
 destructor Destroy; override;

 procedure Clear;
 procedure SetSize(NewSize: integer); overload; override;
 function Write(const Buffer; Count: longint): longint; override;

 procedure LoadFromFile(const FileName: string); virtual;
 procedure LoadFromStream(Stream: TStream); virtual;
 procedure Pack; virtual;

 property Granularity: integer read fGranularity write SetGranularity;
 property ReadOnly: boolean read fReadOnly;
end;

implementation

const
min_size = 1024;

constructor TMemoryMapStream.Create(const AFileName: string; RequestReadOnly: boolean = false; AGranularity: integer = def_Granularity);
var filesize: integer;
begin
inherited Create;
SetPointer(nil, 0);
fRealSize:= 0;
SetGranularity(AGranularity);
fFile := 0;
fMemMap := 0;
fReadOnly := false;
try
 if not RequestReadOnly then
  fFile := CreateFile(
   PChar(AFileName),         // name
   GENERIC_READ or GENERIC_WRITE,      // desired access
   FILE_SHARE_READ,         // share mode (share read)
   nil,            // security attributes
   OPEN_ALWAYS,          // OPEN_EXISTING, // creation disposition
   FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS, // flags and attributes
   0{nil});           // template file
 if (fFile = INVALID_HANDLE_VALUE) or RequestReadOnly then begin
  fFile := CreateFile(
   PChar(AFileName),         // name
   GENERIC_READ,          // desired access
   FILE_SHARE_READ,         // share mode (share read)
   nil,            // security attributes
   OPEN_EXISTING,          // creation disposition
   FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS, // flags and attributes
   0{nil});           // template file
  if fFile = INVALID_HANDLE_VALUE then raise Exception.Create("could not open the file " + AFileName);
  fReadOnly := true;
    end;
    filesize := GetFileSize(fFile, nil);
 if filesize = 0 then SetEOF(min_size);
    OpenMMap;
 except
CloseMMap;
   if (fFile <> 0) and (fFile <> INVALID_HANDLE_VALUE) then CloseHandle(fFile);
   raise;
 end;
 Seek(0, soFromBeginning);
end;

destructor TMemoryMapStream.Destroy;
begin
if fFile <> 0 then begin
    doPack(false);
    CloseHandle(fFile);
   end;
end;

procedure TMemoryMapStream.OpenMMap;
begin
if fFile <> 0 then begin
 if fReadOnly then fMemMap := CreateFileMapping(fFile, nil, PAGE_READONLY or SEC_COMMIT, 0, 0, nil)
 else fMemMap := CreateFileMapping(fFile, nil, PAGE_READWRITE or SEC_COMMIT, 0, 0, nil);
 if fMemMap = 0 then raise Exception.Create("could not create memory map of file");
 Map;
end;
end;

procedure TMemoryMapStream.CloseMMap;
begin
if fMemMap <> 0 then begin
       UnMap;
       CloseHandle(fMemMap);
end;
end;

procedure TMemoryMapStream.Map;
var p: pointer;
filesize: integer;
begin
   SetPointer(nil, 0);
   if fReadOnly then
       p := MapViewOfFile(fMemMap, FILE_MAP_READ, 0, 0, 0)
else
 p := MapViewOfFile(fMemMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if p = nil then raise Exception.Create("could not read file");
filesize := GetFileSize(fFile, nil);
fRealSize := filesize;
SetPointer(p, filesize);
Position := 0;
end;

procedure TMemoryMapStream.UnMap;
begin
if Memory <> nil then begin
 if not fReadOnly then FlushViewOfFile(Memory, 0);
 UnmapViewOfFile(Memory);
end;
end;

procedure TMemoryMapStream.doPack(reopen: boolean);
begin
CloseMMap;
try
 SetEOF(Size);
   finally
    if reopen then OpenMMap;
end;
end;

procedure TMemoryMapStream.SetEOF(pos: integer);
begin
   if fReadOnly then exit;
   if SetFilePointer(fFile, pos, nil, FILE_BEGIN) = DWORD(-1) then // !!! INVALID_SET_FILE_POINTER
    raise Exception.Create("could not resize file");
   SetEndOfFile(fFile);
end;

//---------------------------------------------------------------------------

procedure TMemoryMapStream.SetSize(const NewSize: int64);
begin
SetSize(integer(NewSize));
end;

procedure TMemoryMapStream.SetGranularity(value: integer);
begin
if value = fGranularity then exit;
   fGranularity := value;
   if fGranularity < min_size then fGranularity := min_size;
end;

procedure TMemoryMapStream.Clear;
begin
   SetSize(min_size);
   doPack(true);
   ZeroMemory(Memory, min_size);
end;

procedure TMemoryMapStream.SetSize(NewSize: integer);
var mult: integer;
begin
if NewSize = Size then exit;
if (fFile <> 0) and not fReadOnly then begin
 if NewSize > fRealSize then begin
  CloseMMap;
  mult := (NewSize - fRealSize) div fGranularity;
           if ((NewSize - fRealSize) mod fGranularity) > 0 then
            fRealSize := fRealSize + ((mult + 1) * fGranularity)
  else
            fRealSize := fRealSize + (mult * fGranularity);
  SetEOF(fRealSize);
           OpenMMap;
  SetPointer(Memory, NewSize);
 end
 else SetPointer(Memory, NewSize);
end;
end;

function TMemoryMapStream.Write(const Buffer; Count: longint): longint;
var pos: longint;
begin
pos := Position;
if (pos < 0) or (Count <= 0) or fReadOnly then begin
 result := 0;
 exit;
   end;
if (pos + Count) > Size then SetSize(pos + Count);
System.Move(Buffer, (pointer(longint(Memory) + pos))^, Count);
pos := pos + Count;
Position := pos;
   Result := Count;
end;

procedure TMemoryMapStream.LoadFromFile(const FileName: string);
var f: TFileStream;
begin
   f := TFileStream.Create(FileName, fmOpenRead);
   try
    LoadFromStream(f);
finally
    f.Free;
end;
end;

procedure TMemoryMapStream.LoadFromStream(Stream: TStream);
var sz: integer;
begin
if fReadOnly then exit;
sz := Stream.Size;
SetSize(sz);
Stream.Read(Memory^, sz);
Seek(0, soFromBeginning);
end;

procedure TMemoryMapStream.Pack;
begin
doPack(true);
end;

end.

не идеален, но свои функции исполняет...


 
wicked ©   (2006-01-29 22:39) [25]


> По подробнее пример использования MMF + StretchDIBits можно
> посмотреть?

2) вывод изображения с помощью StretchDIBits (на билдере - перевести на паскаль - задание на дом)
void __fastcall PaintStretchedDIB(void * srcdata, TRect& srcrect, HDC dstdc, TRect& dstrect)
{
LPBITMAPFILEHEADER bfh = (LPBITMAPFILEHEADER) srcdata;
LPBITMAPINFO bi = (LPBITMAPINFO)((LPBYTE)srcdata + sizeof(BITMAPFILEHEADER));
StretchDIBits(dstdc, dstrect.left, dstrect.top, dstrect.Width(), dstrect.Height(),
 srcrect.left, srcrect.top, srcrect.Width(), srcrect.Height(),
 ((LPBYTE)srcdata + bfh->bfOffBits), bi, DIB_RGB_COLORS, SRCCOPY);
}

использовать:
PaintStretchedDIB(MemoryMapStream.Memory, Rect(0, 0, 100, 100), dest_dc, Rect(0, 0, 100, 100)) - рисует из MMF-а кусок размером 100x100 пикселей...


 
wicked ©   (2006-01-29 22:41) [26]

ЗЫ если нужно рисовать весь ДИБ, рекомендую подшаманить PaintStretchedDIB - вместо использования srcrect нужно использовать члены структуры LPBITMAPINFO - переменная bi....



Страницы: 1 вся ветка

Текущий архив: 2006.07.09;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.032 c
1-1148583624
navinaiv
2006-05-25 23:00
2006.07.09
Криптография (гост 28 147-89)


2-1150983823
DimaRik
2006-06-22 17:43
2006.07.09
помогите


15-1150036998
PZ
2006-06-11 18:43
2006.07.09
Путь по умолчанию


2-1150781796
SkyRanger
2006-06-20 09:36
2006.07.09
Адресация элемента двумерного массива


4-1143023514
Alex Kryuchkov
2006-03-22 13:31
2006.07.09
Серийный номер мат. платы