Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
6.6 kB
2
Indexable
Never
#include <stdio.h>
#include <stdlib.h>
#include <png.h>
#include <math.h>

#define BLOCK_SIZE 8

// Function to perform DCT on an 8x8 block
void dct(double block[BLOCK_SIZE][BLOCK_SIZE]) {
    double alpha, beta, sum;
    double tmp[BLOCK_SIZE][BLOCK_SIZE];
    for (int u = 0; u < BLOCK_SIZE; u++) {
        for (int v = 0; v < BLOCK_SIZE; v++) {
            sum = 0.0;
            for (int x = 0; x < BLOCK_SIZE; x++) {
                for (int y = 0; y < BLOCK_SIZE; y++) {
                    sum += block[x][y] *
                           cos(((2 * x + 1) * u * M_PI) / (2 * BLOCK_SIZE)) *
                           cos(((2 * y + 1) * v * M_PI) / (2 * BLOCK_SIZE));
                }
            }
            alpha = (u == 0) ? sqrt(1.0 / BLOCK_SIZE) : sqrt(2.0 / BLOCK_SIZE);
            beta = (v == 0) ? sqrt(1.0 / BLOCK_SIZE) : sqrt(2.0 / BLOCK_SIZE);
            tmp[u][v] = alpha * beta * sum;
        }
    }

    // Copy the result back to the original block
    for (int i = 0; i < BLOCK_SIZE; i++) {
        for (int j = 0; j < BLOCK_SIZE; j++) {
            block[i][j] = tmp[i][j];
        }
    }
}

// Function to perform Inverse DCT on an 8x8 block
void inverse_dct(double block[BLOCK_SIZE][BLOCK_SIZE]) {
    double alpha, beta, sum;
    double tmp[BLOCK_SIZE][BLOCK_SIZE];
    for (int x = 0; x < BLOCK_SIZE; x++) {
        for (int y = 0; y < BLOCK_SIZE; y++) {
            sum = 0.0;
            for (int u = 0; u < BLOCK_SIZE; u++) {
                for (int v = 0; v < BLOCK_SIZE; v++) {
                    alpha = (u == 0) ? sqrt(1.0 / BLOCK_SIZE) : sqrt(2.0 / BLOCK_SIZE);
                    beta = (v == 0) ? sqrt(1.0 / BLOCK_SIZE) : sqrt(2.0 / BLOCK_SIZE);
                    sum += alpha * beta * block[u][v] *
                           cos(((2 * x + 1) * u * M_PI) / (2 * BLOCK_SIZE)) *
                           cos(((2 * y + 1) * v * M_PI) / (2 * BLOCK_SIZE));
                }
            }
            tmp[x][y] = sum;
        }
    }

    // Copy the result back to the original block
    for (int i = 0; i < BLOCK_SIZE; i++) {
        for (int j = 0; j < BLOCK_SIZE; j++) {
            block[i][j] = tmp[i][j];
        }
    }
}

// Function to read a PNG image using libpng
void read_png_file(const char *filename, png_bytep **image, int *width, int *height) {
    FILE *fp = fopen(filename, "rb");
    if (!fp) {
        perror("File opening failed");
        return;
    }

    png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png) abort();

    png_infop info = png_create_info_struct(png);
    if (!info) abort();

    if (setjmp(png_jmpbuf(png))) abort();

    png_init_io(png, fp);
    png_read_info(png, info);

    *width = png_get_image_width(png, info);
    *height = png_get_image_height(png, info);

    png_byte color_type = png_get_color_type(png, info);
    png_byte bit_depth = png_get_bit_depth(png, info);

    if (bit_depth == 16)
        png_set_strip_16(png);

    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png);

    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
        png_set_expand_gray_1_2_4_to_8(png);

    if (png_get_valid(png, info, PNG_INFO_tRNS))
        png_set_tRNS_to_alpha(png);

    if (color_type == PNG_COLOR_TYPE_RGB ||
        color_type == PNG_COLOR_TYPE_GRAY ||
        color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_filler(png, 0xFF, PNG_FILLER_AFTER);

    if (color_type == PNG_COLOR_TYPE_GRAY ||
        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png);

    png_read_update_info(png, info);

    *image = (png_bytep*)malloc(sizeof(png_bytep) * (*height));
    for (int y = 0; y < *height; y++) {
        (*image)[y] = (png_byte*)malloc(png_get_rowbytes(png, info));
    }

    png_read_image(png, *image);

    fclose(fp);
    png_destroy_read_struct(&png, &info, NULL);
}

// Function to write a PNG image using libpng
void write_png_file(const char *filename, png_bytep *image, int width, int height) {
    FILE *fp = fopen(filename, "wb");
    if (!fp) {
        perror("File opening failed");
        return;
    }

    png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png) abort();

    png_infop info = png_create_info_struct(png);
    if (!info) abort();

    if (setjmp(png_jmpbuf(png))) abort();

    png_init_io(png, fp);

    png_set_IHDR(
        png,
        info,
        width, height,
        8,
        PNG_COLOR_TYPE_RGBA,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_DEFAULT,
        PNG_FILTER_TYPE_DEFAULT
    );
    png_write_info(png, info);

    png_write_image(png, image);
    png_write_end(png, NULL);

    fclose(fp);
    png_destroy_write_struct(&png, &info);
}

// Function to embed a message into an image using DCT
void embed_message(png_bytep *image, int width, int height, const char *message) {
    int msg_index = 0;
    int msg_length = strlen(message) * 8;
    double block[BLOCK_SIZE][BLOCK_SIZE];
    for (int y = 0; y < height; y += BLOCK_SIZE) {
        for (int x = 0; x < width; x += BLOCK_SIZE) {
            // Load an 8x8 block
            for (int i = 0; i < BLOCK_SIZE; i++) {
                for (int j = 0; j < BLOCK_SIZE; j++) {
                    if (y + i < height && x + j < width) {
                        block[i][j] = (double)image[y + i][4 * (x + j)]; // Using red channel for simplicity
                    } else {
                        block[i][j] = 0.0;
                    }
                }
            }

            // Perform DCT on the block
            dct(block);

            // Embed a bit of the message into the DCT coefficients
            if (msg_index < msg_length) {
                int bit = (message[msg_index / 8] >> (7 - (msg_index % 8))) & 1;
                if (block[1][1] > 0) {
                    block[1][1] = bit ? fabs(block[1][1]) : -fabs(block[1][1]);
                } else {
                    block[1][1] = bit ? -fabs(block[1][1]) : fabs(block[1][1]);
                }
                msg_index++;
            }

            // Perform inverse DCT on the block
            inverse_dct(block);

            // Store the modified block back into the image
            for (int i = 0; i < BLOCK_SIZE; i++) {
                for (int j = 0; j < BLOCK_SIZE; j++) {
                    if (y + i < height && x + j < width) {
                        image[y + i][4 * (x + j)] = (png_byte)fmin(fmax(block[i][j], 0.0), 255.0);
                    }
                }
            }
        }
    }
}

int main(int
Leave a Comment