2011-01-26 28 views
5

¿Alguien sabe cuál es este problema?El campo xxx nunca se asigna a, y siempre tendrá su valor predeterminado nulo

Tengo este xxx campo de advertencia Nunca se le asigna a, y siempre tendrá su valor nulo por defecto en private static Quantizer quantit;

no sé qué hacer para solucionarlo, porque cuando trato de usar quantit.Quantize() depuración dice: "Referencia de objeto no establecida en una instancia de un objeto". y punto a au = quantit.Quantize();

el código:

public class Quantization : System.Windows.Forms.Form 
{ 
    private static Quantizer quantit; 

    private Button btnLoad; 
    private PictureBox imgPhoto; 

    public Quantization() 
    { 

     btnLoad = new Button(); 
     btnLoad.Text = "&Load"; 
     btnLoad.Left = 10; 
     btnLoad.Top = 10; 
     btnLoad.Click += new System.EventHandler(this.OnLoadClick); 

     imgPhoto = new PictureBox(); 
     imgPhoto.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; 
     imgPhoto.Width = this.Width/2; 
     imgPhoto.Height = this.Height/2; 
     imgPhoto.Left = (this.Width - imgPhoto.Width)/2; 
     imgPhoto.Top = (this.Height - imgPhoto.Height)/2; 
     imgPhoto.SizeMode = PictureBoxSizeMode.StretchImage; 

     this.Controls.Add(btnLoad); 
     this.Controls.Add(imgPhoto); 
    } 

    protected void OnLoadClick(object sender, System.EventArgs e) 
    { 
     OpenFileDialog dlg = new OpenFileDialog(); 

     dlg.Title = "Open Image"; 
     dlg.Filter = "jpg files (*.jpg)|*.jpg|All files (*.*)|*.*" ; 

     if (dlg.ShowDialog() == DialogResult.OK) 
     { 
      Bitmap au; 

      //Image bmp = Image.FromFile("D:\\Documents and Settings\\kiosk.suprisul\\My Documents\\foto1.jpg"); 

      au = quantit.Quantize(); 
      imgPhoto.Image = au; 
      //imgPhoto.Image = bmp; 
      //imgPhoto.Image = au; 
      //new Bitmap(dlg.OpenFile()); 
     } 

     dlg.Dispose(); 
    } 
    [STAThread] 
    static void Main(string[] args) 
    { 

     //Image bmp; 

     //bmp = Image.FromFile("teste.jpg"); 
     //PaintEventArgs e; 
     //teste2.Quantize(bmp); 


     Application.Run(new Quantization()); 

     /* 
     System.Console.WriteLine("Hello, World!"); 
     System.Console.ReadLine();*/ 

    } 
} 

La clase:

namespace ImageManipulation 
{ 
    public unsafe abstract class Quantizer 
    { 
     /// <summary> 
     /// Construct the quantizer 
     /// </summary> 
     /// <param name="singlePass">If true, the quantization only needs to loop through the source pixels once</param> 
     /// <remarks> 
     /// If you construct this class with a true value for singlePass, then the code will, when quantizing your image, 
     /// only call the 'QuantizeImage' function. If two passes are required, the code will call 'InitialQuantizeImage' 
     /// and then 'QuantizeImage'. 
     /// </remarks> 
     public Quantizer(bool singlePass) 
     { 
      _singlePass = singlePass; 
     } 

     /// <summary> 
     /// Quantize an image and return the resulting output bitmap 
     /// </summary> 
     /// <param name="source">The image to quantize</param> 
     /// <returns>A quantized version of the image</returns> 
     public Bitmap Quantize()//Image source) 
     { 
      Image source = Image.FromFile("C:\\Users\\crashboy\\Downloads\\image009.jpg"); 
      // Get the size of the source image 
      int height = source.Height; 
      int width = source.Width; 

      // And construct a rectangle from these dimensions 
      Rectangle bounds = new Rectangle(0, 0, width, height); 

      // First off take a 32bpp copy of the image 
      Bitmap copy = new Bitmap(width, height, PixelFormat.Format32bppArgb); 

      // And construct an 8bpp version 
      Bitmap output = new Bitmap(width, height, PixelFormat.Format8bppIndexed); 

      // Now lock the bitmap into memory 
      using (Graphics g = Graphics.FromImage(copy)) 
      { 
       g.PageUnit = GraphicsUnit.Pixel; 

       // Draw the source image onto the copy bitmap, 
       // which will effect a widening as appropriate. 
       g.DrawImage(source, bounds); 
      } 

      // Define a pointer to the bitmap data 
      BitmapData sourceData = null; 

      try 
      { 
       // Get the source image bits and lock into memory 
       sourceData = copy.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

       // Call the FirstPass function if not a single pass algorithm. 
       // For something like an octree quantizer, this will run through 
       // all image pixels, build a data structure, and create a palette. 
       if (!_singlePass) 
        FirstPass(sourceData, width, height); 

       // Then set the color palette on the output bitmap. I'm passing in the current palette 
       // as there's no way to construct a new, empty palette. 
       output.Palette = this.GetPalette(output.Palette); 

       // Then call the second pass which actually does the conversion 
       SecondPass(sourceData, output, width, height, bounds); 
      } 
      finally 
      { 
       // Ensure that the bits are unlocked 
       copy.UnlockBits(sourceData); 
      } 

      // Last but not least, return the output bitmap 
      return output; 

     } 

     /// <summary> 
     /// Execute the first pass through the pixels in the image 
     /// </summary> 
     /// <param name="sourceData">The source data</param> 
     /// <param name="width">The width in pixels of the image</param> 
     /// <param name="height">The height in pixels of the image</param> 
     protected virtual void FirstPass(BitmapData sourceData, int width, int height) 
     { 
      // Define the source data pointers. The source row is a byte to 
      // keep addition of the stride value easier (as this is in bytes) 
      byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer(); 
      Int32* pSourcePixel; 

      // Loop through each row 
      for (int row = 0; row < height; row++) 
      { 
       // Set the source pixel to the first pixel in this row 
       pSourcePixel = (Int32*)pSourceRow; 

       // And loop through each column 
       for (int col = 0; col < width; col++, pSourcePixel++) 
        // Now I have the pixel, call the FirstPassQuantize function... 
        InitialQuantizePixel((Color32*)pSourcePixel); 

       // Add the stride to the source row 
       pSourceRow += sourceData.Stride; 
      } 
     } 

     /// <summary> 
     /// Execute a second pass through the bitmap 
     /// </summary> 
     /// <param name="sourceData">The source bitmap, locked into memory</param> 
     /// <param name="output">The output bitmap</param> 
     /// <param name="width">The width in pixels of the image</param> 
     /// <param name="height">The height in pixels of the image</param> 
     /// <param name="bounds">The bounding rectangle</param> 
     protected virtual void SecondPass(BitmapData sourceData, Bitmap output, int width, int height, Rectangle bounds) 
     { 
      BitmapData outputData = null; 

      try 
      { 
       // Lock the output bitmap into memory 
       outputData = output.LockBits(bounds, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); 

       // Define the source data pointers. The source row is a byte to 
       // keep addition of the stride value easier (as this is in bytes) 
       byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer(); 
       Int32* pSourcePixel = (Int32*)pSourceRow; 
       Int32* pPreviousPixel = pSourcePixel; 

       // Now define the destination data pointers 
       byte* pDestinationRow = (byte*)outputData.Scan0.ToPointer(); 
       byte* pDestinationPixel = pDestinationRow; 

       // And convert the first pixel, so that I have values going into the loop 
       byte pixelValue = QuantizePixel((Color32*)pSourcePixel); 

       // Assign the value of the first pixel 
       *pDestinationPixel = pixelValue; 

       // Loop through each row 
       for (int row = 0; row < height; row++) 
       { 
        // Set the source pixel to the first pixel in this row 
        pSourcePixel = (Int32*)pSourceRow; 

        // And set the destination pixel pointer to the first pixel in the row 
        pDestinationPixel = pDestinationRow; 

        // Loop through each pixel on this scan line 
        for (int col = 0; col < width; col++, pSourcePixel++, pDestinationPixel++) 
        { 
         // Check if this is the same as the last pixel. If so use that value 
         // rather than calculating it again. This is an inexpensive optimisation. 
         if (*pPreviousPixel != *pSourcePixel) 
         { 
          // Quantize the pixel 
          pixelValue = QuantizePixel((Color32*)pSourcePixel); 

          // And setup the previous pointer 
          pPreviousPixel = pSourcePixel; 
         } 

         // And set the pixel in the output 
         *pDestinationPixel = pixelValue; 
        } 

        // Add the stride to the source row 
        pSourceRow += sourceData.Stride; 

        // And to the destination row 
        pDestinationRow += outputData.Stride; 
       } 
      } 
      finally 
      { 
       // Ensure that I unlock the output bits 
       output.UnlockBits(outputData); 
      } 
     } 

     /// <summary> 
     /// Override this to process the pixel in the first pass of the algorithm 
     /// </summary> 
     /// <param name="pixel">The pixel to quantize</param> 
     /// <remarks> 
     /// This function need only be overridden if your quantize algorithm needs two passes, 
     /// such as an Octree quantizer. 
     /// </remarks> 
     protected virtual void InitialQuantizePixel(Color32* pixel) 
     { 

     } 

     /// <summary> 
     /// Override this to process the pixel in the second pass of the algorithm 
     /// </summary> 
     /// <param name="pixel">The pixel to quantize</param> 
     /// <returns>The quantized value</returns> 
     protected abstract byte QuantizePixel(Color32* pixel); 

     /// <summary> 
     /// Retrieve the palette for the quantized image 
     /// </summary> 
     /// <param name="original">Any old palette, this is overrwritten</param> 
     /// <returns>The new color palette</returns> 
     protected abstract ColorPalette GetPalette(ColorPalette original); 

     /// <summary> 
     /// Flag used to indicate whether a single pass or two passes are needed for quantization. 
     /// </summary> 
     private bool _singlePass; 

     /// <summary> 
     /// Struct that defines a 32 bpp colour 
     /// </summary> 
     /// <remarks> 
     /// This struct is used to read data from a 32 bits per pixel image 
     /// in memory, and is ordered in this manner as this is the way that 
     /// the data is layed out in memory 
     /// </remarks> 
     [StructLayout(LayoutKind.Explicit)] 
     public struct Color32 
     { 
      /// <summary> 
      /// Holds the blue component of the colour 
      /// </summary> 
      [FieldOffset(0)] 
      public byte Blue; 
      /// <summary> 
      /// Holds the green component of the colour 
      /// </summary> 
      [FieldOffset(1)] 
      public byte Green; 
      /// <summary> 
      /// Holds the red component of the colour 
      /// </summary> 
      [FieldOffset(2)] 
      public byte Red; 
      /// <summary> 
      /// Holds the alpha component of the colour 
      /// </summary> 
      [FieldOffset(3)] 
      public byte Alpha; 

      /// <summary> 
      /// Permits the color32 to be treated as an int32 
      /// </summary> 
      [FieldOffset(0)] 
      public int ARGB; 

      /// <summary> 
      /// Return the color for this Color32 object 
      /// </summary> 
      public Color Color 
      { 
       get { return Color.FromArgb(Alpha, Red, Green, Blue); } 
      } 
     } 
    } 
} 
+4

Mm. Has publicado demasiado código, creo. Además, el mensaje de error te dice exactamente cuál es el problema. Nunca le asigna nada a esa variable, por lo tanto, es nula, por lo tanto, causa los bloqueos que está viendo. Necesitas asignarle algo. –

Respuesta

6

El compilador le advierte que quantit nunca se inicializa y siempre será null.

probablemente debería inicializar con una instancia de una clase que deriva de ImageManipulation.Quantizer (no se puede crear una instancia Quantizer sí porque es una clase abstract):

private static Quantizer quantit = new QuantizerImplementation(); 
2

miembros estáticos se accede a través del nombre del tipo, es decir,

Quantization.quantit = {some value}; 

Por supuesto, ya que es privado, tendría que hacerlo así que esto desde dentro del tipo, en cuyo caso solo se puede utilizar:

quantit = {some value}; 

Sin embargo, también me pregunto si estática es una opción apropiada aquí, especialmente si usted está haciendo cualquier roscado (o código de la web). La estática a menudo se usa en exceso (y se usa de manera inapropiada).

+1

+1 para "Estático a menudo se usa en exceso" – Homam

3

que nunca están asignando una instancia de la clase Quantizer a su quantit variable estática, por lo que seguirá siendo una referencia null y que generará una excepción cuando se le intenta utilizar uno de sus métodos. Para solucionar el problema, simplemente inicialice ese miembro con un objeto new Quantizer antes de usarlo.

Por cierto, no estoy seguro de que quiera que esa variable sea static.

Editar

vi hace un momento que Quantizer es una clase abstracta ... entonces no se puede instanciar directamente, usted tiene primera para derivar su clase específica de que la aplicación de los métodos abstract (es decir, QuantizePixel y GetPalette) o utilice otra clase lista para usar derivada de Quantizer, y luego inicialice el campo quantit con una nueva instancia de dicha clase.

+0

No puede crear una instancia de esta manera porque Quantizer es una clase abstracta. – Adrian

+0

@antonlavey: Lo vi mientras hacías el comentario, debería arreglarlo ahora. –

+0

upvoted para la corrección (= (así que cambió downvote a upvote) – Adrian

2

Un campo estático es sólo un campo cuyo valor se comparte por todos. Piense en ello como una variable global. Lo que pasa es que todavía necesita crear una instancia al menos una vez. Por lo general, esto se hace en el mismo momento/lugar que la declaración.

public static Quantizer quantit = new Quantizer(?); 

no sé mucho acerca de lo que quiere hacer, pero no creo que realmente desea utilizar un campo estático aquí. Supongo que quiere crear una instancia/crear una nueva instancia de Quantizer en función de algún parámetro de entrada (singlePass o doublePass). Si la clase de Quantizer no tiene estado, debe convertirlo en singleton. Si desea hacerlo, le sugiero que mire en los contenedores de Dependency Injection, como Castle Windsor, que puede manejar eso por usted más fácilmente.

Cuestiones relacionadas