Mostrando postagens com marcador imagem. Mostrar todas as postagens
Mostrando postagens com marcador imagem. Mostrar todas as postagens

Converter PDF em Imagem em C# com GhostScript

Esse é um artigo bem old, mas que muita gente me enviou e-mails pedindo como fazer isso. Então criei um artigo bem resumido baseado no de Lord TaGoH. Primeiramente, você precisa ter a DLL do GhostScript em seu projeto: ou você instala ou pega de alguém que já tenha instalado. O arquivo que me refiro é o gsdll32.dll. Obs: a conversão só funciona para as versões mais recentes então pegue alguma a partir da versão 9 como garantia.

Lembra do meu último post de scaneamento? Adicionei um botão de anexar um PDF e converter em imagem, então irei aproveitar a mesma aplicação adicionando essa funcionalidade. Copie a DLL para seu projeto e, em Propriedades, deixe configurado o atributo Copiar sempre para quando for compilá-la caso seja um Windows Form. Se for um Web Form, adicione em algum local onde a classe conversora possa encontrá-la.


Na página do CodeProject dispõe de uma classe (binária) já pronta para uso uso da DLL chamada de PdfToImage. Então você podem baixar de  ou aqui. Baixado a DLL, você pode adicionar como referência ao seu projeto/página. Agora é só código...

using PdfToImage;

// Objeto de conversão
PDFConvert converter = new PDFConvert();

// Arquivo PDF selecionado de um OpenFileDialog
string arquivo = FileUploadSelect.FileName;

// Local de saída do arquivo convertido
string output = _directoryForImages + "LJ_" + _loja + "_Scan_" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") + ".jpg";

// Configurações de conversão
converter.OutputToMultipleFile = false;
converter.TextAlphaBit = 4;
converter.FirstPageToConvert = 1;
converter.LastPageToConvert = 1;
converter.FitPage = false;
converter.JPEGQuality = 10;
converter.OutputFormat = "png16m";

// Faz a conversão e retorna true se estiver tudo OK
bool resultado = converter.Convert(arquivo, output);

Pronto! Mais fácil do que isso impossível. Fique atento às configurações de conversão, senão não funciona.

Recortando uma Imagem em Tempo de Execução (Image Crop) em C#

Lembram do post de Redimensionar Imagem? Esse post será bem similar e explicarei em poucas palavras o que ele faz. O que é Crop? Segundo a WikipediaCrop (Recorte) refere-se à remoção da parte exterior de uma imagem para melhorar o seu enquadramento. Um exemplo mais entendível: temos uma galeria de fotos nas quais todas as imagens possuem largura e altura diferentes que não são proporcionais; o redimensionamento de imagem para gerar um thumb não irá funcionar pois o produto final ou ficará distorcido ou não ficarão com tamanhos iguais. É aí que o recorte entra...

Veja o exemplo abaixo (retirado da Wikipedia):
No caso em questão era desejado obter um thumb quadrado da imagem. O enquadramento desejado não é proporcional à image original, logo é feito o recorte.

Dessa vez não irei colocar o código pois é um pouco grandinho, mas, como disse, é bem similar ao código do post de Redimensionar Imagem bem como seu uso (em forma de handler.ashx). Esse código é bem velhinho e não é meu. Ele está aí na net a muito tempo e já o vi em vários blogs e artigos. A última vez que o vi estava no subversion de Assembla.

Logo, baixem aqui e usem-o como desejar.

Convertendo HTML em PDF

Nesse artigo veremos como converter um HTML em PDF. O HTML pode vir de uma página externa quanto ser criado em tempo de execução. Não haverá muito o que explicar pois o código em si, você encontra a rodo pela net. Usaremos o componente iTextSharp.

Baixe o binário e adicione em seu aplicativo (pasta Bin). Utilize o código abaixo para fazer o processo de conversão e exibição do PDF na tela:


using System;
using System.Web;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html.simpleparser;


            // Captura ou atribui o HTML a ser convertido - no caso estou baixando de uma URL
            string html = new System.Net.WebClient().DownloadString("http://thiagomarcal.blogspot.com/");
            //string html = "Convertendo o HTML em PDF - Thiago Marçal";
            // Cria o documento aplicando o tamanho e margens
            Document documento = new Document(PageSize.A4, 80, 50, 30, 65);
            // Memory Stream para ser usado na conversão e emissão
            MemoryStream ms = new MemoryStream();
            // Inicializa o gravador
            PdfWriter writer = PdfWriter.GetInstance(documento, ms);
            // Lê o HTML e atribui
            StringReader conteudo = new StringReader(html);
            // Objeto de conversão do HTML
            HTMLWorker objeto = new HTMLWorker(documento);
            // Abre o documento
            documento.Open();
            // Aplica o parser para análise de conversão
            // Geralmente aqui ocasiona muitos erros - irei explicar no post
            objeto.Parse(conteudo);
            // Fecha o documento
            documento.Close();
            // Força o download do PDF gerado - se desejável você pode salvar em disco também
            Response.Clear();
            Response.AddHeader("content-disposition", "attachment; filename=Documento_HTML.pdf");
            Response.ContentType = "application/pdf";
            Response.Buffer = true;
            Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
            Response.OutputStream.Flush();
            Response.End();


Veja que a variável html eu atribuo o HTML que desejo converter. O seu conteúdo pode vir externamente ou posso atribuir um valor desejado.

Vamos aos problemas! Muitos vão encontrar erro quando o objeto estiver fazendo o parser do HTML e muitos irão falhar. Acontece que, devido à complexidade do HTML que estiver trabalhando, o componente não consegue converter para o formato adequado ao que ele usa internamente. Por exemplo, o TABLE do HTML que usamos é "meio" diferente do TABLE que o componente usa. Esse é um dos exemplos... Então prepara-se para fazer um tratamento adequado antes de fazer o parser. Eu sugiro o seguinte:
  1. Use expressão regular para validar seu HTML;
  2. Use expressão regular e/ou o HtmlAgilityPack para remover os JavaScripts;
  3. O conteúdo a ser convertido deve ser apenas o que está dentro do body;
  4. Imagens, CSS e links devem conter o caminho completo (exemplo: http://thiagomarcal.blogspot.com/imgs/logo.png ao invés de ../imgs/logo.png), etc.
Ou seja, quanto mais simplificado for seu HTML mais rápido e fácil será convertido em PDF. Uma observação bem clara é: nem sempre ficará 100% que o esperado.

Uma dica que pode ser usada (e um armengue, claro!) é fazer o seguinte:
  1. Gere um thumb (imagem) do HTML que deseja converter (saiba como gerar um thumb de um HTML nesse post) e salve em disco;
  2. Atribua a variável html com o conteúdo "<img src="http://thiagomarcal.blogspot.com/imgs/thumb.png" />";
  3. Coloque o width e height na tag IMG o tamanho desejado (pode ser até o tamanho do papel).
Pronto! O parser irá identificar apenas uma imagem no HTML e gerará o PDF com ela. Mole-mole...

Redimensionar imagens com alta qualidade em ASP.NET

O código que irei mostrar nem precisarei de muita explicação. Você encontra a rodo aí pela internet... Contudo, esse tem um pequeno diferencial: misturei o código "pescado" da net com o incremento de Glenn Jones. O redimensionamento consiste em colocar no SRC da imagem o Generic Handler que faz todo o processo e gera a imagem. Ou seja, crie um arquivo ImageResize.ashx e coloque o seguinte código abaixo:


using System;
using System.Drawing;
using System.IO;
using System.Web;


public class ImagemHandler : IHttpHandler {
    
    public void ProcessRequest (HttpContext context) {
        
        // Recupera os parâmetros passados pela página
        string strSrcImagemOriginal = "../upload/" + context.Request["img"].ToString();
        string strAlturaImagemRedimensionar = "";
        string strLarguraImagemRedimensionar = context.Request["w"].ToString();        
        
        // Cria temporariamnte a imagem
        System.Drawing.Image imagemTemp = System.Drawing.Image.FromFile(context.Server.MapPath(strSrcImagemOriginal));
        
        // Variáveis contendo o tamanho
        int srcWidth = imagemTemp.Width;
        int srcHeight = imagemTemp.Height;
        int thumbHeight;
        int thumbWidth;
        
        // Redimensiona a largura de forma proporcional
        if (context.Request["w"] != null)
        {
            thumbWidth = int.Parse(strLarguraImagemRedimensionar);
            thumbHeight = (int)(thumbWidth * imagemTemp.Height) / imagemTemp.Width;
        }
        else
        {
            thumbWidth = imagemTemp.Width;
            thumbHeight = imagemTemp.Height;
        }
        
        // Redimensiona a altura
        if (context.Request["h"] != null)
        {
            strAlturaImagemRedimensionar = context.Request["h"].ToString();
            thumbHeight = int.Parse(strAlturaImagemRedimensionar);
            // Faz o rateio para o redimensionamento proporcional
            // Assim a altura e a largura nunca irão ultrapassar o tamanho limite
            double widthRatio = (double)imagemTemp.Width / (double)thumbWidth;
            double heightRatio = (double)imagemTemp.Height / (double)thumbHeight;
            double ratio = Math.Max(widthRatio, heightRatio);
            thumbWidth = (int)(imagemTemp.Width / ratio);
            thumbHeight = (int)(imagemTemp.Height / ratio);
        }
        imagemTemp.Dispose();
        
        // Envia para a memória o objeto a ser trabalhado bem como o novo objeto
        Stream objStream = new StreamReader(context.Server.MapPath(strSrcImagemOriginal)).BaseStream;
        BinaryReader objBinaryReader = new BinaryReader(objStream);
        int i = (int)objStream.Length;
        byte[] arrBytes = objBinaryReader.ReadBytes(i);
        System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(arrBytes);
        System.Drawing.Image image = System.Drawing.Image.FromStream(memoryStream);
        System.Drawing.Image thumbnail = new Bitmap(thumbWidth, thumbHeight);
        System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(thumbnail);
        
        // Melhoria da nova imagem
        graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
        graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        
        // Desenha a nova imagem
        graphic.DrawImage(image, 0, 0, thumbWidth, thumbHeight);


        // Aplica a codificação necessária
        System.Drawing.Imaging.ImageCodecInfo[] info = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
        System.Drawing.Imaging.EncoderParameters encoderParameters;
        encoderParameters = new System.Drawing.Imaging.EncoderParameters(1);
        encoderParameters.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
        
        // Exibe a imagem em forma de JPG
        context.Response.ContentType = "image/jpeg";
        thumbnail.Save(context.Response.OutputStream, info[1], encoderParameters);


    }


}

Mais dado do que isso é só de mão beijada!

Inserindo Imagem em DLL

A alguns dias atrás, comecei a desenvolver um Framework para que eu pudesse incorporar em minhas aplicações e que pudesse reaproveitá-la constantemente. Nela contém classes de conexão, criação de objetos dinamicamente e imagens. Estava quase pronto quando me deparei com a parte das imagens. Eu queria que as imagens ficassem na DLL e quando eu fosse atualizar uma aplicação, eu só substituiria a DLL e não esquecesse dos arquivos.

Óbvio que comecei a ler alguns materiais na Internet para saber qual o melhor método para desenvolver. Por mais que eu lia, mais eu achava complicado. E outros, quanto eu mais fazia mais eu achava que estava errado. Até que então consegui...

Você pode utilizar de duas formas: chamando dentro da própria DLL ou através de uma página ASPX para, ao final, gerar uma imagem. Irei explicar como pois é praticamente a mesma coisa...

No Visual Studio, abra seu projeto (ele deve ser um Class Library). Clique com o direito sobre a Solução na aba do Solution Explorer e escolha a opção Properties. Irá abrir o conjunto de propriedades vigentes da DLL. Entre na aba Resources e notará a seguinte tela:


Nesse caso ele diz que não, por padrão, nenhum recurso. Clique sobre o link para adicionarmos um. Agora, vá em Add Resource, New Image e escolha um dos tipos de imagem suportado ou escolha Add Existing File... para selecionar uma imagem existente no disco.


Se escolhido a primeira opção terá que dar um nome que o identifique para que possamos invocá-lo posteriormente e terá que desenhar ou incorporar uma imagem no editor que irá abrir. Caso contrário, a segunda opção é a mais rápida pois iremos apenas selecionar uma imagem que ela já será incoporada.

Logo após incorporá-la nos recursos, verá, através do Solution Explorer, que foi criada uma pasta chamada Resources contendo a imagem desejada. Agora iremos permitir também que a imagem seja "chamada" ou, melhor dizendo, seja embedded. Para isso, clique com o direito sobre a imagem e entre em Properties. No Build Action, escolha a propriedade Embedded Resource.

Agora, vá na pasta Properties da solução e abra o arquivo AssemblyInfo.cs. Adicione o namespace:

using System.Web.UI;

E adicione a seguinte linha no final (pode ser depois de todas que tiverem):

[assembly: WebResource("Framework.Resources.Calendario.png", "image/png")]

Sendo que é constituído por:

  • Framework: é o namespace que compõe sua solução, no meu caso estava utilizando o namespace Framework;
  • Resources: indica o nome da pasta onde está o recurso;
  • Imagem

Assim a imagem já está incorporada à DLL e prontra para uso. Para invocarmos, conforme descrito anteriormente, pode ser de duas formas: de dentro da DLL e fora dela.

Por dentro, podemos gerar um objeto Image e adicionar seu atributo ImageUrl diretamente:

Image imagem = new Image();

imagem.ImageUrl = ClientScript.GetWebResourceUrl(this.GetType(), "Framework.Resources.Calendario.png");

Pode-se utilizar a mesma forma de invocação quando for chamar de fora da DLL pelo CodeBehind. Se for chamar direto na página ASPX basta utilizar as tags <%= %>colocando dentro o método de invocação do recurso.

Você pode utilizar essa forma de acoplamento de recursos para alguns outros tipos de objetos como JavaScript, por exemplo. Lembrando que não é bom ter uma DLL muito grande com diversos objetos. Caso for de extrema importância mantê-lo na DLL, fragmente-os em diversas outras DLLs.