[C#] GDI +, JPEG 이미지에서 MemoryStream으로 일반 오류가 발생했습니다.

이것은 웹 전체에서 약간의 악명 높은 오류 인 것 같습니다. 시나리오가 맞지 않아서 문제에 대한 답변을 찾지 못했습니다. 이미지를 스트림에 저장하면 예외가 발생합니다.

이상하게도 이것은 png와 완벽하게 작동하지만 다소 혼란스러운 jpg와 gif에 대한 위의 오류를 제공합니다.

가장 비슷한 문제는 이미지를 권한없이 파일에 저장하는 것과 관련이 있습니다. 아이러니하게도 해결책은 내가하고있는 것처럼 메모리 스트림을 사용하는 것입니다.

public static byte[] ConvertImageToByteArray(Image imageToConvert)
{
    using (var ms = new MemoryStream())
    {
        ImageFormat format;
        switch (imageToConvert.MimeType())
        {
            case "image/png":
                format = ImageFormat.Png;
                break;
            case "image/gif":
                format = ImageFormat.Gif;
                break;
            default:
                format = ImageFormat.Jpeg;
                break;
        }

        imageToConvert.Save(ms, format);
        return ms.ToArray();
    }
}

예외에 대한 자세한 내용. 이것이 많은 문제를 일으키는 이유는 설명이 없기 때문입니다.

System.Runtime.InteropServices.ExternalException was unhandled by user code
Message="A generic error occurred in GDI+."
Source="System.Drawing"
ErrorCode=-2147467259
StackTrace:
   at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters    encoderParams)
   at System.Drawing.Image.Save(Stream stream, ImageFormat format)
   at Caldoo.Infrastructure.PhotoEditor.ConvertImageToByteArray(Image imageToConvert) in C:\Users\Ian\SVN\Caldoo\Caldoo.Coordinator\PhotoEditor.cs:line 139
   at Caldoo.Web.Controllers.PictureController.Croppable() in C:\Users\Ian\SVN\Caldoo\Caldoo.Web\Controllers\PictureController.cs:line 132
   at lambda_method(ExecutionScope , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
 InnerException: 

내가 지금까지 시도한 것들.

  1. 이미지를 복제하고 그 작업.
  2. JPEG 품질 설정으로 MIME에 대한 인코더를 검색합니다.


답변

좋아, 나는 단지 운이 좋은 원인으로 그 원인을 찾았고 그 특정 방법에는 아무런 문제가 없다고 생각한다. 이는 콜 스택을 더 백업한다.

이전에 이미지 크기를 조정하고 해당 메소드의 일부로 다음과 같이 크기 조정 된 객체를 반환합니다. 위의 메소드에 대한 두 번의 호출과 파일에 직접 저장을 삽입했습니다.

// At this point the new bitmap has no MimeType
// Need to output to memory stream
using (var m = new MemoryStream())
{
       dst.Save(m, format);

       var img = Image.FromStream(m);

       //TEST
       img.Save("C:\\test.jpg");
       var bytes = PhotoEditor.ConvertImageToByteArray(img);


       return img;
 }

이 오브젝트이 작성된 메모리 스트림이 나타납니다 객체가 저장되는 시간 오픈 할 수 있습니다. 왜 그런지 잘 모르겠습니다. 누구든지 나를 깨우칠 수 있고 어떻게 해결할 수 있습니까?

난 단지 때문에 유사한 크기 조정 코드 사용 후 스트림에서 반환 그것은 하드 쓰기 일반적인 만드는 모든 이미지 객체에 대한 올바른 것으로 MIME 타입과 같은 대상 파일이 알 수없는 MIME 형식을 가지고 (img.RawFormat.Guid)과 ID를 그렇지 않으면 코드를 처리합니다.

편집하다

이것은 내 초기 검색에서 나타나지 않았지만 여기에 Jon Skeet의 답변이 있습니다.


답변

해당 오류가 발생하면 응용 프로그램에 일부 디렉토리에 대한 쓰기 권한이 없다고 말할 수 있습니다.

예를 들어, 이미지를 메모리 스트림에서 파일 시스템으로 저장하려고하면 해당 오류가 발생할 수 있습니다.

XP를 사용하는 경우 해당 폴더에 aspnet 계정에 대한 쓰기 권한을 추가하십시오.

Windows 서버 (2003,2008) 또는 Vista를 사용하는 경우 네트워크 서비스 계정에 대한 쓰기 권한을 추가하십시오.

그것이 도움이되기를 바랍니다.


답변

이 오류의 원인을 추가하여 미래의 인터넷 여행자에게 도움이되기를 바랍니다. 🙂

GDI +는 이미지의 최대 높이를 65500으로 제한합니다

기본 이미지 크기 조정을 수행하지만 크기 조정시 종횡비를 유지하려고합니다. 우리는이 일을 조금 잘하는 QA 녀석이 있습니다. 그는 키가 480 픽셀 인 1 픽셀 너비의 사진으로 이것을 테스트하기로 결정했습니다. 이미지가 크기에 맞게 크기가 조정되었을 때 높이는 68,000 픽셀의 북쪽에 있었고 앱은으로 폭발했습니다 A generic error occurred in GDI+.

테스트로 직접 확인할 수 있습니다.

  int width = 480;
  var height = UInt16.MaxValue - 36; //succeeds at 65499, 65500
  try
  {
    while(true)
    {
      var image = new Bitmap(width, height);
      using(MemoryStream ms = new MemoryStream())
      {
        //error will throw from here
        image.Save(ms, ImageFormat.Jpeg);
      }
      height += 1;
    }
  }
  catch(Exception ex)
  {
    //explodes at 65501 with "A generic error occurred in GDI+."
  }

ArgumentException의 생성자에 친화적 인 .net이없는 것은 너무 나쁩니다 Bitmap.


답변

이 기사에서는 정확히 어떤 일이 발생하는지 설명합니다 : 비트 맵 및 이미지 생성자 종속성

요컨대, stream으로Image 구성된 수명 동안 스트림은 파괴되어서는 안됩니다.

그래서 대신

using (var strm = new ... )  {
    myImage = Image.FromStream(strm);
}

이 시도

Stream imageStream;
...

    imageStream = new ...;
    myImage = Image.FromStream(strm);

같이 ImageStream 형태 가까이 또는 웹 페이지 가까이에서.


답변

잘못된 경로에 저장하려고하거나 권한 문제가있는 경우에도이 예외가 발생합니다.

파일 경로가 사용 가능하고 권한이 올바른지 100 % 확실하지 않은 경우 텍스트 파일에을 쓰십시오. 아주 간단한 해결책을 배제하는 데 몇 초 밖에 걸리지 않습니다.

var img = System.Drawing.Image.FromStream(incomingStream);

// img.Save(path);
System.IO.File.WriteAllText(path, "Testing valid path & permissions.");

파일을 정리하는 것을 잊지 마십시오.


답변

비트 맵 변수에 이미지 저장

using (var ms = new MemoryStream())
{
    Bitmap bmp = new Bitmap(imageToConvert);
    bmp.Save(ms, format);
    return ms.ToArray();
}


답변

누군가가 내가 멍청한 짓을한다면 1. 경로가 존재하는지 확인하십시오. 2. 쓰기 권한이 있는지 확인하십시오. 3. 경로가 올바른지 확인하십시오. 필자의 경우 TargetPath에 파일 이름이 없습니다.

“GDI +에서 일반적인 오류가 발생했습니다.”보다 경로가 빨라졌습니다.