新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → PSD格式文件的读取 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 8579 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: PSD格式文件的读取 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 PSD格式文件的读取

    PhotoShop,我想没有人会不知道吧。其图象文件*.PSD和5.5相比变化并不太大。以下我就介绍*.PSD文件的读取方法,并提供完整读取函数。其中:m_Rect为目标区域,m_lpDDS7为目标DirectDraw表面,m_pbAlphaMask为目标Aplha通告指针。Read16函数为从指定文件当前位置读取一个WORD,Read32函数为从指定文件当前位置读取一个DWORD。MAX_PSD_CHANNELS为24。以下就是*.PSD文件的读取方法,有兴趣的朋友可以继续深入研究,到时可别忘了发我一份。

      HRESULT LoadPSD( LPSTR strFilename ) // 读取PSD文件
      {
        DWORD dwWidth, dwHeight; // 宽高
        long lSurfWidth = m_Rect.right - m_Rect.left;
        long lSurfHeight = m_Rect.bottom - m_Rect.top;
        WORD CompressionType; // 压缩类型
        HDC hDC;
        FILE *fpPSD;
        WORD ChannelCount; // 通道数

        // 打开PSD文件
        if ( ( fpPSD = fopen ( strFilename, "rb" ) ) == NULL ) {
          return E_FAIL;
        }

        // 头四个字节为"8BPS"
        char signature[5];
        signature[0] = fgetc( fpPSD );
        signature[1] = fgetc( fpPSD );
        signature[2] = fgetc( fpPSD );
        signature[3] = fgetc( fpPSD );
        signature[4] = '\0';
        if ( strcmp( signature,"8BPS" ) != 0 ) {
          return E_FAIL;
        }

        // 版本必须为1
        if ( Read16( fpPSD ) != 1 ) {
          return E_FAIL;
        }

        // 跳过一些数据 (总是0)
        Read32( fpPSD );
        Read16( fpPSD );

        // 读取通道数
        ChannelCount = Read16( fpPSD );

        // 确定至少有一个通道
        if ( ( ChannelCount < 0 ) || ( ChannelCount > MAX_PSD_CHANNELS ) ) {
          return E_FAIL;
        }

        // 读入宽和高
        dwHeight = Read32( fpPSD );
        dwWidth = Read32( fpPSD );
        if ( dwWidth != ( DWORD )lSurfWidth || dwHeight != ( DWORD )lSurfHeight ) {
          return E_FAIL;
        }

        // 只读入8位通道
        if ( Read16( fpPSD ) != 8 ) {
          return E_FAIL;
        }

        // 确定模式为RGB.
        // 可能值:
        // 0: 位图
        // 1: 灰阶
        // 2: 索引
        // 3: RGB
        // 4: CMYK
        // 7: Multichannel
        // 8: Duotone
        // 9: Lab
        if ( Read16( fpPSD ) != 3 ) {
          return E_FAIL;
        }

        // 跳过数据(如调色板)
        int ModeDataCount = Read32( fpPSD );
        if ( ModeDataCount )
          fseek( fpPSD, ModeDataCount, SEEK_CUR );

        // 跳过数据(如:pen tool paths, etc)
        int ResourceDataCount = Read32( fpPSD );
        if ( ResourceDataCount )
          fseek( fpPSD, ResourceDataCount, SEEK_CUR );

        // 条过保留数据
        int ReservedDataCount = Read32( fpPSD );
        if ( ReservedDataCount )
          fseek( fpPSD, ReservedDataCount, SEEK_CUR );

        // 0: 非压缩
        // 1: RLE压缩
        CompressionType = Read16( fpPSD );
        if ( CompressionType > 1 ) {
          return E_FAIL;
        }

        BYTE* PSDPixels = new BYTE[ ( lSurfWidth * lSurfHeight ) * 4 ];

        // 解包数据
        UnPackPSD( fpPSD, lSurfWidth, lSurfHeight, PSDPixels, ChannelCount, CompressionType );

        fclose( fpPSD );

        // 复制信息
        BITMAPINFO BitmapInfo;
        ZeroMemory( &BitmapInfo, sizeof( BitmapInfo ) );
        BitmapInfo.bmiHeader.biSize = sizeof( BitmapInfo.bmiHeader );
        BitmapInfo.bmiHeader.biWidth = lSurfWidth;
        BitmapInfo.bmiHeader.biHeight = -lSurfHeight;
        BitmapInfo.bmiHeader.biPlanes = 1;
        BitmapInfo.bmiHeader.biBitCount = 32;

        m_lpDDS7->GetDC( &hDC );

        int rc = StretchDIBits( hDC,
                    0,
                    0,
                    lSurfWidth,
                    lSurfHeight,
                    0,
                    0,
                    lSurfWidth,
                    lSurfHeight,
                    PSDPixels,
                    &BitmapInfo,
                    DIB_RGB_COLORS,
                    SRCCOPY );

        m_lpDDS7->ReleaseDC( hDC );

        if ( rc == GDI_ERROR ) {
          H_ARRAY_DELETE( PSDPixels );

      #ifdef _DEBUG
        g_pHERR->OutDebugMsg( 3, H2DSERR_INVALID_PSD );
      #endif
        return E_FAIL;

        }

        // 是否读取Alpha混合通道
        if( ChannelCount > 3 ) {
          m_pbAlphaMask = new BYTE[ lSurfWidth * lSurfHeight ];

        for ( int x = 0; x < lSurfWidth; x++ )
          for ( int y = 0; y < lSurfHeight; y++ ) {
            m_pbAlphaMask[ ( y * lSurfWidth ) + x ] =
                    PSDPixels[ ( ( ( y * lSurfHeight ) + x ) * 4 ) + 3 ];
          }
        }
        else {
          m_pbAlphaMask = NULL;
        }

        H_ARRAY_DELETE( PSDPixels );

        return DD_OK;
      }

      // PSD文件解包
     
      void CHades2DSurface::UnPackPSD( FILE *fp,     // fp为PSD文件指针,
                       DWORD dwWidth,   // dwWidth、dwHeight为宽高,
                       DWORD dwHeight,
                       BYTE* pixels,   // pixels为解包目标指针,
                       WORD ChannelCnt,  // ChannelCnt为通道数,
                       WORD Compression ) // Compression位压缩类型。
                    
                    
      {
        int Default[4] = { 0, 0, 0, 255 };
        int chn[4] = { 2, 1, 0, 3};
        int PixelCount = dwWidth * dwHeight;

        if ( Compression ) {
          fseek( fp, dwHeight * ChannelCnt * 2, SEEK_CUR );

          for ( int c = 0; c < 4; c++ ) {
            int pn = 0;
            int channel = chn[c];

            if ( channel >= ChannelCnt ) {
              for ( pn=0; pn < PixelCount ;pn++ ) {
                pixels[ ( pn * 4 ) + channel ] = Default[ channel ];
              }
            }
            else // 非压缩
            {
              int count = 0;
              while( count < PixelCount ) {
                int len = fgetc( fp );
                if( len == 128 ) { }
                else if ( len < 128 ) // 非RLE
                {
                  len++;
                  count += len;
                  while(len) {
                    pixels[ ( pn * 4 ) + channel ] = fgetc( fp );
                    pn++;
                    len--;
                  }
                }
                 else if ( len > 128 ) // RLE打包
                {
                  len ^= 0x0FF;
                  len += 2;
                  unsigned char val = fgetc( fp );
                  count += len;
                  while( len ) {
                    pixels[ ( pn * 4 ) + channel ] = val;
                    pn++;
                    len--;
                  }
                }
              }
            }
          }
        }
        else
        {
          for ( int c=0; c < 4; c++ ) {
            int channel = chn[c];
            if ( channel > ChannelCnt ) {
              for( int pn = 0; pn < PixelCount; pn++ ) {
                pixels[ ( pn * 4 ) + channel ] = Default[ channel ];
              }
            }
            else {
              for( int n = 0; n < PixelCount; n++ ) {
                pixels[ ( n * 4 ) + channel ] = fgetc( fp );
              }
            }
          }
        }
      }


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/5/7 10:44:00
     
     zjun001 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:1
      积分:55
      门派:XML.ORG.CN
      注册:2008/1/7

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给zjun001发送一个短消息 把zjun001加入好友 查看zjun001的个人资料 搜索zjun001在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看zjun001的博客2
    发贴心情 请问有没有办法 读出  psd文件中的各图层的混合选项
    比如说,我要用程序 判断 某个psd文件的某个 图层 是否应用了“斜面和浮雕“的效果、以及各参数的设置是否符合 要求。
        如能回答,就帮了我一个大忙,我找相关资料都快找疯了。
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/1/7 15:39:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2025/7/18 15:55:03

    本主题贴数2,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    46.875ms