Tuesday, June 30, 2009

Firefox tarda mucho para correr despues de actualizar a 3.5

Firefox 3.5 (nombre clave Shirekoto) esta listo, todos a bajarlo!

Despues de actualizar y correrlo la primera vez, me salio esta pequeña ventana

Me tomo un rato para darme cuenta que esta ventanita estaba siquiera en mi pantalla, pense que simplemente estaba tardando mucho para correr la primera vez, pero luego ya me parecio demasiado tiempo, entonces di click en la barra de tareas, en el icono de firefox y fue cuando vi la ventanita esta, trate de redimensionarla para ver los contenidos, pero no me dejo, lo unico que pude hacer fue cerrarla y ya Firefox corrio normal

Asi que solo lo agregue aqui por si a alguien le pasa lo mismo, espero que sea de ayuda

sintomas: Firefox tarda mucho en correr la primera vez despues de actualizar a 3.5
solucion: click en la barra de tareas, en el icono de firefox y encuentra la ventanita esta, cierrala y Firefox correra normal

Tuesday, June 23, 2009

Como convertir DIB a Bitmap

El fin de semana pasado un amigo me pidio ayuda con un codigo para convertir DIB a Bitmap en .NET, habia encontrado un codigo que casi hacia todo lo que necesitaba, pero la imagen se cortaba en los lados, supusimos que el problema era con el codigo que obtenia un puntero al bitmap, asi que investigamos mas y encontramos un codigo que supuestamente arreglaba ese problema, solo tuvimos que hacer unos cambios y un par de arreglos para que funcionara correctamente. Como no encontramos una solucion completa por ningun lado decidi escribir este post ya que vi muchisima gente con este problema preguntando en muchos foros en Internet, asi que espero que pueda ser util, sin mas, aqui va la solucion:

Primero tienes que agregar una referencia a System.Drawing.dll en tu proyecto, luego agrega esto al uses

//Name spaces needed
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
El siguiente paso es declarar la estructura BITMAPINFOHEADER, esta puede estar declarada fuera de tu clase:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BITMAPINFOHEADER
{
public uint biSize;
public int biWidth;
public int biHeight;
public ushort biPlanes;
public ushort biBitCount;
public uint biCompression;
public uint biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public uint biClrUsed;
public uint biClrImportant;

public void Init()
{
biSize = (uint)Marshal.SizeOf(this);
}
}

Luego necesitas agregar esto para importar una funcion de GdiPlus.dll
//GDI External method needed Place it within your class
[DllImport("GdiPlus.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern int GdipCreateBitmapFromGdiDib(IntPtr pBIH,
IntPtr pPix, out IntPtr pBitmap);
Y bien, ahora podemos irnos al codigo en si que nos servira para convertir el DIB a Bitmap, notese el uso de la funcion GetPixelInfo, aqui precisamente estaba la raiz de nuestros problemas; la funcion BitmapFromDIB que encuentras por todo internet no tiene este codigo asi que eso hace que no funcione en muchos casos. De hecho la funcion esta que anda rondando por internet, toma un parametro pPix pero nunca menciona como obtener este valor. Este codigo necesita estar declarado dentro de tu clase

//THIS METHOD SAVES THE CONTENTS OF THE DIB POINTER INTO A BITMAP OBJECT
private static Bitmap BitmapFromDIB(IntPtr pDIB)
{
//get pointer to bitmap header info
IntPtr pPix = GetPixelInfo(pDIB);

//Call external GDI method
MethodInfo mi = typeof(Bitmap).GetMethod("FromGDIplus", BindingFlags.Static | BindingFlags.NonPublic);
if (mi == null)
return null;

// Initialize memory pointer where Bitmap will be saved
IntPtr pBmp = IntPtr.Zero;

//Call external methosd that saves bitmap into pointer
int status = GdipCreateBitmapFromGdiDib(pDIB, pPix, out pBmp);

//If success return bitmap, if failed return null
if ((status == 0) && (pBmp != IntPtr.Zero))
return (Bitmap)mi.Invoke(null, new object[] { pBmp });
else
return null
;
}

//THIS METHOD GETS THE POINTER TO THE BITMAP HEADER INFO
private static IntPtr GetPixelInfo(IntPtr bmpPtr)
{
BITMAPINFOHEADER bmi = (BITMAPINFOHEADER)Marshal.PtrToStructure(bmpPtr, typeof(BITMAPINFOHEADER));

if (bmi.biSizeImage == 0)
bmi.biSizeImage = (uint)(((((bmi.biWidth * bmi.biBitCount) + 31) & ~31) >> 3) * bmi.biHeight);

int p = (int)bmi.biClrUsed;
if ((p == 0) && (bmi.biBitCount <= 8))
p = 1 << bmi.biBitCount;
p = (p * 4) + (int)bmi.biSize + (int)bmpPtr;
return (IntPtr)p;
}
Finalmente, como algo agregado, lo que mi amigo realmente necesitaba era convertir de DIB a TIFF (grupo 4), asi que escribio una funcion mas que usa la funcion previa de BitmapFromDIB function and allows you to set the image resolution

private void SavehDibToTiff(int hDIB, string fileName, int xRes, int yRes)
{
//Identify the memory pointer to the DIB Handler (hDIB)
IntPtr dibPtr = new IntPtr(hDIB);

//Save the contents of DIB pointer into bitmap object
Bitmap myBitmap = BitmapFromDIB(dibPtr);

//Set resolution if needed
if (xRes >0 && yRes>0)
myBitmap.SetResolution(xRes, yRes);

//Create an instance of the windows TIFF encoder
ImageCodecInfo ici = GetEncoderInfo("image/tiff");

//Define encoder parameters
EncoderParameters eps = new EncoderParameters(1); // only one parameter in this case (compression)

//Create an Encoder Value for TIFF compression Group 4
long ev = (long)EncoderValue.CompressionCCITT4;
eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, ev);

//Save file
myBitmap.Save(fileName, ici, eps);
}
//Helper to get Encoder from Windows for file type.
private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType == mimeType)
return encoders[j];
}
return null;
}

Y eso es todo, espero les sea de utilidad, gracias a Danny por darme el codigo final y agregarle comentarios

Saturday, June 13, 2009

Porque las pestañas de IE tienen colores?

colored tabs

Esto es algo de lo que me gusto mucho en Internet Explorer 8, pero no todo mundo capta inmediatamente el significado de los colores. Los colores son para agrupar pestañas relacionadas entre si, osea que si tu sigues un link de una pagina y IE abre una pestaña, asignara el mismo color que la pestaña previa de donde se abrio esta nueva y de esta manera podras ver facilmente que una fue derivada de la otra, esto es muy util en estos dias que uno normalmente mantiene muchisimas pestañas abiertas al mismo tiempo, unas para cuestiones personales, otras para trabajo, busquedas, etc, el tenerlas agrupadas por colores nos permite ver cuales estan relacionadas entre si.

La motivacion a escribir este post fue precisamente porque alguien me pregunto que significaban los colores, asi que pense que seguramente habria mas gente que tendria la misma pregunta.