解决方案 »

  1.   

    为啥要操作内存呢?你需要实现什么功能呢?如果是拷贝数组,可以在Arrays类里找到封装好的方法。
      

  2.   


    因为我想操作24-bit的bmp格式图片,实现它的旋转,模拟了好了旋转的方法后,我想将旋转的图保存到一个新文件,因为24-bit的位图是一个像素对应3个字节,所以我想每次将数组中的三个值给新的数组
      

  3.   

    JDK的Arrays类有方法:
    static byte[] copyOf(byte[] original, int newLength)  
    是否符合你的需求?
      

  4.   


    我找了一个System.arraycopy(),结果还没有出来,
    我想将存有位图数据的char类型数组写入到文件中,但是总是得不到目标图片途中旋转后的图是我想得到的目标图,不知道是不是像素存储的方式错了,总是得到如上的图像
      

  5.   

    //以图像中心为原点左上角,右上角,左下角和右下角的坐标,用于计算旋转后的图像的宽和高
    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);
    }
      

  6.   

    这个是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;
    }
      

  7.   

    着实看的头晕了
    就瞎说几句哈,你这个转换可逆么?比如你转了,再转回来,还是原来的图么?感觉changeByte的移位操作,可能不可逆啊。
      

  8.   

    不可逆的,因为在转换的过程中用到了math类,最后得到的数都强制转化成了int。
    不过我要实现的结果不可逆也没关系。
      

  9.   

    不可逆的,因为在转换的过程中用到了math类,最后得到的数都强制转化成了int。
    不过我要实现的结果不可逆也没关系。
    那会不会是算法问题?LZ试试一个简单的线条或者点,进行旋转,能得到正确的值么?