2011-07-21 1 views
3

今、9スライスのコードが期待どおりに機能しない理由を理解しようとしました。私が見る限り、9つのスライス画像を正しく処理しないGraphics.DrawImageメソッドの問題があるようです。だから私の問題は、コンパクトなフレームワークで自分のコードを実行するときに実行される不正なスケーリングをどのように補正するかです。私は、このコードは完全なフレームワーク環境で動作しているときに完全に動作することを追加するかもしれません。この問題は、画像を大きな画像に拡大縮小するときにのみ発生します。ここにスニペットがあります:DrawImageでスライスされた画像の位置を正しく設定できない

public class NineSliceBitmapSnippet 
{ 
    private Bitmap m_OriginalBitmap; 

    public int CornerLength { get; set; } 

    /// <summary> 
    /// Initializes a new instance of the NineSliceBitmapSnippet class. 
    /// </summary> 
    public NineSliceBitmapSnippet(Bitmap bitmap) 
    { 
     CornerLength = 5; 
     m_OriginalBitmap = bitmap; 
    } 

    public Bitmap ScaleSingleBitmap(Size size) 
    { 
     Bitmap scaledBitmap = new Bitmap(size.Width, size.Height); 
     int[] horizontalTargetSlices = Slice(size.Width); 
     int[] verticalTargetSlices = Slice(size.Height); 

     int[] horizontalSourceSlices = Slice(m_OriginalBitmap.Width); 
     int[] verticalSourceSlices = Slice(m_OriginalBitmap.Height); 

     using (Graphics graphics = Graphics.FromImage(scaledBitmap)) 
     { 
      using (Brush brush = new SolidBrush(Color.Fuchsia)) 
      { 
       graphics.FillRectangle(brush, new Rectangle(0, 0, size.Width, size.Height)); 
      } 

      int horizontalTargetOffset = 0; 
      int verticalTargetOffset = 0; 

      int horizontalSourceOffset = 0; 
      int verticalSourceOffset = 0; 

      for (int x = 0; x < horizontalTargetSlices.Length; x++) 
      { 
       verticalTargetOffset = 0; 
       verticalSourceOffset = 0; 
       for (int y = 0; y < verticalTargetSlices.Length; y++) 
       { 
        Rectangle destination = new Rectangle(horizontalTargetOffset, verticalTargetOffset, horizontalTargetSlices[x], verticalTargetSlices[y]); 
        Rectangle source = new Rectangle(horizontalSourceOffset, verticalSourceOffset, horizontalSourceSlices[x], verticalSourceSlices[y]); 

        graphics.DrawImage(m_OriginalBitmap, destination, source, GraphicsUnit.Pixel); 

        verticalTargetOffset += verticalTargetSlices[y]; 
        verticalSourceOffset += verticalSourceSlices[y]; 
       } 

       horizontalTargetOffset += horizontalTargetSlices[x]; 
       horizontalSourceOffset += horizontalSourceSlices[x]; 
      } 
     } 
     return scaledBitmap; 
    } 

    public int[] Slice(int length) 
    { 
     int cornerLength = CornerLength; 

     if (length <= (cornerLength * 2)) 
      throw new Exception("Image to small for sliceing up"); 

     int[] slices = new int[3]; 
     slices[0] = cornerLength; 
     slices[1] = length - (2 * cornerLength); 
     slices[2] = cornerLength; 

     return slices; 
    } 
} 

私の質問は、間違ったスケーリングをどのように補償できるかです。 /ダン

+0

エラーは何ですか?または、動作していないイメージをリンクすることはできますか? – LarsTech

+0

問題は、画像をもう一度つなぎ合わせて、大きな画像にスケーリングした場合、一方向にのみ伸びる部分は、1ピクセル伸びで、もう一方の方向に引き伸ばされるということです。私は私の評判のより高い評価を得るとき、間違ったDrawImage動作のイメージを投稿しようとします。 –

+0

スマートデバイス(WCE)上で実行されているDrawImageのコンパクトなフレームワーク版は、一方向に伸びた画像に問題があり、このような誤った動作をしているようです。画像を両方向に伸ばすと正しい画像になります。問題を集約する:DrawImageを使用してイメージを水平方向にストレッチすると、予期しないことにイメージが縦方向にもわずかに伸びます。 –

答えて

1

は、いくつかのより多くの試行錯誤の後、私はようやく私の問題への解決策を見つけました。スケーリングの問題は、9つのスライススケーリングのロジックに従って、常に一方向にのみ伸びるため、常に上部中央、右中央、下部中央および左中央スライスになりました。正しいストレッチを適用する前に、それらのスライスに一時的に正方形のストレッチを適用すると、最終的なビットマップが正しいでしょう。この問題は、Windows CEデバイス(スマートデバイス)の.Net Compact Frameworkのみに表示されます。ここでは、CFのバグを調整するコードのスニペットを示します。私の唯一の関心事は、正方形に引き伸ばされたスライスが訂正コードのためにはるかに多くのメモリを必要とすることです。一方、このステップは短期間であるため、私はそれを取り除くかもしれません。 ;)

public class NineSliceBitmapSnippet 
{ 
    private Bitmap m_OriginalBitmap; 

    public int CornerLength { get; set; } 

    public NineSliceBitmapSnippet(Bitmap bitmap) 
    { 
     CornerLength = 5; 
     m_OriginalBitmap = bitmap; 
    } 

    public Bitmap Scale(Size size) 
    { 
     if (m_OriginalBitmap != null) 
     { 
      return ScaleSingleBitmap(size); 
     } 

     return null; 
    } 

    public Bitmap ScaleSingleBitmap(Size size) 
    { 
     Bitmap scaledBitmap = new Bitmap(size.Width, size.Height); 
     int[] horizontalTargetSlices = Slice(size.Width); 
     int[] verticalTargetSlices = Slice(size.Height); 

     int[] horizontalSourceSlices = Slice(m_OriginalBitmap.Width); 
     int[] verticalSourceSlices = Slice(m_OriginalBitmap.Height); 

     using (Graphics graphics = Graphics.FromImage(scaledBitmap)) 
     { 
      using (Brush brush = new SolidBrush(Color.Fuchsia)) 
      { 
       graphics.FillRectangle(brush, new Rectangle(0, 0, size.Width, size.Height)); 
      } 

      int horizontalTargetOffset = 0; 
      int verticalTargetOffset = 0; 

      int horizontalSourceOffset = 0; 
      int verticalSourceOffset = 0; 

      for (int x = 0; x < horizontalTargetSlices.Length; x++) 
      { 
       verticalTargetOffset = 0; 
       verticalSourceOffset = 0; 
       for (int y = 0; y < verticalTargetSlices.Length; y++) 
       { 
        Rectangle destination = new Rectangle(horizontalTargetOffset, verticalTargetOffset, horizontalTargetSlices[x], verticalTargetSlices[y]); 
        Rectangle source = new Rectangle(horizontalSourceOffset, verticalSourceOffset, horizontalSourceSlices[x], verticalSourceSlices[y]); 

        bool isWidthAffectedByVerticalStretch = (y == 1 && (x == 0 || x == 2) && destination.Height > source.Height); 
        bool isHeightAffectedByHorizontalStretch = (x == 1 && (y == 0 || y == 2) && destination.Width > source.Width); 
        if (isHeightAffectedByHorizontalStretch) 
        { 
         BypassDrawImageError(graphics, destination, source, Orientation.Horizontal); 
        } 
        else if (isWidthAffectedByVerticalStretch) 
        { 
         BypassDrawImageError(graphics, destination, source, Orientation.Vertical); 
        } 
        else 
        { 
         graphics.DrawImage(m_OriginalBitmap, destination, source, GraphicsUnit.Pixel); 
        } 

        verticalTargetOffset += verticalTargetSlices[y]; 
        verticalSourceOffset += verticalSourceSlices[y]; 
       } 

       horizontalTargetOffset += horizontalTargetSlices[x]; 
       horizontalSourceOffset += horizontalSourceSlices[x]; 
      } 
     } 
     return scaledBitmap; 
    } 

    private void BypassDrawImageError(Graphics graphics, Rectangle destination, Rectangle source, Orientation orientationAdjustment) 
    { 
     Size adjustedSize = Size.Empty; 
     switch (orientationAdjustment) 
     { 
      case Orientation.Horizontal: 
       adjustedSize = new Size(destination.Width, destination.Width); 
       break; 
      case Orientation.Vertical: 
       adjustedSize = new Size(destination.Height, destination.Height); 
       break; 
      default: 
       break; 
     } 

     using (Bitmap quadScaledBitmap = new Bitmap(adjustedSize.Width, adjustedSize.Height)) 
     { 
      using (Graphics tempGraphics = Graphics.FromImage(quadScaledBitmap)) 
      { 
       tempGraphics.Clear(Color.Fuchsia); 
       tempGraphics.DrawImage(m_OriginalBitmap, new Rectangle(0, 0, adjustedSize.Width, adjustedSize.Height), source, GraphicsUnit.Pixel); 
      } 
      graphics.DrawImage(quadScaledBitmap, destination, new Rectangle(0, 0, quadScaledBitmap.Width, quadScaledBitmap.Height), GraphicsUnit.Pixel); 
     } 
    } 

    public int[] Slice(int length) 
    { 
     int cornerLength = CornerLength; 

     if (length <= (cornerLength * 2)) 
      throw new Exception("Image to small for sliceing up"); 

     int[] slices = new int[3]; 
     slices[0] = cornerLength; 
     slices[1] = length - (2 * cornerLength); 
     slices[2] = cornerLength; 

     return slices; 
    } 
} 
関連する問題