Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
42 / 35 / 8
Регистрация: 10.03.2017
Сообщений: 291
RAD XE3+

Прочитать три байта

05.11.2022, 05:36. Показов 3054. Ответов 54
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Так работает:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
type
 FArrLw=Array[0..2047] of LongWord;
 PArrLw=^FArrLw;
var
 Bm:TBitMap;
 ArrRCM:Array[0..1] of LongWord;
procedure DoReplace(Bm:TBitmap);
  var
   cyc1,cyc2:LongInt;
   psl:PArrLw;
 begin
  if Bm.PixelFormat<>pf32bit then
   Exit;
  for cyc2:=0 to Bm.Height-1 do
   begin
    psl:=Bm.ScanLine[cyc2];
    for cyc1:=0 to Bm.Width-1 do
     psl[cyc1]:=ArrRCM[psl[cyc1] mod 2];
   end;;
 end;
procedure TForm1.FormCreate(Sender:TObject);
 begin
  Bm:=TBitmap.Create;
  Bm.PixelFormat:=pf32bit;
  begin //Для примера
   Bm.SetSize(100,100);
   ArrRCM[0]:=Random($FFFFFF);
   ArrRCM[1]:=Random($FFFFFF);
   BitBlt(Bm.Canvas.Handle,0,0,100,100,GetDC(0),0,0,SRCCOPY);
  end;
  DoReplace(Bm);
  Form1.Image1.Picture.Assign(Bm);
 end;
Как теперь сделать тоже самое, только для pf24bit?
Как сделать, чтобы оно читало по 3 байта, и устанавливала обратно тоже 3 байта?
Желательно именно при такой конфигурации, потому что важна скорость.
И массивы будут что-то вроде:
Delphi
1
2
 FArrLw=Array[0..2047] of 0..$FFFFFF;
 ArrRCM:Array[0..1] of 0..$FFFFFF;
Этот пример с 4-мя байтами LongWord'а уже работает быстро, но нужно ещё быстрее. В оригинальной задаче у меня стоит обрезка по маске:
Delphi
1
psl[cyc1]:=ArrRCol[psl[cyc1] and $FFFFFF]; //ArrRCol:Array[0..$FFFFFF] of LongWord;
потому что не могу понять, как читать по 3 байта, а не 4. Думаю, что если избавлюсь от "and $FFFFFF", то смогу выиграть ещё немного больше производительности.
P.s. потоки само собой юзаются. Насколько я понимаю, читать/писать 3 байта вместо 4-х = быстрее. Как сделать?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.11.2022, 05:36
Ответы с готовыми решениями:

Как прочитать три разных байта в файле
Вот так пробовал: FileStream fs = File.OpenRead(path); byte f1 = new byte; byte f2 = new byte; byte...

Как прочитать строку до нулевого байта?
Имеется класс для чтения и записи в память процесса. Данный код читает строку указанной длины (длина полезной строки) не известна...

Как прочитать файл в бинарном режиме по 32 байта
Здравствуйте, как считать файл в бинарном режиме (в двоичной системе счисления) по 32 байта, попутно записывая эти 32 байта в переменную...

54
Модератор
 Аватар для D1973
9954 / 6490 / 2461
Регистрация: 21.01.2014
Сообщений: 27,498
Записей в блоге: 3
09.11.2022, 14:36
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от ugorek Посмотреть сообщение
очень информативная
А что не так-то? Там же сразу и отсылка к MSDN - где же еще быть описанной WinAPI-шной функции?
0
42 / 35 / 8
Регистрация: 10.03.2017
Сообщений: 291
09.11.2022, 14:40  [ТС]
Цитата Сообщение от D1973 Посмотреть сообщение
где же еще быть описанной WinAPI-шной функции?
Окей, окей. Всё так. Очень круто. Но к чему это было? Чтобы что?
Подразумевалось, что я с этого должен был что-то понять с этой ссылки. Что же?
Что это win-api функция? Ок, понял, а дальше что? У меня от этого 3 байта читаться быстрее не стали :C
0
 Аватар для mr-Crocodile
3054 / 1673 / 657
Регистрация: 19.03.2019
Сообщений: 5,380
09.11.2022, 14:49
Цитата Сообщение от ugorek Посмотреть сообщение
Что это win-api функция? Ок, понял, а дальше что? У меня от этого 3 байта читаться быстрее не стали :C
покажи, как ты CopyMemory вызываешь у себя в коде.
0
42 / 35 / 8
Регистрация: 10.03.2017
Сообщений: 291
09.11.2022, 14:55  [ТС]
Цитата Сообщение от mr-Crocodile Посмотреть сообщение
покажи
См. мой "победный" пост.

Вот так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
procedure DoConvert(Bm:TBitmap);
  var cyc1,cyc2,lw,pp:LongWord;
 begin
  lw:=0;
  for cyc2:=0 to Bm.Height-1 do
   begin
    pp:=LongWord(Bm.ScanLine[cyc2]);
    for cyc1:=0 to Bm.Width-1 do
     begin
      CopyMemory(@lw,Pointer(pp+cyc1*3),3);
      CopyMemory(Pointer(pp+cyc1*3),@ArrRCol[lw],3);
     end;
   end;
 end;
При этом, CopyMemory ничто иное как:
Delphi
1
2
3
4
 procedure CopyMemory(Destination:Pointer;Source:Pointer;Length:NativeUInt);
  begin
   move(Source^,Destination^,Length);
  end;
Показал. Что дальше?
0
 Аватар для mr-Crocodile
3054 / 1673 / 657
Регистрация: 19.03.2019
Сообщений: 5,380
09.11.2022, 15:04
Цитата Сообщение от ugorek Посмотреть сообщение
При этом, CopyMemory ничто иное как:
Delphi
1
2
3
4
 procedure CopyMemory(Destination:Pointer;Source:Pointer;Length:NativeUInt);
  begin
   move(Source^,Destination^,Length);
  end;
да, вижу. тогда я был неправ, забудь про CopyMemory, извини за путаницу, я ожидал, что CopyMemory - это обращение к WinAPI, а нет тот же MOVE()
1
42 / 35 / 8
Регистрация: 10.03.2017
Сообщений: 291
09.11.2022, 15:12  [ТС]
Я когда-то вместо того, чтобы зажать ctrl и кликнуть на CopyMemory, попёрся в гугл гуглить "В чём разница между CopyMemory() и Move()".

Окей, всё круто конечно же, но осталось только разгадать тайну с TRGBTriple, что я пометил оранжевым цветом.

Цитата Сообщение от mr-Crocodile Посмотреть сообщение
И зачем тему продолжать развивать - ты свою задачу решил
Вообще-то нет. Нужно было "ещё быстрее", а не "ещё медленнее".
1
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,498
09.11.2022, 17:07
Цитата Сообщение от ugorek Посмотреть сообщение
Нужно было "ещё быстрее", а не "ещё медленнее".
Не получается быстрее такими упражнениями.
Ну вот у меня получилось на 24 битном через RGBTriple около 60 fps, и на 32 битном через массив DWORDArray около 95 fps. Брал картинку размером 2048х2048 и заменял пиксели по таблице, как в твоём первом посте.
0
09.11.2022, 18:14

Не по теме:


Всё дело в регистрах процессора, данные-то по-любому проходят ч/з них.
А вообще получившийся ассемблерный код нужно смотреть, ну или на ассемблере переписать критическую секцию кода - так делали в старые добрые времена.

0
09.11.2022, 18:54

Не по теме:

вы чо еще не прочитали 3 байта? Чем вы тут неделю занимались, а?)))

0
42 / 35 / 8
Регистрация: 10.03.2017
Сообщений: 291
10.11.2022, 04:59  [ТС]
Цитата Сообщение от AzAtom Посмотреть сообщение
через массив DWORDArray около 95 fps
О:
А можно исходники? Твой процессор видать по мощнее моего будет.
Цитата Сообщение от AzAtom Посмотреть сообщение
RGBTriple около 60 fps
Неужели это означает, что хвалёный TRGBTriple оказался хренью?

Цитата Сообщение от Arcor Посмотреть сообщение
вы чо еще не прочитали 3 байта? Чем вы тут неделю занимались?
Вообще-то прочитали. См. мой "победный" пост. И прошло только 5 дней и ~2 часа.
0
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,498
10.11.2022, 10:20
Цитата Сообщение от ugorek Посмотреть сообщение
Твой процессор видать по мощнее моего будет.
Это вряд ли - ноутбучный Core i5 2-го поколения.

Цитата Сообщение от ugorek Посмотреть сообщение
А можно исходники?
Это было состряпано чисто для тестов:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Jpeg;
 
type
  TMyRGB = packed record // Это не сработало
    case integer of
    0: (B, G, R: byte);
    1: (dw: dword);
  end;
 
  TForm1 = class(TForm)
    btn24bit: TButton;
    Label1: TLabel;
    Timer1: TTimer;
    btn32bit: TButton;
    btnStop: TButton;
    PaintBox1: TPaintBox;
    procedure btn24bitClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure btn32bitClick(Sender: TObject);
    procedure btnStopClick(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    { Private declarations }
    ArrRCol: array of TColor;
    ArrRCol24: array of TRGBTriple;
    bmPic24, bmPic32, bmView: TBitmap;
    fps: integer;
    UsrStop: boolean;
  public
    { Public declarations }
  end;
 
  PRGBArray = ^TRGBArray;
  TRGBArray = array[0..0] of TRGBTriple;
  PDWORDArray = ^TDWORDArray;
  TDWORDArray = array[0..0] of DWORD;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure LoadPicture(bmap: TBitmap; FileName: string);
var
  pic: TPicture;
begin
  pic := TPicture.Create;
  try
    pic.LoadFromFile(FileName);
    bmap.Width  := pic.Width ;
    bmap.Height := pic.Height;
    bmap.Canvas.Draw(0, 0, pic.Graphic);
  finally
    pic.Free;
  end;
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
begin
  SetLength(ArrRCol24, 256*256*256);
  for i := 0 to High(ArrRCol24) do begin
    ArrRCol24[i].rgbtBlue  := (High(ArrRCol24) - i       ) and $FF;
    ArrRCol24[i].rgbtGreen := (High(ArrRCol24) - i shr  8) and $FF;
    ArrRCol24[i].rgbtRed   := (High(ArrRCol24) - i shr 16) and $FF;
//    ArrRCol24[i].dw := High(ArrRCol24) - i;
  end;
 
  SetLength(ArrRCol, 256*256*256);
  for i := 0 to High(ArrRCol) do
    ArrRCol[i] := High(ArrRCol) - i;
 
  bmPic24 := TBitmap.Create;
  bmPic24.Width  := 2048;
  bmPic24.Height := 2048;
  bmPic24.PixelFormat := pf24bit;
  LoadPicture(bmPic24, ExtractFilePath(ParamStr(0)) + '1.jpg');
 
  bmPic32 := TBitmap.Create;
  bmPic32.Width  := 2048;
  bmPic32.Height := 2048;
  bmPic32.PixelFormat := pf32bit;
  LoadPicture(bmPic32, ExtractFilePath(ParamStr(0)) + '1.jpg');
 
  bmView := bmPic32;
  fps := 0;
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil(bmPic24);
  FreeAndNil(bmPic32);
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Label1.Caption := IntToStr(fps) + ' fps';
  fps := 0;
  PaintBox1.Canvas.Draw(0, 0, bmView);
end;
 
procedure TForm1.btn24bitClick(Sender: TObject);
var
  pLine: PRGBArray;
  x, y, w: integer;
  bst, bbpl, bh: integer;
begin
  //
  UsrStop := false;
  bmView := bmPic24;
  bst := integer(bmPic24.ScanLine[bmPic24.Height-1]);
  bbpl := (bmPic24.Width*3 + 3) and -4;
  bh := bmPic24.Height - 1;
  w := bmPic24.Width - 1;
  repeat
    for y := 0 to bmPic24.Height-1 do begin
      pLine := pointer(bst + (bh - y)*bbpl); // Так быстрее
//      pLine := bmPic24.ScanLine[y]; // Так медленнее
      for x := 0 to w do
        pLine^[x] := ArrRCol24[((pLine^[x].rgbtBlue) +
                                (pLine^[x].rgbtGreen shl 8) +
                                (pLine^[x].rgbtRed shl 16))];
    end;
    Inc(fps);
    Application.ProcessMessages;
  until UsrStop;
end;
 
procedure TForm1.btn32bitClick(Sender: TObject);
var
  pLine: PDWORDArray;
  x, y: integer;
  bst, bbpl, bh: integer;
begin
  //
  UsrStop := false;
  bmView := bmPic32;
  bst := integer(bmPic32.ScanLine[bmPic32.Height-1]);
  bbpl := (bmPic32.Width*4 + 3) and -4; // Выравнивание на 4 в большую сторону
  bh := bmPic32.Height - 1;
  repeat
    for y := 0 to bmPic32.Height-1 do begin
      pLine := pointer(bst + (bh - y)*bbpl); // Так быстрее
//      pLine := bmPic32.ScanLine[y]; // Тут заметно медленнее
      for x := 0 to bmPic32.Width-1 do
        pLine^[x] := ArrRCol[pLine^[x] and $00FFFFFF];
    end;
    Inc(fps);
    Application.ProcessMessages;
  until UsrStop;
end;
 
procedure TForm1.btnStopClick(Sender: TObject);
begin
  UsrStop := true;
end;
 
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  UsrStop := true;
end;
 
end.
С загруженной картинкой получается 60 fps при 24 бит и 95 fps при 32 бит.
А если не загружать картинку, оставить белым полем, то получается соответственно 100 и 275 fps, но это не показатель.

Добавлено через 10 минут
Цитата Сообщение от ugorek Посмотреть сообщение
psl[cyc1]:=ArrRCol[psl[cyc1] and $FFFFFF];
Что в таблице ArrRCol? Как заполняется?
1
42 / 35 / 8
Регистрация: 10.03.2017
Сообщений: 291
10.11.2022, 11:27  [ТС]
Охренеть!!1
Действительно 95 fps!
Так вот в каком ядерном реакторе я на самом деле нуждался: pLine^[x] := ArrRCol[pLine^[x] and $00FFFFFF];
Волшебная штука.

Цитата Сообщение от AzAtom Посмотреть сообщение
Что в таблице ArrRCol?
Delphi
1
2
3
SetLength(ArrRCol,256*256*256);
for i:=0 to high(ArrRCol) do
 ArrRCol[i]:=high(ArrRCol)-i;
Ты угадал, именно вот это. И другое.
0
Модератор
4153 / 2362 / 814
Регистрация: 15.11.2015
Сообщений: 9,498
10.11.2022, 11:33
Цитата Сообщение от ugorek Посмотреть сообщение
Именно вот это
Ну тогда удивись ещё раз:
замени
Delphi
1
pLine^[x] := ArrRCol[pLine^[x] and $00FFFFFF];
на
Delphi
1
pLine^[x] := (256*256*256-1) - pLine^[x];
и получи 295 fps без таблицы.
А по такой большой таблице будет медленно, да.
0
42 / 35 / 8
Регистрация: 10.03.2017
Сообщений: 291
10.11.2022, 11:37  [ТС]
Цитата Сообщение от AzAtom Посмотреть сообщение
Ну тогда удивись ещё раз:
О спасибо, я на это не куплюсь))00)0
Ключевое слово у меня "И другое":
Цитата Сообщение от ugorek Посмотреть сообщение
Ты угадал, именно вот это. И другое.
Мой "ArrRCol" каждый раз может содержать разные методы замены.
Тебе повезло угадать самый простой и быстрый из них.
У меня же некоторые методы требуют создания по ~2 секунды с потоками.
Вычислить, на что будут заменяться каждые 16777216 пикселей, это вам не раз плюнуть))00)0
Именно поэтому я и создал свой "ArrRCol", чтобы вычислить один раз и не париться.
0
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
11.11.2022, 02:21
Цитата Сообщение от ugorek Посмотреть сообщение
499 книг по Delphi,
Цитата Сообщение от ugorek Посмотреть сообщение
Возможно ещё понадобятся 800 гайдов на ютубе от индусов
1 книга по Ассемблеру и устройству памяти
Цитата Сообщение от ugorek Посмотреть сообщение
Я только что написал код, использующий move(), который читает/пишет прямо из картинки TBitmap'а по 3 байта. И результаты этого - снижение производительности в ~2 раза.
Процессор быстрее работает с выровненными по 4 байта данными.
Цитата Сообщение от ugorek Посмотреть сообщение
всё круто конечно же, но осталось только разгадать тайну с TRGBTriple, что я пометил оранжевым цветом.
быстрее не будет, потому что процессор...Даже с RGBQuad не будет. указатели(на 4 байтовые данные) самое быстрое для доступа к 4 байтовым данным.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
11.11.2022, 02:21

Как прочитать значение байта по адресу в оперативке?
Как прочитать значение байта по адресу в оперативке? Аналог peek(a) в qbasic?

Как прочитать несколько байтов в файле с n-го байта по m-й байт ?
Как прочитать несколько байтов в файле с n-го байта по m-й байт ?

Прочитать 4 байта как вещественное число с плавающей точкой
Всем здравствуйте. имеется байтовый массив из четырёх байт как прочитать его как одно значение типа Single схожая задача имеется...

В переменную типа integer прочитать число длиною в 4 байта
Добрый день. Кто чем может, помогите разобраться. Решил разобраться с изображениями (пока формат bmp), не использую стандартные...

Три байта в Int
Приветствую. так как С# не поддерживает 24 bit integers, a BitConverter требует четвертый байт. Нужна помощь. Из трех байт нужно...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
55
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru