2016-02-14 19 views
5

Ben JPEG dosyası yüklemek ve görüntüden.NET Bitmap.Load yöntemi farklı bilgisayarlarda farklı bir sonuç üretmek

C# Kod tüm siyah ve beyaz pikselleri silmeyi deneyin: Ben bulmaya Bundan sonra

... 
    m_SrcImage = new Bitmap(imagePath); 

    Rectangle r = new Rectangle(0, 0, m_SrcImage.Width, m_SrcImage.Height); 
    BitmapData bd = m_SrcImage.LockBits(r, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 

    //Load Colors 
    int[] colours = new int[m_SrcImage.Width * m_SrcImage.Height]; 
    Marshal.Copy(bd.Scan0, colours, 0, colours.Length); 
    m_SrcImage.UnlockBits(bd); 

    int len = colours.Length; 

    List<Color> result = new List<Color>(len); 

    for (int i = 0; i < len; ++i) 
    { 
     uint w = ((uint)colours[i]) & 0x00FFFFFF; //Delete alpha-channel 
     if (w != 0x00000000 && w != 0x00FFFFFF) //Check pixel is not black or white 
     { 
      w |= 0xFF000000;      //Return alpha channel 
      result.Add(Color.FromArgb((int)w)); 
     } 
    } 
    ... 

Bu kod tarafından listelenen benzersiz renkler Bu kod tarafından listelenen benzersiz renkler

result.Sort((a, b) => 
    { 
     return a.R != b.R ? a.R - b.R : 
       a.G != b.G ? a.G - b.G : 
       a.B != b.B ? a.B - b.B : 
       0; 
    }); 


    List<Color> uniqueColors = new List<Color>(result.Count); 

    Color rgbTemp = result[0]; 

    for (int i = 0; i < len; ++i) 
    { 
     if (rgbTemp == result[i]) 
     {  
       continue; 
     } 

     uniqueColors.Add(rgbTemp); 
     rgbTemp = result[i]; 
    } 
    uniqueColors.Add(rgbTemp); 
Ve bu kod aynı görüntüdeki farklı makinelerde farklı sonuçlar üretir! Örneğin

, this image üzerinde ürettiği:

  • 43198 benzersiz renkler XP SP3 .NET sürümü ile .NET sürümü ile Win7 Ultimate 4
  • 43168 benzersiz renkler 4,5

Asgari test projesi download here yapabilirsiniz. Sadece seçilen görüntüyü açar ve benzersiz renklerle txt dosyası üretir.

Bir gerçek daha. Bazı pikseller farklı makinelerde farklı okunur. Txt dosyalarını notepad ++ ile karşılaştırdım ve bazı piksellerin farklı RGB bileşenlerine sahip olduğunu gösteriyor. Her bileşen için fark, örn.

  • Win7 piksel: 255 200 100
  • WinXP piksel: bu yazı

    stackoverflow.com/questions/2419598/why-might-different- okuma 254 199 99

bilgisayar-hesapla-farklı-aritmetik-sonuçları-in-vb-net

(Üzgünüm, normal bağlantı için yeterli miktarda bekletme yok).

... ama nasıl düzeltileceği hakkında bilgi yoktu.


Proje VS 2015 Commumity Sürümü OS Windows 7 ile makinede .NET 4 İstemci profili için derlendi.

+0

Resimleri yüklemek için bize giriş yapmanıza gerek olmayan ücretsiz bir yükleme hizmeti seçmelisiniz – TaW

+0

@TaW Image imgur.com'a taşı ve test projesini github'a taşı –

+0

Teşekkürler. Ancak, Lasse'nin cevabının doğru olduğunu düşünüyorum: JPeg, görüntüyü mutlak doğrulukla yeniden üretmek anlamına gelmez. Gerçekten buna ihtiyacınız varsa, PNG'ye geçin! – TaW

cevap

3

Wikipedia has this to say about the accuracy requirements for JPEG Decoders

:

JPEG kodlama tanımı standart görüntü sıkıştırılmış çıkış için gerekli hassas düzeltmez.Bununla birlikte, JPEG standardı (ve benzer MPEG standartları), kod çözme işleminin tüm kısımları (değişken uzunluk şifre çözme, ters DCT, dequantizasyon, çıktıların yeniden sınıflandırılması) dahil olmak üzere, kod çözme için bazı hassas gereklilikler içerir; Referans algoritmasından çıkış aşmamalıdır:

  • her piksel bileşeni için farkın bir bitin bir maksimum
  • her biri 8 x 8 piksel blok
  • çok düşük ortalama üzerinde düşük ortalama kare hatası bütün görüntü
üzerinde tüm görüntü
  • son derece düşük ortalama hata üzerindeki her bir 8 x 8 piksel blok
  • çok düşük ortalama kare hatası üzerinde hata bileşeninde
  • (vurgu bana ait) Kısacası

    , burada iki farklı kod çözücü uygulamaları oynayan basitçe yoktur ve onlar doğruluk gereksinimi içinde, farklı görüntüler üretmek (1 bitlik = +/- 1 gözlemlediğiniz gibi değerler.

    Aynı (yerleşik olmayan) jpeg kod çözücüsünü kullanmaktan çok kısa bir süre beklemek gerekir. Aynı çıktıya sahip olmanız gerekiyorsa, muhtemelen, hangi .NET sürümü veya Windows üzerinde çalışıyor olursanız olun, aynı olacak olan farklı bir kod çözücüye geçiş yapmanız gerekecektir. Windows XP'den bu yana büyük değişikliklere uğradığı için GDI + 'nın buradaki suçlu olduğunu tahmin ediyorum.

    +0

    Bu üzücü bir haber ... Cevap için Thanx. PNG, BMP, JPEG ve TIFF formatlarıyla birlikte çalışabilecek bir kütüphane biliyor musunuz? –

    +0

    Bitmiracle Libjpeg.NET kütüphanesini eklemeye çalıştım ve aynı sonucu verdim ... –

    +1

    Yine de bu pikselleri aynı platformda üretmek için neden buna ihtiyacınız var? Kayıp bir sıkıştırma görüntü formatı kullanıyorsunuz, zaten pikseller üzerinde gerçek kontrolünüz yok. –

    0

    Ben yansıtmak ve bu kodu yazmak için LibJpeg.Net ekleyerek benim sorunu çözmek:

     private Bitmap JpegToBitmap(JpegImage jpeg) 
         { 
          int width = jpeg.Width; 
          int height = jpeg.Height; 
    
          // Read the image into the memory buffer 
          int[] raster = new int[height * width]; 
    
          for(int i = 0; i < height; ++i) 
          { 
           byte[] temp = jpeg.GetRow(i).ToBytes(); 
    
           for (int j = 0; j < temp.Length; j += 3) 
           { 
            int offset = i*width + j/3; 
            raster[offset] = 0; 
            raster[offset] |= (((int)temp[j+2]) << 16); 
            raster[offset] |= (((int)temp[j+1]) << 8); 
            raster[offset] |= (int)temp[j]; 
           } 
          } 
    
          Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); 
          Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); 
          BitmapData bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); 
          byte[] bits = new byte[bmpdata.Stride * bmpdata.Height]; 
    
          for (int y = 0; y < bmp.Height; y++) 
          { 
           int rasterOffset = y * bmp.Width; 
           int bitsOffset = (bmp.Height - y - 1) * bmpdata.Stride; 
    
           for (int x = 0; x < bmp.Width; x++) 
           { 
            int rgba = raster[rasterOffset++]; 
            bits[bitsOffset++] = (byte)((rgba >> 16) & 0xff); 
            bits[bitsOffset++] = (byte)((rgba >> 8) & 0xff); 
            bits[bitsOffset++] = (byte)(rgba & 0xff); 
           } 
          } 
          System.Runtime.InteropServices.Marshal.Copy(bits, 0, bmpdata.Scan0, bits.Length); 
          bmp.UnlockBits(bmpdata); 
    
          return bmp; 
         } 
    

    Yani, bu benim için yeterli.

    İlgili konular