Работа с изображением в памяти
01.01.2007
Вот кусок одного моего класса, в котором есть две интересные вещицы -
проецирование файлов в память и работа с битмэпом в памяти через указатель.
type TarrRGBTriple=array[byte] of TRGBTriple; ParrRGBTriple=^TarrRGBTriple; {организует битмэп размером SX,SY;true_color} procedure TMBitmap.Allocate(SX,SY:integer); var DC:HDC; begin if BM<>0 then DeleteObject(BM); {удаляем старый битмэп, если был} BM:=0; PB:=nil; fillchar(BI,sizeof(BI),0); with BI.bmiHeader do {заполняем структуру с параметрами битмэпа} begin biSize:=sizeof(BI.bmiHeader); biWidth:=SX; biHeight:=SY; biPlanes:=1; biBitCount:=24; biCompression:=BI_RGB; biSizeImage:=0; biXPelsPerMeter:=0; biYPelsPerMeter:=0; biClrUsed:=0; biClrImportant:=0; FLineSize:=(biWidth+1)*3 and (-1 shl 2); {размер строки(кратна 4 байтам)} if (biWidth or biHeight)<>0 then begin DC:=CreateDC('DISPLAY',nil,nil,nil); {замечательная функция (см.HELP), возвращает HBITMAP, позволяет сразу разместить выделяемый битмэп в спроецированном файле, что позволяет ускорять работу и экономить память при генерировании большого битмэпа} BM:=CreateDIBSection(DC,BI, DIB_RGB_COLORS, pointer(PB), nil, 0); DeleteDC(DC); {в PB получаем указатель на битмэп-----^^} if BM=0 then Error('error creating DIB'); end; end; end; {эта процедура загружает из файла true-color'ный битмэп} procedure TMBitmap.LoadFromFile(const FileName:string); var HF:integer; {file handle} HM:THandle; {file-mapping handle} PF:pchar; {pointer to file view in memory} i,j:integer; Ofs:integer; begin {открываем файл} HF:=FileOpen(FileName,fmOpenRead or fmShareDenyWrite); if HF<0 then Error('open file '''+FileName+''''); try {создаем объект-проецируемый файл} HM:=CreateFileMapping(HF,nil,PAGE_READONLY,0,0,nil); if HM=0 then Error('cannot create file mapping'); try {собственно проецируем объект в адресное } PF:=MapViewOfFile(HM,FILE_MAP_READ,0,0,0); {получаем указатель на область памяти, в которую спроецирован файл} if PF=nil then Error('cannot create map view of file'); try {работаем с файлом как с областью памяти через указатель PF} if PBitmapFileHeader(PF)^.bfType<>$4D42 then Error('file format'); Ofs:=PBitmapFileHeader(PF)^.bfOffBits; with PBitmapInfo(PF+sizeof(TBitmapFileHeader))^.bmiHeader do begin if (biSize<>40) or (biPlanes<>1) then Error('file format'); if (biCompression<>BI_RGB) or (biBitCount<>24) then Error('only true-color BMP supported'); {выделяем память под битмэп} Allocate(biWidth,biHeight); end; for j:=0 to BI.bmiHeader.biHeight-1 do for i:=0 to BI.bmiHeader.biWidth-1 do {Pixels - это property, возвр. указатель на соотв. RGBTriple в битмэпе} Pixels[i,j]^.Tr:=ParrRGBTriple(PF+j*FLineSize+Ofs)^[i]; finally UnmapViewOfFile(PF); end; finally CloseHandle(HM); end; finally FileClose(HF); end; end; {эта функция - реализация Pixels read} function TMBitmap.GetPixel(X,Y:integer):PRGB; begin if (X>=0) and (Xand (Y>=0) and (Ythen Result:=PRGB(PB+(Y)*FLineSize+X*3) else Result:=PRGB(PB); end;
Если у вас на форме есть компонент TImage, то можно сделать так:
var BMP:TMBitmap; B:TBitmap; ... BMP.LoadFromFile(..); B:=TBitmap.Create; B.Handle:=BMP.Handle; Image1.Picture.Bitmap:=B;
и загруженный битмэп появится на экране.
Alexander Burnashov
E-mail alex@arta.spb.su
(2:5030/254.36)