Android转换原始数据到Png图像颜色不好?

时间:2012-07-05 12:00:44

标签: android png

我试图将纯原始数据转换为png图像。我无法获得具有精确颜色的正确输出图像。

作为参考我已经附加了原始文件和图像。请建议我用正确的颜色获得图像。我添加了图像和原始文件。

CODE

File screensPath = new File(SCREENSHOT_FOLDER);
            screensPath.mkdirs();

            // construct screenshot file name
            StringBuilder sb = new StringBuilder();
            sb.append(SCREENSHOT_FOLDER);
            sb.append(Math.abs(UUID.randomUUID().hashCode()));  // hash code of UUID should be quite random yet short
            sb.append(".png");
            String file = sb.toString();

            // fetch the screen and save it
            Screenshot ss = null;
            try {
                ss = retreiveRawScreenshot();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            if(ss!=null)
            {
            writeImageFile(ss, file);
            }

            incre++;



 private Screenshot retreiveRawScreenshot() throws Exception {
        try {


             InputStream    is = new FileInputStream("/mnt/sdcard/screenshots/ss"+incre+".raw");
            // retrieve response -- first the size and BPP of the screenshot

            StringBuilder sb = new StringBuilder();
            int c;
            while ((c = is.read()) != -1) {
                if (c == 0) break;
                sb.append((char)c);
            }

        //========================================= not used =====================================
            // parse it
            String[] screenData = sb.toString().split(" ");
            if (screenData.length >= 3) {
                System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$ ");
                Screenshot ss = new Screenshot();
                ss.width = Integer.parseInt(screenData[0]);
                ss.height = Integer.parseInt(screenData[1]);
                ss.bpp = Integer.parseInt(screenData[2]);
                System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$ ");
                // retreive the screenshot
                // (this method - via ByteBuffer - seems to be the fastest)
                ByteBuffer bytes = ByteBuffer.allocate (ss.width * ss.height * ss.bpp / 8);
                is = new BufferedInputStream(is);   // buffering is very important apparently

                byte[] rgbsnew = null;
                toRGB565(bytes.array(), ss.width, ss.height, rgbsnew);


            //  is.read(bytes.array());             // reading all at once for speed
                is.read(rgbsnew);               // reading all at once for speed

                bytes.position(0);                  // reset position to the beginning of ByteBuffer

                ss.pixels =ByteBuffer.wrap(rgbsnew);

                // convert byte-buffer to integer

                return ss;
            }
     //========================================= not used ==========================================        
            Screenshot ss = new Screenshot();
            ss.width = 320;
            ss.height = 480;
            ss.bpp = 16;
            ByteBuffer bytes = ByteBuffer.allocate (ss.width * ss.height * ss.bpp / 8);
            is = new BufferedInputStream(is);   // buffering is very important apparently
            is.read(bytes.array());             // reading all at once for speed
            bytes.position(0);                  // reset position to the beginning of ByteBuffer
            ss.pixels = bytes;

            //============================= newly tried to set raw to image view ==============================
            /*mRawImage = new RawImage();
            mRawImage.readHeader(1, bytes);

         // Receive framebuffer data.
            byte[] data = new byte[mRawImage.size];
            bytes = ByteBuffer.wrap(data);         
            mRawImage.data = data;

            Bitmap bmp=BitmapFactory.decodeByteArray(mRawImage.data,0,mRawImage.data.length);

            imageView1.setImageBitmap(bmp);*/


          //============================newly tried to set raw to image view  ===============================
            return ss;
        }
        catch (Exception e) {

        //  throw new Exception(e);
            return null;
        }
        finally {}

        //return null;
    }

    class Screenshot {
        public Buffer pixels;
        public int width;
        public int height;
        public int bpp;

        public boolean isValid() {
            if (pixels == null || pixels.capacity() == 0 || pixels.limit() == 0) return false;
            if (width <= 0 || height <= 0)  return false;
            return true;
        }
    }


    private void writeImageFile(Screenshot ss, String file) {
        //if (ss == null || !ss.isValid())      throw new IllegalArgumentException();
        //if (file == null || file.length() == 0)   throw new IllegalArgumentException();

        // resolve screenshot's BPP to actual bitmap pixel format
        Bitmap.Config pf;
        switch (ss.bpp) {
            //case 16:  pf = Config.RGB_565; break;

            case 16:    pf = Config.RGB_565; break;
            case 32:    pf = Config.ARGB_8888; break;
            default:    pf = Config.ARGB_8888; break;
        }
//=====================================================================
        /*int[] rgb24 = new int[ss.pixels.capacity()];
        int i = 0;
        for (;i<320*480;i++)
        {
            //uint16_t pixel16 = ((uint16_t *)gr_framebuffer[0].data)[i];
            //int pixel16=(IntBuffer)
                    int pixel16=Integer.parseInt(ss.pixels.position(i).toString());




            // RRRRRGGGGGGBBBBBB -> RRRRRRRRGGGGGGGGBBBBBBBB
            // in rgb24 color max is 2^8 per channel (*255/32 *255/64 *255/32)
            rgb24[3*i+2]   = (255*(pixel16 & 0x001F))/ 32;      //Blue
            rgb24[3*i+1]   = (255*((pixel16 & 0x07E0) >> 5))/64;    //Green
            rgb24[3*i]     = (255*((pixel16 & 0xF800) >> 11))/32;   //Red
        }
        //ss.pixels=rgb24;
*///=====================================================================       

        // create appropriate bitmap and fill it wit data
        Bitmap bmp = Bitmap.createBitmap(ss.width, ss.height, pf);
        bmp.copyPixelsFromBuffer(ss.pixels);

        // handle the screen rotation
        int rot = getScreenRotation();
        if (rot != 0) {
            Matrix matrix = new Matrix();
            matrix.postRotate(-rot);
            bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
        }

        // save it in PNG format
        FileOutputStream fos;
        try {
            fos = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            throw new InvalidParameterException();
        }
        bmp.compress(CompressFormat.PNG, 100, fos);
    }

    private int getScreenRotation()  {
        WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);
        Display disp = wm.getDefaultDisplay();

        // check whether we operate under Android 2.2 or later
        try {
            Class<?> displayClass = disp.getClass();
            Method getRotation = displayClass.getMethod("getRotation");
            int rot = ((Integer)getRotation.invoke(disp)).intValue();

                switch (rot) {
                    case Surface.ROTATION_0:    return 0;
                    case Surface.ROTATION_90:   return 90;
                    case Surface.ROTATION_180:  return 180;
                    case Surface.ROTATION_270:  return 270;
                    default:                    return 0;
                }
        } catch (NoSuchMethodException e) {
            // no getRotation() method -- fall back to dispation()
            int orientation = disp.getOrientation();

            // Sometimes you may get undefined orientation Value is 0
            // simple logic solves the problem compare the screen
            // X,Y Co-ordinates and determine the Orientation in such cases
            if(orientation==Configuration.ORIENTATION_UNDEFINED){

                Configuration config = getResources().getConfiguration();
                orientation = config.orientation;

                if(orientation==Configuration.ORIENTATION_UNDEFINED){
                    //if height and widht of screen are equal then
                    // it is square orientation
                    if(disp.getWidth()==disp.getHeight()){
                        orientation = Configuration.ORIENTATION_SQUARE;
                    }else{ //if widht is less than height than it is portrait
                        if(disp.getWidth() < disp.getHeight()){
                            orientation = Configuration.ORIENTATION_PORTRAIT;
                        }else{ // if it is not any of the above it will defineitly be landscape
                            orientation = Configuration.ORIENTATION_LANDSCAPE;
                        }
                    }
                }
            }

            return orientation == 1 ? 0 : 90; // 1 for portrait, 2 for landscape
        } catch (Exception e) {
            return 0; // bad, I know ;P
        }
    }

    //===========================================================================
    /**
     * Converts semi-planar YUV420 as generated for camera preview into RGB565
     * format for use as an OpenGL ES texture. It assumes that both the input
     * and output data are contiguous and start at zero.
     * 
     * @param yuvs the array of YUV420 semi-planar data
     * @param rgbs an array into which the RGB565 data will be written
     * @param width the number of pixels horizontally
     * @param height the number of pixels vertically
     */

    //we tackle the conversion two pixels at a time for greater speed
    private void toRGB565(byte[] yuvs, int width, int height, byte[] rgbs) {
        //the end of the luminance data
        final int lumEnd = width * height;
        //points to the next luminance value pair
        int lumPtr = 0;
        //points to the next chromiance value pair
        int chrPtr = lumEnd;
        //points to the next byte output pair of RGB565 value
        int outPtr = 0;
        //the end of the current luminance scanline
        int lineEnd = width;

        while (true) {

            //skip back to the start of the chromiance values when necessary
            if (lumPtr == lineEnd) {
                if (lumPtr == lumEnd) break; //we've reached the end
                //division here is a bit expensive, but's only done once per scanline
                chrPtr = lumEnd + ((lumPtr  >> 1) / width) * width;
                lineEnd += width;
            }

            //read the luminance and chromiance values
            final int Y1 = yuvs[lumPtr++] & 0xff; 
            final int Y2 = yuvs[lumPtr++] & 0xff; 
            final int Cr = (yuvs[chrPtr++] & 0xff) - 128; 
            final int Cb = (yuvs[chrPtr++] & 0xff) - 128;
            int R, G, B;

            //generate first RGB components
            B = Y1 + ((454 * Cb) >> 8);
            if(B < 0) B = 0; else if(B > 255) B = 255; 
            G = Y1 - ((88 * Cb + 183 * Cr) >> 8); 
            if(G < 0) G = 0; else if(G > 255) G = 255; 
            R = Y1 + ((359 * Cr) >> 8); 
            if(R < 0) R = 0; else if(R > 255) R = 255; 
            //NOTE: this assume little-endian encoding
            rgbs[outPtr++]  = (byte) (((G & 0x3c) << 3) | (B >> 3));
            rgbs[outPtr++]  = (byte) ((R & 0xf8) | (G >> 5));

            //generate second RGB components
            B = Y2 + ((454 * Cb) >> 8);
            if(B < 0) B = 0; else if(B > 255) B = 255; 
            G = Y2 - ((88 * Cb + 183 * Cr) >> 8); 
            if(G < 0) G = 0; else if(G > 255) G = 255; 
            R = Y2 + ((359 * Cr) >> 8); 
            if(R < 0) R = 0; else if(R > 255) R = 255; 
            //NOTE: this assume little-endian encoding
            rgbs[outPtr++]  = (byte) (((G & 0x3c) << 3) | (B >> 3));
            rgbs[outPtr++]  = (byte) ((R & 0xf8) | (G >> 5));
        }
    }

谢谢。                    Image RAW file

0 个答案:

没有答案