PByte jak to ugryść?

0

Mam coś takiego:

var
  inBuff, outBuff: PByte;
  Width: Height, nStride: Integer;
begin
  Width:= 1920;
  Height:= 1200;
  nStride:= Width * 3;
  GetMem(inBuff, nStride * Height);
  // tutaj wrzucam do inBuff bitmapę bez nagłówka
  // tu chcę ją obrócić
  // i zapisać w innym formacie
  FreeMem(inBuff);// wczytana bitmapa
  FreeMem(outBuff);// obrócona bitmapa
end;

Do inBuff za pomocą TMemoryStream wrzucam bitmapę 24bitową bez początkowego 54-bitowego nagłówka.
Problem jest taki że ta bitmapa jest do góry nogami i po konwersji do innego formatu zapisuje się do góry nogami.
Jak obrócić bitmapę w inBuff?

Myślałam o tym aby pobrać cały wiersz (albo początkowy adres) i wklepywać to do outBuff we właściwej kolejności. Niestety nie idzie mi z tymi PByte. Rozumiem, że to rodzaj tablicy bajtów ale nie potrafię się dobrać do poszczególnych bajtów obrazu. Wywnioskowałam że dane zapisane w inBuff to kolejne bajty kolorów (po 3 na piksel) zapisane jednym ciągiem (BGR,BGR,BGR,BGR, itp.) jak w tablicy jednowymiarowej, bez rozróżnienia które bajty są w którym wierszu.

Jakieś wskazówki? Podpowiedzi jak ruszyć z typem PByte?

0

Czytaj od tyłu w pętli i zapisuj do nowej tablicy ?

0

Zrobiłam tak ale, obraz jest odwrócony w pionie i ma zmienione kolory. Chyba coś nie tak zrobiłam, bo nie nie wiem jak posługiwać się typem PByte.

0

To może pokaż kod ? :>

0

Kod jest nieładny i nieprofesjonalny. Chyba inaczej się to robi.
Fragment odpowiedzialny za obracanie:

var
  ...
  Rot: array of Byte;
  x: Cardinal;
begin
  ...  // to co wyżej podałam
  SetLength(Rot, (nStride * Hight) - 54);
  for x:= Length(Rot) - 1 downto 0 do
  begin
     Rot[x]:= Byte(inBuff^);// <- Rot typu array of Byte, to chyba inaczej się robi.
     Inc(inBuff);
  end;
   ... // zapisywanie
  // i freememsy
end;

W wyniku mam bitmapę odwróconą jak trzeba z tym że lewa strona stała się prawą a prawa lewą i kolory są zmienone.

0
procedure dupa;
var
  inBuff, outBuff: PByte;
  Width, Height, nStride: Integer;
  inPointer, outPointer: PByte;
  y: Integer;
begin
  Width:= 1920;
  Height:= 1200;
  nStride:= Width * 3;
  GetMem(inBuff, nStride * Height);
  GetMem(outBuff, nStride * Height);
  //wczytanie bitmapy
  for y := Height - 1 downto 0 do
  begin
    inPointer := Ptr(Integer(inBuff) + y * nStride);
    outPointer := Ptr(Integer(outBuff) + (Height - y - 1) * nStride);
    CopyMemory(outPointer, inPointer, nStride);
  end;

  FreeMem(inBuff);// wczytana bitmapa
  FreeMem(outBuff);// obrócona bitmapa
end;
0

Dzięki Misiekd. Jesteś Wielki.
Działa tak jak chciałam.

inPointer := Ptr(Integer(inBuff) + y * nStride);

Integer(inBuff) zwraca aktualne miejsce w inBuff, do tego dodajemy numer wiersza pomnożony przez szerokość obrazu x 3 (bo tyle jest bajtów w obrazie na przemian BGR, BGR itp). W ten sposób mam ustawiany wskaźnik na początek kolejnych wierszy w inBuff.

outPointer := Ptr(Integer(outBuff) + (Height - y - 1) * nStride);

Integer(outBuff) zwraca aktualne miejsce w outBuff, do tego dodajemy wyskość obrazu pomniejszoną o aktualny numer wiersza - 1, wszystko mnożąc przez nStride aby przesunąć wskaźnik na koniec ostatniego wiersza. np. przy pierwszym przebiegu zaczynamy od 1 + (1200 - 1199 -1) * 5760 = 1 bajtu, potem od 5761, itp.

Popraw mnie jak coś pokręciłam.

0

dokładnie

1 użytkowników online, w tym zalogowanych: 0, gości: 1