Im currently deploying a ImageScroller by UIScrollView, and it contain a filter toolbar at the bottom as you can see on the image.
But im facing a problem is that when i press the button, the filters is only apply to the last image as example below:
Gif Example
So please anyone can help me to solve this one, my expected output is the filter is applied to the current displaying image, not only the last one. Here i would attach my code for your reference and thank you so much.
#interface EditImageVC ()
#end
#implementation EditImageVC
UIImageView *img;
- (void)viewDidLoad {
[super viewDidLoad];
int x=0;
for (int i = 0; i < _scrollViewImageArray.count ; i++) {
_picture = [_scrollViewImageArray objectAtIndex:i];
img =[[UIImageView alloc]initWithFrame:CGRectMake(x,20,[[UIScreen mainScreen] bounds].size.width,
self.imgScrollView.frame.size.height)];
img.image =_picture;
x=x+[[UIScreen mainScreen] bounds].size.width;
[_imgScrollView addSubview:img];
}
_imgScrollView.backgroundColor = [UIColor blackColor];
_imgScrollView.contentSize=CGSizeMake(x,
_imgScrollView.frame.size.height);
_imgScrollView.contentOffset=CGPointMake(0, 0);
img.contentMode = UIViewContentModeScaleAspectFit;
}
-(void)viewDidLayoutSubviews{
self.automaticallyAdjustsScrollViewInsets = NO;
}
- (IBAction)filterAction:(UIButton *)sender {
for (int i = 0; i < _scrollViewImageArray.count ; i++) {
UIImage *picture = [_scrollViewImageArray objectAtIndex:i];
GPUImageFilter *selectedFilter;
switch (sender.tag) {
case 0:
selectedFilter = [[GPUImageSepiaFilter alloc] init];
break;
case 1:
selectedFilter = [[GPUImageToonFilter alloc] init];
break;
default:
break;
}
UIImage *filteredImage = [selectedFilter imageByFilteringImage:picture];
[img setImage:filteredImage];
}
}
Just filter the last shown image and when filter image when scrollview scrolled to another image.
remember to add UIScrollViewDelegate
#interface EditImageVC : UIViewController <UIScrollViewDelegate> {
}
#end
- (void)viewDidLoad {
[super viewDidLoad];
imageViewsArray = [[NSMutableArray alloc] init];
int x=0;
for (int i = 0; i < _scrollViewImageArray.count ; i++) {
_picture = [_scrollViewImageArray objectAtIndex:i];
img =[[UIImageView alloc]initWithFrame:CGRectMake(x,20,[[UIScreen mainScreen] bounds].size.width,
self.imgScrollView.frame.size.height)];
img.image =_picture;
[imageViewsArray addObject:img];
x=x+[[UIScreen mainScreen] bounds].size.width;
[self.imgScrollView addSubview:img];
}
self.imgScrollView.backgroundColor = [UIColor blackColor];
self.imgScrollView.contentSize=CGSizeMake(x,
self.imgScrollView.frame.size.height);
self.imgScrollView.contentOffset=CGPointMake(0, 0);
img.contentMode = UIViewContentModeScaleAspectFit;
self.imgScrollView.delegate = self;
}
GPUImageFilter *selectedFilter = nil;
NSInteger currentShownIndex = 0;
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSInteger indexAfterScrolled = scrollView.contentOffset.x / scrollView.frame.size.width;
if(indexAfterScrolled==currentShownIndex) return;
currentShownIndex = indexAfterScrolled;
if(selectedFilter!=nil) {
UIImage *filteredImage = [selectedFilter imageByFilteringImage:[_scrollViewImageArray objectAtIndex:currentShownIndex]];
[[imageViewsArray objectAtIndex:currentShownIndex] setImage:filteredImage];
}
}
- (IBAction)filterAction:(UIButton *)sender {
switch (sender.tag) {
case 0:
selectedFilter = [[GPUImageSepiaFilter alloc] init];
break;
case 1:
selectedFilter = [[GPUImageToonFilter alloc] init];
break;
default:
break;
}
UIImage *picture = [_scrollViewImageArray objectAtIndex:currentShownIndex];
UIImage *filteredImage = [selectedFilter imageByFilteringImage:picture];
[[imageViewsArray objectAtIndex:currentShownIndex] setImage:filteredImage];
}
Updated
If you want to filter current shown image, not need to apply UIScrollViewDelegate:
- (void)viewDidLoad {
[super viewDidLoad];
imageViewsArray = [[NSMutableArray alloc] init];
int x=0;
for (int i = 0; i < _scrollViewImageArray.count ; i++) {
_picture = [_scrollViewImageArray objectAtIndex:i];
img =[[UIImageView alloc]initWithFrame:CGRectMake(x,20,[[UIScreen mainScreen] bounds].size.width,
self.imgScrollView.frame.size.height)];
img.image =_picture;
[imageViewsArray addObject:img];
x=x+[[UIScreen mainScreen] bounds].size.width;
[self.imgScrollView addSubview:img];
}
self.imgScrollView.backgroundColor = [UIColor blackColor];
self.imgScrollView.contentSize=CGSizeMake(x,
self.imgScrollView.frame.size.height);
self.imgScrollView.contentOffset=CGPointMake(0, 0);
img.contentMode = UIViewContentModeScaleAspectFit;
self.imgScrollView.delegate = self;
}
- (IBAction)filterAction:(UIButton *)sender {
NSInteger objectAtIndex:currentShownIndex = scrollView.contentOffset.x / scrollView.frame.size.width;
GPUImageFilter *selectedFilter = nil;
switch (sender.tag) {
case 0:
selectedFilter = [[GPUImageSepiaFilter alloc] init];
break;
case 1:
selectedFilter = [[GPUImageToonFilter alloc] init];
break;
default:
break;
}
UIImage *picture = [_scrollViewImageArray objectAtIndex:currentShownIndex];
UIImage *filteredImage = [selectedFilter imageByFilteringImage:picture];
[[imageViewsArray objectAtIndex:currentShownIndex] setImage:filteredImage];
}
I implemented “swipe to delete cell in TableView” and it works fine in iOS 7 but that same code is not working for iOS 8. Is there any changes done for iOS 8 in this?
After swiping the cell I see nothing in my “Groups” section in iOS 8 while in iOS 7 I see a delete button.
Here is the code I am using:
- (void)swipeableTableViewCell:(SWTableViewCell *)cell scrollingToState: (SWCellState)state
{
switch (state) {
case 0:
NSLog(#"utility buttons closed");
[customDropDown hideDropDown:dropDownFrame];
[customDropDown removeFromSuperview];
customDropDown = nil;
break;
case 1:
NSLog(#"left utility buttons open");
break;
case 2:
NSLog(#"right utility buttons open");
break;
default:
break;
}
}
- (void)swipeableTableViewCell:(SWTableViewCell *)cell didTriggerRightUtilityButtonWithIndex:(NSInteger)index
{
switch (index)
{
case 0:
{
if (cell.rightUtilityButtons.count == 1)
{
NSArray * arr = [[NSArray alloc] init];
arr = [NSArray arrayWithArray:[self.groupsInfoDict allKeys]];
if(customDropDown == nil)
{
indexPathForSelectedcontact = [self.groupListTableView indexPathForCell:cell];
CGRect frame = [self.groupListTableView rectForRowAtIndexPath:indexPathForSelectedcontact];
CGRect animatedViewFrame = [self.view convertRect:frame fromView:self.groupListTableView];
CGFloat height = self.view.frame.size.height-(animatedViewFrame.origin.y+44);
NSString* direction;
if (height<88)
{
direction = #"up";
CGFloat noOfRowHeight = [arr count]*40;
if (noOfRowHeight <animatedViewFrame.origin.y)
{
height = noOfRowHeight;
}
else
{
height = animatedViewFrame.origin.y;
}
}
else
{
direction = #"down";
CGFloat noOfRowHeight = [arr count]*40;
if (noOfRowHeight <height)
{
height = noOfRowHeight;
}
}
dropDownFrame = CGRectMake(animatedViewFrame.origin.x, animatedViewFrame.origin.y, 160,height);
customDropDown = [[CustomDropDown alloc]showDropDown:dropDownFrame arrayOfData:arr ArrayOfimages:nil inDirection:direction onView:self.view];
customDropDown.delegate = self;
}
else
{
[customDropDown hideDropDown:dropDownFrame];
[customDropDown removeFromSuperview];
dropDownFrame = CGRectZero;
customDropDown = nil;
}
}
else
{
NSIndexPath* indexpath = [self.groupListTableView indexPathForCell:cell];
NSArray* arrayOfKeys = (NSArray *)self.groupsInfoDict.allKeys;
NSArray *sortedValues = [arrayOfKeys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
groupTitleSelectedForRename = [sortedValues objectAtIndex:indexpath.row];
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"Events" bundle:nil];
AddANewGroupViewController *addANewGroupViewController = [storyboard instantiateViewControllerWithIdentifier:#"AddANewGroupViewController"];
addANewGroupViewController.screenType = kScreenEditGroup;
addANewGroupViewController.useTableIndex = YES;
addANewGroupViewController.allowSearchControl = YES;
addANewGroupViewController.groupTitleSelectedForRename = groupTitleSelectedForRename;
[self.navigationController pushViewController:addANewGroupViewController animated:YES];
//[self getGroupNameAlert:groupTitleSelectedForRename ifAlreadyExists:NO];
}
break;
}
case 1:
{
NSIndexPath* indexPath = [self.groupListTableView indexPathForCell:cell];
// Change the cell appearance
NSArray* arrayOfKeys = (NSArray *)self.groupsInfoDict.allKeys;
NSArray *sortedValues = [arrayOfKeys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
selectedGroupKey = [sortedValues objectAtIndex:indexPath.row];
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"" message:#"Are you sure you want to delete this group?" delegate:self cancelButtonTitle:#"NO" otherButtonTitles:#"YES", nil];
[alert setTag:990];
[alert show];
break;
}
default:
break;
}
}
- (BOOL)swipeableTableViewCellShouldHideUtilityButtonsOnSwipe:(SWTableViewCell *)cell
{
// allow just one cell's utility button to be open at once
return YES;
}
- (BOOL)swipeableTableViewCell:(SWTableViewCell *)cell canSwipeToState:(SWCellState)state{
switch (state) {
case 1:
// set to NO to disable all left utility buttons appearing
return YES;
break;
case 2:
// set to NO to disable all right utility buttons appearing
return YES;
break;
default:
break;
}
return YES;
}
I Am using GPUImage.
I Want to Rotate (With 90, 180, 270, 360 degree) Image With Animation using GPUImageFilter.
Please Help.
Thanks in Advance.
Just Check What i did to do For Rotation
int tag - is defined in .h file
-(IBAction)btnRotate_Clicked:(id)sender
{
[self hideFilterView];
[self hideFontView];
[self hideEnhanceView];
if (tag == 0)
{
staticPictureOriginalOrientation = UIImageOrientationRight;
tag = 1;
}
else if (tag == 1)
{
staticPictureOriginalOrientation = UIImageOrientationDown;
tag = 2;
}
else if (tag == 2)
{
staticPictureOriginalOrientation = UIImageOrientationLeft;
tag = 3;
}
else
{
staticPictureOriginalOrientation = UIImageOrientationUp;
tag = 0;
}
UIImageOrientation orientation = staticPictureOriginalOrientation;
switch(orientation){
case UIImageOrientationUp:
[self.MimageView setFillMode:kGPUImageFillModePreserveAspectRatioAndFill];
break;
case UIImageOrientationLeft:
[self.MimageView setFillMode:kGPUImageFillModePreserveAspectRatio];
break;
case UIImageOrientationRight:
[self.MimageView setFillMode:kGPUImageFillModePreserveAspectRatio];
break;
case UIImageOrientationDown:
[self.MimageView setFillMode:kGPUImageFillModePreserveAspectRatioAndFill];
break;
default:
break;
}
[self prepareStaticFilter];
}
-(void) prepareStaticFilter
{
isImageProcessed = TRUE;
[staticPicture addTarget:filter];
if (hasBlur)
{
[filter addTarget:blurFilter];
[blurFilter addTarget:self.MimageView];
}
else
{
[filter addTarget:self.MimageView];
}
GPUImageRotationMode imageViewRotationMode = kGPUImageNoRotation;
switch (staticPictureOriginalOrientation)
{
case UIImageOrientationLeft:
imageViewRotationMode = kGPUImageRotateLeft;
break;
case UIImageOrientationRight:
imageViewRotationMode = kGPUImageRotateRight;
break;
case UIImageOrientationDown:
imageViewRotationMode = kGPUImageRotate180;
break;
default:
imageViewRotationMode = kGPUImageNoRotation;
break;
}
[filter setInputRotation:imageViewRotationMode atIndex:0];
[staticPicture processImage];
}
I created a simple calculator. Everything works great; however, if I divide by zero, I would like to show an error message. I know how to do alert popups, but I don't know how to implement it so it comes up when I divide by zero. Here is a snipped of my calculator code:
- (IBAction)buttonOperationPressed:(id)sender {
if (currentOperation == 0) result = currentNumber;
else {
switch (currentOperation) {
case 1:
result = result + currentNumber;
break;
case 2:
result = result - currentNumber;
break;
case 3:
result = result * currentNumber;
break;
case 4:
result = result / currentNumber;
break;
case 5:
currentOperation = 0;
break;
default:
break;
}
}
currentNumber = 0;
CalcDisplay.text = [NSString stringWithFormat:#"%g",result];
if ([sender tag] == 0) result = 0;
currentOperation = [sender tag];
userInTheMiddleOfEnteringDecimal = NO;
You can just add a test prior to doing the division e.g. change:
case 4:
result = result / currentNumber;
break;
to:
case 4:
if (currentNumber == 0)
// ... do alert here ...
else
result = result / currentNumber;
break;
You have to check if the second division operand is zero, and if yes, then print an error message. Don't forget, that you can't just compare double or something with ==, you have to use presicion, like this:
case 4:
if(ABS(currentNumber) < 1e-12) // most probably its zero
// your message
return;
- (IBAction)buttonOperationPressed:(id)sender {
if (currentOperation == 0) result = currentNumber;
else {
switch (currentOperation) {
case 1:
result = result + currentNumber;
break;
case 2:
result = result - currentNumber;
break;
case 3:
result = result * currentNumber;
break;
case 4:
if(currentNumber == 0){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Title" message:#"Message" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}else{
result = result / currentNumber;
}
break;
case 5:
currentOperation = 0;
break;
default:
break;
}
}
currentNumber = 0;
CalcDisplay.text = [NSString stringWithFormat:#"%g",result];
if ([sender tag] == 0) result = 0;
currentOperation = [sender tag];
userInTheMiddleOfEnteringDecimal = NO;
Please try this code, I have copied an pasted the code you have given and added some necessary lines to it which i felt would solve your issue.
I want to make a new filter like GPUImage's GPUImageTwoInputFilter.
here is my code . A base class named IFFourInputFilter, it is likely GPUImageTwoInputFilter.
#import "IFFourInputFilter.h"
NSString *const kIFFourInputTextureVertexShaderString = SHADER_STRING
(
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
attribute vec4 inputTextureCoordinate2;
attribute vec4 inputTextureCoordinate3;
attribute vec4 inputTextureCoordinate4;
varying vec2 textureCoordinate;
varying vec2 textureCoordinate2;
varying vec2 textureCoordinate3;
varying vec2 textureCoordinate4;
void main()
{
gl_Position = position;
textureCoordinate = inputTextureCoordinate.xy;
textureCoordinate2 = inputTextureCoordinate2.xy;
textureCoordinate3 = inputTextureCoordinate3.xy;
textureCoordinate4 = inputTextureCoordinate4.xy;
}
);
#implementation IFFourInputFilter
#pragma mark -
#pragma mark Initialization and teardown
- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString;
{
if (!(self = [self initWithVertexShaderFromString:kIFFourInputTextureVertexShaderString fragmentShaderFromString:fragmentShaderString]))
{
return nil;
}
return self;
}
- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShaderFromString:(NSString *)fragmentShaderString;
{
if (!(self = [super initWithVertexShaderFromString:vertexShaderString fragmentShaderFromString:fragmentShaderString]))
{
return nil;
}
inputRotation2 = kGPUImageNoRotation;
inputRotation3 = kGPUImageNoRotation;
inputRotation4 = kGPUImageNoRotation;
hasSetTexture1 = NO;
hasSetTexture2 = NO;
hasSetTexture3 = NO;
hasReceivedFrame1 = NO;
hasReceivedFrame2 = NO;
hasReceivedFrame3 = NO;
hasReceivedFrame4 = NO;
frameWasVideo1 = NO;
frameWasVideo2 = NO;
frameWasVideo3 = NO;
frameWasVideo4 = NO;
frameCheckDisabled1 = NO;
frameCheckDisabled2 = NO;
frameCheckDisabled3 = NO;
frameCheckDisabled4 = NO;
frameTime1 = kCMTimeInvalid;
frameTime2 = kCMTimeInvalid;
frameTime3 = kCMTimeInvalid;
frameTime4 = kCMTimeInvalid;
runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageOpenGLESContext useImageProcessingContext];
filterTextureCoordinateAttribute2 = [filterProgram attributeIndex:#"inputTextureCoordinate2"];
filterInputTextureUniform2 = [filterProgram uniformIndex:#"inputImageTexture2"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
glEnableVertexAttribArray(filterTextureCoordinateAttribute2);
filterTextureCoordinateAttribute3 = [filterProgram attributeIndex:#"inputTextureCoordinate3"];
filterInputTextureUniform3 = [filterProgram uniformIndex:#"inputImageTexture3"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
glEnableVertexAttribArray(filterTextureCoordinateAttribute3);
filterTextureCoordinateAttribute4 = [filterProgram attributeIndex:#"inputTextureCoordinate4"];
filterInputTextureUniform4 = [filterProgram uniformIndex:#"inputImageTexture4"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
glEnableVertexAttribArray(filterTextureCoordinateAttribute4);
});
return self;
}
- (void)initializeAttributes;
{
[super initializeAttributes];
[filterProgram addAttribute:#"inputTextureCoordinate2"];
[filterProgram addAttribute:#"inputTextureCoordinate3"];
[filterProgram addAttribute:#"inputTextureCoordinate4"];
}
- (void)disableFrameCheck1;
{
frameCheckDisabled1 = YES;
}
- (void)disableFrameCheck2;
{
frameCheckDisabled2 = YES;
}
- (void)disableFrameCheck3;
{
frameCheckDisabled3 = YES;
}
- (void)disableFrameCheck4;
{
frameCheckDisabled4 = YES;
}
#pragma mark -
#pragma mark Rendering
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates sourceTexture:(GLuint)sourceTexture;
{
if (self.preventRendering)
{
return;
}
[GPUImageOpenGLESContext setActiveShaderProgram:filterProgram];
[self setUniformsForProgramAtIndex:0];
[self setFilterFBO];
glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, sourceTexture);
glUniform1i(filterInputTextureUniform, 2);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, filterSourceTexture2);
glUniform1i(filterInputTextureUniform2, 3);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, filterSourceTexture3);
glUniform1i(filterInputTextureUniform3, 4);
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D, filterSourceTexture4);
glUniform1i(filterInputTextureUniform4, 5);
glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates);
glVertexAttribPointer(filterTextureCoordinateAttribute2, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:inputRotation2]);
glVertexAttribPointer(filterTextureCoordinateAttribute3, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:inputRotation3]);
glVertexAttribPointer(filterTextureCoordinateAttribute4, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:inputRotation4]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
- (void)releaseInputTexturesIfNeeded;
{
if (shouldConserveMemoryForNextFrame)
{
[firstTextureDelegate textureNoLongerNeededForTarget:self];
[textureDelegate2 textureNoLongerNeededForTarget:self];
[textureDelegate3 textureNoLongerNeededForTarget:self];
[textureDelegate4 textureNoLongerNeededForTarget:self];
shouldConserveMemoryForNextFrame = NO;
}
}
#pragma mark -
#pragma mark GPUImageInput
- (NSInteger)nextAvailableTextureIndex;
{
if (!hasSetTexture1){
return 0;
}else if (!hasSetTexture2) {
return 1;
}else if (!hasSetTexture3) {
return 2;
}else{
return 3;
}
}
- (void)setInputTexture:(GLuint)newInputTexture atIndex:(NSInteger)textureIndex;
{
switch (textureIndex) {
case 0:
filterSourceTexture = newInputTexture;
hasSetTexture1 = YES;
break;
case 1:
filterSourceTexture2 = newInputTexture;
hasSetTexture2 = YES;
break;
case 2:
filterSourceTexture3 = newInputTexture;
hasSetTexture3 = YES;
break;
case 3:
filterSourceTexture4 = newInputTexture;
break;
default:
break;
}
}
- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex;
{
if (textureIndex == 0)
{
[super setInputSize:newSize atIndex:textureIndex];
if (CGSizeEqualToSize(newSize, CGSizeZero))
{
hasSetTexture1 = NO;
}
}
}
- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex;
{
switch (textureIndex) {
case 0:
inputRotation = newInputRotation;
break;
case 1:
inputRotation2 = newInputRotation;
break;
case 2:
inputRotation3 = newInputRotation;
break;
case 3:
inputRotation4 = newInputRotation;
break;
default:
break;
}
}
- (CGSize)rotatedSize:(CGSize)sizeToRotate forIndex:(NSInteger)textureIndex;
{
CGSize rotatedSize = sizeToRotate;
GPUImageRotationMode rotationToCheck;
switch (textureIndex) {
case 0:
rotationToCheck = inputRotation;
break;
case 1:
rotationToCheck = inputRotation2;
break;
case 2:
rotationToCheck = inputRotation3;
break;
case 3:
rotationToCheck = inputRotation4;
break;
default:
break;
}
if (GPUImageRotationSwapsWidthAndHeight(rotationToCheck))
{
rotatedSize.width = sizeToRotate.height;
rotatedSize.height = sizeToRotate.width;
}
return rotatedSize;
}
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
{
outputTextureRetainCount = [targets count];
// You can set up infinite update loops, so this helps to short circuit them
if (hasReceivedFrame1 && hasReceivedFrame2 && hasReceivedFrame3 && hasReceivedFrame4)
{
return;
}
BOOL updatedMovieFrameOppositeStillImage = NO;
switch (textureIndex) {
case 0:
hasReceivedFrame1 = YES;
frameTime1 = frameTime;
if (frameCheckDisabled2)
{
hasReceivedFrame2 = YES;
}
if (frameCheckDisabled3)
{
hasReceivedFrame3 = YES;
}
if (frameCheckDisabled4)
{
hasReceivedFrame4 = YES;
}
if (!CMTIME_IS_INDEFINITE(frameTime))
{
if (CMTIME_IS_INDEFINITE(frameTime2) && CMTIME_IS_INDEFINITE(frameTime3) && CMTIME_IS_INDEFINITE(frameTime4))
{
updatedMovieFrameOppositeStillImage = YES;
}
}
break;
case 1:
hasReceivedFrame2 = YES;
frameTime2 = frameTime;
if (frameCheckDisabled1)
{
hasReceivedFrame1 = YES;
}
if (frameCheckDisabled3)
{
hasReceivedFrame3 = YES;
}
if (frameCheckDisabled4)
{
hasReceivedFrame4 = YES;
}
if (!CMTIME_IS_INDEFINITE(frameTime))
{
if (CMTIME_IS_INDEFINITE(frameTime1) && CMTIME_IS_INDEFINITE(frameTime3) && CMTIME_IS_INDEFINITE(frameTime4))
{
updatedMovieFrameOppositeStillImage = YES;
}
}
break;
case 2:
hasReceivedFrame3 = YES;
frameTime3 = frameTime;
if (frameCheckDisabled1)
{
hasReceivedFrame1 = YES;
}
if (frameCheckDisabled2)
{
hasReceivedFrame2 = YES;
}
if (frameCheckDisabled4)
{
hasReceivedFrame4 = YES;
}
if (!CMTIME_IS_INDEFINITE(frameTime))
{
if (CMTIME_IS_INDEFINITE(frameTime1) && CMTIME_IS_INDEFINITE(frameTime2) && CMTIME_IS_INDEFINITE(frameTime4))
{
updatedMovieFrameOppositeStillImage = YES;
}
}
break;
case 3:
hasReceivedFrame4 = YES;
frameTime4 = frameTime;
if (frameCheckDisabled1)
{
hasReceivedFrame1 = YES;
}
if (frameCheckDisabled3)
{
hasReceivedFrame3 = YES;
}
if (frameCheckDisabled2)
{
hasReceivedFrame2 = YES;
}
if (!CMTIME_IS_INDEFINITE(frameTime))
{
if (CMTIME_IS_INDEFINITE(frameTime1) && CMTIME_IS_INDEFINITE(frameTime3) && CMTIME_IS_INDEFINITE(frameTime2))
{
updatedMovieFrameOppositeStillImage = YES;
}
}
break;
default:
break;
}
// || (hasReceivedFirstFrame && secondFrameCheckDisabled) || (hasReceivedSecondFrame && firstFrameCheckDisabled)
if ((hasReceivedFrame1 && hasReceivedFrame2 && hasReceivedFrame3 && hasReceivedFrame4) || updatedMovieFrameOppositeStillImage)
{
[super newFrameReadyAtTime:frameTime atIndex:0];
hasReceivedFrame1 = NO;
hasReceivedFrame2 = NO;
hasReceivedFrame3 = NO;
hasReceivedFrame4 = NO;
}
}
- (void)setTextureDelegate:(id<GPUImageTextureDelegate>)newTextureDelegate atIndex:(NSInteger)textureIndex;
{
switch (textureIndex) {
case 0:
firstTextureDelegate = newTextureDelegate;
break;
case 1:
textureDelegate2 = newTextureDelegate;
break;
case 2:
textureDelegate3 = newTextureDelegate;
break;
case 3:
textureDelegate4 = newTextureDelegate;
break;
default:
break;
}
}
#end
A class named IFAmaroFilter extend IFFourInputFilter.
#import "IFAmaroFilter.h"
NSString *const kIFAmaroFilterFragmentShaderString = SHADER_STRING
(
precision lowp float;
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform sampler2D inputImageTexture2; //blowout;
uniform sampler2D inputImageTexture3; //overlay;
uniform sampler2D inputImageTexture4; //map
void main()
{
vec4 texel = texture2D(inputImageTexture, textureCoordinate);
vec3 bbTexel = texture2D(inputImageTexture2, textureCoordinate).rgb;
texel.r = texture2D(inputImageTexture3, vec2(bbTexel.r, texel.r)).r;
texel.g = texture2D(inputImageTexture3, vec2(bbTexel.g, texel.g)).g;
texel.b = texture2D(inputImageTexture3, vec2(bbTexel.b, texel.b)).b;
vec4 mapped;
mapped.r = texture2D(inputImageTexture4, vec2(texel.r, 0.16666)).r;
mapped.g = texture2D(inputImageTexture4, vec2(texel.g, .5)).g;
mapped.b = texture2D(inputImageTexture4, vec2(texel.b, .83333)).b;
mapped.a = 1.0;
gl_FragColor = texel;
}
);
#implementation IFAmaroFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kIFAmaroFilterFragmentShaderString]))
{
return nil;
}
return self;
}
#end
when I use the filter I got a black output. code below:
filter = [[IFAmaroFilter alloc] init];
GPUImagePicture *gp1 = [[GPUImagePicture alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"blackboard1024" ofType:#"png"]]];
GPUImagePicture *gp2 = [[GPUImagePicture alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"overlayMap" ofType:#"png"]]];
GPUImagePicture *gp3 = [[GPUImagePicture alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"amaroMap" ofType:#"png"]]];
[stillCamera addTarget:filter atTextureLocation:0];
[gp1 addTarget:filter atTextureLocation:1];
[gp1 processImage];
[gp2 addTarget:filter atTextureLocation:2];
[gp2 processImage];
[gp3 addTarget:filter atTextureLocation:3];
[gp3 processImage];
[filter addTarget:(GPUImageView *)self.view];
I found the GPUImagePicture will be auto release, so the filter will not receive the texture.
If u met the same question, check the texture's life control carefully, watch when they be dealloc.
I agree with ZhouQi's answer, but I'd like to clarify a bit.
You need to have a GPUImagePicture property in your interface declaration so that your GPUImagePictureObject isn't autoreleased right away.
In your interface declaration:
#property (strong, nonatomic) GPUImagePicture *sourcePicture;
In your implementation:
UIImage *inputImage = [UIImage imageNamed:#"MyPicture.png"];
_sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage
smoothlyScaleOutput:YES];
[_sourcePicture processImage];
[_videoCamera addTarget:_myFilter];
[_sourcePicture addTarget:_myFilter];
[_myFilter addTarget:_myView];
Check out any of the blend filters in the Filter Showcase example project here:
https://github.com/BradLarson/GPUImage/tree/master/examples/iOS/FilterShowcase
I had try to use this shader to merge my three video to make MV effect
filter0 = [[GPUImageThreeInputFilter alloc] initWithFragmentShaderFromString:#"\nprecision highp float;\nuniform sampler2D inputImageTexture; //video\nuniform sampler2D inputImageTexture2; //mv\nuniform sampler2D inputImageTexture3; //alpha\nvarying vec2 textureCoordinate;\nvoid main()\n{\nvec4 video = texture2D(inputImageTexture, textureCoordinate);\nvec4 mv = texture2D(inputImageTexture2, textureCoordinate);\nvec4 alpha = texture2D(inputImageTexture3, textureCoordinate);\ngl_FragColor = video * (1.0 - alpha.r) + mv;\n}"];
I have same issue , could you tell me some idea ?