2010-09-13 20 views
2

J'ai plusieurs images JPEG et je veux les combiner en une seule grande image JPEG.Comment combiner plusieurs fichiers JPEG en un fichier JPEG plus grand sans perte de programmation (.net)

Je peux le faire en créant un Bitmap puis en les combinant mais de cette façon, si je le sauvegarde à nouveau au format JPEG, l'image se détériorera.

Alors, y a-t-il une méthode que je peux utiliser pour faire cela sans perdre en qualité lors du décodage/encodage?

Dans le programme ACDSee, j'ai vu une option permettant de faire pivoter les fichiers JPEG sans perte de qualité. Il est donc possible de combiner plusieurs images sans perte de qualité.

grâce

Répondre

1

bien que j'ai écrit le code et donc je voulais le partager ici :)
s'il vous plaît noter que le code ne fonctionnera pas sur toutes les situations mais son bien pour mon utilisation. J'utilise la librairie LibJpeg.Net http://bitmiracle.com/libjpeg.
aussi il y a un bug dans la bibliothèque (ou un bug en moi :)) que vous ne pouvez pas obtenir le composant height_in_blocks c'est pourquoi ce code ne fonctionnera que sur les carreaux carrés.
Je pense que les images doivent avoir la même table de quantification que Vlasta mentionné.
Je pense que ce code peut être étendu pour supporter cela mais bon je n'ai pas besoin d'un tel soutien.
et vient maintenant ici le code :)

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(); 
} 
5

Selon Wikipedia/Jpeg il pourrait être possible que si vos images ont des tailles multiples de 16.

Wikipedia/Lossless editing/JPEG parle aussi de JPEGJoin qui peuvent combiner plusieurs images.

Il n'y a rien de construit dans .NET Framework, mais vous pourriez utiliser les outils ci-dessus de C#.

+0

mes images sont des multiples de 16. jpegjoin est un programme mais je besoin d'une bibliothèque puisque j'ai besoin d'automatiser le processus. – Karim

+0

je regarde la librairie @ LibJpeg.Net http://bitmiracle.com/libjpeg/. que j'ai trouvé dans l'article wikipedia, mais je ne vois toujours rien qui me permettra de fusionner plusieurs jpegs ensemble. – Karim

3

Presque tous les outils JPEG sans perte sont basés sur jpegtran de http://sylvana.net/jpegcrop/jpegtran/ (le code source est disponible). Ce dont vous avez besoin est d'étendre le canevas jpeg, puis d'utiliser la fonctionnalité "drop" encore expérimentale pour placer une image dans une autre image.

Je ne suis pas sûr de cela, mais je pense que les images doivent utiliser les mêmes tables de quantification (~ qualité d'encodage) afin d'être joint sans perte.

+0

merci beaucoup. mais il y a plusieurs fichiers sources sur cette page. pouvez-vous me guider lequel exactement mettre en œuvre cette fonctionnalité? – Karim

+0

Vous devriez probablement commencer par droppatch8.zip, bien que je ne l'ai pas essayé moi-même. – Vlasta

+0

merci, va essayer, en espérant toujours trouver le code .net qui fait cela et peut-être une explication sur la façon de le faire :) – Karim