iOS-盲水印、數(shù)字水印

// 嵌入信息
- (UIImage *)embedMessage:(NSString *)message inImage:(UIImage *)image {
    // 將圖片轉(zhuǎn)換為位圖數(shù)據(jù)
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    NSUInteger bytesPerPixel = 4; // 每個(gè)像素占 4 個(gè)字節(jié)(RGBA)
    NSUInteger bitsPerComponent = 8; // 每個(gè)顏色分量占 8 位
    NSUInteger bytesPerRow = bytesPerPixel * width; // 每行的字節(jié)數(shù)
    unsigned char *rawData = (unsigned char *)calloc(height * width * bytesPerPixel, sizeof(unsigned char));
    CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);


    // 將消息轉(zhuǎn)換為二進(jìn)制數(shù)據(jù),并在末尾添加終止符 '\0'
    NSString *messageWithTerminator = [message stringByAppendingString:@"\0"];
    NSData *messageData = [messageWithTerminator dataUsingEncoding:NSUTF8StringEncoding];
    const char *messageBytes = [messageData bytes];
    NSUInteger messageLength = [messageData length];


    // 使用 LSB 嵌入消息
    NSUInteger byteIndex = 0;
    NSUInteger bitIndex = 0;
    for (NSUInteger y = 0; y < height; y++) {
        for (NSUInteger x = 0; x < width; x++) {
            NSUInteger pixelIndex = (width * y + x) * bytesPerPixel;
            for (NSUInteger i = 0; i < 3; i++) { // 修改 RGB 通道的最低有效位
                if (byteIndex < messageLength) {
                    unsigned char bit = (messageBytes[byteIndex] >> bitIndex) & 1;
                    rawData[pixelIndex + i] = (rawData[pixelIndex + i] & 0xFE) | bit;
                    bitIndex++;
                    if (bitIndex == 8) {
                        byteIndex++;
                        bitIndex = 0;
                    }
                }
            }
        }
    }


    // 生成新的圖片
    CGImageRef newImageRef = CGBitmapContextCreateImage(context);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(newImageRef);
    free(rawData);


    return newImage;
}
// 提取
- (NSString *)extractMessageFromImage:(UIImage *)image {
    // 將圖片轉(zhuǎn)換為位圖數(shù)據(jù)
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    NSUInteger bytesPerPixel = 4; // 每個(gè)像素占 4 個(gè)字節(jié)(RGBA)
    NSUInteger bitsPerComponent = 8; // 每個(gè)顏色分量占 8 位
    NSUInteger bytesPerRow = bytesPerPixel * width; // 每行的字節(jié)數(shù)
    unsigned char *rawData = (unsigned char *)calloc(height * width * bytesPerPixel, sizeof(unsigned char));
    CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);


    // 從 LSB 中提取消息
    NSMutableData *messageData = [NSMutableData data];
    unsigned char byte = 0;
    NSUInteger bitIndex = 0;
    BOOL endOfMessage = NO;


    for (NSUInteger y = 0; y < height && !endOfMessage; y++) {
        for (NSUInteger x = 0; x < width && !endOfMessage; x++) {
            NSUInteger pixelIndex = (width * y + x) * bytesPerPixel;
            for (NSUInteger i = 0; i < 3 && !endOfMessage; i++) { // 讀取 RGB 通道的最低有效位
                unsigned char bit = rawData[pixelIndex + i] & 1;
                byte |= (bit << bitIndex);
                bitIndex++;
                if (bitIndex == 8) {
                    [messageData appendBytes:&byte length:1];
                    if (byte == '\0') { // 遇到終止符,結(jié)束提取
                        endOfMessage = YES;
                        break;
                    }
                    byte = 0;
                    bitIndex = 0;
                }
            }
        }
    }


    // 轉(zhuǎn)換為字符串
    NSString *message = [[NSString alloc] initWithData:messageData encoding:NSUTF8StringEncoding];
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    free(rawData);


    return message;
}

-(void)saveWithImage:(UIImage *)image{
    // 將 UIImage 轉(zhuǎn)換為 PNG 數(shù)據(jù)
    NSData *pngData = UIImagePNGRepresentation(image);


    // 保存 PNG 數(shù)據(jù)到相冊(cè)
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        [PHAssetCreationRequest creationRequestForAssetFromImage:[UIImage imageWithData:pngData]];
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
        if (success) {
            NSLog(@"保存成功");
        } else {
            NSLog(@"保存失敗: %@", error.localizedDescription);
        }
    }];
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容