[Android]libpng的編譯與使用

庫地址

https://github.com/julienr/libpng-android

設置NDK環境變量

將NDK目錄加入PATH變量:
C:\Users\xx\AppData\Local\Android\Sdk\ndk\20.0.5594570\

靜態庫

修改Android.mk文件

#LOCAL_SHARED_LIBRARIES := -lz
LOCAL_EXPORT_LDLIBS := -lz
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/.

#include $(BUILD_SHARED_LIBRARY)
include $(BUILD_STATIC_LIBRARY)

動態庫

修改Android.mk文件

#LOCAL_SHARED_LIBRARIES := -lz
#LOCAL_EXPORT_LDLIBS := -lz
LOCAL_LDLIBS := -lz 
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/.

include $(BUILD_SHARED_LIBRARY)
#include $(BUILD_STATIC_LIBRARY)

編譯命令

ndk-build NDK_PROJECT_PATH=./

libpng庫使用

從內存中讀取png圖片數據,解碼爲RGBA格式的raw數據
glPngReader.h

//
// Created by Jinzhu on 2019/9/7.
//

#ifndef OPENGLES_GLPNGREADER_H
#define OPENGLES_GLPNGREADER_H


#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
#include <string.h>

struct glPngReader {
    uint8_t *m_raw_data;
    size_t m_raw_size;
    size_t m_raw_offset;

    int m_width;
    int m_height;
    int m_color_type;
    int m_pixel_depth;

    int m_status;

    uint8_t *m_pixel_data;
};

void glPngReader_Create(struct glPngReader *pngReader, uint8_t *raw_data, size_t raw_size);
void glPngReader_Destory(struct glPngReader *pngReader);

uint8_t *glPngReader_GetPixelData(struct glPngReader *pngReader);

int glPngReader_GetWidth(struct glPngReader *pngReader);
int glPngReader_GetHeight(struct glPngReader *pngReader);


#ifdef __cplusplus
};
#endif


#endif //OPENGLES_GLPNGREADER_H

glPngReader.c

//
// Created by Jinzhu on 2019/9/7.
//


#include <android/log.h>

#ifdef __cplusplus
extern "C" {
#endif

#include "glPngReader.h"
#include <pnglibconf.h>
#include <png.h>
#include <pngstruct.h>
#include <pngconf.h>
#include <pnginfo.h>


#define LOG_TAG "PNGREADER-LIB"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)


void glPngReader_ReadCallback(png_structp png_ptr, png_bytep data, png_size_t length) {
    struct glPngReader *pThis = (struct glPngReader *) png_get_io_ptr(png_ptr);
    if (pThis != NULL) {
        if (pThis->m_raw_offset + length <= pThis->m_raw_size) {
            memcpy(data, pThis->m_raw_data + pThis->m_raw_offset, length);
            pThis->m_raw_offset += length;
        } else {
            ALOGE("the length is illegal.");
        }
    }
}

void glPngReader_ReadImage(struct glPngReader *pngReader) {
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        ALOGE("load libpng error,png_ptr = NULL.");
        pngReader->m_status = 0;
        return;
    }
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        ALOGE("load libpng error,info_ptr = NULL.");
        pngReader->m_status = 0;
        return;
    }


    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        ALOGE("libpng process error.");
        pngReader->m_status = 0;
        return;
    }


    png_set_read_fn(png_ptr, pngReader, glPngReader_ReadCallback);
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, NULL);

    pngReader->m_width = info_ptr->width;
    pngReader->m_height = info_ptr->height;
    pngReader->m_color_type = info_ptr->color_type;
    pngReader->m_pixel_depth = info_ptr->pixel_depth;

    if ((pngReader->m_color_type != PNG_COLOR_TYPE_RGB &&
         pngReader->m_color_type != PNG_COLOR_TYPE_RGB_ALPHA)
        && pngReader->m_pixel_depth == 8) {
        ALOGE("image format error.");
        pngReader->m_status = 0;
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return;
    }

    if (pngReader->m_pixel_data != NULL) {
        free(pngReader->m_pixel_data);
        pngReader->m_pixel_data = NULL;
    }
    pngReader->m_pixel_data = (uint8_t *) malloc(pngReader->m_width * pngReader->m_height * 4);

    png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);

    if (pngReader->m_color_type == PNG_COLOR_TYPE_RGB) {
        int pos = 0;
        for (int row = 0; row < pngReader->m_height; ++row) {
            for (int col = 0; col < (3 * pngReader->m_width); col += 3) {
                pngReader->m_pixel_data[pos++] = row_pointers[row][col + 0];//RED
                pngReader->m_pixel_data[pos++] = row_pointers[row][col + 1];//GREEN
                pngReader->m_pixel_data[pos++] = row_pointers[row][col + 2];//BLUE
                pngReader->m_pixel_data[pos++] = 255;//ALPHA
            }
        }
        pngReader->m_status = 1;
    } else if (pngReader->m_color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
        int pos = 0;
        for (int row = 0; row < pngReader->m_height; ++row) {
            for (int col = 0; col < (4 * pngReader->m_width); col += 4) {
                pngReader->m_pixel_data[pos++] = row_pointers[row][col + 0];//RED
                pngReader->m_pixel_data[pos++] = row_pointers[row][col + 1];//GREEN
                pngReader->m_pixel_data[pos++] = row_pointers[row][col + 2];//BLUE
                pngReader->m_pixel_data[pos++] = row_pointers[row][col + 3];//ALPHA
            }
        }
        pngReader->m_status = 1;
    } else {
        pngReader->m_status = 0;
    }
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
}

void glPngReader_Create(struct glPngReader *pngReader, uint8_t *raw_data, size_t raw_size) {
    pngReader->m_raw_data = raw_data;
    pngReader->m_raw_size = raw_size;
    pngReader->m_raw_offset = 0;

    pngReader->m_width = 0;
    pngReader->m_height = 0;
    pngReader->m_color_type = PNG_TRANSFORM_STRIP_ALPHA;
    pngReader->m_pixel_depth = 8;

    pngReader->m_status = 0;
    pngReader->m_pixel_data = NULL;

    glPngReader_ReadImage(pngReader);
}

void glPngReader_Destory(struct glPngReader *pngReader) {
    if (pngReader->m_pixel_data != NULL) {
        free(pngReader->m_pixel_data);
        pngReader->m_pixel_data = NULL;
    }
}

uint8_t *glPngReader_GetPixelData(struct glPngReader *pngReader) { return pngReader->m_pixel_data; }

int glPngReader_GetWidth(struct glPngReader *pngReader) { return pngReader->m_width; }

int glPngReader_GetHeight(struct glPngReader *pngReader) { return pngReader->m_height; }

#ifdef __cplusplus
};
#endif
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章