首页 > 其他分享 >Android 编译和使用libpng

Android 编译和使用libpng

时间:2023-10-02 11:32:28浏览次数:25  
标签:lib .. library libraries 编译 libpng Android png


libpng

libpng is the official PNG reference library. It supports almost all PNG features, is extensible, and has been extensively tested for over 28 years. The home site for development versions (i.e., may be buggy or subject to change or include experimental features) is https://libpng.sourceforge.io/, and the place to go for questions about the library is the png-mng-implement mailing list. libpng is available as ANSI C (C89) source code and requires zlib 1.0.4 or later (1.2.13 or later recommended for performance and security reasons). The current public release, libpng 1.6.40, is a maintenance release with various fixes and improvements to the build
scripts, docs, and handlers for three of the chunk types (eXIf, pCAL,tRNS).

从上面的信息中可以看出libpng是一个历史悠久的处理png的库,需要zlib依赖。

Android版本

Android版本的libpng。

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

将代码clone下来就可以进行编译了。

编译

静态库

使用下面的命令可以直接编译为静态库。

ndk-build NDK_PROJECT_PATH=./

动态库

修改Android.mk中的,编译动态库

include $(BUILD_SHARED_LIBRARY)
# include $(BUILD_STATIC_LIBRARY)

使用上面的命令编译报错,从错误中推测应该需要zlib依赖,还需要下载zlib,由于Android自带zlib库,遂使用cmake进行。

Android 编译和使用libpng_android-studio


只需要在CmakeList.txt中加入下面这句话就可以了。ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/libpng-android-master) 。这个路径是clone下来的libpng中CmakeLists.txt所在的目录。

cmake_minimum_required(VERSION 3.22.1)
# Declares and names the project.
project("myapplication")
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/libpng-android-master)
# set(png-lib ${CMAKE_SOURCE_DIR}/../../../libs)
#将第三方库作为动态库引用
add_library( # Sets the name of the library.
        myapplication

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp)

修改libpng中CmakeLists.txt中的add_library,修改为动态共享库。

find_package( zlib REQUIRED )

# If you want a shared library instead of static, specify the BUILD_SHARED_LIBS
# variable (which is a built-in CMake option).
add_library( ${project_name} SHARED  ${sources} ${headers} )
target_link_libraries( ${project_name} PUBLIC ZLIB::ZLIB )
target_include_directories( ${project_name} PUBLIC
    $<BUILD_INTERFACE:${source_dir}>
    $<INSTALL_INTERFACE:include>
)

然后就可以通过Build Apks进行编译了。

使用

将编译出来的so文件放在libs文件夹下面。也就是下面代码中的${CMAKE_SOURCE_DIR}/../../../libs将相应的.h问价拷贝到应用程序代码能够引用到的位置即可

CMakeLists.txt内容如下:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.22.1)
set(my_lib_path ${CMAKE_SOURCE_DIR}/../../../libs)

# Declares and names the project.

project("myapplication")

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
# ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/libpng-android-master)
set(png-lib ${CMAKE_SOURCE_DIR}/../../../libs)
#将第三方库作为动态库引用
add_library(png-lib
        SHARED
        IMPORTED)
#指定第三方库的绝对路径
set_target_properties(png-lib
        PROPERTIES IMPORTED_LOCATION
        ${my_lib_path}/${ANDROID_ABI}/libpng.so)

add_library( # Sets the name of the library.
        myapplication

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        myapplication
        png-lib
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib}
        )

官方的例子

“android_png.h”

#ifndef _ANDROID_PNG_H_
#define _ANDROID_PNG_H_

#include "common.h"

class AAssetManager;

struct ImageData {
  int img_width, img_height;
  uint8_t* pixels;

  virtual ~ImageData();
};

inline
bool IsPowerOfTwo(int n) {
  // http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/
  return (n & (n - 1)) == 0;
}

inline
int NextPowerOfTwo(int n) {
  // Explanation : http://stackoverflow.com/questions/1322510/given-an-integer-how-do-i-find-the-next-largest-power-of-two-using-bit-twiddlin
  if (n < 0) {
    return 0;
  }
  n--;
  n |= n >> 1;   // Divide by 2^k for consecutive doublings of k up to 32,
  n |= n >> 2;   // and then or the results.
  n |= n >> 4;
  n |= n >> 8;
  n |= n >> 16;
  n++;           // The result is a number of 1 bits equal to the number
                 // of bits in the original number, plus 1. That's the
                 // next highest power of 2.
  return n;
}

// Loads a PNG image from the asset directory
// Note that this REQUIRES that fname has a power-of-two size
ImageData* FromAssetPNGFile(AAssetManager* mgr, const string& fname);


#endif
#include "android_png.h"

#include <android/asset_manager.h>
#include "png.h"

struct PNGImageData : public ImageData {
  PNGImageData(png_byte* pixels, int width, int height) {
    this->img_width = width;
    this->img_height = height;
    this->pixels = (uint8_t*)pixels;
  }

  virtual ~PNGImageData() {
    delete[] pixels;
  }
};

static AAsset* asset;

void png_asset_read(png_structp png_ptr, png_bytep data, png_size_t length) {
  CHECK_GT(AAsset_read(asset, data, length), 0) << "Reading past end-of-file";
}

// Adapted from http://en.wikibooks.org/wiki/OpenGL_Programming/Intermediate/Textures
ImageData* FromAssetPNGFile(AAssetManager* mgr, const string& fname) {
  asset = AAssetManager_open(mgr, fname.c_str(), AASSET_MODE_STREAMING);
  if (!asset) {
    LOG(ERROR) << "Error opening " <<  fname;
    return NULL;
  }

  //header for testing if it is a png
  png_byte header[8];

  //read the header
  AAsset_read(asset, header, 8);

  //test if png
  int is_png = !png_sig_cmp(header, 0, 8);
  if (!is_png) {
    AAsset_close(asset);
    LOG(ERROR) << "Not a png file : " << fname;
    return NULL;
  }

  //create png struct
  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
      NULL, NULL);
  if (!png_ptr) {
    AAsset_close(asset);
    LOG(ERROR) << "Unable to create png struct : " << fname;
    return NULL;
  }

  //create png info struct
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
    LOG(ERROR) << "Unable to create png info : " << fname;
    AAsset_close(asset);
    return NULL;
  }

  //create png end info struct
  png_infop end_info = png_create_info_struct(png_ptr);
  if (!end_info) {
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
    LOG(ERROR) << "Unable to create png end info : " << fname;
    AAsset_close(asset);
    return NULL;
  }

  //png error stuff, not sure libpng man suggests this.
  if (setjmp(png_jmpbuf(png_ptr))) {
    AAsset_close(asset);
    LOG(ERROR) << "Error during setjmp : " << fname;
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    return NULL;
  }

  //init png reading
  //png_init_io(png_ptr, fp);
  png_set_read_fn(png_ptr, NULL, png_asset_read);

  //let libpng know you already read the first 8 bytes
  png_set_sig_bytes(png_ptr, 8);

  // read all the info up to the image data
  png_read_info(png_ptr, info_ptr);

  //variables to pass to get info
  int bit_depth, color_type;
  png_uint_32 width, height;

  // get info about png
  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
      NULL, NULL, NULL);

  if (!IsPowerOfTwo(width) || !IsPowerOfTwo(height)) {
      LOG(ERROR) << "Non-power of two (" << width << "x" << height
                 << ") texture are not supported : " << fname;
      png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
      AAsset_close(asset);
      return NULL;
  }

  // Update the png info struct.
  png_read_update_info(png_ptr, info_ptr);

  // Row size in bytes.
  int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

  // Allocate the image_data as a big block
  png_byte *image_data = new png_byte[rowbytes * height];
  if (!image_data) {
    //clean up memory and close stuff
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    LOG(ERROR) << "Unable to allocate image_data while loading " << fname;
    AAsset_close(asset);
    return NULL;
  }

  //row_pointers is for pointing to image_data for reading the png with libpng
  png_bytep *row_pointers = new png_bytep[height];
  if (!row_pointers) {
    //clean up memory and close stuff
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    delete[] image_data;
    LOG(ERROR) << "Unable to allocate row_pointer while loading " << fname;
    AAsset_close(asset);
    return NULL;
  }
  // set the individual row_pointers to point at the correct offsets of image_data
  for (int i = 0; i < height; ++i) {
    //row_pointers[height - 1 - i] = image_data + i * rowbytes;
    row_pointers[i] = image_data + i * rowbytes;
  }

  //read the png into image_data through row_pointers
  png_read_image(png_ptr, row_pointers);

  ImageData* img = new PNGImageData(image_data, width, height);

  //clean up memory and close stuff
  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  delete[] row_pointers;

  AAsset_close(asset);

  return img;
}

目录结构

Android 编译和使用libpng_ide_02

公众号

更多内容,欢迎关注我的微信公众号: 半夏之夜的无情剑客。


标签:lib,..,library,libraries,编译,libpng,Android,png
From: https://blog.51cto.com/u_16087831/7682455

相关文章

  • lapce源码学习-编译调试
    master分支调试1、报错:`#![feature]`maynotbeusedonthestablereleasechannel2、Channel切换到nightly,报错:thetraitbound`file_type::FileType:std::sealed::Sealed`isnotsatisfied3、Channel切换到beta,编译ok,但提示不能调试rustupinstallbeta4、编译成功后,......
  • Android中OkHttp源码阅读二(责任链模式)
    AndroidOkHttp源码阅读详解一看OkHttp源码,发现OkHttp里面使用了责任链设计模式,所以才要学习责任链设计模式小节2最终会返回ResponseResponsegetResponseWithInterceptorChain()throwsIOException{//Buildafullstackofinterceptors.List<Interceptor>inte......
  • 解决Android studio 更新到2022.3版本后,一直卡在waiting for target device to come o
    解决Androidstudio更新到2022.3.1patch1之后卡在waitingfortargetdevicetocomeonline的问题1.现象在发布一个app的时候,每次走到waitingforalltargetdevicestocomeonline之后,就没有后续了,模拟器没有调起来,更不用谈后续的install。2.原因暂时不明3.解决方法......
  • 点播模块编译nginx
    VOD模块NGINX编译部署主要解决我那破电视的观影需求、软件装不了又不想掏钱看线上广告;U盘也没法播、没几个兼容的解码软件,五六年前的电视买的是真坑爹,我又不会刷机,那索性用废笔记本装linux整个nginx-vod模块整个音视频链接,电视上用短小精悍的VLC观影。下包mkdir/usr/local/n......
  • 【rk356x】Linux Cmake如何进行交叉编译
    compiler.arm.cmakeSET(GCC_PATH/work/xxx/buildroot/output/rockchip/host/bin)SET(toolpathprefix${GCC_PATH}/aarch64-buildroot-linux-gnu-)set(libusb_path/work/xxx/libusb/install/lib/pkgconfig/libusb-1.0.pc)SET(CMAKE_C_COMPILER${toolpathprefix}gcc)SET......
  • 【X3m】opencv和opencv_contrib交叉编译
    opencv和contrib版本必须要一直,否则可以编译不匹配opencv4-4.5.4.tar.gzopencv4-contrib-4.5.5.tar.gzopencv交叉编译命令,主要eigen3的地址cmake\-DCMAKE_BUILD_TYPE=Release\-DCMAKE_INSTALL_PREFIX=../install\-DBUILD_PNG=ON\-DBUILD_TIFF=ON\......
  • Go每日一库之136:gopherjs(将Go代码编译成JS)
    简介GopherJS可以将Go代码编译成纯JavaScript代码。其主要目的是为了让你可以使用Go来编写前端代码,这些代码可执行在浏览器上运行。你可以通过这里尝试下GopherJS:GopherJSPlayground.例如JavaScript代码:document.write("Hello world!");用GopherJS来写就变成这......
  • maven 编译.../maven-metadata.xml 报错
    问题突然编译报错:解决打开maven的里离线工作模式,感觉就是下载包到本地.一个是在maven设置里面或者直接在maven编译的窗口:......
  • flutter编译安卓/ios命令
    一、flutter打包编译命令1、编译安卓apkflutterbuildapk--debug--flavorbeta--build-number=123--build-name=1.2.3--target-platformandroid-arm--split-per-abi--dart-define=APP_CHANNEL=vivo--dart-define=APP_NAME=TestApp 2、编译安卓AppBundle ......
  • ovs编译安装
    ovs打开debug.ci/linux-build.sh中-O2改成-O0编译安装ovsgitclonehttps://github.com/openvswitch/ovs.git./boot.sh./configure--prefix=/usr--localstatedir=/var--sysconfdir=/etcmakemakeinstall ......