Image.Save () на MemoryBmp в TIFF с EncoderParams - Как? - PullRequest
2 голосов
/ 06 ноября 2010

У меня есть приложение, которое позволяет пользователю определить область изображения и сохранить эту область в файл.Я столкнулся с препятствием, с которым не могу разобраться.Растровое изображение, которое я создаю для рисования выбранной области, застряло с ImageFormat «MemoryBmp», кажется, что это ImageFormat, который установлен для любых не загруженных файлов растровых изображений.Проблема в том, что мое растровое изображение создано в памяти, и я хочу сохранить его как битовый TIFF CCITT4, но я получаю исключение «Произошла общая ошибка в GDI +».Я вполне уверен, что это связано с тем, что свойство Image.RawFormat является тем страшным MemoryBmp.

Image.Save () имеет перегрузку, которая принимает параметр ImageFormat, и когда я использую этот проход ImageFormat.Tiff егоСохраняет нормально, но у меня нет возможности указать параметры моего кодировщика.

Единственный возможный обходной путь, о котором я могу подумать, - это сохранить на диск, используя Image.Save (Image, ImageFormat), а затем перезагрузить его (RawFormat).теперь будет правильно установлено значение ImageFormat.Tif), а затем снова сохраните, передав настройки кодера.Это просто глупо, но должен быть лучший способ.

Вот фрагмент кода (это просто тестирование), который должен дать вам представление о том, что я делаю в случае, если мое предыдущее описание былонедостаточно ясно:

SizeF dpiScale = GetScreenToImageDPIRatio(loadedImage);
using (Bitmap image = new Bitmap(loadedImage,
    (int)(_cropBox.Width * dpiScale.Width),
    (int)(_cropBox.Height * dpiScale.Height)))
{
    image.SetResolution(loadedImage.HorizontalResolution, 
        loadedImage.VerticalResolution);

    using (Graphics g = Graphics.FromImage(image))
    {
        g.DrawImage(loadedImage, 0, 0, new Rectangle(
            (int)(_cropBox.Location.X * dpiScale.Width),
            (int)(_cropBox.Location.Y * dpiScale.Height),
            (int)(_cropBox.Width * dpiScale.Width),
            (int)(_cropBox.Height * dpiScale.Height)),
            GraphicsUnit.Pixel);
    }

    //  It's stuck as a MemoryBmp so none of these checks will work
    if (true || image.RawFormat.Equals(ImageFormat.Tiff))
    {
        ImageCodecInfo tiffCodecInfo = ImageUtils.GetEncoderInfo("image/tiff");
        EncoderParameters myEncoderParameters = new EncoderParameters(2);

        myEncoderParameters.Param[0] = new
            EncoderParameter(System.Drawing.Imaging.Encoder.Compression,
                (long)EncoderValue.CompressionCCITT4);
        myEncoderParameters.Param[1] = new
            EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 1L);

        image.Save(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".tif"),
            tiffCodecInfo, myEncoderParameters);

        //  The file is a "MemoryBmp" and it's screwing things up
        //image.Save(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".tif"),
        //    ImageFormat.Tiff);
    }
    else
    {
        //  other format saving support, blah blah blah
    }
}

О, я должен упомянуть, что "loadedIimage "действительно является изображением tiff, я передал ссылку наloadedImage в Bitmap.ctor (), чтобы посмотреть, может ли это понятьс чем он имеет дело, но это не имело никакого значения.

1 Ответ

5 голосов
/ 06 ноября 2010

Выяснил, что CCITT4 требует двухтональных изображений, ха!Итак, я пошел искать в Google, наткнулся на статью CodeProject и стал искать в источнике.Автор предоставил довольно приличный метод для преобразования 32bppARGB в 1bpp двухтональный.Я попробовал это, и это быстро (тестовое шоу около 34 мс на одну страницу), и это помогло!

Я отвечаю на свой вопрос.Я надеюсь, что это, по крайней мере, поможет кому-то еще, кто сталкивается с этой проблемой.

...