Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何计算位图的闭合裁剪矩形?_Delphi_Image Processing - Fatal编程技术网

Delphi 如何计算位图的闭合裁剪矩形?

Delphi 如何计算位图的闭合裁剪矩形?,delphi,image-processing,Delphi,Image Processing,我需要根据给定的背景色键计算位图的闭合裁剪矩形。在下面的图片中,你可以看到什么是接近的作物。左侧是源,右侧是闭合裁剪的输出: 如您所见,我需要找到与背景颜色不同的最上面、最左边、最下面和最右边的像素,以构建闭合裁剪矩形。那么,如何找到这些不同的外部像素来获得接近的裁剪矩形呢?或者,换句话说,如何计算位图的闭合裁剪矩形?您可以使用此代码(您也可以按照本文的说明进行操作): procedure CalcCloseCrop(ABitmap:TBitmap;const ABackColor:TCol

我需要根据给定的背景色键计算位图的闭合裁剪矩形。在下面的图片中,你可以看到什么是接近的作物。左侧是源,右侧是闭合裁剪的输出:

如您所见,我需要找到与背景颜色不同的最上面、最左边、最下面和最右边的像素,以构建闭合裁剪矩形。那么,如何找到这些不同的外部像素来获得接近的裁剪矩形呢?或者,换句话说,如何计算位图的闭合裁剪矩形?

您可以使用此代码(您也可以按照本文的说明进行操作):

procedure CalcCloseCrop(ABitmap:TBitmap;const ABackColor:TColor;
外冠:TRect);
变量
X:整数;
Y:整数;
颜色:TColor;
像素:PRGB3P;
RowClean:布尔值;
LastClean:布尔;
开始
如果是ABitmap.PixelFormat PF24位,则
引发异常。创建('位深度不正确,位图必须为24位!');
LastClean:=假;
ACropRect:=Rect(ABitmap.Width,ABitmap.Height,0,0);
对于Y:=0到ABitmap.Height-1 do
开始
RowClean:=真;
像素:=ABitmap.ScanLine[Y];
对于X:=0到ABitmap.Width-1 do
开始
颜色:=RGB(Pixel.rgbtRed、Pixel.rgbtGreen、Pixel.rgbtBlue);
如果颜色是ABackColor那么
开始
RowClean:=False;
如果XACropRect.那么
右顶点:=X+1;
结束;
像素公司;
结束;
如果不干净的话
开始
如果不干净的话
开始
LastClean:=真;
顶点:=Y;
结束;
如果Y+1>ACropRect.Bottom,则
顶点底部:=Y+1;
结束;
结束;
如果我是空的,那么
开始
如果ACropRect.Left=ABitmap.Width,则
左顶点:=0;
如果ACropRect.Top=ABitmap.Height,则
顶点:=0;
如果ACropRect.Right=0,则
ACropRect.Right:=绝对贴图宽度;
如果ACropRect.Bottom=0,则
ACropRect.Bottom:=ABitmap.Height;
结束;
结束;
程序TForm1.按钮1单击(发送方:TObject);
变量
R:TRect;
位图:TBitmap;
开始
CalcCloseCrop(Image1.Picture.Bitmap,$00FFA749,R);
位图:=TBitmap.Create;
尝试
位图.设置大小(R.宽度,R.高度);
Bitmap.Canvas.CopyRect(Rect(0,0,R.宽度,R.高度),Image1.Canvas,R);
Image1.Picture.Bitmap.Assign(位图);
最后
位图。免费;
结束;
结束;

我尝试了大卫最近帮我解答的一些问题的混合代码:我想我能理解,但不是真的。我应该能够调整ResizeBitmapCanvas过程来实现这一点,但我不能,我很容易被搞糊涂。@Blobby一种方法是从位图的每一侧开始,减小循环变量,直到找到一个与背景颜色不同的像素,对每一侧重复这个过程,瞧,你给自己弄了个自动裁剪机tool@Dorin,您可以在一个
扫描线
通过槽中完成,您只需记住限制;-)@TLama我不确定,例如立方体可能有右“边”倾斜(不是直的),因此,你最终会得到非常糟糕的裁剪,可能是我缺少了一些东西(:@Dorin,不,在这种情况下,你只需要记住右上一个脏像素的位置。你会从上到下扫描,当你找到一个离左更远的脏像素时,你会存储该像素的位置等。非常棒的东西TLama,不会从这一个拿走积分;)我只希望我不仅能理解你的答案,还能理解其他许多问题。编辑:位图上的像素是否被一个不可见的框(边界框)包围正如我最初所想的那样?如果是通过使用Rect发现的?我将尝试对此进行评论,但在回顾之后。关于不可见框,您是指裁剪图像周围的一些空白,对吗?我将添加一些,但是如果第一个(非背景)像素位于位置[0;0]上会怎么样,你想把它扩展到图像大小后面,并用ABackColor填充这个外部空间吗?@TLama看到这个问题了,我编辑了它,试图展示我所说的不可见边界框的确切含义(甚至有这样的东西吗??)。我想如果第一个像素是[0,0]这样就不会发生裁剪。我明白了,所以裁剪结果周围只有一个额外的空白。关于左上角的第一个像素情况,你是对的,不会有任何裁剪,但是即使在这种情况下,你想用该空间扩展图像吗?不过,最简单的方法是获得紧密裁剪矩形(使用CalcCloseCrop),创建一个临时位图,大小为ACropRect+边界空间,用ABackColor填充,并将ACropRect区域从源图像复制到该临时位图的中心。然后从该临时位图生成结果:-)尝试查看。
ScanLine
函数的结果是指向表示线的第一个像素的第一个颜色结构的指针。此结构由用于表示单个像素的字节值计数组成。如果您有24位图像,您将使用PRGBTriple(指向TRGBTriple记录的指针,其中包含3个字节),因为24位图像像素存储为3个字节,如蓝绿色和红色。如果您有8位映像,则只使用PByte(指向单个字节的指针)。
Inc(像素)表示。。
procedure CalcCloseCrop(ABitmap: TBitmap; const ABackColor: TColor;
  out ACropRect: TRect);
var
  X: Integer;
  Y: Integer;
  Color: TColor;
  Pixel: PRGBTriple;
  RowClean: Boolean;
  LastClean: Boolean;
begin
  if ABitmap.PixelFormat <> pf24bit then
    raise Exception.Create('Incorrect bit depth, bitmap must be 24-bit!');

  LastClean := False;
  ACropRect := Rect(ABitmap.Width, ABitmap.Height, 0, 0);

  for Y := 0 to ABitmap.Height-1 do
  begin
    RowClean := True;
    Pixel := ABitmap.ScanLine[Y];
    for X := 0 to ABitmap.Width - 1 do
    begin
      Color := RGB(Pixel.rgbtRed, Pixel.rgbtGreen, Pixel.rgbtBlue);
      if Color <> ABackColor then
      begin
        RowClean := False;
        if X < ACropRect.Left then
          ACropRect.Left := X;
        if X + 1 > ACropRect.Right then
          ACropRect.Right := X + 1;
      end;
      Inc(Pixel);
    end;

    if not RowClean then
    begin
      if not LastClean then
      begin
        LastClean := True;
        ACropRect.Top := Y;
      end;
      if Y + 1 > ACropRect.Bottom then
        ACropRect.Bottom := Y + 1;
    end;
  end;

  if ACropRect.IsEmpty then
  begin
    if ACropRect.Left = ABitmap.Width then
      ACropRect.Left := 0;
    if ACropRect.Top = ABitmap.Height then
      ACropRect.Top := 0;
    if ACropRect.Right = 0 then
      ACropRect.Right := ABitmap.Width;
    if ACropRect.Bottom = 0 then
      ACropRect.Bottom := ABitmap.Height;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  R: TRect;
  Bitmap: TBitmap;
begin
  CalcCloseCrop(Image1.Picture.Bitmap, $00FFA749, R);
  Bitmap := TBitmap.Create;
  try
    Bitmap.SetSize(R.Width, R.Height);
    Bitmap.Canvas.CopyRect(Rect(0, 0, R.Width, R.Height), Image1.Canvas, R);
    Image1.Picture.Bitmap.Assign(Bitmap);
  finally
    Bitmap.Free;
  end;
end;