Changeset 46 for trunk/ScreenTools.pas


Ignore:
Timestamp:
Jan 11, 2017, 8:12:01 AM (7 years ago)
Author:
chronos
Message:
  • Fixed: Some graphic drawing problems caused by different pixel byte width of bitmaps under Linux.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ScreenTools.pas

    r43 r46  
    1919  end;
    2020
     21  TColor32 = type Cardinal;
     22  TColor32Component = (ccBlue, ccGreen, ccRed, ccAlpha);
     23  TPixel32 = packed record
     24   case Integer of
     25     0: (B, G, R, A: Byte);
     26     1: (ARGB: TColor32);
     27     2: (Planes: array[0..3] of Byte);
     28     3: (Components: array[TColor32Component] of Byte);
     29  end;
     30  PPixel32 = ^TPixel32;
     31
    2132{$IFDEF WINDOWS}
    2233function ChangeResolution(x, y, bpp, freq: integer): boolean;
    2334{$ENDIF}
     35function GetBitmapPixelPtr(Bitmap: TBitmap; X, Y: Integer): PPixel32;
    2436procedure RestoreResolution;
    2537function Play(Item: string; Index: integer = -1): boolean;
     
    272284end;
    273285
     286function GetBitmapPixelPtr(Bitmap: TBitmap; X, Y: Integer): PPixel32;
     287begin
     288  Result := Pointer(Bitmap.RawImage.Data) + X * (Bitmap.RawImage.Description.BitsPerPixel shr 3) + Y * Bitmap.RawImage.Description.BytesPerLine;
     289end;
     290
    274291procedure EmptyMenu(MenuItems: TMenuItem; Keep: integer = 0);
    275292var
     
    514531
    515532function LoadGraphicSet(Name: string): integer;
    516 type
    517   TLine = array [0 .. 999, 0 .. 2] of Byte;
    518533var
    519534  i, x, y, xmax, OriginalColor: integer;
    520535  FileName: string;
    521536  Source: TBitmap;
    522   DataLine, MaskLine: ^TLine;
     537  DataPixel, MaskPixel: PPixel32;
    523538begin
    524539  i := 0;
     
    556571    for y := 0 to Source.Height - 1 do
    557572    begin
    558       DataLine := GrExt[nGrExt].Data.ScanLine[y];
    559       MaskLine := GrExt[nGrExt].Mask.ScanLine[y];
    560573      for x := 0 to xmax - 1 do
    561574      begin
    562         OriginalColor := Cardinal((@DataLine[x])^) and $FFFFFF;
     575        DataPixel := GetBitmapPixelPtr(GrExt[nGrExt].Data, x, y);
     576        MaskPixel := GetBitmapPixelPtr(GrExt[nGrExt].Mask, x, Y);
     577
     578        OriginalColor := DataPixel^.ARGB and $FFFFFF;
    563579        if (OriginalColor = $FF00FF) or (OriginalColor = $7F007F) then
    564580        begin // transparent
    565           Cardinal((@MaskLine[x])^) := $FFFFFF;
    566           Cardinal((@DataLine[x])^) := Cardinal((@DataLine[x])^) and $FF000000
     581          MaskPixel^.ARGB := $FFFFFF;
     582          DataPixel^.ARGB := DataPixel^.ARGB and $FF000000
    567583        end
    568584        else
    569585        begin
    570           Cardinal((@MaskLine[x])^) := $000000; // non-transparent
     586          MaskPixel^.ARGB := $000000; // non-transparent
    571587          if Gamma <> 100 then
    572588          begin
    573             DataLine[x, 0] := GammaLUT[DataLine[x, 0]];
    574             DataLine[x, 1] := GammaLUT[DataLine[x, 1]];
    575             DataLine[x, 2] := GammaLUT[DataLine[x, 2]];
     589            DataPixel^.B := GammaLUT[DataPixel^.B];
     590            DataPixel^.G := GammaLUT[DataPixel^.G];
     591            DataPixel^.R := GammaLUT[DataPixel^.R];
    576592          end
    577593        end
     
    621637// Src is template
    622638// X channel = background amp (old Dst content), 128=original brightness
    623 type
    624   TPixel = array [0 .. 2] of Byte;
    625639var
    626640  i, Brightness, test: integer;
    627641  PixelSrc: ^Byte;
    628   PixelDst: ^TPixel;
     642  PixelDst: PPixel32;
    629643begin
    630644  {TODO assert(Src.PixelFormat = pf8bit);}
     
    654668  while yDst < h do
    655669  begin
    656     PixelDst := dst.ScanLine[yDst] + 3 * xDst;
     670    PixelDst := GetBitmapPixelPtr(dst, xDst, yDst);
    657671    PixelSrc := Src.ScanLine[ySrc] + xSrc;
    658672    for i := 0 to w - 1 do
    659673    begin
    660674      Brightness := PixelSrc^;
    661       test := (PixelDst[2] * Brightness) shr 7;
     675      test := (PixelDst^.R * Brightness) shr 7;
     676      if test >= 256 then PixelDst^.R := 255
     677        else PixelDst^.R := test; // Red
     678      test := (PixelDst^.G * Brightness) shr 7;
     679      if test >= 256 then PixelDst^.G := 255
     680        else PixelDst^.G := test; // Green
     681      test := (PixelDst^.B * Brightness) shr 7;
    662682      if test >= 256 then
    663         PixelDst[2] := 255
     683        PixelDst^.R := 255
    664684      else
    665         PixelDst[2] := test; // Red
    666       test := (PixelDst[1] * Brightness) shr 7;
    667       if test >= 256 then
    668         PixelDst[1] := 255
    669       else
    670         PixelDst[1] := test; // Green
    671       test := (PixelDst[0] * Brightness) shr 7;
    672       if test >= 256 then
    673         PixelDst[2] := 255
    674       else
    675         PixelDst[0] := test; // Blue
    676       PixelDst := Pointer(PixelDst) + 3;
     685        PixelDst^.B := test; // Blue
     686      PixelDst := Pointer(PixelDst) + (Dst.RawImage.Description.BitsPerPixel shr 3);
    677687      PixelSrc := Pointer(PixelSrc) + 1;
    678688    end;
     
    690700// G channel = Color1 amp, 128=original brightness
    691701// R channel = Color2 amp, 128=original brightness
    692 type
    693   TLine = array [0 .. 9999, 0 .. 2] of Byte;
    694702var
    695703  ix, iy, amp1, amp2, trans, Value: integer;
    696   SrcLine, DstLine: ^TLine;
     704  SrcPixel, DstPixel: PPixel32;
    697705begin
    698706  if xDst < 0 then begin
     
    717725  for iy := 0 to h - 1 do
    718726  begin
    719     SrcLine := Src.ScanLine[ySrc + iy];
    720     DstLine := dst.ScanLine[yDst + iy];
    721727    for ix := 0 to w - 1 do
    722728    begin
    723       trans := SrcLine[xSrc + ix, 0] * 2; // green channel = transparency
    724       amp1 := SrcLine[xSrc + ix, 1] * 2;
    725       amp2 := SrcLine[xSrc + ix, 2] * 2;
     729      SrcPixel := GetBitmapPixelPtr(Src, xSrc + ix, ySrc + iy);
     730      DstPixel := GetBitmapPixelPtr(Dst, xDst + ix, yDst + iy);
     731      trans := SrcPixel^.B * 2; // green channel = transparency
     732      amp1 := SrcPixel^.G * 2;
     733      amp2 := SrcPixel^.R * 2;
    726734      if trans <> $FF then
    727735      begin
    728         Value := (DstLine[xDst + ix][0] * trans + ((Color2 shr 16) and $FF) * amp2
     736        Value := (DstPixel^.B * trans + ((Color2 shr 16) and $FF) * amp2
    729737          + ((Color1 shr 16) and $FF) * amp1) div $FF;
    730         if Value < 256 then
    731           DstLine[xDst + ix][0] := Value
    732         else
    733           DstLine[xDst + ix][0] := 255;
    734         Value := (DstLine[xDst + ix][1] * trans + ((Color2 shr 8) and $FF) * amp2
     738        if Value < 256 then DstPixel^.B := Value
     739        else DstPixel^.B := 255;
     740        Value := (DstPixel^.G * trans + ((Color2 shr 8) and $FF) * amp2
    735741          + ((Color1 shr 8) and $FF) * amp1) div $FF;
    736         if Value < 256 then
    737           DstLine[xDst + ix][1] := Value
    738         else
    739           DstLine[xDst + ix][1] := 255;
    740         Value := (DstLine[xDst + ix][2] * trans + (Color2 and $FF) * amp2 +
     742        if Value < 256 then DstPixel^.G := Value
     743          else DstPixel^.G := 255;
     744        Value := (DstPixel^.R * trans + (Color2 and $FF) * amp2 +
    741745          (Color1 and $FF) * amp1) div $FF;
    742         if Value < 256 then
    743           DstLine[xDst + ix][2] := Value
    744         else
    745           DstLine[xDst + ix][2] := 255;
    746       end
    747     end
     746        if Value < 256 then DstPixel^.R := Value
     747          else DstPixel^.R := 255;
     748      end;
     749    end;
    748750  end;
    749751  Src.EndUpdate;
     
    757759// G channel = Color1 amp, 128=original brightness
    758760// R channel = Color2 amp, 128=original brightness
    759 type
    760   TPixel = array [0 .. 2] of Byte;
    761761var
    762762  i, Red, Green: integer;
    763   Pixel: ^TPixel;
     763  Pixel: PPixel32;
    764764begin
    765765  bmp.BeginUpdate;
     
    768768  while y < h do
    769769  begin
    770     Pixel := pointer(bmp.ScanLine[y]) + 3 * x;
     770    Pixel := GetBitmapPixelPtr(Bmp, x, y);
    771771    for i := 0 to w - 1 do
    772772    begin
    773       Red := ((Pixel[0] * (Color0 and $0000FF) + Pixel[1] * (Color1 and $0000FF)
    774         + Pixel[2] * (Color2 and $0000FF)) shr 8) and $ff;
    775       Green := ((Pixel[0] * (Color0 shr 8 and $0000FF) + Pixel[1] *
    776         ((Color1 shr 8) and $0000FF) + Pixel[2] * ((Color2 shr 8) and
     773      Red := ((Pixel^.B * (Color0 and $0000FF) + Pixel^.G * (Color1 and $0000FF)
     774        + Pixel^.R * (Color2 and $0000FF)) shr 8) and $ff;
     775      Green := ((Pixel^.B * ((Color0 shr 8) and $0000FF) + Pixel^.G *
     776        ((Color1 shr 8) and $0000FF) + Pixel^.R * ((Color2 shr 8) and
    777777        $0000FF)) shr 8) and $ff;
    778       Pixel[0] := ((Pixel[0] * (Color0 shr 16 and $0000FF) + Pixel[1] *
    779         ((Color1 shr 16) and $0000FF) + Pixel[2] * ((Color2 shr 16) and $0000FF))
     778      Pixel^.B := ((Pixel^.B * ((Color0 shr 16) and $0000FF) + Pixel^.G *
     779        ((Color1 shr 16) and $0000FF) + Pixel^.R * ((Color2 shr 16) and $0000FF))
    780780        shr 8) and $ff; // Blue
    781       Pixel[1] := Green;
    782       Pixel[2] := Red;
    783       Pixel := pointer(Pixel) + 3;
     781      Pixel^.G := Green;
     782      Pixel^.R := Red;
     783      Pixel := pointer(Pixel) + (Bmp.RawImage.Description.BitsPerPixel shr 3);
    784784    end;
    785785    inc(y);
Note: See TracChangeset for help on using the changeset viewer.