Répondre

0

Cela dépend de ce que vous êtes prêt à changer

  1. Faire la taille de l'image plus petite
  2. Modifier le format de l'image
  3. Si le format supporte une compression avec perte, diminuer la qualité
  4. Si vous stockez des méta-données que vous n'avez pas besoin, retirez-le
  5. Réduire le nombre de couleurs (et bits par pixel)
  6. Changement à un format palettisée
  7. Modifier un format palettisée et réduire les couleurs

Il est difficile de deviner ce que la taille du disque final sera, mais si vous connaissez un point de départ, vous pouvez obtenir une assez bonne estimation . La réduction de la taille sera probablement proportionnelle, la réduction des bits par pixel sera probablement proportionnelle.

Si vous changez le format, la compression ou la qualité, c'est vraiment une supposition - cela dépend fortement du contenu de l'image.Vous pourriez probablement obtenir une bonne gamme en l'essayant sur un corpus d'images qui correspond à ce que vous pensez que vous verrez.

7

Vous pouvez calculer un niveau d'information approximative pour l'image en prenant la taille de l'image originale divisée par le nombre de pixels:

info = fileSize/(width * height); 

J'ai une image qui est 369636 octets et 1200x800 pixels, il utilise ~ 0,385 octets par pixel.

J'ai une version plus petite qui est 101111 octets et 600x400 pixels, donc il utilise ~ 0.4213 octets par pixel. Lorsque vous réduisez une image, vous verrez qu'elle contient généralement un peu plus d'informations par pixel, dans ce cas environ 9% de plus. En fonction de votre type d'images et combien vous les psy, vous devriez être en mesure de calculer une moyenne pour combien l'augmentation des rations d'information/pixel (c), de sorte que vous pouvez calculer une taille approximative du fichier:

newFileSize = (fileSize/(width * height)) * (newWidth * newHeight) * c 

de cela, vous pouvez extraire une formule pour la taille que vous devez faire une image pour atteindre une taille de fichier spécifique:

newWidth * newHeight = (newFileSize/fileSize) * (width * height)/c 

cela vous être assez proche de la taille du fichier souhaité. Si vous voulez vous rapprocher, vous pouvez redimensionner l'image à la taille calculée, la compresser et calculer une nouvelle valeur en octets par pixel à partir de la taille du fichier que vous avez obtenu.

1

Si elle est un 24bit BMP je pense que vous devez faire quelque chose comme ceci:

//initial size = WxH 
long bitsperpixel = 24; //for 24 bit BMP 
double ratio; 
long size = 2 * 1 << 20;//2MB = 2 * 2^20 
size -= 0x35;//subtract the BMP header size from it 
long newH, newW, left, right, middle,BMProwsize; 
left = 1; 
right = size;//binary search for new width and height 
while (left < right) 
{ 
    middle = (left + right + 1)/2; 
    newW = middle; 
    ratio = Convert.ToDouble(newW)/Convert.ToDouble(W); 
    newH = Convert.ToInt64(ratio * Convert.ToDouble(H)); 
    BMProwsize = 4 * ((newW * bitsperpixel + 31)/32); 
    //row size must be multiple of 4 
    if (BMProwsize * newH <= size) 
     left = middle; 
    else 
     right = middle-1;     
} 

newW = left; 
ratio = Convert.ToDouble(newW)/Convert.ToDouble(W); 
newH = Convert.ToInt64(ratio * Convert.ToDouble(H)); 
//resize image to newW x newH and it should fit in <= 2 MB 

S'il est un autre type BMP comme 8 bits BMP également dans la section d'en-tête, il y aura plus de données spécifiant les couleur réelle de chaque valeur de 0 à 255, vous devrez donc soustraire plus de la taille totale du fichier avant la recherche binaire.

2

J'ai réalisé ceci en réduisant la qualité jusqu'à ce que j'aie atteint la taille désirée.

NB: vous devez ajouter la référence System.Drawing.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.IO; 
using System.Drawing; 
using System.Drawing.Imaging; 
using System.Drawing.Drawing2D; 

namespace PhotoShrinker 
{ 
class Program 
{ 
/// <summary> 
/// Max photo size in bytes 
/// </summary> 
const long MAX_PHOTO_SIZE = 409600; 

static void Main(string[] args) 
{ 
    var photos = Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.jpg"); 

    foreach (var photo in photos) 
    { 
     var photoName = Path.GetFileNameWithoutExtension(photo); 

     var fi = new FileInfo(photo); 
     Console.WriteLine("Photo: " + photo); 
     Console.WriteLine(fi.Length); 

     if (fi.Length > MAX_PHOTO_SIZE) 
     { 
      using (var image = Image.FromFile(photo)) 
      { 
        using (var stream = DownscaleImage(image)) 
        { 
         using (var file = File.Create(photoName + "-smaller.jpg")) 
         { 
          stream.CopyTo(file); 
         } 
        } 
      } 
      Console.WriteLine("File resized."); 
     } 
     Console.WriteLine("Done.") 
     Console.ReadLine(); 
    } 

} 

private static MemoryStream DownscaleImage(Image photo) 
{ 
    MemoryStream resizedPhotoStream = new MemoryStream(); 

    long resizedSize = 0; 
    var quality = 93; 
    //long lastSizeDifference = 0; 
    do 
    { 
     resizedPhotoStream.SetLength(0); 

     EncoderParameters eps = new EncoderParameters(1); 
     eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)quality); 
     ImageCodecInfo ici = GetEncoderInfo("image/jpeg"); 

     photo.Save(resizedPhotoStream, ici, eps); 
     resizedSize = resizedPhotoStream.Length; 

     //long sizeDifference = resizedSize - MAX_PHOTO_SIZE; 
     //Console.WriteLine(resizedSize + "(" + sizeDifference + " " + (lastSizeDifference - sizeDifference) + ")"); 
     //lastSizeDifference = sizeDifference; 
     quality--; 

    } while (resizedSize > MAX_PHOTO_SIZE); 

    resizedPhotoStream.Seek(0, SeekOrigin.Begin); 

    return resizedPhotoStream; 
} 

private static ImageCodecInfo GetEncoderInfo(String mimeType) 
{ 
    int j; 
    ImageCodecInfo[] encoders; 
    encoders = ImageCodecInfo.GetImageEncoders(); 
    for (j = 0; j < encoders.Length; ++j) 
    { 
     if (encoders[j].MimeType == mimeType) 
      return encoders[j]; 
    } 
    return null; 
} 
} 
} 
+0

merci, super échantillon de travail. Je l'ai changé pour abaisser la qualité 5 unités à la fois et l'ai utilisé dans mon asp.net –

+1

heureux je pourrais aider quelqu'un d'autre dehors! J'ai remarqué que le Image.FromFile (photo) n'était pas éliminé correctement! J'ai mis à jour mon code pour disposer correctement. –

Questions connexes