Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.07.2008, 09:19   #1
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию StrechDIBits своими руками

Пытаюсь реализовать функцию. Ну вообщем то что можно было брать любой TRect на пнг и класть его в любую TRect на массив бит... по сути нам требуются только Scanline свой-ва. ну вот что готово:

TDIBSection - мой класс, не имеет значение что он делает, он возращает Scanline

Код:
const
  MaxPixelCountA = MaxInt div SizeOf(TRGBQuad);
  MaxPixelCount = MaxInt div SizeOf(TRGBTriple);

type
  PRGBArray = ^TRGBArray;
  TRGBArray = array[0..MaxPixelCount-1] of TRGBTriple;
  PRGBAArray = ^TRGBAArray;
  TRGBAArray = array[0..MaxPixelCountA-1] of TRGBQuad;

procedure DrawPNGToDIB(Dest: TDIBSection; DestRect: TRect; Src: TPNGObject;
  SrcRect: TRect);
var
  xsteps, ysteps: array of Integer;
  intscale: Integer;
  i, x, y, x1, x2: Integer;
  ws, hs, w, h: Integer;
  rows, ts, rowd, td, rowsa, tsa: PByte;
  j, c: Integer;
  pf: TPixelFormat;
  xshift, yshift: Integer;
begin
  ws := SrcRect.Right - SrcRect.Left;
  hs := SrcRect.Bottom - SrcRect.Top;
  w := DestRect.Right - DestRect.Left;
  h := DestRect.Bottom - DestRect.Top;

    SetLength(xsteps, ws);
    SetLength(ysteps, hs);
    intscale := round(w / ws * $10000);
    x1 := 0;
    x2 := (intscale + $7FFF) shr 16;
    for i := 0 to ws - 1 do
    begin
      xsteps[i] := x2 - x1;
      x1 := x2;
      x2 := ((i + 2) * intscale + $7FFF) shr 16;
      if x2 > w then
        x2 := w;
    end;
    intscale := round(h / hs * $10000);
    x1 := 0;
    x2 := (intscale + $7FFF) shr 16;
    for i := 0 to hs - 1 do
    begin
      ysteps[i] := (x2 - x1);
      x1 := x2;
      x2 := ((i + 2) * intscale + $7FFF) shr 16;
      if x2 > h then
        x2 := h;
    end;
    rows := @PRGBArray(Src.Scanline[SrcRect.Top])^[SrcRect.Left];
    rowsa := @Src.AlphaScanline[SrcRect.Top]^[SrcRect.Left]; // pByteArray
    rowd := @PRGBAArray(Dest.Scanline[DestRect.Top])^[DestRect.Left];
    for y := 0 to hs - 1 do
    begin
      for j := 1 to ysteps[y] do
      begin
        ts := rows;
        tsa := rowsa;    
        td := rowd;
        for x := 0 to ws - 1 do
        begin
          for i := 1 to xsteps[x] do
          begin
            PRGBQuad(td)^.rgbBlue := PRGBTriple(ts)^.rgbtBlue;
            PRGBQuad(td)^.rgbGreen := PRGBTriple(ts)^.rgbtGreen;
            PRGBQuad(td)^.rgbRed := PRGBTriple(ts)^.rgbtRed;
            PRGBQuad(td)^.rgbReserved := tsa^;
            inc(td, 4);
          end;
          inc(ts, 3);
          inc(tsa);
        end;
        dec(rowd, Dest.Width * 4);
      end;
      dec(rows, Src.Width * 3);
      dec(rowsa, Src.Width);
    end;
end;
По сути он копирует уже, но по краям образуется размаска как бы влево. Я алгоритм нашел в DW, но что за числа при формировании steps я вообще не пойму. Может кто знает алгоритм на слова, я бы почитал и сам бы уже реализовал )))
BOBAH13 вне форума Ответить с цитированием
Старый 06.07.2008, 21:59   #2
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Ну как обычно всем спасибо. Понял что это врятли выйдет, сделал функцию, она копируется область DestRect по 32 бита на пиксель, потом рисуем через Api StrechBlt потом формируем SrcRect область по байту - альфа канал. Потом относительно данного альфа канала в цикле устанавливаем прозрачность смешивая ранне созданный буфер и текущий цвет. вот и все.. конечно не идеально, но выход и довольно таки быстрый.
BOBAH13 вне форума Ответить с цитированием
Старый 06.07.2008, 22:23   #3
B_N
Новичок
Джуниор
 
Регистрация: 18.01.2008
Сообщений: 1,720
По умолчанию

Цитата:
Сообщение от BOBAH13 Посмотреть сообщение
Ну как обычно всем спасибо. Понял что это врятли выйдет, сделал функцию, она копируется область DestRect по 32 бита на пиксель, потом рисуем через Api StrechBlt потом формируем SrcRect область по байту - альфа канал. Потом относительно данного альфа канала в цикле устанавливаем прозрачность смешивая ранне созданный буфер и текущий цвет. вот и все.. конечно не идеально, но выход и довольно таки быстрый.
Зря Вы так. Сами же понимаете, что для того, чтобы найти проблемные места, нужно проверить эту функцию в работе, для чего весьма желательно иметь полный код, а не
Цитата:
TDIBSection - мой класс, не имеет значение что он делает, он возращает Scanline
. StrechDIBits ведь ещё и масштабирует картинки, чем собственно, и занята половина этой функции, прокручивать её работу в голове вряд ли кто станет, а полного кода опять же нет. Видимо поэтому никто не стал тратить время - vita brevis. Да и Вы, кстати, вполне возможно, зря его потратили, Windows уже давно умеет работать с PNG.
B_N вне форума Ответить с цитированием
Старый 22.07.2008, 14:52   #4
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Странно ) ну чтобы тему закрыть, вот код... все оказалось не так уж и тяжело. p.s. вспомнил про эту тему случайно ))
Скорость кода хорошая )

Код:
procedure TDIBSection.DrawPNG(DestRect: TRect; Src: TPNGObject;
  SrcRect: TRect; AlphaTransparent: Boolean);
var
  wd, ws, hd, hs: Integer;
  FactorX, FactorY: Double;
  ImageAlpha, ImageSource: PByteArray;
  ImageDest: PRGBAArray;
  i, j, i2, j2: Integer;
  BytesPerRowDest: Integer;
begin
  wd := DestRect.Right - DestRect.Left;
  hd := DestRect.Bottom - DestRect.Top;
  ws := SrcRect.Right - SrcRect.Left;
  hs := SrcRect.Bottom - SrcRect.Top;
  if (ws = 0) or (wd = 0) then FactorX := 1 else FactorX := wd / ws;
  if (hs = 0) or (hd = 0) then FactorY := 1 else FactorY := hd / hs;
  BytesPerRowDest := FWidth * 4;

  Integer(ImageDest) := Integer(FBits) + (FHeight - DestRect.Top - 1) *
    BytesPerRowDest + DestRect.Left * 4;

  for i:= 0 to hd - 1 do
  begin
    i2 := Trunc(i / FactorY);
    if (SrcRect.Top + i2 >= Integer(Src.Header.Height)) then Break;
    Integer(ImageSource) := Integer(Src.Scanline[SrcRect.Top + i2]) + SrcRect.Left * 3;
    Integer(ImageAlpha) := Integer(Src.AlphaScanline[SrcRect.Top + i2]) + SrcRect.Left;

    for j:= 0 to wd - 1 do
    begin
      j2 := Trunc(j / FactorX);

      if (ImageAlpha[j2] = 0) then
      begin
        if AlphaTransparent then
        ImageDest[j].rgbReserved := 0;
      end else
      if (ImageAlpha[j2] = MAXBYTE) then
      begin
        ImageDest[j].rgbBlue := ImageSource[j2 * 3];
        ImageDest[j].rgbGreen := ImageSource[j2 * 3 + 1];
        ImageDest[j].rgbRed := ImageSource[j2 * 3 + 2];
        if AlphaTransparent then
        ImageDest[j].rgbReserved := MAXBYTE;
      end else
      begin
        ImageDest[j].rgbBlue := (MAXBYTE + ImageSource[j2 * 3] * ImageAlpha[j2] +
          ImageDest[j].rgbBlue * (not ImageAlpha[j2])) shr 8;
        ImageDest[j].rgbGreen := (MAXBYTE + ImageSource[j2 * 3 + 1] * ImageAlpha[j2] +
          ImageDest[j].rgbGreen * (not ImageAlpha[j2])) shr 8;
        ImageDest[j].rgbRed := (MAXBYTE + ImageSource[j2 * 3 + 2] * ImageAlpha[j2] +
          ImageDest[j].rgbRed * (not ImageAlpha[j2])) shr 8;
        if AlphaTransparent then
        ImageDest[j].rgbReserved := ImageAlpha[j2];
      end;
    end;
    
    dec(Integer(ImageDest), BytesPerRowDest);
  end;
end;
BOBAH13 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проигрыватель своими руками Prisian Мультимедиа в Delphi 2 01.09.2008 16:09
точки плоскости, заданные своими координатами, попадают в круг с радиусом R Jondeer Общие вопросы C/C++ 6 16.06.2008 00:06
Создать класс – треугольник, заданный своими координатами (точками). jenja Общие вопросы Delphi 5 18.04.2008 07:50
TEdit - собственными руками BOBAH13 Компоненты Delphi 2 25.12.2007 17:53
панель задач своими руками RammFan Win Api 8 03.06.2007 16:38