|
Вопрос # 20/ вопрос открыт / |
|
Здравствуйте, эксперты!
Вопрос таков:
Подскажите как можно инвертировать, вращать, устанавливать фоновый цвет изображения, загруженного в TImage?
Ответ #1. Отвечает эксперт: Степанов Игорь Николаевич
Посмотри, возможно поможет:
Приложение: Переключить в обычный режим- procedure RotateRight(BitMap: tImage);
- var
- FirstC, LastC, c, r: integer;
-
- procedure FixPixels(c, r: integer);
- var
- SavePix, SavePix2: tColor;
- i, NewC, NewR: integer;
- begin
- SavePix := Bitmap.Canvas.Pixels[c, r];
- for i := 1 to 4 do
- begin
- newc := BitMap.Height - r + 1;
- newr := c;
- SavePix2 := BitMap.Canvas.Pixels[newc, newr];
- Bitmap.Canvas.Pixels[newc, newr] := SavePix;
- SavePix := SavePix2;
- c := Newc;
- r := NewR;
- end;
- end;
-
- begin
- if BitMap.Width <> BitMap.Height then
- exit;
- BitMap.Visible := false;
- with Bitmap.Canvas do
- begin
- firstc := 0;
- lastc := BitMap.Width;
- for r := 0 to BitMap.Height div 2 do
- begin
- for c := firstc to lastc do
- begin
- FixPixels(c, r);
- end;
- inc(FirstC);
- Dec(LastC);
- end;
- end;
- BitMap.Visible := true;
- end;
Ответ #2. Отвечает эксперт: Матвеев Игорь Владимирович
На счет вращения и инверсии все понятно - см. приложение, но что Вы имели ввиду под установкой фонового цвета? Может Вам нужно просто залить какую-то область нужным цветом - это функция FloodFill:
Canvas.FloodFill(10, 10, clBlack, fsBorder);
Приложение: Переключить в обычный режим- procedure RotateBitmap(Bitmap: TBitmap; Angle: Double; BackColor: TColor);
- var
- x, y, W, H, v1, v2: Integer;
- Dest, Src: pRGB;
- VertArray: array of pByteArray;
- Bmp: TBitmap;
-
- procedure SinCos(AngleRad: Double; var ASin, ACos: Double);
- begin
- ASin := Sin(AngleRad);
- ACos := Cos(AngleRad);
- end;
-
- function RotateRect(const Rect: TRect; const Center: TPoint; Angle: Double):
- TRectList;
- var
- DX, DY: Integer;
- SinAng, CosAng: Double;
- function RotPoint(PX, PY: Integer): TPoint;
- begin
- DX := PX - Center.x;
- DY := PY - Center.y;
- Result.x := Center.x + Round(DX * CosAng - DY * SinAng);
- Result.y := Center.y + Round(DX * SinAng + DY * CosAng);
- end;
- begin
- SinCos(Angle * (Pi / 180), SinAng, CosAng);
- Result[1] := RotPoint(Rect.Left, Rect.Top);
- Result[2] := RotPoint(Rect.Right, Rect.Top);
- Result[3] := RotPoint(Rect.Right, Rect.Bottom);
- Result[4] := RotPoint(Rect.Left, Rect.Bottom);
- end;
-
- function Min(A, B: Integer): Integer;
- begin
- if A < B then
- Result := A
- else
- Result := B;
- end;
-
- function Max(A, B: Integer): Integer;
- begin
- if A > B then
- Result := A
- else
- Result := B;
- end;
-
- function GetRLLimit(const RL: TRectList): TRect;
- begin
- Result.Left := Min(Min(RL[1].x, RL[2].x), Min(RL[3].x, RL[4].x));
- Result.Top := Min(Min(RL[1].y, RL[2].y), Min(RL[3].y, RL[4].y));
- Result.Right := Max(Max(RL[1].x, RL[2].x), Max(RL[3].x, RL[4].x));
- Result.Bottom := Max(Max(RL[1].y, RL[2].y), Max(RL[3].y, RL[4].y));
- end;
-
- procedure Rotate;
- var
- x, y, xr, yr, yp: Integer;
- ACos, ASin: Double;
- Lim: TRect;
- begin
- W := Bmp.Width;
- H := Bmp.Height;
- SinCos(-Angle * Pi / 180, ASin, ACos);
- Lim := GetRLLimit(RotateRect(Rect(0, 0, Bmp.Width, Bmp.Height), Point(0, 0),
- Angle));
- Bitmap.Width := Lim.Right - Lim.Left;
- Bitmap.Height := Lim.Bottom - Lim.Top;
- Bitmap.Canvas.Brush.Color := BackColor;
- Bitmap.Canvas.FillRect(Rect(0, 0, Bitmap.Width, Bitmap.Height));
- for y := 0 to Bitmap.Height - 1 do
- begin
- Dest := Bitmap.ScanLine[y];
- yp := y + Lim.Top;
- for x := 0 to Bitmap.Width - 1 do
- begin
- xr := Round(((x + Lim.Left) * ACos) - (yp * ASin));
- yr := Round(((x + Lim.Left) * ASin) + (yp * ACos));
- if (xr > -1) and (xr < W) and (yr > -1) and (yr < H) then
- begin
- Src := Bmp.ScanLine[yr];
- Inc(Src, xr);
- Dest^ := Src^;
- end;
- Inc(Dest);
- end;
- end;
- end;
-
- begin
- Bitmap.PixelFormat := pf24Bit;
- Bmp := TBitmap.Create;
- try
- Bmp.Assign(Bitmap);
- W := Bitmap.Width - 1;
- H := Bitmap.Height - 1;
- if Frac(Angle) <> 0.0 then
- Rotate
- else
- case Trunc(Angle) of
- -360, 0, 360, 720: Exit;
- 90, 270:
- begin
- Bitmap.Width := H + 1;
- Bitmap.Height := W + 1;
- SetLength(VertArray, H + 1);
- v1 := 0;
- v2 := 0;
- if Angle = 90.0 then
- v1 := H
- else
- v2 := W;
- for y := 0 to H do
- VertArray[y] := Bmp.ScanLine[Abs(v1 - y)];
- for x := 0 to W do
- begin
- Dest := Bitmap.ScanLine[x];
- for y := 0 to H do
- begin
- v1 := Abs(v2 - x) * 3;
- with Dest^ do
- begin
- B := VertArray[y, v1];
- G := VertArray[y, v1 + 1];
- R := VertArray[y, v1 + 2];
- end;
- Inc(Dest);
- end;
- end
- end;
- 180:
- begin
- for y := 0 to H do
- begin
- Dest := Bitmap.ScanLine[y];
- Src := Bmp.ScanLine[H - y];
- Inc(Src, W);
- for x := 0 to W do
- begin
- Dest^ := Src^;
- Dec(Src);
- Inc(Dest);
- end;
- end;
- end;
- else
- Rotate;
- end;
- finally
- Bmp.Free;
- end;
- end;
-
- procedure InvertBitmap(Bitmap: TBitmap);
- var
- x, y : Integer;
- Dest : pRGB;
- begin
- Bitmap.PixelFormat := pf24Bit;
- for y := 0 to Bitmap.Height - 1 do
- begin
- Dest := Bitmap.ScanLine[y];
- for x := 0 to Bitmap.Width - 1 do
- begin
- with Dest^ do
- begin
- R := not R;
- G := not G;
- B := not B;
- end;
- Inc(Dest);
- end;
- end;
- end;
Ответ #3. Отвечает эксперт: bruder
Здравствуйте, Ситников Константин Евгеньевич!
Инвертировать - код в приложении. Удачи!
Приложение: Переключить в обычный режим- function InvertBitmap(MyBitmap: TBitmap): TBitmap;
- var
- x, y: Integer;
- ByteArray: PByteArray;
- begin
- MyBitmap.PixelFormat := pf24Bit;
- for y := 0 to MyBitmap.Height - 1 do
- begin
- ByteArray := MyBitmap.ScanLine[y];
- for x := 0 to MyBitmap.Width * 3 - 1 do
- begin
- ByteArray[x] := 255 - ByteArray[x];
- end;
- end;
- Result := MyBitmap;
- end; Example:
-
- procedure TForm1.Button1Click(Sender: TObject);
- begin
- Image1.Picture.Bitmap := InvertBitmap(Image1.Picture.Bitmap);
- Image1.Refresh;
- end;
-
-
-
- procedure RotateBitmap(Bitmap: TBitmap; Angle: Double; BackColor: TColor);
- type
- TRGB = record
- B, G, R: Byte;
- end;
- pRGB = ^TRGB;
- pByteArray = ^TByteArray;
- TByteArray = array[0..32767] of Byte;
- TRectList = array[1..4] of TPoint;
-
- var
- x, y, W, H, v1, v2: Integer;
- Dest, Src: pRGB;
- VertArray: array of pByteArray;
- Bmp: TBitmap;
-
- procedure SinCos(AngleRad: Double; var ASin, ACos: Double);
- begin
- ASin := Sin(AngleRad);
- ACos := Cos(AngleRad);
- end;
-
- function RotateRect(const Rect: TRect; const Center: TPoint; Angle: Double):
- TRectList;
- var
- DX, DY: Integer;
- SinAng, CosAng: Double;
- function RotPoint(PX, PY: Integer): TPoint;
- begin
- DX := PX - Center.x;
- DY := PY - Center.y;
- Result.x := Center.x + Round(DX * CosAng - DY * SinAng);
- Result.y := Center.y + Round(DX * SinAng + DY * CosAng);
- end;
- begin
- SinCos(Angle * (Pi / 180), SinAng, CosAng);
- Result[1] := RotPoint(Rect.Left, Rect.Top);
- Result[2] := RotPoint(Rect.Right, Rect.Top);
- Result[3] := RotPoint(Rect.Right, Rect.Bottom);
- Result[4] := RotPoint(Rect.Left, Rect.Bottom);
- end;
-
- function Min(A, B: Integer): Integer;
- begin
- if A < B then
- Result := A
- else
- Result := B;
- end;
-
- function Max(A, B: Integer): Integer;
- begin
- if A > B then
- Result := A
- else
- Result := B;
- end;
-
- function GetRLLimit(const RL: TRectList): TRect;
- begin
- Result.Left := Min(Min(RL[1].x, RL[2].x), Min(RL[3].x, RL[4].x));
- Result.Top := Min(Min(RL[1].y, RL[2].y), Min(RL[3].y, RL[4].y));
- Result.Right := Max(Max(RL[1].x, RL[2].x), Max(RL[3].x, RL[4].x));
- Result.Bottom := Max(Max(RL[1].y, RL[2].y), Max(RL[3].y, RL[4].y));
- end;
-
- procedure Rotate;
- var
- x, y, xr, yr, yp: Integer;
- ACos, ASin: Double;
- Lim: TRect;
- begin
- W := Bmp.Width;
- H := Bmp.Height;
- SinCos(-Angle * Pi / 180, ASin, ACos);
- Lim := GetRLLimit(RotateRect(Rect(0, 0, Bmp.Width, Bmp.Height), Point(0, 0),
- Angle));
- Bitmap.Width := Lim.Right - Lim.Left;
- Bitmap.Height := Lim.Bottom - Lim.Top;
- Bitmap.Canvas.Brush.Color := BackColor;
- Bitmap.Canvas.FillRect(Rect(0, 0, Bitmap.Width, Bitmap.Height));
- for y := 0 to Bitmap.Height - 1 do
- begin
- Dest := Bitmap.ScanLine[y];
- yp := y + Lim.Top;
- for x := 0 to Bitmap.Width - 1 do
- begin
- xr := Round(((x + Lim.Left) * ACos) - (yp * ASin));
- yr := Round(((x + Lim.Left) * ASin) + (yp * ACos));
- if (xr > -1) and (xr < W) and (yr > -1) and (yr < H) then
- begin
- Src := Bmp.ScanLine[yr];
- Inc(Src, xr);
- Dest^ := Src^;
- end;
- Inc(Dest);
- end;
- end;
- end;
-
- begin
- Bitmap.PixelFormat := pf24Bit;
- Bmp := TBitmap.Create;
- try
- Bmp.Assign(Bitmap);
- W := Bitmap.Width - 1;
- H := Bitmap.Height - 1;
- if Frac(Angle) <> 0.0 then
- Rotate
- else
- case Trunc(Angle) of
- -360, 0, 360, 720: Exit;
- 90, 270:
- begin
- Bitmap.Width := H + 1;
- Bitmap.Height := W + 1;
- SetLength(VertArray, H + 1);
- v1 := 0;
- v2 := 0;
- if Angle = 90.0 then
- v1 := H
- else
- v2 := W;
- for y := 0 to H do
- VertArray[y] := Bmp.ScanLine[Abs(v1 - y)];
- for x := 0 to W do
- begin
- Dest := Bitmap.ScanLine[x];
- for y := 0 to H do
- begin
- v1 := Abs(v2 - x) * 3;
- with Dest^ do
- begin
- B := VertArray[y, v1];
- G := VertArray[y, v1 + 1];
- R := VertArray[y, v1 + 2];
- end;
- Inc(Dest);
- end;
- end
- end;
- 180:
- begin
- for y := 0 to H do
- begin
- Dest := Bitmap.ScanLine[y];
- Src := Bmp.ScanLine[H - y];
- Inc(Src, W);
- for x := 0 to W do
- begin
- Dest^ := Src^;
- Dec(Src);
- Inc(Dest);
- end;
- end;
- end;
- else
- Rotate;
- end;
- finally
- Bmp.Free;
- end;
- end;
-
- Example:
-
- procedure TForm1.Button1Click(Sender: TObject);
- begin
- RotateBitmap(Image1.Picture.Bitmap, 17.23, clWhite);
- end;
 |
Ответ отправил: bruder (статус: 4-ый класс)
Время отправки: 8 мая 2006, 15:40
|
Ответ #4. Отвечает эксперт: Zeon
Для вращения: (см. приложение)
А для заливки одним цветом лучше использовать:
procedureTForm1.Button1Click(Sender: TObject);
begin
PatBlt(Form1.Canvas.Handle,
0,
0,
Form1.ClientWidth,
Form1.ClientHeight,
WHITENESS);
end;
побыстрее работает.
Приложение: Переключить в обычный режим- Const PixelMax = 32768;
- Type
- pPixelArray = ^TPixelArray;
- TPixelArray = Array[0..PixelMax-1] Of TRGBTriple;
-
- Procedure RotateBitmap_ads(
- SourceBitmap : TBitmap;
- out DestBitmap : TBitmap;
- Center : TPoint;
- Angle : Double);
- Var
- cosRadians : Double;
- inX : Integer;
- inXOriginal : Integer;
- inXPrime : Integer;
- inXPrimeRotated : Integer;
- inY : Integer;
- inYOriginal : Integer;
- inYPrime : Integer;
- inYPrimeRotated : Integer;
- OriginalRow : pPixelArray;
- Radians : Double;
- RotatedRow : pPixelArray;
- sinRadians : Double;
- begin
- DestBitmap.Width := SourceBitmap.Width;
- DestBitmap.Height := SourceBitmap.Height;
- DestBitmap.PixelFormat := pf24bit;
- Radians := -(Angle) * PI / 180;
- sinRadians := Sin(Radians);
- cosRadians := Cos(Radians);
- For inX := DestBitmap.Height-1 Downto 0 Do
- Begin
- RotatedRow := DestBitmap.Scanline[inX];
- inXPrime := 2*(inX - Center.y) + 1;
- For inY := DestBitmap.Width-1 Downto 0 Do
- Begin
- inYPrime := 2*(inY - Center.x) + 1;
- inYPrimeRotated := Round(inYPrime * CosRadians - inXPrime * sinRadians);
- inXPrimeRotated := Round(inYPrime * sinRadians + inXPrime * cosRadians);
- inYOriginal := (inYPrimeRotated - 1) Div 2 + Center.x;
- inXOriginal := (inXPrimeRotated - 1) Div 2 + Center.y;
- If
- (inYOriginal >= 0) And
- (inYOriginal <= SourceBitmap.Width-1) And
- (inXOriginal >= 0) And
- (inXOriginal <= SourceBitmap.Height-1)
- Then
- Begin
- OriginalRow := SourceBitmap.Scanline[inXOriginal];
- RotatedRow[inY] := OriginalRow[inYOriginal]
- End
- Else
- Begin
- RotatedRow[inY].rgbtBlue := 255;
- RotatedRow[inY].rgbtGreen := 0;
- RotatedRow[inY].rgbtRed := 0
- End;
- End;
- End;
- End;
-
- {Usage:}
- procedure TForm1.Button1Click(Sender: TObject);
- Var
- Center : TPoint;
- Bitmap : TBitmap;
- begin
- Bitmap := TBitmap.Create;
- Try
- Center.y := (Image.Height div 2)+20;
- Center.x := (Image.Width div 2)+0;
- RotateBitmap_ads(
- Image.Picture.Bitmap,
- Bitmap,
- Center,
- Angle);
- Angle := Angle + 15;
- Image2.Picture.Bitmap.Assign(Bitmap);
- Finally
- Bitmap.Free;
- End;
- end;
 |
Ответ отправил: Zeon (статус: 2-ой класс)
Время отправки: 9 мая 2006, 19:20
|
Ответ #5. Отвечает эксперт: Вадим К
В обычном изображении фоновый цвет никак не отличается от всех остальных. Определить его можно только "зрительно". Причём в разных людей это может быть разный цвет. К примеру, возмём изображение флага. Где там фон? (При условии, что всё изображение занимает флаг).
А теперь ответ На вопрос, как изменить фон.
Изменить фон - значит заменить пиксели с цветом, который мы признали фоном на новый цвет.
Компонент TImage, если ему выставить свойство Transparent, прозрачным считает левый нижний пиксель.
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 10 мая 2006, 12:22
|
Мини-форум вопроса
Всего сообщений: 6; последнее сообщение — 27 октября 2011, 02:17; участников в обсуждении: 4.
|
Егор (статус: 10-ый класс), 12 июня 2010, 19:03 [#1]:
Цитата (Ситников Константин Евгеньевич):
как можно инвертировать, вращать, устанавливать фоновый цвет изображения, загруженного в TImage?
мамочки мои...
ВРАЩАТЬ фоновый цвет?!
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
padonak (статус: Посетитель), 22 июня 2010, 15:03 [#2]:
помойму это просто нереально... такое реализовать невозможно...
|
|
Надежда1286 (статус: Посетитель), 26 октября 2011, 02:52 [#4]:
Помогите решить задачи:
Дан файл f, компоненты которого являются целыми числами. Количество компонентов файла кратно 10. Записать в файл g наибольшее значение первых 10 компонент, затем следующих 10 компонент и так далее. Полученный файл отсортировать в порядке возрастания.
Дан линейный массив A[1..N], содержащий целые числа. Отсортировать его элементы указанным способом: в порядке убывания – элементы, стоящие на местах с индексами, дающими при делении на 3 остаток 2, в порядке возрастания – элементы, стоящие на местах с индексами, дающими при делении на 3 остаток 1.Остальные элементы оставить без изменения места расположения.
|
|
Мережников Андрей (статус: Абитуриент), 26 октября 2011, 18:12 [#5]:
Цитата (Надежда1286):
Помогите решить задачи:
На создание отдельного вопроса тоже УМАения не хватает?
|
|
Надежда1286 (статус: Посетитель), 27 октября 2011, 02:17 [#6]:
А по-культурнее никак...
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|