2013-05-17 5 views
10

Mam dziwny problem w moim projekcie. Chcę tylko, aby użytkownik malował lub rysował, przesuwając po obrazie jako nakładkę i po prostu trzeba przyciąć obszar z obrazu znajdującego się poniżej malowanego regionu. Mój kod działa dobrze tylko wtedy, gdy widok poniżej obszaru farby ma szerokość 320 pikseli, tj. Szerokość iPhone'a. Ale jeśli zmienię szerokość ImageView, nie otrzymam pożądanego rezultatu.narysowany obszar w UIImage nie został poprawnie rozpoznany

Korzystam z następującego kodu, aby zbudować CGRect wokół malowanej części.

-(CGRect)detectRectForFaceInImage:(UIImage *)image{ 
    int l,r,t,b; 
    l = r = t = b = 0; 

    CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage)); 
    const UInt8* data = CFDataGetBytePtr(pixelData); 

    BOOL pixelFound = NO; 

    for (int i = leftX ; i < rightX; i++) { 
     for (int j = topY; j < bottomY + 20; j++) { 
      int pixelInfo = ((image.size.width * j) + i) * 4; 
      UInt8 alpha = data[pixelInfo + 2]; 
      if (alpha) { 
       NSLog(@"Left %d", alpha); 
       l = i; 
       pixelFound = YES; 
       break; 
      } 
     } 
     if(pixelFound) break; 
    } 

    pixelFound = NO; 
    for (int i = rightX ; i >= l; i--) { 
     for (int j = topY; j < bottomY ; j++) { 
      int pixelInfo = ((image.size.width * j) + i) * 4; 
      UInt8 alpha = data[pixelInfo + 2]; 
      if (alpha) { 
       NSLog(@"Right %d", alpha); 
       r = i; 
       pixelFound = YES; 
       break; 
      } 
     } 
     if(pixelFound) break; 
    } 

    pixelFound = NO; 
    for (int i = topY ; i < bottomY ; i++) { 
     for (int j = l; j < r; j++) { 
      int pixelInfo = ((image.size.width * i) + j) * 4; 
      UInt8 alpha = data[pixelInfo + 2]; 
      if (alpha) { 
       NSLog(@"Top %d", alpha); 
       t = i; 
       pixelFound = YES; 
       break; 
      } 
     } 
     if(pixelFound) break; 
    } 

    pixelFound = NO; 
    for (int i = bottomY ; i >= t; i--) { 
     for (int j = l; j < r; j++) { 
      int pixelInfo = ((image.size.width * i) + j) * 4; 
      UInt8 alpha = data[pixelInfo + 2]; 
      if (alpha) { 
       NSLog(@"Bottom %d", alpha); 
       b = i; 
       pixelFound = YES; 
       break; 
      } 
     } 
     if(pixelFound) break; 
    } 

    CFRelease(pixelData); 


    return CGRectMake(l, t, r - l, b-t); 
} 

w powyższym kodzie leftX, rightX, Topy, BottomY są wartości skrajne (od CGPoint) w pływak, który jest liczony gdy użytkownik przesuń palcem na ekranie w czasie malowania i reprezentuje prostokąt, który zawiera malowaną powierzchnię w jego granicach (aby zminimalizować pętlę).

leftX - minimum in X-axis 
    rightX - maximum in X-axis 
    topY - min in Y-axis 
    bottom - max in Y-axis 

Tutaj l, r, t, b są wartościami obliczonymi dla rzeczywistego prostokąta.

Zgodnie z tym, co zostało powiedziane wcześniej, kod ten działa dobrze, gdy obraz, w którym wykonywane jest malowanie, ma szerokość 320 pikseli i jest rozłożony na całej szerokości ekranu. Ale jeśli szerokość widoku obrazu jest mniejsza niż 300 i jest umieszczona na środku ekranu, kod daje fałszywy wynik.

Uwaga: Skaluje obraz zgodnie z szerokością obrazu.

Poniżej wyjście NSLog:

  1. Gdy szerokość ImageView wynosi 320 pikseli (Są to wartości dla składowej koloru w dopasowanej piksela lub nieprzezroczystego piksel):

    2013-05-17 17:58:17.170 FunFace[12103:907] Left 41 
    2013-05-17 17:58:17.172 FunFace[12103:907] Right 1 
    2013-05-17 17:58:17.173 FunFace[12103:907] Top 73 
    2013-05-17 17:58:17.174 FunFace[12103:907] Bottom 12 
    
  2. Gdy szerokość widoku obrazu wynosi 300 pikseli:

    2013-05-17 17:55:26.066 FunFace[12086:907] Left 42 
    2013-05-17 17:55:26.067 FunFace[12086:907] Right 255 
    2013-05-17 17:55:26.069 FunFace[12086:907] Top 42 
    2013-05-17 17:55:26.071 FunFace[12086:907] Bottom 255 
    

Jak mogę rozwiązać ten problem, ponieważ potrzebuję widoku obrazu w środku z dopełnieniem po jego obu stronach.

EDIT: OK wygląda na to, że mój problem wynika z orientacji obrazów JPEG (z aparatu). Obrazy Png działają dobrze i nie wpływają na zmianę szerokości widoku. Ale nadal pliki JPEG nie działają, nawet jeśli obsługuję orientację.

+0

Jaki jest rozmiar obrazu? – Wain

+0

320x240, gdy szerokość widoku obrazu wynosi 320, a szerokość widoku wynosi 300 to skaluję obraz do rozmiaru 300x225 (który jest wielkością widoku obrazu). –

+0

Czy faktycznie przerysowujesz obrazek do tego rozmiaru lub po prostu umieszczasz go w widoku obrazu? i pozwalając obrazowi na skalowanie go? – Wain

Odpowiedz

2

Po pierwsze, zastanawiam się, czy uzyskujesz dostęp do czegoś innego niż 32-bitowa RGBA? Wartość indeksu dla danych [] jest przechowywana w parametrze pikselInfo, a następnie przesuwa o +2 bajty zamiast o +3. To wyląduje na niebieskim bajcie. Jeśli masz zamiar użyć RGBA, fakt ten wpłynie na resztę wyników twojego kodu.

Przechodząc dalej, przy założeniu, że wciąż otrzymujesz błędne wyniki pomimo posiadania prawidłowej wartości składnika alfa, wydaje się, że Twój "stały" kod dałby lewe, prawe, górne, dolne wyniki NSLog z wartościami alfa mniejszymi niż pełne -do 255, coś zbliżonego do 0. W tym przypadku bez dalszego kodu sugeruję, że problem leży w kodzie używanym do skalowania obrazu ze źródła 320x240 do 300x225 (lub dowolnych innych skalowanych wymiarów). Mogę sobie wyobrazić, że twój obraz ma wartości alfa na skraju 255, jeśli twój kod "skali" wykonuje plon, a nie skalę.

+0

Mam nieco rozwiązany problem. Metoda w poniższym linku po zmianie malloc na calloc działa dla mnie: [link] (http://stackoverflow.com/questions/448125/how-to-get-pixel-data-from-a-uiimage-cocoa- touch-or-cgimage-core-graphics) –

+0

Ale czasami moja aplikacja ulega awarii podczas sprawdzania pikseli i nie znam powodu. Być może dostęp do pamięci jest pusty. –

+0

@GauravSingh Myślę, że twoje użycie CGDataProviderCopyData, CGImageGetDataProvider i CFDataGetBytePtr jest właściwe. Czy zmieniłeś kod teraz? Pomoże Ci to, jeśli zaktualizujesz pytanie, aby wyjaśnić, jaki jest Twój problem. –