الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

تحويل الصور

بدأه mohref في 15 يوليو 2009 · 5 رد · 944 مشاهدة · في JavaME
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكــم ورحمـة الله وبركاتــه ،،

بصراحة اسف لإني لم اعرف اين اضع الموضوع

باختصار انا قمت ببناء MIDlet من اجل المراقبة الصحية في مدينة الرياض و قد ادخلت فيه عملية التوقيع الرقمي

حيث ان صاحب المحل بعد انتهاء عملية التفتيش على محله يطلب المراقب منه ان يقوم بالتوقيع على الPDA

طبعا عملية التوقيع هي عبارة عن تتبع لحركات المؤشر ورسم الخطوط بين هذه النقاط وطبعا العملية تتم باستخدام ال Canvas

المشكلة هي اني اريد تحويل الCanvas بعد عملية رسم التوقيع الى صورة باللامتداد PNG

قمت بعملية التحويل بعد جهد جهيد و كانت في البداية الحجم ضخم جدا لإني اعتمدت على محول لل PNG يعطي 32bit حيث وصل حجم الصورة الى 300k تقريبا

ثم قمت بتعديل هذا المحول ليعطي 8bit و حصلت على الحجم 60k تقريبا

مااريده الان هو تعديله ليعطي 1bit او 2bit حتى احصل على حجم صغير اتوقع ان يكون (7k)

لم اعرف المكان المناسب لوضع هذا الموضوع فوضعته هنا بحكم اني اكتب في هذا القسم عادة

المطلوب : لو كان هنالك احد قد تعامل مع برمجة الصور او يعلم منتدى يناقش فيه مثل هذا الامور ان لايبخل علي بالمعلومة

chunk.writeByte(8); // Bitdepth

chunk.writeByte(0); // Colortype ARGB

في حال كان المراد الحصول على ال ARGB يتم تحويل السطرين السابقين في الكود الى :

chunk.writeByte(8); // Bitdepth

chunk.writeByte(6); // Colortype ARGB

حيث انا الاول هو عدد البيتات لكل لون اي لكل لون 8bit اي 1Byte و الثاني هو الالوان حيث ان 0 يشير الى grayscale و 6 هو عبارة عن 4 + 2 اي ال RGB بالاضافة الى قناة ال alpha

ونغير الMethod التاليه فقط من اجل تغير طول الصورة لاحظو السطر byte[] raw = new byte[4*(width*height) + height];

ومن اجل اضافة قنوات الالوان و قناة alpha لاحظوا هذه الاسطر ايضا

raw[dest++] = green[source];

raw[dest++] = blue[source];

raw[dest++] = alpha[source++];

 public static byte[] createDataChunk(int width, int height, byte[] alpha, byte[] red, byte[] green, byte[] blue) throws IOException
  {	
	int source = 0;
	int dest = 0;
	byte[] raw = new byte[4*(width*height) + height];
	for (int y = 0; y < height; y++)
	{
	  raw[dest++] = 0; // No filter
	  for (int x = 0; x < width; x++)
	  {
		raw[dest++] = red[source];
		raw[dest++] = green[source];
		raw[dest++] = blue[source];
		raw[dest++] = alpha[source++];
	  }
	}
	return toChunk("IDAT", toZLIB(raw));
  }

import java.io.*;


public class PNG
{


  public static byte[] toPNG(int width, int height, byte[] photo) throws IOException
  {
	byte[] signature = new byte[] {(byte) 137, (byte) 80, (byte) 78, (byte) 71, (byte) 13, (byte) 10, (byte) 26, (byte) 10};
	byte[] header = createHeaderChunk(width, height);
	byte[] data = createDataChunk(width, height, photo,null,null,null);
	byte[] trailer = createTrailerChunk();

	ByteArrayOutputStream png = new ByteArrayOutputStream(signature.length + header.length + data.length + trailer.length);
	png.write(signature);
	png.write(header);
	png.write(data);
	png.write(trailer);
	return png.toByteArray();
  }

 public static byte[] createHeaderChunk(int width, int height) throws IOException
  {
	ByteArrayOutputStream baos = new ByteArrayOutputStream(13);
	DataOutputStream chunk = new DataOutputStream(baos);
	chunk.writeInt(width);
	chunk.writeInt(height);
	chunk.writeByte(8); // Bitdepth
	chunk.writeByte(0); // Colortype ARGB
	chunk.writeByte(0); // Compression
	chunk.writeByte(0); // Filter
	chunk.writeByte(0); // Interlace
	return toChunk("IHDR", baos.toByteArray());
  }

  public static byte[] createDataChunk(int width, int height, byte[] alpha, byte[] red, byte[] green, byte[] blue) throws IOException
  {
	int source = 0;
	int dest = 0;
	byte[] raw = new byte[(width*height) + height];
	for (int y = 0; y < height; y++)
	{
	  raw[dest++] = 0; // No filter
	  for (int x = 0; x < width; x++)
	  {
		raw[dest++] = alpha[source++];
	  }
	}
	return toChunk("IDAT", toZLIB(raw));
  }

  public static byte[] createTrailerChunk() throws IOException
  {
	return toChunk("IEND", new byte[] {});
  }

  public static byte[] toChunk(String id, byte[] raw) throws IOException
  {
	ByteArrayOutputStream baos = new ByteArrayOutputStream(raw.length + 12);
	DataOutputStream chunk = new DataOutputStream(baos);

	chunk.writeInt(raw.length);

	byte[] bid = new byte[4];
	for (int i = 0; i < 4; i++)
	{
	  bid = (byte) id.charAt(i);
	}

	chunk.write(bid);

	chunk.write(raw);

	int crc = 0xFFFFFFFF;
	crc = updateCRC(crc, bid);  
	crc = updateCRC(crc, raw);	
	chunk.writeInt(~crc);

	return baos.toByteArray();
  }

  static int[] crcTable = null;

  public static void createCRCTable()
  {
	crcTable = new int[256];

	for (int i = 0; i < 256; i++)
	{
	  int c = i;
	  for (int k = 0; k < 8; k++)
	  {
		c = ((c & 1) > 0) ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
	  }
	  crcTable = c;
	}
  }

  public static int updateCRC(int crc, byte[] raw)
  {
	if (crcTable == null)
	{
	  createCRCTable();
	}

	for (int i = 0; i < raw.length; i++)
	{
	  crc = crcTable[(crc ^ raw) & 0xFF] ^ (crc >>> 8);	  
	}

	return crc;
  }

  /* This method is called to encode the image data as a zlib
	 block as required by the PNG specification. This file comes
	 with a minimal ZLIB encoder which uses uncompressed deflate
	 blocks (fast, short, easy, but no compression). If you want
	 compression, call another encoder (such as JZLib?) here. */
  public static byte[] toZLIB(byte[] raw) throws IOException
  {
	return ZLIB.toZLIB(raw);	
  }
}



class ZLIB
{
  static final int BLOCK_SIZE = 32000;

  public static byte[] toZLIB(byte[] raw) throws IOException
  {	
	ByteArrayOutputStream baos = new ByteArrayOutputStream(raw.length + 6 + (raw.length / BLOCK_SIZE) * 5);
	DataOutputStream zlib = new DataOutputStream(baos);

	byte tmp = (byte) 8;	   
	zlib.writeByte(tmp);						   // CM = 8, CMINFO = 0
	zlib.writeByte((31 - ((tmp << 8) % 31)) % 31); // FCHECK (FDICT/FLEVEL=0)

	int pos = 0;
	while (raw.length - pos > BLOCK_SIZE)
	{
	  writeUncompressedDeflateBlock(zlib, false, raw, pos, (char) BLOCK_SIZE);
	  pos += BLOCK_SIZE;
	}

	writeUncompressedDeflateBlock(zlib, true, raw, pos, (char) (raw.length - pos));

	// zlib check sum of uncompressed data
	zlib.writeInt(calcADLER32(raw));

	return baos.toByteArray();
  }

  private static void writeUncompressedDeflateBlock(DataOutputStream zlib, boolean last,
						byte[] raw, int off, char len) throws IOException
  {
	zlib.writeByte((byte)(last ? 1 : 0));		 // Final flag, Compression type 0
	zlib.writeByte((byte)(len & 0xFF));		   // Length LSB
	zlib.writeByte((byte)((len & 0xFF00) >> 8));  // Length MSB
	zlib.writeByte((byte)(~len & 0xFF));		  // Length 1st complement LSB
	zlib.writeByte((byte)((~len & 0xFF00) >> 8)); // Length 1st complement MSB 
	zlib.write(raw,off,len);					  // Data	
  }

  private static int calcADLER32(byte[] raw)
  {
	int s1 = 1;
	int s2 = 0;
	for (int i = 0; i < raw.length; i++)
	{
	  int abs = raw >=0 ? raw : (raw + 256);
	  s1 = (s1 + abs) % 65521;
	  s2 = (s2 + s1) % 65521;	  
	}
	return (s2 << 16) + s1;
  }
}

وهذه هدية للمنتدى MIDlet يقوم بعملية التصوير وحفظ الصور وبنفس الوقت اضفت اليه Progress Bar (شريط التقدم ليس من برمجتي لكن الصور من برمجتي)

ولكم جزيل الشكر

cameraTesting.zip

تم تعديل هذه المشاركة بواسطة mohref في 15 يوليو 2009 في 10:25

#2

اخوي في قسم خاص للجوالات

#3

يمكنك صنع صورة Mutable Image

Image image=Image.createImage(getWidth(), getHeight());

و بعدها خذ

Graphics graphics=image.getGraphics();

و باستخدام graphics تقوم بالرسم على هذه الصورة

و عند الانتهاء من التوقيع عليها احفظها :

int[] imgRgbData = new int[width * height];

image.getRGB(imgRgbData, 0, width, 0, 0, width, height);

ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);

 for (int i = 0; i < imgRgbData.length; i++) {
				dos.writeInt(imgRgbData);
			}

FileConnection fileConnection= (FileConnection)Connector.open(FilePath, Connector.READ_WRITE);
fileConnection.openDataOutputStream().....

و يمكنك المتابعة من هنا

#4

شكرا لك اخي لكن المشكلة ان المراد هو ان تكون بتنسيق PNG ثم نقطة ثانية ان الصورة التي حفظتها هي عبارة عن BitMap

وسيكون حجمها كبير جدا تقريبا 300K او اكثر على مااعتقد

لإني في البداية تعاملت مع هذه الطريقة

كل مااطلبه اذا كان هنالك من تعامل مع تنسيق الPNG ان يضع ملاحظته من اجل تحويل الكلاس من محول الى 8bit الى 1 او 2 bit

انا اعلم انه يجب ان تتغير السطور الى

chunk.writeByte(1); // Bitdepth
chunk.writeByte(0); // Colortype ARGB

حيث ان السطر الاول يعبر عن طول كل عنصر في الصورة

و السطر الثاني يعبر عن نظام الالوان و في حالة الصفر فإنه يكون GrayScale

و يخبرني ايضا عن طول المصفوفة التي يجب ان استخدمها بدل المصفوفة المستخدمة

  byte[] raw = new byte[(width*height) + height];

المطلوب باختصار احد تعامل مع الصور PNG او يعرف منتدى يناقش فيه مثل هذه الامور

ولكم جزيل الشكر

تم تعديل هذه المشاركة بواسطة علاء الصالحي في 19 يوليو 2009 في 07:45 — السبب: إضافة وسم الشيفرة code

#6

Thanks very much

But if you notice i get my encoder from this page

then i update the color, bitDepth and the length and structure

but my question is how to make the bitDepth to 1 or 2 bit

and how can i modify the array to that

thanks again for you interactive

مواضيع مشابهة