Потоковая передача (и конвертирование?) многостраничного TIFF с использованием ASP.NET

StackOverflow https://stackoverflow.com/questions/1255024

Вопрос

Я создал простую программу просмотра изображений в .NET, и мне необходимо отображать многокадровые изображения TIFF в браузере.В настоящее время у меня есть настройка обработчика (ashx) для потоковой передачи JPEG-файлов, которые смешаны в той же базе данных, что и многокадровые файлы TIFF, и стоит отметить, что этот обработчик также вернет первый кадр файла TIFF в его текущем состоянии. .В приведенном ниже коде VB.NET (часть обработчика) я могу определить, содержит ли файл TIFF несколько кадров, и начал пытаться сшить кадры вместе, но пока безуспешно.Кто-нибудь возвращал многокадровые TIFF, используя аналогичный подход? Примечание: Я использовал Как открыть многокадровое изображение TIFF в качестве справки при разработке кода ниже.

        context.Response.Cache.SetCacheability(HttpCacheability.NoCache)
        context.Response.Cache.SetNoStore()
        context.Response.Cache.SetExpires(DateTime.MinValue)

        imageList = GetPhoto(picid)
        If (imageList IsNot Nothing) Then
            Dim img As Image
            Dim prevImageHeight = 0
            For Each img In imageList
                Dim imgGraphics As Graphics = Graphics.FromImage(img)
                imgGraphics.DrawImage(img, 0, prevImageHeight, img.Width, img.Height * imageList.Count)
                prevImageHeight += img.Height
                img.Save(context.Response.OutputStream, ImageFormat.Jpeg)
                img.Dispose()
            Next img
        Else
            ' Return 404
            context.Response.StatusCode = 404
            context.Response.End()
        End If

Вот код функции GetPhoto:

Public Function GetPhoto(ByVal id As String) As List(Of Image)
    Dim db As New UtilDb
    Dim imageLocation As String
    Dim errMsg As String = ""
    Dim imageList As New List(Of Image)
    Dim returnImage As Bitmap = Nothing
    imageLocation = GetFileName(id)

    If (imageLocation IsNot Nothing) Then
        Dim iFile As Image = Image.FromFile(imageLocation)
        If (imageLocation.ToUpper.EndsWith("TIF")) Then
            Dim frameCount As Integer = iFile.GetFrameCount(FrameDimension.Page)
            Dim i As Integer
            If (frameCount > 1) Then
                For i = 0 To frameCount - 1
                    iFile.SelectActiveFrame(FrameDimension.Page, i)
                    returnImage = New Bitmap(iFile, iFile.Width * 0.4, iFile.Height * 0.4)
                    imageList.Add(returnImage)
                Next i
            Else
                returnImage = New Bitmap(iFile, iFile.Width * 0.4, iFile.Height * 0.4)
                imageList.Add(returnImage)
            End If

        Else
            Dim scaledWidth As Integer = (iFile.Width / iFile.Height) * 480
            returnImage = New Bitmap(iFile, scaledWidth, 480)
            imageList.Add(returnImage)
        End If
        iFile.Dispose()
    End If
    Return imageList
End Function

Можно ли поместить каждый кадр многокадрового TIFF в непрерывное изображение и отправить его обратно в браузер?Должен ли я сосредоточить свои усилия на преобразовании многокадрового TIFF в другой формат, например PDF?По сути, у меня нет бюджета на покупку конверсионных пакетов... Буду очень признателен за любую помощь или рекомендации!

Это было полезно?

Решение

Итак, решение оказалось очень простым — я понял, что сохранение каждого кадра отдельно в потоке ответов было основной причиной, по которой верхний кадр был единственным кадром, отображаемым в браузере.

Вот фрагмент функции, которую я написал для сбора всех необходимых параметров из изображения (хотя это и многокадровые файлы TIFF, однокадровые файлы TIFF или JPEG):

Dim iFile As Image = Image.FromFile(imageLocation)
Dim frameCount As Integer = iFile.GetFrameCount(FrameDimension.Page)
Dim totalWidth, totalHeight As Integer

If (imageLocation.ToUpper.EndsWith("TIF")) Then
    Dim i As Integer
    If (frameCount > 1) Then
        totalWidth = 0
        totalHeight = 0
        For i = 0 To frameCount - 1
            iFile.SelectActiveFrame(FrameDimension.Page, i)
            imageStructure.totalWidth = Math.Max(totalWidth, (iFile.Width * 0.4))
            imageStructure.totalHeight += (iFile.Height * 0.4)
            returnImage = New Bitmap(iFile, iFile.Width * 0.4, iFile.Height * 0.4)
            imageList.Add(returnImage)
        Next i
     Else
        returnImage = New Bitmap(iFile, iFile.Width * 0.4, iFile.Height * 0.4)
        imageStructure.totalWidth = (iFile.Width * 0.4)
        imageStructure.totalHeight = (iFile.Height * 0.4)
        imageList.Add(returnImage)
     End If

 Else
    Dim scaledWidth As Integer = (iFile.Width / iFile.Height) * defaultHeight
    returnImage = New Bitmap(iFile, scaledWidth, defaultHeight)
    imageStructure.totalWidth = scaledWidth
    imageStructure.totalHeight = defaultHeight
    imageList.Add(returnImage)
 End If
 iFile.Dispose()
 imageStructure.frameCount = frameCount
 imageStructure.frameList = imageList

Вот фрагмент кода, который отображает изображения:

If (imageStructure.frameCount > 1) Then
   'We know we have a multi-frame TIFF
   Dim appendedImage As Bitmap = New Bitmap(imageStructure.totalWidth, imageStructure.totalHeight)
   imgGraphics = Graphics.FromImage(appendedImage)
   Dim prevHeight As Integer = 0
   For Each img In imageStructure.frameList
         imgGraphics.DrawImage(img, 0, prevHeight, img.Width, img.Height)
         prevHeight += img.Height
         img.Dispose()
   Next
   appendedImage.Save(context.Response.OutputStream, ImageFormat.Jpeg)
   appendedImage.Dispose()
Else
    ' JPEG or single frame TIFF
    img = imageStructure.frameList(0)
    imgGraphics = Graphics.FromImage(img)
    imgGraphics.DrawImage(img, 0, 0, img.Width, img.Height)
    img.Save(context.Response.OutputStream, ImageFormat.Jpeg)
    img.Dispose()
 End If

Примечание: Переменная imageStructure — это тривиальная структура, которая хранит общую ширину, высоту, количество кадров и список изображений, представляющих каждый кадр.

Теперь мне осталось провести небольшой рефакторинг, и все будет готово!Я надеюсь, что кто-то еще найдет это полезным...

Другие советы

Огромное спасибо! Это было действительно полезно.Я перевел его на C# и сделал его немного короче, всегда зацикливая независимо от количества страниц в tiff-файле.Я также устранил структуру и вместо нее использую переменные.Ниже приведен код:

protected void Page_Load(object sender, EventArgs e)
{
    string cFileName = Request.QueryString["cFileName"];

    if (cFileName != null && cFileName.ToString().Trim().Length > 0)
    {

        Image iFile = Image.FromFile(cFileName.ToString().Trim());
        MemoryStream imgStream = new MemoryStream();

        int i = 0;
        int frameCount = iFile.GetFrameCount(FrameDimension.Page);

        List<Image> imageList = new List<Image>();
        Image returnImage;
        Graphics imgGraphics;

        int totalWidth = 0;
        int nStatus = 0;
        int totalHeight = 0;

        if (cFileName.ToUpper().Trim().EndsWith("TIF") || cFileName.ToUpper().Trim().EndsWith("TIFF"))
        {
            if (frameCount > 0)
            {
                for (i = 0; i < frameCount; i++)
                {
                    nStatus = iFile.SelectActiveFrame(FrameDimension.Page, i);
                    totalWidth = (int)Math.Max(totalWidth, (iFile.Width) * 0.4);
                    totalHeight += (int)(iFile.Height * 0.4);

                    returnImage = new Bitmap(iFile, (int)(iFile.Width * 0.4), (int)(iFile.Height * 0.4));
                    imageList.Add(returnImage);
                }
            }
        }
        else
        {
            returnImage = new Bitmap(iFile, (int)(iFile.Width), (int)(iFile.Height));
            totalWidth = (int)(iFile.Width);
            totalHeight = (int)(iFile.Height);

            imageList.Add(returnImage);
        }

        iFile.Dispose();

        if (frameCount > 0)
        {
            Bitmap appendedImage = new Bitmap(totalWidth, totalHeight);
            imgGraphics = Graphics.FromImage(appendedImage);
            int prevHeight = 0;

            foreach (Image iImage in imageList)
            {
                imgGraphics.DrawImage(iImage, 0, prevHeight, iImage.Width, iImage.Height);
                prevHeight += iImage.Height;
                iImage.Dispose();
            }
            appendedImage.Save(Context.Response.OutputStream, ImageFormat.Jpeg);
            appendedImage.Dispose();
        }

    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top