首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何以无损的编程方式将多个JPEG组合成更大的JPEG (.net)

如何以无损的编程方式将多个JPEG组合成更大的JPEG (.net)
EN

Stack Overflow用户
提问于 2010-09-13 14:05:28
回答 3查看 4.2K关注 0票数 2

我有几个JPEG图像,我想把它们组合成一个大的JPEG图像。

我可以创建一个Bitmap,然后将它们组合在一起,但如果我再次将其另存为JPEG,图像将会恶化。

那么,有没有什么方法可以在解码/编码时不损失质量的情况下做到这一点?

在ACDSee程序中,我看到了一个旋转JPEG而不损失质量的选项,所以可能有一种方法可以组合多个图像而不损失质量。

谢谢

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-09-17 23:48:37

好的,我已经写了代码,所以我想在这里分享它:)

请注意,代码不会在所有情况下工作,但它对我的使用很好。

我使用的是LibJpeg.Net库http://bitmiracle.com/libjpeg

此外,库中有一个错误(或me中的一个错误:),您无法获得组件height_in_blocks,这就是为什么该代码只能在正方形的tiles上工作。

我认为图像需要具有与Vlasta提到的相同的量化表。

我认为这段代码可以扩展以支持这一点,但是我不需要这样的支持。

现在代码来了:)

代码语言:javascript
运行
复制
public void CreateBigImage()
{
    const int iTileWidth = 256;
    const int iTileHeigth = 256;
    int iImageWidthInTiles = 2;
    int iImageHeigthInTiles = 2;

    //Open Image to read its header in the new image
    BitMiracle.LibJpeg.Classic.jpeg_decompress_struct objJpegDecompressHeader = new BitMiracle.LibJpeg.Classic.jpeg_decompress_struct();
    System.IO.FileStream objFileStreamHeaderImage = new System.IO.FileStream(GetImagePath(0), System.IO.FileMode.Open, System.IO.FileAccess.Read);
    objJpegDecompressHeader.jpeg_stdio_src(objFileStreamHeaderImage);
    objJpegDecompressHeader.jpeg_read_header(true);

    BitMiracle.LibJpeg.Classic.jvirt_array<BitMiracle.LibJpeg.Classic.JBLOCK>[] varrJBlockBigImage = new BitMiracle.LibJpeg.Classic.jvirt_array<BitMiracle.LibJpeg.Classic.JBLOCK>[10];
    for (int i = 0; i < 3; i++)//3 compounds per image (YCbCr)
    {
        int iComponentWidthInBlocks = objJpegDecompressHeader.Comp_info[i].Width_in_blocks;
        int iComponentHeigthInBlocks = iComponentWidthInBlocks;//there is no Height_in_blocks in the library so will use widht for heigth also (wont work if image is not rectangular)
        varrJBlockBigImage[i] = BitMiracle.LibJpeg.Classic.jpeg_common_struct.CreateBlocksArray(iComponentWidthInBlocks * iImageWidthInTiles, iComponentHeigthInBlocks * iImageHeigthInTiles);
    }

    for (int iX = 0; iX < iImageWidthInTiles; iX++)
    {
        for (int iY = 0; iY < iImageHeigthInTiles; iY++)
        {
            WriteImageToJBlockArr(varrJBlockBigImage, GetImagePath(iY*iImageHeigthInTiles+iX), iX, iY);
        }
    }

    System.IO.FileStream objFileStreamMegaMap = System.IO.File.Create(GetImagePath(999));
    BitMiracle.LibJpeg.Classic.jpeg_compress_struct objJpegCompress = new BitMiracle.LibJpeg.Classic.jpeg_compress_struct();
    objJpegCompress.jpeg_stdio_dest(objFileStreamMegaMap);
    objJpegDecompressHeader.jpeg_copy_critical_parameters(objJpegCompress);//will copy the critical parameter from the header image
    objJpegCompress.Image_height = iTileHeigth * iImageHeigthInTiles;
    objJpegCompress.Image_width = iTileWidth * iImageWidthInTiles;
    objJpegCompress.jpeg_write_coefficients(varrJBlockBigImage);
    objJpegCompress.jpeg_finish_compress();
    objFileStreamMegaMap.Close();

    objJpegDecompressHeader.jpeg_abort_decompress();
    objFileStreamHeaderImage.Close();
}

public void WriteImageToJBlockArr(BitMiracle.LibJpeg.Classic.jvirt_array<BitMiracle.LibJpeg.Classic.JBLOCK>[] varrJBlockNew, string strImagePath, int iTileX, int iTileY)
{
    BitMiracle.LibJpeg.Classic.jpeg_decompress_struct objJpegDecompress = new BitMiracle.LibJpeg.Classic.jpeg_decompress_struct();
    System.IO.FileStream objFileStreamImage = new System.IO.FileStream(strImagePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
    objJpegDecompress.jpeg_stdio_src(objFileStreamImage);
    objJpegDecompress.jpeg_read_header(true);
    BitMiracle.LibJpeg.Classic.jvirt_array<BitMiracle.LibJpeg.Classic.JBLOCK>[] varrJBlockOrg = objJpegDecompress.jpeg_read_coefficients();
    for (int i = 0; i < 3; i++)//3 compounds per image (YCbCr)
    {
        int iComponentWidthInBlocks = objJpegDecompress.Comp_info[i].Width_in_blocks;
        int iComponentHeigthInBlocks = iComponentWidthInBlocks;//there is no Height_in_blocks in the library so will use widht for heigth also (wont work if image is not rectangular)
        for (int iY = 0; iY < iComponentHeigthInBlocks; iY++)
        {
            for (int iX = 0; iX < iComponentWidthInBlocks; iX++)
            {
                varrJBlockNew[i].Access(iY + iTileY * iComponentHeigthInBlocks, 1)[0][iX + iTileX * iComponentWidthInBlocks] = varrJBlockOrg[i].Access(iY, 1)[0][iX];
            }
        }
    }
    objJpegDecompress.jpeg_finish_decompress();
    objFileStreamImage.Close();
}
票数 1
EN

Stack Overflow用户

发布于 2010-09-13 14:25:17

根据Wikipedia/Jpeg的说法,如果你的图像大小是16的倍数,这是可能的。

Wikipedia/Lossless editing/JPEG还谈到了可以组合多个图像的JPEGJoin。

虽然.NET框架中没有内置任何东西,但您可以使用C#中的上述工具。

票数 5
EN

Stack Overflow用户

发布于 2010-09-14 08:01:06

几乎所有无损的JPEG工具都是基于http://sylvana.net/jpegcrop/jpegtran/的jpegtran (源代码可用)。

您需要的是扩展jpeg画布,然后使用仍处于实验阶段的"drop“功能将一个图像放入另一个图像中。

我不确定这一点,但我认为图像需要使用相同的量化表(~编码质量)才能无损地连接。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3698123

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档