私はEAGLViewに表示されているものからUIImageを取得しようとしています。これを行う方法に関する提案はありますか?EAGLViewからUIImageを取得するには?
答えて
EDIT:以下のdemianturnerノートでレイヤーをレンダリングする必要はなくなりました。上位レベルの[UIView drawViewHierarchyInRect:]
を使用することができます。それ以外;これは同じように動作するはずです。
EAGLView
は一種の見解であり、その基礎となるCAEAGLLayer
は単なる一種のレイヤーです。つまり、ビュー/レイヤーをUIImageに変換するためのstandard approachが機能します。 (リンク質問がのUIWebViewは問題ではないという事実;。それはちょうどビューのさらに別のようなものだ)
-(UIImage *) saveImageFromGLView
{
NSInteger myDataLength = 320 * 480 * 4;
// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, 320, 480, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// gl renders "upside down" so swap top to bottom into new array.
// there's gotta be a better way, but this works.
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
for(int y = 0; y <480; y++)
{
for(int x = 0; x <320 * 4; x++)
{
buffer2[(479 - y) * 320 * 4 + x] = buffer[y * 4 * 320 + x];
}
}
// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * 320;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
// make the cgimage
CGImageRef imageRef = CGImageCreate(320, 480, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *myImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpaceRef);
free(buffer2);
return myImage;
}
上記のコードにはいくつかのリークがありますので、代わりにBramの答えで提供されるより効率的なコードを使用することを強くお勧めします。 –
今後の開発者がこのコードをコピーして自分のアプリケーションに貼り付ける場合に備えて、Bramのコードからより重要なメモリリークの修正を取り入れました。 –
リークを修正していただきありがとうございます! –
ここQuakeboyのコードのクリーンアップバージョンです。 私はiPadでそれをテストし、うまく動作します。 改善は、次のとおりのmemcpy
- 作品ボーナスとしてphotoalbum。あなたのEAGLViewでの方法として
これを使用して:
-(void)snapUIImage
{
int s = 1;
UIScreen* screen = [ UIScreen mainScreen ];
if ([ screen respondsToSelector:@selector(scale) ])
s = (int) [ screen scale ];
const int w = self.frame.size.width;
const int h = self.frame.size.height;
const NSInteger myDataLength = w * h * 4 * s * s;
// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, w*s, h*s, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// gl renders "upside down" so swap top to bottom into new array.
// there's gotta be a better way, but this works.
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
for(int y = 0; y < h*s; y++)
{
memcpy(buffer2 + (h*s - 1 - y) * w * 4 * s, buffer + (y * 4 * w * s), w * 4 * s);
}
free(buffer); // work with the flipped buffer, so get rid of the original one.
// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * w * s;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
// make the cgimage
CGImageRef imageRef = CGImageCreate(w*s, h*s, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *myImage = [ UIImage imageWithCGImage:imageRef scale:s orientation:UIImageOrientationUp ];
UIImageWriteToSavedPhotosAlbum(myImage, nil, nil, nil);
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpaceRef);
free(buffer2);
}
上記のコードでは、色空間とデータプロバイダの一致するリリースが不足していたため、メソッドの最後に漏れを防ぐためにそれらを追加しました。 –
また、 'buffer2'は実際にリークを避けるために手動で解放する必要があります。これも修正されました。 –
私はこれを試しましたが、常に描画なしの黒い画像を作成します。何が間違っているのでしょうか? – Brodie
私は私のために正常に動作するために、ここで他の回答を得ることができませんでした。
数日後、私はついにこの問題に対する解決策を得ました。 EAGLViewからUIImageを生成するコードがAppleによって提供されています。その後、UIkitが上下逆になっているので、画像を上下に反転させるだけです。
Apple提供の方法 - 画像にしたいビューの内側になるように修正されました。
-(UIImage *) drawableToCGImage
{
GLint backingWidth2, backingHeight2;
//Bind the color renderbuffer used to render the OpenGL ES view
// If your application only creates a single color renderbuffer which is already bound at this point,
// this call is redundant, but it is needed if you're dealing with multiple renderbuffers.
// Note, replace "_colorRenderbuffer" with the actual name of the renderbuffer object defined in your class.
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
// Get the size of the backing CAEAGLLayer
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth2);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight2);
NSInteger x = 0, y = 0, width2 = backingWidth2, height2 = backingHeight2;
NSInteger dataLength = width2 * height2 * 4;
GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));
// Read pixel data from the framebuffer
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glReadPixels(x, y, width2, height2, 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(width2, height2, 8, 32, width2 * 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 = width2/scale;
heightInPoints = height2/scale;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(widthInPoints, heightInPoints), NO, scale);
}
else {
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
widthInPoints = width2;
heightInPoints = height2;
UIGraphicsBeginImageContext(CGSizeMake(widthInPoints, heightInPoints));
}
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;
}
そして相続画像
- (UIImage *) flipImageVertically:(UIImage *)originalImage {
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:originalImage];
UIGraphicsBeginImageContext(tempImageView.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGAffineTransform flipVertical = CGAffineTransformMake(
1, 0, 0, -1, 0, tempImageView.frame.size.height
);
CGContextConcatCTM(context, flipVertical);
[tempImageView.layer renderInContext:context];
UIImage *flippedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//[tempImageView release];
return flippedImage;
}
そして、ここで私が参照する第一の方法を発見したアップルのdevのページへのリンクですを反転させる方法。 http://developer.apple.com/library/ios/#qa/qa1704/_index.html
ネイト、この質問(これを複製したもの)をここに入れて、人々がOpenGLからさまざまな方法でキャプチャする方法を知ってもらうESシーン。 –
@ネイト:EAGLViewに書き込まれたコンテンツがあるかどうかを知る方法はありますか?私はまた、上記のように動作したビューのスクリーンショットを撮ろうとしていますが、ユーザーがスクリーンショットを撮ったり、スクリーンをクリアしてスクリーンショットを撮ったりすると、空のスクリーンがキャプチャされてしまいます。 –
CGDataProviderCreateWithData
リリースを行う必要があり、データを、リリースごとにコールバックが付属しています:
void releaseBufferData(void *info, const void *data, size_t size)
{
free((void*)data);
}
その後、他の例のように、ではなく、ここでは無料のデータにこれを実行します。
GLubyte *bufferData = (GLubyte *) malloc(bufferDataSize);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bufferData, bufferDataSize, releaseBufferData);
....
CGDataProviderRelease(provider);
代わりに、リリースコールバックの代わりにCGDataProviderCreateWithCFData
を使用してください。
GLubyte *bufferData = (GLubyte *) malloc(bufferDataSize);
NSData *data = [NSData dataWithBytes:bufferData length:bufferDataSize];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
....
CGDataProviderRelease(provider);
free(bufferData); // Remember to free it
、これは議論し確認してください。
What's the right memory management pattern for buffer->CGImageRef->UIImage?
これは正しいです。 Core Graphicsコンテキストでデータを解放するためのコールバックのみを使用します。 –
のブラッドラーソンのこの上記のコードでは、あなたのEAGLView.mあなたがしなければならない
- (id)initWithCoder:(NSCoder*)coder{
self = [super initWithCoder:coder];
if (self) {
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = TRUE;
eaglLayer.drawableProperties =
[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
}
return self;
}
を編集する必要が変更numberWithBool
値YES
- 1. EAGLViewのテクスチャからUIImageを取得するには?
- 2. UIImageからバイトを取得
- 3. 関数からUIImageを取得する
- 4. UIImageからCurrentBackgroundImageパスを取得
- 5. Swift UIViewのレイヤーからUIImageを取得
- 6. UIImageから基になるNSData *を取得する
- 7. UIImageから透過領域を取得する方法は?
- 8. EAGLViewのタッチポイントでピクセルの色を取得できますか?
- 9. リソースフォルダの異なるディレクトリからUIImageを取得する
- 10. UIImageからURLを取得する方法
- 11. UIImageのピクセルを取得する方法
- 12. UIImageでピクセルを取得する
- 13. NSUserDefaultsから取得した後にUIImageをUIImageViewに設定する方法
- 14. は、私はXamarin IOSでアセットライブラリのURLからUIImageを取得できますか
- 15. すぐにUIImageからイメージの拡張子/フォーマットを取得する方法
- 16. サンプルバッファーからUIImageを取得したときにGoogle Visionがクラッシュする
- 17. MPMediaItemPropertyArtWorkからUIImageを取得できません
- 18. UIImageからどのようにCGContextRefを取得できますか?
- 19. UIImage:ウェブサイトタブの取得方法
- 20. UIViewをEAGLViewに変換しますか?
- 21. ゲーム内のEAGLViewにMoPub AdView(UIView)を追加すると、EAGLView touchは無視されますか?
- 22. AVPlayerに添付されたCALayerからUIImageを取得する(ビデオ再生からフレームを抽出する)
- 23. 取得UIBezierpath私はこのような<code>UIImage</code>から<code>UIBezierpath</code>を取得できますかUIImage
- 24. ARKit - オーバーレイなしでカメラからUIImageを取得するにはどうすればよいですか?
- 25. UIImagePickerControllerを使用せずにUIImageメタデータを取得する
- 26. EAGLViewの制限
- 27. UIImageとしてUIViewを取得
- 28. UIImageをトリミングするための正しい領域を取得するには?
- 29. 私の 'Documents'ディレクトリからCached UIImageを取得する方法はありますか?
- 30. iOSのUIImageからbase64にエンコードする
返信ありがとうRob、しかし私は "標準私それはうまくいきませんでした。私のEAGLViewは、それに読み込まれたテクスチャを正しく表示していますが、私は標準的なアプローチを使用してそれから抽出できるUIImageは、空の白い色です。これは、EAGLViewがIBにどのように現れるかです。これは、実際には、EAGLViewがUIViewの一種であることを見て、奇妙です。私は多分glReadPixelsまたは何かを代わりに使用する必要があると思いますか?私はAppleサンプルコードGLImageProcessingの例からEAGLViewを使って作業しています。 – RexOnRoids
ええと...私は本当に速く話しました。 OpenGLはQuartzと同じ方法でレンダリングしません。申し訳ありません。私はこのスレッドがあなたの問題に対処すると信じています。すべてのメッセージを読む。彼は途中でいくつかのバグを解決します。私はあなたがすでにCGContextを扱う方法を知っていて、そこからCGImageを得ることを前提としています(そしてそこからのUIImage)。 http://lists.apple.com/archives/mac-opengl/2006//jan/msg00085.html –
これらの回答は古く、不必要に長引いています。このソリューションはUIKitコードが4行しか必要ではありません。https://developer.apple.com/library/content/qa/qa1817/_index.html – demianturner