Qualité d'image

UniXUniX Membre
02:04 modifié dans API AppKit #1
Salut.

J'ai une question concernant les images. Je créé des vignettes d'images de grandes dimensions en utilisant la méthode setSize: de NSImage. J'obtiens effectivement mes vignettes, mais la qualité d'image n'est pas très bonne ...

Voici 2 vignettes. La première créée avec la méthode setSize:, la seconde avec Photoshop. L'image source est la même. On voit bien la différence entre les 2 ...

cocoa.jpg  ps.jpg

Comment puis-je faire pour obtenir des vignettes de qualité ?

Réponses

  • schlumschlum Membre
    02:04 modifié #2
    Dans SudokuX (pour la création de l'icône du Dock), j'avais le même problème et j'ai fait ça à  la main avec un algorithme de traitement d'image (en gros créer chaque pixel de la vignette avec une moyenne d'une zone de l'image originale), mais doit y avoir des trucs dans CoreImage pour faire ça...
  • UniXUniX Membre
    02:04 modifié #3
    Manque de bol, Core Image n'est disponible qu'à  partir de MacOS X.4 ....
    Il va falloir que je trouve autre chose ....
  • AliGatorAliGator Membre, Modérateur
    02:04 modifié #4
    Et tu as essayé de dessiner ton image dans une nouvelle image plus petite, plutôt qu'un setSize ?

    avec un [tt]drawInRect: fromRect: operation:[/tt], genre (et lockFocus/unlockFocus sur l'image destination pour entourer le drawInRect et que ça dessine bien sur le contexte de l'image miniature)

    Je ne sais pas du tout si ça donne la même chose qu'un setSize ou si ça donnera une meilleure qualité (ou une moins bonne :D) mais c'est à  tester pour voir la différence en tout cas.
  • 02:04 modifié #5
    Essaie cette librairie: http://www.entropy.ch/software/macosx/#epegwrapper

    (attention, ne marche que pour les images jpeg)
  • schlumschlum Membre
    02:04 modifié #6
    dans 1173456039:

    Et tu as essayé de dessiner ton image dans une nouvelle image plus petite, plutôt qu'un setSize ?

    avec un [tt]drawInRect: fromRect: operation:[/tt], genre (et lockFocus/unlockFocus sur l'image destination pour entourer le drawInRect et que ça dessine bien sur le contexte de l'image miniature)

    Je ne sais pas du tout si ça donne la même chose qu'un setSize ou si ça donnera une meilleure qualité (ou une moins bonne :D) mais c'est à  tester pour voir la différence en tout cas.

    Pour avoir testé -> ça donne la même chose  ;)
  • schlumschlum Membre
    mars 2007 modifié #7
    Si ça vous intéresse, voilà  mon code :
    (NB : il crée un handle pour pouvoir l'utiliser comme icône sur un fichier aussi...)

    - (NSImage*)iconImage:(Handle*)handle<br />{<br />	unsigned char *pHandle = NULL;<br />	if(handle) {<br />		*handle = NewHandle(128*128*4);<br />		pHandle = (unsigned char*)**handle;<br />	}<br />	int h_i = 0;<br />	// Image initiale...<br />	NSImage *im1 = [[NSImage alloc] initWithSize:NSMakeSize(558.,558.)];<br />	[im1 lockFocus];<br />	[sudokuView drawRect:NSMakeRect(0.,0.,558.,558.)];<br />	[im1 unlockFocus];<br />	NSBitmapImageRep *imr1 = [NSBitmapImageRep imageRepWithData:[im1 TIFFRepresentation]];<br />	[im1 release];<br />	<br />	//[sudokuView lockFocus];<br />	//NSbitmapImageRep *imr1 = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0.,0.,558.,558.)];<br />	//[sudokuView unlockFocus];<br />	 <br />	<br />	// Image à  renvoyer<br />	NSImage *im2 = [[[NSImage alloc] initWithSize:NSMakeSize(128.,128.)] autorelease];<br />	//NSBitmapImageRep *imr1;<br />	NSBitmapImageRep *imr2 = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL<br />																	 pixelsWide:128<br />																	 pixelsHigh:128<br />																  bitsPerSample:8<br />																	samplesPerPixel:3<br />																	   hasAlpha:NO<br />																	   isPlanar:NO<br />																 colorSpaceName:NSCalibratedRGBColorSpace<br />																	bytesPerRow:0<br />																   bitsPerPixel:0];<br />	[im2 addRepresentation:imr2];<br />	<br />	// Calculs de l&#39;icône par moyennes de zones<br />	int i1,j1,i2,j2,i3,j3,k;<br />	int k_b = [imr1 bitsPerPixel]/8;<br />	unsigned char *dt1 = [imr1 bitmapData];<br />	unsigned char *dt2 = [imr2 bitmapData];<br />	unsigned char *dt1_t,*dt2_t;<br />	float rapp = 558./128.;<br />	unsigned int pix[3];<br />	for(i1=0;i1&lt;128;++i1) {<br />		for(j1=0;j1&lt;128;++j1) {<br />			dt2_t = dt2+3*(128*i1+j1);<br />			i2 = rint((i1+.5)*rapp);<br />			j2 = rint((j1+.5)*rapp);<br />			for(k=0;k&lt;k_b;++k)<br />				pix[k] = 0;<br />			for(i3=i2-2;i3&lt;=i2+2;++i3) {<br />				for(j3=j2-2;j3&lt;=j2+2;++j3) {<br />					dt1_t = dt1+k_b*(558*(i3&lt;0?0:(i3&gt;557?557:i3))+(j3&lt;0?0:(j3&gt;557?557:j3)));<br />					for(k=0;k&lt;k_b;++k)<br />						pix[k] += dt1_t[k];<br />				}<br />			}<br />			if(pHandle) {<br />				pHandle[h_i++] = 255;<br />				for(k=0;k&lt;k_b;++k) {<br />					dt2_t[k] = (unsigned char)(pix[k]/25);<br />					pHandle[h_i++] = dt2_t[k];<br />				}<br />			} else<br />				for(k=0;k&lt;k_b;++k)<br />					dt2_t[k] = (unsigned char)(pix[k]/25);<br />		}<br />	}<br />	[imr2 release];<br />	return im2;<br />}
    


    La partie du haut serait à  arranger un peu pour dessiner directement dans un NSBitmapImageRep (un lockFocus sur une NSImage détruit les anciens ImageRep et crée un NSCachedImageRep sur lequel on ne peut rien faire...), mais là , j'ai la flemme pour l'instant :P
  • UniXUniX Membre
    02:04 modifié #8
    Malheureusement epegwrapper est 10.4 et + ...

    dans 1173458043:

    dans 1173456039:

    Et tu as essayé de dessiner ton image dans une nouvelle image plus petite, plutôt qu'un setSize ?

    avec un [tt]drawInRect: fromRect: operation:[/tt], genre (et lockFocus/unlockFocus sur l'image destination pour entourer le drawInRect et que ça dessine bien sur le contexte de l'image miniature)

    Je ne sais pas du tout si ça donne la même chose qu'un setSize ou si ça donnera une meilleure qualité (ou une moins bonne :D) mais c'est à  tester pour voir la différence en tout cas.

    Pour avoir testé -> ça donne la même chose  ;)


    Effectivement, ça donne la même chose. J'ai rajouté la ligne suivante, mais c'est pas mieux ...
    [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh]
    


    Je vais regarder ton code schlum.
  • schlumschlum Membre
    mars 2007 modifié #9
    dans 1173458687:

    Je vais regarder ton code schlum.


    Si tu veux gérer pour n'importe quelle taille d'image originale et de vignette, va y avoir un peu d'adaptation à  faire...

    (déjà  gérer deux rapports : un d'abscisse et un d'ordonnée...)

    Tu peux zapper tout le début, si tu as ton image toute faite, et commencer par "NSBitmapImageRep *imr1 = [NSBitmapImageRep imageRepWithData:[myImage TIFFRepresentation]];" (et même zapper ça si il y a déjà  un NSBitmapImageRep dans l'image).
  • MalaMala Membre, Modérateur
    mars 2007 modifié #10
    Une solution alternative assez simple et qui marche bien consiste à  passer par une NSImageView en mode  NSScaleProportionally et a en faire une capture.

    Voici ce le bout de code que j'utilise pour mes besoins...
    <br />- (NSImage*)createThumbnailForImage:(NSImage*)image withFactor:(float)factor<br />{<br />&nbsp; &nbsp; NSImage *thumbnail = nil;<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; if( image &amp;&amp; factor&gt;0 &amp;&amp; factor&lt;=1)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; // <br />&nbsp; &nbsp; &nbsp; &nbsp; // Get the image size<br />&nbsp; &nbsp; &nbsp; &nbsp; //<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; NSData *TIFFRep = [[image TIFFRepresentation] retain];<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; NSBitmapImageRep *imageRep = [[NSBitmapImageRep imageRepWithData:TIFFRep] retain];<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; NSSize imageSize = [imageRep size];<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; [TIFFRep&nbsp; release];<br />&nbsp; &nbsp; &nbsp; &nbsp; [imageRep release];<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; //<br />&nbsp; &nbsp; &nbsp; &nbsp; // Create an ImageView according to the image size and the factor and put the image<br />&nbsp; &nbsp; &nbsp; &nbsp; //<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; NSRect rect = NSMakeRect(0,0,imageSize.width*factor,imageSize.height*factor);<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; NSImageView *imageView&nbsp; = [[NSImageView alloc] initWithFrame:rect];<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; [imageView setImageFrameStyle:NSImageFrameNone];<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; [imageView setImageScaling:NSScaleProportionally];<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; [imageView&nbsp; setImage:image];<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; //<br />&nbsp; &nbsp; &nbsp; &nbsp; // Grab the view<br />&nbsp; &nbsp; &nbsp; &nbsp; //<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; // --------------<br />&nbsp; &nbsp; &nbsp; &nbsp; // Tiger only...<br />&nbsp; &nbsp; &nbsp; &nbsp; NSBitmapImageRep * bitmap = [imageView bitmapImageRepForCachingDisplayInRect:rect];<br />&nbsp; &nbsp; &nbsp; &nbsp; [imageView cacheDisplayInRect:rect toBitmapImageRep:bitmap];<br />&nbsp; &nbsp; &nbsp; &nbsp; // --------------<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; thumbnail = [[[NSImage alloc] init] autorelease];<br />&nbsp; &nbsp; &nbsp; &nbsp; [thumbnail addRepresentation:bitmap];<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; [imageView release];<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; return thumbnail;<br />}<br />
    

    On passe en paramètre la NSImage d'origine et le facteur de réduction que l'on souhaite obtenir.

    Par contre, je fais le grab avec bitmapImageRepForCachingDisplayInRect et cacheDisplayInRect qui sont "Tiger only". On peut contourner le problème de compatibilité avec une capture pdf mais c'est moins performant de mémoire  (voir intervention de Chacha sur ce post: http://www.objective-cocoa.org/forum/index.php/topic,2105.0.html ).

    Edit: après relecture du post précité, le drawRect proposé par schlum doit être plus adapté que la capture pdf. :)
  • UniXUniX Membre
    02:04 modifié #11
    Voir la réponse donnée par Bru ici.
Connectez-vous ou Inscrivez-vous pour répondre.