c# तिरछी बिटमैप, आरजीबी 565 सी#के लिए लंबी गणना




.net image-processing (2)

मेरे परिणामस्वरूप छवियों में से कुछ स्लंट हैं, कुछ नहीं हैं

अपेक्षित परिणाम: (52 9 x 22)

वास्तविक परिणाम: (52 9 x 22)

विभिन्न छवि आकारों को ध्यान न दें, ये स्क्रीनशॉट हैं वे दोनों 52 9 x 22 हैं

कोड का उपयोग कर रहा हूं, मुझे इस पर एक सवाल पर उत्तर मिला है।

// some other method
byte[] pixels = new byte[size - 16];
Array.Copy(this.data, offset, pixels, 0, pixels.Length);
this.ByteToImage(w, h, pixels);

// builds the pixels to a image
private Bitmap ByteToImage(int w, int h, byte[] pixels)
{
    var bmp = new Bitmap(w, h, PixelFormat.Format16bppRgb565);

    var BoundsRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    BitmapData bmpData = bmp.LockBits(BoundsRect,
                                    ImageLockMode.WriteOnly,
                                    bmp.PixelFormat);

    // bytes => not using this because it gives error
    // eg. pixel.Length = 16032, bytes = 16064
    int bytes = bmpData.Stride * bmp.Height;

    Marshal.Copy(pixels, 0, bmpData.Scan0, pixels.Length);
    bmp.UnlockBits(bmpData);

    return bmp;
}

मैं उलझन में हूँ क्योंकि कुछ काम ठीक है, नहीं slanted लेकिन दूसरों को झुका हुआ है। मुझसे क्या छूट गया?

अद्यतन करें

जैसा कि टिप्पणियों और उत्तरों में बताया गया है, समस्या यह है कि मैं कितनी लंबी गणना कर रहा हूं मैं अभी भी यह कैसे करना है पर उलझन में हूँ, लेकिन मैंने यह कोशिश की:

public static void RemovePadding(this Bitmap bitmap)
{
    int bytesPerPixel = Image.GetPixelFormatSize(bitmap.PixelFormat) / 8;

    BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
    var pixels = new byte[bitmapData.Width * bitmapData.Height * bytesPerPixel];

    for (int row = 0; row < bitmapData.Height; row++)
    {
        var dataBeginPointer = IntPtr.Add(bitmapData.Scan0, row * bitmapData.Stride);
        Marshal.Copy(dataBeginPointer, pixels, row * bitmapData.Width * bytesPerPixel, bitmapData.Width * bytesPerPixel);
    }

    Marshal.Copy(pixels, 0, bitmapData.Scan0, pixels.Length);
    bitmap.UnlockBits(bitmapData);
}

लेकिन परिणाम (अधिक तिरछा) है:


यह यहां काम करने लगता है:

private Bitmap ByteToImage(int w, int h, byte[] pixels)
{
    var bmp = new Bitmap(w, h, PixelFormat.Format16bppRgb565);
    byte bpp = 2;
    var BoundsRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    BitmapData bmpData = bmp.LockBits(BoundsRect,
                                    ImageLockMode.WriteOnly,
                                    bmp.PixelFormat);
    // copy line by line:
    for (int y = 0; y < h; y++ )
        Marshal.Copy(pixels, y * w * bpp, bmpData.Scan0 + bmpData.Stride * y, w * bpp);
    bmp.UnlockBits(bmpData);

    return bmp;
}

मैं सही जगह पर डेटा की प्रत्येक पंक्ति को स्थानांतरित करने के लिए एक पाश का उपयोग करता हूं डेटा में पैडिंग शामिल नहीं है, लेकिन लक्ष्य पते को ऐसा करना चाहिए।

इसलिए हमें वास्तविक width * bytePerPixel द्वारा डेटा पहुंच को गुणा करना होगा, लेकिन Stride द्वारा लक्षित पता , अर्थात स्कैनलाइन की लंबाई, चार बाइट्स के अगले एकाधिक के लिए पैड। width=300 यह width=300 है, width=301 यह stride=304

सभी पिक्सेल डेटा एक चरण में ले जाने पर केवल तभी काम किया जा सकता है जब कोई पैडिंग नहीं हो, यानी जब चौड़ाई 4 का एक बहुमूल्य है


यह अपेक्षा करता है कि चौड़ाई के अनुरूप पैडिंग के बिना, अनुरूप होना चाहिए। पैडिंग हो सकते हैं पैडिंग अगली पंक्ति में से कुछ "खाएगा", जो कि बायीं ओर बदलाव करने के लिए दिखाई देगी।

चूंकि पैडिंग लाइनों को तोड़ता है, इसके साथ निपटने का एकमात्र वास्तविक तरीका (हर जगह एक ही पैडिंग का इस्तेमाल करने के अलावा) लाइन द्वारा प्रतिलिपि लाइन है आप bmpData.Scan0 + y * bmpData.Stride साथ एक लाइन के शुरुआती पता की गणना कर सकते हैं। कॉपी शुरू करने के लिए, हर y लिए

// बाइट्स => इसका उपयोग नहीं क्योंकि यह त्रुटि देता है

हां, क्योंकि आपके सरणी में पैडिंग नहीं है तो आप इसे आयोजित सरणी की तुलना में अधिक डेटा कॉपी करने के लिए कह रहे थे।





stride