Недопустимый параметр Image.Save

Я хочу поставить водяной знак на файлы в папке с другим изображением. Однако получаю ошибку

«Параметр недействителен»

при вызове кода

img.Save(filepath, System.Drawing.Imaging.ImageFormat.Jpeg);

У меня есть следующий код;

    public static string WatermarkImagesInFolder(string url)
    {
        if (url == null)
            throw new Exception("URL must be provided");

        string path = HttpContext.Current.Server.MapPath(url);

        if (!Directory.Exists(path))
            throw new DirectoryNotFoundException();

        Directory.CreateDirectory(String.Format(@"{0}\watermarked", path));

        List<string> urls = GetJpgFilesFromFolder(path);

        foreach (string imageUrl in urls)
        {
            Image img = WatermarkImage(imageUrl);

            string filename = Path.GetFileName(imageUrl);
            string filepath = String.Format(@"{0}\watermarked\{1}", path, filename);
            img.Save(filepath, System.Drawing.Imaging.ImageFormat.Jpeg);
        }

        return "complete";
    }

и

    public static Image WatermarkImage(string filename)
    {
        using (Image image = Image.FromFile(filename))
        using (Image watermarkImage = Image.FromFile(HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["WatermarkImageUrl"])))
        using (Graphics imageGraphics = Graphics.FromImage(image))
        using (TextureBrush watermarkBrush = new TextureBrush(watermarkImage))
        {
            int x = (image.Width / 2 - watermarkImage.Width / 2);
            int y = (image.Height / 2 - watermarkImage.Height / 2);
            watermarkBrush.TranslateTransform(x, y);
            imageGraphics.FillRectangle(watermarkBrush, new Rectangle(new Point(x, y), new Size(watermarkImage.Width + 1, watermarkImage.Height)));
            return image;
        }
    }

как пример ввода для img.save;

img.save("C:\\IMAGES\\wateremarked\\IMAGE (1).jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

Любые идеи о том, что может быть причиной ошибки здесь, пожалуйста?


person Matthew Flynn    schedule 11.08.2016    source источник
comment
пожалуйста, покажите эту функцию GetJpgFilesFromFolder   -  person naveen    schedule 11.08.2016


Ответы (2)


В вашем WatermarkImage у вас есть объект изображения в операторе использования. Как только это выходит за рамки, для изображения вызывается Dispose. Вам нужно будет вернуть копию изображения - или не использовать оператор using и убедиться, что вы правильно утилизируете его позже.

См.: Исключение: параметр недействителен (на передача нового изображения в pictureBox)

public static string WatermarkImagesInFolder(string url)
{
    if (url == null)
        throw new Exception("URL must be provided");

    string path = HttpContext.Current.Server.MapPath(url);

    if (!Directory.Exists(path))
        throw new DirectoryNotFoundException();

    Directory.CreateDirectory(String.Format(@"{0}\watermarked", path));

    List<string> urls = GetJpgFilesFromFolder(path);

    foreach (string imageUrl in urls)
    {
        using(Image img = WatermarkImage(imageUrl))
        {
        string filename = Path.GetFileName(imageUrl);
        string filepath = String.Format(@"{0}\watermarked\{1}", path, filename);
        img.Save(filepath, System.Drawing.Imaging.ImageFormat.Jpeg);
        }
    }

    return "complete";
}

public static Image WatermarkImage(string filename)
{
    Image image = Image.FromFile(filename);
    using (Image watermarkImage = Image.FromFile(HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["WatermarkImageUrl"])))
    using (Graphics imageGraphics = Graphics.FromImage(image))
    using (TextureBrush watermarkBrush = new TextureBrush(watermarkImage))
    {
        int x = (image.Width / 2 - watermarkImage.Width / 2);
        int y = (image.Height / 2 - watermarkImage.Height / 2);
        watermarkBrush.TranslateTransform(x, y);
        imageGraphics.FillRectangle(watermarkBrush, new Rectangle(new Point(x, y), new Size(watermarkImage.Width + 1, watermarkImage.Height)));
        return image;
    }
}
person PaulF    schedule 11.08.2016
comment
Спасибо что подметил это. Не видел леса за деревьями. - person Matthew Flynn; 11.08.2016

Вот мое альтернативное решение, которое дает возможность использовать поток изображений, но не его местоположение, поскольку оно в настоящее время просматривается из Kendo Control, как в моем примере, и до сих пор не имеет физического местоположения.

    public static Image ApplyWatermark(HttpPostedFileBase img, string appDataPath)
{
    Image resultImage = null;
    using (Image image = Image.FromStream(img.InputStream))
    {
        using (Image watermarkImage = Image.FromFile(appDataPath + "\\Watermark\\sample-watermark.png"))
        {
            using (Graphics imageGraphics = Graphics.FromImage(image))
            {
                using (Brush watermarkBrush = new TextureBrush(watermarkImage))
                {
                    imageGraphics.FillRectangle(watermarkBrush, new Rectangle(new Point(0, 0), image.Size));
                    resultImage = (Image)image.Clone();
                }
            }
        }
    }

    return resultImage;
}

private void SaveImagesOnDisk(IEnumerable<HttpPostedFileBase> images, int rentalPropertyId)
    {
        if (images != null)
        {
            foreach (var file in images)
            {
                // Some browsers send file names with full path. This needs to be stripped.
                var fileName = Path.GetFileName(file.FileName);
                var appDataPath = this.Server.MapPath("~/App_Data/");
                var newPath = Path.Combine(appDataPath, rentalPropertyId.ToString());
                if (!Directory.Exists(newPath))
                {
                    DirectoryInfo di = Directory.CreateDirectory(newPath);
                }

                var physicalPath = Path.Combine(newPath, fileName);
                System.Drawing.Image markedImage = Helper.ApplyWatermark(file, appDataPath);
                markedImage.Save(physicalPath, System.Drawing.Imaging.ImageFormat.Png);
            }
        }

        //return this.Json(new { status = "OK" }, "text/plain");
    }
person ppenchev    schedule 13.01.2017