आईओएस सहेजे गए छवि पर ओपनजीएल ईएस का गलत परिणाम है (आंशिक रूप से पारदर्शी किनारों पर काला रंग)

मैं एक ड्राइंग व्यू के साथ एक ऐप के लिए ऐप्पल के जीएलपेंट उदाहरण के शीर्ष पर बना रहा हूं। मैं इसे साफ़ करने के लिए उपयोग करता हूं:

glClearcolor (0.0f, 0.0f, 0.0f, 0.0f);

यह मुझे खींचा जा रहा है के पीछे एक छवि डालने की अनुमति देता है, बाद में मैं दो छवियों को विलय करता हूं, लेकिन जब मैं ओपनजीएल संदर्भ से अधिकतर पारदर्शी छवि को सहेजता हूं, तो आंशिक रूप से पारदर्शी होने वाला कोई भी पिक्सेल काला रंग के साथ मिश्रण होता है। (पारदर्शी सफेद के लिए स्पष्ट रंग बदलना इसे सफेद से मिश्रण करता है)। मैंने कई विकल्पों के साथ खेलने की कोशिश की है और मुझे कोई काम नहीं मिला है।

यहां दो स्क्रीनशॉट हैं, पहला यह है कि ड्रॉइंग ऐप कैसा दिखता है, दूसरा तब होता है जब मैं ओपनजीएल संदर्भ से एक छवि को सहेजने का प्रयास करता हूं।

From screenshot: Image as seen on iOS

From glReadPixels, being displayed in a UIImageView: Image I get from glReadPixels

प्रासंगिक कोड:

-(UIImage*)mergeImage:(UIImage*)image1 withImage:(UIImage*)image2{

CGSize size = image1.size;

// UIGraphicsBeginImageContext (आकार);     UIGraphicsBeginImageContextWithOptions (आकार, नहीं, 1.0 एफ);

[image1 drawAtPoint:CGPointMake(0.0f, 0.0f)];
[image2 drawAtPoint:CGPointMake(0.0f, 0.0f)];

UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();


return result;

}

- (यूआईएममेज *) glToUIImage {

int imageWidth, imageHeight;

imageWidth = self.frame.size.width;
imageHeight = self.frame.size.height;

NSInteger myDataLength = imageWidth * imageHeight * 4;


// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, imageWidth, imageHeight, 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 < imageHeight; y++){
    for(int x = 0; x < imageWidth * 4; x++){
        buffer2[((imageHeight - 1) - y) * imageWidth * 4 + x] = buffer[y * 4 * imageWidth + x];
    }
}

// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
//CGDataProviderRef provider2 = CGDataProviderCreateWithData(NULL, white, myDataLength, NULL);

// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * imageWidth;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

// make the cgimage
CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);


UIImage *myImage = [UIImage imageWithCGImage:imageRef];

CGImageRelease(imageRef);
CGColorSpaceRelease(colorSpaceRef);

UIImageWriteToSavedPhotosAlbum(myImage, NULL, NULL, NULL);

CGDataProviderRelease(provider);
free(buffer);
free(buffer2);

return myImage;

}

- (UIImage *) glToUIImageOnWhite {

int imageWidth, imageHeight;

imageWidth = self.frame.size.width;
imageHeight = self.frame.size.height;

NSInteger myDataLength = imageWidth * imageHeight * 4;


// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, imageWidth, imageHeight, 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);

GLubyte R, G, B, A;

for(int y = 0; y < imageHeight; y++){
    for(int x = 0; x < imageWidth*4; x+=4){
        R = buffer[y * 4 * imageWidth + x];
        G = buffer[y * 4 * imageWidth + x +1];
        B = buffer[y * 4 * imageWidth + x +2];
        A = buffer[y * 4 * imageWidth + x +3];

        buffer2[((imageHeight - 1) - y) * imageWidth * 4 + x]    = 255-(A-R);
        buffer2[((imageHeight - 1) - y) * imageWidth * 4 + x +1] = 255-(A-G);
        buffer2[((imageHeight - 1) - y) * imageWidth * 4 + x +2] = 255-(A-B);

        buffer2[((imageHeight - 1) - y) * imageWidth * 4 + x +3] = 255;
    }
}

// make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
//CGDataProviderRef provider2 = CGDataProviderCreateWithData(NULL, white, myDataLength, NULL);

// prep the ingredients
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * imageWidth;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaLast;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

// make the cgimage
CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

UIImage *myImage = [UIImage imageWithCGImage:imageRef];

CGImageRelease(imageRef);
CGColorSpaceRelease(colorSpaceRef);


CGDataProviderRelease(provider);

free(buffer);
free(buffer2);

return myImage;

}

0
मैं इस पृष्ठ से glToUIImage फ़ंक्शन का उपयोग कर रहा हूं: iphonedevsdk.com/forum/iphone-sdk-development/… अपवाद के साथ मैंने CGImage के अल्फा चैनल को संरक्षित करने के लिए बिटमैप जानकारी में "kCGImageAlphaLast" जोड़ा है।
जोड़ा लेखक Patrick T Nelson, स्रोत
दिलचस्प खोज: ब्लेंडिंग ठीक काम करता है अगर मैं opbrushColorWithRed में gluniform4fv को पास करके ओपेसिटी ब्रश बदलता हूं: ग्रीन: ब्लू: फ़ंक्शन। ब्रश छवि की केवल आंशिक पारदर्शिता ही गलत ओ_ओ को जोड़ती है
जोड़ा लेखक Patrick T Nelson, स्रोत
ऐसा लगता है कि मैं बड़ी टिप्पणियां नहीं कर सकता, यहां प्रासंगिक कोड है, आपको इसे सिंटैक्स हाइलाइटिंग के लिए एक्सकोड में पेस्ट करना होगा: digitaldiscrepancy.com/code.txt पहली छवि जिसे मैं कैप्चर करता हूं gltoUIImageOnWhite का उपयोग करता है, उसके बाद मैं glToUIImage और मर्ज फ़ंक्शन का उपयोग करता हूं। यहां तक ​​कि अगर मैं glToUIImage के बाद सीधे यूआईएममेज को सहेजता हूं तो इसे अभी भी सही नहीं दिखता है।
जोड़ा लेखक Patrick T Nelson, स्रोत
एचटीएमएल सिंटैक्स हाइलाइटिंग के साथ प्रासंगिक कोड: digitaldiscrepancy.com/code.html
जोड़ा लेखक Patrick T Nelson, स्रोत
उपर्युक्त छवियां वास्तव में ऐप से स्क्रीनशॉट हैं, नीचे की ओर एक UIImageView पर प्रदर्शित की जा रही है, यह फोटो एलबम से नहीं है।
जोड़ा लेखक Patrick T Nelson, स्रोत
अहा! इसने निश्चित रूप से छवि तय की है, धन्यवाद! मैंने उस मूल्य के साथ थोड़ा सा खेल खेला, लेकिन कभी कोशिश नहीं की। इसे एक उत्तर के रूप में रखो और मैं इसे बंद कर दूंगा :)
जोड़ा लेखक Patrick T Nelson, स्रोत
क्या आप स्क्रीनशॉट जेनरेट कर रहे हैं इसके लिए कोड दिखा सकते हैं?
जोड़ा लेखक Tark, स्रोत
आपको कुछ कोड दिखाने की आवश्यकता होगी। आप स्क्रीनशॉट को कैसे देख और सहेज रहे हैं?
जोड़ा लेखक Tark, स्रोत
आपको प्रश्न में प्रासंगिक विधि डालना चाहिए। मुझे संदेह है कि समस्याएं हैं UIImageWriteToSavedPhotosAlbum (myImage, NULL, NULL, NULL) , यह छवि पर जेपीईजी संपीड़न कर रहा है जो अल्फा घटकों को प्रभावित कर सकता है। कौन सी छवि ऊपर है? क्या यूआईएममेज लौटा है और दूसरा फोटो एलबम में सहेजा गया है?
जोड़ा लेखक Tark, स्रोत
क्या आपने kCGImageAlphaPremultipliedLast का उपयोग करने का प्रयास किया है?
जोड़ा लेखक Tark, स्रोत

1 उत्तर

अल्फा क्षेत्र बहुत अंधेरे हैं, यह संभव है कि रंग बफर ने अल्फा को प्रीमिलीप्लाइड किया हो। उस स्थिति में, आपका CGImage का उपयोग करके बनाया जाना चाहिए:

CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
2
जोड़ा