JAVA实现C语言中的memcpy函数 c语言java 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 为啥要操作内存呢?你需要实现什么功能呢?如果是拷贝数组,可以在Arrays类里找到封装好的方法。 因为我想操作24-bit的bmp格式图片,实现它的旋转,模拟了好了旋转的方法后,我想将旋转的图保存到一个新文件,因为24-bit的位图是一个像素对应3个字节,所以我想每次将数组中的三个值给新的数组 JDK的Arrays类有方法:static byte[] copyOf(byte[] original, int newLength) 是否符合你的需求? 我找了一个System.arraycopy(),结果还没有出来,我想将存有位图数据的char类型数组写入到文件中,但是总是得不到目标图片途中旋转后的图是我想得到的目标图,不知道是不是像素存储的方式错了,总是得到如上的图像 //以图像中心为原点左上角,右上角,左下角和右下角的坐标,用于计算旋转后的图像的宽和高 int srcW = w; int srcH = h; int bitCount = 24; int lineSize = bitCount * srcW / 8; //偏移量,windows系统要求每个扫描行按四字节对齐 int alignBytes = (int) (((srcW * bitCount + 31) & ~31) / 8L - srcW * bitCount / 8L); //原图像缓存 int srcBufSize = lineSize * srcH; char[] srcBuf = new char[srcBufSize]; Point pLT = new Point(); Point pRT = new Point(); Point pLB = new Point(); Point pRB = new Point(); pLT.x = -srcW/2;pLT.y = srcH/2; pRT.x = srcW/2;pRT.y = srcH/2; pLB.x = -srcW/2;pLB.y = -srcH/2; pRB.x = srcW/2; pRB.y = -srcH/2; Point pLTN = new Point(); Point pRTN = new Point(); Point pLBN = new Point(); Point pRBN = new Point(); double sina = Math.sin(RADIAN(angle)); double cosa = Math.cos(RADIAN(angle)); pLTN.x = (long) (pLT.x*cosa + pLT.y*sina); pLTN.y = (long) (-pLT.x*sina + pLT.y*cosa); pRTN.x = (long) (pRT.x*cosa + pRT.y*sina); pRTN.y = (long) (-pRT.x*sina + pRT.y*cosa); pLBN.x = (long) (pLB.x*cosa + pLB.y*sina); pLBN.y = (long) (-pLB.x*sina + pLB.y*cosa); pRBN.x = (long) (pRB.x*cosa + pRB.y*sina); pRBN.y = (long) (-pRB.x*sina + pRB.y*cosa); //旋转后图像宽和高 int desWidth = (int) Math.max(Math.abs(pRBN.x - pLTN.x),Math.abs(pRTN.x - pLBN.x)); int desHeight = (int) Math.max(Math.abs(pRBN.y - pLTN.y),Math.abs(pRTN.y - pLBN.y)); //分配旋转后图像的缓存 int desBufSize = ((desWidth * bitCount + 31) / 32) * 4 * desHeight; //unsigned char char[] desBuf = new char[desBufSize]; for(int i = 0; i < desBufSize; i++){ desBuf[i] = 255; } //新图像每一行字节数,带有偏移量 int desLineSize = ((desWidth * bitCount + 31) / 32) * 4; //通过新图像的坐标,计算对应的原图像的坐标 for (int i = 0; i < desHeight; i++) { for (int j = 0; j < desWidth; j++) { //转换到以图像为中心的坐标系,并进行逆旋转 int tX = (int) ((j - desWidth / 2)*Math.cos(RADIAN(360 - angle)) + (-i + desHeight / 2)*Math.sin(RADIAN(360 - angle))); int tY = (int) (-(j - desWidth / 2)*Math.sin(RADIAN(360 - angle)) + (-i + desHeight / 2)*Math.cos(RADIAN(360 - angle))); //如果这个坐标不在原图像内,则不赋值 if (tX > srcW / 2 || tX < -srcW / 2 || tY > srcH / 2 || tY < -srcH / 2) { continue; } //再转换到原坐标系下 int tXN = tX + srcW / 2; int tYN = Math.abs(tY - srcH / 2); //System.out.println(tXN+","+tYN); //值拷贝 // memcpy(desBuf[i * desLineSize + j * bitCount / 8],srcBuf[tYN * lineSize + tXN * bitCount / 8],3); System.arraycopy(srcBuf,(tYN * lineSize + tXN * bitCount / 8),desBuf,(i * desLineSize + j * bitCount / 8),3); } }desBuf里面是我想存到bmp图片的值如下是写入过程:// 创建输出流文件对象 java.io.FileOutputStream fos = new java.io.FileOutputStream( "D:\\MyEclipse-8.6\\testK.bmp"); // 创建原始数据输出流对象 java.io.DataOutputStream dos = new java.io.DataOutputStream(fos); // 给文件头的变量赋值 int bfType = 0x424d; // 位图文件类型(0—1字节) int bfSize = 54 + w * h * 3;// bmp文件的大小(2—5字节) int bfReserved1 = 0;// 位图文件保留字,必须为0(6-7字节) int bfReserved2 = 0;// 位图文件保留字,必须为0(8-9字节) int bfOffBits = 54;// 文件头开始到位图实际数据之间的字节的偏移量(10-13字节) // 输入数据的时候要注意输入的数据在内存中要占几个字节, // 然后再选择相应的写入方法,而不是它自己本身的数据类型 // 输入文件头数据 dos.writeShort(bfType); // 输入位图文件类型'BM' dos.write(changeByte(bfSize),0,4); // 输入位图文件大小 dos.write(changeByte(bfReserved1),0,2);// 输入位图文件保留字 dos.write(changeByte(bfReserved2),0,2);// 输入位图文件保留字 dos.write(changeByte(bfOffBits),0,4);// 输入位图文件偏移量 // 给信息头的变量赋值 int biSize = 40;// 信息头所需的字节数(14-17字节) int biWidth = w;// 位图的宽(18-21字节) int biHeight = h;// 位图的高(22-25字节) int biPlanes = 1; // 目标设备的级别,必须是1(26-27字节) int biBitcount = 24;// 每个像素所需的位数(28-29字节),必须是1位(双色)、4位(16色)、8位(256色)或者24位(真彩色)之一。 int biCompression = 0;// 位图压缩类型,必须是0(不压缩)(30-33字节)、1(BI_RLEB压缩类型)或2(BI_RLE4压缩类型)之一。 int biSizeImage = w * h;// 实际位图图像的大小,即整个实际绘制的图像大小(34-37字节) int biXPelsPerMeter = 0;// 位图水平分辨率,每米像素数(38-41字节)这个数是系统默认值 int biYPelsPerMeter = 0;// 位图垂直分辨率,每米像素数(42-45字节)这个数是系统默认值 int biClrUsed = 0;// 位图实际使用的颜色表中的颜色数(46-49字节),如果为0的话,说明全部使用了 int biClrImportant = 0;// 位图显示过程中重要的颜色数(50-53字节),如果为0的话,说明全部重要 // 因为java是大端存储,那么也就是说同样会大端输出。 // 但计算机是按小端读取,如果我们不改变多字节数据的顺序的话,那么机器就不能正常读取。 // 所以首先调用方法将int数据转变为多个byte数据,并且按小端存储的顺序。 // 输入信息头数据 dos.write(changeByte(biSize),0,4);// 输入信息头数据的总字节数 dos.write(changeByte(biWidth),0,4);// 输入位图的宽 dos.write(changeByte(biHeight),0,4);// 输入位图的高 dos.write(changeByte(biPlanes),0,2);// 输入位图的目标设备级别 dos.write(changeByte(biBitcount),0,2);// 输入每个像素占据的字节数 dos.write(changeByte(biCompression),0,4);// 输入位图的压缩类型 dos.write(changeByte(biSizeImage),0,4);// 输入位图的实际大小 dos.write(changeByte(biXPelsPerMeter),0,4);// 输入位图的水平分辨率 dos.write(changeByte(biYPelsPerMeter),0,4);// 输入位图的垂直分辨率 dos.write(changeByte(biClrUsed),0,4);// 输入位图使用的总颜色数 dos.write(changeByte(biClrImportant),0,4);// 输入位图使用过程中重要的颜色数 for(int i = 0; i < desBufSize; i++){ System.out.println(desBuf[i]-'0'); dos.write(changeByte(desBuf[i]),0,1); } 这个是changeByte(int data)public static byte[] changeByte(int data){ byte b4 = (byte)((data)>>24); byte b3 = (byte)(((data)<<8)>>24); byte b2= (byte)(((data)<<16)>>24); byte b1 = (byte)(((data)<<24)>>24); byte[] bytes = {b1,b2,b3,b4}; return bytes; } 着实看的头晕了就瞎说几句哈,你这个转换可逆么?比如你转了,再转回来,还是原来的图么?感觉changeByte的移位操作,可能不可逆啊。 不可逆的,因为在转换的过程中用到了math类,最后得到的数都强制转化成了int。不过我要实现的结果不可逆也没关系。 不可逆的,因为在转换的过程中用到了math类,最后得到的数都强制转化成了int。不过我要实现的结果不可逆也没关系。那会不会是算法问题?LZ试试一个简单的线条或者点,进行旋转,能得到正确的值么? Jxta(J2SE)jxta configurator 配置 类是可串化的,这是什么意思?? 编译错误和运行错误有什么区别? 关于 float 类型数据的问题 如何获得文件创建日期? java + all jar file for classpath 一道 数学编程题。 请教做java面向对象编程的一般思路 关于jni 的问题,请教高手。。。。。。。。。。。。。。。。。。。。。。 递归问题 关于HashMap的小练习碰到编译问题 求教深入学习JAVA的一些问题
因为我想操作24-bit的bmp格式图片,实现它的旋转,模拟了好了旋转的方法后,我想将旋转的图保存到一个新文件,因为24-bit的位图是一个像素对应3个字节,所以我想每次将数组中的三个值给新的数组
static byte[] copyOf(byte[] original, int newLength)
是否符合你的需求?
我找了一个System.arraycopy(),结果还没有出来,
我想将存有位图数据的char类型数组写入到文件中,但是总是得不到目标图片途中旋转后的图是我想得到的目标图,不知道是不是像素存储的方式错了,总是得到如上的图像
int srcW = w;
int srcH = h;
int bitCount = 24;
int lineSize = bitCount * srcW / 8;
//偏移量,windows系统要求每个扫描行按四字节对齐
int alignBytes = (int) (((srcW * bitCount + 31) & ~31) / 8L
- srcW * bitCount / 8L);
//原图像缓存
int srcBufSize = lineSize * srcH;
char[] srcBuf = new char[srcBufSize];
Point pLT = new Point();
Point pRT = new Point();
Point pLB = new Point();
Point pRB = new Point();
pLT.x = -srcW/2;pLT.y = srcH/2;
pRT.x = srcW/2;pRT.y = srcH/2;
pLB.x = -srcW/2;pLB.y = -srcH/2;
pRB.x = srcW/2; pRB.y = -srcH/2; Point pLTN = new Point();
Point pRTN = new Point();
Point pLBN = new Point();
Point pRBN = new Point();
double sina = Math.sin(RADIAN(angle));
double cosa = Math.cos(RADIAN(angle));
pLTN.x = (long) (pLT.x*cosa + pLT.y*sina);
pLTN.y = (long) (-pLT.x*sina + pLT.y*cosa);
pRTN.x = (long) (pRT.x*cosa + pRT.y*sina);
pRTN.y = (long) (-pRT.x*sina + pRT.y*cosa);
pLBN.x = (long) (pLB.x*cosa + pLB.y*sina);
pLBN.y = (long) (-pLB.x*sina + pLB.y*cosa);
pRBN.x = (long) (pRB.x*cosa + pRB.y*sina);
pRBN.y = (long) (-pRB.x*sina + pRB.y*cosa);
//旋转后图像宽和高
int desWidth = (int) Math.max(Math.abs(pRBN.x - pLTN.x),Math.abs(pRTN.x - pLBN.x));
int desHeight = (int) Math.max(Math.abs(pRBN.y - pLTN.y),Math.abs(pRTN.y - pLBN.y));
//分配旋转后图像的缓存
int desBufSize = ((desWidth * bitCount + 31) / 32) * 4 * desHeight;
//unsigned char
char[] desBuf = new char[desBufSize];
for(int i = 0; i < desBufSize; i++){
desBuf[i] = 255;
}
//新图像每一行字节数,带有偏移量
int desLineSize = ((desWidth * bitCount + 31) / 32) * 4;
//通过新图像的坐标,计算对应的原图像的坐标
for (int i = 0; i < desHeight; i++)
{
for (int j = 0; j < desWidth; j++)
{
//转换到以图像为中心的坐标系,并进行逆旋转
int tX = (int) ((j - desWidth / 2)*Math.cos(RADIAN(360 - angle)) + (-i + desHeight / 2)*Math.sin(RADIAN(360 - angle)));
int tY = (int) (-(j - desWidth / 2)*Math.sin(RADIAN(360 - angle)) + (-i + desHeight / 2)*Math.cos(RADIAN(360 - angle))); //如果这个坐标不在原图像内,则不赋值
if (tX > srcW / 2 || tX < -srcW / 2 || tY > srcH / 2 || tY < -srcH / 2)
{
continue;
}
//再转换到原坐标系下
int tXN = tX + srcW / 2; int tYN = Math.abs(tY - srcH / 2);
//System.out.println(tXN+","+tYN);
//值拷贝
// memcpy(desBuf[i * desLineSize + j * bitCount / 8],srcBuf[tYN * lineSize + tXN * bitCount / 8],3);
System.arraycopy(srcBuf,(tYN * lineSize + tXN * bitCount / 8),desBuf,(i * desLineSize + j * bitCount / 8),3);
}
}
desBuf里面是我想存到bmp图片的值
如下是写入过程:
// 创建输出流文件对象
java.io.FileOutputStream fos = new java.io.FileOutputStream(
"D:\\MyEclipse-8.6\\testK.bmp");
// 创建原始数据输出流对象
java.io.DataOutputStream dos = new java.io.DataOutputStream(fos); // 给文件头的变量赋值
int bfType = 0x424d; // 位图文件类型(0—1字节)
int bfSize = 54 + w * h * 3;// bmp文件的大小(2—5字节)
int bfReserved1 = 0;// 位图文件保留字,必须为0(6-7字节)
int bfReserved2 = 0;// 位图文件保留字,必须为0(8-9字节)
int bfOffBits = 54;// 文件头开始到位图实际数据之间的字节的偏移量(10-13字节) // 输入数据的时候要注意输入的数据在内存中要占几个字节,
// 然后再选择相应的写入方法,而不是它自己本身的数据类型
// 输入文件头数据
dos.writeShort(bfType); // 输入位图文件类型'BM'
dos.write(changeByte(bfSize),0,4); // 输入位图文件大小
dos.write(changeByte(bfReserved1),0,2);// 输入位图文件保留字
dos.write(changeByte(bfReserved2),0,2);// 输入位图文件保留字
dos.write(changeByte(bfOffBits),0,4);// 输入位图文件偏移量 // 给信息头的变量赋值
int biSize = 40;// 信息头所需的字节数(14-17字节)
int biWidth = w;// 位图的宽(18-21字节)
int biHeight = h;// 位图的高(22-25字节)
int biPlanes = 1; // 目标设备的级别,必须是1(26-27字节)
int biBitcount = 24;// 每个像素所需的位数(28-29字节),必须是1位(双色)、4位(16色)、8位(256色)或者24位(真彩色)之一。
int biCompression = 0;// 位图压缩类型,必须是0(不压缩)(30-33字节)、1(BI_RLEB压缩类型)或2(BI_RLE4压缩类型)之一。
int biSizeImage = w * h;// 实际位图图像的大小,即整个实际绘制的图像大小(34-37字节)
int biXPelsPerMeter = 0;// 位图水平分辨率,每米像素数(38-41字节)这个数是系统默认值
int biYPelsPerMeter = 0;// 位图垂直分辨率,每米像素数(42-45字节)这个数是系统默认值
int biClrUsed = 0;// 位图实际使用的颜色表中的颜色数(46-49字节),如果为0的话,说明全部使用了
int biClrImportant = 0;// 位图显示过程中重要的颜色数(50-53字节),如果为0的话,说明全部重要
// 因为java是大端存储,那么也就是说同样会大端输出。
// 但计算机是按小端读取,如果我们不改变多字节数据的顺序的话,那么机器就不能正常读取。
// 所以首先调用方法将int数据转变为多个byte数据,并且按小端存储的顺序。
// 输入信息头数据
dos.write(changeByte(biSize),0,4);// 输入信息头数据的总字节数
dos.write(changeByte(biWidth),0,4);// 输入位图的宽
dos.write(changeByte(biHeight),0,4);// 输入位图的高
dos.write(changeByte(biPlanes),0,2);// 输入位图的目标设备级别
dos.write(changeByte(biBitcount),0,2);// 输入每个像素占据的字节数
dos.write(changeByte(biCompression),0,4);// 输入位图的压缩类型
dos.write(changeByte(biSizeImage),0,4);// 输入位图的实际大小
dos.write(changeByte(biXPelsPerMeter),0,4);// 输入位图的水平分辨率
dos.write(changeByte(biYPelsPerMeter),0,4);// 输入位图的垂直分辨率
dos.write(changeByte(biClrUsed),0,4);// 输入位图使用的总颜色数
dos.write(changeByte(biClrImportant),0,4);// 输入位图使用过程中重要的颜色数
for(int i = 0; i < desBufSize; i++){
System.out.println(desBuf[i]-'0');
dos.write(changeByte(desBuf[i]),0,1);
}
public static byte[] changeByte(int data){
byte b4 = (byte)((data)>>24);
byte b3 = (byte)(((data)<<8)>>24);
byte b2= (byte)(((data)<<16)>>24);
byte b1 = (byte)(((data)<<24)>>24);
byte[] bytes = {b1,b2,b3,b4};
return bytes;
}
就瞎说几句哈,你这个转换可逆么?比如你转了,再转回来,还是原来的图么?感觉changeByte的移位操作,可能不可逆啊。
不过我要实现的结果不可逆也没关系。
不过我要实现的结果不可逆也没关系。
那会不会是算法问题?LZ试试一个简单的线条或者点,进行旋转,能得到正确的值么?