Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Need Help] iOS png some question #349

Open
dong136279559 opened this issue Dec 2, 2019 · 6 comments
Open

[Need Help] iOS png some question #349

dong136279559 opened this issue Dec 2, 2019 · 6 comments

Comments

@dong136279559
Copy link

dong136279559 commented Dec 2, 2019

Hello, I used this code to compress PNG image in IOS project, but the data I got failed to pass a transparency judgment. I wonder if the compressed PNG is not a true color image. How can I modify the code,thank you!

my Code:

int progress_callback_function(float progress_percent, void* user_info) {
    return 1;
}
+ (NSData *)compressToPNGWithImage:(UIImage *)comImg {
    
    unsigned int width, height;

    CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(comImg.CGImage));
    const uint8_t* data = CFDataGetBytePtr(pixelData);

    width = (int)comImg.size.width;
    height = (int)comImg.size.height;

    liq_attr *handle = liq_attr_create();
    liq_attr_set_progress_callback(handle, progress_callback_function, NULL);
    liq_set_quality(handle, 75, 90);//图片质量范围 > 0 < 100;
    liq_set_speed(handle, 3);//压缩速度对压缩比有一定影响的
    liq_image *input_image = liq_image_create_rgba(handle, data, width, height, 0);
        // You could set more options here, like liq_set_quality
    liq_result *quantization_result;
    if (liq_image_quantize(input_image, handle, &quantization_result) != LIQ_OK) {
        fprintf(stderr, "Quantization failed\n");
        return nil;
    }

    // Use libimagequant to make new image pixels from the palette

    size_t pixels_size = width * height;
    unsigned char *raw_8bit_pixels = malloc(pixels_size);
    liq_set_dithering_level(quantization_result, 1.0);

    liq_write_remapped_image(quantization_result, input_image, raw_8bit_pixels, pixels_size);
    const liq_palette *palette = liq_get_palette(quantization_result);

        // Save converted pixels as a PNG file
        // This uses lodepng library for PNG writing (not part of libimagequant)

    LodePNGState state;
    lodepng_state_init(&state);
    state.info_raw.colortype = LCT_PALETTE;
    state.info_raw.bitdepth = 8;
    state.info_png.color.colortype = LCT_PALETTE;
    state.info_png.color.bitdepth = 8;

    for(int i=0; i < palette->count; i++) {
        lodepng_palette_add(&state.info_png.color, palette->entries[i].r, palette->entries[i].g, palette->entries[i].b, palette->entries[i].a);
        lodepng_palette_add(&state.info_raw, palette->entries[i].r, palette->entries[i].g, palette->entries[i].b, palette->entries[i].a);
    }

    unsigned char *output_file_data;
    size_t output_file_size;
    unsigned int out_status = lodepng_encode(&output_file_data, &output_file_size, raw_8bit_pixels, width, height, &state);
    if (out_status) {
        fprintf(stderr, "Can't encode image: %s\n", lodepng_error_text(out_status));
        return nil;
    }
    NSData *output_data = [NSData dataWithBytes:output_file_data length:output_file_size];

    liq_result_destroy(quantization_result); // Must be freed only after you're done using the palette
    liq_image_destroy(input_image);
    liq_attr_destroy(handle);

    free(raw_8bit_pixels);
    lodepng_state_cleanup(&state);
    return output_data;
}

judge:

       uint8_t c;
       [imageData getBytes:&c range:NSMakeRange(25, 1)];
       if (c == 0x03) {
           NSLog(@"It's not what I want!");
           return;
       }
@ofirkris
Copy link

ofirkris commented Dec 9, 2019

Hi @dong136279559 , have you managed to solve this issue?

@dong136279559
Copy link
Author

@ofirkris I didn't solve the problem. I need some help

@kornelski
Copy link
Owner

kornelski commented Dec 12, 2019

iOS uses premultiplied alpha (R*A, G*A, B*A, A), not a uncorrelated alpha (R, G, B, A), so any pixels you get from iOS you have to convert to RGBA first by dividing RGB values by their alpha.

@kornelski
Copy link
Owner

@dong136279559
Copy link
Author

Do you mean that? But it didn't work. Did I understand that?

`
if (palette->entries[i].a) {
lodepng_palette_add(&state.info_png.color, palette->entries[i].r255/palette->entries[i].a, palette->entries[i].g255/palette->entries[i].a, palette->entries[i].b255/palette->entries[i].a, palette->entries[i].a);
lodepng_palette_add(&state.info_raw, palette->entries[i].r
255/palette->entries[i].a, palette->entries[i].g255/palette->entries[i].a, palette->entries[i].b255/palette->entries[i].a, palette->entries[i].a);
}else {
lodepng_palette_add(&state.info_png.color, 0, 0, 1, 0);
lodepng_palette_add(&state.info_raw, 1, 1, 1, 0);
}

`

@kornelski
Copy link
Owner

No, totally not. The palette is never premultiplied! You must adjust the input pixels. See the file I linked to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants