mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 02:15:42 +01:00 
			
		
		
		
	Merge "webpmux: make more use of WebPData"
This commit is contained in:
		| @@ -119,6 +119,27 @@ static int IsNotCompatible(int count1, int count2) { | |||||||
|   return (count1 > 0) != (count2 > 0); |   return (count1 > 0) != (count2 > 0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Allocate necessary storage for dst then copy the contents of src. | ||||||
|  | // Returns 1 on success. | ||||||
|  | static int WebPDataCopy(const WebPData* const src, WebPData* const dst) { | ||||||
|  |   if (src == NULL || dst == NULL) return 0; | ||||||
|  |  | ||||||
|  |   memset(dst, 0, sizeof(*dst)); | ||||||
|  |   if (src->bytes_ != NULL && src->size_ != 0) { | ||||||
|  |     dst->bytes_ = (uint8_t*)malloc(src->size_); | ||||||
|  |     if (dst->bytes_ == NULL) return 0; | ||||||
|  |     memcpy((void*)dst->bytes_, src->bytes_, src->size_); | ||||||
|  |     dst->size_ = src->size_; | ||||||
|  |   } | ||||||
|  |   return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Frees data allocated by WebPDataCopy. | ||||||
|  | static void WebPDataFree(WebPData* const webpdata) { | ||||||
|  |   free((void*)webpdata->bytes_); | ||||||
|  |   memset(webpdata, 0, sizeof(*webpdata)); | ||||||
|  | } | ||||||
|  |  | ||||||
| #define RETURN_IF_ERROR(ERR_MSG)                                      \ | #define RETURN_IF_ERROR(ERR_MSG)                                      \ | ||||||
|     if (err != WEBP_MUX_OK) {                                         \ |     if (err != WEBP_MUX_OK) {                                         \ | ||||||
|       fprintf(stderr, ERR_MSG);                                       \ |       fprintf(stderr, ERR_MSG);                                       \ | ||||||
| @@ -210,11 +231,11 @@ static WebPMuxError DisplayInfo(const WebPMux* mux) { | |||||||
|     printf("Number of tiles: %d\n", nTiles); |     printf("Number of tiles: %d\n", nTiles); | ||||||
|     if (nTiles > 0) { |     if (nTiles > 0) { | ||||||
|       int i; |       int i; | ||||||
|       uint32_t x_offset, y_offset; |  | ||||||
|       printf("No.: x_offset y_offset image_size"); |       printf("No.: x_offset y_offset image_size"); | ||||||
|       if (flag & ALPHA_FLAG) printf(" alpha_size"); |       if (flag & ALPHA_FLAG) printf(" alpha_size"); | ||||||
|       printf("\n"); |       printf("\n"); | ||||||
|       for (i = 1; i <= nTiles; i++) { |       for (i = 1; i <= nTiles; i++) { | ||||||
|  |         uint32_t x_offset, y_offset; | ||||||
|         WebPData image, alpha; |         WebPData image, alpha; | ||||||
|         err = WebPMuxGetTile(mux, i, &image, &alpha, &x_offset, &y_offset); |         err = WebPMuxGetTile(mux, i, &image, &alpha, &x_offset, &y_offset); | ||||||
|         RETURN_IF_ERROR2("Failed to retrieve tile#%d\n", i); |         RETURN_IF_ERROR2("Failed to retrieve tile#%d\n", i); | ||||||
| @@ -298,7 +319,8 @@ static void PrintHelp(void) { | |||||||
|   printf("\nINPUT & OUTPUT are in webp format.\n"); |   printf("\nINPUT & OUTPUT are in webp format.\n"); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int ReadData(const char* filename, void** data_ptr, uint32_t* size_ptr) { | static int ReadData(const char* filename, | ||||||
|  |                     uint8_t** data_ptr, uint32_t* size_ptr) { | ||||||
|   void* data = NULL; |   void* data = NULL; | ||||||
|   long size = 0; |   long size = 0; | ||||||
|   int ok = 0; |   int ok = 0; | ||||||
| @@ -343,19 +365,19 @@ static int ReadData(const char* filename, void** data_ptr, uint32_t* size_ptr) { | |||||||
|  Err: |  Err: | ||||||
|   if (in != stdin) fclose(in); |   if (in != stdin) fclose(in); | ||||||
|   *size_ptr = (uint32_t)size; |   *size_ptr = (uint32_t)size; | ||||||
|   *data_ptr = data; |   *data_ptr = (uint8_t*)data; | ||||||
|   return ok; |   return ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int ReadFile(const char* const filename, WebPMux** mux) { | static int ReadFile(const char* const filename, WebPMux** mux) { | ||||||
|   uint32_t size = 0; |   uint32_t size = 0; | ||||||
|   void* data = NULL; |   uint8_t* data = NULL; | ||||||
|   WebPMuxState mux_state; |   WebPMuxState mux_state; | ||||||
|  |  | ||||||
|   assert(mux != NULL); |   assert(mux != NULL); | ||||||
|  |  | ||||||
|   if (!ReadData(filename, &data, &size)) return 0; |   if (!ReadData(filename, &data, &size)) return 0; | ||||||
|   *mux = WebPMuxCreate((const uint8_t*)data, size, 1, &mux_state); |   *mux = WebPMuxCreate(data, size, 1, &mux_state); | ||||||
|   free(data); |   free(data); | ||||||
|   if (*mux != NULL && mux_state == WEBP_MUX_STATE_COMPLETE) return 1; |   if (*mux != NULL && mux_state == WEBP_MUX_STATE_COMPLETE) return 1; | ||||||
|   fprintf(stderr, "Failed to create mux object from file %s. mux_state = %d.\n", |   fprintf(stderr, "Failed to create mux object from file %s. mux_state = %d.\n", | ||||||
| @@ -364,9 +386,8 @@ static int ReadFile(const char* const filename, WebPMux** mux) { | |||||||
| } | } | ||||||
|  |  | ||||||
| static int ReadImage(const char* filename, | static int ReadImage(const char* filename, | ||||||
|                      const uint8_t** data_ptr, uint32_t* size_ptr, |                      WebPData* const image_ptr, WebPData* const alpha_ptr) { | ||||||
|                      const uint8_t** alpha_data_ptr, uint32_t* alpha_size_ptr) { |   uint8_t* data = NULL; | ||||||
|   void* data = NULL; |  | ||||||
|   uint32_t size = 0; |   uint32_t size = 0; | ||||||
|   WebPData image, alpha; |   WebPData image, alpha; | ||||||
|   WebPMux* mux; |   WebPMux* mux; | ||||||
| @@ -376,7 +397,7 @@ static int ReadImage(const char* filename, | |||||||
|  |  | ||||||
|   if (!ReadData(filename, &data, &size)) return 0; |   if (!ReadData(filename, &data, &size)) return 0; | ||||||
|  |  | ||||||
|   mux = WebPMuxCreate((const uint8_t*)data, size, 1, &mux_state); |   mux = WebPMuxCreate(data, size, 1, &mux_state); | ||||||
|   free(data); |   free(data); | ||||||
|   if (mux == NULL || mux_state != WEBP_MUX_STATE_COMPLETE) { |   if (mux == NULL || mux_state != WEBP_MUX_STATE_COMPLETE) { | ||||||
|     fprintf(stderr, |     fprintf(stderr, | ||||||
| @@ -386,23 +407,14 @@ static int ReadImage(const char* filename, | |||||||
|   } |   } | ||||||
|   err = WebPMuxGetImage(mux, &image, &alpha); |   err = WebPMuxGetImage(mux, &image, &alpha); | ||||||
|   if (err == WEBP_MUX_OK) { |   if (err == WEBP_MUX_OK) { | ||||||
|     uint8_t* const data_mem = (uint8_t*)malloc(image.size_); |  | ||||||
|     uint8_t* const alpha_mem = (uint8_t*)malloc(alpha.size_); |  | ||||||
|     if ((data_mem != NULL) && (alpha_mem != NULL)) { |  | ||||||
|       memcpy(data_mem, image.bytes_, image.size_); |  | ||||||
|       memcpy(alpha_mem, alpha.bytes_, alpha.size_); |  | ||||||
|       *data_ptr = data_mem; |  | ||||||
|       *size_ptr = image.size_; |  | ||||||
|       *alpha_data_ptr = alpha_mem; |  | ||||||
|       *alpha_size_ptr = alpha.size_; |  | ||||||
|     ok = 1; |     ok = 1; | ||||||
|     } else { |     ok &= WebPDataCopy(&image, image_ptr); | ||||||
|       free(data_mem); |     ok &= WebPDataCopy(&alpha, alpha_ptr); | ||||||
|       free(alpha_mem); |     if (!ok) { | ||||||
|       err = WEBP_MUX_MEMORY_ERROR; |       fprintf(stderr, "Error allocating storage for image (%u bytes) " | ||||||
|       fprintf(stderr, "Failed to allocate %u bytes to extract image data from" |               "and alpha (%u bytes) data\n", image.size_, alpha.size_); | ||||||
|               " file %s. Error: %d\n", |       WebPDataFree(image_ptr); | ||||||
|               image.size_ + alpha.size_, filename, err); |       WebPDataFree(alpha_ptr); | ||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
|     fprintf(stderr, "Failed to extract image data from file %s. Error: %d\n", |     fprintf(stderr, "Failed to extract image data from file %s. Error: %d\n", | ||||||
| @@ -412,17 +424,17 @@ static int ReadImage(const char* filename, | |||||||
|   return ok; |   return ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int WriteData(const char* filename, const void* data, uint32_t size) { | static int WriteData(const char* filename, const WebPData* const webpdata) { | ||||||
|   int ok = 0; |   int ok = 0; | ||||||
|   FILE* fout = strcmp(filename, "-") ? fopen(filename, "wb") : stdout; |   FILE* fout = strcmp(filename, "-") ? fopen(filename, "wb") : stdout; | ||||||
|   if (!fout) { |   if (!fout) { | ||||||
|     fprintf(stderr, "Error opening output WebP file %s!\n", filename); |     fprintf(stderr, "Error opening output WebP file %s!\n", filename); | ||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|   if (fwrite(data, size, 1, fout) != 1) { |   if (fwrite(webpdata->bytes_, webpdata->size_, 1, fout) != 1) { | ||||||
|     fprintf(stderr, "Error writing file %s!\n", filename); |     fprintf(stderr, "Error writing file %s!\n", filename); | ||||||
|   } else { |   } else { | ||||||
|     fprintf(stderr, "Saved file %s (%d bytes)\n", filename, size); |     fprintf(stderr, "Saved file %s (%d bytes)\n", filename, webpdata->size_); | ||||||
|     ok = 1; |     ok = 1; | ||||||
|   } |   } | ||||||
|   if (fout != stdout) fclose(fout); |   if (fout != stdout) fclose(fout); | ||||||
| @@ -430,17 +442,17 @@ static int WriteData(const char* filename, const void* data, uint32_t size) { | |||||||
| } | } | ||||||
|  |  | ||||||
| static int WriteWebP(WebPMux* const mux, const char* filename) { | static int WriteWebP(WebPMux* const mux, const char* filename) { | ||||||
|   uint8_t* data = NULL; |   WebPData webpdata; | ||||||
|   uint32_t size = 0; |  | ||||||
|   int ok; |   int ok; | ||||||
|  |  | ||||||
|   WebPMuxError err = WebPMuxAssemble(mux, &data, &size); |   const WebPMuxError err = WebPMuxAssemble( | ||||||
|  |       mux, (uint8_t**)&webpdata.bytes_, &webpdata.size_); | ||||||
|   if (err != WEBP_MUX_OK) { |   if (err != WEBP_MUX_OK) { | ||||||
|     fprintf(stderr, "Error (%d) assembling the WebP file.\n", err); |     fprintf(stderr, "Error (%d) assembling the WebP file.\n", err); | ||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|   ok = WriteData(filename, data, size); |   ok = WriteData(filename, &webpdata); | ||||||
|   free(data); |   WebPDataFree(&webpdata); | ||||||
|   return ok; |   return ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -826,16 +838,11 @@ static int GetFrameTile(const WebPMux* mux, | |||||||
| static int Process(const WebPMuxConfig* config) { | static int Process(const WebPMuxConfig* config) { | ||||||
|   WebPMux* mux = NULL; |   WebPMux* mux = NULL; | ||||||
|   WebPData webpdata; |   WebPData webpdata; | ||||||
|   const uint8_t* data = NULL; |   uint8_t* data = NULL; | ||||||
|   uint32_t size = 0; |   uint32_t size = 0; | ||||||
|   const uint8_t* alpha_data = NULL; |  | ||||||
|   uint32_t alpha_size = 0; |  | ||||||
|   uint32_t x_offset = 0; |   uint32_t x_offset = 0; | ||||||
|   uint32_t y_offset = 0; |   uint32_t y_offset = 0; | ||||||
|   uint32_t duration = 0; |  | ||||||
|   uint32_t loop_count = 0; |  | ||||||
|   WebPMuxError err = WEBP_MUX_OK; |   WebPMuxError err = WEBP_MUX_OK; | ||||||
|   long num; |  | ||||||
|   int index = 0; |   int index = 0; | ||||||
|   int ok = 1; |   int ok = 1; | ||||||
|   const Feature* const feature = &config->feature_; |   const Feature* const feature = &config->feature_; | ||||||
| @@ -858,14 +865,14 @@ static int Process(const WebPMuxConfig* config) { | |||||||
|           if (err != WEBP_MUX_OK) { |           if (err != WEBP_MUX_OK) { | ||||||
|             ERROR_GOTO2("ERROR#%d: Could not get color profile.\n", err, Err2); |             ERROR_GOTO2("ERROR#%d: Could not get color profile.\n", err, Err2); | ||||||
|           } |           } | ||||||
|           ok = WriteData(config->output_, webpdata.bytes_, webpdata.size_); |           ok = WriteData(config->output_, &webpdata); | ||||||
|           break; |           break; | ||||||
|         case FEATURE_XMP: |         case FEATURE_XMP: | ||||||
|           err = WebPMuxGetMetadata(mux, &webpdata); |           err = WebPMuxGetMetadata(mux, &webpdata); | ||||||
|           if (err != WEBP_MUX_OK) { |           if (err != WEBP_MUX_OK) { | ||||||
|             ERROR_GOTO2("ERROR#%d: Could not get XMP metadata.\n", err, Err2); |             ERROR_GOTO2("ERROR#%d: Could not get XMP metadata.\n", err, Err2); | ||||||
|           } |           } | ||||||
|           ok = WriteData(config->output_, webpdata.bytes_, webpdata.size_); |           ok = WriteData(config->output_, &webpdata); | ||||||
|           break; |           break; | ||||||
|  |  | ||||||
|         default: |         default: | ||||||
| @@ -884,31 +891,31 @@ static int Process(const WebPMuxConfig* config) { | |||||||
|           } |           } | ||||||
|           for (index = 0; index < feature->arg_count_; ++index) { |           for (index = 0; index < feature->arg_count_; ++index) { | ||||||
|             if (feature->args_[index].subtype_ == SUBTYPE_LOOP) { |             if (feature->args_[index].subtype_ == SUBTYPE_LOOP) { | ||||||
|               num = strtol(feature->args_[index].params_, NULL, 10); |               const long num = strtol(feature->args_[index].params_, NULL, 10); | ||||||
|               if (num < 0) { |               if (num < 0) { | ||||||
|                 ERROR_GOTO1("ERROR: Loop count must be non-negative.\n", Err2); |                 ERROR_GOTO1("ERROR: Loop count must be non-negative.\n", Err2); | ||||||
|               } else { |  | ||||||
|                 loop_count = num; |  | ||||||
|               } |               } | ||||||
|               err  = WebPMuxSetLoopCount(mux, loop_count); |               err = WebPMuxSetLoopCount(mux, num); | ||||||
|               if (err != WEBP_MUX_OK) { |               if (err != WEBP_MUX_OK) { | ||||||
|                 ERROR_GOTO2("ERROR#%d: Could not set loop count.\n", err, Err2); |                 ERROR_GOTO2("ERROR#%d: Could not set loop count.\n", err, Err2); | ||||||
|               } |               } | ||||||
|             } else if (feature->args_[index].subtype_ == SUBTYPE_FRM) { |             } else if (feature->args_[index].subtype_ == SUBTYPE_FRM) { | ||||||
|               ok = ReadImage(feature->args_[index].filename_, |               WebPData image, alpha; | ||||||
|                              &data, &size, &alpha_data, &alpha_size); |               uint32_t duration; | ||||||
|  |               ok = ReadImage(feature->args_[index].filename_, &image, &alpha); | ||||||
|               if (!ok) goto Err2; |               if (!ok) goto Err2; | ||||||
|               ok = ParseFrameArgs(feature->args_[index].params_, |               ok = ParseFrameArgs(feature->args_[index].params_, | ||||||
|                                   &x_offset, &y_offset, &duration); |                                   &x_offset, &y_offset, &duration); | ||||||
|               if (!ok) { |               if (!ok) { | ||||||
|                 free((void*)data); |                 WebPDataFree(&image); | ||||||
|                 free((void*)alpha_data); |                 WebPDataFree(&alpha); | ||||||
|                 ERROR_GOTO1("ERROR: Could not parse frame properties.\n", Err2); |                 ERROR_GOTO1("ERROR: Could not parse frame properties.\n", Err2); | ||||||
|               } |               } | ||||||
|               err = WebPMuxAddFrame(mux, 0, data, size, alpha_data, alpha_size, |               err = WebPMuxAddFrame(mux, 0, image.bytes_, image.size_, | ||||||
|  |                                     alpha.bytes_, alpha.size_, | ||||||
|                                     x_offset, y_offset, duration, 1); |                                     x_offset, y_offset, duration, 1); | ||||||
|               free((void*)data); |               WebPDataFree(&image); | ||||||
|               free((void*)alpha_data); |               WebPDataFree(&alpha); | ||||||
|               if (err != WEBP_MUX_OK) { |               if (err != WEBP_MUX_OK) { | ||||||
|                 ERROR_GOTO3("ERROR#%d: Could not add a frame at index %d.\n", |                 ERROR_GOTO3("ERROR#%d: Could not add a frame at index %d.\n", | ||||||
|                             err, index, Err2); |                             err, index, Err2); | ||||||
| @@ -926,20 +933,21 @@ static int Process(const WebPMuxConfig* config) { | |||||||
|                         WEBP_MUX_MEMORY_ERROR, Err2); |                         WEBP_MUX_MEMORY_ERROR, Err2); | ||||||
|           } |           } | ||||||
|           for (index = 0; index < feature->arg_count_; ++index) { |           for (index = 0; index < feature->arg_count_; ++index) { | ||||||
|             ok = ReadImage(feature->args_[index].filename_, |             WebPData image, alpha; | ||||||
|                            &data, &size, &alpha_data, &alpha_size); |             ok = ReadImage(feature->args_[index].filename_, &image, &alpha); | ||||||
|             if (!ok) goto Err2; |             if (!ok) goto Err2; | ||||||
|             ok = ParseTileArgs(feature->args_[index].params_, &x_offset, |             ok = ParseTileArgs(feature->args_[index].params_, &x_offset, | ||||||
|                                &y_offset); |                                &y_offset); | ||||||
|             if (!ok) { |             if (!ok) { | ||||||
|               free((void*)data); |               WebPDataFree(&image); | ||||||
|               free((void*)alpha_data); |               WebPDataFree(&alpha); | ||||||
|               ERROR_GOTO1("ERROR: Could not parse tile properties.\n", Err2); |               ERROR_GOTO1("ERROR: Could not parse tile properties.\n", Err2); | ||||||
|             } |             } | ||||||
|             err = WebPMuxAddTile(mux, 0, data, size, alpha_data, alpha_size, |             err = WebPMuxAddTile(mux, 0, image.bytes_, image.size_, | ||||||
|  |                                  alpha.bytes_, alpha.size_, | ||||||
|                                  x_offset, y_offset, 1); |                                  x_offset, y_offset, 1); | ||||||
|             free((void*)data); |             WebPDataFree(&image); | ||||||
|             free((void*)alpha_data); |             WebPDataFree(&alpha); | ||||||
|             if (err != WEBP_MUX_OK) { |             if (err != WEBP_MUX_OK) { | ||||||
|               ERROR_GOTO3("ERROR#%d: Could not add a tile at index %d.\n", |               ERROR_GOTO3("ERROR#%d: Could not add a tile at index %d.\n", | ||||||
|                           err, index, Err2); |                           err, index, Err2); | ||||||
| @@ -950,7 +958,7 @@ static int Process(const WebPMuxConfig* config) { | |||||||
|         case FEATURE_ICCP: |         case FEATURE_ICCP: | ||||||
|           ok = ReadFile(config->input_, &mux); |           ok = ReadFile(config->input_, &mux); | ||||||
|           if (!ok) goto Err2; |           if (!ok) goto Err2; | ||||||
|           ok = ReadData(feature->args_[0].filename_, (void**)&data, &size); |           ok = ReadData(feature->args_[0].filename_, &data, &size); | ||||||
|           if (!ok) goto Err2; |           if (!ok) goto Err2; | ||||||
|           err = WebPMuxSetColorProfile(mux, data, size, 1); |           err = WebPMuxSetColorProfile(mux, data, size, 1); | ||||||
|           free((void*)data); |           free((void*)data); | ||||||
| @@ -962,10 +970,10 @@ static int Process(const WebPMuxConfig* config) { | |||||||
|         case FEATURE_XMP: |         case FEATURE_XMP: | ||||||
|           ok = ReadFile(config->input_, &mux); |           ok = ReadFile(config->input_, &mux); | ||||||
|           if (!ok) goto Err2; |           if (!ok) goto Err2; | ||||||
|           ok = ReadData(feature->args_[0].filename_, (void**)&data, &size); |           ok = ReadData(feature->args_[0].filename_, &data, &size); | ||||||
|           if (!ok) goto Err2; |           if (!ok) goto Err2; | ||||||
|           err = WebPMuxSetMetadata(mux, data, size, 1); |           err = WebPMuxSetMetadata(mux, data, size, 1); | ||||||
|           free((void*)data); |           free(data); | ||||||
|           if (err != WEBP_MUX_OK) { |           if (err != WEBP_MUX_OK) { | ||||||
|             ERROR_GOTO2("ERROR#%d: Could not set XMP metadata.\n", err, Err2); |             ERROR_GOTO2("ERROR#%d: Could not set XMP metadata.\n", err, Err2); | ||||||
|           } |           } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user