Bitmap.Scanline для PixelFormat

Советы » Bitmap » Bitmap.Scanline для PixelFormat

Кто-то из Италии попросил меня пример использования pf1bit в изображениях (Bitmaps), я послал часто ответа из имеющихся заготовок, подумал, и добавил здесь другие детали для pf8bit и pf24bit.

Общее

Новое в Delphi 3 свойство scanline допускает быстрый доступ к отдельным пикселям, но необходимо указать с каким Bitmap.PixelFormat вы работаете, прежде чем сможете иметь доступ к пикселям.

Возможные PixelFormats включают:

  1. pfDevice
  2. pf1bit
  3. pf4bit
  4. pf8bit
  5. pf15bit
  6. pf16bit
  7. pf24bit
  8. pf32bit

pf24bit-изображения

Для pf24bit-изображений необходимо определить:

CONST

PixelCountMax = 32768; TYPE

pRGBArray = ^TRGBArray; TRGBArray = ARRAY

[0..PixelCountMax-1] OF

TRGBTriple;

Примечание: TRGBTriple определен в модуле Windows.PAS.

Для того, чтобы к существующему 24-битному изображению иметь доступ как к изображению, созданному с разрешением 3 байта на пиксел, сделайте следующее:

...
VAR

i : INTEGER; j : INTEGER; RowOriginal : pRGBArray; RowProcessed: pRGBArray; BEGIN

IF

OriginalBitmap.PixelFormat <> pf24bit THEN

RAISE

EImageProcessingError.Create('GetImageSpace: ' + 'Изображение должно быть 24-х битным.'); {Шаг через каждую строчку изображения.} FOR

j := OriginalBitmap.Height-1 DOWNTO

0 DO

BEGIN

RowOriginal := pRGBArray(OriginalBitmap.Scanline[j]); RowProcessed := pRGBArray(ProcessedBitmap.Scanline[j]); FOR

i := OriginalBitmap.Width-1 DOWNTO

0 DO

BEGIN

// Доступ к RGB-цветам отдельных пикселей должен осуществляться следующим образом: // RowProcessed[i].rgbtRed := RowOriginal[i].rgbtRed; // RowProcessed[i].rgbtGreen := RowOriginal[i].rgbtGreen; // RowProcessed[i].rgbtBlue := RowOriginal[i].rgbtBlue; END

END

...

pf8bit-изображения

Доступ к такому формату изображения легко получить, используя TByteArray (определен в SysUtils.PAS):

PByteArray = ^TByteArray;
TByteArray = array

[0..32767] of

Byte;

(Я думаю (но сам этого не пробовал), что вы сможете получить доступ к pf16bit-изображениям, используя следующие определения в SysUtils.PAS:

PWordArray = ^TWordArray;
TWordArray = array

[0..16383] of

Word;

Для того, чтобы обработать 8-битное (pf8bit) изображение, используйте конструктор подобный этому, который создает гистограмму изображения:

TYPE

THistogram = ARRAY

[0..255] OF

INTEGER; ... VAR

Histogram: THistogram; i : INTEGER; j : INTEGER; Row : pByteArray; ... FOR

i := Low(THistogram) TO

High(THistogram) DO

Histogram[i] := 0; IF

Bitmap.PixelFormat = pf8bit THEN

BEGIN

FOR

j := Bitmap.Height-1 DOWNTO

0 DO

BEGIN

Row := pByteArray(Bitmap.Scanline[j]); FOR

i := Bitmap.Width-1 DOWNTO

0 DO

BEGIN

INC (Histogram[Row[i]]) END

END

END

...

pf1bit-изображения

Доступ к pf8bit-изображениям осуществляется достаточно легко, с тех пор, как они стали использовать один байт на пиксель. Но вы можете сохранить много памяти, если вам необходим единственный бит на пиксель (как, например, с различными масками) в случае pf1bit-изображения.

Как и в случае с pf8bit-изображениями, используйте TByteArray для доступа к pf1bit-ным линиям чередования (Scanlines). Но для доступа к отдельным пикселям вам понадобиться работать с битами отдельного байта. Так, ширина линии чередования равна Bitmap.Width DIV 8 байт.

Нижеприведенный код показывает как можно создать шаблон 1-битного изображения: черный, белый, полоски, "g", "стрелка" и случайный -- опция "инвертировано" также доступна. (Надеюсь, технологию вы освоете без труда.)

Создайте форму с Image1: для TImage я использую одно изображение Image1 размером 256x256 и свойством Stretch := TRUE, чтобы отдельные пиксели было легко разглядеть. Кнопки Black, White и Stripes имеют свойство tags, c соответствующими значениями 0, 255, и 85 ($55 = 01010101 в двоичной системе исчисления), вызывающие при нажатии обработчик события ButtonStripesClick.

Кнопки "g" и "arrow" имеют собственные обработчики событий, позволяющие корректно распечатать тестовые изображения на принтере HP Laserjet.

"Random" случайным образом устанавливает биты в 1-битном изображении.

"Invert" меняет нули на единички и наоборот.

// Пример того, как использовать Bitmap.Scanline для PixelFormat=pf1Bit.
// По просьбе Mino Ballone из Италии.
//
// Авторское право (C) 1997, Earl F. Glynn, Overland Park, KS.
// Все права защищены.
// Может свободно использоваться для некоммерческих целей.

unit

ScreenSingleBit; interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type

TForm1 = class

(TForm) Image1: TImage; ButtonBlack: TButton; ButtonWhite: TButton; ButtonStripes: TButton; ButtonG: TButton; ButtonArrow: TButton; ButtonRandom: TButton; ButtonInvert: TButton; procedure

ButtonStripesClick(Sender: TObject); procedure

ButtonGClick(Sender: TObject); procedure

FormCreate(Sender: TObject); procedure

FormDestroy(Sender: TObject); procedure

ButtonRandomClick(Sender: TObject); procedure

ButtonInvertClick(Sender: TObject); procedure

ButtonArrowClick(Sender: TObject); private

Bitmap: TBitmap; { Private declarations } public

{ Public declarations } end

; var

Form1: TForm1; implementation

{$R *.DFM} const

BitsPerPixel = 8; procedure

TForm1.ButtonStripesClick(Sender: TObject); var

i: INTEGER; j: INTEGER; Row: pByteArray; Value: BYTE; begin

Value := (Sender as

TButton).Tag; // Value = $00 = 00000000 в двоичном исчислении для черного // Value = $FF = 11111111 в двоичном исчислении для белого // Value = $55 = 01010101 в двоичном исчислении для черных и белых полос for

j := 0 to

Bitmap.Height - 1 do

begin

Row := pByteArray(Bitmap.Scanline[j]); for

i := 0 to

(Bitmap.Width div

BitsPerPixel) - 1 do

begin

Row[i] := Value end

end

; Image1.Picture.Graphic := Bitmap end

; procedure

TForm1.ButtonGClick(Sender: TObject); const

{Изображение "g" было адаптировано для печати на принтере LaserJet IIP в соответствии с техническим руководством} G: array

[0..31, 0..3] of

BYTE = { 0}(($00, $FC, $0F, $C0), {00000000 11111100 00001111 11000000} { 1}($07, $FF, $1F, $E0), {00000111 11111111 00011111 11100000} { 2}($0F, $FF, $9F, $C0), {00001111 11111111 10011111 11000000} { 3}($3F, $D7, $DE, $00), {00111111 11010111 11011110 00000000} { 4}($3E, $01, $FE, $00), {00111110 00000001 11111110 00000000} { 5}($7C, $00, $7E, $00), {01111100 00000000 01111110 00000000} { 6}($78, $00, $7E, $00), {01111000 00000000 01111110 00000000} { 7}($F0, $00, $3E, $00), {11110000 00000000 00111110 00000000} { 8}($F0, $00, $3E, $00), {11110000 00000000 00111110 00000000} { 9}($F0, $00, $1E, $00), {11110000 00000000 00011110 00000000} {10}($F0, $00, $1E, $00), {11110000 00000000 00011110 00000000} {11}($F0, $00, $1E, $00), {11110000 00000000 00011110 00000000} {12}($F0, $00, $1E, $00), {11110000 00000000 00011110 00000000} {13}($F0, $00, $3E, $00), {11110000 00000000 00111110 00000000} {14}($78, $00, $3E, $00), {01111000 00000000 00111110 00000000} {15}($78, $00, $3E, $00), {01111000 00000000 00111110 00000000} {16}($78, $00, $7E, $00), {01111000 00000000 01111110 00000000} {17}($3C, $00, $FE, $00), {00111100 00000000 11111110 00000000} {18}($1F, $D7, $DE, $00), {00011111 11010111 11011110 00000000} {19}($0F, $FF, $5E, $00), {00001111 11111111 10011110 00000000} {20}($07, $FF, $1E, $00), {00000111 11111111 00011110 00000000} {21}($00, $A8, $1E, $00), {00000000 10101000 00011110 00000000} {22}($00, $00, $1E, $00), {00000000 00000000 00011110 00000000} {23}($00, $00, $1E, $00), {00000000 00000000 00011110 00000000} {24}($00, $00, $1E, $00), {00000000 00000000 00011110 00000000} {25}($00, $00, $3E, $00), {00000000 00000000 00111110 00000000} {26}($00, $00, $3C, $00), {00000000 00000000 00111100 00000000} {27}($00, $00, $7C, $00), {00000000 00000000 01111100 00000000} {28}($00, $01, $F8, $00), {00000000 00000001 11111000 00000000} {29}($01, $FF, $F0, $00), {00000001 11111111 11110000 00000000} {30}($03, $FF, $E0, $00), {00000011 11111111 11100000 00000000} {31}($01, $FF, $80, $00)); {00000001 11111111 10000000 00000000} var

i: INTEGER; j: INTEGER; Row: pByteArray; begin

for

j := 0 to

Bitmap.Height - 1 do

begin

Row := pByteArray(Bitmap.Scanline[j]); for

i := 0 to

(Bitmap.Width div

BitsPerPixel) - 1 do

begin

Row[i] := G[j, i] end

end

; Image1.Picture.Graphic := Bitmap end

; procedure

TForm1.ButtonArrowClick(Sender: TObject); const

{Изображение "стрелка" было адаптировано для печати на принтере LaserJet IIP в соответствии с техническим руководством} Arrow: array

[0..31, 0..3] of

BYTE = { 0}(($00, $00, $80, $00), {00000000 00000000 10000000 00000000} { 1}($00, $00, $C0, $00), {00000000 00000000 11000000 00000000} { 2}($00, $00, $E0, $00), {00000000 00000000 11100000 00000000} { 3}($00, $00, $F0, $00), {00000000 00000000 11110000 00000000} { 4}($00, $00, $F8, $00), {00000000 00000000 11111000 00000000} { 5}($00, $00, $FC, $00), {00000000 00000000 11111100 00000000} { 6}($00, $00, $FE, $00), {00000000 00000000 11111110 00000000} { 7}($00, $00, $FF, $00), {00000000 00000000 11111111 00000000} { 8}($00, $00, $FF, $80), {00000000 00000000 11111111 10000000} { 9}($FF, $FF, $FF, $C0), {11111111 11111111 11111111 11000000} {10}($FF, $FF, $FF, $E0), {11111111 11111111 11111111 11100000} {11}($FF, $FF, $FF, $F0), {11111111 11111111 11111111 11110000} {12}($FF, $FF, $FF, $F8), {11111111 11111111 11111111 11111000} {13}($FF, $FF, $FF, $FC), {11111111 11111111 11111111 11111100} {14}($FF, $FF, $FF, $FE), {11111111 11111111 11111111 11111110} {15}($FF, $FF, $FF, $FF), {11111111 11111111 11111111 11111111} {16}($FF, $FF, $FF, $FF), {11111111 11111111 11111111 11111111} {17}($FF, $FF, $FF, $FE), {11111111 11111111 11111111 11111110} {18}($FF, $FF, $FF, $FC), {11111111 11111111 11111111 11111100} {19}($FF, $FF, $FF, $F8), {11111111 11111111 11111111 11111000} {20}($FF, $FF, $FF, $F0), {11111111 11111111 11111111 11110000} {21}($FF, $FF, $FF, $E0), {11111111 11111111 11111111 11100000} {22}($FF, $FF, $FF, $C0), {11111111 11111111 11111111 11000000} {23}($00, $00, $FF, $80), {00000000 00000000 11111111 10000000} {24}($00, $00, $FF, $00), {00000000 00000000 11111111 00000000} {25}($00, $00, $FE, $00), {00000000 00000000 11111110 00000000} {26}($00, $00, $FC, $00), {00000000 00000000 11111100 00000000} {27}($00, $00, $F8, $00), {00000000 00000000 11111000 00000000} {28}($00, $00, $F0, $00), {00000000 00000000 11110000 00000000} {29}($00, $00, $E0, $00), {00000000 00000000 11100000 00000000} {30}($00, $00, $C0, $00), {00000000 00000000 11000000 00000000} {31}($00, $00, $80, $00)); {00000000 00000000 10000000 00000000} var

i: INTEGER; j: INTEGER; Row: pByteArray; begin

for

j := 0 to

Bitmap.Height - 1 do

begin

Row := pByteArray(Bitmap.Scanline[j]); for

i := 0 to

(Bitmap.Width div

BitsPerPixel) - 1 do

begin

Row[i] := arrow[j, i] end

end

; Image1.Picture.Graphic := Bitmap end

; procedure

TForm1.FormCreate(Sender: TObject); begin

Bitmap := TBitmap.Create; with

Bitmap do

begin

Width := 32; Height := 32; PixelFormat := pf1bit end

; Image1.Picture.Graphic := Bitmap end

; procedure

TForm1.FormDestroy(Sender: TObject); begin

Bitmap.Free end

; procedure

TForm1.ButtonRandomClick(Sender: TObject); var

i: INTEGER; j: INTEGER; Row: pByteArray; begin

for

j := 0 to

Bitmap.Height - 1 do

begin

Row := pByteArray(Bitmap.Scanline[j]); for

i := 0 to

(Bitmap.Width div

BitsPerPixel) - 1 do

begin

Row[i] := Random(256) end

end

; Image1.Picture.Graphic := Bitmap end

; procedure

TForm1.ButtonInvertClick(Sender: TObject); var

i: INTEGER; j: INTEGER; Row: pByteArray; begin

for

j := 0 to

Bitmap.Height - 1 do

begin

Row := pByteArray(Bitmap.Scanline[j]); for

i := 0 to

(Bitmap.Width div

BitsPerPixel) - 1 do

begin

Row[i] := not

Row[i] end

end

; Image1.Picture.Graphic := Bitmap end

; end

.

Другое по теме:

Категории

Статьи

Советы

Copyright © 2022 - All Rights Reserved - www.delphirus.com