10-05-18, 04:35 AM
(آخر تعديل لهذه المشاركة : 10-05-18, 04:49 AM {2} بواسطة silverlight.)
مقدمة:
الموضوع هذا محاولة بسيطة لتوضيح كيفية ضغط الصور بدون أن تفقد الصورة شيئا من دقتها او من ألوانها الأصلية
الفكرة ممكن تطبيقها علي البرامج التي تحتاج الي أن نحفظ الصورة في ملف مثل ملفات الدات بيز
الخطوات التالية توضح كيفية ضغط الصورة:
1- تعريف متغير يعبر عن الصورة و هنا سأفترض أن الصورة موجودة في Resources المشروع
2- تحويل بيانات الصورة إلي مصفوفات بايت
أولا : تحويل العرض Width الي مصفوفة بايت
ثانيا : تحويل الطول Height الي مصفوفة بايت
ثالثا : تحويل PixelFormat الخاصة بالصورة إلي مصفوفة بايت
يتم استخدام الدالة التالية
ونحصل علي مصفوفة البايت كالتالي:
رابعا : الحصول علي مصفوفة الألوان الخاصة بالصورة علي هيئة مصفوفة بايت
3- ندمج مصفوفات البايت معا في مصفوفة واحدة
بخيث تكون ترتيب المصفوفات كالتال
مصفوفة PixelFormat
مصفوفة Width
مصفوفة Height
مصفوفة الألوان
وبهذا الترتيب نحن ها نبيني ما يمطن أن نطلق عليه Bytes layout
والهدف من هذا الترتيب هو سهولة استرداد بيانات الصورة كاملة لاحقا ومن ثم نستطيع استرجاع الصورة الأصلية دون أن نفقد شيئا من دقة الصورة
وبذلك نكون حصلنا علي مصفوفة واحدة اسمها imgArray تجتمع بها معظم خصائص الصورة وبياناتها
4- نقوم بضغط الصورة باستخدام
ويمكن استخدام الدلة التالية لضغط المصفوفة والدالة تقوم بالتشفيير و الضغط معا
ااستخدام الدالة:
الحقيقة انا لا أستطيع أن أختبر الفكرة مع برامج الداتا بيز و السبب هو أني لا أعلم شيئا عن الداتا بيز
لذلك فضلا لا أمرا أرجو من أحد الزملاء المهتمين بالداتابيز أن يختبر الفكرة ويبني مشروعان
بحيث في احد المشروعان يحفظ أكثر من صوره بعد أن يضغطها باستخدام الأسلوب أعلاه
وأيضا يحفظ نفس العدد من الصور في مشروع أخر ولكن بدون أن يضغط الصورة
ثم يقارن بين حجم الملفات و يعطينا النتائج
فإن كانت النتائج ايجابية سأكمل الفكرة و اوضح كيفية استرجاع الصورة ثانية بعد قراءتها من ملف الدات بيز
وللتيسير أكثر علي الزميل الذي سيحفظ الصور في ملف الداتا بيز يمكنه فقط اضافة الدوال التالية و يستخدمها في بناء مصفوفات الصور و ضغطها بعد ذلك
ويتم الاستخدام كالتالي
الموضوع هذا محاولة بسيطة لتوضيح كيفية ضغط الصور بدون أن تفقد الصورة شيئا من دقتها او من ألوانها الأصلية
الفكرة ممكن تطبيقها علي البرامج التي تحتاج الي أن نحفظ الصورة في ملف مثل ملفات الدات بيز
الخطوات التالية توضح كيفية ضغط الصورة:
1- تعريف متغير يعبر عن الصورة و هنا سأفترض أن الصورة موجودة في Resources المشروع
PHP كود :
Dim bmp As Bitmap = My.Resources.rm
2- تحويل بيانات الصورة إلي مصفوفات بايت
أولا : تحويل العرض Width الي مصفوفة بايت
PHP كود :
' Convet bitmap width to byte array
Dim widthBytes As Byte() = BitConverter.GetBytes(CUInt(bmp.Width))
كود :
' Convet bitmap height to byte array
Dim heightBytes As Byte() = BitConverter.GetBytes(CUInt(bmp.Height))
يتم استخدام الدالة التالية
كود :
Private Function ConvertFromPixelFormat(bmp As Bitmap) As Byte()
Dim imgFormat As Long = CType(Convert.ChangeType(bmp.PixelFormat, GetType(Imaging.PixelFormat)), Long)
Return BitConverter.GetBytes(imgFormat)
End Function
كود :
' Convet bitmap pixelformaat to byte array
Dim imgFormatBytes As Byte() = Me.ConvertFromPixelFormat(bmp)
كود :
' Convet bitmap to byte array
Dim data As Imaging.BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat)
Dim bitmapBytes As Byte() = New Byte(data.Stride * data.Height - 1) {}
Runtime.InteropServices.Marshal.Copy(data.Scan0, bitmapBytes, 0, bitmapBytes.Length)
bmp.UnlockBits(data)
3- ندمج مصفوفات البايت معا في مصفوفة واحدة
بخيث تكون ترتيب المصفوفات كالتال
مصفوفة PixelFormat
مصفوفة Width
مصفوفة Height
مصفوفة الألوان
وبهذا الترتيب نحن ها نبيني ما يمطن أن نطلق عليه Bytes layout
والهدف من هذا الترتيب هو سهولة استرداد بيانات الصورة كاملة لاحقا ومن ثم نستطيع استرجاع الصورة الأصلية دون أن نفقد شيئا من دقة الصورة
كود :
' Build up byte arrays layout by .....
' Concatenate imageformat, width, height, bmp byte arrays in a single byte array
Dim imgArray As Byte() = New Byte(imgFormatBytes.Length + widthBytes.Length + heightBytes.Length + bitmapBytes.Length - 1) {}
Array.Copy(imgFormatBytes, 0, imgArray, 0, imgFormatBytes.Length)
Array.Copy(widthBytes, 0, imgArray, imgFormatBytes.Length, widthBytes.Length)
Array.Copy(heightBytes, 0, imgArray, imgFormatBytes.Length + widthBytes.Length, heightBytes.Length)
Array.Copy(bitmapBytes, 0, imgArray, imgFormatBytes.Length + widthBytes.Length + heightBytes.Length, bitmapBytes.Length)
وبذلك نكون حصلنا علي مصفوفة واحدة اسمها imgArray تجتمع بها معظم خصائص الصورة وبياناتها
4- نقوم بضغط الصورة باستخدام
ويمكن استخدام الدلة التالية لضغط المصفوفة والدالة تقوم بالتشفيير و الضغط معا
كود :
Public Function Compress(bytes As Byte()) As Byte()
Dim result As Byte() = Nothing
Using ms As IO.MemoryStream = New IO.MemoryStream()
Using g As GZipStream = New GZipStream(ms, CompressionMode.Compress, True)
g.Write(bytes, 0, bytes.Length)
End Using
result = ms.ToArray()
End Using
Return result
End Function
ااستخدام الدالة:
كود :
Dim result As Byte() = Me.Compress(imgarray)
الحقيقة انا لا أستطيع أن أختبر الفكرة مع برامج الداتا بيز و السبب هو أني لا أعلم شيئا عن الداتا بيز
لذلك فضلا لا أمرا أرجو من أحد الزملاء المهتمين بالداتابيز أن يختبر الفكرة ويبني مشروعان
بحيث في احد المشروعان يحفظ أكثر من صوره بعد أن يضغطها باستخدام الأسلوب أعلاه
وأيضا يحفظ نفس العدد من الصور في مشروع أخر ولكن بدون أن يضغط الصورة
ثم يقارن بين حجم الملفات و يعطينا النتائج
فإن كانت النتائج ايجابية سأكمل الفكرة و اوضح كيفية استرجاع الصورة ثانية بعد قراءتها من ملف الدات بيز
وللتيسير أكثر علي الزميل الذي سيحفظ الصور في ملف الداتا بيز يمكنه فقط اضافة الدوال التالية و يستخدمها في بناء مصفوفات الصور و ضغطها بعد ذلك
كود :
Private Function BuildBytes(bmp As Bitmap) As Byte()
' Convet bitmap width to byte array
Dim widthBytes As Byte() = BitConverter.GetBytes(CUInt(bmp.Width))
' Convet bitmap height to byte array
Dim heightBytes As Byte() = BitConverter.GetBytes(CUInt(bmp.Height))
' Convet bitmap pixelformaat to byte array
Dim imgFormatBytes As Byte() = Me.ConvertFromPixelFormat(bmp)
' Convet bitmap to byte array
Dim data As Imaging.BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat)
Dim bitmapBytes As Byte() = New Byte(data.Stride * data.Height - 1) {}
Runtime.InteropServices.Marshal.Copy(data.Scan0, bitmapBytes, 0, bitmapBytes.Length)
bmp.UnlockBits(data)
' Build up byte arrays layout by .....
' Concatenate imageformat, width, height, bmp byte arrays in a single byte array
Dim imgArray As Byte() = New Byte(imgFormatBytes.Length + widthBytes.Length + heightBytes.Length + bitmapBytes.Length - 1) {}
Array.Copy(imgFormatBytes, 0, imgArray, 0, imgFormatBytes.Length)
Array.Copy(widthBytes, 0, imgArray, imgFormatBytes.Length, widthBytes.Length)
Array.Copy(heightBytes, 0, imgArray, imgFormatBytes.Length + widthBytes.Length, heightBytes.Length)
Array.Copy(bitmapBytes, 0, imgArray, imgFormatBytes.Length + widthBytes.Length + heightBytes.Length, bitmapBytes.Length)
Return imgArray
End Function
كود :
Private Function ConvertFromPixelFormat(bmp As Bitmap) As Byte()
Dim imgFormat As Long = CType(Convert.ChangeType(bmp.PixelFormat, GetType(Imaging.PixelFormat)), Long)
Return BitConverter.GetBytes(imgFormat)
End Function
كود :
Public Function Compress(bytes As Byte()) As Byte()
Dim result As Byte() = Nothing
Using ms As IO.MemoryStream = New IO.MemoryStream()
Using g As GZipStream = New GZipStream(ms, CompressionMode.Compress, True)
g.Write(bytes, 0, bytes.Length)
End Using
result = ms.ToArray()
End Using
Return result
End Function
ويتم الاستخدام كالتالي
كود :
' compress
Dim imgarray As Byte() = Me.BuildBytes(bmp)
Dim result As Byte() = Me.Compress(imgarray)
Retired