Objectiv-C przyspieszenie kodu

0

Robię aplikacje która w ciągu sekundy robi parenaście zdjęć pulpitu. Do robienia zrzutów wykorzystuję ten kodL

- (NSImage*) captureScreen 
{
	int bitsPP, w, h;
	int bytesPerRow, bytesPerPixel, numRowBytes;
	unsigned char* srcPixels;
	unsigned char* dstPixels;
	unsigned long index, pRow, srcPix, dstPix, rowLen;
	NSImage* resImg;
	NSBitmapImageRep* bmapRep;

	// screen width & height
	w = CGDisplayPixelsWide(kCGDirectMainDisplay );
	h = CGDisplayPixelsHigh(kCGDirectMainDisplay );
	srcPixels = (unsigned char*) CGDisplayBaseAddress(kCGDirectMainDisplay);
	dstPixels = (unsigned char*) malloc( w * h * 4);
	bitsPP = CGDisplayBitsPerPixel(kCGDirectMainDisplay);
	bytesPerRow = CGDisplayBytesPerRow(kCGDirectMainDisplay);
	bytesPerPixel = bitsPP >> 3;

	if ( dstPixels != 0 ) 
	{
		int y;

		numRowBytes = (w * 4);
		for (y=0; y < h; y++) 
		{
			rowLen = (unsigned long)(y * bytesPerRow);

			for (index=0; index < w; index++) 
			{
				pRow = (index * bytesPerPixel) + rowLen;
				srcPix = *((unsigned long*)(srcPixels + pRow));
				dstPix = (srcPix >> 24) | ((srcPix & 0x00FFFFFF) << 8);
				*((unsigned long*)(dstPixels + pRow)) = dstPix;
			} 
		}
	}
	
	bmapRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&dstPixels
		pixelsWide:w
		pixelsHigh:h	 bitsPerSample:8
		samplesPerPixel:4
		hasAlpha:YES
		isPlanar:NO
		colorSpaceName:NSDeviceRGBColorSpace
		bytesPerRow:numRowBytes
	bitsPerPixel:32];

	resImg = [[NSImage alloc] initWithSize:[bmapRep size]];
	if ( resImg != nil ) 
	{
		[resImg addRepresentation:bmapRep];
	} else {
		NSLog(@"Image is nil");
	}
	[bmapRep release];
	return resImg;
} 

Jednak ta metoda daje mi bardzo mały FPS(ledwie klatka na sekunde) więc po chcąc zoptymalizować podzieiłem to na dwie fazy. Podczas startu programu:

@implementation AppController
	
unsigned char* srcPixels;
	unsigned char* dstPixels;
    unsigned int indeks, pRow, srcPix, dstPix, rowLen, _u;
	int bitsPP, w, h;
	int bytesPerRow, bytesPerPixel, numRowBytes;
	NSImage* resImg;
	NSBitmapImageRep* bmapRep;
	
- (void) awakeFromNib
{
	//Główne informacje zbieranie itp...
	w = CGDisplayPixelsWide(kCGDirectMainDisplay );
	h = CGDisplayPixelsHigh(kCGDirectMainDisplay );
	srcPixels = (unsigned char*) CGDisplayBaseAddress(kCGDirectMainDisplay);
	dstPixels = (unsigned char*) malloc( w * h * 4);
	bitsPP = CGDisplayBitsPerPixel(kCGDirectMainDisplay);
	bytesPerRow = CGDisplayBytesPerRow(kCGDirectMainDisplay);
	bytesPerPixel = bitsPP >> 3;
	numRowBytes = (w * 4);
	
	
}

oraz tą właściwą:

- (NSImage*) captureScreen 
{

		
		for (y=0; y < h; y++) 
		{
			rowLen = y * bytesPerRow;

			for (indeks=0; indeks < w; indeks++) 
			{
				pRow = (indeks * bytesPerPixel) + rowLen;
				srcPix = *((int*)(srcPixels + pRow));
				dstPix = (srcPix >> 24) | ((srcPix & 0x00FFFFFF) << 8);
				*((int*)(dstPixels + pRow)) = dstPix;
			} 
		}
	
	
	bmapRep = [[NSBitmapImageRep alloc] 
		initWithBitmapDataPlanes:&dstPixels
		pixelsWide:w
		pixelsHigh:h	
		bitsPerSample:8
		samplesPerPixel:4
		hasAlpha:YES
		isPlanar:NO
		colorSpaceName:NSDeviceRGBColorSpace
		bytesPerRow:numRowBytes
	bitsPerPixel:32];

	resImg = [[NSImage alloc] initWithSize:[bmapRep size]];
	[resImg addRepresentation:bmapRep];
	return resImg;
} 

Jednak udało mi się zwiększyć tylko FPS o 3, 4 klatki. Po dokładnej analizie zauważyłem że najwięcej czasu zajmuje przemulenie tych linijek

				srcPix = *((int*)(srcPixels + pRow));
				*((int*)(dstPixels + pRow)) = dstPix;

Jako że objectiv-C zbyt dobrze do końca nie pojełem to zdaje mi się że jest tu chyba jakieś rzutowanie. Wie może ktoś jak by się dało przyspieszyć ten kod?

0

Nie prościej tak???

char*	src_ptr=srcPixels;	 
char*	dst_ptr=dstPixels;	 
	
for (y=0; y<h; y++) 
{
	memcpy(dst_ptr,src_ptr,bytesPerRow);
	src_ptr+=bytesPerRow;
	dst_ptr+=bytesPerRow;
}

Zasadniczo jeżeli formaty bitmap są te same to wszystko można załatwić jednym wywołaniem memcpy.

0

ten twój kod powoduje zawieszanie się programu...

0

Heh, nie zauważyłem, że coś tam się jeszcze robi z pixelami :P

Może to:

int x_beg=0;
int x_end;
int y_beg=0;
int y_end;

y_end=bytesPerRow*h;

while(y_beg<y_end)
{
	x_beg=y_beg;
	x_end=x_beg+bytesPerRow;
	
	while(x_beg<x_end)
	{
		srcPix = *((int*)(srcPixels+x_beg));
		*((int*)(dstPixels + x_beg)) = (srcPix >> 24) | ((srcPix & 0x00FFFFFF) << 8);
		x_beg+=bytesPerPixel;
	} 
	
	y_beg=x_end;
}

PS. nie testowałem więc działać nie musi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1