zoukankan      html  css  js  c++  java
  • 编译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
    ",
                 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

  • 相关阅读:
    MySQL5.7修改默认密码、随机密码
    Java基础知识_毕向东_Java基础视频教程笔记(26 反射)
    Java基础知识_毕向东_Java基础视频教程笔记(22-25 GUI 网络编程 正则)
    Java基础知识_毕向东_Java基础视频教程笔记(19-21 IO流)
    Java基础知识_毕向东_Java基础视频教程笔记(14-18集合框架)
    Java基础知识_毕向东_Java基础视频教程笔记(13 字符)
    Java基础知识_毕向东_Java基础视频教程笔记(11-12 多线程)
    JIT和AOT编译详解
    PAT 说反话
    PAT 程序运行时间
  • 原文地址:https://www.cnblogs.com/redrainblog/p/4275823.html
Copyright © 2011-2022 走看看