VNC demo have some black Lines - ios

I wanna to build a VNC client project in iPad,but when i'm using NPDeskTop demo ,i found that when the picture changes, the screen on iPad maybe show some black lines. I want to know how to fix it.
Here is the demo adress: enter link description here

int bytesPerPixel = (pixelFormat.bitsPerPixel + 7) >> 3;
CGContextTranslateCTM(ctx, 0, _size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
// FIXME: rect origin can be negative?
uint32_t *start = (uint32_t *)_buffer.bytes;
int bytesPerRow = _size.width * bytesPerPixel;
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
CGContextRef bmpctx = CGBitmapContextCreate(start, _size.width, _size.height,8 , bytesPerRow, cs, kCGImageAlphaNoneSkipFirst);
CGImageRef image = CGBitmapContextCreateImage(bmpctx);
CGContextDrawImage(ctx, rect, image);
CGImageRelease(image);
CGColorSpaceRelease(cs);
CGContextRelease(bmpctx);
here is my create view func.

Related

Fastest and most effiecient way to find out non-transparent pixel of UIImage on iOS

I want to ask about image processing mechanism. I develop an iOS app which using OpenGLES for hand-writing on a view. I have a function save that convert a view with all drawing to an Image and save to Photo Library.
I can properly convert content of view to image easily using below code
(Note: The following code is not the problem. Its purpose is just to convert content of view to image and it worked perfect, but I show here for reference)
// Get the size of the backing CAEAGLLayer
NSInteger x = 0, y = 0, width = backingWidth, height = backingHeight;
NSInteger dataLength = width * height * 4;
GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));
// Read pixel data from the framebuffer
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
// Create a CGImage with the pixel data
// If your OpenGL ES content is opaque, use kCGImageAlphaNoneSkipLast to ignore the alpha channel
// otherwise, use kCGImageAlphaPremultipliedLast
CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGImageRef iref = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
ref, NULL, true, kCGRenderingIntentDefault);
// OpenGL ES measures data in PIXELS
// Create a graphics context with the target size measured in POINTS
NSInteger widthInPoints, heightInPoints;
if (NULL != &UIGraphicsBeginImageContextWithOptions) {
// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
// Set the scale parameter to your OpenGL ES view's contentScaleFactor
// so that you get a high-resolution snapshot when its value is greater than 1.0
CGFloat scale = self.contentScaleFactor;
widthInPoints = width / scale;
heightInPoints = height / scale;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(widthInPoints, heightInPoints), NO, scale);
} else {
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
}
CGContextRef cgcontext = UIGraphicsGetCurrentContext();
// UIKit coordinate system is upside down to GL/Quartz coordinate system
// Flip the CGImage by rendering it to the flipped bitmap context
// The size of the destination area is measured in POINTS
CGContextSetBlendMode(cgcontext, kCGBlendModeCopy);
CGContextDrawImage(cgcontext, CGRectMake(0.0, 0.0, widthInPoints, heightInPoints), iref);
// Retrieve the UIImage from the current context
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Clean up
free(data);
CFRelease(ref);
CFRelease(colorspace);
CGImageRelease(iref);
return image;
The problem is I want to determine if the view has any drawing or not. If no drawing -> can't save because saving a blank image is useless so my thinking is to check if image has any non-transparent pixel or not
My solution
Convert my drawing view to Image (its pixels have alpha channel)
Check if the Image has any non-zero alpha channel pixel
If yes, user properly draws something -> can Save
If no, user not draws anything or user erases everything -> not Save
I know the BruteForce algorithim to go through all pixels but it seems the worst way and just be implemented if there is no other efficient ways
So is there any efficient way to check it
I found that the BruteForce algorithm is not slower as I though. It just take about less than 200 miliseconds to go through all pixel datas of an image has size of iPad Pro as well as iPad mini 2
So I though using BruteForce is acceptable
Following is code to check
CGImageRef imageRef = [selfImage CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
float total = width * height * 4;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = (unsigned char*) calloc(total, sizeof(unsigned char));
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef tempContext = CGBitmapContextCreate(rawData, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(tempContext, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(tempContext);
// Now your rawData contains the image data in the RGBA8888 pixel format
BOOL empty = YES;
for (int i = 0 ; i < total ;) {
CGFloat alpha = ((CGFloat) rawData[i + 3] ) / 255.0f;
// CGFloat red = ((CGFloat) rawData[i] ) / alpha;
// CGFloat green = ((CGFloat) rawData[i + 1] ) / alpha;
// CGFloat blue = ((CGFloat) rawData[i + 2] ) / alpha;
i += bytesPerPixel;
if (alpha != 0) {
empty = NO;
break;
}
}
if (empty) {
//Do something
} else {
//Do other thing
}
If is there any improvement or other effiecient algorithms, please post here, I really appreciate

Compositing image using Core Graphics and retaining the alpha channel

I have a PNG (complete with alpha channel) that I'm looking to composite onto a CGContextRef using CGContextDrawImage. I'd like the RBG channels to be composited, but I'd also like for the source images alpha channel to be copied over as well.
Ultimately I'll be passing the final CGContextRef (in the form of a CGImageRef) to GLKit where I'm hoping to manipulate the alpha channel for colour tinting purposes using a fragment shader.
Unfortunately I'm running into issues when it comes to creating my texture atlas using Core Graphics. It appears that the final CGImageRef fails to copy over the alpha channel from my source image and is non-transparent. I've attached my current compositing code, and a copy of my test image below:
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UInt8 * m_PixelBuf = malloc(sizeof(UInt8) * atlasSize.height * atlasSize.width * 4);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * atlasSize.width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(m_PixelBuf,
atlasSize.width,
atlasSize.height,
bitsPerComponent,
bytesPerRow,
colorSpace
kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(context, CGRectMake(x, y, image.size.width, image.size.height), image.CGImage);
CGImageRef imgRef = CGBitmapContextCreateImage(context);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
Where do you people find this procedures of using CGBitmapContextCreate as this is one of the most common issues: kCGImageAlphaPremultipliedFirst will set the alpha to 1 and PREMULTIPLY RGB with the alpha value.
If you are using Xcode pleas command-click kCGImageAlphaPremultipliedFirst and find an appropriate replacement such as kCGImageAlphaLast.
Adding an example of using alpha as last channel:
+ (UIImage *)generateRadialGradient {
int size = 256;
uint8_t *buffer = malloc(size*size*4);
memset(buffer, 255, size*size*4);
for(int i=0; i<size; i++) {
for(int j=0; j<size; j++) {
float x = ((float)i/(float)size)*2.0f - 1.0f;
float y = ((float)j/(float)size)*2.0f - 1.0f;
float relativeRadius = x*x + y*y;
if(relativeRadius >= 0.0 && relativeRadius < 1.0) { buffer[(i*size + j)*4 + 3] = (uint8_t)((1.0-sqrt(relativeRadius))*255.0); }
else buffer[(i*size + j)*4 + 3] = 0;
}
}
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL,
buffer,
size*size*4,
NULL);
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4*size;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big|kCGImageAlphaLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef imageRef = CGImageCreate(size,
size,
bitsPerComponent,
bitsPerPixel,
bytesPerRow,
colorSpaceRef,
bitmapInfo,
provider,
NULL,
NO,
renderingIntent);
/*I get the current dimensions displayed here */
return [UIImage imageWithCGImage:imageRef];
}
So this code creates a radial gradient from code. The inner part is full opaque while it gets transparent when it gets further from center.
We could also use kCGImageAlphaFirst which results in yellowish gradient. Alpha is always at 1 and only the first (red) channel is being decreased. The result is being white in the middle and as the red channel is decreased the yellow color starts showing.

iOS find subimage in a larger image

What is the best way to find coordinates of subimages in a larger image. Subimage is very simple and always the same. For example how do I find coordinates of all black squares in the image below:
I think the best way here might be to write a function/UIImage category to check the color at a pixel in the image. Then (if you know for a fact the images are squares), you can check the color of each pixel moving down diagonally until you one is a different color (then you have the location and size of your square).
One working implementation I found for checking the color of a pixel is in the open source component OBShapedButton.
It is a UIImage category.
Code:
- (UIColor *)colorAtPixel:(CGPoint)point {
// Cancel if point is outside image coordinates
if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, self.size.width, self.size.height), point)) {
return nil;
}
// Create a 1x1 pixel byte array and bitmap context to draw the pixel into.
// Reference: http://stackoverflow.com/questions/1042830/retrieving-a-pixel-alpha-value-for-a-uiimage
NSInteger pointX = trunc(point.x);
NSInteger pointY = trunc(point.y);
CGImageRef cgImage = self.CGImage;
NSUInteger width = self.size.width;
NSUInteger height = self.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
int bytesPerPixel = 4;
int bytesPerRow = bytesPerPixel * 1;
NSUInteger bitsPerComponent = 8;
unsigned char pixelData[4] = { 0, 0, 0, 0 };
CGContextRef context = CGBitmapContextCreate(pixelData,
1,
1,
bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextSetBlendMode(context, kCGBlendModeCopy);
// Draw the pixel we are interested in onto the bitmap context
CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
CGContextRelease(context);
// Convert color values [0..255] to floats [0.0..1.0]
CGFloat red = (CGFloat)pixelData[0] / 255.0f;
CGFloat green = (CGFloat)pixelData[1] / 255.0f;
CGFloat blue = (CGFloat)pixelData[2] / 255.0f;
CGFloat alpha = (CGFloat)pixelData[3] / 255.0f;
return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}

how to perform calculations on image raw data with CoreGraphics?

I'm trying to create specific custom filter effects on image for iOS. So far, I've been trying to get raw data using CGBitmapContextCreate. However, I don't really have an idea of how to modify my rawData. I hope to perform calculations on it. I hope to effect pixel by pixel with the rawData but I have no idea how to manipulate it.
I also don't know how I can draw my bitmap context to a UIImage, so I can render the finished product on an UIImageView.
Could somebody give me some pointers to how I might be able to achieve that?
Here's my code so far:
// First get the image into your data buffer
CGImageRef imageRef = imageView.image.CGImage;
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = calloc(height * width * 4, sizeof(unsigned char));
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
//perform calculations on rawData? or context? not sure!! i hope to effect pixel by pixel.
//am i doing this correctly?
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//set the imageview with the new image
[imageView setImage:newImage];
CGContextRelease(context);
You are almost there.
You can perform your transactions on the RGB and Alpha channels via:
for (NSUInteger i = 0 ; i < rawDataSpace ; i+=4) {
rawData[i+0] = ...
rawData[i+1] = ...
rawData[i+2] = ...
rawData[i+3] = ... // = Alpha channel

iOS -- detect the color of a pixel?

For example, suppose I want to detect the color of the pixel with screen coordinates (100, 200). Is there a way to do this?
EDIT -- I'm not worried about retina display issues for now.
This may not be the most direct route, but you could:
Use UIGraphicsBeginImageContextWithOptions to grab the screen (see the Apple Q&A QA1703 - "Screen Capture in UIKit Applications").
Then use CGImageCreateWithImageInRect to grab the portion of the resultant image you require.
Finally analyse the resultant image. It gets complicated at this point, but thankfully there's an existing question that should show you the way: How to get the RGB values for a pixel on an image on the iphone
Alternatively, there's the following blog article that has accompanying code: What Color is My Pixel? Image based color picker on iPhone
Here is how to do it
CGContextRef ctx;
CGImageRef imageRef = [image CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = malloc(height * width * 4);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);
//GET PIXEL FROM POINT
int index = 4*((width*round(yCoor))+round(xCoor));
int R = rawData[index];
int G = rawData[index+1];
int B = rawData[index+2];
NSLog(#"%d %d %d", R, G, B);
//IF YOU WANT TO ALTER THE PIXELS
int byteIndex = 0;
for(int ii = 0 ; ii < width * height ; ++ii)
{
rawData[byteIndex] = (char)(newPixelValue);
rawData[byteIndex+1] = (char)(newPixelValue);
rawData[byteIndex+2] = (char)(newPixelValue);
byteIndex += 4;
}
ctx = CGBitmapContextCreate(rawData,
CGImageGetWidth( imageRef ),
CGImageGetHeight( imageRef ),
8,
CGImageGetBytesPerRow( imageRef ),
CGImageGetColorSpace( imageRef ),
kCGImageAlphaPremultipliedLast );
imageRef = CGBitmapContextCreateImage(ctx);
UIImage* rawImage = [UIImage imageWithCGImage:imageRef];
CGContextRelease(ctx);
image = rawImage;
free(rawData);
Try This One Where "self.m_imgvwSource" is the uiview/uiimageview as per your need
- (UIColor *) GetCurrentPixelColorAtPoint:(CGPoint)point
{
unsigned char pixel[4] = {0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
CGContextTranslateCTM(context, -point.x, -point.y);
[self.m_imgvwSource.layer renderInContext:context];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
NSLog(#"pixel: %d %d %d %d", pixel[0], pixel[1], pixel[2], pixel[3]);
UIColor *color = [UIColor colorWithRed:pixel[0]/255.0 green:pixel[1]/255.0 blue:pixel[2]/255.0 alpha:pixel[3]/255.0];
return color;
}

Resources