org.oscim.ios.backend.IosBitmap.java Source code

Java tutorial

Introduction

Here is the source code for org.oscim.ios.backend.IosBitmap.java

Source

/*
 * Copyright 2016 Longri
 *
 * This program is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.oscim.ios.backend;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Pixmap;
import org.oscim.backend.AssetAdapter;
import org.oscim.backend.GL;
import org.oscim.backend.canvas.Bitmap;
import org.oscim.backend.canvas.Color;
import org.robovm.apple.coregraphics.*;
import org.robovm.apple.foundation.NSData;
import org.robovm.apple.uikit.UIColor;
import org.robovm.apple.uikit.UIImage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * iOS specific implementation of {@link Bitmap}<br>
 * <br>
 * Created by Longri on 25.06.16.
 */
public class IosBitmap implements Bitmap {

    static final Logger log = LoggerFactory.getLogger(IosBitmap.class);

    final CGBitmapContext cgBitmapContext;
    final int width;
    final int height;
    Pixmap pixmap;

    /**
     * Constructor<br>
     * Create a IosBitmap with given width and height. <br>
     * The format is ignored and set always to ARGB8888
     *
     * @param width
     * @param height
     * @param format ignored always ARGB8888
     */
    public IosBitmap(int width, int height, int format) {
        this.width = width;
        this.height = height;
        this.cgBitmapContext = CGBitmapContext.create(width, height, 8, 4 * width, CGColorSpace.createDeviceRGB(),
                CGImageAlphaInfo.PremultipliedLast);
    }

    /**
     * Constructor<br>
     * Create a IosBitmap from given InputStream
     *
     * @param inputStream
     * @throws IOException
     */
    public IosBitmap(InputStream inputStream) throws IOException {
        NSData data = new NSData(toByteArray(inputStream));
        CGImage image = new UIImage(data).getCGImage();
        this.width = (int) image.getWidth();
        this.height = (int) image.getHeight();
        this.cgBitmapContext = CGBitmapContext.create(width, height, 8, 4 * width, CGColorSpace.createDeviceRGB(),
                CGImageAlphaInfo.PremultipliedLast);

        this.cgBitmapContext.drawImage(new CGRect(0, 0, width, height), image);
        image.dispose();
    }

    /**
     * Constructor<br>
     * Load a IosBitmap from Asset with given FilePath
     *
     * @param fileName
     * @throws IOException
     */
    public IosBitmap(String fileName) throws IOException {
        if (fileName == null || fileName.length() == 0) {
            // no image source defined
            this.cgBitmapContext = null;
            this.width = 0;
            this.height = 0;
            return;
        }

        InputStream inputStream = AssetAdapter.readFileAsStream(fileName);
        if (inputStream == null) {
            log.error("invalid bitmap source: " + fileName);
            // no image source defined
            this.cgBitmapContext = null;
            this.width = 0;
            this.height = 0;
            return;
        }

        NSData data = new NSData(toByteArray(inputStream));
        CGImage image = new UIImage(data).getCGImage();
        this.width = (int) image.getWidth();
        this.height = (int) image.getHeight();
        this.cgBitmapContext = CGBitmapContext.create(width, height, 8, 4 * width, CGColorSpace.createDeviceRGB(),
                CGImageAlphaInfo.PremultipliedLast);

        this.cgBitmapContext.drawImage(new CGRect(0, 0, width, height), image);
        image.dispose();
    }

    @Override
    public int getWidth() {
        return this.width;
    }

    @Override
    public int getHeight() {
        return this.height;
    }

    @Override
    public void recycle() {
        if (this.cgBitmapContext != null)
            this.cgBitmapContext.release();
        if (this.pixmap != null)
            this.pixmap.dispose();
    }

    @Override
    public int[] getPixels() {
        //Todo fill a int[] with pixmap.getPixel(x,y)
        return new int[0];
    }

    @Override
    public void eraseColor(int color) {

        //delete all pixels and fill with given color

        CGRect rect = new CGRect(0, 0, this.width, this.height);
        this.cgBitmapContext.setFillColor(getCGColor(color));
        this.cgBitmapContext.setBlendMode(CGBlendMode.Clear);
        this.cgBitmapContext.fillRect(rect);
        this.cgBitmapContext.setBlendMode(CGBlendMode.Normal);
        this.cgBitmapContext.fillRect(rect);
    }

    @Override
    public void uploadToTexture(boolean replace) {

        //create Pixmap from cgBitmapContext
        UIImage uiImage = new UIImage(cgBitmapContext.toImage());
        NSData data = uiImage.toPNGData();
        byte[] encodedData = data.getBytes();

        if (pixmap != null) {
            // release outdated native pixel buffer
            pixmap.dispose();
        }

        pixmap = new Pixmap(encodedData, 0, encodedData.length);

        Gdx.gl.glTexImage2D(GL.TEXTURE_2D, 0, pixmap.getGLInternalFormat(), pixmap.getWidth(), pixmap.getHeight(),
                0, pixmap.getGLFormat(), pixmap.getGLType(), pixmap.getPixels());

        data.dispose();
        uiImage.dispose();
        encodedData = null;

    }

    @Override
    public boolean isValid() {
        return this.cgBitmapContext != null;
    }

    /**
     * Returns a ByteArray from InputStream
     *
     * @param in InputStream
     * @return
     * @throws IOException
     */
    static byte[] toByteArray(InputStream in) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buff = new byte[8192];
        while (in.read(buff) > 0) {
            out.write(buff);
        }
        out.close();
        return out.toByteArray();
    }

    /**
     * Returns the CGColor from given int
     *
     * @param color
     * @return
     */
    static CGColor getCGColor(int color) {
        return UIColor.fromRGBA(Color.a(color), Color.g(color), Color.b(color), Color.r(color)).getCGColor();
    }
}