编译skia静态库时,图片解码库无法注册的问题

转载:http://www.cnblogs.com/imlucky/archive/2012/08/01/2617851.html

今天编译skia库,增加图片解码库时总是无效。按照此博客的方法修改后成功,特此转载。


android编译skia静态库时,图片解码库无法注册的问题

经过千辛万苦将skia编译成了静态库,但是发现图片解码都不成功,后来发现是图片解码库没有注册成功,可能是代码优化导致的,但是加上-O0编译选项也不行。后来就在SkImageDecoder_Factory.cpp中直接调用各个解码库的注册文件,结果png解码可以了,但是jpeg和gif编译不通过,后来发现时需要一个-fvisibility=hidden编译选项,增加后就OK了。修改的skia文件如下:

SkImageDecoder_Factory.cpp

/* libs/graphics/ports/SkImageDecoder_Factory.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#include "SkImageDecoder.h"
#include "SkMovie.h"
#include "SkStream.h"
#include "SkTRegistry.h"
#include "dhlog.h"

typedef SkTRegistry<SkImageDecoder*, SkStream*> DecodeReg;

// N.B. You can't use "DecodeReg::gHead here" due to complex C++
// corner cases.
template DecodeReg* SkTRegistry<SkImageDecoder*, SkStream*>::gHead;

#ifdef SK_ENABLE_LIBPNG
    extern SkImageDecoder* sk_libpng_dfactory(SkStream*);
#endif
#ifdef SK_ENABLE_LIBJPEG
    extern SkImageDecoder* sk_libjpeg_dfactory(SkStream*);
#endif
#ifdef SK_ENABLE_LIBGIF
    extern SkImageDecoder* sk_libgif_dfactory(SkStream*);
#endif

SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
    SkImageDecoder* codec = NULL;
    const DecodeReg* curr = DecodeReg::Head();
    logdh("SkImageDecoder::Factory curr=0x%x", curr);
    while (curr) {
        codec = curr->factory()(stream);
        logdh("SkImageDecoder::Factory stream=0x%x codec=0x%x", stream, codec);
        // we rewind here, because we promise later when we call "decode", that
        // the stream will be at its beginning.
        stream->rewind();
        if (codec) {
            return codec;
        }
        curr = curr->next();
    }
#ifdef SK_ENABLE_LIBPNG
    codec = sk_libpng_dfactory(stream);
    if (codec) {
        stream->rewind();
        return codec;
    }
#endif
#ifdef SK_ENABLE_LIBJPEG
    logdh("SkImageDecoder::Factory enter SK_ENABLE_LIBJPEG");
    //for jpeg decode

    codec = sk_libjpeg_dfactory(stream);
    if (codec) {
        logdh("SkImageDecoder::Factory codec=0x%x ok", codec);
        stream->rewind();
        return codec;
    }
#endif
#ifdef SK_ENABLE_LIBGIF
    //for gif decode
    codec = sk_libgif_dfactory(stream);
    if (codec) {
        stream->rewind();
        return codec;
    }
#endif
    return NULL;
}

/////////////////////////////////////////////////////////////////////////

typedef SkTRegistry<SkMovie*, SkStream*> MovieReg;

SkMovie* SkMovie::DecodeStream(SkStream* stream) {
    const MovieReg* curr = MovieReg::Head();
    while (curr) {
        SkMovie* movie = curr->factory()(stream);
        if (movie) {
            return movie;
        }
        // we must rewind only if we got NULL, since we gave the stream to the
        // movie, who may have already started reading from it
        stream->rewind();
        curr = curr->next();
    }
    return NULL;
}

SkImageDecoder_libgif.cpp

/* libs/graphics/images/SkImageDecoder_libgif.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#include "SkImageDecoder.h"
#include "SkColor.h"
#include "SkColorPriv.h"
#include "SkStream.h"
#include "SkTemplates.h"
#include "SkPackBits.h"

#include "gif_lib.h"

class SkGIFImageDecoder : public SkImageDecoder {
public:
    virtual Format getFormat() const {
        return kGIF_Format;
    }

protected:
    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
};

static const uint8_t gStartingIterlaceYValue[] = {
    0, 4, 2, 1
};
static const uint8_t gDeltaIterlaceYValue[] = {
    8, 8, 4, 2
};

/*  Implement the GIF interlace algorithm in an iterator.
    1) grab every 8th line beginning at 0
    2) grab every 8th line beginning at 4
    3) grab every 4th line beginning at 2
    4) grab every 2nd line beginning at 1
*/
class GifInterlaceIter {
public:
    GifInterlaceIter(int height) : fHeight(height) {
        fStartYPtr = gStartingIterlaceYValue;
        fDeltaYPtr = gDeltaIterlaceYValue;

        fCurrY = *fStartYPtr++;
        fDeltaY = *fDeltaYPtr++;
    }

    int currY() const {
        SkASSERT(fStartYPtr);
        SkASSERT(fDeltaYPtr);
        return fCurrY;
    }

    void next() {
        SkASSERT(fStartYPtr);
        SkASSERT(fDeltaYPtr);

        int y = fCurrY + fDeltaY;
        // We went from an if statement to a while loop so that we iterate
        // through fStartYPtr until a valid row is found. This is so that images
        // that are smaller than 5x5 will not trash memory.
        while (y >= fHeight) {
            if (gStartingIterlaceYValue +
                    SK_ARRAY_COUNT(gStartingIterlaceYValue) == fStartYPtr) {
                // we done
                SkDEBUGCODE(fStartYPtr = NULL;)
                SkDEBUGCODE(fDeltaYPtr = NULL;)
                y = 0;
            } else {
                y = *fStartYPtr++;
                fDeltaY = *fDeltaYPtr++;
            }
        }
        fCurrY = y;
    }

private:
    const int fHeight;
    int fCurrY;
    int fDeltaY;
    const uint8_t* fStartYPtr;
    const uint8_t* fDeltaYPtr;
};

///////////////////////////////////////////////////////////////////////////////

//#define GIF_STAMP       "GIF"    /* First chars in file - GIF stamp. */
//#define GIF_STAMP_LEN   (sizeof(GIF_STAMP) - 1)

static int DecodeCallBackProc(GifFileType* fileType, GifByteType* out,
                              int size) {
    SkStream* stream = (SkStream*) fileType->UserData;
    return (int) stream->read(out, size);
}

void CheckFreeExtension(SavedImage* Image) {
    if (Image->ExtensionBlocks) {
        FreeExtension(Image);
    }
}

// return NULL on failure
static const ColorMapObject* find_colormap(const GifFileType* gif) {
    const ColorMapObject* cmap = gif->Image.ColorMap;
    if (NULL == cmap) {
        cmap = gif->SColorMap;
    }

    if (NULL == cmap) {
        // no colormap found
        return NULL;
    }
    // some sanity checks
    if (cmap && ((unsigned)cmap->ColorCount > 256 ||
                 cmap->ColorCount != (1 << cmap->BitsPerPixel))) {
        cmap = NULL;
    }
    return cmap;
}

// return -1 if not found (i.e. we're completely opaque)
static int find_transpIndex(const SavedImage& image, int colorCount) {
    int transpIndex = -1;
    for (int i = 0; i < image.ExtensionBlockCount; ++i) {
        const ExtensionBlock* eb = image.ExtensionBlocks + i;
        if (eb->Function == 0xF9 && eb->ByteCount == 4) {
            if (eb->Bytes[0] & 1) {
                transpIndex = (unsigned char)eb->Bytes[3];
                // check for valid transpIndex
                if (transpIndex >= colorCount) {
                    transpIndex = -1;
                }
                break;
            }
        }
    }
    return transpIndex;
}

static bool error_return(GifFileType* gif, const SkBitmap& bm,
                         const char msg[]) {
#if 0
    SkDebugf("libgif error <%s> bitmap [%d %d] pixels %p colortable %p\n",
             msg, bm.width(), bm.height(), bm.getPixels(), bm.getColorTable());
#endif
    return false;
}

bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, Mode mode) {
    GifFileType* gif = DGifOpen(sk_stream, DecodeCallBackProc);
    if (NULL == gif) {
        return error_return(gif, *bm, "DGifOpen");
    }

    SkAutoTCallIProc<GifFileType, DGifCloseFile> acp(gif);

    SavedImage temp_save;
    temp_save.ExtensionBlocks=NULL;
    temp_save.ExtensionBlockCount=0;
    SkAutoTCallVProc<SavedImage, CheckFreeExtension> acp2(&temp_save);

    int width, height;
    GifRecordType recType;
    GifByteType *extData;
    int transpIndex = -1;   // -1 means we don't have it (yet)

    do {
        if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
            return error_return(gif, *bm, "DGifGetRecordType");
        }

        switch (recType) {
        case IMAGE_DESC_RECORD_TYPE: {
            if (DGifGetImageDesc(gif) == GIF_ERROR) {
                return error_return(gif, *bm, "IMAGE_DESC_RECORD_TYPE");
            }

            if (gif->ImageCount < 1) {    // sanity check
                return error_return(gif, *bm, "ImageCount < 1");
            }

            width = gif->SWidth;
            height = gif->SHeight;
            if (width <= 0 || height <= 0 ||
                !this->chooseFromOneChoice(SkBitmap::kIndex8_Config,
                                           width, height)) {
                return error_return(gif, *bm, "chooseFromOneChoice");
            }

            bm->setConfig(SkBitmap::kIndex8_Config, width, height);
            if (SkImageDecoder::kDecodeBounds_Mode == mode)
                return true;

            SavedImage* image = &gif->SavedImages[gif->ImageCount-1];
            const GifImageDesc& desc = image->ImageDesc;

            // check for valid descriptor
            if (   (desc.Top | desc.Left) < 0 ||
                    desc.Left + desc.Width > width ||
                    desc.Top + desc.Height > height) {
                return error_return(gif, *bm, "TopLeft");
            }

            // now we decode the colortable
            int colorCount = 0;
            {
                const ColorMapObject* cmap = find_colormap(gif);
                if (NULL == cmap) {
                    return error_return(gif, *bm, "null cmap");
                }

                colorCount = cmap->ColorCount;
                SkColorTable* ctable = SkNEW_ARGS(SkColorTable, (colorCount));
                SkPMColor* colorPtr = ctable->lockColors();
                for (int index = 0; index < colorCount; index++)
                    colorPtr[index] = SkPackARGB32(0xFF,
                                                   cmap->Colors[index].Red,
                                                   cmap->Colors[index].Green,
                                                   cmap->Colors[index].Blue);

                transpIndex = find_transpIndex(temp_save, colorCount);
                if (transpIndex < 0)
                    ctable->setFlags(ctable->getFlags() | SkColorTable::kColorsAreOpaque_Flag);
                else
                    colorPtr[transpIndex] = 0; // ram in a transparent SkPMColor
                ctable->unlockColors(true);

                SkAutoUnref aurts(ctable);
                if (!this->allocPixelRef(bm, ctable)) {
                    return error_return(gif, *bm, "allocPixelRef");
                }
            }

            SkAutoLockPixels alp(*bm);

            // time to decode the scanlines
            //
            uint8_t*  scanline = bm->getAddr8(0, 0);
            const int rowBytes = bm->rowBytes();
            const int innerWidth = desc.Width;
            const int innerHeight = desc.Height;

            // abort if either inner dimension is <= 0
            if (innerWidth <= 0 || innerHeight <= 0) {
                return error_return(gif, *bm, "non-pos inner width/height");
            }

            // are we only a subset of the total bounds?
            if ((desc.Top | desc.Left) > 0 ||
                 innerWidth < width || innerHeight < height)
            {
                int fill;
                if (transpIndex >= 0) {
                    fill = transpIndex;
                } else {
                    fill = gif->SBackGroundColor;
                }
                // check for valid fill index/color
                if (static_cast<unsigned>(fill) >=
                        static_cast<unsigned>(colorCount)) {
                    fill = 0;
                }
                memset(scanline, fill, bm->getSize());
                // bump our starting address
                scanline += desc.Top * rowBytes + desc.Left;
            }

            // now decode each scanline
            if (gif->Image.Interlace)
            {
                GifInterlaceIter iter(innerHeight);
                for (int y = 0; y < innerHeight; y++)
                {
                    uint8_t* row = scanline + iter.currY() * rowBytes;
                    if (DGifGetLine(gif, row, innerWidth) == GIF_ERROR) {
                        return error_return(gif, *bm, "interlace DGifGetLine");
                    }
                    iter.next();
                }
            }
            else
            {
                // easy, non-interlace case
                for (int y = 0; y < innerHeight; y++) {
                    if (DGifGetLine(gif, scanline, innerWidth) == GIF_ERROR) {
                        return error_return(gif, *bm, "DGifGetLine");
                    }
                    scanline += rowBytes;
                }
            }
            goto DONE;
            } break;

        case EXTENSION_RECORD_TYPE:
            if (DGifGetExtension(gif, &temp_save.Function,
                                 &extData) == GIF_ERROR) {
                return error_return(gif, *bm, "DGifGetExtension");
            }

            while (extData != NULL) {
                /* Create an extension block with our data */
                if (AddExtensionBlock(&temp_save, extData[0],
                                      &extData[1]) == GIF_ERROR) {
                    return error_return(gif, *bm, "AddExtensionBlock");
                }
                if (DGifGetExtensionNext(gif, &extData) == GIF_ERROR) {
                    return error_return(gif, *bm, "DGifGetExtensionNext");
                }
                temp_save.Function = 0;
            }
            break;

        case TERMINATE_RECORD_TYPE:
            break;

        default:    /* Should be trapped by DGifGetRecordType */
            break;
        }
    } while (recType != TERMINATE_RECORD_TYPE);

DONE:
    return true;
}

///////////////////////////////////////////////////////////////////////////////

#include "SkTRegistry.h"

static SkImageDecoder* Factory(SkStream* stream) {
    char buf[GIF_STAMP_LEN];
    if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
        if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
                memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
                memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) {
            return SkNEW(SkGIFImageDecoder);
        }
    }
    return NULL;
}

#ifdef SK_ENABLE_LIBGIF
    SkImageDecoder* sk_libgif_dfactory(SkStream*);
#endif

SkImageDecoder* sk_libgif_dfactory(SkStream* stream) {
    char buf[GIF_STAMP_LEN];
    if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
        if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
                memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
                memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) {
            return SkNEW(SkGIFImageDecoder);
        }
    }
    return NULL;
}

static SkTRegistry<SkImageDecoder*, SkStream*> gReg(sk_libgif_dfactory);

SkImageDecoder_libjpeg.cpp(略)

SkImageDecoder_libpng.cpp(略)

然后再skia的android.mk文件中增加:

LOCAL_CFLAGS += -DSK_ENABLE_LIBPNG
LOCAL_CFLAGS += -DSK_ENABLE_LIBJPEG
LOCAL_CFLAGS += -DSK_ENABLE_LIBGIF

时间: 2024-08-20 12:54:44

编译skia静态库时,图片解码库无法注册的问题的相关文章

[译] 当发布安卓开源库时我希望知道的东西

本文讲的是[译] 当发布安卓开源库时我希望知道的东西, 原文地址:Things I wish I knew when I started building Android SDK/Libraries 原文作者:本文已获作者 Nishant Srivastava 授权 译文出自:掘金翻译计划 译者:jifaxu 校对者:BoilerYao, gaozp 当发布安卓开源库时我希望知道的东西 一切要从安卓开发者开发自己的"超酷炫应用"开始说起,他们中的大多数会在这个过程中遇到一系列问题,而他

c++-同时使用STLport和boost库时编译通过,但链接失败,求解决方案,急!!!

问题描述 同时使用STLport和boost库时编译通过,但链接失败,求解决方案,急!!! 具体问题是这样的: 我用的是vs2008,把STLport和boost库都加入项目,编译时报错:boostconfigauto_link.hpp(204): fatal error C1189: #error : "Build options aren't compatible with pre-built libraries" 解决方法是在 项目属性->c/c++->命令行 添加

linux下php添加mysqli拓展库时,编译报错

问题描述 linux下php添加mysqli拓展库时,编译报错 php和mysql都是已经编译安装好了,现在想要给php添加mysqli 拓展库,结果在make的时候报错 cd /usr/local/src/php-5.6.19/ext/mysqli /usr/local/php/bin/phpize ./configure --with-php-config=/usr/local/php/bin/php-config --with-mysqli=/usr/local/mysql/bin/mys

mingw-MinGw编译GMP库时出错,跪求大神解答

问题描述 MinGw编译GMP库时出错,跪求大神解答 Config.log如下: This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by GNU MP configure 6.1.0, which was generated by GNU Autoconf 2.69.

在linux下编译软件和第三方库时不分debug和release吗?

问题描述 在linux下编译软件和第三方库时不分debug和release吗? 在win下,通常需要编译debug和release两个版本. 但是我在linux下编译一些第三方的软件和类库,例如QT/jsoncpp/ACE等等在编译的时候都只能选择debug和release中的一个版本,很少有能同时编译两个版本的. 而且用官方的安装软件编译的QT5.5,我查看文件也发现只有一个版本链接库,在QtCreator却可以生成debug和release两种版本的代码.很困惑究竟是为什么?是Qt的原因还是

ANDROID动态加载 使用SO库时要注意的一些问题

基本信息 作者:kaedea 项目:android-dynamical-loading Android项目里的SO库 正好动态加载系列文章谈到了加载SO库的地方,我觉得这里可以顺便谈谈使用SO库时需要注意的一些问题.或许这些问题对于经常和SO库开发打交道的同学来说已经是老生长谈,但是既然要讨论一整个动态加载系列,我想还是有必要说说使用SO库时的一些问题. 在项目里使用SO库非常简单,在 加载SD卡中的SO库 中也有谈到,只需要把需要用到的SO库拷贝进 jniLibs(或者Eclipse项目里面的

原创企业级控件库之图片浏览控件

在上两篇:我介绍了原创企业级控件库之组合查询控件 和原创企业级控件库之大数据量分页控件,受到了很多朋友的支持,给了我很大的动力,在此我特表感谢.有的朋友要求把源码提供上来,我在第一篇就讲了,源码会在我这个系列讲完之后提供,大家先别着急,如果你确实需要,可以时常关注此系列,谢谢大家.其实,在系列文章中,我已把核心代码贡献出来了.学习有时是参考别人与实践别人的劳动成果的过程,你光把别人的代码拿过来用用,不研究其实质,进步很慢. 这篇我将给大家介绍:企业级控件库之图片浏览控件. 摘要 我想大家用过或听

PNG 图片处理库 libpng 曝出漏洞,已初步修复

图片处理库libpng日前曝出漏洞,且需要尽快得到修复.最大的问题在于,libpng的普及范围实在太过广泛--浏览器中任何与生成缩略图相关的图片处理任务外加文件查看工具.音乐播放器等每款操作系统都离不开的应用程序. 经过精心构建的图片能够导致应用甚至服务器进程发生崩溃. 首先强调,这不是什么好消息:图片处理库libpng日前曝出漏洞,且需要尽快得到修复. 最大的问题在于,libpng的普及范围实在太过广泛--浏览器中任何与生成缩略图相关的图片处理任务外加文件查看工具.音乐播放器等每款操作系统都离

php使用GD库创建图片缩略图的方法_php技巧

本文实例讲述了php使用GD库创建图片缩略图的方法.分享给大家供大家参考.具体分析如下: 上传页面的静态html代码: <html> <head> <title>文件上传</title> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> </head> <H1>文件上传</H1> &l