الشفافية/ألفا في سياق CoreGraphics (iPhone ، OBJC)
-
26-09-2019 - |
سؤال
أقوم حاليًا بإنشاء محرر صور أساسي لـ iPhone.
أنا آخذ CGImageRef
من UIImage
وإنشاء سياق له باستخدام الكود التالي
origImage = result.CGImage;
Iheight = CGImageGetHeight(origImage);
Iwidth = CGImageGetWidth(origImage);
IcolorSpace = CGColorSpaceCreateDeviceRGB();
IrawData = malloc(Iheight * Iwidth * 4);
IbytesPerPixel = 4;
IbytesPerRow = IbytesPerPixel * Iwidth;
IbitsPerComponent = 8;
Icontext = CGBitmapContextCreate(IrawData, Iwidth, Iheight, IbitsPerComponent,
IbytesPerRow, IcolorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big
);
//[bytesPerRow release];
CGContextSetBlendMode(Icontext, kCGBlendModeCopy);
CGContextDrawImage(Icontext, CGRectMake(0,0,Iwidth,Iheight), origImage);
أنا ثم حلقة من خلال البكسل
for (int x=0; x<Iwidth; x++) {
for (int y=0; y<Iheight; y++) {
//and set the alpha component to 0
int byteIndex = (y*IbytesPerRow) + x*IbytesPerPixel;
IrawData[byteIndex+3] = 0;
}
}
ثم قم بإنشاء cgimageref من السياق مع
CGImageRef imagea = CGBitmapContextCreateImage(Icontext);
وأضف cgimage إلى uiimage وتعيين إلى uiimageview
المشكلة هي أن تغيير ألفا لا يؤثر على الصورة الناتجة
إذا قمت بتغيير لون البكسل مع
IrawData[byteIndex+(0/1/2)]
يتغير اللون ، ولكن ما زلت لا أستطيع تغيير ألفا بكسل
شكرًا لك،
لا لا لا
المحلول
لا تنسَ ألوانًا غير مستمدة قبل تغيير ألفا ، وإعادة تمييزها بعد ذلك.
تعني اللون الباريبي (الذي يُطلق عليه غالبًا "alpha premultiplied ، وهو مضلل) أن مكونات الألوان يتم تخزينها بالفعل مضروبة من قبل ألفا ، لتخفيف التركيب. تبدو عملية التركيب المعتادة (المصدر) هكذا:
result = (source.rgb * source.a) + (destination.rgb * (1.0 - destination.a));
يعني premultiplication أن الضرب الأول قد تم بالفعل ، بحيث يمكن تخطيه:
result = source.rgb + (destination.rgb * (1.0 - destination.a));
عندما تقوم بتغيير ألفا دون تغيير مكونات الألوان الممتازة ، فإن النتيجة لا تتغير - عندما ترسم الصورة ، لن تبدو مختلفة ، لأن الألوان لا تزال متعمدة من قبل ألفا القديم.
لذا ، فأنت بحاجة إلى عدم وجود ألوان - أي تقسيم كل منها على ألفا (كما سبق مضروبًا ، لذلك يجب عليك الآن القيام بالعكس) - قبل تغيير ألفا. ثم ، بعد تغيير ألفا ، بشكل مسبق الألوان من قبل ألفا الجديدة.
بالطبع ، هذا يعني أنه عند تغيير ألفا إلى صفر ، ستصبح جميع الألوان سوداء (r = g = b = 0). لذا ، تأكد من الاحتفاظ بالصورة الأصلية إذا كان المستخدم قد يرغب في تغييرها مرة أخرى.
من المحتمل أن يكون الأمر أكثر فاعلية ، وسيكون بالتأكيد أسهل ، فقط رسم الصورة الأصلية (دون أي تغييرات ألفا التي تم إجراؤها عليها) في أي ألفا يريد المستخدم. يمكنك القيام بذلك بواسطة تغيير Alpha العالمي لسياق العرض الخاص بك قبل أن ترسم الصورة.