hi i send some c# code this is get from imagealg.dll file the class name is diff code is given below how to get description for this code.
public sealed class Diff
{
// Fields
private int diff;
private Bitmap overlayImage;
private Bitmap overlayImage1;
// Methods
public Diff()
{
}
public Diff(Bitmap overlayImage, Bitmap overlayImage1)
{
this.overlayImage = overlayImage;
this.overlayImage1 = overlayImage1;
}
public int Apply(Bitmap srcImg, Bitmap dstImg)
{
int width = srcImg.Width;
int height = srcImg.Height;
int num3 = dstImg.Width;
int num4 = dstImg.Height;
PixelFormat format = (srcImg.PixelFormat == PixelFormat.Format8bppIndexed) ? PixelFormat.Format8bppIndexed : PixelFormat.Format24bppRgb;
BitmapData data = srcImg.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, format);
BitmapData ovrData = dstImg.LockBits(new Rectangle(0, 0, num3, num4), ImageLockMode.ReadOnly, format);
this.ProcessFilter(data, ovrData, format);
dstImg.UnlockBits(ovrData);
srcImg.UnlockBits(data);
return this.diff;
}
public void ApplyInPlace(Bitmap img)
{
int width = img.Width;
int height = img.Height;
if (((img.PixelFormat != this.overlayImage.PixelFormat) || (width != this.overlayImage.Width)) || (height != this.overlayImage.Height))
{
throw new ArgumentException();
}
if ((img.PixelFormat != PixelFormat.Format8bppIndexed) && (img.PixelFormat != PixelFormat.Format24bppRgb))
{
throw new ArgumentException();
}
BitmapData bitmapdata = img.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
img.UnlockBits(bitmapdata);
}
public int difference()
{
return this.diff;
}
private unsafe void ProcessFilter(BitmapData data, BitmapData ovrData, PixelFormat fmt)
{
int width = data.Width;
int height = data.Height;
int num3 = (fmt == PixelFormat.Format8bppIndexed) ? 1 : 3;
int num4 = width * num3;
int num5 = data.Stride - num4;
byte* numPtr = (byte*) data.Scan0.ToPointer();
byte* numPtr2 = (byte*) ovrData.Scan0.ToPointer();
this.diff = 0;
for (int i = 0; i < height; i++)
{
int num8 = 0;
while (num8 < num4)
{
int num6 = numPtr[0] - numPtr2[0];
string str = Convert.ToString(numPtr[0]);
string str2 = Convert.ToString(numPtr2[0]);
if (num6 != 0)
{
this.diff++;
}
num8++;
numPtr++;
numPtr2++;
}
numPtr += num5;
numPtr2 += num5;
}
}
// Properties
public Bitmap OverlayImage
{
get
{
return this.overlayImage;
}
set
{
this.overlayImage = value;
}
}
}
It sounds like you've recently received and/or been asked to use a library containing code that you don't quite understand. Unfortunately, if the source isn't properly documented, you only have two choices:
Go back to whomever or wherever you got the code from and ask them for proper documentation. Every piece of source code that you receive should come with documentation.
Study the code carefully and try to figure out what it's doing and how you are supposed to use it. This is somewhat closer to "reverse-engineering" the library (except that you have the source), and it's usually reserved as a last-ditch effort.
In fact, if any of us were to try and answer this question, that's all we could do is read and interpret the code you've posted. Is there something specific that you don't understand and are seeking clarification about?
And finally, remember this as a lesson to yourself. Whenever you write code, make sure that you take the time to document it properly so you don't put someone else who tries to use your code in the same situation that you're in now.
You'll be happy to know that the code doesn't do anything particularly significant. The Apply method sets up and calls ProcessFilter, which does a comparison of the two images and returns a count of the number of pixels that differ between the two.
The ApplyInPlace method does nothing.
And I feel sorry for the poor programmer who inherits this code and has to maintain it, what with all those useful variable names like num4 and num6.
It is my fondest wish that the programmer who brought this abomination into the world has been permanently banned from ever touching another keyboard.
Related
I'm using libtiff.net to make a tiff from a jpeg.
The problem apears when I try to write, because the tiff.writeScanLine returns false, meaning the image isn't written in the tiff.
Why is this happening? And how can I figure out what's wrong?
Here's the code:
private bool creatingTiff()
{
using (Bitmap bmp = new Bitmap(targetFile))
{
using (Tiff tif = Tiff.Open("BitmapTo24BitColorTiff.tif", "w"))
{
byte[] raster = getImageRasterBytes(bmp, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
tif.SetField(TiffTag.IMAGEWIDTH, bmp.Width);
tif.SetField(TiffTag.IMAGELENGTH, bmp.Height);
tif.SetField(TiffTag.COMPRESSION, Compression.OJPEG);
tif.SetField(TiffTag.PHOTOMETRIC, Photometric.YCBCR);
tif.SetField(TiffTag.SUBFILETYPE, 0);
tif.SetField(TiffTag.ROWSPERSTRIP, bmp.Height);
tif.SetField(TiffTag.ORIENTATION, BitMiracle.LibTiff.Classic.Orientation.TOPLEFT);
tif.SetField(TiffTag.XRESOLUTION, bmp.HorizontalResolution);
tif.SetField(TiffTag.YRESOLUTION, bmp.VerticalResolution);
tif.SetField(TiffTag.RESOLUTIONUNIT, ResUnit.INCH);
tif.SetField(TiffTag.BITSPERSAMPLE, 8);
tif.SetField(TiffTag.SAMPLESPERPIXEL, 3);
tif.SetField(TiffTag.JPEGIFOFFSET, 768);
tif.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
for (int i = 0, offset = 0; i < bmp.Height; i++)
{
bool b = tif.WriteScanline(raster, offset, i, 0);
Console.WriteLine("write succes: " + b);
offset += stride;
}
}
System.Diagnostics.Process.Start("BitmapTo24BitColorTiff.tif");
return true;
}
}
private static byte[] getImageRasterBytes(Bitmap bmp, System.Drawing.Imaging.PixelFormat format)
{
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
byte[] bits = null;
try
{
// Lock the managed memory
BitmapData bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, format);
// Declare an array to hold the bytes of the bitmap.
bits = new byte[bmpdata.Stride * bmpdata.Height];
// Copy the values into the array.
System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, bits, 0, bits.Length);
// Release managed memory
bmp.UnlockBits(bmpdata);
}
catch
{
return null;
}
return bits;
}
private static void convertSamples(byte[] data, int width, int height)
{
int stride = data.Length / height;
const int samplesPerPixel = 3;
for (int y = 0; y < height; y++)
{
int offset = stride * y;
int strideEnd = offset + width * samplesPerPixel;
for (int i = offset; i < strideEnd; i += samplesPerPixel)
{
byte temp = data[i + 2];
data[i + 2] = data[i];
data[i] = temp;
}
}
}
The tif-tags are written, but the image itself isn't. Perhaps if someone can point me in the direction of the library developers blog (BitMiracle), I can direct my problem to them directly.
I think your code has the following errors:
You can not use Compression.OJPEG for new images. Old-JPEGs can only be de-compressed.
You probably should not specify TiffTag.JPEGIFOFFSET value by hand. The library will specify proper value itself.
You are trying to write the whole strip using WriteScanline method. You should use WriteEncodedStrip instead.
It also helps to review warnings emitted by the library (it emits them into console).
I'm trying to squeeze the best performance out of some imaging code and I've hit a wall.
As far as my knowledge goes it should be possible to speed up the process using pointers but my experience with them is very limited and finding good documentation to read and understand is proving difficult.
Am I correct? Could someone show an annotated example of the code converted to help me understand the process.
public void UpdatePixelIndexes(IEnumerable<byte[]> lineIndexes)
{
int width = this.Image.Width;
int height = this.Image.Height;
IEnumerator<byte[]> indexesIterator = lineIndexes.GetEnumerator();
for (int rowIndex = 0; rowIndex < height; rowIndex++)
{
indexesIterator.MoveNext();
BitmapData data = this.Image.LockBits(Rectangle.FromLTRB(0, rowIndex, width, rowIndex + 1), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
try
{
Marshal.Copy(indexesIterator.Current, 0, data.Scan0, width);
}
finally
{
this.Image.UnlockBits(data);
}
}
}
It's unlikely you actually need unsafe here. As suggested, you should just stop locking/unlocking the bitmap for every scan line. Instead, do this:
public void UpdatePixelIndexes(IEnumerable<byte[]> lineIndexes)
{
int width = this.Image.Width;
int height = this.Image.Height;
int rowIndex = 0;
BitmapData data = this.Image.LockBits(Rectangle.FromLTRB(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
try
{
foreach (byte[] scanLine in lineIndexes)
{
Marshal.Copy(scanLine, 0,
IntPtr.Add(data.Scan0, data.Stride * rowIndex), width);
if (++rowIndex >= height)
{
break;
}
}
}
finally
{
this.Image.UnlockBits(data);
}
}
I have 28 images that have 3 sizes each (84 total) that are all monochrome with different alpha layers to make each image. I want to make each of them available in 5 different colors. that would be 420 images total. This would obviously be a huge pain to do manually. I do not have Photoshop so any type of photoshop function is not a valid answer. I have Paint.NET but the adjust hue doesn't work for me because changing the hue alone does not give me the colors I want.
Basically what I need to do is for every pixel in the image, take the RGBA value and replace the RGB with a new RGB value and keep the same A value.
Anyone know how to do this? I had no luck searching on StackOverflow or Google (probably using the wrong search terms).
I would prefer an answer in C# or VB.NET but if anyone knows how to do this in any language maybe I can apply it to C# or VB.NET.
--Edit--
In case anyone finds this and is looking for the answer, here's what I got based on the link from Yorye Nathan.
private const int RED = 51;
private const int GREEN = 181;
private const int BLUE = 229;
private const int NEW_RED = 170;
private const int NEW_GREEN = 102;
private const int NEW_BLUE = 204;
private void Form1_Load(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Image OriginalImage = Image.FromFile(openFileDialog1.FileName);
Image NewImage = ColorFilter(OriginalImage);
pictureBox1.Image = OriginalImage;
pictureBox2.Image = NewImage;
}
}
public static Image ColorFilter(Image originalImage)
{
Bitmap newImage = new Bitmap(originalImage);
BitmapData originalData = (originalImage as Bitmap).LockBits(new Rectangle(0, 0, originalImage.Width, originalImage.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
BitmapData newData = (newImage as Bitmap).LockBits(new Rectangle(0, 0, originalImage.Width, originalImage.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
int originalStride = originalData.Stride;
System.IntPtr originalScan0 = originalData.Scan0;
int newStride = newData.Stride;
System.IntPtr newScan0 = newData.Scan0;
unsafe
{
byte* pOriginal = (byte*)(void*)originalScan0;
byte* pNew = (byte*)(void*)newScan0;
int nOffset = originalStride - originalImage.Width * 4;
byte red, green, blue;
for (int y = 0; y < originalImage.Height; ++y)
{
for (int x = 0; x < originalImage.Width; ++x)
{
blue = pOriginal[0];
green = pOriginal[1];
red = pOriginal[2];
if (pOriginal[0] == BLUE && pOriginal[1] == GREEN && pOriginal[2] == RED)
{
pNew[0] = (byte)NEW_BLUE;
pNew[1] = (byte)NEW_GREEN;
pNew[2] = (byte)NEW_RED;
}
pOriginal += 4;
pNew += 4;
}
pOriginal += nOffset;
pNew += nOffset;
}
}
(originalImage as Bitmap).UnlockBits(originalData);
(newImage as Bitmap).UnlockBits(newData);
return newImage;
}
Check this question out. Tweak a little with the pixel's bits replacement to make it add them instead of replacing them, and you're good to go.
How could I generate a System.Drawing.Image that contains the differences between the pixels of two other images?
Something similar to GitHub does, but written in C#
The algorithm that GiHub uses is implemented in javascript. There is a context-blender project that replicates Photoshop blend modes.
Do you know if is translated to C# or a similar algorithm that has the same quality level? I need to manage also transparent images (with alpha channel).
Here's a quick and dirty implementation:
void Main()
{
var a = (Bitmap)Image.FromFile("image1.png");
var b = (Bitmap)Image.FromFile("image2.png");
var diff = PixelDiff(a, b);
}
unsafe Bitmap PixelDiff(Bitmap a, Bitmap b)
{
Bitmap output = new Bitmap(a.Width, a.Height, PixelFormat.Format32bppArgb);
Rectangle rect = new Rectangle(Point.Empty, a.Size);
using (var aData = a.LockBitsDisposable(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb))
using (var bData = b.LockBitsDisposable(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb))
using (var outputData = output.LockBitsDisposable(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb))
{
byte* aPtr = (byte*)aData.Scan0;
byte* bPtr = (byte*)bData.Scan0;
byte* outputPtr = (byte*)outputData.Scan0;
int len = aData.Stride * aData.Height;
for (int i = 0; i < len; i++)
{
// For alpha use the average of both images (otherwise pixels with the same alpha won't be visible)
if ((i + 1) % 4 == 0)
*outputPtr = (byte)((*aPtr + *bPtr) / 2);
else
*outputPtr = (byte)~(*aPtr ^ *bPtr);
outputPtr++;
aPtr++;
bPtr++;
}
}
return output;
}
static class Extensions
{
public static DisposableImageData LockBitsDisposable(this Bitmap bitmap, Rectangle rect, ImageLockMode flags, PixelFormat format)
{
return new DisposableImageData(bitmap, rect, flags, format);
}
public class DisposableImageData : IDisposable
{
private readonly Bitmap _bitmap;
private readonly BitmapData _data;
internal DisposableImageData(Bitmap bitmap, Rectangle rect, ImageLockMode flags, PixelFormat format)
{
bitmap.CheckArgumentNull("bitmap");
_bitmap = bitmap;
_data = bitmap.LockBits(rect, flags, format);
}
public void Dispose()
{
_bitmap.UnlockBits(_data);
}
public IntPtr Scan0
{
get { return _data.Scan0; }
}
public int Stride
{
get { return _data.Stride;}
}
public int Width
{
get { return _data.Width;}
}
public int Height
{
get { return _data.Height;}
}
public PixelFormat PixelFormat
{
get { return _data.PixelFormat;}
}
public int Reserved
{
get { return _data.Reserved;}
}
}
}
Notes:
this implementation assumes that both images have the same size, which might not be the case... taking different sizes into account is possible of course, just a little harder.
the LockBitsDisposable method is just a convenience, if you prefer you can use the standard LockBits method (but don't forget to unlock the bits when you're done)
A quick google search yielded this:
http://www.bryancook.net/2009/10/find-differences-between-images-c.html
If your're going to be using ARGB rather then RGB, it'll probably need a bit of editing. If you wanted to get that 'inverted difference' effect, like in the Github link posted, you could find the differance between RGB colors and use that for each pixel in the difference image, etc.
I was wondering if there was an inexpensive way to get the width and height of a JPEG after loading an array of bytes.
I know JpegBitmapDecoder can get the JPEG's pixel width and height but it loads alot of information as well, which I assume would be an expensive operation.
Is there another way to get the width and height from the array of bytes without decoding it?
Thanks
For some unknown reason, instead of going to bed, I went to work on this.
Here's some code that solves this with minimal storage requirements.
void Main()
{
var filePath=#"path\to\my.jpg";
var bytes=File.ReadAllBytes(filePath);
var dimensions=GetJpegDimensions(bytes);
//or
//var dimensions=GetJpegDimensions(filePath);
Console.WriteLine(dimensions);
}
public static Dimensions GetJpegDimensions(byte[] bytes)
{
using(var ms=new MemoryStream(bytes))
{
return GetJpegDimensions(ms);
}
}
public static Dimensions GetJpegDimensions(string filePath)
{
using(var fs=File.OpenRead(filePath))
{
return GetJpegDimensions(fs);
}
}
public static Dimensions GetJpegDimensions(Stream fs)
{
if(!fs.CanSeek) throw new ArgumentException("Stream must be seekable");
long blockStart;
var buf = new byte[4];
fs.Read(buf, 0, 4);
if(buf.SequenceEqual(new byte[]{0xff, 0xd8, 0xff, 0xe0}))
{
blockStart = fs.Position;
fs.Read(buf, 0, 2);
var blockLength = ((buf[0] << 8) + buf[1]);
fs.Read(buf, 0, 4);
if(Encoding.ASCII.GetString(buf, 0, 4) == "JFIF"
&& fs.ReadByte() == 0)
{
blockStart += blockLength;
while(blockStart < fs.Length)
{
fs.Position = blockStart;
fs.Read(buf, 0, 4);
blockLength = ((buf[2] << 8) + buf[3]);
if(blockLength >= 7 && buf[0] == 0xff && buf[1] == 0xc0)
{
fs.Position += 1;
fs.Read(buf, 0, 4);
var height = (buf[0] << 8) + buf[1];
var width = (buf[2] << 8) + buf[3];
return new Dimensions(width, height);
}
blockStart += blockLength + 2;
}
}
}
return null;
}
public class Dimensions
{
private readonly int width;
private readonly int height;
public Dimensions(int width, int height)
{
this.width = width;
this.height = height;
}
public int Width
{
get{return width;}
}
public int Height
{
get{return height;}
}
public override string ToString()
{
return string.Format("width:{0}, height:{1}", Width, Height);
}
}
I've read a CodeProject article about it a couple years back :)
I'm not 100% sure how good it is, and haven't tested it myself, but the author's definitely happy with it; also his tests prove it's a LOT faster than reading the whole image, as you'd expect :)
Here's the article itself.. Hope it's what you need!
http://www.codeproject.com/KB/cs/ReadingImageHeaders.aspx
The piece of code you're looking for starts about here:
http://www.codeproject.com/KB/cs/ReadingImageHeaders.aspx#premain3
UPD: Also, check the comments in the bottom.. Especially the last (top) one there.. Might be useful to make it more generic
Also, more in-depth, advanced info can be picked up here: http://www.codeproject.com/KB/graphics/iptc.aspx