Je dois convertir des fichiers TIFF bional (noir et blanc) dans un autre format d'affichage par un navigateur Web, nous utilisons actuellement des JPGS, mais le format n'est pas crucial. De la lecture autour de .net ne semble pas supporter facilement écrire des images bioniques, nous finissons donc avec ~ 1 Mo de fichiers au lieu d'~ 100 000. J'envisage d'utiliser ImageMagick pour faire cela, mais idéalement, je voudrais une solution qui ne nécessite pas cela si possible si possible.
Snippet de code actuel (qui redimensionne également certains sur l'image): P>
using (Image img = Image.FromFile(imageName)) { using (Bitmap resized = new Bitmap(resizedWidth, resizedHeight) { using (Graphics g = Graphics.FromImage(resized)) { g.DrawImage(img, new Rectangle(0, 0, resized.Width, resized.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel); } resized.Save(outputFilename, System.Drawing.Imaging.ImageFormat.Jpeg); } }
5 Réponses :
Avez-vous essayé d'enregistrer à l'aide du image.save surcharge avec Encoder Paramètres?
Comme le Paramètre Encoder.colordepth ? p>
Essayer la suggestion de Jaroslav pour la profondeur de couleur ne fonctionne pas:
static void Main(string[] args) { var list = ImageCodecInfo.GetImageDecoders(); var jpegEncoder = list[1]; // i know this is the jpeg encoder by inspection Bitmap bitmap = new Bitmap(500, 500); Graphics g = Graphics.FromImage(bitmap); g.DrawRectangle(new Pen(Color.Red), 10, 10, 300, 300); var encoderParams = new EncoderParameters(); encoderParams.Param[0] = new EncoderParameter(Encoder.ColorDepth, 2); bitmap.Save(@"c:\newbitmap.jpeg", jpegEncoder, encoderParams); }
Avez-vous essayé png avec une profondeur de couleur 1 bit? grève> p>
Pour obtenir une taille similaire à un TIFF CCITT4, je pense que votre image doit utiliser une pellette indexée à 1 bits. P>
Cependant, vous ne pouvez pas utiliser l'objet graphique dans .NET pour dessiner une image indexée. P>
Vous devrez probablement utiliser des verrouillages pour manipuler chaque pixel. P>
voir L'excellent article de Bob Powell . P>
Je pense que le problème peut être résolu en vérifiant que En d'autres termes, vous devez utiliser le code suivant au lieu de i Utilisez le code suivant pour redimensionné code> bitmap est de
pixelformat.format1bppindexed code>. Si ce n'est pas le cas, vous devez le convertir en bitmap 1bpp et après cela, vous pouvez l'enregistrer sous forme de png noir et blanc sans problèmes.
redimensionné. .Drawing.iming.Imageformat.jpeg); code> p>
Convertobitonal code>: P>
private static Bitmap convertToBitonal(Bitmap original)
{
int sourceStride;
byte[] sourceBuffer = extractBytes(original, out sourceStride);
// Create destination bitmap
Bitmap destination = new Bitmap(original.Width, original.Height,
PixelFormat.Format1bppIndexed);
destination.SetResolution(original.HorizontalResolution, original.VerticalResolution);
// Lock destination bitmap in memory
BitmapData destinationData = destination.LockBits(
new Rectangle(0, 0, destination.Width, destination.Height),
ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
// Create buffer for destination bitmap bits
int imageSize = destinationData.Stride * destinationData.Height;
byte[] destinationBuffer = new byte[imageSize];
int sourceIndex = 0;
int destinationIndex = 0;
int pixelTotal = 0;
byte destinationValue = 0;
int pixelValue = 128;
int height = destination.Height;
int width = destination.Width;
int threshold = 500;
for (int y = 0; y < height; y++)
{
sourceIndex = y * sourceStride;
destinationIndex = y * destinationData.Stride;
destinationValue = 0;
pixelValue = 128;
for (int x = 0; x < width; x++)
{
// Compute pixel brightness (i.e. total of Red, Green, and Blue values)
pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] +
sourceBuffer[sourceIndex + 3];
if (pixelTotal > threshold)
destinationValue += (byte)pixelValue;
if (pixelValue == 1)
{
destinationBuffer[destinationIndex] = destinationValue;
destinationIndex++;
destinationValue = 0;
pixelValue = 128;
}
else
{
pixelValue >>= 1;
}
sourceIndex += 4;
}
if (pixelValue != 128)
destinationBuffer[destinationIndex] = destinationValue;
}
Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);
destination.UnlockBits(destinationData);
return destination;
}
private static byte[] extractBytes(Bitmap original, out int stride)
{
Bitmap source = null;
try
{
// If original bitmap is not already in 32 BPP, ARGB format, then convert
if (original.PixelFormat != PixelFormat.Format32bppArgb)
{
source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
source.SetResolution(original.HorizontalResolution, original.VerticalResolution);
using (Graphics g = Graphics.FromImage(source))
{
g.DrawImageUnscaled(original, 0, 0);
}
}
else
{
source = original;
}
// Lock source bitmap in memory
BitmapData sourceData = source.LockBits(
new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
// Copy image data to binary array
int imageSize = sourceData.Stride * sourceData.Height;
byte[] sourceBuffer = new byte[imageSize];
Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);
// Unlock source bitmap
source.UnlockBits(sourceData);
stride = sourceData.Stride;
return sourceBuffer;
}
finally
{
if (source != original)
source.Dispose();
}
}
C'est brillant. Merci beaucoup.
C'est un vieux fil. Cependant, j'ajouterai mes 2 cents.
J'utilise les bibliothèques Aforge.net (open source) p>
Utilisez ces DLL. aforge.dll code>,
aforge.iming.dll code> p>