2014年7月21日月曜日
2014年4月24日木曜日
10fpsで動画を作成
- (void)writeImagesAsMovie:(NSArray *)images
toPath:(NSString *)path
{
NSParameterAssert(images);
NSParameterAssert(path);
NSAssert((images.count > 0), @"Set least one image.");
NSFileManager *fileManager = [NSFileManager defaultManager];
// 既にファイルがある場合は削除する
if ([fileManager fileExistsAtPath:path]) {
[fileManager removeItemAtPath:path error:nil];
}
// 最初の画像から動画のサイズ指定する
CGSize size = ((UIImage *)images[0]).size;
NSError *error = nil;
self.videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path]
fileType:AVFileTypeQuickTimeMovie
error:&error];
if (error) {
NSLog(@"%@", [error localizedDescription]);
return;
}
NSDictionary *outputSettings =
@{
AVVideoCodecKey : AVVideoCodecH264,
AVVideoWidthKey : @(size.width),
AVVideoHeightKey : @(size.height),
};
AVAssetWriterInput *writerInput = [AVAssetWriterInput
assetWriterInputWithMediaType:AVMediaTypeVideo
outputSettings:outputSettings];
[self.videoWriter addInput:writerInput];
NSDictionary *sourcePixelBufferAttributes =
@{
(NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32ARGB),
(NSString *)kCVPixelBufferWidthKey : @(size.width),
(NSString *)kCVPixelBufferHeightKey : @(size.height),
};
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor
assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
sourcePixelBufferAttributes:sourcePixelBufferAttributes];
writerInput.expectsMediaDataInRealTime = YES;
// 動画生成開始
if (![self.videoWriter startWriting]) {
NSLog(@"Failed to start writing.");
return;
}
[self.videoWriter startSessionAtSourceTime:kCMTimeZero];
CVPixelBufferRef buffer = NULL;
int frameCount = 0;
double durationForEachImage = 0.05;
int32_t fps = 20;
for (UIImage *image in images) {
if (adaptor.assetWriterInput.readyForMoreMediaData) {
//CMTime frameTime = CMTimeMake((int64_t)frameCount * fps * durationForEachImage, fps);
//CMTime frameTime = CMTimeMake((int64_t)frameCount * 60, 600);
CMTime frameTime = CMTimeMake(1, 10);
CMTime lastTime=CMTimeMake(frameCount, 10);
CMTime presentTime=CMTimeAdd(lastTime, frameTime);
buffer = [self pixelBufferFromCGImage:image.CGImage];
if (![adaptor appendPixelBuffer:buffer withPresentationTime:presentTime]) {
NSLog(@"Failed to append buffer. [image : %@]", image);
}
if(buffer) {
CVBufferRelease(buffer);
}
frameCount++;
NSLog(@"%d",frameCount);
}
}
// 動画生成終了
[writerInput markAsFinished];
[self.videoWriter finishWritingWithCompletionHandler:^{
NSLog(@"Finish writing!");
NSURL *url = [NSURL URLWithString:path];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:url])
{
[library writeVideoAtPathToSavedPhotosAlbum:url
completionBlock:^(NSURL *assetURL, NSError *assetError)
{
if (assetError) { }
}];
}
}];
CVPixelBufferPoolRelease(adaptor.pixelBufferPool);
}
- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image
{
NSDictionary *options = @{
(NSString *)kCVPixelBufferCGImageCompatibilityKey : @(YES),
(NSString *)kCVPixelBufferCGBitmapContextCompatibilityKey: @(YES),
};
CVPixelBufferRef pxbuffer = NULL;
CVPixelBufferCreate(kCFAllocatorDefault,
CGImageGetWidth(image),
CGImageGetHeight(image),
kCVPixelFormatType_32ARGB,
(__bridge CFDictionaryRef)options,
&pxbuffer);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata,
CGImageGetWidth(image),
CGImageGetHeight(image),
8,
4 * CGImageGetWidth(image),
rgbColorSpace,
(CGBitmapInfo)kCGImageAlphaNoneSkipFirst);
CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, CGImageGetHeight(image));
CGContextConcatCTM(context, flipVertical);
CGAffineTransform flipHorizontal = CGAffineTransformMake(-1.0, 0.0, 0.0, 1.0, CGImageGetWidth(image), 0.0);
CGContextConcatCTM(context, flipHorizontal);
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
5フレームごとにUIImageを取り出す
if(saveMode){
if([images count] < 50){
if(saveTime == 0){
[images addObject:[self createImage]];
}
saveTime++;
if (saveTime == 3)saveTime = 0;
NSLog(@"%d",[images count]);
}else{
saveMode = false;
NSString *documentPath = (NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]);
NSString *moviePath = [documentPath stringByAppendingPathComponent:@"movie.mov"];
[self writeImagesAsMovie:(NSArray *)images
toPath:moviePath];
}
}
OpenGLの描画内容を画像にする
-(UIImage *)createImage{
int backingWidth = self.view.bounds.size.width; // OpenGLのバッファの幅
int backingHeight = self.view.bounds.size.height; // OpenGLのバッファの高さ
NSInteger myDataLength = backingWidth * backingHeight * 4;
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, backingWidth, backingHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// FIXME:上下をひっくり返す。この処理が勿体ない。
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
for(int y = 0; y <backingHeight; y++)
{
memcpy(&buffer2[((backingHeight-1) - y) * backingWidth * 4], &buffer[y * 4 * backingWidth], sizeof(GLubyte) * backingWidth * 4);
}
free(buffer);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, myDataLength, NULL);
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGImageRef imageRef = CGImageCreate(backingWidth, backingHeight, 8, 32, 4 * backingWidth, colorSpaceRef, kCGBitmapByteOrderDefault, provider, NULL, NO, kCGRenderingIntentDefault);
UIImage *image = [UIImage imageWithCGImage:imageRef];
return image;
}
カメラロールに保存
[library writeImageToSavedPhotosAlbum:image.CGImage
orientation:(ALAssetOrientation)image.imageOrientation
completionBlock:
^(NSURL *assetURL, NSError *error){
NSLog(@"URL:%@", assetURL);
NSLog(@"error:%@", error);
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
if (status == ALAuthorizationStatusDenied) {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:@"エラー"
message:@"写真へのアクセスが許可されていません。\n設定 > 一般 > 機能制限で許可してください。"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
} else {
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:@""
message:@"フォトアルバムへ保存しました。"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
}
}];
2014年3月12日水曜日
似非マウス回転
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(eye.fovy, (float)eye.width/(float)eye.height, 0.1, 100000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eye.eye[0], eye.eye[1], eye.eye[2],
eye.center[0], eye.center[1], eye.center[2],
eye.up[0], eye.up[1], eye.up[2]);
eye.calcuratePosition(beforePoint,beforeMouse[0],beforeMouse[1]);
eye.calcuratePosition(nowPoint,x,y);
eye.rotateEye(beforePoint,nowPoint);
void Eye::calcuratePosition(double result[3],int x,int y)
{
x -= this->width/2;
y -= this->height/2;
printf("%d,%d\n",x,y);
double rate = (2.0 * 50.0 * tan(PI/180*this->fovy/2))/height;
printf("%lf\n",rate);
double rateX = x * rate;
double rateY = y * rate;
for (int i = 0;i < 3; i++){
result[i] = 50.0 * this->center[i] + rateX * this->left[i] + rateY * this->up[i];
}
}
void Eye::rotateEye(double start[3],double end[3])
{
double axis[3];
double radius;
vectorNormarise(start);
vectorNormarise(end);
exteriorProduct(start ,end, axis);
vectorNormarise(axis);
radius = acos(innerrProduct(start ,end));
printf("%lf,%lf,%lf\n",start[0],start[1],start[2]);
printf("%lf,%lf,%lf\n",end[0],end[1],end[2]);
printf("%lf,%lf,%lf,%lf\n",axis[0],axis[1],axis[2],radius);
rotateVector(axis,radius,center);
rotateVector(axis,radius,up);
rotateVector(axis,radius,left);
}
void Eye::rotateBy(double axis[3],double radius)
{
rotateVector(axis,radius,center);
rotateVector(axis,radius,up);
rotateVector(axis,radius,left);
printf("%lf,%lf,%lf\n",center[0],center[1],center[2]);
printf("%lf,%lf,%lf\n",up[0],up[1],up[2]);
printf("%lf,%lf,%lf\n",up[0],up[1],up[2]);
}
void exteriorProduct(double vec1[3],double vec2[3],double resullt[3])
{
resullt[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
resullt[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
resullt[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
}
double vectorSize(double vec[3])
{
return sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
}
void vectorNormarise(double vec1[3])
{
double size = vectorSize(vec1);
vec1[0] /= size;
vec1[1] /= size;
vec1[2] /= size;
}
double innerrProduct(double vec1[3],double vec2[3])
{
return vec1[0]*vec2[0]+vec1[1]*vec2[1]+vec1[2]*vec2[2];
}
void rotateVector(double axis[3],double radius, double vec[3])
{
double matrix[3][3];
matrix[0][0] = axis[0] * axis[0] * (1 - cos(radius)) + cos(radius);
matrix[0][1] = axis[0] * axis[1] * (1 - cos(radius)) - axis[2] * sin(radius);
matrix[0][2] = axis[2] * axis[0] * (1 - cos(radius)) + axis[1] * sin(radius);
matrix[1][0] = axis[0] * axis[1] * (1 - cos(radius)) + axis[2] * sin(radius);
matrix[1][1] = axis[1] * axis[1] * (1 - cos(radius)) + cos(radius);
matrix[1][2] = axis[1] * axis[2] * (1 - cos(radius)) - axis[0] * sin(radius);
matrix[2][0] = axis[2] * axis[0] * (1 - cos(radius)) - axis[1] * sin(radius);
matrix[2][1] = axis[1] * axis[2] * (1 - cos(radius)) + axis[0] * sin(radius);
matrix[2][2] = axis[2] * axis[2] * (1 - cos(radius)) + cos(radius);
double tmp[3];
for (int i = 0;i < 3;i++){
tmp[i] = vec[i];
}
for (int i = 0;i < 3;i++){
vec[i] = tmp[0] * matrix[i][0] + tmp[1] * matrix[i][1] + tmp[2] * matrix[i][2];
}
}
glLoadIdentity();
gluPerspective(eye.fovy, (float)eye.width/(float)eye.height, 0.1, 100000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eye.eye[0], eye.eye[1], eye.eye[2],
eye.center[0], eye.center[1], eye.center[2],
eye.up[0], eye.up[1], eye.up[2]);
eye.calcuratePosition(beforePoint,beforeMouse[0],beforeMouse[1]);
eye.calcuratePosition(nowPoint,x,y);
eye.rotateEye(beforePoint,nowPoint);
void Eye::calcuratePosition(double result[3],int x,int y)
{
x -= this->width/2;
y -= this->height/2;
printf("%d,%d\n",x,y);
double rate = (2.0 * 50.0 * tan(PI/180*this->fovy/2))/height;
printf("%lf\n",rate);
double rateX = x * rate;
double rateY = y * rate;
for (int i = 0;i < 3; i++){
result[i] = 50.0 * this->center[i] + rateX * this->left[i] + rateY * this->up[i];
}
}
void Eye::rotateEye(double start[3],double end[3])
{
double axis[3];
double radius;
vectorNormarise(start);
vectorNormarise(end);
exteriorProduct(start ,end, axis);
vectorNormarise(axis);
radius = acos(innerrProduct(start ,end));
printf("%lf,%lf,%lf\n",start[0],start[1],start[2]);
printf("%lf,%lf,%lf\n",end[0],end[1],end[2]);
printf("%lf,%lf,%lf,%lf\n",axis[0],axis[1],axis[2],radius);
rotateVector(axis,radius,center);
rotateVector(axis,radius,up);
rotateVector(axis,radius,left);
}
void Eye::rotateBy(double axis[3],double radius)
{
rotateVector(axis,radius,center);
rotateVector(axis,radius,up);
rotateVector(axis,radius,left);
printf("%lf,%lf,%lf\n",center[0],center[1],center[2]);
printf("%lf,%lf,%lf\n",up[0],up[1],up[2]);
printf("%lf,%lf,%lf\n",up[0],up[1],up[2]);
}
void exteriorProduct(double vec1[3],double vec2[3],double resullt[3])
{
resullt[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
resullt[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
resullt[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
}
double vectorSize(double vec[3])
{
return sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
}
void vectorNormarise(double vec1[3])
{
double size = vectorSize(vec1);
vec1[0] /= size;
vec1[1] /= size;
vec1[2] /= size;
}
double innerrProduct(double vec1[3],double vec2[3])
{
return vec1[0]*vec2[0]+vec1[1]*vec2[1]+vec1[2]*vec2[2];
}
void rotateVector(double axis[3],double radius, double vec[3])
{
double matrix[3][3];
matrix[0][0] = axis[0] * axis[0] * (1 - cos(radius)) + cos(radius);
matrix[0][1] = axis[0] * axis[1] * (1 - cos(radius)) - axis[2] * sin(radius);
matrix[0][2] = axis[2] * axis[0] * (1 - cos(radius)) + axis[1] * sin(radius);
matrix[1][0] = axis[0] * axis[1] * (1 - cos(radius)) + axis[2] * sin(radius);
matrix[1][1] = axis[1] * axis[1] * (1 - cos(radius)) + cos(radius);
matrix[1][2] = axis[1] * axis[2] * (1 - cos(radius)) - axis[0] * sin(radius);
matrix[2][0] = axis[2] * axis[0] * (1 - cos(radius)) - axis[1] * sin(radius);
matrix[2][1] = axis[1] * axis[2] * (1 - cos(radius)) + axis[0] * sin(radius);
matrix[2][2] = axis[2] * axis[2] * (1 - cos(radius)) + cos(radius);
double tmp[3];
for (int i = 0;i < 3;i++){
tmp[i] = vec[i];
}
for (int i = 0;i < 3;i++){
vec[i] = tmp[0] * matrix[i][0] + tmp[1] * matrix[i][1] + tmp[2] * matrix[i][2];
}
}
三角形分割
for(int i=0;i<this->target.size();i++){
this->points[i]->x = this->target[i]->x;
this->points[i]->y = this->target[i]->y;
}
count = this->target.size();
for(int i=0;i<this->target.size();i++){
this->target[i]->calcuRad(&startPoint,
this->target[this->target[i]->prevNum],
this->target[this->target[i]->nextNum]);
if(this->target[i]->radian == 0.0){
this->target[i]->life =false;
this->target[this->target[i]->prevNum]->nextNum = this->target[i]->nextNum;
this->target[this->target[i]->nextNum]->prevNum = this->target[i]->prevNum;
count--;
}
//fprintf(hoge,"%d,%d\n",(int)this->target[i]->x,(int)this->target[i]->y);
}
//fclose(hoge);
int peke;
while(count>2){
for(int i=0;i<this->target.size();i++){
if(this->target[i]->radian > 0 && this->target[i]->life){
Teto *teto = this->createFrom(i);
if (this->tetoOK(teto) && !this->otherPointsInTeto(teto))
{
this->tetos.push_back(teto);
this->drawTeto(teto,tetosImg);
this->target[this->target[i]->nextNum]->prevNum = this->target[i]->prevNum;
this->target[this->target[i]->nextNum]->calcuRad(&startPoint,
this->target[this->target[this->target[i]->nextNum]->prevNum],
this->target[this->target[this->target[i]->nextNum]->nextNum]);
this->target[this->target[i]->prevNum]->nextNum = this->target[i]->nextNum;
this->target[this->target[i]->prevNum]->calcuRad(&startPoint,
this->target[this->target[this->target[i]->prevNum]->prevNum],
this->target[this->target[this->target[i]->prevNum]->nextNum]);
this->target[i]->life = false;
count--;
char c = (char)cvWaitKey ( 1 );
cvShowImage("tetosImg",tetosImg);
i++;
}
}
}
}
this->points[i]->x = this->target[i]->x;
this->points[i]->y = this->target[i]->y;
}
count = this->target.size();
for(int i=0;i<this->target.size();i++){
this->target[i]->calcuRad(&startPoint,
this->target[this->target[i]->prevNum],
this->target[this->target[i]->nextNum]);
if(this->target[i]->radian == 0.0){
this->target[i]->life =false;
this->target[this->target[i]->prevNum]->nextNum = this->target[i]->nextNum;
this->target[this->target[i]->nextNum]->prevNum = this->target[i]->prevNum;
count--;
}
//fprintf(hoge,"%d,%d\n",(int)this->target[i]->x,(int)this->target[i]->y);
}
//fclose(hoge);
int peke;
while(count>2){
for(int i=0;i<this->target.size();i++){
if(this->target[i]->radian > 0 && this->target[i]->life){
Teto *teto = this->createFrom(i);
if (this->tetoOK(teto) && !this->otherPointsInTeto(teto))
{
this->tetos.push_back(teto);
this->drawTeto(teto,tetosImg);
this->target[this->target[i]->nextNum]->prevNum = this->target[i]->prevNum;
this->target[this->target[i]->nextNum]->calcuRad(&startPoint,
this->target[this->target[this->target[i]->nextNum]->prevNum],
this->target[this->target[this->target[i]->nextNum]->nextNum]);
this->target[this->target[i]->prevNum]->nextNum = this->target[i]->nextNum;
this->target[this->target[i]->prevNum]->calcuRad(&startPoint,
this->target[this->target[this->target[i]->prevNum]->prevNum],
this->target[this->target[this->target[i]->prevNum]->nextNum]);
this->target[i]->life = false;
count--;
char c = (char)cvWaitKey ( 1 );
cvShowImage("tetosImg",tetosImg);
i++;
}
}
}
}
登録:
投稿 (Atom)