把一个图像旋转任意角度,或90,180度
由于图像较大,pix和scanline不能满足要求

解决方案 »

  1.   

    使用一些现成的控件
    例如ImageN
      

  2.   

    自已对DIB进行处理,
    旋转时候尽量减少乘法,
    用汇编进行优化。
      

  3.   

    DELPHIX这个控件很棒,小日本编的,封装了大部分DIRECTX的东西
      

  4.   

    ScanLine的访问速度照说已经是最快的了。如果实在不行的话就建一个数组来缓存每一行ScanLine的地址值,然后才进行操作。而且如果只是图像的旋转而不涉及到显示,DirectX恐怕也没有什么作用。
      

  5.   

    正解1:用API,不用对象;
    正解2:格式化到数组(最小颗粒度),再用纯数学方式实现....偶做过dither算法,用过Canvas对象,各位可以自行想象多狗死...
      

  6.   

    不要用Canvas,这样利用GDI处理效率非常低,直接利用指针处理~~~尽量少用浮点运算前两天写的,当然还有提升的空间~~~过几天会将我写的一些基本图形处理的代码都贴出来~~~把前一个是旋转90,180,270和翻转的代码,后一个是旋转任意角度procedure ImageRF(const Bitmap:TBitmap;Angle:Integer;HVtype:Integer);
    var
      i,j:Integer;
      rowIn,rowOut:pRGBTriple;
      Bmp:TBitmap;
      Width,Height:Integer;
    begin
      Bmp:=TBitmap.Create;
      if (Angle=90) or (Angle=270) then
      begin
        Bmp.Width := Bitmap.Height;
        Bmp.Height := Bitmap.Width;
      end
      else
      begin
        Bmp.Width := Bitmap.Width;
        Bmp.Height := Bitmap.Height;
      end;
      Width:=Bitmap.Width-1;
      Height:=Bitmap.Height-1;
      if Bitmap.PixelFormat<>pf32Bit then Bitmap.PixelFormat:=pf24Bit;
      Bmp.PixelFormat:=Bitmap.PixelFormat;
      for  j := 0 to Height do
      begin
        rowIn  := Bitmap.ScanLine[j];
        for i := 0 to Width do
        begin
          if Angle=90 then
          begin
            rowOut := Bmp.ScanLine[i];
            Inc(rowOut,Height - j);
          end
          else if Angle=270 then
          begin
            rowOut := Bmp.ScanLine[Width - i];
            Inc(rowOut,j);
          end
          else if HVType=0 then
          begin
            rowOut := Bmp.ScanLine[j];
            Inc(rowOut,Width - i);
          end
          else if HVType=1 then
          begin
            rowOut := Bmp.ScanLine[Height - j];
            Inc(rowOut,i);
          end
          else
          begin
            rowOut := Bmp.ScanLine[Height - j];
            Inc(rowOut,Width - i);
          end;
          rowOut^ := rowIn^;
          Inc(rowIn);
        end;
      end;
      Bitmap.Assign(Bmp);
    end;function RotateBitmap(Bitmap:TBitmap;Angle:Integer;BackColor:TColor):TBitmap;
    var
      i,j,iOriginal,jOriginal,CosPoint,SinPoint : integer;
      RowOriginal,RowRotated : pRGBTriple;
      SinTheta,CosTheta : Extended;
      AngleAdd : integer;
    begin
      Bitmap.PixelFormat := pf24Bit;
      Result:=TBitmap.Create;
      Result.PixelFormat := pf24bit;
      Result.Canvas.Brush.Color:=BackColor;
      Angle:=Angle Mod 360;
      if Angle<0 then Angle:=360-Abs(Angle);
      if Angle=0 then
        Result.Assign(Bitmap)
      else if Angle=90 then
      begin
        Result.Assign(Bitmap);
        ImageRF(Result,90,-1);
      end
      else if (Angle>90) and (Angle<180) then
      begin
        AngleAdd:=90;
        Angle:=Angle-AngleAdd;
      end
      else if Angle=180 then
      begin
        Result.Assign(Bitmap);
        ImageRF(Result,180,-1);
      end
      else if (Angle>180) and (Angle<270) then
      begin
        AngleAdd:=180;
        Angle:=Angle-AngleAdd;
      end
      else if Angle=270 then
      begin
        Result.Assign(Bitmap);
        ImageRF(Result,270,-1);
      end
      else if (Angle>270) and (Angle<360) then
      begin
        AngleAdd:=270;
        Angle:=Angle-AngleAdd;
      end
      else
        AngleAdd:=0;
      if (Angle>0) and (Angle<90) then
      begin
      SinCos((Angle + AngleAdd) * Pi / 180, SinTheta, CosTheta);
      if (SinTheta * CosTheta) < 0 then
      begin
        Result.Width := Round(Abs(Bitmap.Width * CosTheta - Bitmap.Height * SinTheta));
        Result.Height := Round(Abs(Bitmap.Width * SinTheta - Bitmap.Height * CosTheta));
      end
      else
      begin
        Result.Width := Round(Abs(Bitmap.Width * CosTheta + Bitmap.Height * SinTheta));
        Result.Height := Round(Abs(Bitmap.Width * SinTheta + Bitmap.Height * CosTheta));
      end;
      CosTheta:=Abs(CosTheta);
      SinTheta:=Abs(SinTheta);
      if (AngleAdd=0) or (AngleAdd=180) then
      begin
        CosPoint:=Round(Bitmap.Height*CosTheta);
        SinPoint:=Round(Bitmap.Height*SinTheta);
      end
      else
      begin
        SinPoint:=Round(Bitmap.Width*CosTheta);
        CosPoint:=Round(Bitmap.Width*SinTheta);
      end;
      for j := 0 to Result.Height-1 do
      begin
        RowRotated := Result.Scanline[j];
        for i := 0 to Result.Width-1 do
        begin
          Case AngleAdd of
            0:
            begin
              jOriginal := Round((j+1-(i+1-SinPoint)*SinTheta/CosTheta)*CosTheta)-1;
              iOriginal := Round((i+1-(CosPoint-j-1)*SinTheta/CosTheta)*CosTheta)-1;
            end;
            90:
            begin
              iOriginal := Round((j+1-(i+1-SinPoint)/SinTheta*CosTheta)*SinTheta)-1;
              jOriginal := Bitmap.Height-Round((i+1-(CosPoint-j-1)/SinTheta*CosTheta)*SinTheta);
            end;
            180:
            begin
              jOriginal := Bitmap.Height-Round((j+1-(i+1-SinPoint)*SinTheta/CosTheta)*CosTheta);
              iOriginal := Bitmap.Width-Round((i+1-(CosPoint-j-1)*SinTheta/CosTheta)*CosTheta);
            end;
            270:
            begin
              iOriginal := Bitmap.Width-Round((j+1-(i+1-SinPoint)/SinTheta*CosTheta)*SinTheta);
              jOriginal := Round((i+1-(CosPoint-j-1)/SinTheta*CosTheta)*SinTheta)-1;
            end;
          end;
          if (iOriginal >= 0) and (iOriginal <= Bitmap.Width-1)and
             (jOriginal >= 0) and (jOriginal <= Bitmap.Height-1)
          then
          begin
            RowOriginal := Bitmap.Scanline[jOriginal];
            Inc(RowOriginal,iOriginal);
            RowRotated^ := RowOriginal^;
            Inc(RowRotated);
          end
          else
          begin
            Inc(RowRotated);
          end;
        end;
      end;
      end;
    end;