2010-03-06 12 views
0

J'ai utilisé la bibliothèque FJCore dans un projet Silverlight pour aider au traitement d'images en temps réel, et j'essaie de comprendre comment obtenir une compression et des performances supplémentaires de la bibliothèque . Maintenant, si je comprends bien, la norme JPEG vous permet de spécifier un rapport de sous-échantillonnage de chrominance (voir http://en.wikipedia.org/wiki/Chroma_subsampling et http://en.wikipedia.org/wiki/Jpeg); et il semble que cela est censé être mis en œuvre dans la bibliothèque FJCore en utilisant les tableaux HsampFactor et VsampFactor:VsampFactor et HsampFactor dans la bibliothèque FJCore

public static readonly byte[] HsampFactor = { 1, 1, 1 }; 
    public static readonly byte[] VsampFactor = { 1, 1, 1 }; 

Cependant, je vais avoir du mal à comprendre comment les utiliser. Il me semble que les valeurs actuelles sont censées représenter un sous-échantillonnage 4: 4: 4 (par exemple, aucun sous-échantillonnage), et que si je voulais obtenir un sous-échantillonnage 4: 1: 1, les bonnes valeurs seraient les suivantes:

public static readonly byte[] HsampFactor = { 2, 1, 1 }; 
    public static readonly byte[] VsampFactor = { 2, 1, 1 }; 

au moins, c'est ainsi que d'autres bibliothèques similaires utilisent ces valeurs (par exemple, voir le code exemple here pour libjpeg).

Cependant, ni les valeurs ci-dessus de {2, 1, 1} ni aucun autre ensemble de valeurs que j'ai essayé en dehors de {1, 1, 1} ne produisent une image lisible. En regardant le code, on ne dirait pas non plus que c'est comme ça que c'est écrit. Mais pour la vie de moi, je ne peux pas comprendre ce que le code FJCore est en fait en essayant à faire. Il semble que ce soit simplement en utilisant les facteurs de l'échantillon pour répéter les opérations que cela a déjà été fait - c'est-à-dire, si je ne savais pas mieux, je dirais que c'était un bug. Mais c'est une bibliothèque assez établie, basée sur un code Java assez bien établi, donc je serais surpris si c'était le cas.

Quelqu'un a-t-il des suggestions sur la façon d'utiliser ces valeurs pour obtenir un sous-échantillonnage de la chrominance 4: 2: 2 ou 4: 1: 1?

Pour ce que ça vaut la peine, voici le code correspondant de la JpegEncoder classe:

for (comp = 0; comp < _input.Image.ComponentCount; comp++) 
{ 
    Width = _input.BlockWidth[comp]; 
    Height = _input.BlockHeight[comp]; 

    inputArray = _input.Image.Raster[comp]; 

    for (i = 0; i < _input.VsampFactor[comp]; i++) 
    { 
     for (j = 0; j < _input.HsampFactor[comp]; j++) 
     { 
      xblockoffset = j * 8; 
      yblockoffset = i * 8; 
      for (a = 0; a < 8; a++) 
      { 
       // set Y value. check bounds 
       int y = ypos + yblockoffset + a; if (y >= _height) break; 

       for (b = 0; b < 8; b++) 
       { 
        int x = xpos + xblockoffset + b; if (x >= _width) break; 
        dctArray1[a, b] = inputArray[x, y]; 
       } 
      } 
      dctArray2 = _dct.FastFDCT(dctArray1); 
      dctArray3 = _dct.QuantizeBlock(dctArray2, FrameDefaults.QtableNumber[comp]); 
      _huf.HuffmanBlockEncoder(buffer, dctArray3, lastDCvalue[comp], FrameDefaults.DCtableNumber[comp], FrameDefaults.ACtableNumber[comp]); 
      lastDCvalue[comp] = dctArray3[0]; 
     } 
    } 
} 

Et remarquez que, dans les i & boucles j, ils ne sont pas contrôler tout type de saut de pixel: si HsampFactor [0 ] est réglé sur deux, il suffit de saisir deux blocs au lieu d'un.

Répondre

0

Je l'ai compris. Je pensais qu'en définissant les facteurs d'échantillonnage, vous demandiez à la bibliothèque de sous-échantillonner les composants raster eux-mêmes. Il s'avère que lorsque vous définissez les facteurs d'échantillonnage, vous indiquez à la bibliothèque la taille relative des composants raster que vous fournissez. En d'autres termes, vous devez effectuer vous-même le sous-échantillonnage de chrominance de l'image avant de la soumettre à la bibliothèque FJCore pour la compression. Quelque chose comme ça est ce qu'il cherche:

private byte[][,] GetSubsampledRaster() 
    { 
     byte[][,] raster = new byte[3][,]; 
     raster[Y] = new byte[width/hSampleFactor[Y], height/vSampleFactor[Y]]; 
     raster[Cb] = new byte[width/hSampleFactor[Cb], height/vSampleFactor[Cb]]; 
     raster[Cr] = new byte[width/hSampleFactor[Cr], height/vSampleFactor[Cr]]; 

     int rgbaPos = 0; 
     for (short y = 0; y < height; y++) 
     { 
      int Yy = y/vSampleFactor[Y]; 
      int Cby = y/vSampleFactor[Cb]; 
      int Cry = y/vSampleFactor[Cr]; 
      int Yx = 0, Cbx = 0, Crx = 0; 
      for (short x = 0; x < width; x++) 
      { 
       // Convert to YCbCr colorspace. 
       byte b = RgbaSample[rgbaPos++]; 
       byte g = RgbaSample[rgbaPos++]; 
       byte r = RgbaSample[rgbaPos++]; 
       YCbCr.fromRGB(ref r, ref g, ref b); 

       // Only include the byte in question in the raster if it matches the appropriate sampling factor. 
       if (IncludeInSample(Y, x, y)) 
       { 
        raster[Y][Yx++, Yy] = r; 
       } 
       if (IncludeInSample(Cb, x, y)) 
       { 
        raster[Cb][Cbx++, Cby] = g; 
       } 
       if (IncludeInSample(Cr, x, y)) 
       { 
        raster[Cr][Crx++, Cry] = b; 
       } 

       // For YCbCr, we ignore the Alpha byte of the RGBA byte structure, so advance beyond it. 
       rgbaPos++; 
      } 
     } 
     return raster; 
    } 

    static private bool IncludeInSample(int slice, short x, short y) 
    { 
     // Hopefully this gets inlined . . . 
     return ((x % hSampleFactor[slice]) == 0) && ((y % vSampleFactor[slice]) == 0); 
    } 

Il pourrait y avoir des moyens supplémentaires pour optimiser, mais il travaille pour l'instant.

+0

Quelle est la performance de FJCore par rapport à l'encodeur jpeg intégré utilisé par GDI +? J'ai besoin de garder le sous-échantillonnage à 4: 4: 4, pour permettre une compression accrue sans perte de détails (texte à côté des images). Je me demandais si FJCore pourrait faire l'affaire ... –

+0

Je n'ai pas vraiment testé les deux côte à côte: j'ai utilisé FJCore non pas parce que c'était plus rapide ou plus flexible, mais parce que je devais l'utiliser avec Silverlight pour la compression vidéo Motion JPEG. Je serais intéressé à entendre vos résultats. –