Converting List<int> to List<object> for One to Many relation with sqlite-net-extensions
-
Exoskeletor wrote:
i would have to retrieve all the images and check them one by one
you would retrieve all the hashes, not the images, compare the hashes, not the images. You would only get the images if you need to display them, everything else would use the hashes. You could also use the database to compare the hash using a where clause on your sql query.
Never underestimate the power of human stupidity - RAH I'm old. I know stuff - JSOP
i think i have an idea of how im going to do it, i can do something like this:
public static string GetMD5Hash(string text)
{
using ( var md5 = MD5.Create() )
{
byte[] computedHash = md5.ComputeHash( Encoding.UTF8.GetBytes(text) );
return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString();
}
}
var nums = new List {1, 2, 3};
var result = string.Join(", ", nums);
var hash = GetMD5Hash(result); -
you gave an example with a imagehash. what is the imagehash in your example? how i can get a hash from the List or from the images?
An example is Calculate MD5 Checksum for a File using C#[^]; that's assuming your image is a file - and it will return a string with the hashed value. Write a small project to hash a single image that is a file and that shows the result, then you can work from there. The resulting string will change whenever the content of the image changes. In your project, you'd have to compute the hash when you store the image in the database. Get to know the concept first, before trying to add it to an existing project :thumbsup:
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
-
An example is Calculate MD5 Checksum for a File using C#[^]; that's assuming your image is a file - and it will return a string with the hashed value. Write a small project to hash a single image that is a file and that shows the result, then you can work from there. The resulting string will change whenever the content of the image changes. In your project, you'd have to compute the hash when you store the image in the database. Get to know the concept first, before trying to add it to an existing project :thumbsup:
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
my images are xml files that exist within android app, with simple string code inside, but how i can use that to my case? if i hash every image then i will have 5 hashes, how i can store 5 hashes and check them when im inserting a new template with one query?
-
my images are xml files that exist within android app, with simple string code inside, but how i can use that to my case? if i hash every image then i will have 5 hashes, how i can store 5 hashes and check them when im inserting a new template with one query?
I think you are right, i have to md5 the file, and not the resource id which is generated on code compilation, thanks for that. i don't know how i can hash all of them and store them together as a single hash but for now only i will check only one image if already exist
-
my images are xml files that exist within android app, with simple string code inside, but how i can use that to my case? if i hash every image then i will have 5 hashes, how i can store 5 hashes and check them when im inserting a new template with one query?
Exoskeletor wrote:
how i can store 5 hashes
The same way you store the images. Add a string-column next to the blob itself. Calculate the hash from the blob, and write them at the same time.
Exoskeletor wrote:
and check them when im inserting a new template with one query?
You don't check during the insert, but prior. You weren't trying to compare images during the insert before; same applies here. You can check if any of the five hashes exists in the database with a single query though; but one problem at a time - it would work with five queries too, and you can rewrite to use a single query later on.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
-
Exoskeletor wrote:
how i can store 5 hashes
The same way you store the images. Add a string-column next to the blob itself. Calculate the hash from the blob, and write them at the same time.
Exoskeletor wrote:
and check them when im inserting a new template with one query?
You don't check during the insert, but prior. You weren't trying to compare images during the insert before; same applies here. You can check if any of the five hashes exists in the database with a single query though; but one problem at a time - it would work with five queries too, and you can rewrite to use a single query later on.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
which blob? i don't use blobs any more, you mean to create a blod in order to hash it? can you give me a table structure cause im getting confused, this is my structure now
[Table("Templates")]
public class Template
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public int Category { get; set; }
//[TextBlob("imagesBlobbed")]
[OneToMany, Indexed(Name = "TemplateImagesUnique", Unique = true)]
public List TemplateImages { get; set; }
public string ImagesHash { get; set; }
//public string imagesBlobbed { get; set; }
}
[Table("TemplateImages")]
public class TemplateImage
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public int Category { get; set; }
public int Image { get; set; }
[ForeignKey(typeof(Template))]
public int TemplateId { get; set; }
} -
which blob? i don't use blobs any more, you mean to create a blod in order to hash it? can you give me a table structure cause im getting confused, this is my structure now
[Table("Templates")]
public class Template
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public int Category { get; set; }
//[TextBlob("imagesBlobbed")]
[OneToMany, Indexed(Name = "TemplateImagesUnique", Unique = true)]
public List TemplateImages { get; set; }
public string ImagesHash { get; set; }
//public string imagesBlobbed { get; set; }
}
[Table("TemplateImages")]
public class TemplateImage
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public int Category { get; set; }
public int Image { get; set; }
[ForeignKey(typeof(Template))]
public int TemplateId { get; set; }
}Exoskeletor wrote:
which blob? i don't use blobs any more
With the blob I meant the image you're storing.
\[Table("TemplateImages")\] public class TemplateImage { \[PrimaryKey, AutoIncrement\] public int Id { get; set; } public int Category { get; set; } public stream Image { get; set; } // why was that an int? Numbers aren't images public string ImageHash { get; set; } \[ForeignKey(typeof(Template))\] public int TemplateId { get; set; } }
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
-
Exoskeletor wrote:
which blob? i don't use blobs any more
With the blob I meant the image you're storing.
\[Table("TemplateImages")\] public class TemplateImage { \[PrimaryKey, AutoIncrement\] public int Id { get; set; } public int Category { get; set; } public stream Image { get; set; } // why was that an int? Numbers aren't images public string ImageHash { get; set; } \[ForeignKey(typeof(Template))\] public int TemplateId { get; set; } }
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
oh im storing the images as int cause this int represent the ResourceId of the image, i thought that since the images are stored inside the local app folder that is more efficient to store the
ResourceId
rather than the image itself (which is a string, my images are vectors .xml files) Is this a bad idea? Im starting thinking that this is a very silly idea :) because i guess the Resource id is generated every time i compile a new version of my app, so im trying to create a unique hash of something that is not unique
-
oh im storing the images as int cause this int represent the ResourceId of the image, i thought that since the images are stored inside the local app folder that is more efficient to store the
ResourceId
rather than the image itself (which is a string, my images are vectors .xml files) Is this a bad idea? Im starting thinking that this is a very silly idea :) because i guess the Resource id is generated every time i compile a new version of my app, so im trying to create a unique hash of something that is not unique
What if i do this: 1) Get the xml content as string 2) convert them with +s from all the images to one string, 3) md5hash this string? It sounds like an overkill although, i think i have to read the images as files, and in order to do that i have to open a stream, this sounds very heavy to me, cause i also have to move the images to assets, android can't read images from drawable folder. I think im coming to a dead end and the only solution is to delete and recreate the database every time the app is opened, or every time i made a new update of the app, im not sure
-
oh im storing the images as int cause this int represent the ResourceId of the image, i thought that since the images are stored inside the local app folder that is more efficient to store the
ResourceId
rather than the image itself (which is a string, my images are vectors .xml files) Is this a bad idea? Im starting thinking that this is a very silly idea :) because i guess the Resource id is generated every time i compile a new version of my app, so im trying to create a unique hash of something that is not unique
Exoskeletor wrote:
Im starting thinking that this is a very silly idea :) because i guess the Resource id is generated every time i compile a new version of my app, so im trying to create a unique hash of something that is not unique
You don't want to hash it's id, but the data that represents the image :) You want to compare those to each other, not the Id's that identify the image.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
-
What if i do this: 1) Get the xml content as string 2) convert them with +s from all the images to one string, 3) md5hash this string? It sounds like an overkill although, i think i have to read the images as files, and in order to do that i have to open a stream, this sounds very heavy to me, cause i also have to move the images to assets, android can't read images from drawable folder. I think im coming to a dead end and the only solution is to delete and recreate the database every time the app is opened, or every time i made a new update of the app, im not sure
Exoskeletor wrote:
- convert them with +s from all the images to one string,
Not "all" the images; you need a separate fingerprint for each image.
Exoskeletor wrote:
i think i have to read the images as files, and in order to do that i have to open a stream, this sounds very heavy to me
You'd have to read the images anyway to use them; opening them as a stream is not heavy, but the most used way to handle binary data. Since it is XML-data and not binary, you may get away with simply reading that string without needing a stream.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
-
Exoskeletor wrote:
- convert them with +s from all the images to one string,
Not "all" the images; you need a separate fingerprint for each image.
Exoskeletor wrote:
i think i have to read the images as files, and in order to do that i have to open a stream, this sounds very heavy to me
You'd have to read the images anyway to use them; opening them as a stream is not heavy, but the most used way to handle binary data. Since it is XML-data and not binary, you may get away with simply reading that string without needing a stream.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
but if i have a seperate hash for every image where im going to store it? in the templateimage table? one hash for each image?
-
but if i have a seperate hash for every image where im going to store it? in the templateimage table? one hash for each image?
Exoskeletor wrote:
one hash for each image?
Yes; since each hash represents the content in the image, in another form. If you have that for each image, then looking if you already have it is as easy as getting the hash from the new image (the one you want to compare to the ones already there), and see if it is in there.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
-
Exoskeletor wrote:
one hash for each image?
Yes; since each hash represents the content in the image, in another form. If you have that for each image, then looking if you already have it is as easy as getting the hash from the new image (the one you want to compare to the ones already there), and see if it is in there.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
yes but what if i don't mind if the same image exist but not in the same order? thats why im thinking of converting all bytes into one. A template might have some images that other template have (in the future). Since i am generating bitmaps for every image maybe is not so expensive to generate one more md5 from a bitmap that will do that
public static byte[] ConcatByteArrays(params byte[][] arrays)
{
return arrays.SelectMany(x => x).ToArray();
}and then have a hash for every template AND a hash for every image
-
yes but what if i don't mind if the same image exist but not in the same order? thats why im thinking of converting all bytes into one. A template might have some images that other template have (in the future). Since i am generating bitmaps for every image maybe is not so expensive to generate one more md5 from a bitmap that will do that
public static byte[] ConcatByteArrays(params byte[][] arrays)
{
return arrays.SelectMany(x => x).ToArray();
}and then have a hash for every template AND a hash for every image
I tried with this code but im getting an out of memory exception
static class DatabaseHelper
{
public static string GetMD5Hash(string content)
{
using (var md5 = MD5.Create())
{
byte[] computedHash = md5.ComputeHash(Encoding.UTF8.GetBytes(content));
return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString();
}
}public static string GetMD5Hash(byte\[\] content) { using (var md5 = MD5.Create()) { byte\[\] computedHash = md5.ComputeHash(Encoding.UTF8.GetBytes(BitConverter.ToString(content).Replace("-", ""))); return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString(); } } public static string DrawableToMD5(int drawableId) { var templateDB = new TemplateDB(); return GetMD5Hash(templateDB.DrawableToByteArray(drawableId)); } private static SQLiteConnection instance; public static SQLiteConnection db() { if (instance == null) instance = new SQLiteConnection(System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "TemplatesData.db")); return instance; } public static void CloseConnection() { if (instance != null) { instance.Close(); instance.Dispose(); instance = null; } } } public class TemplateDB { public enum TemplateCategories { Emojis, Stars, Hearts, Characters, Emotions, } public static byte\[\] ConcatByteArrays(params byte\[\]\[\] arrays) { return arrays.SelectMany(x => x).ToArray(); } public static byte\[\] ConcatByteList(List list) { return list .SelectMany(a => a) .ToArray(); } public static Bitmap GetBitmapFromVectorDrawable(Context context, int drawableId) { Drawable drawable = ContextCompat.GetDrawable(context, drawableId); if (Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.Lollipop) { drawable = (DrawableCompat.Wrap(drawable)).Mutate();
-
I tried with this code but im getting an out of memory exception
static class DatabaseHelper
{
public static string GetMD5Hash(string content)
{
using (var md5 = MD5.Create())
{
byte[] computedHash = md5.ComputeHash(Encoding.UTF8.GetBytes(content));
return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString();
}
}public static string GetMD5Hash(byte\[\] content) { using (var md5 = MD5.Create()) { byte\[\] computedHash = md5.ComputeHash(Encoding.UTF8.GetBytes(BitConverter.ToString(content).Replace("-", ""))); return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString(); } } public static string DrawableToMD5(int drawableId) { var templateDB = new TemplateDB(); return GetMD5Hash(templateDB.DrawableToByteArray(drawableId)); } private static SQLiteConnection instance; public static SQLiteConnection db() { if (instance == null) instance = new SQLiteConnection(System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "TemplatesData.db")); return instance; } public static void CloseConnection() { if (instance != null) { instance.Close(); instance.Dispose(); instance = null; } } } public class TemplateDB { public enum TemplateCategories { Emojis, Stars, Hearts, Characters, Emotions, } public static byte\[\] ConcatByteArrays(params byte\[\]\[\] arrays) { return arrays.SelectMany(x => x).ToArray(); } public static byte\[\] ConcatByteList(List list) { return list .SelectMany(a => a) .ToArray(); } public static Bitmap GetBitmapFromVectorDrawable(Context context, int drawableId) { Drawable drawable = ContextCompat.GetDrawable(context, drawableId); if (Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.Lollipop) { drawable = (DrawableCompat.Wrap(drawable)).Mutate();
What if i just give my own unique hash in every template manually? i cant think of another solution, either way im creating a list of templates before inserting them to db, why not just give them my own hash?
-
What if i just give my own unique hash in every template manually? i cant think of another solution, either way im creating a list of templates before inserting them to db, why not just give them my own hash?
Exoskeletor wrote:
What if i just give my own unique hash in every template manually? i cant think of another solution, either way im creating a list of templates before inserting them to db, why not just give them my own hash?
You already assign them an id; if you want to compare if two complex objects are the same, you usually do that by comparing their hash values.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
-
I tried with this code but im getting an out of memory exception
static class DatabaseHelper
{
public static string GetMD5Hash(string content)
{
using (var md5 = MD5.Create())
{
byte[] computedHash = md5.ComputeHash(Encoding.UTF8.GetBytes(content));
return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString();
}
}public static string GetMD5Hash(byte\[\] content) { using (var md5 = MD5.Create()) { byte\[\] computedHash = md5.ComputeHash(Encoding.UTF8.GetBytes(BitConverter.ToString(content).Replace("-", ""))); return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString(); } } public static string DrawableToMD5(int drawableId) { var templateDB = new TemplateDB(); return GetMD5Hash(templateDB.DrawableToByteArray(drawableId)); } private static SQLiteConnection instance; public static SQLiteConnection db() { if (instance == null) instance = new SQLiteConnection(System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "TemplatesData.db")); return instance; } public static void CloseConnection() { if (instance != null) { instance.Close(); instance.Dispose(); instance = null; } } } public class TemplateDB { public enum TemplateCategories { Emojis, Stars, Hearts, Characters, Emotions, } public static byte\[\] ConcatByteArrays(params byte\[\]\[\] arrays) { return arrays.SelectMany(x => x).ToArray(); } public static byte\[\] ConcatByteList(List list) { return list .SelectMany(a => a) .ToArray(); } public static Bitmap GetBitmapFromVectorDrawable(Context context, int drawableId) { Drawable drawable = ContextCompat.GetDrawable(context, drawableId); if (Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.Lollipop) { drawable = (DrawableCompat.Wrap(drawable)).Mutate();
That's reading all the images and making one big array of bytes of it; may be a bit much for the memorymanager.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
-
Exoskeletor wrote:
What if i just give my own unique hash in every template manually? i cant think of another solution, either way im creating a list of templates before inserting them to db, why not just give them my own hash?
You already assign them an id; if you want to compare if two complex objects are the same, you usually do that by comparing their hash values.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
well i cant seem to find a way to do that, i have also create this funny post in stackoverflow with that matter :) c# - Checking if data exist in sqlite-net before inserting them to database - Stack Overflow[^]
-
well i cant seem to find a way to do that, i have also create this funny post in stackoverflow with that matter :) c# - Checking if data exist in sqlite-net before inserting them to database - Stack Overflow[^]
Are you trying to compare bitmaps, or simply looking for a way to do an insert-query while checking if there's already such a record? In pseudo, comparing bitmaps would be similar to below;
Bitmap bitmap1 = (get bitmap from somewhere)
string hashedImage = MakeMD5(bitmap1);
Bitmap compareTo = (get bitmap you want to compare to)
string compareToHash = MakeMD5(compareTo);
bool imagesAreEqual = (hashedImage == compareToHash);That's not helping though if you are trying an insert that does an update when the record is already there.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.