どのようにリサイズ画像をクライアントまで、フルのC#特定のハードディスクの大きさはどれくらいですか?
-
12-09-2019 - |
質問
どのようにリサイズ画像の画像をクライアントまで、フルのC#特定のハードディスクサイズのように、2MiB?がより良い方法をより試行錯誤がで近似しますか?
特定のキーワードで検索しようとした場合に解決策を見つけのウェブ?
解決
でかいの変更
- の画像のサイズを小さく
- の書式を変更画像
- る場合の形式に対応し、非可逆圧縮、減らし、品質
- の場合は保存メタデータが必要なように
- 点数の削減色(ビットピクセル)
- 変更paletted形式
- 変更paletted形式の削減色
でか最後のディスクサイズが合わなくてはならない点ができても良い。削減のサイズは、その比例減のビットピクセルのものが比例する。
変更した場合の形式は、圧縮品質で本当にただのん--に依存する画像の内容です。きょういくようなコーパスの像と一致するお返事ありがとうございます。きます。
他のヒント
は画素数で割った元の画像サイズを取ることによって、画像のおおよその情報レベルを計算することができる:
info = fileSize / (width * height);
Iは、369636バイトと1200x800ピクセルの画像を持っているので、画素毎〜0.385バイトを使用する。
Iは、101111バイトと600x400ピクセルである小さいバージョンを持っているので、画素毎〜0.4213バイトを使用する。
場合、あなたはそれは、一般に、約9%より多く、この場合には、ピクセル当たりわずかにより多くの情報を含むことになることがわかります画像を縮小。あなたのイメージの種類とどのくらいあなたがそれらを縮小によって、あなたがおおよそのファイルサイズを計算することができるように、どの程度の情報/ピクセル比増加(C)の平均を計算することができる必要があります:
newFileSize = (fileSize / (width * height)) * (newWidth * newHeight) * c
このことから、あなたは、特定のファイルサイズに到達するために画像を作成する必要がどのように大規模な式を抽出することができます:
newWidth * newHeight = (newFileSize / fileSize) * (width * height) / c
これは、目的のファイルサイズにあなたは非常に近いでしょう。あなたが近づく取得したい場合は、計算されたサイズに画像のサイズを変更し、それを圧縮し、あなたが得た、ファイルサイズからピクセル値ごとに新しいバイトを計算することができます。
私は私の希望のサイズに達するまで、品質を低下させることによって、これを達成します。
NB:。た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;
}
}
}
BMPは、私はあなたがこのような何かをする必要があると思います:
//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
それが8ビットBMPのような異なるBMPタイプは、ヘッダセクションに0から255までの各値の実際の色を指定する、より多くのデータが存在することになる場合は、あなたはバイナリの前に総ファイルサイズからより多くを減算する必要があります検索ます。
(MVC)を(メモリ内で、反復)の削減、変換&ダウンロード
public ActionResult ReduceFileSize(string ImageURL, long MAX_PHOTO_SIZE) //KB
{
var photo = Server.MapPath("~/" + ImageURL); //Files/somefiles/2018/DOC_82401583cb534b95a10252d29a1eb4ee_1.jpg
var photoName = Path.GetFileNameWithoutExtension(photo);
var fi = new FileInfo(photo);
//const long MAX_PHOTO_SIZE = 100; //KB //109600;
var MAX_PHOTO_SIZE_BYTES = (MAX_PHOTO_SIZE * 1000);
if (fi.Length > MAX_PHOTO_SIZE_BYTES)
{
using (var image = Image.FromFile(photo))
{
using (var mstream = DownscaleImage(image, MAX_PHOTO_SIZE_BYTES))
{
//Convert the memorystream to an array of bytes.
byte[] byteArray = mstream.ToArray();
//Clean up the memory stream
mstream.Flush();
mstream.Close();
// Clear all content output from the buffer stream
Response.Clear();
// Add a HTTP header to the output stream that specifies the default filename
// for the browser's download dialog
Response.AddHeader("Content-Disposition", "attachment; filename=" + fi.Name);
// Add a HTTP header to the output stream that contains the
// content length(File Size). This lets the browser know how much data is being transfered
Response.AddHeader("Content-Length", byteArray.Length.ToString());
// Set the HTTP MIME type of the output stream
Response.ContentType = "application/octet-stream";
// Write the data out to the client.
Response.BinaryWrite(byteArray);
}
}
}
else
{
return null;
}
return null;
}
private static MemoryStream DownscaleImage(Image photo, long MAX_PHOTO_SIZE_BYTES)
{
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_BYTES);
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;
}