2012-07-10 2 views
0

지금 다음을 수행하려고 몇 시간 동안 있었다,CGImageCreate는 Completly 검은 부여하거나 어떤 이미지 또는 충돌

  • 플레이어는 플레이어가 도청 한 픽셀의 값을 가져 화면을
  • 도청
  • 화상 통한 루프는 픽셀이 새롭게 생성 같이있는 UIImage 설정 동일한 동일 값을 가진 모든
  • 화소가 0의 알파는 새로운 이미지를 만들도록하고
  • 아르 알 하나
  • 012,351,
  • ...
  • 이익

그러나 제목이 말한다 완전히 검은 화면이나 이미지가 전혀 ... 아마도 어쩌면 모두 0으로 알파를 설정하지 않기 때문에 그 중 하나가해야 할 것, 또는 뭔가 충돌 이 기능 여기 CGSConvertBGRX8888toRGBA8888

근처 스택에 나쁜 액세스에 대한 기능을

+ (UIImage*)getRGBAsFromImage:(UIImage*)image atX:(int)xx andY:(int)yy 

{

입니다 51,515,
// First get the image into your data buffer 

CGImageRef imageRef = [image CGImage]; 

NSUInteger width = CGImageGetWidth(imageRef); 
NSUInteger height = CGImageGetHeight(imageRef); 
NSUInteger bitsPerComponent = CGImageGetBitsPerComponent(imageRef); 
NSUInteger bitsPerPixel = CGImageGetBitsPerPixel(imageRef); 
NSUInteger bytesPerRow = CGImageGetBytesPerRow(imageRef); 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 


unsigned char *rawData = (unsigned char*) malloc(height * width * 4); 


CGContextRef context = CGBitmapContextCreate(rawData, 
              width, 
              height, 
              bitsPerComponent, 
              bytesPerRow, 
              colorSpace, 
              kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 


CGContextClearRect(context, CGRectMake(0, 0, width, height)); 
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); 

//convert phone screen coords to texture coordinates. 
xx *= width/320; 
yy *= height/480; 

int counter = 0; 


// Now your rawData contains the image data in the RGBA8888 pixel format. 
// Get the byteIndex of pixel tapped. 

int byteIndex = (bytesPerRow * yy) + xx * bitsPerPixel; 

CGFloat red = (rawData[byteIndex]  * 1.0)/255.0; 
CGFloat green = (rawData[byteIndex + 1] * 1.0)/255.0; 
CGFloat blue = (rawData[byteIndex + 2] * 1.0)/255.0; 
CGFloat alpha = (rawData[byteIndex + 3] * 1.0)/255.0; 
byteIndex += 4; 

for(int x = 0; x < width; x++) 
{ 
    for(int y = 0; y < height; y++) 
    { 
     byteIndex = (width * y) + x * bitsPerPixel; 

     CGFloat redVal = (rawData[byteIndex]  * 1.0)/255.0; 
     CGFloat greenVal = (rawData[byteIndex + 1] * 1.0)/255.0; 
     CGFloat blueVal = (rawData[byteIndex + 2] * 1.0)/255.0; 
     CGFloat alphaVal = (rawData[byteIndex + 3] * 1.0)/255.0; 
     byteIndex += 4; 

     if(alphaVal != 0) 
     { 
      if(redVal == red && greenVal == green && blueVal == blue) 
      { 
       rawData[byteIndex + 3] = 0; 
       counter ++; 
      } 
     } 
    } 
} 

NSLog(@"Pixels amount: %i", counter); 

CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, 
                  rawData, 
                  width*height*4, 
                  NULL); 

CGImageRef newCGimage = CGImageCreate(width, 
             height, 
             bitsPerComponent, 
             bitsPerPixel, 
             bytesPerRow, 
             colorSpace, 
             kCGBitmapByteOrderDefault, 
             provider, 
             NULL, NO, kCGRenderingIntentDefault); 

UIImage *newImage = [UIImage imageWithCGImage:newCGimage]; 

CGDataProviderRelease(provider); 
CGImageRelease(newCGimage); 
CGContextRelease(context); 
CGColorSpaceRelease(colorSpace); 
free(rawData); 

return newImage; 

}

제가 몇몇 시험을 통해 정확한 화소를 획득하고 일부 잘 작동하는 것 같은 도면에 선택된 색상을 출력하고 매우 확신, I는 잔상을 작성하고있을 때 보인다 원시 데이터를 편집하는 것은 최소한 그것이 문제가 있다고 생각하는 부분입니다.

사전에 도움을 청합니다.

편집

: 지금 코드 때문에 본질적으로이하는 모든 원시 데이터에 PNG를 복사입니다 박탈 한

가에서있는 UIImage를 생성하고 설정, 기본적으로 내가 다시 똑같은 이미지를 얻을해야하며, 아무것도 변경하지합니다 . 그러나이 시간은 그냥 내가 다른 사람의 예에 따라 잘 나는 그것을 해결 한

// First get the image into your data buffer 
CGImageRef imageRef = [image CGImage]; 

NSUInteger width = CGImageGetWidth(imageRef); 
NSUInteger height = CGImageGetHeight(imageRef); 
NSUInteger bitsPerComponent = CGImageGetBitsPerComponent(imageRef); 
NSUInteger bitsPerPixel = CGImageGetBitsPerPixel(imageRef); 
NSUInteger bytesPerRow = CGImageGetBytesPerRow(imageRef); 
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef); 
CGBitmapInfo imageInfo = CGImageGetBitmapInfo(imageRef); 


unsigned char *rawData = (unsigned char*) malloc(height * width * 4); 


CGContextRef context = CGBitmapContextCreate(rawData, 
              width, 
              height, 
              bitsPerComponent, 
              bytesPerRow, 
              colorSpace, 
              imageInfo); 

//convert phone screen coords to texture coordinates. 
xx *= (width/[[UIScreen mainScreen] bounds].size.width); 
yy *= (height/[[UIScreen mainScreen] bounds].size.height); 

NSLog(@"converted X pos: %i",xx); 
NSLog(@"converted Y pos: %i",yy); 


int counter = 0; 


CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, 
                  rawData, 
                  width*height*4, 
                  NULL); 
CGImageRef newCGimage = CGImageCreate(width, 
             height, 
             bitsPerComponent, 
             bitsPerPixel, 
             bytesPerRow, 
             colorSpace, 
             imageInfo, 
             provider, 
             NULL, NO, kCGRenderingIntentDefault); 

UIImage *newImage = [[UIImage alloc]initWithCGImage:newCGimage]; 

CGDataProviderRelease(provider); 
CGImageRelease(newCGimage); 
CGContextRelease(context); 
free(rawData); 

return newImage; 

답변

1

을 다음과 같이하지 않도록 편집 코드가 때때로 당신이 지출 결국입니다입니다 알파 인 0에 이르기까지 모든 0 값 또는 인해 중, 사라져 하루 종일 내 픽셀 검사를 다시 사용하기 전에

for(int y = 0; y < height; y++) 
{ 
    byteIndex = (width * y) + x * bitsPerPixel; 

    CGFloat redVal = (rawData[byteIndex]  * 1.0)/255.0; 
    CGFloat greenVal = (rawData[byteIndex + 1] * 1.0)/255.0; 
    CGFloat blueVal = (rawData[byteIndex + 2] * 1.0)/255.0; 
    CGFloat alphaVal = (rawData[byteIndex + 3] * 1.0)/255.0; 
    byteIndex += 4; 

    if(alphaVal != 0) 
    { 
     if(redVal == red && greenVal == green && blueVal == blue) 
     { 
      rawData[byteIndex + 3] = 0; 
      counter ++; 
     } 
    } 
} 

내가 바이트 인덱스를 증가하고를 제외하고 ... 오히려 않을 것 뭔가 ... 위의 코드는 괜찮 어느 방법을 알아 내려고 , 시험 후에 그것을 움직여 라. 그러면 그것은 모두 좋다.

그림 표시 문제는 "free (rawData);를 제거하십시오. 분명히 메모리 싫어함이 풀린 것입니다.

2

EDIT 게시물에서 컨텍스트에 대해 아무 것도하지 않기 때문에 이미지가 모두 검은 색입니다. 그냥 빈 컨텍스트를 만들고 이미지로 변환하면됩니다.

또한 알고리즘의 주요 부분을 좀 더 효율적으로 만들었습니다. 배열을 반복 할 때 항상 for-loop를 행 우선 순서 (이 경우, 높이의 경우 외부 루프, 너비의 경우 내부 루프)에 배치하여 인덱스 계산을 훨씬 쉽게 수행 할 수 있습니다.

int byteIndex = (bytesPerRow * yy) + (xx * (bitsPerPixel/8)); //you want bytes, not bits, so divide the bitsPerPixel by 8 

//you don't need to do the "* 1.0/255.0" part if you are just 
//going to compare the values with other values in the same 0-255 range. 
//Only do it if something requires the values to be from 0-1 or if that 
//is how you want it to print. 
CGFloat red = (rawData[byteIndex++]; 
CGFloat green = (rawData[byteIndex++]; 
CGFloat blue = (rawData[byteIndex++]; 
CGFloat alpha = (rawData[byteIndex++]; 

//because the 2-dimensional data is in a 1-dimensional array, 
//the lines wrap as they go down, so the data reads like a book 
//with height = 0 at the top and width = 0 on the left. 
//This for loop configuration allows for easy iteration by just 
//incrementing the index while iterating. 

byteIndex = 0; 

for (int y = 0; y < height; y++) 
{ 
    for(int x = 0; x < width; x++) 
    { 
     //Incrementing byteIndex like this makes it go to the correct 
     //position for the next loop cycle. 

     //Do not multiply by one unless you want maximum readability. 
     //If you were trying to get out of doing integer division, 
     //multiplying by one isn't necessary because the 255.0 not an integer. 
     //Because multiplying by one is executed at run-time, it hogs 
     //the CPU for a little bit. To overcome this, cast if you really 
     //have to, because casting is a compile time operation, 
     //not a run-time one, giving more performance. 

     CGFloat redVal = rawData[byteIndex++]; 
     CGFloat greenVal = rawData[byteIndex++]; 
     CGFloat blueVal = rawData[byteIndex++]; 
     CGFloat alphaVal = rawData[byteIndex++]; 

     //you can combine the if statements into one because of short-circuiting 

     if(alphaVal != 0 && redVal == red && greenVal == green && blueVal == blue) 
     { 
      rawData[byteIndex-1] = 0; 
      counter ++; 
     } 
    } 
} 

는 희망이 도움이!