STDIO
Tìm kiếm gần đây
    Nội dung
    0
    0
    Chia sẻ
    Nội dung
    0
    0
    Chia sẻ

    Đánh Dấu và Kiểm Tra Bản Quyền Tài Liệu Số

    Hướng dẫn 1 trong những phương pháp để đánh dấu bản quyền và kiểm tra xem file ảnh có phải là file do mình đánh dấu hay không?
    26/08/2015 21/09/2020 7 phút đọc
    Đánh Dấu và Kiểm Tra Bản Quyền Tài Liệu Số

    Giới thiệu

    Với sự bùng nổ Internet như hiện nay, việc phát tán các phần mềm, băng đĩa lậu hay ảnh, video có bản quyền không có xa lạ gì nữa. Người sử dụng máy tính dần dần cũng mất đi sự tôn trọng đối với các sản phẩm có bản quyền.

    Đứng về phía nhà phát triển, thật sự rất khó để có thể ngăn chặn tình trạng trên diễn ra. Bởi vậy, chứng minh 1 sản phẩm có phải là sản phẩm do mình tạo ra hay không là 1 giải pháp để hạn chế người dùng phát tán sản phẩm có bản quyền.

    Bài viết hướng dẫn 1 trong những phương pháp để đánh dấu bản quyền và kiểm tra xem file ảnh có phải là file do mình đánh dấu hay không? Do bài viết chỉ mang tính minh họa nên chỉ thao tác trên file ảnh có định dạng TGA. Phương pháp này vẫn có thể áp dụng cho các loại định dạng ảnh và audio, video khác.

    Các phương pháp đánh dấu bản quyền trên file ảnh

    Nhìn chung có 2 cách đánh dấu bản quyền trên các file ảnh phổ biến:

    • Đánh dấu thấy được.
    • Đánh dấu không thấy được.

    Đánh dấu bản quyền thấy được

    Đánh dấu bản quyền thấy được là phương pháp đánh dấu của nhà xuất bản mà người sử dụng có thể dễ dàng thấy được (bằng mắt), hoặc nghe được (bằng tai).

    Đối với hình ảnh, bản quyền thường được đánh dấu bằng 1 dòng chữ ghi tên nhà sản xuất hoặc logo của nhà sản xuất.

    Đánh dấu bản quyền thấy được.
    Đánh dấu bản quyền thấy được

    Đánh dấu bản quyền không thấy được

    Cách đánh dấu như trên dường như quá "lộ", mọi người đều có thể thấy, sửa, xóa chúng. Nhà xuất bản có yêu cầu cao hơn sẽ đòi hỏi làm thế nào để che giấu thông tin của nhà xuất bản. Phương pháp này gọi là đánh dấu bản quyền không thấy được.

    Phần còn lại của bài viết sẽ hướng dẫn phương pháp đánh dấu và kiểm tra bản quyền không thấy được trên các file ảnh có định dạng TGA.

    Đề xuất ý tưởng

    Với yêu cầu như trên, ý tưởng là làm thế nào để thêm thông tin của nhà xuất bản vào file ảnh mà không làm thay đổi chất lượng cũng như nội dung của file ảnh đó. Điều này sẽ làm cho người xem file ảnh không thể phân biệt được đâu là file ảnh đã được đánh dấu và đâu là file ảnh không được đánh dấu.

    Đối với file ảnh TGA, hiện nay có 2 phiên bản được dùng: TGA v1.0 và TGA v2.0:

    • Đối với TGA v1.0, file gồm 2 phần: header và nội dung ảnh. Thay đổi bất kỳ thông tin nào trong file ảnh sẽ làm biến đổi nội dung được hiển thị của ảnh.
    • Đối với TGA v2.0, định dạng mới này cho phép nhà xuất bản có thể chèn bất kỳ thông tin gì vào khu vực có tên Developer Area. Có thể dùng khu vực này để đánh dấu bản quyền cho ảnh. Để tìm hiểu thông tin chi tiết về định dạng TGA, các bạn có thể xem tại mục Tham khảo.

    Hiện thực

    Đánh dấu bản quyền

    Định dạng TGA hỗ trợ nhiều dạng ảnh khác nhau như grayscale, RGB, RGBA nén hoặc không nén. Vì bài viết chỉ mang tính minh họa, chỉ hiện thực việc đánh dấu bản quyền trên ảnh RGB và RGBA không nén.

    Phương pháp hiện thực là ghi nội dung của file ảnh cũ vào file ảnh mới (file ảnh có chứa thông tin bản quyền) sau đó ghi thêm thông tin bản quyền và các thông tin kèm theo để phù hợp với định dạng TGA v2.0.

    Đọc nội dung của file ảnh trước khi đánh dấu, bao gồm header và thông tin ảnh:

    fread(&imageWidth, sizeof(short), 1, f);
    fread(&imageHeight, sizeof(short), 1, f);
    fread(&bitsPerPixel, sizeof(char), 1, f);
    
    int bytesPerPixel = bitsPerPixel / 8;
    int imageDataSize = imageWidth * imageHeight * bytesPerPixel;
    int imageSize = HEADER_SIZE + imageDataSize;
    
    char *imageData = new char[imageSize];
    fseek(f, 0, SEEK_SET);
    fread(imageData, imageSize, 1, f);

    Ghi nội dung của file ảnh vào file ảnh mới và thêm thông tin nhà xuất bản:

    fwrite(imageData, imageSize, 1, signedFilePtr);
    fwrite(STDIO_DEVELOPER_AREA, sizeof(STDIO_DEVELOPER_AREA), 1, signedFilePtr);
    writeLEInt(signedFilePtr, 0);           // extension area's offset
    writeLEInt(signedFilePtr, imageSize);   // developer area's offset
    const char *SIGN = "TRUEVISION-XFILE.";
    fwrite(SIGN, 18, 1, signedFilePtr);     // TGA v2.0 signature

    Giả sử Developer Area hiện tại cần lưu 3 thông tin:

    • STDIO Signature: là chuỗi STDIO dùng để nhận biết Developer Area này là do STDIO đánh dấu.
    • Data Length: kích thước vùng dữ liệu chứa thông tin bản quyền.
    • Data: thông tin bản quyền (trong bài viết này, thông tin bản quyền là chuỗi developer@stdio.vn).

    Vì các số trong định dạng TGA đều được biểu diễn ở dạng little endian nên khi ghi số xuống file cần phải lưu ý vị trí của các byte trong số đó. Phần hiện thực như sau:

    void writeLEInt(FILE* f, int x)
    {
        char buf[4];
        buf[3] = ((x) & 0xFF000000) >> 24;
        buf[2] = ((x) & 0x00FF0000) >> 16;
        buf[1] = ((x) & 0x0000FF00) >> 8;
        buf[0] = ((x) & 0x000000FF);
        fwrite(buf, 4, 1, f);
    }

    Kiểm tra bản quyền

    Phần kiểm tra bản quyền của là kiểm tra xem các điều kiện sau có thỏa mãn hay không?

    • Phiên bản ảnh sử dụng có phải là TGA v2.0 hay không?
    • Developer Area có phải do STDIO thêm vào hay không?
    • Thông tin bản quyền có phải là developer@stdio.vn hay không?

    Mã nguồn của toàn bộ bài viết

    Đánh dấu bản quyền

    #include <stdio.h>
    #include <string.h>
    
    #define OFFSET_IMG_WIDTH    12
    #define HEADER_SIZE         18
    
    static const char STDIO_DEVELOPER_AREA[] = 
    {
        "STDIO"                 // signature
        "\x13\x00\x00\x00"      // data length
        "developer@stdio.vn"    // data
    };
    
    void writeLEInt(FILE* f, int x)
    {
        char buf[4];
        buf[3] = ((x) & 0xFF000000) >> 24;
        buf[2] = ((x) & 0x00FF0000) >> 16;
        buf[1] = ((x) & 0x0000FF00) >> 8;
        buf[0] = ((x) & 0x000000FF);
        fwrite(buf, 4, 1, f);
    }
    
    int main(int argc, char **argv)
    {
        if(argc < 2)
        {
            printf("%s <image>\n", argv[0]);
            return -1;
        }
    
        /* Read image */
        FILE *f = fopen(argv[1], "rb");
    
        if(f == NULL)
        {
            printf("Can't open img_logo.tga to read\n");
            return -1;
        }
    
        fseek(f, OFFSET_IMG_WIDTH, SEEK_SET);
    
        short imageWidth, imageHeight;
        char bitsPerPixel;
    
        fread(&imageWidth, sizeof(short), 1, f);
        fread(&imageHeight, sizeof(short), 1, f);
        fread(&bitsPerPixel, sizeof(char), 1, f);
    
        int bytesPerPixel = bitsPerPixel/8;
        int imageDataSize = imageWidth*imageHeight*bytesPerPixel;
        int imageSize = HEADER_SIZE + imageDataSize;
    
        char *imageData = new char[imageSize];
        fseek(f, 0, SEEK_SET);
        fread(imageData, imageSize, 1, f);
        fclose(f);
    
        printf("Image Size: (%d, %d)\n", imageWidth, imageHeight);
        printf("Bits per pixel: %d\n", bitsPerPixel);
        printf("Image Size: %d\n", imageSize);
    
        /* Write image data + image footer to signed image */
        char outputFilename[256];
        sprintf(outputFilename, "signed_%s", argv[1]);
        FILE *signedFilePtr = fopen(outputFilename, "wb");
        if(signedFilePtr == NULL)
        {
            printf("Can't open signed_img_logo.tga to write\n");
            return -1;
        }
    
        fwrite(imageData, imageSize, 1, signedFilePtr);
        fwrite(STDIO_DEVELOPER_AREA, sizeof(STDIO_DEVELOPER_AREA), 1, signedFilePtr);
        writeLEInt(signedFilePtr, 0);           // extension area's offset
        writeLEInt(signedFilePtr, imageSize);   // developer area's offset
        const char *SIGN = "TRUEVISION-XFILE.";
        fwrite(SIGN, 18, 1, signedFilePtr);     // TGA v2.0 signature
    
        fclose(signedFilePtr);
    
        printf("-> Created signed_img_logo.tga\n");
    
        delete[] imageData; // release buffer to prevent leaking memory
    
        return 0;
    }

    Kiểm tra bản quyền

    #include <stdio.h>
    #include <string.h>
    
    #define TGAFOOTER_SIZE	26
    
    unsigned int readLEInt(FILE* f)
    {
        char buf[4];
        fread(buf, 4, 1, f);
    
        return (
        	((buf[0] << 0)	& 0xff) + \
        	((buf[1] << 8) 	& 0xff00) + \
        	((buf[2] << 16) & 0xff0000) + \
        	((buf[3] << 24) & 0xff000000));
    }
    
    int main(int argc, char **argv)
    {
        if(argc < 2)
        {
            printf("%s <image>\n", argv[0]);
            return -1;
        }
    
        /* Read signed image */
        FILE *signedFilePtr = fopen(argv[1], "rb");
        if(signedFilePtr == NULL)
        {
            return -1;
        }
    
        // find image size
        fseek(signedFilePtr, 0, SEEK_END);
        long int fileSize = ftell(signedFilePtr);
    
        // read image footer
        fseek(signedFilePtr, fileSize - TGAFOOTER_SIZE, SEEK_SET);
    
        unsigned int developerAreaOffset;
        unsigned int extensionOffset;
        char sig[18];
    
        extensionOffset = readLEInt(signedFilePtr);
        developerAreaOffset = readLEInt(signedFilePtr);
        fread(sig, 18, 1, signedFilePtr);
    
        if(strcmp(sig, "TRUEVISION-XFILE.") != 0)
        {
            printf("ERROR: This is not TGA v2.0 image\n");
            return -1;
        }
    
        printf("Extension area's offset: %d\n", extensionOffset);
        printf("Developer area's offset: %d\n", developerAreaOffset);
        printf("Signature: %s\n", sig);
    
        // read developer area
        // this area includes:
        //     1. STDIO signature: "STDIO"
        //	   2. data length
        //	   3. data
        fseek(signedFilePtr, developerAreaOffset, SEEK_SET);
    
        char stdioSig[6] = { 0 };
        char *developerAreaData;
        unsigned int dataSize = 0;
    
        fread(stdioSig, 5, 1, signedFilePtr); 		// read STDIO signature
    
        if(strcmp(stdioSig, "STDIO") != 0)
        {
            printf("ERROR: This image isn't signed by STDIO\n");
            return -1;
        }
    
        dataSize = readLEInt(signedFilePtr);	// read data length
        developerAreaData = new char[dataSize];
        fread(developerAreaData, dataSize, 1, signedFilePtr);	// read data
    
        if(strcmp(developerAreaData, "developer@stdio.vn") != 0)
        {
            printf("ERROR: License is invalid\n");
            return -1;
        }
    
        printf("STDIO Signature: %s\n", stdioSig);
        printf("Data Length: %d\n", dataSize);
        printf("Data: %s\n", developerAreaData);
    
        printf("-> This image is copyrighted by STDIO\n");
    
        delete[] developerAreaData;
    
        return 0;
    }
    0 Bình luận
    Khi bạn nhấn vào sản phẩm do chúng tôi đề xuất và mua hàng, chúng tôi sẽ nhận được hoa hồng. Điều này hỗ trợ chúng tôi có thêm kinh phí tạo nhiều nội dung hữu ích. Tìm hiểu thêm.
    STDIO

    Trang chính

    Công ty TNHH STDIO

    • 30, Trịnh Đình Thảo, Hòa Thạnh, Tân Phú, Hồ Chí Minh
      +84 28.36205514 - +84 942.111912
      developer@stdio.vn
    • 383/1 Quang Trung, Phường 10, Quận Gò Vấp, Hồ Chí Minh
      Số giấy phép ĐKKD: 0311563559 do sở Kế hoạch và Đầu Tư TPHCM cấp ngày 23/02/2012
    ©STDIO, 2013 - 2021