static HPDF_STATUS Get3DStreamType (HPDF_Stream stream, const char **type) { HPDF_BYTE tag[4]; HPDF_UINT len; HPDF_PTRACE ((" HPDF_U3D_Get3DStreamType\n")); len = 4; if (HPDF_Stream_Read (stream, tag, &len) != HPDF_OK) { return HPDF_Error_GetCode (stream->error); } if (HPDF_Stream_Seek (stream, 0, HPDF_SEEK_SET) != HPDF_OK) { return HPDF_Error_GetCode (stream->error); } if (HPDF_MemCmp(tag, (HPDF_BYTE *)u3d, 4/* yes, \0 is required */) == 0) { *type = u3d; return HPDF_OK; } if (HPDF_MemCmp(tag, (HPDF_BYTE *)prc, 3) == 0) { *type = prc; return HPDF_OK; } return HPDF_INVALID_U3D_DATA; }
HPDF_ResetStream (HPDF_Doc pdf) { if (!HPDF_HasDoc (pdf)) return HPDF_INVALID_DOCUMENT; if (!HPDF_Stream_Validate (pdf->stream)) return HPDF_RaiseError (&pdf->error, HPDF_INVALID_OPERATION, 0); return HPDF_Stream_Seek (pdf->stream, 0, HPDF_SEEK_SET); }
HPDF_Image HPDF_Image_LoadJpegImage (HPDF_MMgr mmgr, HPDF_Stream jpeg_data, HPDF_Xref xref) { HPDF_Dict image; HPDF_STATUS ret = HPDF_OK; HPDF_PTRACE ((" HPDF_Image_LoadJpegImage\n")); image = HPDF_DictStream_New (mmgr, xref); if (!image) return NULL; image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT; /* add requiered elements */ image->filter = HPDF_STREAM_FILTER_DCT_DECODE; ret += HPDF_Dict_AddName (image, "Type", "XObject"); ret += HPDF_Dict_AddName (image, "Subtype", "Image"); if (ret != HPDF_OK) return NULL; if (LoadJpegHeader (image, jpeg_data) != HPDF_OK) return NULL; if (HPDF_Stream_Seek (jpeg_data, 0, HPDF_SEEK_SET) != HPDF_OK) return NULL; for (;;) { HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ]; HPDF_UINT len = HPDF_STREAM_BUF_SIZ; HPDF_STATUS ret = HPDF_Stream_Read (jpeg_data, buf, &len); if (ret != HPDF_OK) { if (ret == HPDF_STREAM_EOF) { if (len > 0) { ret = HPDF_Stream_Write (image->stream, buf, len); if (ret != HPDF_OK) return NULL; } break; } else return NULL; } if (HPDF_Stream_Write (image->stream, buf, len) != HPDF_OK) return NULL; } return image; }
static HPDF_STATUS LoadJpegHeader (HPDF_Image image, HPDF_Stream stream) { HPDF_UINT16 tag; HPDF_UINT16 height; HPDF_UINT16 width; HPDF_BYTE precision; HPDF_BYTE num_components; const char *color_space_name; HPDF_UINT len; HPDF_STATUS ret; HPDF_Array array; HPDF_PTRACE ((" HPDF_Image_LoadJpegHeader\n")); len = 2; if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&tag, &len) != HPDF_OK) return HPDF_Error_GetCode (stream->error); HPDF_UInt16Swap (&tag); if (tag != 0xFFD8) return HPDF_INVALID_JPEG_DATA; /* find SOF record */ for (;;) { HPDF_UINT16 size; len = 2; if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&tag, &len) != HPDF_OK) return HPDF_Error_GetCode (stream->error); HPDF_UInt16Swap (&tag); len = 2; if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&size, &len) != HPDF_OK) return HPDF_Error_GetCode (stream->error); HPDF_UInt16Swap (&size); HPDF_PTRACE (("tag=%04X size=%u\n", tag, size)); if (tag == 0xFFC0 || tag == 0xFFC1 || tag == 0xFFC2 || tag == 0xFFC9) { len = 1; if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&precision, &len) != HPDF_OK) return HPDF_Error_GetCode (stream->error); len = 2; if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&height, &len) != HPDF_OK) return HPDF_Error_GetCode (stream->error); HPDF_UInt16Swap (&height); len = 2; if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&width, &len) != HPDF_OK) return HPDF_Error_GetCode (stream->error); HPDF_UInt16Swap (&width); len = 1; if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&num_components, &len) != HPDF_OK) return HPDF_Error_GetCode (stream->error); break; } else if ((tag | 0x00FF) != 0xFFFF) /* lost marker */ return HPDF_SetError (image->error, HPDF_UNSUPPORTED_JPEG_FORMAT, 0); if (HPDF_Stream_Seek (stream, size - 2, HPDF_SEEK_CUR) != HPDF_OK) return HPDF_Error_GetCode (stream->error); } if (HPDF_Dict_AddNumber (image, "Height", height) != HPDF_OK) return HPDF_Error_GetCode (stream->error); if (HPDF_Dict_AddNumber (image, "Width", width) != HPDF_OK) return HPDF_Error_GetCode (stream->error); /* classification of RGB and CMYK is less than perfect * YCbCr and YCCK are classified into RGB or CMYK. * * It is necessary to read APP14 data to distinguish colorspace perfectly. */ switch (num_components) { case 1: color_space_name = COL_GRAY; break; case 3: color_space_name = COL_RGB; break; case 4: array = HPDF_Array_New (image->mmgr); if (!array) return HPDF_Error_GetCode (stream->error); ret = HPDF_Dict_Add (image, "Decode", array); if (ret != HPDF_OK) return HPDF_Error_GetCode (stream->error); ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1)); ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0)); ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1)); ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0)); ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1)); ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0)); ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1)); ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0)); if (ret != HPDF_OK) return HPDF_Error_GetCode (stream->error); color_space_name = COL_CMYK; break; default: return HPDF_SetError (image->error, HPDF_UNSUPPORTED_JPEG_FORMAT, 0); } if (HPDF_Dict_Add (image, "ColorSpace", HPDF_Name_New (image->mmgr, color_space_name)) != HPDF_OK) return HPDF_Error_GetCode (stream->error); if (HPDF_Dict_Add (image, "BitsPerComponent", HPDF_Number_New (image->mmgr, precision)) != HPDF_OK) return HPDF_Error_GetCode (stream->error); return HPDF_OK; }