Qualité graphique d'un niveau à  bulles "IOs 7's like" ....

Hello merveilleux forum CocaCafé !!!


 


Je souhaite réaliser une prise d'image avec un niveau à  bulles en overlay dont le design ressemble le plus possible au niveau à  bulles super chouette de l'application " Boussole " d'Apple sous IOs 7 (2ème écran de l'appli). Les deux pastilles se croisant en "kCGBlendModeXOR" m'ont tapé dans l'oeil ...


 


Le code ci-dessous fonctionne ...mais n'est pas génial :


 


J'ai défini mon UIImageView " VueBulles " de la façon suivante :



CGRect screenBounds = [[UIScreen mainScreen] bounds];
UIImageView *VueBulles = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, screenBounds.size.width, screenBounds.size.height)];
[overlayView addSubview:VueBulles];

Puis je récupère les coordonnées X et Y renvoyé par l'accéléromètre pour " animer " mes deux bulles " BulleRouge " et " BulleBleue " qu'ensuite je " photographie " dans une UIImage " CaptureBulles " qui devient l'image de " VueBulles " :



UIImage *BulleRouge = [UIImage imageNamed:@Red200x200.png];
UIImage *BulleBleue = [UIImage imageNamed:@Blue200x200.png];
 
UIGraphicsBeginImageContext(CGSizeMake(screenBounds.size.width,screenBounds.size.height));
CGRect imageBulleRouge = CGRectMake(screenBounds.size.width*(1-x)/2-115,screenBounds.size.height*(1+y)/2-115, 230.0, 230.0);
CGRect imageBulleBleue = CGRectMake(screenBounds.size.width*(1+x)/2-115,screenBounds.size.height*(1-y)/2-115, 230.0, 230.0);
[BulleRouge drawInRect:imageBulleRouge blendMode:kCGBlendModeXOR alpha:1.0];
[BulleBleue drawInRect:imageBulleBleue blendMode:kCGBlendModeXOR alpha:1.0];
UIImage *CaptureBulles = UIGraphicsGetImageFromCurrentImageContext();
CGRect cropCaptureBulles = CGRectMake(0, 0, screenBounds.size.width, screenBounds.size.height);
CGImageRef RefCaptureBulles = CGImageCreateWithImageInRect([CaptureBulles CGImage], cropCaptureBulles);
VueBulles.image = [UIImage imageWithCGImage:RefCaptureBulles];
CGImageRelease(RefCaptureBulles);
UIGraphicsEndImageContext();

Ceci marche parfaitement avec " BulleRouge " et " BulleBleue " faisant 200x200 pixels ... mais au niveau qualité graphique c'est pas top, mes bulles sont beaucoup trop pixelisées  ..... et si j'augmente la qualité de ces deux bulles " BulleRouge " et " BulleBleue " par exemple à  400x400 pixels ... ma consomation CPU passe à  > 90% et mes bulles saccadent (accelerometerUpdateInterval = 1.0f/25.0f) ... Avez-vous une solution pour augmenter la qualité graphique de mes bulles ... sans augmenter la consommation CPU ?


Par avance un immense merci !!!


OldNick


Réponses

  • CéroceCéroce Membre, Modérateur
    Le principe que tu emploies comporte deux problèmes:
    1) tu utilises des images bitmaps (pas très grave)
    2) tu crées un contexte graphique "offscreen", tu fais tes opérations dedans, et puis tu l'affiches dans le contexte courant. C'est super lourd !

    Essaie plutôt ça:
    - crée une sous-classe de UIView pour surcharger -drawRect:
    - Remplis le fond de noir
    - Dessine le premier cercle blanc
    - Appelle CGContextSetBlendMode() pour passer en mode XOR.
    - Dessine le deuxième cercle en noir.
    - Dessine le texte en noir.

    Il est déconseillé de dessiner dans -drawRect: sous iOS, mais le dessin est simple, et je ne suis crois pas qu'on puisse changer le blend mode avec les CALayers.
  • Bonjour,


     


    Pourquoi utiliser des images pour les 2 ronds ?


    Tu peux les dessiner directement.


     


    UIGraphicsBeginImageContext est à  utiliser pour les écrans non rétina.


    Pour les écrans rétina, il faut utiliser (je crois) UIGraphicsBeginImageContextWithOptions

  • Merci Céroce et Eric P. pour vos réponses super rapides !!! Je me doutais bien que manipuler des images bitmap c'est hyper lourd ...


    N'étant pas très à  l'aise avec la création de sous-classe (désolé Céroce, mais je suis encore un poil novice en dev objective-c ) ... je vais tenter le dessin de mes bulles comme tu me le recommandes Eric ...


    Je vous tiens au courant. Encore merci. Old Nick


  • CéroceCéroce Membre, Modérateur
    Je t'explique quand même parce que je pense que les performances n'iront toujours pas !

    Rien de bien méchant. Tu crées une classe comme d'habitude, et dans le formulaire, au lieu d'une faire une sous-classe de NSObject, tu choisis UIView.
    La seule difficulté est alors de remplacer ton instance de UIImageView par l'instance de ta classe.
  • Merci Céroce .. je vais creuser avec tes recommandations ... car il faut que j'arrive à  maitriser cette aspect "sous classe" ...


    En attendant, j'ai suivi les recommandations d'Eric P. ....et ça marche impeccable : qualité graphique topissime pour une consommation CPU raisonnable (34 % en moyenne sur un 4S), voici ce que j'ai fait :



    UIGraphicsBeginImageContext(CGSizeMake(screenBounds.size.width,screenBounds.size.height));
                     
    [[UIColor clearColor] setStroke];
    [[UIColor colorWithRed:252.0/255.0 green:38.0/255.0 blue:50.0/255.0 alpha:1] setFill];
    UIBezierPath *BulleRouge = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(screenBounds.size.width*(1-x)/2-115,screenBounds.size.height*(1+y)/2-115, 230.0, 230.0)];
    [BulleRouge strokeWithBlendMode:kCGBlendModeXOR alpha:1.0];
    [BulleRouge fillWithBlendMode:kCGBlendModeXOR alpha:1.0];                 
    [[UIColor clearColor] setStroke];
    [[UIColor colorWithRed:82.0/255.0 green:201.0/255.0 blue:255.0/255.0 alpha:1] setFill];
    UIBezierPath *BulleBleue = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(screenBounds.size.width*(1+x)/2-115,screenBounds.size.height*(1-y)/2-115, 230.0, 230.0)];
    [BulleBleue strokeWithBlendMode:kCGBlendModeXOR alpha:1.0];
    [BulleBleue fillWithBlendMode:kCGBlendModeXOR alpha:1.0];
    UIImage *CaptureBulles = UIGraphicsGetImageFromCurrentImageContext();
    CGRect cropCaptureBulles = CGRectMake(0, 0, screenBounds.size.width, screenBounds.size.height);
    CGImageRef RefCaptureBulles = CGImageCreateWithImageInRect([CaptureBulles CGImage], cropCaptureBulles);
    VueBulles.image = [UIImage imageWithCGImage:RefCaptureBulles];
    CGImageRelease(RefCaptureBulles);
    UIGraphicsEndImageContext();

    Merci à  vous 2 !!! J'ai même pu augmenter l' accelerometerUpdateInterval en le passant de 1/25 à  1/40 ...mon niveau à  bulle en overlay est encore plus fluide ...


    Encore 1000 mercis !


    OldNick


  • L'outil http://www.paintcodeapp.com/ peut également s'avérer très utile dans ton cas.


  • Merci xyloweb pour ce bon conseil !


Connectez-vous ou Inscrivez-vous pour répondre.