static void SwapCoreHeader(BITMAPCOREHEADER *header) { SwapLong(&header->bcSize); SwapShort(&header->bcWidth); SwapShort(&header->bcHeight); SwapShort(&header->bcPlanes); SwapShort(&header->bcBitCnt); }
static void SwapOS21XHeader(BITMAPINFOOS2_1X_HEADER *header) { SwapLong(&header->biSize); SwapShort(&header->biWidth); SwapShort(&header->biHeight); SwapShort(&header->biPlanes); SwapShort(&header->biBitCount); }
static void SwapFileHeader(BITMAPFILEHEADER *header) { SwapShort(&header->bfType); SwapLong(&header->bfSize); SwapShort(&header->bfReserved1); SwapShort(&header->bfReserved2); SwapLong(&header->bfOffBits); }
static void SwapHeader(SGIHeader *header) { SwapShort(&header->magic); SwapShort(&header->dimension); SwapShort(&header->xsize); SwapShort(&header->ysize); SwapShort(&header->zsize); SwapLong((DWORD*)&header->pixmin); SwapLong((DWORD*)&header->pixmax); SwapLong((DWORD*)&header->colormap); }
static void SwapHeader(PCXHEADER *header) { SwapShort(&header->window[0]); SwapShort(&header->window[1]); SwapShort(&header->window[2]); SwapShort(&header->window[3]); SwapShort(&header->hdpi); SwapShort(&header->vdpi); SwapShort(&header->bytes_per_line); SwapShort(&header->palette_info); SwapShort(&header->h_screen_size); SwapShort(&header->v_screen_size); }
ILint iGetScanLine(ILubyte *ScanLine, iSgiHeader *Head, ILuint Length) { ILushort Pixel, Count; // For current pixel ILuint BppRead = 0, CurPos = 0, Bps = Head->XSize * Head->Bpc; while (BppRead < Length && CurPos < Bps) { Pixel = 0; if (iread(&Pixel, Head->Bpc, 1) != 1) return -1; #ifndef __LITTLE_ENDIAN__ Pixel = SwapShort(Pixel); #endif if (!(Count = (Pixel & 0x7f))) // If 0, line ends return CurPos; if (Pixel & 0x80) { // If top bit set, then it is a "run" if (iread(ScanLine, Head->Bpc, Count) != Count) return -1; BppRead += Head->Bpc * Count + Head->Bpc; ScanLine += Head->Bpc * Count; CurPos += Head->Bpc * Count; } else { if (iread(&Pixel, Head->Bpc, 1) != 1) return -1; #ifndef __LITTLE_ENDIAN__ Pixel = SwapShort(Pixel); #endif if (Head->Bpc == 1) { while (Count--) { *ScanLine = (ILubyte)Pixel; ScanLine++; CurPos++; } } else { while (Count--) { *(ILushort*)ScanLine = Pixel; ScanLine += 2; CurPos += 2; } } BppRead += Head->Bpc + Head->Bpc; } } return CurPos; }
static void SwapInfoHeader(BITMAPINFOHEADER *header) { SwapLong(&header->biSize); SwapLong((DWORD *)&header->biWidth); SwapLong((DWORD *)&header->biHeight); SwapShort(&header->biPlanes); SwapShort(&header->biBitCount); SwapLong(&header->biCompression); SwapLong(&header->biSizeImage); SwapLong((DWORD *)&header->biXPelsPerMeter); SwapLong((DWORD *)&header->biYPelsPerMeter); SwapLong(&header->biClrUsed); SwapLong(&header->biClrImportant); }
bool CmpParser::openFile(std::string filename){ this->closeFile(); file.open (filename.c_str(), std::fstream::in | std::fstream::binary); if (file.is_open()==false) return false; file.read((char*)&hdr,sizeof(HTKhdr)); if (IsVAXOrder()){ SwapShort(&hdr.sampSize); SwapShort(&hdr.sampKind); SwapInt32(&hdr.sampPeriod); SwapInt32(&hdr.nSamples); } return true; }
void F_CastPrint(char* text) { char* ch; int c; int cx; int w; int width; // find width ch = text; width = 0; while (ch) { c = *ch++; if (!c) break; c = toupper(c) - HU_FONTSTART; if (c < 0 || c > HU_FONTSIZE) { width += 4; continue; } w = SwapShort(hu_font[c]->width); width += w; } // draw it cx = 160 - width / 2; ch = text; while (ch) { c = *ch++; if (!c) break; c = toupper(c) - HU_FONTSTART; if (c < 0 || c > HU_FONTSIZE) { cx += 4; continue; } w = SwapShort(hu_font[c]->width); V_DrawPatch(cx, 180, 0, hu_font[c]); cx += w; } }
void HUlib_eraseTextLine(hu_textline_t* l) { // killough 11/98: trick to shadow variables int x = viewwindowx, y = viewwindowy; int viewwindowx = x >> hires, viewwindowy = y >> hires; // killough 11/98 // Only erases when NOT in automap and the screen is reduced, // and the text must either need updating or refreshing // (because of a recent change back from the automap) if (!automapactive && viewwindowx && l->needsupdate) { int yoffset, lh = SwapShort(l->f[0]->height) + 1; for (y = l->y, yoffset = y * SCREENWIDTH ; y < l->y + lh ; y++, yoffset += SCREENWIDTH) if (y < viewwindowy || y >= viewwindowy + scaledviewheight) // killough 11/98: R_VideoErase(yoffset, SCREENWIDTH); // erase entire line else { // erase left border R_VideoErase(yoffset, viewwindowx); // erase right border R_VideoErase(yoffset + viewwindowx + scaledviewwidth, viewwindowx); // killough 11/98 } } if (l->needsupdate) l->needsupdate--; }
static void HUlib_eraseMBg(hu_mtext_t* m) { // killough 11/98: trick to shadow variables int x = viewwindowx, y = viewwindowy; int viewwindowx = x >> hires, viewwindowy = y >> hires; // killough 11/98 // Only erases when NOT in automap and the screen is reduced, // and the text must either need updating or refreshing // (because of a recent change back from the automap) if (!automapactive && viewwindowx) { int yoffset, lh = SwapShort(m->l[0].f[0]->height) + 1; for (y = m->y, yoffset = y * SCREENWIDTH; y < m->y + lh * (hud_msg_lines + 2); y++, yoffset += SCREENWIDTH) if (y < viewwindowy || y >= viewwindowy + scaledviewheight) // killough 11/98 R_VideoErase(yoffset, SCREENWIDTH); // erase entire line else { // erase left border R_VideoErase(yoffset, viewwindowx); // erase right border R_VideoErase(yoffset + viewwindowx + scaledviewwidth, viewwindowx); // killough 11/98 } } }
/******************************************************************** * ConvertUnsignedShortBuffer ********************************************************************/ void ConvertUnsignedShortBuffer(unsigned short *buffer, unsigned long nbShorts) { while (nbShorts-- > 0) { *buffer = SwapShort(*buffer); buffer++; } }
// // P_InitSwitchList() // // Only called at game initialization in order to list the set of switches // and buttons known to the engine. This enables their texture to change // when activated, and in the case of buttons, change back after a timeout. // // This routine modified to read its data from a predefined lump or // PWAD lump called SWITCHES rather than a static table in this module to // allow wad designers to insert or modify switches. // // Lump format is an array of byte packed switchlist_t structures, terminated // by a structure with episode == -0. The lump can be generated from a // text source file using SWANTBLS.EXE, distributed with the BOOM utils. // The standard list of switches and animations is contained in the example // source text file DEFSWANI.DAT also in the BOOM util distribution. // // Rewritten by Lee Killough to remove limit 2/8/98 // void P_InitSwitchList(void) { int index = 0; int episode; switchlist_t *alphSwitchList; //jff 3/23/98 pointer to switch table int lumpnum = -1; episode = GameModeInfo->switchEpisode; //jff 3/23/98 read the switch table from a predefined lump // haleyjd 08/29/09: run down the hash chain for SWITCHES WadChainIterator wci(wGlobalDir, "SWITCHES"); for(wci.begin(); wci.current(); wci.next()) { // look for a lump which is of a possibly good size if(wci.testLump() && (*wci)->size % sizeof(switchlist_t) == 0) { lumpnum = (*wci)->selfindex; break; } } if(lumpnum < 0) I_Error("P_InitSwitchList: missing SWITCHES lump\n"); alphSwitchList = (switchlist_t *)(wGlobalDir.cacheLumpNum(lumpnum, PU_STATIC)); for(int i = 0; ; i++) { if(index + 1 >= max_numswitches) { max_numswitches = max_numswitches ? max_numswitches * 2 : 8; switchlist = erealloc(int *, switchlist, sizeof(*switchlist) * max_numswitches); } if(SwapShort(alphSwitchList[i].episode) <= episode) //jff 5/11/98 endianess { if(!SwapShort(alphSwitchList[i].episode)) break; switchlist[index++] = R_FindWall(alphSwitchList[i].name1); switchlist[index++] = R_FindWall(alphSwitchList[i].name2); } }
/******************************************************************** * ConvertUnsignedShortBuffer ********************************************************************/ void ConvertUnsignedShortBuffer(void * ptr, size_t length) { uint16_t * buffer = (uint16_t *)ptr; uint32_t nbShorts = (uint32_t)(length / sizeof(uint16_t)); while (nbShorts-- > 0) { *buffer = SwapShort(*buffer); buffer++; } }
void HUlib_drawTextLine(hu_textline_t* l, boolean drawcursor) { int i, x = l->x, y = l->y; // killough 1/18/98 -- support multiple lines unsigned char c; char* oc = l->cr; //jff 2/17/98 remember default color // draw the new stuff for (i = 0; i < l->len; i++) { c = toupper(l->l[i]); //jff insure were not getting a cheap toupper conv. if (c == '\n') // killough 1/18/98 -- support multiple lines x = 0, y += 8; else if (c == '\t') // killough 1/23/98 -- support tab stops x = x - x % 80 + 80; else if (c == '\x1b') //jff 2/17/98 escape code for color change { //jff 3/26/98 changed to actual escape char if (++i < l->len && l->l[i] >= '0' && l->l[i] <= '9') l->cr = colrngs[l->l[i] - '0']; } else if (c != ' ' && c >= l->sc && c <= 127) { int w = SwapShort(l->f[c - l->sc]->width); if (x + w > SCREENWIDTH) break; // killough 1/18/98 -- support multiple lines: V_DrawPatchTranslated(x, y, FG, l->f[c - l->sc], l->cr, 0); x += w; } else if ((x += 4) >= SCREENWIDTH) break; } l->cr = oc; //jff 2/17/98 restore original color // draw the cursor if requested // killough 1/18/98 -- support multiple lines if (drawcursor && x + SwapShort(l->f['_' - l->sc]->width) <= SCREENWIDTH) V_DrawPatchDirect(x, y, FG, l->f['_' - l->sc]); }
static void SwapHeader(BMHD *header) { SwapShort(&header->w); SwapShort(&header->h); SwapShort(&header->x); SwapShort(&header->y); SwapShort(&header->transparentColor); SwapShort(&header->pageWidth); SwapShort(&header->pageHeight); }
void HUlib_initSText(hu_stext_t* s, int x, int y, int h, patch_t** font, int startchar, char* cr, boolean* on) { int i; s->h = h; s->on = on; s->laston = true; s->cl = 0; for (i = 0; i < h; i++) HUlib_initTextLine(s->l + i, x, y - i * (SwapShort(font[0]->height) + 1), font, startchar, cr); }
inline void _assignPixel<16>(BYTE* bits, BYTE* val, BOOL as24bit) { WORD value(*reinterpret_cast<WORD*>(val)); #ifdef FREEIMAGE_BIGENDIAN SwapShort(&value); #endif if (as24bit) { bits[FI_RGBA_BLUE] = (BYTE)((((value & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F); bits[FI_RGBA_GREEN] = (BYTE)((((value & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F); bits[FI_RGBA_RED] = (BYTE)((((value & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F); } else {
static void SwapHeader(TGAHEADER *header) { SwapShort(&header->cm_first_entry); SwapShort(&header->cm_length); SwapShort(&header->is_xorigin); SwapShort(&header->is_yorigin); SwapShort(&header->is_width); SwapShort(&header->is_height); }
void F_TextWrite(void) { int w; // killough 8/9/98: move variables below int count; char* ch; int c; int cx; int cy; // erase the entire screen to a tiled background // killough 11/98: the background-filling code was already in m_menu.c M_DrawBackground(finaleflat, screens[0]); // draw some of the text onto the screen cx = 10; cy = 10; ch = finaletext; count = (int)((finalecount - 10) / Get_TextSpeed()); // phares if (count < 0) count = 0; for (; count ; count--) { c = *ch++; if (!c) break; if (c == '\n') { cx = 10; cy += 11; continue; } c = toupper(c) - HU_FONTSTART; if (c < 0 || c > HU_FONTSIZE) { cx += 4; continue; } w = SwapShort(hu_font[c]->width); if (cx + w > SCREENWIDTH) break; V_DrawPatch(cx, cy, 0, hu_font[c]); cx += w; } }
/** Load uncompressed image pixels for 1-, 4-, 8-, 16-, 24- and 32-bit dib @param io FreeImage IO @param handle FreeImage IO handle @param dib Image to be loaded @param height Image height @param pitch Image pitch @param bit_count Image bit-depth (1-, 4-, 8-, 16-, 24- or 32-bit) @return Returns TRUE if successful, returns FALSE otherwise */ static BOOL LoadPixelData(FreeImageIO *io, fi_handle handle, FIBITMAP *dib, int height, unsigned pitch, unsigned bit_count) { unsigned count = 0; // Load pixel data // NB: height can be < 0 for BMP data if (height > 0) { count = io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle); if(count != 1) { return FALSE; } } else { int positiveHeight = abs(height); for (int c = 0; c < positiveHeight; ++c) { count = io->read_proc((void *)FreeImage_GetScanLine(dib, positiveHeight - c - 1), pitch, 1, handle); if(count != 1) { return FALSE; } } } // swap as needed #ifdef FREEIMAGE_BIGENDIAN if (bit_count == 16) { for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y); for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { SwapShort(pixel); pixel++; } } } #endif #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB if (bit_count == 24 || bit_count == 32) { for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *pixel = FreeImage_GetScanLine(dib, y); for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) { INPLACESWAP(pixel[0], pixel[2]); pixel += (bit_count >> 3); } } } #endif return TRUE; }
static void swapShortPixels(FIBITMAP* dib) { if(FreeImage_GetImageType(dib) != FIT_BITMAP) { return; } const unsigned Bpp = FreeImage_GetBPP(dib)/8; if(Bpp != 2) { return; } BYTE* bits = FreeImage_GetBits(dib); const unsigned height = FreeImage_GetHeight(dib); const unsigned pitch = FreeImage_GetPitch(dib); BYTE* line = bits; for(unsigned y = 0; y < height; y++, line += pitch) { for(BYTE* pixel = line; pixel < line + pitch ; pixel += Bpp) { SwapShort((WORD*)pixel); } } }
static FIBITMAP * LoadOS22XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset) { FIBITMAP *dib = NULL; try { // load the info header BITMAPINFOHEADER bih; io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle); #ifdef FREEIMAGE_BIGENDIAN SwapInfoHeader(&bih); #endif // keep some general information about the bitmap int used_colors = bih.biClrUsed; int width = bih.biWidth; int height = bih.biHeight; int bit_count = bih.biBitCount; int compression = bih.biCompression; int pitch = CalculatePitch(CalculateLine(width, bit_count)); switch (bit_count) { case 1 : case 4 : case 8 : { if ((used_colors <= 0) || (used_colors > CalculateUsedPaletteEntries(bit_count))) used_colors = CalculateUsedPaletteEntries(bit_count); // allocate enough memory to hold the bitmap (header, palette, pixels) and read the palette dib = FreeImage_Allocate(width, height, bit_count); if (dib == NULL) throw "DIB allocation failed"; BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib); pInfoHeader->biXPelsPerMeter = bih.biXPelsPerMeter; pInfoHeader->biYPelsPerMeter = bih.biYPelsPerMeter; // load the palette io->seek_proc(handle, sizeof(BITMAPFILEHEADER) + bih.biSize, SEEK_SET); RGBQUAD *pal = FreeImage_GetPalette(dib); for (int count = 0; count < used_colors; count++) { FILE_BGR bgr; io->read_proc(&bgr, sizeof(FILE_BGR), 1, handle); pal[count].rgbRed = bgr.r; pal[count].rgbGreen = bgr.g; pal[count].rgbBlue = bgr.b; } // seek to the actual pixel data. // this is needed because sometimes the palette is larger than the entries it contains predicts if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3))) io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); // read the pixel data switch (compression) { case BI_RGB : if (height > 0) { io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle); } else { for (int c = 0; c < abs(height); ++c) { io->read_proc((void *)FreeImage_GetScanLine(dib, height - c - 1), pitch, 1, handle); } } return dib; case BI_RLE4 : { BYTE status_byte = 0; BYTE second_byte = 0; int scanline = 0; int bits = 0; BOOL low_nibble = FALSE; for (;;) { io->read_proc(&status_byte, sizeof(BYTE), 1, handle); switch (status_byte) { case RLE_COMMAND : io->read_proc(&status_byte, sizeof(BYTE), 1, handle); switch (status_byte) { case RLE_ENDOFLINE : bits = 0; scanline++; low_nibble = FALSE; break; case RLE_ENDOFBITMAP : return (FIBITMAP *)dib; case RLE_DELTA : { // read the delta values BYTE delta_x; BYTE delta_y; io->read_proc(&delta_x, sizeof(BYTE), 1, handle); io->read_proc(&delta_y, sizeof(BYTE), 1, handle); // apply them bits += delta_x / 2; scanline += delta_y; break; } default : io->read_proc(&second_byte, sizeof(BYTE), 1, handle); BYTE *sline = FreeImage_GetScanLine(dib, scanline); for (int i = 0; i < status_byte; i++) { if (low_nibble) { *(sline + bits) |= LOWNIBBLE(second_byte); if (i != status_byte - 1) io->read_proc(&second_byte, sizeof(BYTE), 1, handle); bits++; } else { *(sline + bits) |= HINIBBLE(second_byte); } low_nibble = !low_nibble; } if (((status_byte / 2) & 1 ) == 1) io->read_proc(&second_byte, sizeof(BYTE), 1, handle); break; }; break; default : { BYTE *sline = FreeImage_GetScanLine(dib, scanline); io->read_proc(&second_byte, sizeof(BYTE), 1, handle); for (unsigned i = 0; i < status_byte; i++) { if (low_nibble) { *(sline + bits) |= LOWNIBBLE(second_byte); bits++; } else { *(sline + bits) |= HINIBBLE(second_byte); } low_nibble = !low_nibble; } } break; }; } break; } case BI_RLE8 : { BYTE status_byte = 0; BYTE second_byte = 0; int scanline = 0; int bits = 0; for (;;) { io->read_proc(&status_byte, sizeof(BYTE), 1, handle); switch (status_byte) { case RLE_COMMAND : io->read_proc(&status_byte, sizeof(BYTE), 1, handle); switch (status_byte) { case RLE_ENDOFLINE : bits = 0; scanline++; break; case RLE_ENDOFBITMAP : return (FIBITMAP *)dib; case RLE_DELTA : { // read the delta values BYTE delta_x; BYTE delta_y; io->read_proc(&delta_x, sizeof(BYTE), 1, handle); io->read_proc(&delta_y, sizeof(BYTE), 1, handle); // apply them bits += delta_x; scanline += delta_y; break; } default : io->read_proc((void *)(FreeImage_GetScanLine(dib, scanline) + bits), sizeof(BYTE) * status_byte, 1, handle); // align run length to even number of bytes if ((status_byte & 1) == 1) io->read_proc(&second_byte, sizeof(BYTE), 1, handle); bits += status_byte; break; }; break; default : BYTE *sline = FreeImage_GetScanLine(dib, scanline); io->read_proc(&second_byte, sizeof(BYTE), 1, handle); for (unsigned i = 0; i < status_byte; i++) { *(sline + bits) = second_byte; bits++; } break; }; } break; } default : throw "compression type not supported"; } break; } case 16 : { if (bih.biCompression == 3) { DWORD bitfields[3]; io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle); dib = FreeImage_Allocate(width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]); } else { dib = FreeImage_Allocate(width, height, bit_count, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK); } if (dib == NULL) throw "DIB allocation failed"; BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib); pInfoHeader->biXPelsPerMeter = bih.biXPelsPerMeter; pInfoHeader->biYPelsPerMeter = bih.biYPelsPerMeter; if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3))) io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle); #ifdef FREEIMAGE_BIGENDIAN for(int y = 0; y < FreeImage_GetHeight(dib); y++) { WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y); for(int x = 0; x < FreeImage_GetWidth(dib); x++) { SwapShort(pixel); pixel++; } } #endif return dib; } case 24 : case 32 : { if( bit_count == 32 ) { dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); } else { dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); } if (dib == NULL) throw "DIB allocation failed"; BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib); pInfoHeader->biXPelsPerMeter = bih.biXPelsPerMeter; pInfoHeader->biYPelsPerMeter = bih.biYPelsPerMeter; // Skip over the optional palette // A 24 or 32 bit DIB may contain a palette for faster color reduction if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3))) io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); // read in the bitmap bits io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle); #ifdef FREEIMAGE_BIGENDIAN for(int y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *pixel = FreeImage_GetScanLine(dib, y); for(int x = 0; x < FreeImage_GetWidth(dib); x++) { INPLACESWAP(pixel[0], pixel[2]); pixel += (bit_count>>3); } } #endif // check if the bitmap contains transparency, if so enable it in the header FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA)); return dib; } } } catch(const char *message) { if(dib) FreeImage_Unload(dib); FreeImage_OutputMessageProc(s_format_id, message); } return NULL; }
static FIBITMAP * DLL_CALLCONV Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { if( data == NULL ) { return NULL; } GIFinfo *info = (GIFinfo *)data; if( page == -1 ) { page = 0; } if( page < 0 || page >= (int)info->image_descriptor_offsets.size() ) { return NULL; } FIBITMAP *dib = NULL; try { bool have_transparent = false, no_local_palette = false, interlaced = false; int disposal_method = GIF_DISPOSAL_LEAVE, delay_time = 0, transparent_color = 0; WORD left, top, width, height; BYTE packed, b; WORD w; //playback pages to generate what the user would see for this frame if( (flags & GIF_PLAYBACK) == GIF_PLAYBACK ) { //Logical Screen Descriptor io->seek_proc(handle, 6, SEEK_SET); WORD logicalwidth, logicalheight; io->read_proc(&logicalwidth, 2, 1, handle); io->read_proc(&logicalheight, 2, 1, handle); #ifdef FREEIMAGE_BIGENDIAN SwapShort(&logicalwidth); SwapShort(&logicalheight); #endif //set the background color with 0 alpha RGBQUAD background; if( info->global_color_table_offset != 0 && info->background_color < info->global_color_table_size ) { io->seek_proc(handle, info->global_color_table_offset + (info->background_color * 3), SEEK_SET); io->read_proc(&background.rgbRed, 1, 1, handle); io->read_proc(&background.rgbGreen, 1, 1, handle); io->read_proc(&background.rgbBlue, 1, 1, handle); } else { background.rgbRed = 0; background.rgbGreen = 0; background.rgbBlue = 0; } background.rgbReserved = 0; //allocate entire logical area dib = FreeImage_Allocate(logicalwidth, logicalheight, 32); if( dib == NULL ) { throw "DIB allocated failed"; } //fill with background color to start int x, y; RGBQUAD *scanline; for( y = 0; y < logicalheight; y++ ) { scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, y); for( x = 0; x < logicalwidth; x++ ) { *scanline++ = background; } } //cache some info about each of the pages so we can avoid decoding as many of them as possible std::vector<PageInfo> pageinfo; int start = page, end = page; while( start >= 0 ) { //Graphic Control Extension io->seek_proc(handle, info->graphic_control_extension_offsets[start] + 1, SEEK_SET); io->read_proc(&packed, 1, 1, handle); have_transparent = (packed & GIF_PACKED_GCE_HAVETRANS) ? true : false; disposal_method = (packed & GIF_PACKED_GCE_DISPOSAL) >> 2; //Image Descriptor io->seek_proc(handle, info->image_descriptor_offsets[page], SEEK_SET); io->read_proc(&left, 2, 1, handle); io->read_proc(&top, 2, 1, handle); io->read_proc(&width, 2, 1, handle); io->read_proc(&height, 2, 1, handle); #ifdef FREEIMAGE_BIGENDIAN SwapShort(&left); SwapShort(&top); SwapShort(&width); SwapShort(&height); #endif pageinfo.push_back(PageInfo(disposal_method, left, top, width, height)); if( start != end ) { if( left == 0 && top == 0 && width == logicalwidth && height == logicalheight ) { if( disposal_method == GIF_DISPOSAL_BACKGROUND ) { pageinfo.pop_back(); start++; break; } else if( disposal_method != GIF_DISPOSAL_PREVIOUS ) { if( !have_transparent ) { break; } } } } start--; } if( start < 0 ) { start = 0; } //draw each page into the logical area for( page = start; page <= end; page++ ) { PageInfo &info = pageinfo[end - page]; //things we can skip having to decode if( page != end ) { if( info.disposal_method == GIF_DISPOSAL_PREVIOUS ) { continue; } if( info.disposal_method == GIF_DISPOSAL_BACKGROUND ) { for( y = 0; y < info.height; y++ ) { scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, logicalheight - (y + info.top) - 1) + info.left; for( x = 0; x < info.width; x++ ) { *scanline++ = background; } } } } //decode page FIBITMAP *pagedib = Load(io, handle, page, GIF_LOAD256, data); if( pagedib != NULL ) { RGBQUAD *pal = FreeImage_GetPalette(pagedib); have_transparent = false; if( FreeImage_IsTransparent(pagedib) ) { int count = FreeImage_GetTransparencyCount(pagedib); BYTE *table = FreeImage_GetTransparencyTable(pagedib); for( int i = 0; i < count; i++ ) { if( table[i] == 0 ) { have_transparent = true; transparent_color = i; break; } } } //copy page data into logical buffer, with full alpha opaqueness for( y = 0; y < info.height; y++ ) { scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, logicalheight - (y + info.top) - 1) + info.left; BYTE *pageline = FreeImage_GetScanLine(pagedib, info.height - y - 1); for( x = 0; x < info.width; x++ ) { if( !have_transparent || *pageline != transparent_color ) { *scanline = pal[*pageline]; scanline->rgbReserved = 255; } scanline++; pageline++; } } FreeImage_Unload(pagedib); } } return dib; } //get the actual frame image data for a single frame //Image Descriptor io->seek_proc(handle, info->image_descriptor_offsets[page], SEEK_SET); io->read_proc(&left, 2, 1, handle); io->read_proc(&top, 2, 1, handle); io->read_proc(&width, 2, 1, handle); io->read_proc(&height, 2, 1, handle); #ifdef FREEIMAGE_BIGENDIAN SwapShort(&left); SwapShort(&top); SwapShort(&width); SwapShort(&height); #endif io->read_proc(&packed, 1, 1, handle); interlaced = (packed & GIF_PACKED_ID_INTERLACED) ? true : false; no_local_palette = (packed & GIF_PACKED_ID_HAVELCT) ? false : true; int bpp = 8; if( (flags & GIF_LOAD256) == 0 ) { if( !no_local_palette ) { int size = 2 << (packed & GIF_PACKED_ID_LCTSIZE); if( size <= 2 ) bpp = 1; else if( size <= 16 ) bpp = 4; } else if( info->global_color_table_offset != 0 ) { if( info->global_color_table_size <= 2 ) bpp = 1; else if( info->global_color_table_size <= 16 ) bpp = 4; } } dib = FreeImage_Allocate(width, height, bpp); if( dib == NULL ) { throw "DIB allocated failed"; } FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameLeft", ANIMTAG_FRAMELEFT, FIDT_SHORT, 1, 2, &left); FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameTop", ANIMTAG_FRAMETOP, FIDT_SHORT, 1, 2, &top); b = no_local_palette ? 1 : 0; FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "NoLocalPalette", ANIMTAG_NOLOCALPALETTE, FIDT_BYTE, 1, 1, &b); b = interlaced ? 1 : 0; FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "Interlaced", ANIMTAG_INTERLACED, FIDT_BYTE, 1, 1, &b); //Palette RGBQUAD *pal = FreeImage_GetPalette(dib); if( !no_local_palette ) { int size = 2 << (packed & GIF_PACKED_ID_LCTSIZE); int i = 0; while( i < size ) { io->read_proc(&pal[i].rgbRed, 1, 1, handle); io->read_proc(&pal[i].rgbGreen, 1, 1, handle); io->read_proc(&pal[i].rgbBlue, 1, 1, handle); i++; } } else if( info->global_color_table_offset != 0 ) { long pos = io->tell_proc(handle); io->seek_proc(handle, info->global_color_table_offset, SEEK_SET); int i = 0; while( i < info->global_color_table_size ) { io->read_proc(&pal[i].rgbRed, 1, 1, handle); io->read_proc(&pal[i].rgbGreen, 1, 1, handle); io->read_proc(&pal[i].rgbBlue, 1, 1, handle); i++; } io->seek_proc(handle, pos, SEEK_SET); } else { //its legal to have no palette, but we're going to generate *something* for( int i = 0; i < 256; i++ ) { pal[i].rgbRed = i; pal[i].rgbGreen = i; pal[i].rgbBlue = i; } } //LZW Minimum Code Size io->read_proc(&b, 1, 1, handle); StringTable stringtable; stringtable.Initialize(b); //Image Data Sub-blocks int x = 0, xpos = 0, y = 0, shift = 8 - bpp, mask = (1 << bpp) - 1, interlacepass = 0; BYTE *scanline = FreeImage_GetScanLine(dib, height - 1); BYTE buf[1024]; io->read_proc(&b, 1, 1, handle); while( b ) { io->read_proc(stringtable.FillInputBuffer(b), b, 1, handle); int size = sizeof(buf); while( stringtable.Decompress(buf, &size) ) { for( int i = 0; i < size; i++ ) { scanline[xpos] |= (buf[i] & mask) << shift; if( shift > 0 ) { shift -= bpp; } else { xpos++; shift = 8 - bpp; } if( ++x >= width ) { if( interlaced ) { y += g_GifInterlaceIncrement[interlacepass]; if( y >= height && interlacepass < GIF_INTERLACE_PASSES ) { y = g_GifInterlaceOffset[++interlacepass]; } } else { y++; } if( y >= height ) { stringtable.Done(); break; } x = xpos = 0; shift = 8 - bpp; scanline = FreeImage_GetScanLine(dib, height - y - 1); } } size = sizeof(buf); } io->read_proc(&b, 1, 1, handle); } if( page == 0 ) { size_t idx; //Logical Screen Descriptor io->seek_proc(handle, 6, SEEK_SET); WORD logicalwidth, logicalheight; io->read_proc(&logicalwidth, 2, 1, handle); io->read_proc(&logicalheight, 2, 1, handle); #ifdef FREEIMAGE_BIGENDIAN SwapShort(&logicalwidth); SwapShort(&logicalheight); #endif FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "LogicalWidth", ANIMTAG_LOGICALWIDTH, FIDT_SHORT, 1, 2, &logicalwidth); FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "LogicalHeight", ANIMTAG_LOGICALHEIGHT, FIDT_SHORT, 1, 2, &logicalheight); //Global Color Table if( info->global_color_table_offset != 0 ) { RGBQUAD globalpalette[256]; io->seek_proc(handle, info->global_color_table_offset, SEEK_SET); int i = 0; while( i < info->global_color_table_size ) { io->read_proc(&globalpalette[i].rgbRed, 1, 1, handle); io->read_proc(&globalpalette[i].rgbGreen, 1, 1, handle); io->read_proc(&globalpalette[i].rgbBlue, 1, 1, handle); globalpalette[i].rgbReserved = 0; i++; } FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "GlobalPalette", ANIMTAG_GLOBALPALETTE, FIDT_PALETTE, info->global_color_table_size, info->global_color_table_size * 4, globalpalette); //background color if( info->background_color < info->global_color_table_size ) { FreeImage_SetBackgroundColor(dib, &globalpalette[info->background_color]); } } //Application Extension LONG loop = 1; //If no AE with a loop count is found, the default must be 1 for( idx = 0; idx < info->application_extension_offsets.size(); idx++ ) { io->seek_proc(handle, info->application_extension_offsets[idx], SEEK_SET); io->read_proc(&b, 1, 1, handle); if( b == 11 ) { //All AEs start with an 11 byte sub-block to determine what type of AE it is char buf[11]; io->read_proc(buf, 11, 1, handle); if( !memcmp(buf, "NETSCAPE2.0", 11) || !memcmp(buf, "ANIMEXTS1.0", 11) ) { //Not everybody recognizes ANIMEXTS1.0 but it is valid io->read_proc(&b, 1, 1, handle); if( b == 3 ) { //we're supposed to have a 3 byte sub-block now io->read_proc(&b, 1, 1, handle); //this should be 0x01 but isn't really important io->read_proc(&w, 2, 1, handle); #ifdef FREEIMAGE_BIGENDIAN SwapShort(&w); #endif loop = w; if( loop > 0 ) loop++; break; } } } } FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "Loop", ANIMTAG_LOOP, FIDT_LONG, 1, 4, &loop); //Comment Extension for( idx = 0; idx < info->comment_extension_offsets.size(); idx++ ) { io->seek_proc(handle, info->comment_extension_offsets[idx], SEEK_SET); std::string comment; char buf[255]; io->read_proc(&b, 1, 1, handle); while( b ) { io->read_proc(buf, b, 1, handle); comment.append(buf, b); io->read_proc(&b, 1, 1, handle); } comment.append(1, '\0'); sprintf(buf, "Comment%d", idx); FreeImage_SetMetadataEx(FIMD_COMMENTS, dib, buf, 1, FIDT_ASCII, comment.size(), comment.size(), comment.c_str()); } } //Graphic Control Extension if( info->graphic_control_extension_offsets[page] != 0 ) { io->seek_proc(handle, info->graphic_control_extension_offsets[page] + 1, SEEK_SET); io->read_proc(&packed, 1, 1, handle); io->read_proc(&w, 2, 1, handle); #ifdef FREEIMAGE_BIGENDIAN SwapShort(&w); #endif io->read_proc(&b, 1, 1, handle); have_transparent = (packed & GIF_PACKED_GCE_HAVETRANS) ? true : false; disposal_method = (packed & GIF_PACKED_GCE_DISPOSAL) >> 2; delay_time = w * 10; //convert cs to ms transparent_color = b; if( have_transparent ) { int size = 1 << bpp; if( transparent_color <= size ) { BYTE table[256]; memset(table, 0xFF, size); table[transparent_color] = 0; FreeImage_SetTransparencyTable(dib, table, size); } } }
inline void mng_SwapShort(WORD *sp) { #ifndef FREEIMAGE_BIGENDIAN SwapShort(sp); #endif }
FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) { if(handle == NULL) return NULL; bool header_only = (_fi_flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; WORD nCompression = 0; io->read_proc(&nCompression, sizeof(nCompression), 1, handle); #ifndef FREEIMAGE_BIGENDIAN SwapShort(&nCompression); #endif if((nCompression != PSDP_COMPRESSION_NONE && nCompression != PSDP_COMPRESSION_RLE)) { FreeImage_OutputMessageProc(_fi_format_id, "Unsupported compression %d", nCompression); return NULL; } const unsigned nWidth = _headerInfo._Width; const unsigned nHeight = _headerInfo._Height; const unsigned nChannels = _headerInfo._Channels; const unsigned depth = _headerInfo._BitsPerChannel; const unsigned bytes = (depth == 1) ? 1 : depth / 8; // channel(plane) line (BYTE aligned) const unsigned lineSize = (_headerInfo._BitsPerChannel == 1) ? (nWidth + 7) / 8 : nWidth * bytes; if(nCompression == PSDP_COMPRESSION_RLE && depth > 16) { FreeImage_OutputMessageProc(_fi_format_id, "Unsupported RLE with depth %d", depth); return NULL; } // build output buffer FIBITMAP* bitmap = NULL; unsigned dstCh = 0; short mode = _headerInfo._ColourMode; if(mode == PSDP_MULTICHANNEL && nChannels < 3) { // CM mode = PSDP_GRAYSCALE; // C as gray, M as extra channel } bool needPalette = false; switch (mode) { case PSDP_BITMAP: case PSDP_DUOTONE: case PSDP_INDEXED: case PSDP_GRAYSCALE: dstCh = 1; switch(depth) { case 16: bitmap = FreeImage_AllocateHeaderT(header_only, FIT_UINT16, nWidth, nHeight, depth*dstCh); break; case 32: bitmap = FreeImage_AllocateHeaderT(header_only, FIT_FLOAT, nWidth, nHeight, depth*dstCh); break; default: // 1-, 8- needPalette = true; bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh); break; } break; case PSDP_RGB: case PSDP_LAB: case PSDP_CMYK : case PSDP_MULTICHANNEL : // force PSDP_MULTICHANNEL CMY as CMYK dstCh = (mode == PSDP_MULTICHANNEL && !header_only) ? 4 : MIN<unsigned>(nChannels, 4); if(dstCh < 3) { throw "Invalid number of channels"; } switch(depth) { case 16: bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGB16 : FIT_RGBA16, nWidth, nHeight, depth*dstCh); break; case 32: bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGBF : FIT_RGBAF, nWidth, nHeight, depth*dstCh); break; default: bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh); break; } break; default: throw "Unsupported color mode"; break; } if(!bitmap) { throw FI_MSG_ERROR_DIB_MEMORY; } // write thumbnail FreeImage_SetThumbnail(bitmap, _thumbnail.getDib()); // @todo Add some metadata model if(header_only) { return bitmap; } // Load pixels data const unsigned dstChannels = dstCh; const unsigned dstBpp = (depth == 1) ? 1 : FreeImage_GetBPP(bitmap)/8; const unsigned dstLineSize = FreeImage_GetPitch(bitmap); BYTE* const dst_first_line = FreeImage_GetScanLine(bitmap, nHeight - 1);//<*** flipped BYTE* line_start = new BYTE[lineSize]; //< fileline cache switch ( nCompression ) { case PSDP_COMPRESSION_NONE: // raw data { for(unsigned c = 0; c < nChannels; c++) { if(c >= dstChannels) { // @todo write extra channels break; } const unsigned channelOffset = c * bytes; BYTE* dst_line_start = dst_first_line; for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped io->read_proc(line_start, lineSize, 1, handle); for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; line += bytes, dst_line += dstBpp) { #ifdef FREEIMAGE_BIGENDIAN memcpy(dst_line + channelOffset, line, bytes); #else // reverse copy bytes for (unsigned b = 0; b < bytes; ++b) { dst_line[channelOffset + b] = line[(bytes-1) - b]; } #endif // FREEIMAGE_BIGENDIAN } } //< h }//< ch SAFE_DELETE_ARRAY(line_start); } break; case PSDP_COMPRESSION_RLE: // RLE compression { // The RLE-compressed data is preceeded by a 2-byte line size for each row in the data, // store an array of these // later use this array as WORD rleLineSizeList[nChannels][nHeight]; WORD *rleLineSizeList = new (std::nothrow) WORD[nChannels*nHeight]; if(!rleLineSizeList) { FreeImage_Unload(bitmap); SAFE_DELETE_ARRAY(line_start); throw std::bad_alloc(); } io->read_proc(rleLineSizeList, 2, nChannels * nHeight, handle); WORD largestRLELine = 0; for(unsigned ch = 0; ch < nChannels; ++ch) { for(unsigned h = 0; h < nHeight; ++h) { const unsigned index = ch * nHeight + h; #ifndef FREEIMAGE_BIGENDIAN SwapShort(&rleLineSizeList[index]); #endif if(largestRLELine < rleLineSizeList[index]) { largestRLELine = rleLineSizeList[index]; } } } BYTE* rle_line_start = new (std::nothrow) BYTE[largestRLELine]; if(!rle_line_start) { FreeImage_Unload(bitmap); SAFE_DELETE_ARRAY(line_start); SAFE_DELETE_ARRAY(rleLineSizeList); throw std::bad_alloc(); } // Read the RLE data (assume 8-bit) const BYTE* const line_end = line_start + lineSize; for (unsigned ch = 0; ch < nChannels; ch++) { const unsigned channelOffset = ch * bytes; BYTE* dst_line_start = dst_first_line; for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped const unsigned index = ch * nHeight + h; // - read and uncompress line - const WORD rleLineSize = rleLineSizeList[index]; io->read_proc(rle_line_start, rleLineSize, 1, handle); for (BYTE* rle_line = rle_line_start, *line = line_start; rle_line < rle_line_start + rleLineSize, line < line_end;) { int len = *rle_line++; // NOTE len is signed byte in PackBits RLE if ( len < 128 ) { //<- MSB is not set // uncompressed packet // (len + 1) bytes of data are copied ++len; // assert we don't write beyound eol memcpy(line, rle_line, line + len > line_end ? line_end - line : len); line += len; rle_line += len; } else if ( len > 128 ) { //< MSB is set // RLE compressed packet // One byte of data is repeated (–len + 1) times len ^= 0xFF; // same as (-len + 1) & 0xFF len += 2; // // assert we don't write beyound eol memset(line, *rle_line++, line + len > line_end ? line_end - line : len); line += len; } else if ( 128 == len ) { // Do nothing } }//< rle_line // - write line to destination - if(ch >= dstChannels) { // @todo write to extra channels break; } // byte by byte copy a single channel to pixel for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; line += bytes, dst_line += dstBpp) { #ifdef FREEIMAGE_BIGENDIAN memcpy(dst_line + channelOffset, line, bytes); #else // reverse copy bytes for (unsigned b = 0; b < bytes; ++b) { dst_line[channelOffset + b] = line[(bytes-1) - b]; } #endif // FREEIMAGE_BIGENDIAN } }//< h }//< ch SAFE_DELETE_ARRAY(line_start); SAFE_DELETE_ARRAY(rleLineSizeList); SAFE_DELETE_ARRAY(rle_line_start); } break; case 2: // ZIP without prediction, no specification break; case 3: // ZIP with prediction, no specification break; default: // Unknown format break; } // --- Further process the bitmap --- if((mode == PSDP_CMYK || mode == PSDP_MULTICHANNEL)) { // CMYK values are "inverted", invert them back if(mode == PSDP_MULTICHANNEL) { invertColor(bitmap); } else { FreeImage_Invert(bitmap); } if((_fi_flags & PSD_CMYK) == PSD_CMYK) { // keep as CMYK if(mode == PSDP_MULTICHANNEL) { //### we force CMY to be CMYK, but CMY has no ICC. // Create empty profile and add the flag. FreeImage_CreateICCProfile(bitmap, NULL, 0); FreeImage_GetICCProfile(bitmap)->flags |= FIICC_COLOR_IS_CMYK; } } else { // convert to RGB ConvertCMYKtoRGBA(bitmap); // The ICC Profile is no longer valid _iccProfile.clear(); // remove the pending A if not present in source if(nChannels == 4 || nChannels == 3 ) { FIBITMAP* t = RemoveAlphaChannel(bitmap); if(t) { FreeImage_Unload(bitmap); bitmap = t; } // else: silently fail } } } else if ( mode == PSDP_LAB && !((_fi_flags & PSD_LAB) == PSD_LAB)) { ConvertLABtoRGB(bitmap); } else { if (needPalette && FreeImage_GetPalette(bitmap)) { if(mode == PSDP_BITMAP) { CREATE_GREYSCALE_PALETTE_REVERSE(FreeImage_GetPalette(bitmap), 2); } else if(mode == PSDP_INDEXED) { if(!_colourModeData._plColourData || _colourModeData._Length != 768 || _ColourCount < 0) { FreeImage_OutputMessageProc(_fi_format_id, "Indexed image has no palette. Using the default grayscale one."); } else { _colourModeData.FillPalette(bitmap); } } // GRAYSCALE, DUOTONE - use default grayscale palette } #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR if(FreeImage_GetImageType(bitmap) == FIT_BITMAP) { SwapRedBlue32(bitmap); } #endif } return bitmap; }
FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) { FIBITMAP *Bitmap = NULL; if(handle != NULL) { BYTE ShortValue[2]; int n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle); short nCompression = (short)psdGetValue( ShortValue, sizeof(ShortValue) ); switch ( nCompression ) { case PSD_COMPRESSION_NONE: // raw data { int nWidth = _headerInfo._Width; int nHeight = _headerInfo._Height; int bytes = _headerInfo._BitsPerPixel / 8; int nPixels = nWidth * nHeight; int nTotalBytes = nPixels * bytes * _headerInfo._Channels; if(_headerInfo._BitsPerPixel == 1) { // special case for PSD_BITMAP mode bytes = 1; nWidth = (nWidth + 7) / 8; nWidth = ( nWidth > 0 ) ? nWidth : 1; nPixels = nWidth * nHeight; nTotalBytes = nWidth * nHeight; } BYTE * plData = 0; BYTE * plPixel = 0; int nBytes = 0; switch (_headerInfo._ColourMode) { case PSD_BITMAP: { plData = new BYTE [nTotalBytes]; plPixel = new BYTE [bytes]; while(nBytes < nTotalBytes) { n = (int)io->read_proc(plPixel, bytes, 1, handle); memcpy(plData+nBytes, plPixel, bytes ); nBytes += n * bytes; } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_INDEXED: // Indexed { assert( (-1 != _ColourCount) && (0 < _ColourCount) ); assert( NULL != _colourModeData._plColourData ); plData = new BYTE [nTotalBytes]; plPixel = new BYTE [bytes]; while(nBytes < nTotalBytes) { n = (int)io->read_proc(plPixel, bytes, 1, handle); memcpy(plData+nBytes, plPixel, bytes ); nBytes += n * bytes; } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_GRAYSCALE: // Grayscale case PSD_DUOTONE: // Duotone case PSD_RGB: // RGB { plData = new BYTE [nTotalBytes]; plPixel = new BYTE [bytes]; int nPixelCounter = 0; int nChannels = _headerInfo._Channels; for(int c = 0; c < nChannels; c++) { nPixelCounter = c * bytes; for(int nPos = 0; nPos < nPixels; ++nPos) { n = (int)io->read_proc(plPixel, bytes, 1, handle); if(n == 0) { break; } if(2 == bytes) { // swap for uint16 SwapShort((WORD*)&plPixel[0]); } else if(4 == bytes) { // swap for float SwapLong((DWORD*)&plPixel[0]); } memcpy( plData + nPixelCounter, plPixel, bytes ); nBytes += n * bytes; nPixelCounter += nChannels*bytes; } } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_CMYK: // CMYK case PSD_MULTICHANNEL: // Multichannel { plPixel = new BYTE[bytes]; plData = new BYTE[nTotalBytes]; int nPixelCounter = 0; for (int c=0; c<_headerInfo._Channels; c++) { nPixelCounter = c*bytes; for ( int nPos = 0; nPos < nPixels; ++nPos ) { n = (int)io->read_proc(plPixel, bytes, 1, handle); if(n == 0) { break; } memcpy(plData + nPixelCounter, plPixel, bytes ); nBytes += n * bytes; nPixelCounter += _headerInfo._Channels*bytes; } } SAFE_DELETE_ARRAY(plPixel); } break; case PSD_LAB: // Lab { plPixel = new BYTE[bytes]; plData = new BYTE[nTotalBytes]; int nPixelCounter = 0; for(int c = 0; c < 3; c++) { nPixelCounter = c*bytes; for ( int nPos = 0; nPos < nPixels; ++nPos ) { n = (int)io->read_proc(plPixel, bytes, 1, handle); if(n == 0) { break; } memcpy(plData + nPixelCounter, plPixel, bytes); nBytes += n * bytes; nPixelCounter += 3*bytes; } } SAFE_DELETE_ARRAY(plPixel); } break; } assert( nBytes == nTotalBytes ); if (nBytes == nTotalBytes) { if (plData) { switch (_headerInfo._BitsPerPixel) { case 1: case 8: case 16: case 32: Bitmap = ProcessBuffer(plData); break; default: // Unsupported break; } } } SAFE_DELETE_ARRAY(plData); } break; case PSD_COMPRESSION_RLE: // RLE compression { int nWidth = _headerInfo._Width; int nHeight = _headerInfo._Height; int bytes = _headerInfo._BitsPerPixel / 8; int nPixels = nWidth * nHeight; int nTotalBytes = nPixels * bytes * _headerInfo._Channels; if(_headerInfo._BitsPerPixel == 1) { // special case for PSD_BITMAP mode bytes = 1; nWidth = (nWidth + 7) / 8; nWidth = ( nWidth > 0 ) ? nWidth : 1; nPixels = nWidth * nHeight; nTotalBytes = nWidth * nHeight; } BYTE * plData = new BYTE[nTotalBytes]; BYTE * p = plData; int nValue = 0; BYTE ByteValue[1]; int Count = 0; // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, // which we're going to just skip. io->seek_proc(handle, nHeight * _headerInfo._Channels * 2, SEEK_CUR); for (int channel = 0; channel < _headerInfo._Channels; channel++) { // Read the RLE data. Count = 0; while (Count < nPixels) { io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle); int len = psdGetValue( ByteValue, sizeof(ByteValue) ); if ( 128 > len ) { len++; Count += len; while (len) { io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle); nValue = psdGetValue( ByteValue, sizeof(ByteValue) ); *p = (BYTE)nValue; p += sizeof(ByteValue); len--; } } else if ( 128 < len ) { // Next -len+1 bytes in the dest are replicated from next source byte. // (Interpret len as a negative 8-bit int.) len ^= 0x0FF; len += 2; io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle); nValue = psdGetValue( ByteValue, sizeof(ByteValue) ); Count += len; while (len) { *p = (BYTE)nValue; p += sizeof(ByteValue); len--; } } else if ( 128 == len ) { // Do nothing } } } BYTE * prSource = plData; BYTE * plDest = new BYTE[nTotalBytes]; memset(plDest, 254, nTotalBytes); int nPixelCounter = 0; for(int c=0; c<_headerInfo._Channels; c++) { nPixelCounter = c*bytes; for (int nPos = 0; nPos<nPixels; ++nPos) { memcpy( plDest + nPixelCounter, prSource, bytes ); prSource++; nPixelCounter += _headerInfo._Channels*bytes; } } SAFE_DELETE_ARRAY(plData); if (plDest) { switch (_headerInfo._BitsPerPixel) { case 1: case 8: case 16: Bitmap = ProcessBuffer(plDest); break; default: // Unsupported format break; } } SAFE_DELETE_ARRAY(plDest); } break; case 2: // ZIP without prediction, no specification break; case 3: // ZIP with prediction, no specification break; default: // Unknown format break; } } return Bitmap; }
static FIBITMAP * LoadOS21XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset) { FIBITMAP *dib = NULL; try { BITMAPINFOOS2_1X_HEADER bios2_1x; io->read_proc(&bios2_1x, sizeof(BITMAPINFOOS2_1X_HEADER), 1, handle); #ifdef FREEIMAGE_BIGENDIAN SwapOS21XHeader(&bios2_1x); #endif // keep some general information about the bitmap int used_colors = 0; int width = bios2_1x.biWidth; int height = bios2_1x.biHeight; int bit_count = bios2_1x.biBitCount; int pitch = CalculatePitch(CalculateLine(width, bit_count)); switch (bit_count) { case 1 : case 4 : case 8 : { used_colors = CalculateUsedPaletteEntries(bit_count); // allocate enough memory to hold the bitmap (header, palette, pixels) and read the palette dib = FreeImage_Allocate(width, height, bit_count); if (dib == NULL) throw "DIB allocation failed"; BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib); pInfoHeader->biXPelsPerMeter = 0; pInfoHeader->biYPelsPerMeter = 0; // load the palette RGBQUAD *pal = FreeImage_GetPalette(dib); for (int count = 0; count < used_colors; count++) { FILE_BGR bgr; io->read_proc(&bgr, sizeof(FILE_BGR), 1, handle); pal[count].rgbRed = bgr.r; pal[count].rgbGreen = bgr.g; pal[count].rgbBlue = bgr.b; } // Skip over the optional palette // A 24 or 32 bit DIB may contain a palette for faster color reduction io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); // read the pixel data if (height > 0) { io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle); } else { for (int c = 0; c < abs(height); ++c) { io->read_proc((void *)FreeImage_GetScanLine(dib, height - c - 1), pitch, 1, handle); } } return dib; } case 16 : { dib = FreeImage_Allocate(width, height, bit_count, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK); if (dib == NULL) throw "DIB allocation failed"; BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib); pInfoHeader->biXPelsPerMeter = 0; pInfoHeader->biYPelsPerMeter = 0; io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle); #ifdef FREEIMAGE_BIGENDIAN for(int y = 0; y < FreeImage_GetHeight(dib); y++) { WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y); for(int x = 0; x < FreeImage_GetWidth(dib); x++) { SwapShort(pixel); pixel++; } } #endif return dib; } case 24 : case 32 : { if( bit_count == 32 ) { dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); } else { dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); } if (dib == NULL) throw "DIB allocation failed"; BITMAPINFOHEADER *pInfoHeader = FreeImage_GetInfoHeader(dib); pInfoHeader->biXPelsPerMeter = 0; pInfoHeader->biYPelsPerMeter = 0; // Skip over the optional palette // A 24 or 32 bit DIB may contain a palette for faster color reduction io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle); #ifdef FREEIMAGE_BIGENDIAN for(int y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *pixel = FreeImage_GetScanLine(dib, y); for(int x = 0; x < FreeImage_GetWidth(dib); x++) { INPLACESWAP(pixel[0], pixel[2]); pixel += (bit_count>>3); } } #endif // check if the bitmap contains transparency, if so enable it in the header FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA)); return dib; } } } catch(const char *message) { if(dib) FreeImage_Unload(dib); FreeImage_OutputMessageProc(s_format_id, message); } return NULL; }
static void SwapExtensionArea(TGAEXTENSIONAREA *ex) { SwapShort(&ex->extension_size); SwapShort(&ex->datetime_stamp[0]); SwapShort(&ex->datetime_stamp[1]); SwapShort(&ex->datetime_stamp[2]); SwapShort(&ex->datetime_stamp[3]); SwapShort(&ex->datetime_stamp[4]); SwapShort(&ex->datetime_stamp[5]); SwapShort(&ex->job_time[0]); SwapShort(&ex->job_time[1]); SwapShort(&ex->job_time[2]); SwapLong (&ex->key_color); SwapShort(&ex->pixel_aspect_ratio[0]); SwapShort(&ex->pixel_aspect_ratio[1]); SwapShort(&ex->gamma_value[0]); SwapShort(&ex->gamma_value[1]); SwapLong (&ex->color_correction_offset); SwapLong (&ex->postage_stamp_offset); SwapLong (&ex->scan_line_offset); }
static BOOL DLL_CALLCONV Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { if ((dib != NULL) && (handle != NULL)) { // write the file header BITMAPFILEHEADER bitmapfileheader; bitmapfileheader.bfType = 0x4D42; bitmapfileheader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib); bitmapfileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD); bitmapfileheader.bfReserved1 = 0; bitmapfileheader.bfReserved2 = 0; // take care of the bit fields data of any bool bit_fields = (FreeImage_GetBPP(dib) == 16); if (bit_fields) { bitmapfileheader.bfSize += 3 * sizeof(DWORD); bitmapfileheader.bfOffBits += 3 * sizeof(DWORD); } #ifdef FREEIMAGE_BIGENDIAN SwapFileHeader(&bitmapfileheader); #endif if (io->write_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle) != 1) return FALSE; // update the bitmap info header BITMAPINFOHEADER bih = *FreeImage_GetInfoHeader(dib); if (bit_fields) bih.biCompression = BI_BITFIELDS; else if ((bih.biBitCount == 8) && (flags & BMP_SAVE_RLE)) bih.biCompression = BI_RLE8; else bih.biCompression = BI_RGB; // write the bitmap info header #ifdef FREEIMAGE_BIGENDIAN SwapInfoHeader(&bih); #endif if (io->write_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle) != 1) return FALSE; // write the bit fields when we are dealing with a 16 bit BMP if (bit_fields) { DWORD d; d = FreeImage_GetRedMask(dib); if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) return FALSE; d = FreeImage_GetGreenMask(dib); if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) return FALSE; d = FreeImage_GetBlueMask(dib); if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1) return FALSE; } // write the palette if (FreeImage_GetPalette(dib) != NULL) { RGBQUAD *pal = FreeImage_GetPalette(dib); FILE_BGRA bgra; for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++ ) { bgra.b = pal[i].rgbBlue; bgra.g = pal[i].rgbGreen; bgra.r = pal[i].rgbRed; bgra.a = pal[i].rgbReserved; if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1) return FALSE; } } // write the bitmap data... if RLE compression is enable, use it unsigned bpp = FreeImage_GetBPP(dib); if ((bpp == 8) && (flags & BMP_SAVE_RLE)) { BYTE *buffer = new BYTE[FreeImage_GetPitch(dib) * 2]; for (DWORD i = 0; i < FreeImage_GetHeight(dib); ++i) { int size = RLEEncodeLine(buffer, FreeImage_GetScanLine(dib, i), FreeImage_GetLine(dib)); if (io->write_proc(buffer, size, 1, handle) != 1) { delete [] buffer; return FALSE; } } buffer[0] = RLE_COMMAND; buffer[1] = RLE_ENDOFBITMAP; if (io->write_proc(buffer, 2, 1, handle) != 1) { delete [] buffer; return FALSE; } delete [] buffer; #ifdef FREEIMAGE_BIGENDIAN } else if (bpp == 16) { WORD pixel; for(int y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *line = FreeImage_GetScanLine(dib, y); for(int x = 0; x < FreeImage_GetWidth(dib); x++) { pixel = ((WORD *)line)[x]; SwapShort(&pixel); if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1) return FALSE; } } } else if (bpp == 24) { FILE_BGR bgr; for(int y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *line = FreeImage_GetScanLine(dib, y); for(int x = 0; x < FreeImage_GetWidth(dib); x++) { RGBTRIPLE *triple = ((RGBTRIPLE *)line)+x; bgr.b = triple->rgbtBlue; bgr.g = triple->rgbtGreen; bgr.r = triple->rgbtRed; if (io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle) != 1) return FALSE; } } } else if (bpp == 32) { FILE_BGRA bgra; for(int y = 0; y < FreeImage_GetHeight(dib); y++) { BYTE *line = FreeImage_GetScanLine(dib, y); for(int x = 0; x < FreeImage_GetWidth(dib); x++) { RGBQUAD *quad = ((RGBQUAD *)line)+x; bgra.b = quad->rgbBlue; bgra.g = quad->rgbGreen; bgra.r = quad->rgbRed; bgra.a = quad->rgbReserved; if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1) return FALSE; } } #endif } else if (io->write_proc(FreeImage_GetBits(dib), FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib), 1, handle) != 1) { return FALSE; } return TRUE; } else { return FALSE; } }