私のプロジェクトではjcropプラグインを使用しています。問題は、プレビュー画像から画像を切り取って、コントローラから元の画像からその部分を切り抜こうとすると、選択した正確な位置から画像が切り取られないということです。サーバーにイメージを保存し、フロントエンドのプレビューから返された値に従ってクロップします
ユーザーが[参照]をクリックして写真を選択すると、そのイメージをサーバーにアップロードし、サーバーからのそのイメージへのリンク付きのビューを開きます。 プラグインを使用すると、正しくクロッピングされ、ビューでプレビューされます。
イメージが1000px幅と500px高さで、幅が700px、高さが350pxのimg srcにロードするとします(jcropでは、boxwidthとboxheightという固定幅/高さを与えるオプションがあります)。ただし、正確なサイズを指定しても、幅と高さはピクセル+50pxなどで変更されます。
クロップ領域の幅、クロップ領域の高さ、クロップxの座標、crop yのco POSTメソッドの-ordinate。
イメージをPOSTメソッドで切り取っています。ここでは元の画像の幅をプレビュー画像の幅と元の画像の高さをプレビュー画像の高さで除算して画像のスケール差を求め、それをx/y座標値と幅/高さの切り抜き領域に乗算して正しく切り抜きます元の画像から。
バイト[](インターネットからのコード)から画像を切り取っています。私は自分の問題は、この行に '新しい矩形(int x、int y、int width、int height)を使って作図領域を抽出することだと思う。
int値を使用してiamの矩形で浮動小数点値を使用することができなかったので、なぜそのバリエーションが発生するのかと思います。
IAMのは、私の状況を説明するために全力をしようとの「新しいRectangle(」パラメータとしてフラットな値を使用する方法があります。、あなたはこれ以上の説明が必要な場合は私に知らせてください。感謝にあなたを。
ご覧ください。また、より良い私のsitutaionを理解するために、ここで
は、私がこれまで行っている符号化部で下の画像、
ビューページ
@using (Html.BeginForm("PhotoChange", "Profile", FormMethod.Post, new { enctype = "multipart/form-data", id = "changeProfilePhotoForm" }))
{
@Html.HiddenFor(x => x.IsCropped, new { id = "IsCropped", Value = @Model.IsCropped })
@Html.HiddenFor(x => x.PersonID)
@Html.HiddenFor(x => x.PersonDetailID)
@Html.HiddenFor(x => x.Photo)
@Html.HiddenFor(x => x.ImageURL, new { id = "ImageURL", Value = @Model.ImageURL })
@Html.HiddenFor(x => x.CropPointX, new { id = "CropPointX" })
@Html.HiddenFor(x => x.CropPointY, new { id = "CropPointY" })
@Html.HiddenFor(x => x.CropPortionWidth, new { id = "CropPortionWidth" })
@Html.HiddenFor(x => x.CropPortionHeight, new { id = "CropPortionHeight" })
@Html.HiddenFor(x => x.PreviewImageWidth, new { id = "PreviewImageWidth" })
@Html.HiddenFor(x => x.PreviewImageHeight, new { id = "PreviewImageHeight" })
<div class="form-horizontal image-preview-page">
<div class="row">
<div class="form-group">
<div class="col-sm-12">
<div id="profile-image-preview-pane">
<div class="profile-image-preview-container">
<img src="@Model.ImageURL" class="profile-image-preview-image" alt="Preview" />
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-12">
<div class="profile-image-source-wrap">
<img id="profile-image-source" accept="image" name="photo" id="Photo" src="@Model.ImageURL" />
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-sm-12 text-center">
<input type="button" value="Upload" onclick="cropImage()" />
</div>
</div>
</div>
</div>
}
<script type="text/javascript">
var imageCropWidth,
imageCropHeight,
cropPointX,
cropPointY,
jcrop_api,
boundx,
boundy
parent.$('.modal-content').css('height', '510px');
parent.$('.bootstrap-modal-body').css('height', '500px');
parent.$('.modal-content').css('width', '680px');
parent.$('.bootstrap-modal-body').css('width', '690px');
// Grab some information about the preview pane
$preview = $('#profile-image-preview-pane'),
$pcnt = $('#profile-image-preview-pane .profile-image-preview-container'),
$pimg = $('#profile-image-preview-pane .profile-image-preview-container img'),
xsize = $pcnt.width(),
ysize = $pcnt.height();
$('#profile-image-source').Jcrop({
boxWidth: 450, //Maximum width you want for your bigger images
boxHeight: 400, //Maximum Height for your bigger images
minSize: [25, 25],
onChange: updatePreview,
onSelect: updatePreview,
aspectRatio: 1,
bgFade: true, // use fade effect
bgOpacity: .6, // fade opacity
}, function() {
// Use the API to get the real image size
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
// Store the API in the jcrop_api variable
jcrop_api = this;
// Move the preview into the jcrop container for css positioning
$preview.appendTo(jcrop_api.ui.holder);
});
function updatePreview(c) {
if (parseInt(c.w) > 0) {
var rx = xsize/c.w;
var ry = ysize/c.h;
$pimg.css({
width: Math.round(rx * boundx) + 'px',
height: Math.round(ry * boundy) + 'px',
marginLeft: '-' + Math.round(rx * c.x) + 'px',
marginTop: '-' + Math.round(ry * c.y) + 'px'
});
cropPointX = Math.round(c.x);
cropPointY = Math.round(c.y);
imageCropWidth = Math.round(c.w);
imageCropHeight = Math.round(c.h);
$('#CropPointX').val(cropPointX);
$('#CropPointY').val(cropPointY);
$('#CropPortionWidth').val(imageCropWidth);
$('#CropPortionHeight').val(imageCropHeight);
$('#PreviewImageWidth').val($('.jcrop-holder img').width());
$('#PreviewImageHeight').val($('.jcrop-holder img').height());
}
};
function cropImage() {
if (imageCropWidth == 0 && imageCropHeight == 0) {
alert("Please select crop area.");
return;
}
$('#IsCropped').val(true);
$.ajax({
url: "@Url.Action("PhotoChange", "Profile")",
type: 'POST',
data: $("#changeProfilePhotoForm").serialize(),
async: false,
success: function (data) {
parent.ChangeImageAfterSave('@ViewData["CroppedImage"]')
},
error: function (data) { }
});
}
</script>
コントローラのページ
[HttpPost]
public ActionResult PhotoChange(ProfilePicVM profilePic, HttpPostedFileBase photo)
{
bool isUpdated = false;
string fileName = string.Empty;
byte[] imageBytes = null;
byte[] croppedImage = null;
int scaleValueX = 0;
int scaleValueY = 0;
try
{
imageBytes = System.IO.File.ReadAllBytes(Server.MapPath(profilePic.ImageURL));
System.Drawing.Image image = System.Drawing.Image.FromStream(new System.IO.MemoryStream(imageBytes));
if (image.Width >= profilePic.PreviewImageWidth || image.Height >= profilePic.PreviewImageHeight)
{
scaleValueX = image.Width/profilePic.PreviewImageWidth;
scaleValueY = image.Height/profilePic.PreviewImageHeight;
}
croppedImage = ProfileController.CropImage(imageBytes, scaleValueX * profilePic.CropPointX, scaleValueY * profilePic.CropPointY, scaleValueX * profilePic.CropPortionWidth, scaleValueY * profilePic.CropPortionHeight);
string tempFolderName = Server.MapPath("~/uploads/PersonProfile/");
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(profilePic.ImageURL);
fileName = Path.GetFileName(profilePic.ImageURL).Replace(fileNameWithoutExtension, fileNameWithoutExtension + "_cropped");
profilePic.ImageCroppedURL = string.Concat(tempFolderName, fileName);
FileHelper.SaveFile(croppedImage, Path.Combine(tempFolderName, fileName));
isUpdated = (new PersonDetailService(this.GdbObject)).UpdateProfilePhoto(profilePic.PersonDetailID, fileName);
if (isUpdated)
{
this.ViewData["CroppedImage"] = fileName;
}
}
catch (Exception ex)
{
}
return this.View(profilePic);
}
public static byte[] CropImage(byte[] content, int x, int y, int width, int height)
{
using (MemoryStream stream = new MemoryStream(content))
{
return CropImage(stream, x, y, width, height);
}
}
public static byte[] CropImage(Stream content, int x, int y, int width, int height)
{
//// Parsing stream to bitmap
using (Bitmap sourceBitmap = new Bitmap(content))
{
//// Get new dimensions
double sourceWidth = Convert.ToDouble(sourceBitmap.Size.Width);
double sourceHeight = Convert.ToDouble(sourceBitmap.Size.Height);
Rectangle cropRect = new Rectangle (x, y, width, height);
//// Creating new bitmap with valid dimensions
using (Bitmap newBitMap = new Bitmap(cropRect.Width, cropRect.Height))
{
using (Graphics g = Graphics.FromImage(newBitMap))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.DrawImage(sourceBitmap, new Rectangle(0, 0, newBitMap.Width, newBitMap.Height), cropRect, GraphicsUnit.Pixel);
return GetBitmapBytes(newBitMap);
}
}
}
}
public static byte[] GetBitmapBytes(Bitmap source)
{
////Settings to increase quality of the image
ImageCodecInfo codec = ImageCodecInfo.GetImageEncoders()[4];
EncoderParameters parameters = new EncoderParameters(1);
parameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
////Temporary stream to save the bitmap
using (MemoryStream tmpStream = new MemoryStream())
{
source.Save(tmpStream, codec, parameters);
////Get image bytes from temporary stream
byte[] result = new byte[tmpStream.Length];
tmpStream.Seek(0, SeekOrigin.Begin);
tmpStream.Read(result, 0, (int)tmpStream.Length);
return result;
}
}
それに応じて高さも変わった。 –