Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image processing 改变DCT系数_Image Processing_Libjpeg - Fatal编程技术网

Image processing 改变DCT系数

Image processing 改变DCT系数,image-processing,libjpeg,Image Processing,Libjpeg,我决定使用libjpeg作为处理jpeg文件的主库。 我已经阅读了libjpg.txt文件。我很高兴这个库允许DCT系数以一种方便的方式读/写。因为编写自己的解码器需要很长时间 我的工作与无损嵌入有关。目前,我需要从文件中读取DCT系数,然后修改其中的一些系数,并将更改后的系数写入同一文件中 我找到了jpeg\u write\u coverties()函数。我天真地认为我可以将它应用到解压对象(struct jpeg\u decompress\u struct)。但它不起作用,需要一个压缩对象

我决定使用libjpeg作为处理jpeg文件的主库。 我已经阅读了libjpg.txt文件。我很高兴这个库允许DCT系数以一种方便的方式读/写。因为编写自己的解码器需要很长时间

我的工作与无损嵌入有关。目前,我需要从文件中读取DCT系数,然后修改其中的一些系数,并将更改后的系数写入同一文件中

我找到了
jpeg\u write\u coverties()
函数。我天真地认为我可以将它应用到解压对象(
struct jpeg\u decompress\u struct
)。但它不起作用,需要一个压缩对象

我不敢相信如此强大的图书馆不能做到这一点。 我想我很可能错过了什么。尽管我尽力专心。 也许书写系数可以用更复杂的方法来完成。 但我不知道怎么做


如果您能提出您的想法,我将非常高兴。

您真的应该看看transupp.h和库中附带的JPEG-Tran源代码。 无论如何,这是我的带注释的脏代码,部分来自jpegtran。它允许您逐个操作DCT系数

#include "jpeglib.h"             /* Common decls for cjpeg/djpeg applications */
#include "transupp.h"            /* Support routines for jpegtran */


struct jpeg_decompress_struct srcinfo;
struct jpeg_compress_struct dstinfo;
struct jpeg_error_mgr jsrcerr, jdsterr;

static jpeg_transform_info transformoption; /* image transformation options */
transformoption.transform = JXFORM_NONE;
transformoption.trim = FALSE;
transformoption.force_grayscale = FALSE;

jvirt_barray_ptr * src_coef_arrays;
jvirt_barray_ptr * dst_coef_arrays;

/* Initialize the JPEG decompression object with default error handling. */
srcinfo.err = jpeg_std_error(&jsrcerr);
jpeg_create_decompress(&srcinfo);
/* Initialize the JPEG compression object with default error handling. */
dstinfo.err = jpeg_std_error(&jdsterr);
jpeg_create_compress(&dstinfo);

FILE *fp;

if((fp = fopen(filePath], "rb")) == NULL) {
    //Throw an error
} else {
    //Continue
}

/* Specify data source for decompression */
jpeg_stdio_src(&srcinfo, fp);

/* Enable saving of extra markers that we want to copy */
jcopy_markers_setup(&srcinfo, JCOPYOPT_ALL);

/* Read file header */
(void) jpeg_read_header(&srcinfo, TRUE);

jtransform_request_workspace(&srcinfo, &transformoption);
src_coef_arrays = jpeg_read_coefficients(&srcinfo);
jpeg_copy_critical_parameters(&srcinfo, &dstinfo);

/* Do your DCT shenanigans here on src_coef_arrays like this (I've moved it into a separate function): */

moveDCTAround(&srcinfo, &dstinfo, 0, src_coef_arrays);

/* ..when done with DCT, do this: */
dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, src_coef_arrays, &transformoption);
fclose(fp);

//And write everything back
fp = fopen(filePath, "wb");

/* Specify data destination for compression */
jpeg_stdio_dest(&dstinfo, fp);

/* Start compressor (note no image data is actually written here) */
jpeg_write_coefficients(&dstinfo, dst_coef_arrays);

/* Copy to the output file any extra markers that we want to preserve */
jcopy_markers_execute(&srcinfo, &dstinfo, JCOPYOPT_ALL);

jpeg_finish_compress(&dstinfo);
jpeg_destroy_compress(&dstinfo);
(void) jpeg_finish_decompress(&srcinfo);
jpeg_destroy_decompress(&srcinfo);

fclose(fp);
以及功能本身:

void moveDCTAround (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays)
{
    size_t block_row_size;
    JBLOCKARRAY coef_buffers[MAX_COMPONENTS];
    JBLOCKARRAY row_ptrs[MAX_COMPONENTS];

    //Allocate DCT array buffers
    for (JDIMENSION compnum=0; compnum<srcinfo->num_components; compnum++)
    {
        coef_buffers[compnum] = (dstinfo->mem->alloc_barray)((j_common_ptr) dstinfo, JPOOL_IMAGE, srcinfo->comp_info[compnum].width_in_blocks,
         srcinfo->comp_info[compnum].height_in_blocks);
    }

    //For each component,
    for (JDIMENSION compnum=0; compnum<srcinfo->num_components; compnum++)
    {
        block_row_size = (size_t) sizeof(JCOEF)*DCTSIZE2*srcinfo->comp_info[compnum].width_in_blocks;
        //...iterate over rows,
        for (JDIMENSION rownum=0; rownum<srcinfo->comp_info[compnum].height_in_blocks; rownum++)
        {
            row_ptrs[compnum] = ((dstinfo)->mem->access_virt_barray)((j_common_ptr) &dstinfo, src_coef_arrays[compnum], rownum, (JDIMENSION) 1, FALSE);
            //...and for each block in a row,
            for (JDIMENSION blocknum=0; blocknum<srcinfo->comp_info[compnum].width_in_blocks; blocknum++)
                //...iterate over DCT coefficients
                for (JDIMENSION i=0; i<DCTSIZE2; i++)
                {
                        //Manipulate your DCT coefficients here. For instance, the code here inverts the image.
                        coef_buffers[compnum][rownum][blocknum][i] = -row_ptrs[compnum][0][blocknum][i];
                }
        }
    }

    //Save the changes
    //For each component,
    for (JDIMENSION compnum=0; compnum<srcinfo->num_components; compnum++)
    {
        block_row_size = (size_t) sizeof(JCOEF)*DCTSIZE2 * srcinfo->comp_info[compnum].width_in_blocks;
        //...iterate over rows
        for (JDIMENSION rownum=0; rownum < srcinfo->comp_info[compnum].height_in_blocks; rownum++)
        {
            //Copy the whole rows
            row_ptrs[compnum] = (dstinfo->mem->access_virt_barray)((j_common_ptr) dstinfo, src_coef_arrays[compnum], rownum, (JDIMENSION) 1, TRUE);
            memcpy(row_ptrs[compnum][0][0], coef_buffers[compnum][rownum][0], block_row_size);
        }
    }
void movedctrand(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,jvirt_barray_ptr*src_coef_数组)
{
大小\块\行\大小;
JBLOCKARRAY coef_缓冲区[最大组件];
JBLOCKARRAY行存储寄存器[最大组件];
//分配DCT数组缓冲区
对于(JDIMENSION compnum=0;compnumnum_组件;compnum++)
{
coef_buffers[compnum]=(dstinfo->mem->alloc_barray)((j_common_ptr)dstinfo,JPOOL_IMAGE,srcinfo->comp_info[compnum]。块中的宽度,
srcinfo->comp_info[compnum]。高度(以块为单位);
}
//对于每个组件,
对于(JDIMENSION compnum=0;compnumnum_组件;compnum++)
{
块的行大小=(大小)大小(JCOEF)*DCTSIZE2*srcinfo->comp\u info[compnum]。块的宽度;
//…迭代行,
对于(JDIMENSION rownum=0;rownumcomp_信息[compnum]。块中的高度;rownum++)
{
行ptrs[compnum]=((dstinfo)->mem->access_virt_barray)((j_common_ptr)和dstinfo,src_coef_数组[compnum],行数,(JDIMENSION)1,FALSE);
//…对于一行中的每个块,
对于(JDIMENSION blocknum=0;blocknumcomp_信息[compnum]。块中的宽度;blocknum++)
//…迭代DCT系数
对于(JDIMENSION i=0;icomp\u info[compnum]),宽度(以块为单位);
//…对行进行迭代
对于(JDIMENSION rownum=0;rownumcomp_info[compnum]。块中的高度;rownum++)
{
//复制整行
行ptrs[compnum]=(dstinfo->mem->access_virt_barray)((j_common_ptr)dstinfo,src_coef_数组[compnum],行数,(JDIMENSION)1,TRUE);
memcpy(行ptrs[compnum][0][0],coef_缓冲区[compnum][rownum][0],块行大小);
}
}

您可以使用jpeg\u write\u系数来写入更改后的DCT

以下信息可在
libjpeg.txt

To write the contents of a JPEG file as DCT coefficients, you must provide
the DCT coefficients stored in virtual block arrays.  You can either pass
block arrays read from an input JPEG file by jpeg_read_coefficients(), or
allocate virtual arrays from the JPEG compression object and fill them
yourself.  In either case, jpeg_write_coefficients() is substituted for
jpeg_start_compress() and jpeg_write_scanlines().  Thus the sequence is
  * Create compression object
  * Set all compression parameters as necessary
  * Request virtual arrays if needed
  * jpeg_write_coefficients()
  * jpeg_finish_compress()
  * Destroy or re-use compression object
jpeg_write_coefficients() is passed a pointer to an array of virtual block
array descriptors; the number of arrays is equal to cinfo.num_components.

The virtual arrays need only have been requested, not realized, before
jpeg_write_coefficients() is called.  A side-effect of
jpeg_write_coefficients() is to realize any virtual arrays that have been
requested from the compression object's memory manager.  Thus, when obtaining
the virtual arrays from the compression object, you should fill the arrays
after calling jpeg_write_coefficients().  The data is actually written out
when you call jpeg_finish_compress(); jpeg_write_coefficients() only writes
the file header.

When writing raw DCT coefficients, it is crucial that the JPEG quantization
tables and sampling factors match the way the data was encoded, or the
resulting file will be invalid.  For transcoding from an existing JPEG file,
we recommend using jpeg_copy_critical_parameters().  This routine initializes
all the compression parameters to default values (like jpeg_set_defaults()),
then copies the critical information from a source decompression object.
The decompression object should have just been used to read the entire
JPEG input file --- that is, it should be awaiting jpeg_finish_decompress().

jpeg_write_coefficients() marks all tables stored in the compression object
as needing to be written to the output file (thus, it acts like
jpeg_start_compress(cinfo, TRUE)).  This is for safety's sake, to avoid
emitting abbreviated JPEG files by accident.  If you really want to emit an
abbreviated JPEG file, call jpeg_suppress_tables(), or set the tables'
individual sent_table flags, between calling jpeg_write_coefficients() and
jpeg_finish_compress().
因此,要更改单个dct,可以使用以下简单代码: 要访问任何dct系数,您需要更改四个索引,cx、bx、by、bi。 在我的代码中,我使用了
blockptr_one[bi]++
来增加一个dct系数

#include <stdio.h>
#include <jpeglib.h>
#include <stdlib.h>
#include <iostream>
#include <string>    

int write_jpeg_file(std::string outname,jpeg_decompress_struct in_cinfo, jvirt_barray_ptr *coeffs_array ){

    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    FILE * infile;

    if ((infile = fopen(outname.c_str(), "wb")) == NULL) {
      fprintf(stderr, "can't open %s\n", outname.c_str());
      return 0;
    }

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, infile);

    j_compress_ptr cinfo_ptr = &cinfo;
    jpeg_copy_critical_parameters((j_decompress_ptr)&in_cinfo,cinfo_ptr);
    jpeg_write_coefficients(cinfo_ptr, coeffs_array);

    jpeg_finish_compress( &cinfo );
    jpeg_destroy_compress( &cinfo );
    fclose( infile );

    return 1;
}

int read_jpeg_file( std::string filename, std::string outname )
{
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    FILE * infile;

    if ((infile = fopen(filename.c_str(), "rb")) == NULL) {
      fprintf(stderr, "can't open %s\n", filename.c_str());
      return 0;
    }

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, infile);
    (void) jpeg_read_header(&cinfo, TRUE);


    jvirt_barray_ptr *coeffs_array = jpeg_read_coefficients(&cinfo);

    //change one dct:
    int ci = 0; // between 0 and number of image component
    int by = 0; // between 0 and compptr_one->height_in_blocks
    int bx = 0; // between 0 and compptr_one->width_in_blocks
    int bi = 0; // between 0 and 64 (8x8)
    JBLOCKARRAY buffer_one;
    JCOEFPTR blockptr_one;
    jpeg_component_info* compptr_one;
    compptr_one = cinfo.comp_info + ci;
    buffer_one = (cinfo.mem->access_virt_barray)((j_common_ptr)&cinfo, coeffs_array[ci], by, (JDIMENSION)1, FALSE);
    blockptr_one = buffer_one[0][bx];
    blockptr_one[bi]++;

    write_jpeg_file(outname, cinfo, coeffs_array);

    jpeg_finish_decompress( &cinfo );
    jpeg_destroy_decompress( &cinfo );
    fclose( infile );

    return 1;


}

int main()
{
    std::string infilename = "you_image.jpg", outfilename = "out_image.jpg";

    /* Try opening a jpeg*/
    if( read_jpeg_file( infilename, outfilename ) > 0 )
    {
        std::cout << "It's Okay..." << std::endl;
    }
    else return -1;
    return 0;
}
#包括
#包括
#包括
#包括
#包括
int write_jpeg_文件(std::string outname,jpeg_decompression_struct in_cinfo,jvirt_barray_ptr*coefs_数组){
结构jpeg\u压缩\u结构cinfo;
结构jpeg\u错误\u管理器jerr;
文件*填充;
if((infle=fopen(outname.c_str(),“wb”))==NULL){
fprintf(stderr,“无法打开%s\n”,outname.c_str());
返回0;
}
cinfo.err=jpeg\u std\u error(&jerr);
jpeg\u创建\u压缩(&cinfo);
jpeg标准文件(和cinfo,infle);
j_compress_ptr cinfo_ptr=&cinfo;
jpeg_copy_critical_参数((j_decompress_ptr)和in_cinfo,cinfo_ptr);
jpeg_write_系数(cinfo_ptr,系数数组);
jpeg\u完成\u压缩(&cinfo);
jpeg\u destroy\u compress(&cinfo);
fclose(infle);
返回1;
}
int read_jpeg_文件(std::string filename,std::string outname)
{
结构jpeg\u解压缩\u结构cinfo;
结构jpeg\u错误\u管理器jerr;
文件*填充;
if((infle=fopen(filename.c_str(),“rb”))==NULL){
fprintf(stderr,“无法打开%s\n”,filename.c_str());
返回0;
}
cinfo.err=jpeg\u std\u error(&jerr);
jpeg\u创建\u解压缩(&cinfo);
jpeg_stdio_src(&cinfo,infle);
(void)jpeg_read_头(&cinfo,TRUE);
jvirt_barray_ptr*coefs_array=jpeg_read_系数(&cinfo);
//更改一个dct:
int ci=0;//介于0和图像组件数量之间
int by=0;//在0和compptr_one之间->块中的高度
int bx=0;//在0和compptr_one之间->块中的宽度
int bi=0;//介于0和64(8x8)之间
JBLOCKARRAY缓冲区\ 1;
JCOEFPTR blockptr_one;
jpeg_组件_信息*compptr_一;
compptr_one=cinfo.comp_info+ci;
buffer_one=(cinfo.mem->access_virt_barray)((j_common_ptr)和cinfo,coeffs_array[ci],by,(JDIMENSION)1,FALSE);
blockptr_one=缓冲区_one[0][bx];
blockptr_one[bi]+;
写入jpeg文件(outname、cinfo、coeffs\u数组);
jpeg_finish_解压缩(&cinfo);
jpeg\u destroy\u解压缩(&cinfo);
fclose(infle);
返回1;
}
int main()
{
std::string infilename=“you\u image.jpg”,outfilename=“out\u image.jpg”;
/*尝试打开一个jpeg*/
如果(读取jpeg文件(填充名、输出名)>0)
{

std::我不能看Misha!谢谢你的回答!但我不知道如何将你的源代码应用到我的问题中。我也提取了DCT系数。现在我的任务只是将更改后的系数写入同一个jpeg文件。但显然jpeglib不能仅使用函数调用。我不需要更改任何信息,只需要量化DCT值锿。